Forward ChangeServiceConfig2A, QueryServiceConfig2A/W and EnumServicesStatusExA to...
authorEric Kohl <eric.kohl@reactos.org>
Sun, 1 Jan 2006 10:31:35 +0000 (10:31 +0000)
committerEric Kohl <eric.kohl@reactos.org>
Sun, 1 Jan 2006 10:31:35 +0000 (10:31 +0000)
svn path=/trunk/; revision=20500

reactos/include/idl/svcctl.idl
reactos/lib/advapi32/advapi32.def
reactos/lib/advapi32/service/scm.c
reactos/subsys/system/services/rpcserver.c

index 5003d61..1f22ff9 100644 (file)
@@ -329,17 +329,17 @@ cpp_quote("#endif")
                                [in, out, ref] LPDWORD lpcchBuffer);\r
 \r
   /* Function 34 */\r
-  /* ScmrGetCurrentGroupStateW */\r
+  DWORD ScmrGetCurrentGroupStateW([in] handle_t BindingHandle); /* FIXME */\r
 \r
   /* Function 35 */\r
-  /* ScmrEnumServiceGroupW */\r
+  DWORD ScmrEnumServiceGroupW([in] handle_t BindingHandle); /* FIXME */\r
 \r
   /* Function 36 */\r
-//  DWORD ScmrChangeServiceConfig2A([in] handle_t BindingHandle,\r
-//                                  [in] SC_HANDLE hService,\r
-//                                  [in] DWORD dwInfoLevel,\r
-//                                  [in, size_is(dwInfoSize)] LPBYTE lpInfo,\r
-//                                  [in] DWORD dwInfoSize);\r
+  DWORD ScmrChangeServiceConfig2A([in] handle_t BindingHandle,\r
+                                  [in] SC_HANDLE hService,\r
+                                  [in] DWORD dwInfoLevel,\r
+                                  [in, size_is(dwInfoSize)] LPBYTE lpInfo,\r
+                                  [in] DWORD dwInfoSize);\r
 \r
   /* Function 37 */\r
   DWORD ScmrChangeServiceConfig2W([in] handle_t BindingHandle,\r
@@ -349,10 +349,20 @@ cpp_quote("#endif")
                                   [in] DWORD dwInfoSize);\r
 \r
   /* Function 38 */\r
-  /* ScmrQueryServiceConfig2A */\r
+  DWORD ScmrQueryServiceConfig2A([in] handle_t BindingHandle,\r
+                                 [in] SC_HANDLE hService,\r
+                                 [in] DWORD dwInfoLevel,\r
+                                 [out, unique, size_is(cbBufSize)] LPBYTE lpBuffer,\r
+                                 [in] DWORD cbBufSize,\r
+                                 [out] LPDWORD pcbBytesNeeded);\r
 \r
   /* Function 39 */\r
-  /* ScmrQueryServiceConfig2W */\r
+  DWORD ScmrQueryServiceConfig2W([in] handle_t BindingHandle,\r
+                                 [in] SC_HANDLE hService,\r
+                                 [in] DWORD dwInfoLevel,\r
+                                 [out, unique, size_is(cbBufSize)] LPBYTE lpBuffer,\r
+                                 [in] DWORD cbBufSize,\r
+                                 [out] LPDWORD pcbBytesNeeded);\r
 \r
   /* Function 40 */\r
   DWORD ScmrQueryServiceStatusEx([in] handle_t BindingHandle,\r
@@ -363,17 +373,17 @@ cpp_quote("#endif")
                                  [out] LPDWORD pcbBytesNeeded);\r
 \r
   /* Function 41 */\r
-//  DWORD ScmrEnumServicesStatusExA([in] handle_t BindingHandle,\r
-//                                  [in] SC_HANDLE hService,\r
-//                                  [in] SC_ENUM_TYPE InfoLevel,\r
-//                                  [in] DWORD dwServiceType,\r
-//                                  [in] DWORD dwServiceState,\r
-//                                  [out, unique, size_is(cbBufSize)] LPBYTE lpServices,\r
-//                                  [in] DWORD cbBufSize,\r
-//                                  [out] LPDWORD pcbBytesNeeded,\r
-//                                  [out] LPDWORD lpServicesReturned,\r
-//                                  [in, out, unique] LPDWORD lpResumeHandle,\r
-//                                  [in, string] LPCSTR pszGroupName);\r
+  DWORD ScmrEnumServicesStatusExA([in] handle_t BindingHandle,\r
+                                  [in] SC_HANDLE hService,\r
+                                  [in] SC_ENUM_TYPE InfoLevel,\r
+                                  [in] DWORD dwServiceType,\r
+                                  [in] DWORD dwServiceState,\r
+                                  [out, unique, size_is(cbBufSize)] LPBYTE lpServices,\r
+                                  [in] DWORD cbBufSize,\r
+                                  [out] LPDWORD pcbBytesNeeded,\r
+                                  [out] LPDWORD lpServicesReturned,\r
+                                  [in, out, unique] LPDWORD lpResumeHandle,\r
+                                  [in, string] LPCSTR pszGroupName);\r
 \r
   /* Function 42 */\r
   DWORD ScmrEnumServicesStatusExW([in] handle_t BindingHandle,\r
index bcd9f6f..175ddb9 100644 (file)
@@ -58,7 +58,7 @@ BuildTrusteeWithObjectsAndSidW@20
 BuildTrusteeWithSidA@8
 BuildTrusteeWithSidW@8
 ;CancelOverlappedAccess@4
-;ChangeServiceConfig2A@12
+ChangeServiceConfig2A@12
 ChangeServiceConfig2W@12
 ChangeServiceConfigA@44
 ChangeServiceConfigW@44
index eb50852..3a9012d 100644 (file)
@@ -77,6 +77,59 @@ HandleUnbind(VOID)
 #endif
 
 
+/**********************************************************************
+ *  ChangeServiceConfig2A
+ *
+ * @implemented
+ */
+BOOL WINAPI
+ChangeServiceConfig2A(SC_HANDLE hService,
+                      DWORD dwInfoLevel,
+                      LPVOID lpInfo)
+{
+    DWORD lpInfoSize;
+    DWORD dwError;
+
+    DPRINT("ChangeServiceConfig2A() called\n");
+
+    /* Determine the length of the lpInfo parameter */
+    switch (dwInfoLevel)
+    {
+        case SERVICE_CONFIG_DESCRIPTION:
+            lpInfoSize = sizeof(SERVICE_DESCRIPTIONA);
+            break;
+
+        case SERVICE_CONFIG_FAILURE_ACTIONS:
+            lpInfoSize = sizeof(SERVICE_FAILURE_ACTIONSA);
+            break;
+
+        default:
+            DPRINT1("Unknown info level 0x%lx\n", dwInfoLevel);
+            SetLastError(ERROR_INVALID_PARAMETER);
+            return FALSE;
+    }
+
+    if (lpInfo == NULL)
+        return TRUE;
+
+    HandleBind();
+
+    dwError = ScmrChangeServiceConfig2A(BindingHandle,
+                                        (unsigned int)hService,
+                                        dwInfoLevel,
+                                        lpInfo,
+                                        lpInfoSize);
+    if (dwError != ERROR_SUCCESS)
+    {
+        DPRINT1("ScmrChangeServiceConfig2A() failed (Error %lu)\n", dwError);
+        SetLastError(dwError);
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+
 /**********************************************************************
  *  ChangeServiceConfig2W
  *
@@ -96,11 +149,13 @@ ChangeServiceConfig2W(SC_HANDLE hService,
     switch (dwInfoLevel)
     {
         case SERVICE_CONFIG_DESCRIPTION:
-            lpInfoSize = sizeof(SERVICE_DESCRIPTION);
+            lpInfoSize = sizeof(SERVICE_DESCRIPTIONW);
             break;
+
         case SERVICE_CONFIG_FAILURE_ACTIONS:
-            lpInfoSize = sizeof(SERVICE_FAILURE_ACTIONS);
+            lpInfoSize = sizeof(SERVICE_FAILURE_ACTIONSW);
             break;
+
         default:
             DPRINT1("Unknown info level 0x%lx\n", dwInfoLevel);
             SetLastError(ERROR_INVALID_PARAMETER);
@@ -652,23 +707,60 @@ EnumServiceGroupW(
 /**********************************************************************
  *  EnumServicesStatusA
  *
- * @unimplemented
+ * @implemented
  */
-BOOL
-STDCALL
-EnumServicesStatusA(
-    SC_HANDLE               hSCManager,
-    DWORD                   dwServiceType,
-    DWORD                   dwServiceState,
-    LPENUM_SERVICE_STATUSA  lpServices,
-    DWORD                   cbBufSize,
-    LPDWORD                 pcbBytesNeeded,
-    LPDWORD                 lpServicesReturned,
-    LPDWORD                 lpResumeHandle)
+BOOL STDCALL
+EnumServicesStatusA(SC_HANDLE hSCManager,
+                    DWORD dwServiceType,
+                    DWORD dwServiceState,
+                    LPENUM_SERVICE_STATUSA lpServices,
+                    DWORD cbBufSize,
+                    LPDWORD pcbBytesNeeded,
+                    LPDWORD lpServicesReturned,
+                    LPDWORD lpResumeHandle)
 {
-    DPRINT1("EnumServicesStatusA is unimplemented\n");
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return FALSE;
+    LPENUM_SERVICE_STATUSA lpStatusPtr;
+    DWORD dwError = ERROR_SUCCESS;
+    DWORD dwCount;
+
+    DPRINT("EnumServicesStatusA() called\n");
+
+    HandleBind();
+
+    dwError = ScmrEnumServicesStatusA(BindingHandle,
+                                      (unsigned int)hSCManager,
+                                      dwServiceType,
+                                      dwServiceState,
+                                      (unsigned char *)lpServices,
+                                      cbBufSize,
+                                      pcbBytesNeeded,
+                                      lpServicesReturned,
+                                      lpResumeHandle);
+
+    lpStatusPtr = (LPENUM_SERVICE_STATUSA)lpServices;
+    for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++)
+    {
+        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);
+
+        lpStatusPtr++;
+    }
+
+    if (dwError != ERROR_SUCCESS)
+    {
+        DPRINT("ScmrEnumServicesStatusA() failed (Error %lu)\n", dwError);
+        SetLastError(dwError);
+        return FALSE;
+    }
+
+    DPRINT("ScmrEnumServicesStatusA() done\n");
+
+    return TRUE;
 }
 
 
@@ -735,24 +827,64 @@ EnumServicesStatusW(SC_HANDLE hSCManager,
 /**********************************************************************
  *  EnumServicesStatusExA
  *
- * @unimplemented
+ * @implemented
  */
-BOOL
-STDCALL
-EnumServicesStatusExA(SC_HANDLE  hSCManager,
-  SC_ENUM_TYPE  InfoLevel,
-  DWORD  dwServiceType,
-  DWORD  dwServiceState,
-  LPBYTE  lpServices,
-  DWORD  cbBufSize,
-  LPDWORD  pcbBytesNeeded,
-  LPDWORD  lpServicesReturned,
-  LPDWORD  lpResumeHandle,
-  LPCSTR  pszGroupName)
+BOOL STDCALL
+EnumServicesStatusExA(SC_HANDLE hSCManager,
+                      SC_ENUM_TYPE InfoLevel,
+                      DWORD dwServiceType,
+                      DWORD dwServiceState,
+                      LPBYTE lpServices,
+                      DWORD cbBufSize,
+                      LPDWORD pcbBytesNeeded,
+                      LPDWORD lpServicesReturned,
+                      LPDWORD lpResumeHandle,
+                      LPCSTR pszGroupName)
 {
-    DPRINT1("EnumServicesStatusExA is unimplemented\n");
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return FALSE;
+    LPENUM_SERVICE_STATUS_PROCESSA lpStatusPtr;
+    DWORD dwError = ERROR_SUCCESS;
+    DWORD dwCount;
+
+    DPRINT("EnumServicesStatusExA() called\n");
+
+    HandleBind();
+
+    dwError = ScmrEnumServicesStatusExA(BindingHandle,
+                                        (unsigned int)hSCManager,
+                                        (unsigned long)InfoLevel,
+                                        dwServiceType,
+                                        dwServiceState,
+                                        (unsigned char *)lpServices,
+                                        cbBufSize,
+                                        pcbBytesNeeded,
+                                        lpServicesReturned,
+                                        lpResumeHandle,
+                                        (char *)pszGroupName);
+
+    lpStatusPtr = (LPENUM_SERVICE_STATUS_PROCESSA)lpServices;
+    for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++)
+    {
+        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);
+
+        lpStatusPtr++;
+    }
+
+    if (dwError != ERROR_SUCCESS)
+    {
+        DPRINT1("ScmrEnumServicesStatusExA() failed (Error %lu)\n", dwError);
+        SetLastError(dwError);
+        return FALSE;
+    }
+
+    DPRINT("ScmrEnumServicesStatusExA() done\n");
+
+    return TRUE;
 }
 
 
@@ -777,7 +909,7 @@ EnumServicesStatusExW(SC_HANDLE hSCManager,
     DWORD dwError = ERROR_SUCCESS;
     DWORD dwCount;
 
-    DPRINT1("EnumServicesStatusExW() called\n");
+    DPRINT("EnumServicesStatusExW() called\n");
 
     HandleBind();
 
@@ -814,7 +946,7 @@ EnumServicesStatusExW(SC_HANDLE hSCManager,
         return FALSE;
     }
 
-    DPRINT1("ScmrEnumServicesStatusExW() done\n");
+    DPRINT("ScmrEnumServicesStatusExW() done\n");
 
     return TRUE;
 }
@@ -1313,38 +1445,150 @@ QueryServiceConfigW(SC_HANDLE hService,
 /**********************************************************************
  *  QueryServiceConfig2A
  *
- * @unimplemented
+ * @implemented
  */
-BOOL
-STDCALL
-QueryServiceConfig2A(
-    SC_HANDLE       hService,
-    DWORD           dwInfo,
-    LPBYTE          lpBuffer,
-    DWORD           cbBufSize,
-    LPDWORD         pcbBytesNeeded)
+BOOL STDCALL
+QueryServiceConfig2A(SC_HANDLE hService,
+                     DWORD dwInfoLevel,
+                     LPBYTE lpBuffer,
+                     DWORD cbBufSize,
+                     LPDWORD pcbBytesNeeded)
 {
-    DPRINT1("QueryServiceConfig2A is unimplemented\n");
-    return FALSE;
+    DWORD dwError;
+
+    DPRINT("QueryServiceConfig2A(%p, %lu, %p, %lu, %p)\n",
+           hService, dwInfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
+
+    HandleBind();
+
+    /* Call to services.exe using RPC */
+    dwError = ScmrQueryServiceConfig2A(BindingHandle,
+                                       (unsigned int)hService,
+                                       dwInfoLevel,
+                                       (unsigned char *)lpBuffer,
+                                       cbBufSize,
+                                       pcbBytesNeeded);
+    if (dwError != ERROR_SUCCESS)
+    {
+        DPRINT("ScmrQueryServiceConfig2A() failed (Error %lu)\n", dwError);
+        SetLastError(dwError);
+        return FALSE;
+    }
+
+    switch (dwInfoLevel)
+    {
+        case SERVICE_CONFIG_DESCRIPTION:
+            {
+                LPSERVICE_DESCRIPTIONA lpPtr = (LPSERVICE_DESCRIPTIONA)lpBuffer;
+
+                if (lpPtr->lpDescription != NULL)
+                    lpPtr->lpDescription =
+                        (LPSTR)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpDescription);
+            }
+            break;
+
+        case SERVICE_CONFIG_FAILURE_ACTIONS:
+            {
+                LPSERVICE_FAILURE_ACTIONSA lpPtr = (LPSERVICE_FAILURE_ACTIONSA)lpBuffer;
+
+                if (lpPtr->lpRebootMsg != NULL)
+                    lpPtr->lpRebootMsg =
+                        (LPSTR)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpRebootMsg);
+
+                if (lpPtr->lpCommand != NULL)
+                    lpPtr->lpCommand =
+                        (LPSTR)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpCommand);
+
+                if (lpPtr->lpsaActions != NULL)
+                    lpPtr->lpsaActions =
+                        (SC_ACTION*)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpsaActions);
+            }
+            break;
+
+        default:
+            DPRINT1("Unknown info level 0x%lx\n", dwInfoLevel);
+            SetLastError(ERROR_INVALID_PARAMETER);
+            return FALSE;
+    }
+
+    DPRINT("QueryServiceConfig2A() done\n");
+
+    return TRUE;
 }
 
 
 /**********************************************************************
  *  QueryServiceConfig2W
  *
- * @unimplemented
+ * @implemented
  */
-BOOL
-STDCALL
-QueryServiceConfig2W(
-    SC_HANDLE       hService,
-    DWORD           dwInfo,
-    LPBYTE          lpBuffer,
-    DWORD           cbBufSize,
-    LPDWORD         pcbBytesNeeded)
+BOOL STDCALL
+QueryServiceConfig2W(SC_HANDLE hService,
+                     DWORD dwInfoLevel,
+                     LPBYTE lpBuffer,
+                     DWORD cbBufSize,
+                     LPDWORD pcbBytesNeeded)
 {
-    DPRINT1("QueryServiceConfig2W is unimplemented\n");
-    return FALSE;
+    DWORD dwError;
+
+    DPRINT("QueryServiceConfig2W(%p, %lu, %p, %lu, %p)\n",
+           hService, dwInfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
+
+    HandleBind();
+
+    /* Call to services.exe using RPC */
+    dwError = ScmrQueryServiceConfig2W(BindingHandle,
+                                       (unsigned int)hService,
+                                       dwInfoLevel,
+                                       (unsigned char *)lpBuffer,
+                                       cbBufSize,
+                                       pcbBytesNeeded);
+    if (dwError != ERROR_SUCCESS)
+    {
+        DPRINT("ScmrQueryServiceConfig2W() failed (Error %lu)\n", dwError);
+        SetLastError(dwError);
+        return FALSE;
+    }
+
+    switch (dwInfoLevel)
+    {
+        case SERVICE_CONFIG_DESCRIPTION:
+            {
+                LPSERVICE_DESCRIPTIONW lpPtr = (LPSERVICE_DESCRIPTIONW)lpBuffer;
+
+                if (lpPtr->lpDescription != NULL)
+                    lpPtr->lpDescription =
+                        (LPWSTR)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpDescription);
+            }
+            break;
+
+        case SERVICE_CONFIG_FAILURE_ACTIONS:
+            {
+                LPSERVICE_FAILURE_ACTIONSW lpPtr = (LPSERVICE_FAILURE_ACTIONSW)lpBuffer;
+
+                if (lpPtr->lpRebootMsg != NULL)
+                    lpPtr->lpRebootMsg =
+                        (LPWSTR)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpRebootMsg);
+
+                if (lpPtr->lpCommand != NULL)
+                    lpPtr->lpCommand =
+                        (LPWSTR)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpCommand);
+
+                if (lpPtr->lpsaActions != NULL)
+                    lpPtr->lpsaActions =
+                        (SC_ACTION*)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpsaActions);
+            }
+            break;
+
+        default:
+            DPRINT1("Unknown info level 0x%lx\n", dwInfoLevel);
+            SetLastError(ERROR_INVALID_PARAMETER);
+            return FALSE;
+    }
+
+    DPRINT("QueryServiceConfig2W() done\n");
+
+    return TRUE;
 }
 
 
index 2464ece..d77fc75 100644 (file)
@@ -2105,15 +2105,34 @@ ScmrGetServiceKeyNameA(handle_t BindingHandle,
 
 
 /* Function 34 */
-/* ScmrGetCurrentGroupStateW */
+unsigned long
+ScmrGetCurrentGroupStateW(handle_t BindingHandle)
+{
+    DPRINT1("ScmrGetCurrentGroupStateW() is unimplemented\n");
+    return ERROR_CALL_NOT_IMPLEMENTED;
+}
 
 
 /* Function 35 */
-/* ScmrEnumServiceGroupW */
+unsigned long
+ScmrEnumServiceGroupW(handle_t BindingHandle)
+{
+    DPRINT1("ScmrEnumServiceGroupW() is unimplemented\n");
+    return ERROR_CALL_NOT_IMPLEMENTED;
+}
 
 
 /* Function 36 */
-/* ScmrChangeServiceConfig2A */
+unsigned long
+ScmrChangeServiceConfig2A(handle_t BindingHandle,
+                          unsigned int hService,
+                          unsigned long dwInfoLevel,
+                          unsigned char *lpInfo,
+                          unsigned long dwInfoSize)
+{
+    DPRINT1("ScmrChangeServiceConfig2A() is unimplemented\n");
+    return ERROR_CALL_NOT_IMPLEMENTED;
+}
 
 
 /* Function 37 */
@@ -2130,11 +2149,31 @@ ScmrChangeServiceConfig2W(handle_t BindingHandle,
 
 
 /* Function 38 */
-/* ScmrQueryServiceConfig2A */
+unsigned long
+ScmrQueryServiceConfig2A(handle_t BindingHandle,
+                         unsigned int hService,
+                         unsigned long dwInfoLevel,
+                         unsigned char *lpBuffer,
+                         unsigned long cbBufSize,
+                         unsigned long *pcbBytesNeeded)
+{
+    DPRINT1("ScmrQueryServiceConfig2A() is unimplemented\n");
+    return ERROR_CALL_NOT_IMPLEMENTED;
+}
 
 
 /* Function 39 */
-/* ScmrQueryServiceConfig2W */
+unsigned long
+ScmrQueryServiceConfig2W(handle_t BindingHandle,
+                         unsigned int hService,
+                         unsigned long dwInfoLevel,
+                         unsigned char *lpBuffer,
+                         unsigned long cbBufSize,
+                         unsigned long *pcbBytesNeeded)
+{
+    DPRINT1("ScmrQueryServiceConfig2W() is unimplemented\n");
+    return ERROR_CALL_NOT_IMPLEMENTED;
+}
 
 
 /* Function 40 */
@@ -2199,7 +2238,24 @@ ScmrQueryServiceStatusEx(handle_t BindingHandle,
 
 
 /* Function 41 */
-/* ScmrEnumServicesStatusExA */
+unsigned long
+ScmrEnumServicesStatusExA(handle_t BindingHandle,
+                          unsigned int hSCManager,
+                          unsigned long InfoLevel,
+                          unsigned long dwServiceType,
+                          unsigned long dwServiceState,
+                          unsigned char *lpServices,
+                          unsigned long dwBufSize,
+                          unsigned long *pcbBytesNeeded,
+                          unsigned long *lpServicesReturned,
+                          unsigned long *lpResumeHandle,
+                          char *pszGroupName)
+{
+    DPRINT1("ScmrEnumServicesStatusExA() is unimplemented\n");
+    *pcbBytesNeeded = 0;
+    *lpServicesReturned = 0;
+    return ERROR_CALL_NOT_IMPLEMENTED;
+}
 
 
 /* Function 42 */
@@ -2290,9 +2346,17 @@ ScmrEnumServicesStatusExW(handle_t BindingHandle,
 
         if (pszGroupName)
         {
-            if ((CurrentService->lpGroup == NULL) ||
-                _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName))
-                continue;
+            if (*pszGroupName == 0)
+            {
+                if (CurrentService->lpGroup != NULL)
+                    continue;
+            }
+            else
+            {
+                if ((CurrentService->lpGroup == NULL) ||
+                    _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName))
+                    continue;
+            }
         }
 
         dwSize = sizeof(ENUM_SERVICE_STATUS_PROCESSW) +
@@ -2337,9 +2401,17 @@ ScmrEnumServicesStatusExW(handle_t BindingHandle,
 
         if (pszGroupName)
         {
-            if ((CurrentService->lpGroup == NULL) ||
-                _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName))
-                continue;
+            if (*pszGroupName == 0)
+            {
+                if (CurrentService->lpGroup != NULL)
+                    continue;
+            }
+            else
+            {
+                if ((CurrentService->lpGroup == NULL) ||
+                    _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName))
+                    continue;
+            }
         }
 
         dwRequiredSize += (sizeof(ENUM_SERVICE_STATUS_PROCESSW) +
@@ -2380,9 +2452,17 @@ ScmrEnumServicesStatusExW(handle_t BindingHandle,
 
         if (pszGroupName)
         {
-            if ((CurrentService->lpGroup == NULL) ||
-                _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName))
-                continue;
+            if (*pszGroupName == 0)
+            {
+                if (CurrentService->lpGroup != NULL)
+                    continue;
+            }
+            else
+            {
+                if ((CurrentService->lpGroup == NULL) ||
+                    _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName))
+                    continue;
+            }
         }
 
         dwSize = sizeof(ENUM_SERVICE_STATUS_PROCESSW) +