-Implement EnumServicesStatusExW.
authorEric Kohl <eric.kohl@reactos.org>
Mon, 26 Dec 2005 15:06:46 +0000 (15:06 +0000)
committerEric Kohl <eric.kohl@reactos.org>
Mon, 26 Dec 2005 15:06:46 +0000 (15:06 +0000)
-Add missing [unique] Attributes to svcctrl.idl.

svn path=/trunk/; revision=20335

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

index 239fe64..ed6e758 100644 (file)
@@ -12,6 +12,7 @@
 #define SC_LOCK unsigned int\r
 #define SERVICE_STATUS_HANDLE unsigned long\r
 #define SC_STATUS_TYPE unsigned long\r
+#define SC_ENUM_TYPE unsigned long\r
 #define LPSTR char*\r
 #define LPCSTR char*\r
 #define LPWSTR wchar_t*\r
@@ -138,7 +139,7 @@ cpp_quote("#endif")
   DWORD ScmrEnumDependentServicesW([in] handle_t BindingHandle,\r
                                    [in] SC_HANDLE hService,\r
                                    [in] DWORD dwServiceState,\r
-                                   [out, size_is(cbBufSize)] LPBYTE lpServices,\r
+                                   [out, unique, size_is(cbBufSize)] LPBYTE lpServices,\r
                                    [in] DWORD cbBufSize,\r
                                    [out] LPDWORD pcbBytesNeeded,\r
                                    [out] LPDWORD lpServicesReturned);\r
@@ -148,7 +149,7 @@ cpp_quote("#endif")
                                 [in] SC_HANDLE hSCManager,\r
                                 [in] DWORD dwServiceType,\r
                                 [in] DWORD dwServiceState,\r
-                                [out, size_is(dwBufSize)] LPBYTE lpServices,\r
+                                [out, unique, size_is(dwBufSize)] LPBYTE lpServices,\r
                                 [in] DWORD dwBufSize,\r
                                 [out] LPDWORD pcbBytesNeeded,\r
                                 [out] LPDWORD lpServicesReturned,\r
@@ -178,7 +179,7 @@ cpp_quote("#endif")
   /* Function 18 */\r
   DWORD ScmrQueryServiceLockStatusW([in] handle_t BindingHandle,\r
                                     [in] SC_HANDLE hSCManager,\r
-                                    [out, size_is(cbBufSize), unique] LPBYTE lpLockStatus,\r
+                                    [out, unique, size_is(cbBufSize)] LPBYTE lpLockStatus,\r
                                     [in] DWORD cbBufSize,\r
                                     [out] LPDWORD pcbBytesNeeded);\r
 \r
@@ -249,7 +250,7 @@ cpp_quote("#endif")
   DWORD ScmrEnumDependentServicesA([in] handle_t BindingHandle,\r
                                    [in] SC_HANDLE hService,\r
                                    [in] DWORD dwServiceState,\r
-                                   [out, size_is(cbBufSize)] LPBYTE lpServices,\r
+                                   [out, unique, size_is(cbBufSize)] LPBYTE lpServices,\r
                                    [in] DWORD cbBufSize,\r
                                    [out] LPDWORD pcbBytesNeeded,\r
                                    [out] LPDWORD lpServicesReturned);\r
@@ -259,7 +260,7 @@ cpp_quote("#endif")
                                 [in] SC_HANDLE hSCManager,\r
                                 [in] DWORD dwServiceType,\r
                                 [in] DWORD dwServiceState,\r
-                                [out, size_is(dwBufSize)] LPBYTE lpServices,\r
+                                [out, unique, size_is(dwBufSize)] LPBYTE lpServices,\r
                                 [in] DWORD dwBufSize,\r
                                 [out] LPDWORD pcbBytesNeeded,\r
                                 [out] LPDWORD lpServicesReturned,\r
@@ -289,7 +290,7 @@ cpp_quote("#endif")
   /* Function 30 */\r
 //  DWORD ScmrQueryServiceLockStatusA([in] handle_t BindingHandle,\r
 //                                    [in] SC_HANDLE hSCManager,\r
-//                                    [out, size_is(cbBufSize), unique] LPBYTE lpLockStatus,\r
+//                                    [out, unique, size_is(cbBufSize)] LPBYTE lpLockStatus,\r
 //                                    [in] DWORD cbBufSize,\r
 //                                    [out] LPDWORD pcbBytesNeeded);\r
 \r
@@ -297,20 +298,20 @@ cpp_quote("#endif")
 //  DWORD ScmrStartServiceA([in] handle_t BindingHandle,\r
 //                          [in] SC_HANDLE hService,\r
 //                          [in] DWORD dwNumServiceArgs,\r
-//                          [in, string, size_is(dwNumServiceArgs, ), unique] LPSTR *lpServiceArgVectors);\r
+//                          [in, unique, string, size_is(dwNumServiceArgs, )] LPSTR *lpServiceArgVectors);\r
 \r
   /* Function 32 */\r
   DWORD ScmrGetServiceDisplayNameA([in] handle_t BindingHandle,\r
                                    [in] SC_HANDLE hSCManager,\r
                                    [in, string, ref] LPCSTR lpServiceName,\r
-                                   [out, size_is(*lpcchBuffer), unique] LPSTR lpDisplayName,\r
+                                   [out, unique, size_is(*lpcchBuffer)] LPSTR lpDisplayName,\r
                                    [in, out, ref] LPDWORD lpcchBuffer);\r
 \r
   /* Function 33 */\r
   DWORD ScmrGetServiceKeyNameA([in] handle_t BindingHandle,\r
                                [in] SC_HANDLE hSCManager,\r
                                [in, string, ref] LPCSTR lpDisplayName,\r
-                               [out, size_is(*lpcchBuffer), unique] LPSTR lpServiceName,\r
+                               [out, unique, size_is(*lpcchBuffer)] LPSTR lpServiceName,\r
                                [in, out, ref] LPDWORD lpcchBuffer);\r
 \r
   /* Function 35 */\r
@@ -335,15 +336,35 @@ cpp_quote("#endif")
   DWORD ScmrQueryServiceStatusEx([in] handle_t BindingHandle,\r
                                  [in] SC_HANDLE hService,\r
                                  [in] SC_STATUS_TYPE InfoLevel,\r
-                                 [out, size_is(cbBufSize)] LPBYTE lpBuffer,\r
+                                 [out, unique, size_is(cbBufSize)] LPBYTE lpBuffer,\r
                                  [in] DWORD cbBufSize,\r
                                  [out] LPDWORD pcbBytesNeeded);\r
 \r
   /* Function 41 */\r
-  /* ScmrEnumServicesStatusExA */\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
-  /* ScmrEnumServicesStatusExW */\r
+  DWORD ScmrEnumServicesStatusExW([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] LPCWSTR pszGroupName);\r
 \r
   /* Function 43 */\r
   /* ScmrSendTSMessage */\r
index 20befe2..e148407 100644 (file)
@@ -708,24 +708,64 @@ EnumServicesStatusExA(SC_HANDLE  hSCManager,
 /**********************************************************************
  *  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 @@ QueryServiceStatusEx(SC_HANDLE hService,
                                        pcbBytesNeeded);
     if (dwError != ERROR_SUCCESS)
     {
-        DPRINT1("ScmrQueryServiceStatusEx() failed (Error %lu)\n", dwError);
+        DPRINT("ScmrQueryServiceStatusEx() failed (Error %lu)\n", dwError);
         SetLastError(dwError);
         return FALSE;
     }
index bae5348..58164ad 100644 (file)
@@ -1393,9 +1393,9 @@ ScmrEnumServicesStatusW(handle_t BindingHandle,
     *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,7 +2138,227 @@ ScmrQueryServiceStatusEx(handle_t BindingHandle,
 
 
 /* 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 */