Author: ekohl Date: Sat Aug 20 19:08:21 2011 New Revision: 53344
URL: http://svn.reactos.org/svn/reactos?rev=53344&view=rev Log: [ADVAPI32] QueryServiceConfig2A/W: Handle small or null buffer properly.
Modified: trunk/reactos/dll/win32/advapi32/service/scm.c
Modified: trunk/reactos/dll/win32/advapi32/service/scm.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/advapi32/service/... ============================================================================== --- trunk/reactos/dll/win32/advapi32/service/scm.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/advapi32/service/scm.c [iso-8859-1] Sat Aug 20 19:08:21 2011 @@ -2076,23 +2076,43 @@ DWORD cbBufSize, LPDWORD pcbBytesNeeded) { + SERVICE_DESCRIPTIONA ServiceDescription; + SERVICE_FAILURE_ACTIONSA ServiceFailureActions; + LPBYTE lpTempBuffer; + BOOL bUseTempBuffer = FALSE; + DWORD dwBufferSize; DWORD dwError;
TRACE("QueryServiceConfig2A(hService %p, dwInfoLevel %lu, lpBuffer %p, cbBufSize %lu, pcbBytesNeeded %p)\n", hService, dwInfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
- if (dwInfoLevel != SERVICE_CONFIG_DESCRIPTION && - dwInfoLevel != SERVICE_CONFIG_FAILURE_ACTIONS) - { - SetLastError(ERROR_INVALID_LEVEL); - return FALSE; - } - - if ((lpBuffer == NULL && cbBufSize != 0) || - pcbBytesNeeded == NULL) - { - SetLastError(ERROR_INVALID_ADDRESS); - return FALSE; + lpTempBuffer = lpBuffer; + dwBufferSize = cbBufSize; + + switch (dwInfoLevel) + { + case SERVICE_CONFIG_DESCRIPTION: + if ((lpBuffer == NULL) || (cbBufSize < sizeof(SERVICE_DESCRIPTIONA))) + { + lpTempBuffer = (LPBYTE)&ServiceDescription; + dwBufferSize = sizeof(SERVICE_DESCRIPTIONA); + bUseTempBuffer = TRUE; + } + break; + + case SERVICE_CONFIG_FAILURE_ACTIONS: + if ((lpBuffer == NULL) || (cbBufSize < sizeof(SERVICE_FAILURE_ACTIONSA))) + { + lpTempBuffer = (LPBYTE)&ServiceFailureActions; + dwBufferSize = sizeof(SERVICE_FAILURE_ACTIONSA); + bUseTempBuffer = TRUE; + } + break; + + default: + WARN("Unknown info level 0x%lx\n", dwInfoLevel); + SetLastError(ERROR_INVALID_LEVEL); + return FALSE; }
RpcTryExcept @@ -2100,8 +2120,8 @@ /* Call to services.exe using RPC */ dwError = RQueryServiceConfig2A((SC_RPC_HANDLE)hService, dwInfoLevel, - lpBuffer, - cbBufSize, + lpTempBuffer, + dwBufferSize, pcbBytesNeeded); } RpcExcept(EXCEPTION_EXECUTE_HANDLER) @@ -2114,6 +2134,13 @@ { TRACE("RQueryServiceConfig2A() failed (Error %lu)\n", dwError); SetLastError(dwError); + return FALSE; + } + + if (bUseTempBuffer == TRUE) + { + TRACE("RQueryServiceConfig2A() returns ERROR_INSUFFICIENT_BUFFER\n"); + SetLastError(ERROR_INSUFFICIENT_BUFFER); return FALSE; }
@@ -2121,7 +2148,7 @@ { case SERVICE_CONFIG_DESCRIPTION: { - LPSERVICE_DESCRIPTIONA lpPtr = (LPSERVICE_DESCRIPTIONA)lpBuffer; + LPSERVICE_DESCRIPTIONA lpPtr = (LPSERVICE_DESCRIPTIONA)lpTempBuffer;
if (lpPtr->lpDescription != NULL) lpPtr->lpDescription = @@ -2131,7 +2158,7 @@
case SERVICE_CONFIG_FAILURE_ACTIONS: { - LPSERVICE_FAILURE_ACTIONSA lpPtr = (LPSERVICE_FAILURE_ACTIONSA)lpBuffer; + LPSERVICE_FAILURE_ACTIONSA lpPtr = (LPSERVICE_FAILURE_ACTIONSA)lpTempBuffer;
if (lpPtr->lpRebootMsg != NULL) lpPtr->lpRebootMsg = @@ -2146,11 +2173,6 @@ (SC_ACTION*)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpsaActions); } break; - - default: - ERR("Unknown info level 0x%lx\n", dwInfoLevel); - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; }
TRACE("QueryServiceConfig2A() done\n"); @@ -2171,23 +2193,43 @@ DWORD cbBufSize, LPDWORD pcbBytesNeeded) { + SERVICE_DESCRIPTIONW ServiceDescription; + SERVICE_FAILURE_ACTIONSW ServiceFailureActions; + LPBYTE lpTempBuffer; + BOOL bUseTempBuffer = FALSE; + DWORD dwBufferSize; DWORD dwError;
TRACE("QueryServiceConfig2W(%p, %lu, %p, %lu, %p)\n", hService, dwInfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
- if (dwInfoLevel != SERVICE_CONFIG_DESCRIPTION && - dwInfoLevel != SERVICE_CONFIG_FAILURE_ACTIONS) - { - SetLastError(ERROR_INVALID_LEVEL); - return FALSE; - } - - if ((lpBuffer == NULL && cbBufSize != 0) || - pcbBytesNeeded == NULL) - { - SetLastError(ERROR_INVALID_ADDRESS); - return FALSE; + lpTempBuffer = lpBuffer; + dwBufferSize = cbBufSize; + + switch (dwInfoLevel) + { + case SERVICE_CONFIG_DESCRIPTION: + if ((lpBuffer == NULL) || (cbBufSize < sizeof(SERVICE_DESCRIPTIONW))) + { + lpTempBuffer = (LPBYTE)&ServiceDescription; + dwBufferSize = sizeof(SERVICE_DESCRIPTIONW); + bUseTempBuffer = TRUE; + } + break; + + case SERVICE_CONFIG_FAILURE_ACTIONS: + if ((lpBuffer == NULL) || (cbBufSize < sizeof(SERVICE_FAILURE_ACTIONSW))) + { + lpTempBuffer = (LPBYTE)&ServiceFailureActions; + dwBufferSize = sizeof(SERVICE_FAILURE_ACTIONSW); + bUseTempBuffer = TRUE; + } + break; + + default: + WARN("Unknown info level 0x%lx\n", dwInfoLevel); + SetLastError(ERROR_INVALID_LEVEL); + return FALSE; }
RpcTryExcept @@ -2195,8 +2237,8 @@ /* Call to services.exe using RPC */ dwError = RQueryServiceConfig2W((SC_RPC_HANDLE)hService, dwInfoLevel, - lpBuffer, - cbBufSize, + lpTempBuffer, + dwBufferSize, pcbBytesNeeded); } RpcExcept(EXCEPTION_EXECUTE_HANDLER) @@ -2209,6 +2251,13 @@ { TRACE("RQueryServiceConfig2W() failed (Error %lu)\n", dwError); SetLastError(dwError); + return FALSE; + } + + if (bUseTempBuffer == TRUE) + { + TRACE("RQueryServiceConfig2W() returns ERROR_INSUFFICIENT_BUFFER\n"); + SetLastError(ERROR_INSUFFICIENT_BUFFER); return FALSE; }
@@ -2216,7 +2265,7 @@ { case SERVICE_CONFIG_DESCRIPTION: { - LPSERVICE_DESCRIPTIONW lpPtr = (LPSERVICE_DESCRIPTIONW)lpBuffer; + LPSERVICE_DESCRIPTIONW lpPtr = (LPSERVICE_DESCRIPTIONW)lpTempBuffer;
if (lpPtr->lpDescription != NULL) lpPtr->lpDescription = @@ -2226,7 +2275,7 @@
case SERVICE_CONFIG_FAILURE_ACTIONS: { - LPSERVICE_FAILURE_ACTIONSW lpPtr = (LPSERVICE_FAILURE_ACTIONSW)lpBuffer; + LPSERVICE_FAILURE_ACTIONSW lpPtr = (LPSERVICE_FAILURE_ACTIONSW)lpTempBuffer;
if (lpPtr->lpRebootMsg != NULL) lpPtr->lpRebootMsg = @@ -2241,11 +2290,6 @@ (SC_ACTION*)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpsaActions); } break; - - default: - WARN("Unknown info level 0x%lx\n", dwInfoLevel); - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; }
TRACE("QueryServiceConfig2W() done\n");