-Implement EnumServicesStatusExW.
-Add missing [unique] Attributes to svcctrl.idl.
Modified: trunk/reactos/include/idl/svcctl.idl
Modified: trunk/reactos/lib/advapi32/service/scm.c
Modified: trunk/reactos/subsys/system/services/rpcserver.c

Modified: trunk/reactos/include/idl/svcctl.idl
--- trunk/reactos/include/idl/svcctl.idl	2005-12-26 02:45:49 UTC (rev 20334)
+++ trunk/reactos/include/idl/svcctl.idl	2005-12-26 15:06:46 UTC (rev 20335)
@@ -12,6 +12,7 @@
 #define SC_LOCK unsigned int
 #define SERVICE_STATUS_HANDLE unsigned long
 #define SC_STATUS_TYPE unsigned long
+#define SC_ENUM_TYPE unsigned long
 #define LPSTR char*
 #define LPCSTR char*
 #define LPWSTR wchar_t*
@@ -138,7 +139,7 @@
   DWORD ScmrEnumDependentServicesW([in] handle_t BindingHandle,
                                    [in] SC_HANDLE hService,
                                    [in] DWORD dwServiceState,
-                                   [out, size_is(cbBufSize)] LPBYTE lpServices,
+                                   [out, unique, size_is(cbBufSize)] LPBYTE lpServices,
                                    [in] DWORD cbBufSize,
                                    [out] LPDWORD pcbBytesNeeded,
                                    [out] LPDWORD lpServicesReturned);
@@ -148,7 +149,7 @@
                                 [in] SC_HANDLE hSCManager,
                                 [in] DWORD dwServiceType,
                                 [in] DWORD dwServiceState,
-                                [out, size_is(dwBufSize)] LPBYTE lpServices,
+                                [out, unique, size_is(dwBufSize)] LPBYTE lpServices,
                                 [in] DWORD dwBufSize,
                                 [out] LPDWORD pcbBytesNeeded,
                                 [out] LPDWORD lpServicesReturned,
@@ -178,7 +179,7 @@
   /* Function 18 */
   DWORD ScmrQueryServiceLockStatusW([in] handle_t BindingHandle,
                                     [in] SC_HANDLE hSCManager,
-                                    [out, size_is(cbBufSize), unique] LPBYTE lpLockStatus,
+                                    [out, unique, size_is(cbBufSize)] LPBYTE lpLockStatus,
                                     [in] DWORD cbBufSize,
                                     [out] LPDWORD pcbBytesNeeded);
 
@@ -249,7 +250,7 @@
   DWORD ScmrEnumDependentServicesA([in] handle_t BindingHandle,
                                    [in] SC_HANDLE hService,
                                    [in] DWORD dwServiceState,
-                                   [out, size_is(cbBufSize)] LPBYTE lpServices,
+                                   [out, unique, size_is(cbBufSize)] LPBYTE lpServices,
                                    [in] DWORD cbBufSize,
                                    [out] LPDWORD pcbBytesNeeded,
                                    [out] LPDWORD lpServicesReturned);
@@ -259,7 +260,7 @@
                                 [in] SC_HANDLE hSCManager,
                                 [in] DWORD dwServiceType,
                                 [in] DWORD dwServiceState,
-                                [out, size_is(dwBufSize)] LPBYTE lpServices,
+                                [out, unique, size_is(dwBufSize)] LPBYTE lpServices,
                                 [in] DWORD dwBufSize,
                                 [out] LPDWORD pcbBytesNeeded,
                                 [out] LPDWORD lpServicesReturned,
@@ -289,7 +290,7 @@
   /* Function 30 */
 //  DWORD ScmrQueryServiceLockStatusA([in] handle_t BindingHandle,
 //                                    [in] SC_HANDLE hSCManager,
-//                                    [out, size_is(cbBufSize), unique] LPBYTE lpLockStatus,
+//                                    [out, unique, size_is(cbBufSize)] LPBYTE lpLockStatus,
 //                                    [in] DWORD cbBufSize,
 //                                    [out] LPDWORD pcbBytesNeeded);
 
@@ -297,20 +298,20 @@
 //  DWORD ScmrStartServiceA([in] handle_t BindingHandle,
 //                          [in] SC_HANDLE hService,
 //                          [in] DWORD dwNumServiceArgs,
-//                          [in, string, size_is(dwNumServiceArgs, ), unique] LPSTR *lpServiceArgVectors);
+//                          [in, unique, string, size_is(dwNumServiceArgs, )] LPSTR *lpServiceArgVectors);
 
   /* Function 32 */
   DWORD ScmrGetServiceDisplayNameA([in] handle_t BindingHandle,
                                    [in] SC_HANDLE hSCManager,
                                    [in, string, ref] LPCSTR lpServiceName,
-                                   [out, size_is(*lpcchBuffer), unique] LPSTR lpDisplayName,
+                                   [out, unique, size_is(*lpcchBuffer)] LPSTR lpDisplayName,
                                    [in, out, ref] LPDWORD lpcchBuffer);
 
   /* Function 33 */
   DWORD ScmrGetServiceKeyNameA([in] handle_t BindingHandle,
                                [in] SC_HANDLE hSCManager,
                                [in, string, ref] LPCSTR lpDisplayName,
-                               [out, size_is(*lpcchBuffer), unique] LPSTR lpServiceName,
+                               [out, unique, size_is(*lpcchBuffer)] LPSTR lpServiceName,
                                [in, out, ref] LPDWORD lpcchBuffer);
 
   /* Function 35 */
@@ -335,15 +336,35 @@
   DWORD ScmrQueryServiceStatusEx([in] handle_t BindingHandle,
                                  [in] SC_HANDLE hService,
                                  [in] SC_STATUS_TYPE InfoLevel,
-                                 [out, size_is(cbBufSize)] LPBYTE lpBuffer,
+                                 [out, unique, size_is(cbBufSize)] LPBYTE lpBuffer,
                                  [in] DWORD cbBufSize,
                                  [out] LPDWORD pcbBytesNeeded);
 
   /* Function 41 */
-  /* ScmrEnumServicesStatusExA */
+//  DWORD ScmrEnumServicesStatusExA([in] handle_t BindingHandle,
+//                                  [in] SC_HANDLE hService,
+//                                  [in] SC_ENUM_TYPE InfoLevel,
+//                                  [in] DWORD dwServiceType,
+//                                  [in] DWORD dwServiceState,
+//                                  [out, unique, size_is(cbBufSize)] LPBYTE lpServices,
+//                                  [in] DWORD cbBufSize,
+//                                  [out] LPDWORD pcbBytesNeeded,
+//                                  [out] LPDWORD lpServicesReturned,
+//                                  [in, out, unique] LPDWORD lpResumeHandle,
+//                                  [in, string] LPCSTR pszGroupName);
 
   /* Function 42 */
-  /* ScmrEnumServicesStatusExW */
+  DWORD ScmrEnumServicesStatusExW([in] handle_t BindingHandle,
+                                  [in] SC_HANDLE hService,
+                                  [in] SC_ENUM_TYPE InfoLevel,
+                                  [in] DWORD dwServiceType,
+                                  [in] DWORD dwServiceState,
+                                  [out, unique, size_is(cbBufSize)] LPBYTE lpServices,
+                                  [in] DWORD cbBufSize,
+                                  [out] LPDWORD pcbBytesNeeded,
+                                  [out] LPDWORD lpServicesReturned,
+                                  [in, out, unique] LPDWORD lpResumeHandle,
+                                  [in, string] LPCWSTR pszGroupName);
 
   /* Function 43 */
   /* ScmrSendTSMessage */

Modified: trunk/reactos/lib/advapi32/service/scm.c
--- trunk/reactos/lib/advapi32/service/scm.c	2005-12-26 02:45:49 UTC (rev 20334)
+++ trunk/reactos/lib/advapi32/service/scm.c	2005-12-26 15:06:46 UTC (rev 20335)
@@ -708,24 +708,64 @@
 /**********************************************************************
  *  EnumServicesStatusExW
  *
- * @unimplemented
+ * @implemented
  */
-BOOL
-STDCALL
-EnumServicesStatusExW(SC_HANDLE  hSCManager,
-  SC_ENUM_TYPE  InfoLevel,
-  DWORD  dwServiceType,
-  DWORD  dwServiceState,
-  LPBYTE  lpServices,
-  DWORD  cbBufSize,
-  LPDWORD  pcbBytesNeeded,
-  LPDWORD  lpServicesReturned,
-  LPDWORD  lpResumeHandle,
-  LPCWSTR  pszGroupName)
+BOOL STDCALL
+EnumServicesStatusExW(SC_HANDLE hSCManager,
+                      SC_ENUM_TYPE InfoLevel,
+                      DWORD dwServiceType,
+                      DWORD dwServiceState,
+                      LPBYTE lpServices,
+                      DWORD cbBufSize,
+                      LPDWORD pcbBytesNeeded,
+                      LPDWORD lpServicesReturned,
+                      LPDWORD lpResumeHandle,
+                      LPCWSTR pszGroupName)
 {
-    DPRINT1("EnumServicesStatusExW is unimplemented\n");
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return FALSE;
+    LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr;
+    DWORD dwError = ERROR_SUCCESS;
+    DWORD dwCount;
+
+    DPRINT1("EnumServicesStatusExW() called\n");
+
+    HandleBind();
+
+    dwError = ScmrEnumServicesStatusExW(BindingHandle,
+                                        (unsigned int)hSCManager,
+                                        (unsigned long)InfoLevel,
+                                        dwServiceType,
+                                        dwServiceState,
+                                        (unsigned char *)lpServices,
+                                        cbBufSize,
+                                        pcbBytesNeeded,
+                                        lpServicesReturned,
+                                        lpResumeHandle,
+                                        (wchar_t *)pszGroupName);
+
+    lpStatusPtr = (LPENUM_SERVICE_STATUS_PROCESSW)lpServices;
+    for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++)
+    {
+        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);
+
+        lpStatusPtr++;
+    }
+
+    if (dwError != ERROR_SUCCESS)
+    {
+        DPRINT1("ScmrEnumServicesStatusExW() failed (Error %lu)\n", dwError);
+        SetLastError(dwError);
+        return FALSE;
+    }
+
+    DPRINT1("ScmrEnumServicesStatusExW() done\n");
+
+    return TRUE;
 }
 
 
@@ -1390,7 +1430,7 @@
                                        pcbBytesNeeded);
     if (dwError != ERROR_SUCCESS)
     {
-        DPRINT1("ScmrQueryServiceStatusEx() failed (Error %lu)\n", dwError);
+        DPRINT("ScmrQueryServiceStatusEx() failed (Error %lu)\n", dwError);
         SetLastError(dwError);
         return FALSE;
     }

Modified: trunk/reactos/subsys/system/services/rpcserver.c
--- trunk/reactos/subsys/system/services/rpcserver.c	2005-12-26 02:45:49 UTC (rev 20334)
+++ trunk/reactos/subsys/system/services/rpcserver.c	2005-12-26 15:06:46 UTC (rev 20335)
@@ -1393,9 +1393,9 @@
     *lpServicesReturned = dwServiceCount;
     *pcbBytesNeeded = dwRequiredSize;
 
-    lpStatusPtr = (LPENUM_SERVICE_STATUS)lpServices;
+    lpStatusPtr = (LPENUM_SERVICE_STATUSW)lpServices;
     lpStringPtr = (LPWSTR)((ULONG_PTR)lpServices +
-                           dwServiceCount * sizeof(ENUM_SERVICE_STATUS));
+                           dwServiceCount * sizeof(ENUM_SERVICE_STATUSW));
 
     dwRequiredSize = 0;
     for (ServiceEntry = &lpService->ServiceListEntry;
@@ -2138,9 +2138,229 @@
 
 
 /* Function 42 */
-/* ScmrEnumServicesStatusExW */
+unsigned long
+ScmrEnumServicesStatusExW(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,
+                          wchar_t *pszGroupName)
+{
+    PMANAGER_HANDLE hManager;
+    PSERVICE lpService;
+    DWORD dwError = ERROR_SUCCESS;
+    PLIST_ENTRY ServiceEntry;
+    PSERVICE CurrentService;
+    DWORD dwState;
+    DWORD dwRequiredSize;
+    DWORD dwServiceCount;
+    DWORD dwSize;
+    DWORD dwLastResumeCount;
+    LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr;
+    LPWSTR lpStringPtr;
 
+    DPRINT("ScmrEnumServicesStatusExW() called\n");
 
+    if (ScmShutdown)
+        return ERROR_SHUTDOWN_IN_PROGRESS;
+
+    if (InfoLevel != SC_ENUM_PROCESS_INFO)
+        return ERROR_INVALID_LEVEL;
+
+    hManager = (PMANAGER_HANDLE)hSCManager;
+    if (hManager->Handle.Tag != MANAGER_TAG)
+    {
+        DPRINT1("Invalid manager handle!\n");
+        return ERROR_INVALID_HANDLE;
+    }
+
+    /* Check access rights */
+    if (!RtlAreAllAccessesGranted(hManager->Handle.DesiredAccess,
+                                  SC_MANAGER_ENUMERATE_SERVICE))
+    {
+        DPRINT1("Insufficient access rights! 0x%lx\n",
+                hManager->Handle.DesiredAccess);
+        return ERROR_ACCESS_DENIED;
+    }
+
+    *pcbBytesNeeded = 0;
+    *lpServicesReturned = 0;
+
+    dwLastResumeCount = *lpResumeHandle;
+
+    /* Lock the service list shared */
+
+    lpService = ScmGetServiceEntryByResumeCount(dwLastResumeCount);
+    if (lpService == NULL)
+    {
+        dwError = ERROR_SUCCESS;
+        goto Done;
+    }
+
+    dwRequiredSize = 0;
+    dwServiceCount = 0;
+
+    for (ServiceEntry = &lpService->ServiceListEntry;
+         ServiceEntry != &ServiceListHead;
+         ServiceEntry = ServiceEntry->Flink)
+    {
+        CurrentService = CONTAINING_RECORD(ServiceEntry,
+                                           SERVICE,
+                                           ServiceListEntry);
+
+        if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
+            continue;
+
+        dwState = SERVICE_ACTIVE;
+        if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
+            dwState = SERVICE_INACTIVE;
+
+        if ((dwState & dwServiceState) == 0)
+            continue;
+
+        if (pszGroupName)
+        {
+            if (_wcsicmp(pszGroupName, CurrentService->lpServiceGroup))
+                continue;
+        }
+
+        dwSize = sizeof(ENUM_SERVICE_STATUS_PROCESSW) +
+                 ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
+                 ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
+
+        if (dwRequiredSize + dwSize <= dwBufSize)
+        {
+            DPRINT("Service name: %S  fit\n", CurrentService->lpServiceName);
+            dwRequiredSize += dwSize;
+            dwServiceCount++;
+            dwLastResumeCount = CurrentService->dwResumeCount;
+        }
+        else
+        {
+            DPRINT("Service name: %S  no fit\n", CurrentService->lpServiceName);
+            break;
+        }
+
+    }
+
+    DPRINT("dwRequiredSize: %lu\n", dwRequiredSize);
+    DPRINT("dwServiceCount: %lu\n", dwServiceCount);
+
+    for (;
+         ServiceEntry != &ServiceListHead;
+         ServiceEntry = ServiceEntry->Flink)
+    {
+        CurrentService = CONTAINING_RECORD(ServiceEntry,
+                                           SERVICE,
+                                           ServiceListEntry);
+
+        if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
+            continue;
+
+        dwState = SERVICE_ACTIVE;
+        if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
+            dwState = SERVICE_INACTIVE;
+
+        if ((dwState & dwServiceState) == 0)
+            continue;
+
+        if (pszGroupName)
+        {
+            if (_wcsicmp(pszGroupName, CurrentService->lpServiceGroup))
+                continue;
+        }
+
+        dwRequiredSize += (sizeof(ENUM_SERVICE_STATUS_PROCESSW) +
+                           ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
+                           ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR)));
+
+        dwError = ERROR_MORE_DATA;
+    }
+
+    DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize);
+
+    *lpResumeHandle = dwLastResumeCount;
+    *lpServicesReturned = dwServiceCount;
+    *pcbBytesNeeded = dwRequiredSize;
+
+    lpStatusPtr = (LPENUM_SERVICE_STATUS_PROCESSW)lpServices;
+    lpStringPtr = (LPWSTR)((ULONG_PTR)lpServices +
+                           dwServiceCount * sizeof(ENUM_SERVICE_STATUS_PROCESSW));
+
+    dwRequiredSize = 0;
+    for (ServiceEntry = &lpService->ServiceListEntry;
+         ServiceEntry != &ServiceListHead;
+         ServiceEntry = ServiceEntry->Flink)
+    {
+        CurrentService = CONTAINING_RECORD(ServiceEntry,
+                                           SERVICE,
+                                           ServiceListEntry);
+
+        if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
+            continue;
+
+        dwState = SERVICE_ACTIVE;
+        if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
+            dwState = SERVICE_INACTIVE;
+
+        if ((dwState & dwServiceState) == 0)
+            continue;
+
+        if (pszGroupName)
+        {
+            if (_wcsicmp(pszGroupName, CurrentService->lpServiceGroup))
+                continue;
+        }
+
+        dwSize = sizeof(ENUM_SERVICE_STATUS_PROCESSW) +
+                 ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
+                 ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
+
+        if (dwRequiredSize + dwSize <= dwBufSize)
+        {
+            /* Copy the service name */
+            wcscpy(lpStringPtr,
+                   CurrentService->lpServiceName);
+            lpStatusPtr->lpServiceName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpServices);
+            lpStringPtr += (wcslen(CurrentService->lpServiceName) + 1);
+
+            /* Copy the display name */
+            wcscpy(lpStringPtr,
+                   CurrentService->lpDisplayName);
+            lpStatusPtr->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpServices);
+            lpStringPtr += (wcslen(CurrentService->lpDisplayName) + 1);
+
+            /* Copy the status information */
+            memcpy(&lpStatusPtr->ServiceStatusProcess,
+                   &CurrentService->Status,
+                   sizeof(SERVICE_STATUS));
+            lpStatusPtr->ServiceStatusProcess.dwProcessId = CurrentService->ProcessId; /* FIXME */
+            lpStatusPtr->ServiceStatusProcess.dwServiceFlags = 0; /* FIXME */
+
+            lpStatusPtr++;
+            dwRequiredSize += dwSize;
+        }
+        else
+        {
+            break;
+        }
+
+    }
+
+Done:;
+    /* Unlock the service list */
+
+    DPRINT("ScmrEnumServicesStatusExW() done (Error %lu)\n", dwError);
+
+    return dwError;
+}
+
+
 /* Function 43 */
 /* ScmrSendTSMessage */