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/rpcser... ============================================================================== --- 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; }