[ADVAPI32]

QueryServiceConfig2A/W: Handle small or null buffer properly.

svn path=/trunk/; revision=53344
This commit is contained in:
Eric Kohl 2011-08-20 19:08:21 +00:00
parent 954922d0cd
commit a02dd46b35

View file

@ -2076,23 +2076,43 @@ QueryServiceConfig2A(SC_HANDLE hService,
DWORD cbBufSize, DWORD cbBufSize,
LPDWORD pcbBytesNeeded) LPDWORD pcbBytesNeeded)
{ {
SERVICE_DESCRIPTIONA ServiceDescription;
SERVICE_FAILURE_ACTIONSA ServiceFailureActions;
LPBYTE lpTempBuffer;
BOOL bUseTempBuffer = FALSE;
DWORD dwBufferSize;
DWORD dwError; DWORD dwError;
TRACE("QueryServiceConfig2A(hService %p, dwInfoLevel %lu, lpBuffer %p, cbBufSize %lu, pcbBytesNeeded %p)\n", TRACE("QueryServiceConfig2A(hService %p, dwInfoLevel %lu, lpBuffer %p, cbBufSize %lu, pcbBytesNeeded %p)\n",
hService, dwInfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded); hService, dwInfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
if (dwInfoLevel != SERVICE_CONFIG_DESCRIPTION && lpTempBuffer = lpBuffer;
dwInfoLevel != SERVICE_CONFIG_FAILURE_ACTIONS) dwBufferSize = cbBufSize;
{
SetLastError(ERROR_INVALID_LEVEL);
return FALSE;
}
if ((lpBuffer == NULL && cbBufSize != 0) || switch (dwInfoLevel)
pcbBytesNeeded == NULL)
{ {
SetLastError(ERROR_INVALID_ADDRESS); case SERVICE_CONFIG_DESCRIPTION:
return FALSE; 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 RpcTryExcept
@ -2100,8 +2120,8 @@ QueryServiceConfig2A(SC_HANDLE hService,
/* Call to services.exe using RPC */ /* Call to services.exe using RPC */
dwError = RQueryServiceConfig2A((SC_RPC_HANDLE)hService, dwError = RQueryServiceConfig2A((SC_RPC_HANDLE)hService,
dwInfoLevel, dwInfoLevel,
lpBuffer, lpTempBuffer,
cbBufSize, dwBufferSize,
pcbBytesNeeded); pcbBytesNeeded);
} }
RpcExcept(EXCEPTION_EXECUTE_HANDLER) RpcExcept(EXCEPTION_EXECUTE_HANDLER)
@ -2117,11 +2137,18 @@ QueryServiceConfig2A(SC_HANDLE hService,
return FALSE; return FALSE;
} }
if (bUseTempBuffer == TRUE)
{
TRACE("RQueryServiceConfig2A() returns ERROR_INSUFFICIENT_BUFFER\n");
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return FALSE;
}
switch (dwInfoLevel) switch (dwInfoLevel)
{ {
case SERVICE_CONFIG_DESCRIPTION: case SERVICE_CONFIG_DESCRIPTION:
{ {
LPSERVICE_DESCRIPTIONA lpPtr = (LPSERVICE_DESCRIPTIONA)lpBuffer; LPSERVICE_DESCRIPTIONA lpPtr = (LPSERVICE_DESCRIPTIONA)lpTempBuffer;
if (lpPtr->lpDescription != NULL) if (lpPtr->lpDescription != NULL)
lpPtr->lpDescription = lpPtr->lpDescription =
@ -2131,7 +2158,7 @@ QueryServiceConfig2A(SC_HANDLE hService,
case SERVICE_CONFIG_FAILURE_ACTIONS: 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) if (lpPtr->lpRebootMsg != NULL)
lpPtr->lpRebootMsg = lpPtr->lpRebootMsg =
@ -2146,11 +2173,6 @@ QueryServiceConfig2A(SC_HANDLE hService,
(SC_ACTION*)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpsaActions); (SC_ACTION*)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpsaActions);
} }
break; break;
default:
ERR("Unknown info level 0x%lx\n", dwInfoLevel);
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
} }
TRACE("QueryServiceConfig2A() done\n"); TRACE("QueryServiceConfig2A() done\n");
@ -2171,23 +2193,43 @@ QueryServiceConfig2W(SC_HANDLE hService,
DWORD cbBufSize, DWORD cbBufSize,
LPDWORD pcbBytesNeeded) LPDWORD pcbBytesNeeded)
{ {
SERVICE_DESCRIPTIONW ServiceDescription;
SERVICE_FAILURE_ACTIONSW ServiceFailureActions;
LPBYTE lpTempBuffer;
BOOL bUseTempBuffer = FALSE;
DWORD dwBufferSize;
DWORD dwError; DWORD dwError;
TRACE("QueryServiceConfig2W(%p, %lu, %p, %lu, %p)\n", TRACE("QueryServiceConfig2W(%p, %lu, %p, %lu, %p)\n",
hService, dwInfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded); hService, dwInfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
if (dwInfoLevel != SERVICE_CONFIG_DESCRIPTION && lpTempBuffer = lpBuffer;
dwInfoLevel != SERVICE_CONFIG_FAILURE_ACTIONS) dwBufferSize = cbBufSize;
{
SetLastError(ERROR_INVALID_LEVEL);
return FALSE;
}
if ((lpBuffer == NULL && cbBufSize != 0) || switch (dwInfoLevel)
pcbBytesNeeded == NULL)
{ {
SetLastError(ERROR_INVALID_ADDRESS); case SERVICE_CONFIG_DESCRIPTION:
return FALSE; 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 RpcTryExcept
@ -2195,8 +2237,8 @@ QueryServiceConfig2W(SC_HANDLE hService,
/* Call to services.exe using RPC */ /* Call to services.exe using RPC */
dwError = RQueryServiceConfig2W((SC_RPC_HANDLE)hService, dwError = RQueryServiceConfig2W((SC_RPC_HANDLE)hService,
dwInfoLevel, dwInfoLevel,
lpBuffer, lpTempBuffer,
cbBufSize, dwBufferSize,
pcbBytesNeeded); pcbBytesNeeded);
} }
RpcExcept(EXCEPTION_EXECUTE_HANDLER) RpcExcept(EXCEPTION_EXECUTE_HANDLER)
@ -2212,11 +2254,18 @@ QueryServiceConfig2W(SC_HANDLE hService,
return FALSE; return FALSE;
} }
if (bUseTempBuffer == TRUE)
{
TRACE("RQueryServiceConfig2W() returns ERROR_INSUFFICIENT_BUFFER\n");
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return FALSE;
}
switch (dwInfoLevel) switch (dwInfoLevel)
{ {
case SERVICE_CONFIG_DESCRIPTION: case SERVICE_CONFIG_DESCRIPTION:
{ {
LPSERVICE_DESCRIPTIONW lpPtr = (LPSERVICE_DESCRIPTIONW)lpBuffer; LPSERVICE_DESCRIPTIONW lpPtr = (LPSERVICE_DESCRIPTIONW)lpTempBuffer;
if (lpPtr->lpDescription != NULL) if (lpPtr->lpDescription != NULL)
lpPtr->lpDescription = lpPtr->lpDescription =
@ -2226,7 +2275,7 @@ QueryServiceConfig2W(SC_HANDLE hService,
case SERVICE_CONFIG_FAILURE_ACTIONS: 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) if (lpPtr->lpRebootMsg != NULL)
lpPtr->lpRebootMsg = lpPtr->lpRebootMsg =
@ -2241,11 +2290,6 @@ QueryServiceConfig2W(SC_HANDLE hService,
(SC_ACTION*)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpsaActions); (SC_ACTION*)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpsaActions);
} }
break; break;
default:
WARN("Unknown info level 0x%lx\n", dwInfoLevel);
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
} }
TRACE("QueryServiceConfig2W() done\n"); TRACE("QueryServiceConfig2W() done\n");