From 33e3cab77dfe65df0240a78cfb37a6c4e3b391e7 Mon Sep 17 00:00:00 2001 From: Eric Kohl Date: Sat, 13 Aug 2011 10:53:15 +0000 Subject: [PATCH] [ADVAPI32] Fix EnumServicesStatusEx[A/W]: - If lpServices is NULL or cbBufSize is less than sizeof(ENUM_SERVICE_STATUS_PROCESS) pass a pointer to an internal status buffer to REnumServicesStatusExA/W. Adding 'in' and 'unique' attributes in the idl file is NOT an option because this is not compatible with Windows. - Check the InfoLevel. svn path=/trunk/; revision=53201 --- reactos/dll/win32/advapi32/service/scm.c | 82 +++++++++++++++++------- 1 file changed, 60 insertions(+), 22 deletions(-) diff --git a/reactos/dll/win32/advapi32/service/scm.c b/reactos/dll/win32/advapi32/service/scm.c index 2b2f9a32bf8..3ce9907ad0f 100644 --- a/reactos/dll/win32/advapi32/service/scm.c +++ b/reactos/dll/win32/advapi32/service/scm.c @@ -1150,7 +1150,9 @@ EnumServicesStatusExA(SC_HANDLE hSCManager, LPDWORD lpResumeHandle, LPCSTR pszGroupName) { + ENUM_SERVICE_STATUS_PROCESSA ServiceStatus; LPENUM_SERVICE_STATUS_PROCESSA lpStatusPtr; + DWORD dwBufferSize; DWORD dwError; DWORD dwCount; @@ -1168,14 +1170,26 @@ EnumServicesStatusExA(SC_HANDLE hSCManager, return FALSE; } + if (lpServices == NULL || + cbBufSize < sizeof(ENUM_SERVICE_STATUS_PROCESSA)) + { + lpStatusPtr = &ServiceStatus; + dwBufferSize = sizeof(ENUM_SERVICE_STATUS_PROCESSA); + } + else + { + lpStatusPtr = (LPENUM_SERVICE_STATUS_PROCESSA)lpServices; + dwBufferSize = cbBufSize; + } + RpcTryExcept { dwError = REnumServicesStatusExA((SC_RPC_HANDLE)hSCManager, InfoLevel, dwServiceType, dwServiceState, - (LPBYTE)lpServices, - cbBufSize, + (LPBYTE)lpStatusPtr, + dwBufferSize, pcbBytesNeeded, lpServicesReturned, lpResumeHandle, @@ -1189,18 +1203,20 @@ EnumServicesStatusExA(SC_HANDLE hSCManager, if (dwError == ERROR_SUCCESS || dwError == ERROR_MORE_DATA) { - lpStatusPtr = (LPENUM_SERVICE_STATUS_PROCESSA)lpServices; - for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++) + if (InfoLevel == SC_ENUM_PROCESS_INFO) { - if (lpStatusPtr->lpServiceName) - lpStatusPtr->lpServiceName = - (LPSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName); + for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++) + { + if (lpStatusPtr->lpServiceName) + lpStatusPtr->lpServiceName = + (LPSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName); - if (lpStatusPtr->lpDisplayName) - lpStatusPtr->lpDisplayName = - (LPSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName); + if (lpStatusPtr->lpDisplayName) + lpStatusPtr->lpDisplayName = + (LPSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName); - lpStatusPtr++; + lpStatusPtr++; + } } } @@ -1234,20 +1250,40 @@ EnumServicesStatusExW(SC_HANDLE hSCManager, LPDWORD lpResumeHandle, LPCWSTR pszGroupName) { + ENUM_SERVICE_STATUS_PROCESSW ServiceStatus; LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr; + DWORD dwBufferSize; DWORD dwError; DWORD dwCount; TRACE("EnumServicesStatusExW() called\n"); + if (InfoLevel != SC_ENUM_PROCESS_INFO) + { + SetLastError(ERROR_INVALID_LEVEL); + return FALSE; + } + + if (lpServices == NULL || + cbBufSize < sizeof(ENUM_SERVICE_STATUS_PROCESSW)) + { + lpStatusPtr = &ServiceStatus; + dwBufferSize = sizeof(ENUM_SERVICE_STATUS_PROCESSW); + } + else + { + lpStatusPtr = (LPENUM_SERVICE_STATUS_PROCESSW)lpServices; + dwBufferSize = cbBufSize; + } + RpcTryExcept { dwError = REnumServicesStatusExW((SC_RPC_HANDLE)hSCManager, InfoLevel, dwServiceType, dwServiceState, - (LPBYTE)lpServices, - cbBufSize, + (LPBYTE)lpStatusPtr, + dwBufferSize, pcbBytesNeeded, lpServicesReturned, lpResumeHandle, @@ -1261,18 +1297,20 @@ EnumServicesStatusExW(SC_HANDLE hSCManager, if (dwError == ERROR_SUCCESS || dwError == ERROR_MORE_DATA) { - lpStatusPtr = (LPENUM_SERVICE_STATUS_PROCESSW)lpServices; - for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++) + if (InfoLevel == SC_ENUM_PROCESS_INFO) { - if (lpStatusPtr->lpServiceName) - lpStatusPtr->lpServiceName = - (LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName); + 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); + if (lpStatusPtr->lpDisplayName) + lpStatusPtr->lpDisplayName = + (LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName); - lpStatusPtr++; + lpStatusPtr++; + } } } -- 2.17.1