[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
This commit is contained in:
Eric Kohl 2011-08-13 10:53:15 +00:00
parent 86f6c946e7
commit 33e3cab77d

View file

@ -1150,7 +1150,9 @@ EnumServicesStatusExA(SC_HANDLE hSCManager,
LPDWORD lpResumeHandle, LPDWORD lpResumeHandle,
LPCSTR pszGroupName) LPCSTR pszGroupName)
{ {
ENUM_SERVICE_STATUS_PROCESSA ServiceStatus;
LPENUM_SERVICE_STATUS_PROCESSA lpStatusPtr; LPENUM_SERVICE_STATUS_PROCESSA lpStatusPtr;
DWORD dwBufferSize;
DWORD dwError; DWORD dwError;
DWORD dwCount; DWORD dwCount;
@ -1168,14 +1170,26 @@ EnumServicesStatusExA(SC_HANDLE hSCManager,
return FALSE; 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 RpcTryExcept
{ {
dwError = REnumServicesStatusExA((SC_RPC_HANDLE)hSCManager, dwError = REnumServicesStatusExA((SC_RPC_HANDLE)hSCManager,
InfoLevel, InfoLevel,
dwServiceType, dwServiceType,
dwServiceState, dwServiceState,
(LPBYTE)lpServices, (LPBYTE)lpStatusPtr,
cbBufSize, dwBufferSize,
pcbBytesNeeded, pcbBytesNeeded,
lpServicesReturned, lpServicesReturned,
lpResumeHandle, lpResumeHandle,
@ -1189,18 +1203,20 @@ EnumServicesStatusExA(SC_HANDLE hSCManager,
if (dwError == ERROR_SUCCESS || dwError == ERROR_MORE_DATA) if (dwError == ERROR_SUCCESS || dwError == ERROR_MORE_DATA)
{ {
lpStatusPtr = (LPENUM_SERVICE_STATUS_PROCESSA)lpServices; if (InfoLevel == SC_ENUM_PROCESS_INFO)
for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++)
{ {
if (lpStatusPtr->lpServiceName) for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++)
lpStatusPtr->lpServiceName = {
(LPSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName); if (lpStatusPtr->lpServiceName)
lpStatusPtr->lpServiceName =
(LPSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName);
if (lpStatusPtr->lpDisplayName) if (lpStatusPtr->lpDisplayName)
lpStatusPtr->lpDisplayName = lpStatusPtr->lpDisplayName =
(LPSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName); (LPSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName);
lpStatusPtr++; lpStatusPtr++;
}
} }
} }
@ -1234,20 +1250,40 @@ EnumServicesStatusExW(SC_HANDLE hSCManager,
LPDWORD lpResumeHandle, LPDWORD lpResumeHandle,
LPCWSTR pszGroupName) LPCWSTR pszGroupName)
{ {
ENUM_SERVICE_STATUS_PROCESSW ServiceStatus;
LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr; LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr;
DWORD dwBufferSize;
DWORD dwError; DWORD dwError;
DWORD dwCount; DWORD dwCount;
TRACE("EnumServicesStatusExW() called\n"); 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 RpcTryExcept
{ {
dwError = REnumServicesStatusExW((SC_RPC_HANDLE)hSCManager, dwError = REnumServicesStatusExW((SC_RPC_HANDLE)hSCManager,
InfoLevel, InfoLevel,
dwServiceType, dwServiceType,
dwServiceState, dwServiceState,
(LPBYTE)lpServices, (LPBYTE)lpStatusPtr,
cbBufSize, dwBufferSize,
pcbBytesNeeded, pcbBytesNeeded,
lpServicesReturned, lpServicesReturned,
lpResumeHandle, lpResumeHandle,
@ -1261,18 +1297,20 @@ EnumServicesStatusExW(SC_HANDLE hSCManager,
if (dwError == ERROR_SUCCESS || dwError == ERROR_MORE_DATA) if (dwError == ERROR_SUCCESS || dwError == ERROR_MORE_DATA)
{ {
lpStatusPtr = (LPENUM_SERVICE_STATUS_PROCESSW)lpServices; if (InfoLevel == SC_ENUM_PROCESS_INFO)
for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++)
{ {
if (lpStatusPtr->lpServiceName) for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++)
lpStatusPtr->lpServiceName = {
(LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName); if (lpStatusPtr->lpServiceName)
lpStatusPtr->lpServiceName =
(LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName);
if (lpStatusPtr->lpDisplayName) if (lpStatusPtr->lpDisplayName)
lpStatusPtr->lpDisplayName = lpStatusPtr->lpDisplayName =
(LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName); (LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName);
lpStatusPtr++; lpStatusPtr++;
}
} }
} }