[ADVAPI32] Take into account the service handler context when dispatching a control...
[reactos.git] / dll / win32 / advapi32 / service / scm.c
index 4bffbd5..5a20508 100644 (file)
@@ -5,15 +5,12 @@
  * PURPOSE:         Service control manager functions
  * PROGRAMMER:      Emanuele Aliberti
  *                  Eric Kohl
- * UPDATE HISTORY:
- *  19990413 EA created
- *  19990515 EA
  */
 
 /* INCLUDES ******************************************************************/
 
 #include <advapi32.h>
-WINE_DEFAULT_DEBUG_CHANNEL(advapi);
+WINE_DEFAULT_DEBUG_CHANNEL(advapi_service);
 
 
 /* FUNCTIONS *****************************************************************/
@@ -22,35 +19,35 @@ handle_t __RPC_USER
 SVCCTL_HANDLEA_bind(SVCCTL_HANDLEA szMachineName)
 {
     handle_t hBinding = NULL;
-    UCHAR *pszStringBinding;
-    RPC_STATUS status;
+    RPC_CSTR pszStringBinding;
+    RPC_STATUS Status;
 
     TRACE("SVCCTL_HANDLEA_bind() called\n");
 
-    status = RpcStringBindingComposeA(NULL,
-                                      (UCHAR *)"ncacn_np",
-                                      (UCHAR *)szMachineName,
-                                      (UCHAR *)"\\pipe\\ntsvcs",
+    Status = RpcStringBindingComposeA(NULL,
+                                      (RPC_CSTR)"ncacn_np",
+                                      (RPC_CSTR)szMachineName,
+                                      (RPC_CSTR)"\\pipe\\ntsvcs",
                                       NULL,
-                                      (UCHAR **)&pszStringBinding);
-    if (status != RPC_S_OK)
+                                      &pszStringBinding);
+    if (Status != RPC_S_OK)
     {
-        ERR("RpcStringBindingCompose returned 0x%x\n", status);
+        ERR("RpcStringBindingCompose returned 0x%x\n", Status);
         return NULL;
     }
 
     /* Set the binding handle that will be used to bind to the server. */
-    status = RpcBindingFromStringBindingA(pszStringBinding,
+    Status = RpcBindingFromStringBindingA(pszStringBinding,
                                           &hBinding);
-    if (status != RPC_S_OK)
+    if (Status != RPC_S_OK)
     {
-        ERR("RpcBindingFromStringBinding returned 0x%x\n", status);
+        ERR("RpcBindingFromStringBinding returned 0x%x\n", Status);
     }
 
-    status = RpcStringFreeA(&pszStringBinding);
-    if (status != RPC_S_OK)
+    Status = RpcStringFreeA(&pszStringBinding);
+    if (Status != RPC_S_OK)
     {
-        ERR("RpcStringFree returned 0x%x\n", status);
+        ERR("RpcStringFree returned 0x%x\n", Status);
     }
 
     return hBinding;
@@ -61,14 +58,14 @@ void __RPC_USER
 SVCCTL_HANDLEA_unbind(SVCCTL_HANDLEA szMachineName,
                       handle_t hBinding)
 {
-    RPC_STATUS status;
+    RPC_STATUS Status;
 
     TRACE("SVCCTL_HANDLEA_unbind() called\n");
 
-    status = RpcBindingFree(&hBinding);
-    if (status != RPC_S_OK)
+    Status = RpcBindingFree(&hBinding);
+    if (Status != RPC_S_OK)
     {
-        ERR("RpcBindingFree returned 0x%x\n", status);
+        ERR("RpcBindingFree returned 0x%x\n", Status);
     }
 }
 
@@ -77,35 +74,35 @@ handle_t __RPC_USER
 SVCCTL_HANDLEW_bind(SVCCTL_HANDLEW szMachineName)
 {
     handle_t hBinding = NULL;
-    LPWSTR pszStringBinding;
-    RPC_STATUS status;
+    RPC_WSTR pszStringBinding;
+    RPC_STATUS Status;
 
     TRACE("SVCCTL_HANDLEW_bind() called\n");
 
-    status = RpcStringBindingComposeW(NULL,
+    Status = RpcStringBindingComposeW(NULL,
                                       L"ncacn_np",
                                       szMachineName,
                                       L"\\pipe\\ntsvcs",
                                       NULL,
                                       &pszStringBinding);
-    if (status != RPC_S_OK)
+    if (Status != RPC_S_OK)
     {
-        ERR("RpcStringBindingCompose returned 0x%x\n", status);
+        ERR("RpcStringBindingCompose returned 0x%x\n", Status);
         return NULL;
     }
 
     /* Set the binding handle that will be used to bind to the server. */
-    status = RpcBindingFromStringBindingW(pszStringBinding,
+    Status = RpcBindingFromStringBindingW(pszStringBinding,
                                           &hBinding);
-    if (status != RPC_S_OK)
+    if (Status != RPC_S_OK)
     {
-        ERR("RpcBindingFromStringBinding returned 0x%x\n", status);
+        ERR("RpcBindingFromStringBinding returned 0x%x\n", Status);
     }
 
-    status = RpcStringFreeW(&pszStringBinding);
-    if (status != RPC_S_OK)
+    Status = RpcStringFreeW(&pszStringBinding);
+    if (Status != RPC_S_OK)
     {
-        ERR("RpcStringFree returned 0x%x\n", status);
+        ERR("RpcStringFree returned 0x%x\n", Status);
     }
 
     return hBinding;
@@ -116,23 +113,25 @@ void __RPC_USER
 SVCCTL_HANDLEW_unbind(SVCCTL_HANDLEW szMachineName,
                       handle_t hBinding)
 {
-    RPC_STATUS status;
+    RPC_STATUS Status;
 
     TRACE("SVCCTL_HANDLEW_unbind() called\n");
 
-    status = RpcBindingFree(&hBinding);
-    if (status != RPC_S_OK)
+    Status = RpcBindingFree(&hBinding);
+    if (Status != RPC_S_OK)
     {
-        ERR("RpcBindingFree returned 0x%x\n", status);
+        ERR("RpcBindingFree returned 0x%x\n", Status);
     }
 }
 
 
+/* HACK: because of a problem with rpcrt4, rpcserver is hacked to return 6 for ERROR_SERVICE_DOES_NOT_EXIST */
 DWORD
 ScmRpcStatusToWinError(RPC_STATUS Status)
 {
     switch (Status)
     {
+        case STATUS_ACCESS_VIOLATION:
         case RPC_S_INVALID_BINDING:
         case RPC_X_SS_IN_NULL_CONTEXT:
             return ERROR_INVALID_HANDLE;
@@ -165,17 +164,18 @@ ChangeServiceConfig2A(SC_HANDLE hService,
 
     TRACE("ChangeServiceConfig2A() called\n");
 
-    /* Fill relevent field of the Info structure */
+    if (lpInfo == NULL) return TRUE;
+
+    /* 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:
@@ -184,9 +184,6 @@ ChangeServiceConfig2A(SC_HANDLE hService,
             return FALSE;
     }
 
-    if (lpInfo == NULL)
-        return TRUE;
-
     RpcTryExcept
     {
         dwError = RChangeServiceConfig2A((SC_RPC_HANDLE)hService,
@@ -224,16 +221,18 @@ ChangeServiceConfig2W(SC_HANDLE hService,
 
     TRACE("ChangeServiceConfig2W() called\n");
 
-    /* Fill relevent field of the Info structure */
+    if (lpInfo == NULL) return TRUE;
+
+    /* 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:
@@ -242,9 +241,6 @@ ChangeServiceConfig2W(SC_HANDLE hService,
             return FALSE;
     }
 
-    if (lpInfo == NULL)
-        return TRUE;
-
     RpcTryExcept
     {
         dwError = RChangeServiceConfig2W((SC_RPC_HANDLE)hService,
@@ -287,8 +283,11 @@ ChangeServiceConfigA(SC_HANDLE hService,
 {
     DWORD dwError;
     DWORD dwDependenciesLength = 0;
-    DWORD dwLength;
+    SIZE_T cchLength;
     LPCSTR lpStr;
+    DWORD dwPasswordLength = 0;
+    LPWSTR lpPasswordW = NULL;
+    LPBYTE lpEncryptedPassword = NULL;
 
     TRACE("ChangeServiceConfigA() called\n");
 
@@ -298,18 +297,39 @@ ChangeServiceConfigA(SC_HANDLE hService,
         lpStr = lpDependencies;
         while (*lpStr)
         {
-            dwLength = strlen(lpStr) + 1;
-            dwDependenciesLength += dwLength;
-            lpStr = lpStr + dwLength;
+            cchLength = strlen(lpStr) + 1;
+            dwDependenciesLength += (DWORD)cchLength;
+            lpStr = lpStr + cchLength;
         }
         dwDependenciesLength++;
     }
 
-    /* FIXME: Encrypt the password */
+    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));
+
+        /* FIXME: Encrypt the password */
+        lpEncryptedPassword = (LPBYTE)lpPasswordW;
+        dwPasswordLength = (wcslen(lpPasswordW) + 1) * sizeof(WCHAR);
+    }
 
     RpcTryExcept
     {
-        /* Call to services.exe using RPC */
         dwError = RChangeServiceConfigA((SC_RPC_HANDLE)hService,
                                         dwServiceType,
                                         dwStartType,
@@ -317,11 +337,11 @@ ChangeServiceConfigA(SC_HANDLE hService,
                                         (LPSTR)lpBinaryPathName,
                                         (LPSTR)lpLoadOrderGroup,
                                         lpdwTagId,
-                                        (LPSTR)lpDependencies,
+                                        (LPBYTE)lpDependencies,
                                         dwDependenciesLength,
                                         (LPSTR)lpServiceStartName,
-                                        NULL,              /* FIXME: lpPassword */
-                                        0,                 /* FIXME: dwPasswordLength */
+                                        lpEncryptedPassword,
+                                        dwPasswordLength,
                                         (LPSTR)lpDisplayName);
     }
     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
@@ -330,6 +350,9 @@ ChangeServiceConfigA(SC_HANDLE hService,
     }
     RpcEndExcept;
 
+    if (lpPasswordW != NULL)
+        HeapFree(GetProcessHeap(), 0, lpPasswordW);
+
     if (dwError != ERROR_SUCCESS)
     {
         TRACE("RChangeServiceConfigA() failed (Error %lu)\n", dwError);
@@ -361,8 +384,10 @@ ChangeServiceConfigW(SC_HANDLE hService,
 {
     DWORD dwError;
     DWORD dwDependenciesLength = 0;
-    DWORD dwLength;
+    SIZE_T cchLength;
     LPCWSTR lpStr;
+    DWORD dwPasswordLength = 0;
+    LPBYTE lpEncryptedPassword = NULL;
 
     TRACE("ChangeServiceConfigW() called\n");
 
@@ -372,18 +397,23 @@ ChangeServiceConfigW(SC_HANDLE hService,
         lpStr = lpDependencies;
         while (*lpStr)
         {
-            dwLength = wcslen(lpStr) + 1;
-            dwDependenciesLength += dwLength;
-            lpStr = lpStr + dwLength;
+            cchLength = wcslen(lpStr) + 1;
+            dwDependenciesLength += (DWORD)cchLength;
+            lpStr = lpStr + cchLength;
         }
         dwDependenciesLength++;
+        dwDependenciesLength *= sizeof(WCHAR);
     }
 
-    /* FIXME: Encrypt the password */
+    if (lpPassword != NULL)
+    {
+        /* FIXME: Encrypt the password */
+        lpEncryptedPassword = (LPBYTE)lpPassword;
+        dwPasswordLength = (wcslen(lpPassword) + 1) * sizeof(WCHAR);
+    }
 
     RpcTryExcept
     {
-        /* Call to services.exe using RPC */
         dwError = RChangeServiceConfigW((SC_RPC_HANDLE)hService,
                                         dwServiceType,
                                         dwStartType,
@@ -394,8 +424,8 @@ ChangeServiceConfigW(SC_HANDLE hService,
                                         (LPBYTE)lpDependencies,
                                         dwDependenciesLength,
                                         (LPWSTR)lpServiceStartName,
-                                        NULL,              /* FIXME: lpPassword */
-                                        0,                 /* FIXME: dwPasswordLength */
+                                        lpEncryptedPassword,
+                                        dwPasswordLength,
                                         (LPWSTR)lpDisplayName);
     }
     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
@@ -435,7 +465,6 @@ CloseServiceHandle(SC_HANDLE hSCObject)
 
     RpcTryExcept
     {
-        /* Call to services.exe using RPC */
         dwError = RCloseServiceHandle((LPSC_RPC_HANDLE)&hSCObject);
     }
     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
@@ -474,7 +503,6 @@ ControlService(SC_HANDLE hService,
 
     RpcTryExcept
     {
-        /* Call to services.exe using RPC */
         dwError = RControlService((SC_RPC_HANDLE)hService,
                                   dwControl,
                                   lpServiceStatus);
@@ -539,11 +567,14 @@ CreateServiceA(SC_HANDLE hSCManager,
     SC_HANDLE hService = NULL;
     DWORD dwDependenciesLength = 0;
     DWORD dwError;
-    DWORD dwLength;
+    SIZE_T cchLength;
     LPCSTR lpStr;
+    DWORD dwPasswordLength = 0;
+    LPWSTR lpPasswordW = NULL;
+    LPBYTE lpEncryptedPassword = NULL;
 
     TRACE("CreateServiceA() called\n");
-    TRACE("%p %s %s\n", hSCManager, 
+    TRACE("%p %s %s\n", hSCManager,
           lpServiceName, lpDisplayName);
 
     if (!hSCManager)
@@ -558,18 +589,39 @@ CreateServiceA(SC_HANDLE hSCManager,
         lpStr = lpDependencies;
         while (*lpStr)
         {
-            dwLength = strlen(lpStr) + 1;
-            dwDependenciesLength += dwLength;
-            lpStr = lpStr + dwLength;
+            cchLength = strlen(lpStr) + 1;
+            dwDependenciesLength += (DWORD)cchLength;
+            lpStr = lpStr + cchLength;
         }
         dwDependenciesLength++;
     }
 
-    /* FIXME: Encrypt the password */
+    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));
+
+        /* FIXME: Encrypt the password */
+        lpEncryptedPassword = (LPBYTE)lpPasswordW;
+        dwPasswordLength = (wcslen(lpPasswordW) + 1) * sizeof(WCHAR);
+    }
 
     RpcTryExcept
     {
-        /* Call to services.exe using RPC */
         dwError = RCreateServiceA((SC_RPC_HANDLE)hSCManager,
                                   (LPSTR)lpServiceName,
                                   (LPSTR)lpDisplayName,
@@ -583,8 +635,8 @@ CreateServiceA(SC_HANDLE hSCManager,
                                   (LPBYTE)lpDependencies,
                                   dwDependenciesLength,
                                   (LPSTR)lpServiceStartName,
-                                  NULL,              /* FIXME: lpPassword */
-                                  0,                 /* FIXME: dwPasswordLength */
+                                  lpEncryptedPassword,
+                                  dwPasswordLength,
                                   (SC_RPC_HANDLE *)&hService);
     }
     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
@@ -593,10 +645,13 @@ CreateServiceA(SC_HANDLE hSCManager,
     }
     RpcEndExcept;
 
+    if (lpPasswordW != NULL)
+        HeapFree(GetProcessHeap(), 0, lpPasswordW);
+
+    SetLastError(dwError);
     if (dwError != ERROR_SUCCESS)
     {
         TRACE("RCreateServiceA() failed (Error %lu)\n", dwError);
-        SetLastError(dwError);
         return NULL;
     }
 
@@ -627,11 +682,13 @@ CreateServiceW(SC_HANDLE hSCManager,
     SC_HANDLE hService = NULL;
     DWORD dwDependenciesLength = 0;
     DWORD dwError;
-    DWORD dwLength;
+    SIZE_T cchLength;
     LPCWSTR lpStr;
+    DWORD dwPasswordLength = 0;
+    LPBYTE lpEncryptedPassword = NULL;
 
     TRACE("CreateServiceW() called\n");
-    TRACE("%p %S %S\n", hSCManager, 
+    TRACE("%p %S %S\n", hSCManager,
           lpServiceName, lpDisplayName);
 
     if (!hSCManager)
@@ -646,20 +703,23 @@ CreateServiceW(SC_HANDLE hSCManager,
         lpStr = lpDependencies;
         while (*lpStr)
         {
-            dwLength = wcslen(lpStr) + 1;
-            dwDependenciesLength += dwLength;
-            lpStr = lpStr + dwLength;
+            cchLength = wcslen(lpStr) + 1;
+            dwDependenciesLength += (DWORD)cchLength;
+            lpStr = lpStr + cchLength;
         }
         dwDependenciesLength++;
-
         dwDependenciesLength *= sizeof(WCHAR);
     }
 
-    /* FIXME: Encrypt the password */
+    if (lpPassword != NULL)
+    {
+        /* FIXME: Encrypt the password */
+        lpEncryptedPassword = (LPBYTE)lpPassword;
+        dwPasswordLength = (wcslen(lpPassword) + 1) * sizeof(WCHAR);
+    }
 
     RpcTryExcept
     {
-        /* Call to services.exe using RPC */
         dwError = RCreateServiceW((SC_RPC_HANDLE)hSCManager,
                                   lpServiceName,
                                   lpDisplayName,
@@ -673,8 +733,8 @@ CreateServiceW(SC_HANDLE hSCManager,
                                   (LPBYTE)lpDependencies,
                                   dwDependenciesLength,
                                   lpServiceStartName,
-                                  NULL,              /* FIXME: lpPassword */
-                                  0,                 /* FIXME: dwPasswordLength */
+                                  lpEncryptedPassword,
+                                  dwPasswordLength,
                                   (SC_RPC_HANDLE *)&hService);
     }
     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
@@ -683,10 +743,10 @@ CreateServiceW(SC_HANDLE hSCManager,
     }
     RpcEndExcept;
 
+    SetLastError(dwError);
     if (dwError != ERROR_SUCCESS)
     {
         TRACE("RCreateServiceW() failed (Error %lu)\n", dwError);
-        SetLastError(dwError);
         return NULL;
     }
 
@@ -708,7 +768,6 @@ DeleteService(SC_HANDLE hService)
 
     RpcTryExcept
     {
-        /* Call to services.exe using RPC */
         dwError = RDeleteService((SC_RPC_HANDLE)hService);
     }
     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
@@ -777,20 +836,17 @@ EnumDependentServicesA(SC_HANDLE hService,
 
     if (dwError == ERROR_SUCCESS || dwError == ERROR_MORE_DATA)
     {
-        if (*lpServicesReturned > 0)
+        for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++)
         {
-            for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++)
-            {
-                if (lpStatusPtr->lpServiceName)
-                    lpStatusPtr->lpServiceName =
-                        (LPSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName);
+            if (lpStatusPtr->lpServiceName)
+                lpStatusPtr->lpServiceName =
+                    (LPSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName);
 
-                if (lpStatusPtr->lpDisplayName)
-                    lpStatusPtr->lpDisplayName =
-                        (LPSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName);
+            if (lpStatusPtr->lpDisplayName)
+                lpStatusPtr->lpDisplayName =
+                    (LPSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName);
 
-                lpStatusPtr++;
-            }
+            lpStatusPtr++;
         }
     }
 
@@ -856,20 +912,17 @@ EnumDependentServicesW(SC_HANDLE hService,
 
     if (dwError == ERROR_SUCCESS || dwError == ERROR_MORE_DATA)
     {
-        if (*lpServicesReturned > 0)
+        for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++)
         {
-            for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++)
-            {
-                if (lpStatusPtr->lpServiceName)
-                    lpStatusPtr->lpServiceName =
-                        (LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName);
+            if (lpStatusPtr->lpServiceName)
+                lpStatusPtr->lpServiceName =
+                    (LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName);
 
-                if (lpStatusPtr->lpDisplayName)
-                    lpStatusPtr->lpDisplayName =
-                        (LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName);
+            if (lpStatusPtr->lpDisplayName)
+                lpStatusPtr->lpDisplayName =
+                    (LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName);
 
-                lpStatusPtr++;
-            }
+            lpStatusPtr++;
         }
     }
 
@@ -916,6 +969,12 @@ EnumServiceGroupW(SC_HANDLE hSCManager,
         return FALSE;
     }
 
+    if (pcbBytesNeeded == NULL || lpServicesReturned == NULL)
+    {
+        SetLastError(ERROR_INVALID_ADDRESS);
+        return FALSE;
+    }
+
     if (lpServices == NULL || cbBufSize < sizeof(ENUM_SERVICE_STATUSW))
     {
         lpStatusPtr = &ServiceStatus;
@@ -961,20 +1020,17 @@ EnumServiceGroupW(SC_HANDLE hSCManager,
 
     if (dwError == ERROR_SUCCESS || dwError == ERROR_MORE_DATA)
     {
-        if (*lpServicesReturned > 0)
+        for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++)
         {
-            for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++)
-            {
-                if (lpStatusPtr->lpServiceName)
-                    lpStatusPtr->lpServiceName =
-                        (LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName);
+            if (lpStatusPtr->lpServiceName)
+                lpStatusPtr->lpServiceName =
+                    (LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName);
 
-                if (lpStatusPtr->lpDisplayName)
-                    lpStatusPtr->lpDisplayName =
-                        (LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName);
+            if (lpStatusPtr->lpDisplayName)
+                lpStatusPtr->lpDisplayName =
+                    (LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName);
 
-                lpStatusPtr++;
-            }
+            lpStatusPtr++;
         }
     }
 
@@ -1020,46 +1076,16 @@ EnumServicesStatusA(SC_HANDLE hSCManager,
         return FALSE;
     }
 
-    if (dwServiceType != SERVICE_DRIVER && dwServiceType != SERVICE_WIN32)
-    {
-        if (pcbBytesNeeded && lpServicesReturned)
-        {
-            *pcbBytesNeeded = 0;
-            *lpServicesReturned = 0;
-        }
-
-        SetLastError(ERROR_INVALID_PARAMETER);
-        return FALSE;
-    }
-
-    if (dwServiceState != SERVICE_ACTIVE && dwServiceState != SERVICE_INACTIVE && dwServiceState != SERVICE_STATE_ALL)
-    {
-            if (pcbBytesNeeded)
-                *pcbBytesNeeded = 0;
-
-            if (lpServicesReturned)
-                *lpServicesReturned = 0;
-
-        SetLastError(ERROR_INVALID_PARAMETER);
-        return FALSE;
-    }
-
-    if (!pcbBytesNeeded || !lpServicesReturned)
+    if (pcbBytesNeeded == NULL || lpServicesReturned == NULL)
     {
         SetLastError(ERROR_INVALID_ADDRESS);
         return FALSE;
     }
 
-    if (!lpServices && cbBufSize != 0)
-    {
-        SetLastError(ERROR_INVALID_ADDRESS);
-        return FALSE;
-    }
-
-    if (lpServices == NULL || cbBufSize < sizeof(ENUM_SERVICE_STATUSW))
+    if (lpServices == NULL || cbBufSize < sizeof(ENUM_SERVICE_STATUSA))
     {
         lpStatusPtr = &ServiceStatus;
-        dwBufferSize = sizeof(ENUM_SERVICE_STATUSW);
+        dwBufferSize = sizeof(ENUM_SERVICE_STATUSA);
     }
     else
     {
@@ -1086,20 +1112,17 @@ EnumServicesStatusA(SC_HANDLE hSCManager,
 
     if (dwError == ERROR_SUCCESS || dwError == ERROR_MORE_DATA)
     {
-        if (*lpServicesReturned > 0)
+        for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++)
         {
-            for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++)
-            {
-                if (lpStatusPtr->lpServiceName)
-                    lpStatusPtr->lpServiceName =
-                        (LPSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName);
+            if (lpStatusPtr->lpServiceName)
+                lpStatusPtr->lpServiceName =
+                    (LPSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName);
 
-                if (lpStatusPtr->lpDisplayName)
-                    lpStatusPtr->lpDisplayName =
-                        (LPSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName);
+            if (lpStatusPtr->lpDisplayName)
+                lpStatusPtr->lpDisplayName =
+                    (LPSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName);
 
-                lpStatusPtr++;
-            }
+            lpStatusPtr++;
         }
     }
 
@@ -1145,6 +1168,12 @@ EnumServicesStatusW(SC_HANDLE hSCManager,
         return FALSE;
     }
 
+    if (pcbBytesNeeded == NULL || lpServicesReturned == NULL)
+    {
+        SetLastError(ERROR_INVALID_ADDRESS);
+        return FALSE;
+    }
+
     if (lpServices == NULL || cbBufSize < sizeof(ENUM_SERVICE_STATUSW))
     {
         lpStatusPtr = &ServiceStatus;
@@ -1175,20 +1204,17 @@ EnumServicesStatusW(SC_HANDLE hSCManager,
 
     if (dwError == ERROR_SUCCESS || dwError == ERROR_MORE_DATA)
     {
-        if (*lpServicesReturned > 0)
+        for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++)
         {
-            for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++)
-            {
-                if (lpStatusPtr->lpServiceName)
-                    lpStatusPtr->lpServiceName =
-                        (LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName);
+            if (lpStatusPtr->lpServiceName)
+                lpStatusPtr->lpServiceName =
+                    (LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName);
 
-                if (lpStatusPtr->lpDisplayName)
-                    lpStatusPtr->lpDisplayName =
-                        (LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName);
+            if (lpStatusPtr->lpDisplayName)
+                lpStatusPtr->lpDisplayName =
+                    (LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName);
 
-                lpStatusPtr++;
-            }
+            lpStatusPtr++;
         }
     }
 
@@ -1242,8 +1268,13 @@ EnumServicesStatusExA(SC_HANDLE hSCManager,
         return FALSE;
     }
 
-    if (lpServices == NULL ||
-        cbBufSize < sizeof(ENUM_SERVICE_STATUS_PROCESSA))
+    if (pcbBytesNeeded == NULL || lpServicesReturned == NULL)
+    {
+        SetLastError(ERROR_INVALID_ADDRESS);
+        return FALSE;
+    }
+
+    if (lpServices == NULL || cbBufSize < sizeof(ENUM_SERVICE_STATUS_PROCESSA))
     {
         lpStatusPtr = &ServiceStatus;
         dwBufferSize = sizeof(ENUM_SERVICE_STATUS_PROCESSA);
@@ -1336,8 +1367,19 @@ EnumServicesStatusExW(SC_HANDLE hSCManager,
         return FALSE;
     }
 
-    if (lpServices == NULL ||
-        cbBufSize < sizeof(ENUM_SERVICE_STATUS_PROCESSW))
+    if (!hSCManager)
+    {
+        SetLastError(ERROR_INVALID_HANDLE);
+        return FALSE;
+    }
+
+    if (pcbBytesNeeded == NULL || lpServicesReturned == NULL)
+    {
+        SetLastError(ERROR_INVALID_ADDRESS);
+        return FALSE;
+    }
+
+    if (lpServices == NULL || cbBufSize < sizeof(ENUM_SERVICE_STATUS_PROCESSW))
     {
         lpStatusPtr = &ServiceStatus;
         dwBufferSize = sizeof(ENUM_SERVICE_STATUS_PROCESSW);
@@ -1443,7 +1485,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;
@@ -1630,6 +1671,42 @@ GetServiceKeyNameW(SC_HANDLE hSCManager,
 }
 
 
+/**********************************************************************
+ *  I_ScGetCurrentGroupStateW
+ *
+ * @implemented
+ */
+DWORD WINAPI
+I_ScGetCurrentGroupStateW(SC_HANDLE hSCManager,
+                          LPWSTR pszGroupName,
+                          LPDWORD pdwGroupState)
+{
+    DWORD dwError;
+
+    TRACE("I_ScGetCurrentGroupStateW() called\n");
+
+    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
  *
@@ -1645,7 +1722,6 @@ LockServiceDatabase(SC_HANDLE hSCManager)
 
     RpcTryExcept
     {
-        /* Call to services.exe using RPC */
         dwError = RLockServiceDatabase((SC_RPC_HANDLE)hSCManager,
                                        (SC_RPC_LOCK *)&hLock);
     }
@@ -1676,28 +1752,14 @@ WaitForSCManager(VOID)
     TRACE("WaitForSCManager() called\n");
 
     /* Try to open the existing event */
-    hEvent = OpenEventW(SYNCHRONIZE,
-                        FALSE,
-                        L"SvcctrlStartEvent_A3752DX");
+    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,
-                              L"SvcctrlStartEvent_A3752DX");
-        if (hEvent == NULL)
-        {
-            /* Try to open the existing event again */
-            hEvent = OpenEventW(SYNCHRONIZE,
-                                FALSE,
-                                L"SvcctrlStartEvent_A3752DX");
-            if (hEvent == NULL)
-                return;
-        }
+        hEvent = CreateEventW(NULL, TRUE, FALSE, SCM_START_EVENT);
+        if (hEvent == NULL) return;
     }
 
     /* Wait for 3 minutes */
@@ -1728,7 +1790,6 @@ OpenSCManagerA(LPCSTR lpMachineName,
 
     RpcTryExcept
     {
-        /* Call to services.exe using RPC */
         dwError = ROpenSCManagerA((LPSTR)lpMachineName,
                                   (LPSTR)lpDatabaseName,
                                   dwDesiredAccess,
@@ -1773,7 +1834,6 @@ OpenSCManagerW(LPCWSTR lpMachineName,
 
     RpcTryExcept
     {
-        /* Call to services.exe using RPC */
         dwError = ROpenSCManagerW((LPWSTR)lpMachineName,
                                   (LPWSTR)lpDatabaseName,
                                   dwDesiredAccess,
@@ -1822,7 +1882,6 @@ OpenServiceA(SC_HANDLE hSCManager,
 
     RpcTryExcept
     {
-        /* Call to services.exe using RPC */
         dwError = ROpenServiceA((SC_RPC_HANDLE)hSCManager,
                                 (LPSTR)lpServiceName,
                                 dwDesiredAccess,
@@ -1834,10 +1893,10 @@ OpenServiceA(SC_HANDLE hSCManager,
     }
     RpcEndExcept;
 
+    SetLastError(dwError);
     if (dwError != ERROR_SUCCESS)
     {
         TRACE("ROpenServiceA() failed (Error %lu)\n", dwError);
-        SetLastError(dwError);
         return NULL;
     }
 
@@ -1871,7 +1930,6 @@ OpenServiceW(SC_HANDLE hSCManager,
 
     RpcTryExcept
     {
-        /* Call to services.exe using RPC */
         dwError = ROpenServiceW((SC_RPC_HANDLE)hSCManager,
                                 (LPWSTR)lpServiceName,
                                 dwDesiredAccess,
@@ -1883,10 +1941,10 @@ OpenServiceW(SC_HANDLE hSCManager,
     }
     RpcEndExcept;
 
+    SetLastError(dwError);
     if (dwError != ERROR_SUCCESS)
     {
         TRACE("ROpenServiceW() failed (Error %lu)\n", dwError);
-        SetLastError(dwError);
         return NULL;
     }
 
@@ -1929,7 +1987,6 @@ QueryServiceConfigA(SC_HANDLE hService,
 
     RpcTryExcept
     {
-        /* Call to services.exe using RPC */
         dwError = RQueryServiceConfigA((SC_RPC_HANDLE)hService,
                                        (LPBYTE)lpConfigPtr,
                                        dwBufferSize,
@@ -2013,7 +2070,6 @@ QueryServiceConfigW(SC_HANDLE hService,
 
     RpcTryExcept
     {
-        /* Call to services.exe using RPC */
         dwError = RQueryServiceConfigW((SC_RPC_HANDLE)hService,
                                        (LPBYTE)lpConfigPtr,
                                        dwBufferSize,
@@ -2117,7 +2173,6 @@ QueryServiceConfig2A(SC_HANDLE hService,
 
     RpcTryExcept
     {
-        /* Call to services.exe using RPC */
         dwError = RQueryServiceConfig2A((SC_RPC_HANDLE)hService,
                                         dwInfoLevel,
                                         lpTempBuffer,
@@ -2137,9 +2192,10 @@ QueryServiceConfig2A(SC_HANDLE hService,
         return FALSE;
     }
 
-    if (bUseTempBuffer == TRUE)
+    if (bUseTempBuffer != FALSE)
     {
         TRACE("RQueryServiceConfig2A() returns ERROR_INSUFFICIENT_BUFFER\n");
+        *pcbBytesNeeded = dwBufferSize;
         SetLastError(ERROR_INSUFFICIENT_BUFFER);
         return FALSE;
     }
@@ -2152,7 +2208,7 @@ QueryServiceConfig2A(SC_HANDLE hService,
 
                 if (lpPtr->lpDescription != NULL)
                     lpPtr->lpDescription =
-                        (LPSTR)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpDescription);
+                        (LPSTR)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpDescription);
             }
             break;
 
@@ -2162,15 +2218,15 @@ QueryServiceConfig2A(SC_HANDLE hService,
 
                 if (lpPtr->lpRebootMsg != NULL)
                     lpPtr->lpRebootMsg =
-                        (LPSTR)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpRebootMsg);
+                        (LPSTR)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpRebootMsg);
 
                 if (lpPtr->lpCommand != NULL)
                     lpPtr->lpCommand =
-                        (LPSTR)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpCommand);
+                        (LPSTR)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpCommand);
 
                 if (lpPtr->lpsaActions != NULL)
                     lpPtr->lpsaActions =
-                        (SC_ACTION*)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpsaActions);
+                        (LPSC_ACTION)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpsaActions);
             }
             break;
     }
@@ -2234,7 +2290,6 @@ QueryServiceConfig2W(SC_HANDLE hService,
 
     RpcTryExcept
     {
-        /* Call to services.exe using RPC */
         dwError = RQueryServiceConfig2W((SC_RPC_HANDLE)hService,
                                         dwInfoLevel,
                                         lpTempBuffer,
@@ -2254,9 +2309,10 @@ QueryServiceConfig2W(SC_HANDLE hService,
         return FALSE;
     }
 
-    if (bUseTempBuffer == TRUE)
+    if (bUseTempBuffer != FALSE)
     {
         TRACE("RQueryServiceConfig2W() returns ERROR_INSUFFICIENT_BUFFER\n");
+        *pcbBytesNeeded = dwBufferSize;
         SetLastError(ERROR_INSUFFICIENT_BUFFER);
         return FALSE;
     }
@@ -2269,7 +2325,7 @@ QueryServiceConfig2W(SC_HANDLE hService,
 
                 if (lpPtr->lpDescription != NULL)
                     lpPtr->lpDescription =
-                        (LPWSTR)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpDescription);
+                        (LPWSTR)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpDescription);
             }
             break;
 
@@ -2279,15 +2335,15 @@ QueryServiceConfig2W(SC_HANDLE hService,
 
                 if (lpPtr->lpRebootMsg != NULL)
                     lpPtr->lpRebootMsg =
-                        (LPWSTR)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpRebootMsg);
+                        (LPWSTR)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpRebootMsg);
 
                 if (lpPtr->lpCommand != NULL)
                     lpPtr->lpCommand =
-                        (LPWSTR)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpCommand);
+                        (LPWSTR)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpCommand);
 
                 if (lpPtr->lpsaActions != NULL)
                     lpPtr->lpsaActions =
-                        (SC_ACTION*)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpsaActions);
+                        (LPSC_ACTION)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpsaActions);
             }
             break;
     }
@@ -2329,9 +2385,8 @@ QueryServiceLockStatusA(SC_HANDLE hSCManager,
 
     RpcTryExcept
     {
-        /* Call to services.exe using RPC */
         dwError = RQueryServiceLockStatusA((SC_RPC_HANDLE)hSCManager,
-                                           lpStatusPtr,
+                                           (LPBYTE)lpStatusPtr,
                                            dwBufferSize,
                                            pcbBytesNeeded);
     }
@@ -2351,7 +2406,7 @@ QueryServiceLockStatusA(SC_HANDLE hSCManager,
     if (lpStatusPtr->lpLockOwner != NULL)
     {
         lpStatusPtr->lpLockOwner =
-            (LPSTR)((UINT_PTR)lpStatusPtr + (UINT_PTR)lpStatusPtr->lpLockOwner);
+            (LPSTR)((ULONG_PTR)lpStatusPtr + (ULONG_PTR)lpStatusPtr->lpLockOwner);
     }
 
     TRACE("QueryServiceLockStatusA() done\n");
@@ -2391,9 +2446,8 @@ QueryServiceLockStatusW(SC_HANDLE hSCManager,
 
     RpcTryExcept
     {
-        /* Call to services.exe using RPC */
         dwError = RQueryServiceLockStatusW((SC_RPC_HANDLE)hSCManager,
-                                           lpStatusPtr,
+                                           (LPBYTE)lpStatusPtr,
                                            dwBufferSize,
                                            pcbBytesNeeded);
     }
@@ -2413,7 +2467,7 @@ QueryServiceLockStatusW(SC_HANDLE hSCManager,
     if (lpStatusPtr->lpLockOwner != NULL)
     {
         lpStatusPtr->lpLockOwner =
-            (LPWSTR)((UINT_PTR)lpStatusPtr + (UINT_PTR)lpStatusPtr->lpLockOwner);
+            (LPWSTR)((ULONG_PTR)lpStatusPtr + (ULONG_PTR)lpStatusPtr->lpLockOwner);
     }
 
     TRACE("QueryServiceLockStatusW() done\n");
@@ -2441,7 +2495,6 @@ QueryServiceObjectSecurity(SC_HANDLE hService,
 
     RpcTryExcept
     {
-        /* Call to services.exe using RPC */
         dwError = RQueryServiceObjectSecurity((SC_RPC_HANDLE)hService,
                                               dwSecurityInformation,
                                               (LPBYTE)lpSecurityDescriptor,
@@ -2508,7 +2561,6 @@ SetServiceObjectSecurity(SC_HANDLE hService,
 
     RpcTryExcept
     {
-        /* Call to services.exe using RPC */
         dwError = RSetServiceObjectSecurity((SC_RPC_HANDLE)hService,
                                             dwSecurityInformation,
                                             (LPBYTE)SelfRelativeSD,
@@ -2555,7 +2607,6 @@ QueryServiceStatus(SC_HANDLE hService,
 
     RpcTryExcept
     {
-        /* Call to services.exe using RPC */
         dwError = RQueryServiceStatus((SC_RPC_HANDLE)hService,
                                       lpServiceStatus);
     }
@@ -2607,7 +2658,6 @@ QueryServiceStatusEx(SC_HANDLE hService,
 
     RpcTryExcept
     {
-        /* Call to services.exe using RPC */
         dwError = RQueryServiceStatusEx((SC_RPC_HANDLE)hService,
                                         InfoLevel,
                                         lpBuffer,
@@ -2715,7 +2765,6 @@ UnlockServiceDatabase(SC_LOCK ScLock)
 
     RpcTryExcept
     {
-        /* Call to services.exe using RPC */
         dwError = RUnlockServiceDatabase((LPSC_RPC_LOCK)&ScLock);
     }
     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
@@ -2724,6 +2773,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);
@@ -2749,7 +2801,6 @@ NotifyBootConfigStatus(BOOL BootAcceptable)
 
     RpcTryExcept
     {
-        /* Call to services.exe using RPC */
         dwError = RNotifyBootConfigStatus(NULL,
                                           BootAcceptable);
     }