[ros-diffs] [mjmartin] 36724: - Implement REnumServicesStatusA - REnumServicesStatusW: Dont try to access lpResumeHandle if it is NULL

mjmartin at svn.reactos.org mjmartin at svn.reactos.org
Sun Oct 12 02:02:17 CEST 2008


Author: mjmartin
Date: Sat Oct 11 19:02:17 2008
New Revision: 36724

URL: http://svn.reactos.org/svn/reactos?rev=36724&view=rev
Log:
- Implement REnumServicesStatusA
- REnumServicesStatusW: Dont try to access lpResumeHandle if it is NULL

Modified:
    trunk/reactos/base/system/services/rpcserver.c

Modified: trunk/reactos/base/system/services/rpcserver.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/system/services/rpcserver.c?rev=36724&r1=36723&r2=36724&view=diff
==============================================================================
--- trunk/reactos/base/system/services/rpcserver.c [iso-8859-1] (original)
+++ trunk/reactos/base/system/services/rpcserver.c [iso-8859-1] Sat Oct 11 19:02:17 2008
@@ -2200,7 +2200,7 @@
     DWORD dwRequiredSize;
     DWORD dwServiceCount;
     DWORD dwSize;
-    DWORD dwLastResumeCount;
+    DWORD dwLastResumeCount = 0;
     LPENUM_SERVICE_STATUSW lpStatusPtr;
     LPWSTR lpStringPtr;
 
@@ -2214,6 +2214,21 @@
     {
         DPRINT1("Invalid manager handle!\n");
         return ERROR_INVALID_HANDLE;
+    }
+
+    *pcbBytesNeeded = 0;
+    *lpServicesReturned = 0;
+
+    if ((dwServiceType!=SERVICE_DRIVER) && (dwServiceType!=SERVICE_WIN32))
+    {
+        DPRINT("Not a valid Service Type!\n");
+        return ERROR_INVALID_PARAMETER;
+    }
+
+    if ((dwServiceState<SERVICE_ACTIVE) || (dwServiceState>SERVICE_STATE_ALL))
+    {
+        DPRINT("Not a valid Service State!\n");
+        return ERROR_INVALID_PARAMETER;
     }
 
     /* Check access rights */
@@ -2225,10 +2240,7 @@
         return ERROR_ACCESS_DENIED;
     }
 
-    *pcbBytesNeeded = 0;
-    *lpServicesReturned = 0;
-
-    dwLastResumeCount = *lpResumeHandle;
+    if (lpResumeHandle) dwLastResumeCount = *lpResumeHandle;
 
     /* FIXME: Lock the service list shared */
 
@@ -2306,7 +2318,7 @@
 
     DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize);
 
-    *lpResumeHandle = dwLastResumeCount;
+    if (lpResumeHandle) *lpResumeHandle = dwLastResumeCount;
     *lpServicesReturned = dwServiceCount;
     *pcbBytesNeeded = dwRequiredSize;
 
@@ -3357,8 +3369,206 @@
     LPBOUNDED_DWORD_256K lpServicesReturned,
     LPBOUNDED_DWORD_256K lpResumeHandle)
 {
-    UNIMPLEMENTED;
-    return ERROR_CALL_NOT_IMPLEMENTED;
+    PMANAGER_HANDLE hManager;
+    PSERVICE lpService;
+    DWORD dwError = ERROR_SUCCESS;
+    PLIST_ENTRY ServiceEntry;
+    PSERVICE CurrentService;
+    DWORD dwState;
+    DWORD dwRequiredSize;
+    DWORD dwServiceCount;
+    DWORD dwSize;
+    DWORD dwLastResumeCount = 0;
+    LPENUM_SERVICE_STATUSA lpStatusPtr;
+    LPSTR lpStringPtr;
+
+    DPRINT("REnumServicesStatusA() called\n");
+
+    if (ScmShutdown)
+        return ERROR_SHUTDOWN_IN_PROGRESS;
+
+    hManager = (PMANAGER_HANDLE)hSCManager;
+    if (!hManager || hManager->Handle.Tag != MANAGER_TAG)
+    {
+        DPRINT1("Invalid manager handle!\n");
+        return ERROR_INVALID_HANDLE;
+    }
+
+    *pcbBytesNeeded = 0;
+    *lpServicesReturned = 0;
+
+    if ((dwServiceType!=SERVICE_DRIVER) && (dwServiceType!=SERVICE_WIN32))
+    {
+        DPRINT1("Not a valid Service Type!\n");
+        return ERROR_INVALID_PARAMETER;
+    }
+
+    if ((dwServiceState<SERVICE_ACTIVE) || (dwServiceState>SERVICE_STATE_ALL))
+    {
+        DPRINT1("Not a valid Service State!\n");
+        return ERROR_INVALID_PARAMETER;
+    }
+
+    /* 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;
+    }
+
+    if (lpResumeHandle) dwLastResumeCount = *lpResumeHandle;
+
+    /* FIXME: 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;
+
+        dwSize = sizeof(ENUM_SERVICE_STATUSA) +
+                 ((wcslen(CurrentService->lpServiceName) + 1)) +
+                 ((wcslen(CurrentService->lpDisplayName) + 1));
+
+        if (dwRequiredSize + dwSize > dwBufSize)
+        {
+            DPRINT("Service name: %S  no fit\n", CurrentService->lpServiceName);
+            break;
+        }
+
+        DPRINT("Service name: %S  fit\n", CurrentService->lpServiceName);
+        dwRequiredSize += dwSize;
+        dwServiceCount++;
+        dwLastResumeCount = CurrentService->dwResumeCount;
+    }
+
+    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;
+
+        dwRequiredSize += (sizeof(ENUM_SERVICE_STATUSA) +
+                           ((wcslen(CurrentService->lpServiceName) + 1)) +
+                           ((wcslen(CurrentService->lpDisplayName) + 1)));
+
+        dwError = ERROR_MORE_DATA;
+    }
+
+    DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize);
+
+    if (lpResumeHandle) *lpResumeHandle = dwLastResumeCount;
+    *lpServicesReturned = dwServiceCount;
+    *pcbBytesNeeded = dwRequiredSize;
+
+    lpStatusPtr = (LPENUM_SERVICE_STATUSA)lpBuffer;
+    lpStringPtr = (LPSTR)((ULONG_PTR)lpBuffer +
+                           dwServiceCount * sizeof(ENUM_SERVICE_STATUSA));
+
+    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;
+
+        dwSize = sizeof(ENUM_SERVICE_STATUSA) +
+                 ((wcslen(CurrentService->lpServiceName) + 1)) +
+                 ((wcslen(CurrentService->lpDisplayName) + 1));
+
+        if (dwRequiredSize + dwSize > dwBufSize)
+            break;
+
+        /* Copy the service name */
+        WideCharToMultiByte(CP_ACP,
+                            0,
+                            CurrentService->lpServiceName,
+                            -1,
+                            lpStringPtr,
+                            wcslen(CurrentService->lpServiceName),
+                            0,
+                            0);
+        lpStatusPtr->lpServiceName = (LPSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpBuffer);
+        lpStringPtr += (wcslen(CurrentService->lpServiceName) + 1);
+
+        /* Copy the display name */
+        WideCharToMultiByte(CP_ACP,
+                            0,
+                            CurrentService->lpDisplayName,
+                            -1,
+                            lpStringPtr,
+                            wcslen(CurrentService->lpDisplayName),
+                            0,
+                            0);
+        lpStatusPtr->lpDisplayName = (LPSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpBuffer);
+        lpStringPtr += (wcslen(CurrentService->lpDisplayName) + 1);
+
+        /* Copy the status information */
+        memcpy(&lpStatusPtr->ServiceStatus,
+               &CurrentService->Status,
+               sizeof(SERVICE_STATUS));
+
+        lpStatusPtr++;
+        dwRequiredSize += dwSize;
+    }
+
+Done:;
+    /* FIXME: Unlock the service list */
+
+    DPRINT("REnumServicesStatusA() done (Error %lu)\n", dwError);
+
+    return dwError;
 }
 
 



More information about the Ros-diffs mailing list