[ADVAPI32][SERVICES] Add (dummy) password encryption/decryption functions to CreateSe...
[reactos.git] / dll / win32 / advapi32 / service / scm.c
index 0e80fc2..022864b 100644 (file)
@@ -5,9 +5,6 @@
  * PURPOSE:         Service control manager functions
  * PROGRAMMER:      Emanuele Aliberti
  *                  Eric Kohl
- * UPDATE HISTORY:
- *  19990413 EA created
- *  19990515 EA
  */
 
 /* INCLUDES ******************************************************************/
@@ -22,17 +19,18 @@ handle_t __RPC_USER
 SVCCTL_HANDLEA_bind(SVCCTL_HANDLEA szMachineName)
 {
     handle_t hBinding = NULL;
-    UCHAR *pszStringBinding;
+    RPC_CSTR pszStringBinding;
     RPC_STATUS status;
 
-    TRACE("SVCCTL_HANDLEA_bind() called\n");
+    TRACE("SVCCTL_HANDLEA_bind(%s)\n",
+          debugstr_a(szMachineName));
 
     status = RpcStringBindingComposeA(NULL,
-                                      (UCHAR *)"ncacn_np",
-                                      (UCHAR *)szMachineName,
-                                      (UCHAR *)"\\pipe\\ntsvcs",
+                                      (RPC_CSTR)"ncacn_np",
+                                      (RPC_CSTR)szMachineName,
+                                      (RPC_CSTR)"\\pipe\\ntsvcs",
                                       NULL,
-                                      (UCHAR **)&pszStringBinding);
+                                      &pszStringBinding);
     if (status != RPC_S_OK)
     {
         ERR("RpcStringBindingCompose returned 0x%x\n", status);
@@ -63,7 +61,8 @@ SVCCTL_HANDLEA_unbind(SVCCTL_HANDLEA szMachineName,
 {
     RPC_STATUS status;
 
-    TRACE("SVCCTL_HANDLEA_unbind() called\n");
+    TRACE("SVCCTL_HANDLEA_unbind(%s %p)\n",
+          debugstr_a(szMachineName), hBinding);
 
     status = RpcBindingFree(&hBinding);
     if (status != RPC_S_OK)
@@ -77,10 +76,11 @@ handle_t __RPC_USER
 SVCCTL_HANDLEW_bind(SVCCTL_HANDLEW szMachineName)
 {
     handle_t hBinding = NULL;
-    LPWSTR pszStringBinding;
+    RPC_WSTR pszStringBinding;
     RPC_STATUS status;
 
-    TRACE("SVCCTL_HANDLEW_bind() called\n");
+    TRACE("SVCCTL_HANDLEW_bind(%s)\n",
+          debugstr_w(szMachineName));
 
     status = RpcStringBindingComposeW(NULL,
                                       L"ncacn_np",
@@ -118,7 +118,8 @@ SVCCTL_HANDLEW_unbind(SVCCTL_HANDLEW szMachineName,
 {
     RPC_STATUS status;
 
-    TRACE("SVCCTL_HANDLEW_unbind() called\n");
+    TRACE("SVCCTL_HANDLEW_unbind(%s %p)\n",
+          debugstr_w(szMachineName), hBinding);
 
     status = RpcBindingFree(&hBinding);
     if (status != RPC_S_OK)
@@ -131,8 +132,12 @@ SVCCTL_HANDLEW_unbind(SVCCTL_HANDLEW szMachineName,
 DWORD
 ScmRpcStatusToWinError(RPC_STATUS Status)
 {
+    TRACE("ScmRpcStatusToWinError(%lx)\n",
+          Status);
+
     switch (Status)
     {
+        case STATUS_ACCESS_VIOLATION:
         case RPC_S_INVALID_BINDING:
         case RPC_X_SS_IN_NULL_CONTEXT:
             return ERROR_INVALID_HANDLE;
@@ -150,6 +155,33 @@ ScmRpcStatusToWinError(RPC_STATUS Status)
 }
 
 
+static
+DWORD
+ScmEncryptPassword(
+    _In_ PCWSTR pClearTextPassword,
+    _Out_ PBYTE *pEncryptedPassword,
+    _Out_ PDWORD pEncryptedPasswordSize)
+{
+    DWORD dwSize;
+    PBYTE pBuffer;
+
+    dwSize = (wcslen(pClearTextPassword) + 1) * sizeof(WCHAR);
+
+    pBuffer = HeapAlloc(GetProcessHeap(), 0, dwSize);
+    if (pBuffer == NULL)
+        return ERROR_OUTOFMEMORY;
+
+    CopyMemory(pBuffer,
+               pClearTextPassword,
+               dwSize);
+
+    *pEncryptedPassword = pBuffer;
+    *pEncryptedPasswordSize = dwSize;
+
+    return ERROR_SUCCESS;
+}
+
+
 /**********************************************************************
  *  ChangeServiceConfig2A
  *
@@ -163,21 +195,21 @@ ChangeServiceConfig2A(SC_HANDLE hService,
     SC_RPC_CONFIG_INFOA Info;
     DWORD dwError;
 
-    TRACE("ChangeServiceConfig2A() called\n");
+    TRACE("ChangeServiceConfig2A(%p %lu %p)\n",
+          hService, dwInfoLevel, lpInfo);
 
     if (lpInfo == NULL) return TRUE;
 
-    /* Fill relevent field of the Info structure */
+    /* Fill relevant field of the Info structure */
     Info.dwInfoLevel = dwInfoLevel;
     switch (dwInfoLevel)
     {
         case SERVICE_CONFIG_DESCRIPTION:
-            Info.psd = (LPSERVICE_DESCRIPTIONA)&lpInfo;
-            Info.lpDescription = ((LPSERVICE_DESCRIPTIONA)lpInfo)->lpDescription; //HACK
+            Info.psd = lpInfo;
             break;
 
         case SERVICE_CONFIG_FAILURE_ACTIONS:
-            Info.psfa = (LPSERVICE_FAILURE_ACTIONSA)lpInfo;
+            Info.psfa = lpInfo;
             break;
 
         default:
@@ -221,20 +253,21 @@ ChangeServiceConfig2W(SC_HANDLE hService,
     SC_RPC_CONFIG_INFOW Info;
     DWORD dwError;
 
-    TRACE("ChangeServiceConfig2W() called\n");
+    TRACE("ChangeServiceConfig2W(%p %lu %p)\n",
+          hService, dwInfoLevel, lpInfo);
 
     if (lpInfo == NULL) return TRUE;
 
-    /* Fill relevent field of the Info structure */
+    /* Fill relevant field of the Info structure */
     Info.dwInfoLevel = dwInfoLevel;
     switch (dwInfoLevel)
     {
         case SERVICE_CONFIG_DESCRIPTION:
-            Info.psd = (LPSERVICE_DESCRIPTIONW)lpInfo;
+            Info.psd = lpInfo;
             break;
 
         case SERVICE_CONFIG_FAILURE_ACTIONS:
-            Info.psfa = (LPSERVICE_FAILURE_ACTIONSW)lpInfo;
+            Info.psfa = lpInfo;
             break;
 
         default:
@@ -287,10 +320,14 @@ ChangeServiceConfigA(SC_HANDLE hService,
     DWORD dwDependenciesLength = 0;
     SIZE_T cchLength;
     LPCSTR lpStr;
-    DWORD dwPasswordLength = 0;
+    DWORD dwPasswordSize = 0;
+    LPWSTR lpPasswordW = NULL;
     LPBYTE lpEncryptedPassword = NULL;
 
-    TRACE("ChangeServiceConfigA() called\n");
+    TRACE("ChangeServiceConfigA(%p %lu %lu %lu %s %s %p %s %s %s %s)\n",
+          hService, dwServiceType, dwStartType, dwErrorControl, debugstr_a(lpBinaryPathName),
+          debugstr_a(lpLoadOrderGroup), lpdwTagId, debugstr_a(lpDependencies),
+          debugstr_a(lpServiceStartName), debugstr_a(lpPassword), debugstr_a(lpDisplayName));
 
     /* Calculate the Dependencies length*/
     if (lpDependencies != NULL)
@@ -305,13 +342,35 @@ ChangeServiceConfigA(SC_HANDLE hService,
         dwDependenciesLength++;
     }
 
-    /* FIXME: Encrypt the password */
-    lpEncryptedPassword = (LPBYTE)lpPassword;
-    dwPasswordLength = (DWORD)(lpPassword ? (strlen(lpPassword) + 1) * sizeof(CHAR) : 0);
+    if (lpPassword != NULL)
+    {
+        /* Convert the password to unicode */
+        lpPasswordW = HeapAlloc(GetProcessHeap(),
+                                HEAP_ZERO_MEMORY,
+                                (strlen(lpPassword) + 1) * sizeof(WCHAR));
+        if (lpPasswordW == NULL)
+        {
+            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+            return FALSE;
+        }
+
+        MultiByteToWideChar(CP_ACP,
+                            0,
+                            lpPassword,
+                            -1,
+                            lpPasswordW,
+                            (int)(strlen(lpPassword) + 1));
+
+        /* Encrypt the unicode password */
+        dwError = ScmEncryptPassword(lpPasswordW,
+                                     &lpEncryptedPassword,
+                                     &dwPasswordSize);
+        if (dwError != ERROR_SUCCESS)
+            goto done;
+    }
 
     RpcTryExcept
     {
-        /* Call to services.exe using RPC */
         dwError = RChangeServiceConfigA((SC_RPC_HANDLE)hService,
                                         dwServiceType,
                                         dwStartType,
@@ -323,7 +382,7 @@ ChangeServiceConfigA(SC_HANDLE hService,
                                         dwDependenciesLength,
                                         (LPSTR)lpServiceStartName,
                                         lpEncryptedPassword,
-                                        dwPasswordLength,
+                                        dwPasswordSize,
                                         (LPSTR)lpDisplayName);
     }
     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
@@ -332,6 +391,20 @@ ChangeServiceConfigA(SC_HANDLE hService,
     }
     RpcEndExcept;
 
+done:
+    if (lpPasswordW != NULL)
+    {
+        /* Wipe and release the password buffers */
+        ZeroMemory(lpPasswordW, (wcslen(lpPasswordW) + 1) * sizeof(WCHAR));
+        HeapFree(GetProcessHeap(), 0, lpPasswordW);
+
+        if (lpEncryptedPassword != NULL)
+        {
+            ZeroMemory(lpEncryptedPassword, dwPasswordSize);
+            HeapFree(GetProcessHeap(), 0, lpEncryptedPassword);
+        }
+    }
+
     if (dwError != ERROR_SUCCESS)
     {
         TRACE("RChangeServiceConfigA() failed (Error %lu)\n", dwError);
@@ -365,10 +438,13 @@ ChangeServiceConfigW(SC_HANDLE hService,
     DWORD dwDependenciesLength = 0;
     SIZE_T cchLength;
     LPCWSTR lpStr;
-    DWORD dwPasswordLength = 0;
+    DWORD dwPasswordSize = 0;
     LPBYTE lpEncryptedPassword = NULL;
 
-    TRACE("ChangeServiceConfigW() called\n");
+    TRACE("ChangeServiceConfigW(%p %lu %lu %lu %s %s %p %s %s %s %s)\n",
+          hService, dwServiceType, dwStartType, dwErrorControl, debugstr_w(lpBinaryPathName),
+          debugstr_w(lpLoadOrderGroup), lpdwTagId, debugstr_w(lpDependencies),
+          debugstr_w(lpServiceStartName), debugstr_w(lpPassword), debugstr_w(lpDisplayName));
 
     /* Calculate the Dependencies length*/
     if (lpDependencies != NULL)
@@ -384,13 +460,20 @@ ChangeServiceConfigW(SC_HANDLE hService,
         dwDependenciesLength *= sizeof(WCHAR);
     }
 
-    /* FIXME: Encrypt the password */
-    lpEncryptedPassword = (LPBYTE)lpPassword;
-    dwPasswordLength = (lpPassword ? (wcslen(lpPassword) + 1) * sizeof(WCHAR) : 0);
+    if (lpPassword != NULL)
+    {
+        dwError = ScmEncryptPassword(lpPassword,
+                                     &lpEncryptedPassword,
+                                     &dwPasswordSize);
+        if (dwError != ERROR_SUCCESS)
+        {
+            ERR("ScmEncryptPassword failed (Error %lu)\n", dwError);
+            goto done;
+        }
+    }
 
     RpcTryExcept
     {
-        /* Call to services.exe using RPC */
         dwError = RChangeServiceConfigW((SC_RPC_HANDLE)hService,
                                         dwServiceType,
                                         dwStartType,
@@ -402,7 +485,7 @@ ChangeServiceConfigW(SC_HANDLE hService,
                                         dwDependenciesLength,
                                         (LPWSTR)lpServiceStartName,
                                         lpEncryptedPassword,
-                                        dwPasswordLength,
+                                        dwPasswordSize,
                                         (LPWSTR)lpDisplayName);
     }
     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
@@ -411,6 +494,14 @@ ChangeServiceConfigW(SC_HANDLE hService,
     }
     RpcEndExcept;
 
+done:
+    if (lpEncryptedPassword != NULL)
+    {
+        /* Wipe and release the password buffer */
+        ZeroMemory(lpEncryptedPassword, dwPasswordSize);
+        HeapFree(GetProcessHeap(), 0, lpEncryptedPassword);
+    }
+
     if (dwError != ERROR_SUCCESS)
     {
         TRACE("RChangeServiceConfigW() failed (Error %lu)\n", dwError);
@@ -432,7 +523,8 @@ CloseServiceHandle(SC_HANDLE hSCObject)
 {
     DWORD dwError;
 
-    TRACE("CloseServiceHandle() called\n");
+    TRACE("CloseServiceHandle(%p)\n",
+          hSCObject);
 
     if (!hSCObject)
     {
@@ -442,7 +534,6 @@ CloseServiceHandle(SC_HANDLE hSCObject)
 
     RpcTryExcept
     {
-        /* Call to services.exe using RPC */
         dwError = RCloseServiceHandle((LPSC_RPC_HANDLE)&hSCObject);
     }
     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
@@ -476,12 +567,11 @@ ControlService(SC_HANDLE hService,
 {
     DWORD dwError;
 
-    TRACE("ControlService(%x, %x, %p)\n",
-           hService, dwControl, lpServiceStatus);
+    TRACE("ControlService(%p %lu %p)\n",
+          hService, dwControl, lpServiceStatus);
 
     RpcTryExcept
     {
-        /* Call to services.exe using RPC */
         dwError = RControlService((SC_RPC_HANDLE)hService,
                                   dwControl,
                                   lpServiceStatus);
@@ -516,8 +606,8 @@ ControlServiceEx(IN SC_HANDLE hService,
                  IN DWORD dwInfoLevel,
                  IN OUT PVOID pControlParams)
 {
-    FIXME("ControlServiceEx(0x%p, 0x%x, 0x%x, 0x%p) UNIMPLEMENTED!\n",
-            hService, dwControl, dwInfoLevel, pControlParams);
+    FIXME("ControlServiceEx(%p %lu %lu %p)\n",
+          hService, dwControl, dwInfoLevel, pControlParams);
     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
     return FALSE;
 }
@@ -548,12 +638,15 @@ CreateServiceA(SC_HANDLE hSCManager,
     DWORD dwError;
     SIZE_T cchLength;
     LPCSTR lpStr;
-    DWORD dwPasswordLength = 0;
+    DWORD dwPasswordSize = 0;
+    LPWSTR lpPasswordW = NULL;
     LPBYTE lpEncryptedPassword = NULL;
 
-    TRACE("CreateServiceA() called\n");
-    TRACE("%p %s %s\n", hSCManager,
-          lpServiceName, lpDisplayName);
+    TRACE("CreateServiceA(%p %s %s %lx %lu %lu %lu %s %s %p %s %s %s)\n",
+          hSCManager, debugstr_a(lpServiceName), debugstr_a(lpDisplayName),
+          dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl,
+          debugstr_a(lpBinaryPathName), debugstr_a(lpLoadOrderGroup), lpdwTagId,
+          debugstr_a(lpDependencies), debugstr_a(lpServiceStartName), debugstr_a(lpPassword));
 
     if (!hSCManager)
     {
@@ -574,13 +667,35 @@ CreateServiceA(SC_HANDLE hSCManager,
         dwDependenciesLength++;
     }
 
-    /* FIXME: Encrypt the password */
-    lpEncryptedPassword = (LPBYTE)lpPassword;
-    dwPasswordLength = (DWORD)(lpPassword ? (strlen(lpPassword) + 1) * sizeof(CHAR) : 0);
+    if (lpPassword != NULL)
+    {
+        /* Convert the password to unicode */
+        lpPasswordW = HeapAlloc(GetProcessHeap(),
+                                HEAP_ZERO_MEMORY,
+                                (strlen(lpPassword) + 1) * sizeof(WCHAR));
+        if (lpPasswordW == NULL)
+        {
+            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+            return FALSE;
+        }
+
+        MultiByteToWideChar(CP_ACP,
+                            0,
+                            lpPassword,
+                            -1,
+                            lpPasswordW,
+                            (int)(strlen(lpPassword) + 1));
+
+        /* Encrypt the password */
+        dwError = ScmEncryptPassword(lpPasswordW,
+                                     &lpEncryptedPassword,
+                                     &dwPasswordSize);
+        if (dwError != ERROR_SUCCESS)
+            goto done;
+    }
 
     RpcTryExcept
     {
-        /* Call to services.exe using RPC */
         dwError = RCreateServiceA((SC_RPC_HANDLE)hSCManager,
                                   (LPSTR)lpServiceName,
                                   (LPSTR)lpDisplayName,
@@ -595,7 +710,7 @@ CreateServiceA(SC_HANDLE hSCManager,
                                   dwDependenciesLength,
                                   (LPSTR)lpServiceStartName,
                                   lpEncryptedPassword,
-                                  dwPasswordLength,
+                                  dwPasswordSize,
                                   (SC_RPC_HANDLE *)&hService);
     }
     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
@@ -604,10 +719,24 @@ CreateServiceA(SC_HANDLE hSCManager,
     }
     RpcEndExcept;
 
+done:
+    if (lpPasswordW != NULL)
+    {
+        /* Wipe and release the password buffers */
+        ZeroMemory(lpPasswordW, (wcslen(lpPasswordW) + 1) * sizeof(WCHAR));
+        HeapFree(GetProcessHeap(), 0, lpPasswordW);
+
+        if (lpEncryptedPassword != NULL)
+        {
+            ZeroMemory(lpEncryptedPassword, dwPasswordSize);
+            HeapFree(GetProcessHeap(), 0, lpEncryptedPassword);
+        }
+    }
+
+    SetLastError(dwError);
     if (dwError != ERROR_SUCCESS)
     {
         TRACE("RCreateServiceA() failed (Error %lu)\n", dwError);
-        SetLastError(dwError);
         return NULL;
     }
 
@@ -640,12 +769,14 @@ CreateServiceW(SC_HANDLE hSCManager,
     DWORD dwError;
     SIZE_T cchLength;
     LPCWSTR lpStr;
-    DWORD dwPasswordLength = 0;
+    DWORD dwPasswordSize = 0;
     LPBYTE lpEncryptedPassword = NULL;
 
-    TRACE("CreateServiceW() called\n");
-    TRACE("%p %S %S\n", hSCManager,
-          lpServiceName, lpDisplayName);
+    TRACE("CreateServiceW(%p %s %s %lx %lu %lu %lu %s %s %p %s %s %s)\n",
+          hSCManager, debugstr_w(lpServiceName), debugstr_w(lpDisplayName),
+          dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl,
+          debugstr_w(lpBinaryPathName), debugstr_w(lpLoadOrderGroup), lpdwTagId,
+          debugstr_w(lpDependencies), debugstr_w(lpServiceStartName), debugstr_w(lpPassword));
 
     if (!hSCManager)
     {
@@ -667,13 +798,18 @@ CreateServiceW(SC_HANDLE hSCManager,
         dwDependenciesLength *= sizeof(WCHAR);
     }
 
-    /* FIXME: Encrypt the password */
-    lpEncryptedPassword = (LPBYTE)lpPassword;
-    dwPasswordLength = (DWORD)(lpPassword ? (wcslen(lpPassword) + 1) * sizeof(WCHAR) : 0);
+    if (lpPassword != NULL)
+    {
+        /* Encrypt the password */
+        dwError = ScmEncryptPassword(lpPassword,
+                                     &lpEncryptedPassword,
+                                     &dwPasswordSize);
+        if (dwError != ERROR_SUCCESS)
+            goto done;
+    }
 
     RpcTryExcept
     {
-        /* Call to services.exe using RPC */
         dwError = RCreateServiceW((SC_RPC_HANDLE)hSCManager,
                                   lpServiceName,
                                   lpDisplayName,
@@ -688,7 +824,7 @@ CreateServiceW(SC_HANDLE hSCManager,
                                   dwDependenciesLength,
                                   lpServiceStartName,
                                   lpEncryptedPassword,
-                                  dwPasswordLength,
+                                  dwPasswordSize,
                                   (SC_RPC_HANDLE *)&hService);
     }
     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
@@ -697,10 +833,18 @@ CreateServiceW(SC_HANDLE hSCManager,
     }
     RpcEndExcept;
 
+done:
+    if (lpEncryptedPassword != NULL)
+    {
+        /* Wipe and release the password buffers */
+        ZeroMemory(lpEncryptedPassword, dwPasswordSize);
+        HeapFree(GetProcessHeap(), 0, lpEncryptedPassword);
+    }
+
+    SetLastError(dwError);
     if (dwError != ERROR_SUCCESS)
     {
         TRACE("RCreateServiceW() failed (Error %lu)\n", dwError);
-        SetLastError(dwError);
         return NULL;
     }
 
@@ -718,11 +862,11 @@ DeleteService(SC_HANDLE hService)
 {
     DWORD dwError;
 
-    TRACE("DeleteService(%x)\n", hService);
+    TRACE("DeleteService(%p)\n",
+          hService);
 
     RpcTryExcept
     {
-        /* Call to services.exe using RPC */
         dwError = RDeleteService((SC_RPC_HANDLE)hService);
     }
     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
@@ -761,7 +905,9 @@ EnumDependentServicesA(SC_HANDLE hService,
     DWORD dwError;
     DWORD dwCount;
 
-    TRACE("EnumDependentServicesA() called\n");
+    TRACE("EnumDependentServicesA(%p %lu %p %lu %p %p)\n",
+          hService, dwServiceState, lpServices, cbBufSize,
+          pcbBytesNeeded, lpServicesReturned);
 
     if (lpServices == NULL || cbBufSize < sizeof(ENUM_SERVICE_STATUSA))
     {
@@ -837,7 +983,9 @@ EnumDependentServicesW(SC_HANDLE hService,
     DWORD dwError;
     DWORD dwCount;
 
-    TRACE("EnumDependentServicesW() called\n");
+    TRACE("EnumDependentServicesW(%p %lu %p %lu %p %p)\n",
+          hService, dwServiceState, lpServices, cbBufSize,
+          pcbBytesNeeded, lpServicesReturned);
 
     if (lpServices == NULL || cbBufSize < sizeof(ENUM_SERVICE_STATUSW))
     {
@@ -916,7 +1064,10 @@ EnumServiceGroupW(SC_HANDLE hSCManager,
     DWORD dwError;
     DWORD dwCount;
 
-    TRACE("EnumServiceGroupW() called\n");
+    TRACE("EnumServiceGroupW(%p %lu %lu %p %lu %p %p %p %s)\n",
+          hSCManager, dwServiceType, dwServiceState, lpServices,
+          cbBufSize, pcbBytesNeeded, lpServicesReturned,
+          lpResumeHandle, debugstr_w(lpGroup));
 
     if (!hSCManager)
     {
@@ -1023,7 +1174,9 @@ EnumServicesStatusA(SC_HANDLE hSCManager,
     DWORD dwError;
     DWORD dwCount;
 
-    TRACE("EnumServicesStatusA() called\n");
+    TRACE("EnumServicesStatusA(%p %lu %lu %p %lu %p %p %p)\n",
+          hSCManager, dwServiceType, dwServiceState, lpServices,
+          cbBufSize, pcbBytesNeeded, lpServicesReturned, lpResumeHandle);
 
     if (!hSCManager)
     {
@@ -1115,7 +1268,9 @@ EnumServicesStatusW(SC_HANDLE hSCManager,
     DWORD dwError;
     DWORD dwCount;
 
-    TRACE("EnumServicesStatusW() called\n");
+    TRACE("EnumServicesStatusW(%p %lu %lu %p %lu %p %p %p)\n",
+          hSCManager, dwServiceType, dwServiceState, lpServices,
+          cbBufSize, pcbBytesNeeded, lpServicesReturned, lpResumeHandle);
 
     if (!hSCManager)
     {
@@ -1209,7 +1364,10 @@ EnumServicesStatusExA(SC_HANDLE hSCManager,
     DWORD dwError;
     DWORD dwCount;
 
-    TRACE("EnumServicesStatusExA() called\n");
+    TRACE("EnumServicesStatusExA(%p %lu %lu %p %lu %p %p %p %s)\n",
+          hSCManager, dwServiceType, dwServiceState, lpServices,
+          cbBufSize, pcbBytesNeeded, lpServicesReturned, lpResumeHandle,
+          debugstr_a(pszGroupName));
 
     if (InfoLevel != SC_ENUM_PROCESS_INFO)
     {
@@ -1314,7 +1472,10 @@ EnumServicesStatusExW(SC_HANDLE hSCManager,
     DWORD dwError;
     DWORD dwCount;
 
-    TRACE("EnumServicesStatusExW() called\n");
+    TRACE("EnumServicesStatusExW(%p %lu %lu %p %lu %p %p %p %s)\n",
+          hSCManager, dwServiceType, dwServiceState, lpServices,
+          cbBufSize, pcbBytesNeeded, lpServicesReturned, lpResumeHandle,
+          debugstr_w(pszGroupName));
 
     if (InfoLevel != SC_ENUM_PROCESS_INFO)
     {
@@ -1411,9 +1572,8 @@ GetServiceDisplayNameA(SC_HANDLE hSCManager,
     LPSTR lpNameBuffer;
     CHAR szEmptyName[] = "";
 
-    TRACE("GetServiceDisplayNameA() called\n");
-    TRACE("%p %s %p %p\n", hSCManager,
-          debugstr_a(lpServiceName), lpDisplayName, lpcchBuffer);
+    TRACE("GetServiceDisplayNameA(%p %s %p %p)\n",
+          hSCManager, debugstr_a(lpServiceName), lpDisplayName, lpcchBuffer);
 
     if (!hSCManager)
     {
@@ -1440,7 +1600,6 @@ GetServiceDisplayNameA(SC_HANDLE hSCManager,
     }
     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
     {
-        /* HACK: because of a problem with rpcrt4, rpcserver is hacked to return 6 for ERROR_SERVICE_DOES_NOT_EXIST */
         dwError = ScmRpcStatusToWinError(RpcExceptionCode());
     }
     RpcEndExcept;
@@ -1471,7 +1630,8 @@ GetServiceDisplayNameW(SC_HANDLE hSCManager,
     LPWSTR lpNameBuffer;
     WCHAR szEmptyName[] = L"";
 
-    TRACE("GetServiceDisplayNameW() called\n");
+    TRACE("GetServiceDisplayNameW(%p %s %p %p)\n",
+          hSCManager, debugstr_w(lpServiceName), lpDisplayName, lpcchBuffer);
 
     if (!hSCManager)
     {
@@ -1528,7 +1688,8 @@ GetServiceKeyNameA(SC_HANDLE hSCManager,
     LPSTR lpNameBuffer;
     CHAR szEmptyName[] = "";
 
-    TRACE("GetServiceKeyNameA() called\n");
+    TRACE("GetServiceKeyNameA(%p %s %p %p)\n",
+          hSCManager, debugstr_a(lpDisplayName), lpServiceName, lpcchBuffer);
 
     if (!hSCManager)
     {
@@ -1555,6 +1716,7 @@ GetServiceKeyNameA(SC_HANDLE hSCManager,
     }
     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
     {
+        /* HACK: because of a problem with rpcrt4, rpcserver is hacked to return 6 for ERROR_SERVICE_DOES_NOT_EXIST */
         dwError = ScmRpcStatusToWinError(RpcExceptionCode());
     }
     RpcEndExcept;
@@ -1585,7 +1747,8 @@ GetServiceKeyNameW(SC_HANDLE hSCManager,
     LPWSTR lpNameBuffer;
     WCHAR szEmptyName[] = L"";
 
-    TRACE("GetServiceKeyNameW() called\n");
+    TRACE("GetServiceKeyNameW(%p %s %p %p)\n",
+          hSCManager, debugstr_w(lpDisplayName), lpServiceName, lpcchBuffer);
 
     if (!hSCManager)
     {
@@ -1627,6 +1790,43 @@ GetServiceKeyNameW(SC_HANDLE hSCManager,
 }
 
 
+/**********************************************************************
+ *  I_ScGetCurrentGroupStateW
+ *
+ * @implemented
+ */
+DWORD WINAPI
+I_ScGetCurrentGroupStateW(SC_HANDLE hSCManager,
+                          LPWSTR pszGroupName,
+                          LPDWORD pdwGroupState)
+{
+    DWORD dwError;
+
+    TRACE("I_ScGetCurrentGroupStateW(%p %s %p)\n",
+          hSCManager, debugstr_w(pszGroupName), pdwGroupState);
+
+    RpcTryExcept
+    {
+        dwError = RI_ScGetCurrentGroupStateW((SC_RPC_HANDLE)hSCManager,
+                                             pszGroupName,
+                                             pdwGroupState);
+    }
+    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
+    {
+        dwError = ScmRpcStatusToWinError(RpcExceptionCode());
+    }
+    RpcEndExcept
+
+    if (dwError != ERROR_SUCCESS)
+    {
+        TRACE("RI_ScGetCurrentGroupStateW() failed (Error %lu)\n", dwError);
+        SetLastError(dwError);
+    }
+
+    return dwError;
+}
+
+
 /**********************************************************************
  *  LockServiceDatabase
  *
@@ -1638,11 +1838,11 @@ LockServiceDatabase(SC_HANDLE hSCManager)
     SC_LOCK hLock;
     DWORD dwError;
 
-    TRACE("LockServiceDatabase(%x)\n", hSCManager);
+    TRACE("LockServiceDatabase(%p)\n",
+          hSCManager);
 
     RpcTryExcept
     {
-        /* Call to services.exe using RPC */
         dwError = RLockServiceDatabase((SC_RPC_HANDLE)hSCManager,
                                        (SC_RPC_LOCK *)&hLock);
     }
@@ -1670,17 +1870,19 @@ WaitForSCManager(VOID)
 {
     HANDLE hEvent;
 
-    TRACE("WaitForSCManager() called\n");
+    TRACE("WaitForSCManager()\n");
 
     /* Try to open the existing event */
     hEvent = OpenEventW(SYNCHRONIZE, FALSE, SCM_START_EVENT);
     if (hEvent == NULL)
     {
-        if (GetLastError() != ERROR_FILE_NOT_FOUND) return;
+        if (GetLastError() != ERROR_FILE_NOT_FOUND)
+            return;
 
         /* Try to create a new event */
         hEvent = CreateEventW(NULL, TRUE, FALSE, SCM_START_EVENT);
-        if (hEvent == NULL) return;
+        if (hEvent == NULL)
+            return;
     }
 
     /* Wait for 3 minutes */
@@ -1704,14 +1906,13 @@ OpenSCManagerA(LPCSTR lpMachineName,
     SC_HANDLE hScm = NULL;
     DWORD dwError;
 
-    TRACE("OpenSCManagerA(%s, %s, %lx)\n",
-           lpMachineName, lpDatabaseName, dwDesiredAccess);
+    TRACE("OpenSCManagerA(%s %s %lx)\n",
+          debugstr_a(lpMachineName), debugstr_a(lpDatabaseName), dwDesiredAccess);
 
     WaitForSCManager();
 
     RpcTryExcept
     {
-        /* Call to services.exe using RPC */
         dwError = ROpenSCManagerA((LPSTR)lpMachineName,
                                   (LPSTR)lpDatabaseName,
                                   dwDesiredAccess,
@@ -1749,14 +1950,13 @@ OpenSCManagerW(LPCWSTR lpMachineName,
     SC_HANDLE hScm = NULL;
     DWORD dwError;
 
-    TRACE("OpenSCManagerW(%S, %S, %lx)\n",
-           lpMachineName, lpDatabaseName, dwDesiredAccess);
+    TRACE("OpenSCManagerW(%s %s %lx)\n",
+          debugstr_w(lpMachineName), debugstr_w(lpDatabaseName), dwDesiredAccess);
 
     WaitForSCManager();
 
     RpcTryExcept
     {
-        /* Call to services.exe using RPC */
         dwError = ROpenSCManagerW((LPWSTR)lpMachineName,
                                   (LPWSTR)lpDatabaseName,
                                   dwDesiredAccess,
@@ -1794,8 +1994,8 @@ OpenServiceA(SC_HANDLE hSCManager,
     SC_HANDLE hService = NULL;
     DWORD dwError;
 
-    TRACE("OpenServiceA(%p, %s, %lx)\n",
-           hSCManager, lpServiceName, dwDesiredAccess);
+    TRACE("OpenServiceA(%p %s %lx)\n",
+           hSCManager, debugstr_a(lpServiceName), dwDesiredAccess);
 
     if (!hSCManager)
     {
@@ -1805,7 +2005,6 @@ OpenServiceA(SC_HANDLE hSCManager,
 
     RpcTryExcept
     {
-        /* Call to services.exe using RPC */
         dwError = ROpenServiceA((SC_RPC_HANDLE)hSCManager,
                                 (LPSTR)lpServiceName,
                                 dwDesiredAccess,
@@ -1817,10 +2016,10 @@ OpenServiceA(SC_HANDLE hSCManager,
     }
     RpcEndExcept;
 
+    SetLastError(dwError);
     if (dwError != ERROR_SUCCESS)
     {
         TRACE("ROpenServiceA() failed (Error %lu)\n", dwError);
-        SetLastError(dwError);
         return NULL;
     }
 
@@ -1843,8 +2042,8 @@ OpenServiceW(SC_HANDLE hSCManager,
     SC_HANDLE hService = NULL;
     DWORD dwError;
 
-    TRACE("OpenServiceW(%p, %S, %lx)\n",
-           hSCManager, lpServiceName, dwDesiredAccess);
+    TRACE("OpenServiceW(%p %s %lx)\n",
+           hSCManager, debugstr_w(lpServiceName), dwDesiredAccess);
 
     if (!hSCManager)
     {
@@ -1854,7 +2053,6 @@ OpenServiceW(SC_HANDLE hSCManager,
 
     RpcTryExcept
     {
-        /* Call to services.exe using RPC */
         dwError = ROpenServiceW((SC_RPC_HANDLE)hSCManager,
                                 (LPWSTR)lpServiceName,
                                 dwDesiredAccess,
@@ -1866,10 +2064,10 @@ OpenServiceW(SC_HANDLE hSCManager,
     }
     RpcEndExcept;
 
+    SetLastError(dwError);
     if (dwError != ERROR_SUCCESS)
     {
         TRACE("ROpenServiceW() failed (Error %lu)\n", dwError);
-        SetLastError(dwError);
         return NULL;
     }
 
@@ -1895,7 +2093,7 @@ QueryServiceConfigA(SC_HANDLE hService,
     DWORD dwBufferSize;
     DWORD dwError;
 
-    TRACE("QueryServiceConfigA(%p, %p, %lu, %p)\n",
+    TRACE("QueryServiceConfigA(%p %p %lu %p)\n",
            hService, lpServiceConfig, cbBufSize, pcbBytesNeeded);
 
     if (lpServiceConfig == NULL ||
@@ -1912,7 +2110,6 @@ QueryServiceConfigA(SC_HANDLE hService,
 
     RpcTryExcept
     {
-        /* Call to services.exe using RPC */
         dwError = RQueryServiceConfigA((SC_RPC_HANDLE)hService,
                                        (LPBYTE)lpConfigPtr,
                                        dwBufferSize,
@@ -1979,7 +2176,7 @@ QueryServiceConfigW(SC_HANDLE hService,
     DWORD dwBufferSize;
     DWORD dwError;
 
-    TRACE("QueryServiceConfigW(%p, %p, %lu, %p)\n",
+    TRACE("QueryServiceConfigW(%p %p %lu %p)\n",
            hService, lpServiceConfig, cbBufSize, pcbBytesNeeded);
 
     if (lpServiceConfig == NULL ||
@@ -1996,7 +2193,6 @@ QueryServiceConfigW(SC_HANDLE hService,
 
     RpcTryExcept
     {
-        /* Call to services.exe using RPC */
         dwError = RQueryServiceConfigW((SC_RPC_HANDLE)hService,
                                        (LPBYTE)lpConfigPtr,
                                        dwBufferSize,
@@ -2066,7 +2262,7 @@ QueryServiceConfig2A(SC_HANDLE hService,
     DWORD dwBufferSize;
     DWORD dwError;
 
-    TRACE("QueryServiceConfig2A(hService %p, dwInfoLevel %lu, lpBuffer %p, cbBufSize %lu, pcbBytesNeeded %p)\n",
+    TRACE("QueryServiceConfig2A(%p %lu %p %lu %p)\n",
           hService, dwInfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
 
     lpTempBuffer = lpBuffer;
@@ -2100,7 +2296,6 @@ QueryServiceConfig2A(SC_HANDLE hService,
 
     RpcTryExcept
     {
-        /* Call to services.exe using RPC */
         dwError = RQueryServiceConfig2A((SC_RPC_HANDLE)hService,
                                         dwInfoLevel,
                                         lpTempBuffer,
@@ -2120,7 +2315,7 @@ QueryServiceConfig2A(SC_HANDLE hService,
         return FALSE;
     }
 
-    if (bUseTempBuffer == TRUE)
+    if (bUseTempBuffer != FALSE)
     {
         TRACE("RQueryServiceConfig2A() returns ERROR_INSUFFICIENT_BUFFER\n");
         *pcbBytesNeeded = dwBufferSize;
@@ -2184,8 +2379,8 @@ QueryServiceConfig2W(SC_HANDLE hService,
     DWORD dwBufferSize;
     DWORD dwError;
 
-    TRACE("QueryServiceConfig2W(%p, %lu, %p, %lu, %p)\n",
-           hService, dwInfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
+    TRACE("QueryServiceConfig2W(%p %lu %p %lu %p)\n",
+          hService, dwInfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
 
     lpTempBuffer = lpBuffer;
     dwBufferSize = cbBufSize;
@@ -2218,7 +2413,6 @@ QueryServiceConfig2W(SC_HANDLE hService,
 
     RpcTryExcept
     {
-        /* Call to services.exe using RPC */
         dwError = RQueryServiceConfig2W((SC_RPC_HANDLE)hService,
                                         dwInfoLevel,
                                         lpTempBuffer,
@@ -2238,7 +2432,7 @@ QueryServiceConfig2W(SC_HANDLE hService,
         return FALSE;
     }
 
-    if (bUseTempBuffer == TRUE)
+    if (bUseTempBuffer != FALSE)
     {
         TRACE("RQueryServiceConfig2W() returns ERROR_INSUFFICIENT_BUFFER\n");
         *pcbBytesNeeded = dwBufferSize;
@@ -2299,7 +2493,8 @@ QueryServiceLockStatusA(SC_HANDLE hSCManager,
     DWORD dwBufferSize;
     DWORD dwError;
 
-    TRACE("QueryServiceLockStatusA() called\n");
+    TRACE("QueryServiceLockStatusA(%p %p %lu %p)\n",
+          hSCManager, lpLockStatus, cbBufSize, pcbBytesNeeded);
 
     if (lpLockStatus == NULL || cbBufSize < sizeof(QUERY_SERVICE_LOCK_STATUSA))
     {
@@ -2314,7 +2509,6 @@ QueryServiceLockStatusA(SC_HANDLE hSCManager,
 
     RpcTryExcept
     {
-        /* Call to services.exe using RPC */
         dwError = RQueryServiceLockStatusA((SC_RPC_HANDLE)hSCManager,
                                            (LPBYTE)lpStatusPtr,
                                            dwBufferSize,
@@ -2361,7 +2555,8 @@ QueryServiceLockStatusW(SC_HANDLE hSCManager,
     DWORD dwBufferSize;
     DWORD dwError;
 
-    TRACE("QueryServiceLockStatusW() called\n");
+    TRACE("QueryServiceLockStatusW(%p %p %lu %p)\n",
+          hSCManager, lpLockStatus, cbBufSize, pcbBytesNeeded);
 
     if (lpLockStatus == NULL || cbBufSize < sizeof(QUERY_SERVICE_LOCK_STATUSW))
     {
@@ -2376,7 +2571,6 @@ QueryServiceLockStatusW(SC_HANDLE hSCManager,
 
     RpcTryExcept
     {
-        /* Call to services.exe using RPC */
         dwError = RQueryServiceLockStatusW((SC_RPC_HANDLE)hSCManager,
                                            (LPBYTE)lpStatusPtr,
                                            dwBufferSize,
@@ -2421,12 +2615,11 @@ QueryServiceObjectSecurity(SC_HANDLE hService,
 {
     DWORD dwError;
 
-    TRACE("QueryServiceObjectSecurity(%p, %lu, %p)\n",
+    TRACE("QueryServiceObjectSecurity(%p %lu %p)\n",
            hService, dwSecurityInformation, lpSecurityDescriptor);
 
     RpcTryExcept
     {
-        /* Call to services.exe using RPC */
         dwError = RQueryServiceObjectSecurity((SC_RPC_HANDLE)hService,
                                               dwSecurityInformation,
                                               (LPBYTE)lpSecurityDescriptor,
@@ -2449,6 +2642,7 @@ QueryServiceObjectSecurity(SC_HANDLE hService,
     return TRUE;
 }
 
+
 /**********************************************************************
  *  SetServiceObjectSecurity
  *
@@ -2464,6 +2658,9 @@ SetServiceObjectSecurity(SC_HANDLE hService,
     NTSTATUS Status;
     DWORD dwError;
 
+    TRACE("SetServiceObjectSecurity(%p %lu %p)\n",
+          hService, dwSecurityInformation, lpSecurityDescriptor);
+
     Length = 0;
     Status = RtlMakeSelfRelativeSD(lpSecurityDescriptor,
                                    SelfRelativeSD,
@@ -2493,7 +2690,6 @@ SetServiceObjectSecurity(SC_HANDLE hService,
 
     RpcTryExcept
     {
-        /* Call to services.exe using RPC */
         dwError = RSetServiceObjectSecurity((SC_RPC_HANDLE)hService,
                                             dwSecurityInformation,
                                             (LPBYTE)SelfRelativeSD,
@@ -2529,8 +2725,8 @@ QueryServiceStatus(SC_HANDLE hService,
 {
     DWORD dwError;
 
-    TRACE("QueryServiceStatus(%p, %p)\n",
-           hService, lpServiceStatus);
+    TRACE("QueryServiceStatus(%p %p)\n",
+          hService, lpServiceStatus);
 
     if (!hService)
     {
@@ -2540,7 +2736,6 @@ QueryServiceStatus(SC_HANDLE hService,
 
     RpcTryExcept
     {
-        /* Call to services.exe using RPC */
         dwError = RQueryServiceStatus((SC_RPC_HANDLE)hService,
                                       lpServiceStatus);
     }
@@ -2575,7 +2770,8 @@ QueryServiceStatusEx(SC_HANDLE hService,
 {
     DWORD dwError;
 
-    TRACE("QueryServiceStatusEx() called\n");
+    TRACE("QueryServiceStatusEx(%p %lu %p %lu %p)\n",
+          hService, InfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
 
     if (InfoLevel != SC_STATUS_PROCESS_INFO)
     {
@@ -2592,7 +2788,6 @@ QueryServiceStatusEx(SC_HANDLE hService,
 
     RpcTryExcept
     {
-        /* Call to services.exe using RPC */
         dwError = RQueryServiceStatusEx((SC_RPC_HANDLE)hService,
                                         InfoLevel,
                                         lpBuffer,
@@ -2628,6 +2823,9 @@ StartServiceA(SC_HANDLE hService,
 {
     DWORD dwError;
 
+    TRACE("StartServiceA(%p %lu %p)\n",
+          hService, dwNumServiceArgs, lpServiceArgVectors);
+
     RpcTryExcept
     {
         dwError = RStartServiceA((SC_RPC_HANDLE)hService,
@@ -2663,6 +2861,9 @@ StartServiceW(SC_HANDLE hService,
 {
     DWORD dwError;
 
+    TRACE("StartServiceW(%p %lu %p)\n",
+          hService, dwNumServiceArgs, lpServiceArgVectors);
+
     RpcTryExcept
     {
         dwError = RStartServiceW((SC_RPC_HANDLE)hService,
@@ -2696,11 +2897,11 @@ UnlockServiceDatabase(SC_LOCK ScLock)
 {
     DWORD dwError;
 
-    TRACE("UnlockServiceDatabase(%x)\n", ScLock);
+    TRACE("UnlockServiceDatabase(%x)\n",
+          ScLock);
 
     RpcTryExcept
     {
-        /* Call to services.exe using RPC */
         dwError = RUnlockServiceDatabase((LPSC_RPC_LOCK)&ScLock);
     }
     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
@@ -2709,6 +2910,9 @@ UnlockServiceDatabase(SC_LOCK ScLock)
     }
     RpcEndExcept;
 
+    if (dwError == ERROR_INVALID_HANDLE)
+        dwError = ERROR_INVALID_SERVICE_LOCK;
+
     if (dwError != ERROR_SUCCESS)
     {
         TRACE("RUnlockServiceDatabase() failed (Error %lu)\n", dwError);
@@ -2730,11 +2934,11 @@ NotifyBootConfigStatus(BOOL BootAcceptable)
 {
     DWORD dwError;
 
-    TRACE("NotifyBootConfigStatus()\n");
+    TRACE("NotifyBootConfigStatus(%u)\n",
+          BootAcceptable);
 
     RpcTryExcept
     {
-        /* Call to services.exe using RPC */
         dwError = RNotifyBootConfigStatus(NULL,
                                           BootAcceptable);
     }