Author: mjmartin Date: Sun Oct 12 08:10:05 2008 New Revision: 36732
URL: http://svn.reactos.org/svn/reactos?rev=36732&view=rev Log: - Implement REnumServicesStatusExA - REnumServicesStatusA/W: Fixed returned param values to match Windows - REnumServicesStatusExW: Dont try to access lpResumeIndex if it is NULL. Fixed returned param values to match windows.
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] Sun Oct 12 08:10:05 2008 @@ -2371,6 +2371,12 @@ dwRequiredSize += dwSize; }
+ if (dwError != ERROR_MORE_DATA) + { + *pcbBytesNeeded = 0; + if (lpResumeHandle) *lpResumeHandle = 0; + } + Done:; /* FIXME: Unlock the service list */
@@ -3451,8 +3457,8 @@ continue;
dwSize = sizeof(ENUM_SERVICE_STATUSA) + - ((wcslen(CurrentService->lpServiceName) + 1)) + - ((wcslen(CurrentService->lpDisplayName) + 1)); + wcslen(CurrentService->lpServiceName) + 1 + + wcslen(CurrentService->lpDisplayName) + 1;
if (dwRequiredSize + dwSize > dwBufSize) { @@ -3487,9 +3493,9 @@ if ((dwState & dwServiceState) == 0) continue;
- dwRequiredSize += (sizeof(ENUM_SERVICE_STATUSA) + - ((wcslen(CurrentService->lpServiceName) + 1)) + - ((wcslen(CurrentService->lpDisplayName) + 1))); + dwRequiredSize += sizeof(ENUM_SERVICE_STATUSA) + + wcslen(CurrentService->lpServiceName) + 1 + + wcslen(CurrentService->lpDisplayName) + 1;
dwError = ERROR_MORE_DATA; } @@ -3524,8 +3530,8 @@ continue;
dwSize = sizeof(ENUM_SERVICE_STATUSA) + - ((wcslen(CurrentService->lpServiceName) + 1)) + - ((wcslen(CurrentService->lpDisplayName) + 1)); + wcslen(CurrentService->lpServiceName) + 1 + + wcslen(CurrentService->lpDisplayName) + 1;
if (dwRequiredSize + dwSize > dwBufSize) break; @@ -3561,6 +3567,12 @@
lpStatusPtr++; dwRequiredSize += dwSize; + } + + if (dwError != ERROR_MORE_DATA) + { + *pcbBytesNeeded = 0; + if (lpResumeHandle) *lpResumeHandle = 0; }
Done:; @@ -4509,10 +4521,295 @@ LPBOUNDED_DWORD_256K lpResumeIndex, LPCSTR pszGroupName) { - UNIMPLEMENTED; + 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_STATUS_PROCESSA lpStatusPtr; + LPSTR lpStringPtr; + LPWSTR pszGroupNameW = NULL; + + DPRINT("REnumServicesStatusExA() 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 || hManager->Handle.Tag != MANAGER_TAG) + { + DPRINT1("Invalid manager handle!\n"); + return ERROR_INVALID_HANDLE; + } + *pcbBytesNeeded = 0; *lpServicesReturned = 0; - return ERROR_CALL_NOT_IMPLEMENTED; + + 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 (lpResumeIndex) dwLastResumeCount = *lpResumeIndex; + + /* FIXME: Lock the service list shared */ + + lpService = ScmGetServiceEntryByResumeCount(dwLastResumeCount); + if (lpService == NULL) + { + dwError = ERROR_SUCCESS; + goto Done; + } + + dwRequiredSize = 0; + dwServiceCount = 0; + + if (pszGroupName) + { + pszGroupNameW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (strlen(pszGroupName) + 1) * sizeof(WCHAR)); + if (!pszGroupNameW) + { + DPRINT1("Failed to allocate buffer!\n"); + return ERROR_NOT_ENOUGH_MEMORY; + } + MultiByteToWideChar(CP_ACP, + 0, + pszGroupName, + -1, + pszGroupNameW, + strlen(pszGroupName) + 1); + } + + 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 (pszGroupNameW) + { + if (*pszGroupNameW == 0) + { + if (CurrentService->lpGroup != NULL) + continue; + } + else + { + if ((CurrentService->lpGroup == NULL) || + _wcsicmp(pszGroupNameW, CurrentService->lpGroup->lpGroupName)) + continue; + } + } + + dwSize = sizeof(ENUM_SERVICE_STATUS_PROCESSW) + + (wcslen(CurrentService->lpServiceName) + 1) + + (wcslen(CurrentService->lpDisplayName) + 1); + + if (dwRequiredSize + dwSize <= cbBufSize) + { + 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 (pszGroupNameW) + { + if (*pszGroupNameW == 0) + { + if (CurrentService->lpGroup != NULL) + continue; + } + else + { + if ((CurrentService->lpGroup == NULL) || + _wcsicmp(pszGroupNameW, CurrentService->lpGroup->lpGroupName)) + continue; + } + } + + dwRequiredSize += (sizeof(ENUM_SERVICE_STATUS_PROCESSW) + + (wcslen(CurrentService->lpServiceName) + 1) + + (wcslen(CurrentService->lpDisplayName) + 1)); + + dwError = ERROR_MORE_DATA; + } + + DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize); + + if (lpResumeIndex) *lpResumeIndex = dwLastResumeCount; + *lpServicesReturned = dwServiceCount; + *pcbBytesNeeded = dwRequiredSize; + + /* If there was no services that matched */ + if (!dwServiceCount) + { + dwError = ERROR_SERVICE_DOES_NOT_EXIST; + goto Done; + } + + lpStatusPtr = (LPENUM_SERVICE_STATUS_PROCESSA)lpBuffer; + lpStringPtr = (LPSTR)((ULONG_PTR)lpBuffer + + dwServiceCount * sizeof(ENUM_SERVICE_STATUS_PROCESSA)); + + 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 (pszGroupNameW) + { + if (*pszGroupNameW == 0) + { + if (CurrentService->lpGroup != NULL) + continue; + } + else + { + if ((CurrentService->lpGroup == NULL) || + _wcsicmp(pszGroupNameW, CurrentService->lpGroup->lpGroupName)) + continue; + } + } + + dwSize = sizeof(ENUM_SERVICE_STATUS_PROCESSW) + + ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) + + ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR)); + + if (dwRequiredSize + dwSize <= cbBufSize) + { + /* 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->ServiceStatusProcess, + &CurrentService->Status, + sizeof(SERVICE_STATUS)); + lpStatusPtr->ServiceStatusProcess.dwProcessId = CurrentService->ProcessId; /* FIXME */ + lpStatusPtr->ServiceStatusProcess.dwServiceFlags = 0; /* FIXME */ + + lpStatusPtr++; + dwRequiredSize += dwSize; + } + else + { + break; + } + } + + if (dwError != ERROR_MORE_DATA) + { + *pcbBytesNeeded = 0; + if (lpResumeIndex) *lpResumeIndex = 0; + } + +Done:; + /* Unlock the service list */ + + if (pszGroupNameW) HeapFree(GetProcessHeap(),0,pszGroupNameW); + + DPRINT("REnumServicesStatusExA() done (Error %lu)\n", dwError); + + return dwError; }
@@ -4539,7 +4836,7 @@ DWORD dwRequiredSize; DWORD dwServiceCount; DWORD dwSize; - DWORD dwLastResumeCount; + DWORD dwLastResumeCount = 0; LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr; LPWSTR lpStringPtr;
@@ -4556,6 +4853,21 @@ { 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 */ @@ -4567,10 +4879,7 @@ return ERROR_ACCESS_DENIED; }
- *pcbBytesNeeded = 0; - *lpServicesReturned = 0; - - dwLastResumeCount = *lpResumeIndex; + if (lpResumeIndex) dwLastResumeCount = *lpResumeIndex;
/* Lock the service list shared */
@@ -4681,9 +4990,16 @@
DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize);
- *lpResumeIndex = dwLastResumeCount; + if (lpResumeIndex) *lpResumeIndex = dwLastResumeCount; *lpServicesReturned = dwServiceCount; *pcbBytesNeeded = dwRequiredSize; + + /* If there was no services that matched */ + if (!dwServiceCount) + { + dwError = ERROR_SERVICE_DOES_NOT_EXIST; + goto Done; + }
lpStatusPtr = (LPENUM_SERVICE_STATUS_PROCESSW)lpBuffer; lpStringPtr = (LPWSTR)((ULONG_PTR)lpBuffer + @@ -4755,7 +5071,12 @@ { break; } - + } + + if (dwError != ERROR_MORE_DATA) + { + *pcbBytesNeeded = 0; + if (lpResumeIndex) *lpResumeIndex = 0; }
Done:;