- Implement GetServiceDisplayNameW (untested).
- SCM must store a services display name.
- Some SCM-Calls must fail while the SCM is shutting down.
Modified: trunk/reactos/include/idl/svcctl.idl
Modified: trunk/reactos/lib/advapi32/service/scm.c
Modified: trunk/reactos/subsys/system/services/database.c
Modified: trunk/reactos/subsys/system/services/rpcserver.c
Modified: trunk/reactos/subsys/system/services/services.c
Modified: trunk/reactos/subsys/system/services/services.h

Modified: trunk/reactos/include/idl/svcctl.idl
--- trunk/reactos/include/idl/svcctl.idl	2005-10-30 12:53:32 UTC (rev 18879)
+++ trunk/reactos/include/idl/svcctl.idl	2005-10-30 13:13:53 UTC (rev 18880)
@@ -9,7 +9,9 @@
 #define BOOL unsigned long
 #define SC_HANDLE unsigned int
 #define SC_LOCK unsigned int
+#define LPSTR char*
 #define LPCSTR char*
+#define LPWSTR wchar_t*
 #define LPCWSTR wchar_t*
 #define LPDWORD unsigned long*
 
@@ -127,6 +129,14 @@
                              [out] SC_HANDLE *hScm);
 
 
+  /* Function 20 */
+  DWORD ScmrGetServiceDisplayNameW([in] handle_t BindingHandle,
+                                   [in] SC_HANDLE hSCManager,
+                                   [in, string, ref] LPCWSTR lpServiceName,
+                                   [out, size_is(*lpcchBuffer), unique] LPWSTR lpDisplayName,
+                                   [in, out, ref] LPDWORD lpcchBuffer);
+
+
   /* Function 27 */
   DWORD ScmrOpenSCManagerA([in] handle_t BindingHandle,
                            [in, string, unique] LPCSTR lpMachineName,

Modified: trunk/reactos/lib/advapi32/service/scm.c
--- trunk/reactos/lib/advapi32/service/scm.c	2005-10-30 12:53:32 UTC (rev 18879)
+++ trunk/reactos/lib/advapi32/service/scm.c	2005-10-30 13:13:53 UTC (rev 18880)
@@ -566,19 +566,33 @@
 /**********************************************************************
  *  GetServiceDisplayNameW
  *
- * @unimplemented
+ * @implemented
  */
-BOOL
-STDCALL
-GetServiceDisplayNameW(
-    SC_HANDLE   hSCManager,
-    LPCWSTR     lpServiceName,
-    LPWSTR      lpDisplayName,
-    LPDWORD     lpcchBuffer)
+BOOL STDCALL
+GetServiceDisplayNameW(SC_HANDLE hSCManager,
+                       LPCWSTR lpServiceName,
+                       LPWSTR lpDisplayName,
+                       LPDWORD lpcchBuffer)
 {
-    DPRINT1("GetServiceDisplayNameW is unimplemented\n");
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return FALSE;
+    DWORD dwError;
+
+    DPRINT("GetServiceDisplayNameW() called\n");
+
+    HandleBind();
+
+    dwError = ScmrGetServiceDisplayNameW(BindingHandle,
+                                         (unsigned int)hSCManager,
+                                         (LPWSTR)lpServiceName,
+                                         lpDisplayName,
+                                         lpcchBuffer);
+    if (dwError != ERROR_SUCCESS)
+    {
+        DPRINT1("ScmrGetServiceDisplayNameW() failed (Error %lu)\n", dwError);
+        SetLastError(dwError);
+        return FALSE;
+    }
+
+    return TRUE;
 }
 
 
@@ -606,14 +620,33 @@
  *
  * @unimplemented
  */
-BOOL
-STDCALL
-GetServiceKeyNameW(
-    SC_HANDLE   hSCManager,
-    LPCWSTR     lpDisplayName,
-    LPWSTR      lpServiceName,
-    LPDWORD     lpcchBuffer)
+BOOL STDCALL
+GetServiceKeyNameW(SC_HANDLE hSCManager,
+                   LPCWSTR lpDisplayName,
+                   LPWSTR lpServiceName,
+                   LPDWORD lpcchBuffer)
 {
+#if 0
+    DWORD dwError;
+
+    DPRINT("GetServiceKeyNameW() called\n");
+
+    HandleBind();
+
+    dwError = ScmrGetServiceKeyNameW(BindingHandle,
+                                     (unsigned int)hSCManager,
+                                     (LPWSTR)lpDisplayName,
+                                     lpServiceName,
+                                     lpcchBuffer);
+    if (dwError != ERROR_SUCCESS)
+    {
+        DPRINT1("ScmrGetServiceKeyNameW() failed (Error %lu)\n", dwError);
+        SetLastError(dwError);
+        return FALSE;
+    }
+
+    return TRUE;
+#endif
     DPRINT1("GetServiceKeyNameW is unimplemented\n");
     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
     return FALSE;

Modified: trunk/reactos/subsys/system/services/database.c
--- trunk/reactos/subsys/system/services/database.c	2005-10-30 12:53:32 UTC (rev 18879)
+++ trunk/reactos/subsys/system/services/database.c	2005-10-30 13:13:53 UTC (rev 18880)
@@ -84,6 +84,35 @@
 }
 
 
+PSERVICE
+ScmGetServiceEntryByDisplayName(LPWSTR lpDisplayName)
+{
+    PLIST_ENTRY ServiceEntry;
+    PSERVICE CurrentService;
+
+    DPRINT("ScmGetServiceEntryByDisplayName() called\n");
+
+    ServiceEntry = ServiceListHead.Flink;
+    while (ServiceEntry != &ServiceListHead)
+    {
+        CurrentService = CONTAINING_RECORD(ServiceEntry,
+                                           SERVICE,
+                                           ServiceListEntry);
+        if (_wcsicmp(CurrentService->lpDisplayName, lpDisplayName) == 0)
+        {
+            DPRINT("Found service: '%S'\n", CurrentService->lpDisplayName);
+            return CurrentService;
+        }
+
+        ServiceEntry = ServiceEntry->Flink;
+    }
+
+    DPRINT("Couldn't find a matching service\n");
+
+    return NULL;
+}
+
+
 static NTSTATUS STDCALL
 CreateGroupOrderListRoutine(PWSTR ValueName,
                             ULONG ValueType,
@@ -204,6 +233,7 @@
     /* Copy service name */
     wcscpy(Service->szServiceName, lpServiceName);
     Service->lpServiceName = Service->szServiceName;
+    Service->lpDisplayName = Service->lpServiceName;
 
     /* Get service data */
     RtlZeroMemory(&QueryTable,
@@ -284,6 +314,7 @@
     /* Copy service name */
     wcscpy(lpService->szServiceName, lpServiceName);
     lpService->lpServiceName = lpService->szServiceName;
+    lpService->lpDisplayName = lpService->lpServiceName;
 
     /* Append service entry */
     InsertTailList(&ServiceListHead,

Modified: trunk/reactos/subsys/system/services/rpcserver.c
--- trunk/reactos/subsys/system/services/rpcserver.c	2005-10-30 12:53:32 UTC (rev 18879)
+++ trunk/reactos/subsys/system/services/rpcserver.c	2005-10-30 13:13:53 UTC (rev 18880)
@@ -283,6 +283,9 @@
 
     DPRINT1("ScmrControlService() called\n");
 
+    if (ScmShutdown)
+        return ERROR_SHUTDOWN_IN_PROGRESS;
+
     hSvc = (PSERVICE_HANDLE)hService;
     if (hSvc->Handle.Tag != SERVICE_TAG)
     {
@@ -325,6 +328,9 @@
 
     DPRINT1("ScmrDeleteService() called\n");
 
+    if (ScmShutdown)
+        return ERROR_SHUTDOWN_IN_PROGRESS;
+
     hSvc = (PSERVICE_HANDLE)hService;
     if (hSvc->Handle.Tag != SERVICE_TAG)
         return ERROR_INVALID_HANDLE;
@@ -409,6 +415,9 @@
 
     DPRINT("ScmrQueryServiceStatus() called\n");
 
+    if (ScmShutdown)
+        return ERROR_SHUTDOWN_IN_PROGRESS;
+
     hSvc = (PSERVICE_HANDLE)hService;
     if (hSvc->Handle.Tag != SERVICE_TAG)
     {
@@ -488,6 +497,10 @@
                          unsigned long dwPasswordLength,
                          wchar_t *lpDisplayName)
 {
+    DWORD dwError = ERROR_SUCCESS;
+    PSERVICE_HANDLE hSvc;
+    PSERVICE lpService = NULL;
+
     DPRINT1("ScmrChangeServiceConfigW() called\n");
     DPRINT1("dwServiceType = %lu\n", dwServiceType);
     DPRINT1("dwStartType = %lu\n", dwStartType);
@@ -496,7 +509,35 @@
     DPRINT1("lpLoadOrderGroup = %S\n", lpLoadOrderGroup);
     DPRINT1("lpDisplayName = %S\n", lpDisplayName);
 
-    return ERROR_SUCCESS;
+    if (ScmShutdown)
+        return ERROR_SHUTDOWN_IN_PROGRESS;
+
+    hSvc = (PSERVICE_HANDLE)hService;
+    if (hSvc->Handle.Tag != SERVICE_TAG)
+    {
+        DPRINT1("Invalid handle tag!\n");
+        return ERROR_INVALID_HANDLE;
+    }
+
+    if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
+                                  SERVICE_CHANGE_CONFIG))
+    {
+        DPRINT1("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
+        return ERROR_ACCESS_DENIED;
+    }
+
+    lpService = hSvc->ServiceEntry;
+    if (lpService == NULL)
+    {
+        DPRINT1("lpService == NULL!\n");
+        return ERROR_INVALID_HANDLE;
+    }
+
+    /* FIXME: ... */
+
+    DPRINT1("ScmrChangeServiceConfigW() done (Error %lu)\n", dwError);
+
+    return dwError;
 }
 
 
@@ -580,6 +621,9 @@
     DPRINT1("lpBinaryPathName = %S\n", lpBinaryPathName);
     DPRINT1("lpLoadOrderGroup = %S\n", lpLoadOrderGroup);
 
+    if (ScmShutdown)
+        return ERROR_SHUTDOWN_IN_PROGRESS;
+
     hManager = (PMANAGER_HANDLE)hSCManager;
     if (hManager->Handle.Tag != MANAGER_TAG)
     {
@@ -625,6 +669,23 @@
     lpService->dwStartType = dwStartType;
     lpService->dwErrorControl = dwErrorControl;
 
+    /* Fill the display name */
+    if (lpDisplayName != NULL &&
+        *lpDisplayName != 0 &&
+        wcsicmp(lpService->lpDisplayName, lpDisplayName) != 0)
+    {
+        lpService->lpDisplayName = HeapAlloc(GetProcessHeap, 0,
+                                             (wcslen(lpDisplayName) + 1) * sizeof(WCHAR));
+        if (lpService->lpDisplayName == NULL)
+        {
+            dwError = ERROR_NOT_ENOUGH_MEMORY;
+            goto done;
+        }
+        wcscpy(lpService->lpDisplayName, lpDisplayName);
+    }
+
+
+
     /* FIXME: set lpLoadOrderGroup, lpDependencies etc. */
 
 
@@ -756,6 +817,10 @@
     }
     else
     {
+        /* Release the display name buffer */
+        if (lpService->lpServiceName != lpService->lpDisplayName)
+            HeapFree(GetProcessHeap(), 0, lpService->lpDisplayName);
+
         if (hServiceHandle != NULL)
         {
             /* Remove the service handle */
@@ -795,6 +860,9 @@
     DPRINT("lpDataBaseName: %S\n", lpDatabaseName);
     DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess);
 
+    if (ScmShutdown)
+        return ERROR_SHUTDOWN_IN_PROGRESS;
+
     dwError = ScmCreateManagerHandle(lpDatabaseName,
                                      &hHandle);
     if (dwError != ERROR_SUCCESS)
@@ -841,6 +909,9 @@
     DPRINT("lpServiceName: %S\n", lpServiceName);
     DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess);
 
+    if (ScmShutdown)
+        return ERROR_SHUTDOWN_IN_PROGRESS;
+
     hManager = (PMANAGER_HANDLE)hSCManager;
     if (hManager->Handle.Tag != MANAGER_TAG)
     {
@@ -886,7 +957,56 @@
 }
 
 
+/* Function 20 */
+unsigned long
+ScmrGetServiceDisplayNameW(handle_t BindingHandle,
+                           unsigned int hSCManager,
+                           wchar_t *lpServiceName,
+                           wchar_t *lpDisplayName, /* [out, unique] */
+                           unsigned long *lpcchBuffer)
+{
+//    PMANAGER_HANDLE hManager;
+    PSERVICE lpService;
+    DWORD dwLength;
+    DWORD dwError;
 
+    DPRINT1("ScmrGetServiceDisplayNameW() called\n");
+    DPRINT1("hSCManager = %x\n", hSCManager);
+    DPRINT1("lpServiceName: %S\n", lpServiceName);
+    DPRINT1("lpDisplayName: %p\n", lpDisplayName);
+    DPRINT1("*lpcchBuffer: %lu\n", *lpcchBuffer);
+
+//    hManager = (PMANAGER_HANDLE)hSCManager;
+//    if (hManager->Handle.Tag != MANAGER_TAG)
+//    {
+//        DPRINT1("Invalid manager handle!\n");
+//        return ERROR_INVALID_HANDLE;
+//    }
+
+    /* Get service database entry */
+    lpService = ScmGetServiceEntryByName(lpServiceName);
+    if (lpService == NULL)
+    {
+        DPRINT1("Could not find a service!\n");
+        return ERROR_SERVICE_DOES_NOT_EXIST;
+    }
+
+    dwLength = wcslen(lpService->lpDisplayName);
+
+    if (lpDisplayName != NULL &&
+        *lpcchBuffer > dwLength)
+    {
+        wcscpy(lpDisplayName, lpService->lpDisplayName);
+    }
+
+    dwError = (*lpcchBuffer > dwLength) ? ERROR_SUCCESS : ERROR_INSUFFICIENT_BUFFER;
+
+    *lpcchBuffer = dwLength;
+
+    return dwError;
+}
+
+
 /* Function 27 */
 unsigned long
 ScmrOpenSCManagerA(handle_t BindingHandle,

Modified: trunk/reactos/subsys/system/services/services.c
--- trunk/reactos/subsys/system/services/services.c	2005-10-30 12:53:32 UTC (rev 18879)
+++ trunk/reactos/subsys/system/services/services.c	2005-10-30 13:13:53 UTC (rev 18880)
@@ -40,7 +40,9 @@
 #define PIPE_BUFSIZE 1024
 #define PIPE_TIMEOUT 1000
 
+BOOL ScmShutdown = FALSE;
 
+
 /* FUNCTIONS *****************************************************************/
 
 VOID
@@ -286,6 +288,23 @@
 }
 
 
+BOOL WINAPI
+ShutdownHandlerRoutine(DWORD dwCtrlType)
+{
+    DPRINT1("ShutdownHandlerRoutine() called\n");
+
+    if (dwCtrlType == CTRL_SHUTDOWN_EVENT)
+    {
+        DPRINT1("Shutdown event received!\n");
+        ScmShutdown = TRUE;
+
+        /* FIXME: Shut all services down */
+    }
+
+    return TRUE;
+}
+
+
 int STDCALL
 WinMain(HINSTANCE hInstance,
         HINSTANCE hPrevInstance,
@@ -330,17 +349,15 @@
     ScmStartRpcServer();
 
     /* Register service process with CSRSS */
-//    RegisterServicesProcess(GetCurrentProcessId());
+    RegisterServicesProcess(GetCurrentProcessId());
 
     DPRINT("SERVICES: Initialized.\n");
 
     /* Signal start event */
     SetEvent(hScmStartEvent);
 
-#if 0
-    /* FIXME: register event handler (used for system shutdown) */
-    SetConsoleCtrlHandler(...);
-#endif
+    /* Register event handler (used for system shutdown) */
+    SetConsoleCtrlHandler(ShutdownHandlerRoutine, TRUE);
 
     /* Start auto-start services */
     ScmAutoStartServices();

Modified: trunk/reactos/subsys/system/services/services.h
--- trunk/reactos/subsys/system/services/services.h	2005-10-30 12:53:32 UTC (rev 18879)
+++ trunk/reactos/subsys/system/services/services.h	2005-10-30 13:13:53 UTC (rev 18880)
@@ -13,6 +13,7 @@
 {
     LIST_ENTRY ServiceListEntry;
     LPWSTR lpServiceName;
+    LPWSTR lpDisplayName;
     UNICODE_STRING ServiceGroup;
 
     SERVICE_STATUS Status;
@@ -32,6 +33,13 @@
 } SERVICE, *PSERVICE;
 
 
+/* VARIABLES ***************************************************************/
+
+extern BOOL ScmShutdown;
+
+
+/* FUNCTIONS ***************************************************************/
+
 /* config.c */
 
 DWORD ScmWriteDependencies(HKEY hServiceKey,
@@ -46,6 +54,7 @@
 VOID ScmAutoStartServices(VOID);
 
 PSERVICE ScmGetServiceEntryByName(LPWSTR lpServiceName);
+PSERVICE ScmGetServiceEntryByDisplayName(LPWSTR lpDisplayName);
 DWORD ScmCreateNewServiceRecord(LPWSTR lpServiceName,
                                 PSERVICE *lpServiceRecord);
 DWORD ScmMarkServiceForDelete(PSERVICE pService);