[SERVICES]

Implement SERVICE_CONFIG_FAILURE_ACTIONS case in RQueryServiceConfig2W and RQueryServiceConfig2A.

Patch by Hermès Bélusca.


See issue #7101 for more details.

svn path=/trunk/; revision=56696
This commit is contained in:
Eric Kohl
2012-06-05 10:19:39 +00:00
parent 4d7e7f2be8
commit 2fc88995de
+181 -26
View File
@@ -4819,7 +4819,11 @@ DWORD RQueryServiceConfig2A(
PSERVICE_HANDLE hSvc;
PSERVICE lpService = NULL;
HKEY hServiceKey = NULL;
DWORD dwRequiredSize = 0;
DWORD dwType = 0;
LPWSTR lpDescriptionW = NULL;
LPWSTR lpRebootMessageW = NULL;
LPWSTR lpFailureCommandW = NULL;
DPRINT("RQueryServiceConfig2A() called hService %p dwInfoLevel %u, lpBuffer %p cbBufSize %u pcbBytesNeeded %p\n",
hService, dwInfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
@@ -4899,14 +4903,116 @@ DWORD RQueryServiceConfig2A(
{
lpServiceDescription->lpDescription = NULL;
dwError = ERROR_SUCCESS;
goto done;
}
}
else if (dwInfoLevel & SERVICE_CONFIG_FAILURE_ACTIONS)
else if (dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS)
{
UNIMPLEMENTED;
dwError = ERROR_CALL_NOT_IMPLEMENTED;
goto done;
LPSERVICE_FAILURE_ACTIONSA lpFailureActions = (LPSERVICE_FAILURE_ACTIONSA)lpBuffer;
LPSTR lpStr;
/* Query value length */
dwRequiredSize = 0;
dwError = RegQueryValueExW(hServiceKey,
L"FailureActions",
NULL,
&dwType,
NULL,
&dwRequiredSize);
if (dwError != ERROR_SUCCESS && dwError != ERROR_MORE_DATA)
goto done;
if (dwType != REG_BINARY)
{
dwError = ERROR_UNSUPPORTED_TYPE;
goto done;
}
dwRequiredSize = max(sizeof(SERVICE_FAILURE_ACTIONSA), dwRequiredSize);
dwError = ScmReadString(hServiceKey,
L"FailureCommand",
&lpFailureCommandW);
dwError = ScmReadString(hServiceKey,
L"RebootMessage",
&lpRebootMessageW);
if (lpRebootMessageW)
dwRequiredSize += (wcslen(lpRebootMessageW) + 1) * sizeof(WCHAR);
if (lpFailureCommandW)
dwRequiredSize += (wcslen(lpFailureCommandW) + 1) * sizeof(WCHAR);
if (cbBufSize < dwRequiredSize)
{
*pcbBytesNeeded = dwRequiredSize;
dwError = ERROR_INSUFFICIENT_BUFFER;
goto done;
}
/* Now we can fill the buffer */
dwError = RegQueryValueExW(hServiceKey,
L"FailureActions",
NULL,
NULL,
(LPBYTE)lpFailureActions,
&dwRequiredSize);
if (dwError != ERROR_SUCCESS)
goto done;
if ((dwRequiredSize < sizeof(SERVICE_FAILURE_ACTIONSA)) ||
(dwRequiredSize > cbBufSize))
{
dwError = ERROR_BUFFER_OVERFLOW;
goto done;
}
if (dwError == ERROR_SUCCESS)
{
lpFailureActions->cActions = min(lpFailureActions->cActions, (dwRequiredSize - FIELD_OFFSET(SERVICE_FAILURE_ACTIONSA, lpsaActions)) / sizeof(SC_ACTION));
lpFailureActions->lpsaActions = (lpFailureActions->cActions > 0) ? (LPSC_ACTION)(lpFailureActions + 1) : NULL;
lpStr = (LPSTR)((ULONG_PTR)(lpFailureActions + 1) + lpFailureActions->cActions * sizeof(SC_ACTION));
}
else
{
lpFailureActions->dwResetPeriod = 0;
lpFailureActions->cActions = 0;
lpFailureActions->lpsaActions = NULL;
lpStr = (LPSTR)(lpFailureActions + 1);
}
lpFailureActions->lpRebootMsg = NULL;
lpFailureActions->lpCommand = NULL;
if (lpRebootMessageW)
{
WideCharToMultiByte(CP_ACP,
0,
lpRebootMessageW,
-1,
lpStr,
wcslen(lpRebootMessageW),
NULL,
NULL);
lpFailureActions->lpRebootMsg = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpFailureActions);
lpStr += strlen(lpStr) + 1;
}
if (lpFailureCommandW)
{
WideCharToMultiByte(CP_ACP,
0,
lpFailureCommandW,
-1,
lpStr,
wcslen(lpFailureCommandW),
NULL,
NULL);
lpFailureActions->lpCommand = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpFailureActions);
/* lpStr += strlen(lpStr) + 1; */
}
dwError = ERROR_SUCCESS;
}
done:
@@ -4916,10 +5022,16 @@ done:
if (lpDescriptionW != NULL)
HeapFree(GetProcessHeap(), 0, lpDescriptionW);
if (lpRebootMessageW != NULL)
HeapFree(GetProcessHeap(), 0, lpRebootMessageW);
if (lpFailureCommandW != NULL)
HeapFree(GetProcessHeap(), 0, lpFailureCommandW);
if (hServiceKey != NULL)
RegCloseKey(hServiceKey);
DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError);
DPRINT("RQueryServiceConfig2A() done (Error %lu)\n", dwError);
return dwError;
}
@@ -4937,10 +5049,11 @@ DWORD RQueryServiceConfig2W(
PSERVICE_HANDLE hSvc;
PSERVICE lpService = NULL;
HKEY hServiceKey = NULL;
DWORD dwRequiredSize;
DWORD dwRequiredSize = 0;
DWORD dwType = 0;
LPWSTR lpDescription = NULL;
LPWSTR lpFailureCommand = NULL;
LPWSTR lpRebootMessage = NULL;
LPWSTR lpFailureCommand = NULL;
DPRINT("RQueryServiceConfig2W() called\n");
@@ -5015,10 +5128,27 @@ DWORD RQueryServiceConfig2W(
}
else if (dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS)
{
LPWSTR lpStr;
LPSERVICE_FAILURE_ACTIONSW lpFailureActions = (LPSERVICE_FAILURE_ACTIONSW)lpBuffer;
LPWSTR lpStr;
UNIMPLEMENTED;
/* Query value length */
dwRequiredSize = 0;
dwError = RegQueryValueExW(hServiceKey,
L"FailureActions",
NULL,
&dwType,
NULL,
&dwRequiredSize);
if (dwError != ERROR_SUCCESS && dwError != ERROR_MORE_DATA)
goto done;
if (dwType != REG_BINARY)
{
dwError = ERROR_UNSUPPORTED_TYPE;
goto done;
}
dwRequiredSize = max(sizeof(SERVICE_FAILURE_ACTIONSW), dwRequiredSize);
dwError = ScmReadString(hServiceKey,
L"FailureCommand",
@@ -5028,14 +5158,12 @@ DWORD RQueryServiceConfig2W(
L"RebootMessage",
&lpRebootMessage);
dwRequiredSize = sizeof(SERVICE_FAILURE_ACTIONSW);
if (lpRebootMessage)
dwRequiredSize += (wcslen(lpRebootMessage) + 1) * sizeof(WCHAR);
if (lpFailureCommand)
dwRequiredSize += (wcslen(lpFailureCommand) + 1) * sizeof(WCHAR);
if (lpRebootMessage)
dwRequiredSize += (wcslen(lpRebootMessage) + 1) * sizeof(WCHAR);
if (cbBufSize < dwRequiredSize)
{
*pcbBytesNeeded = dwRequiredSize;
@@ -5043,28 +5171,55 @@ DWORD RQueryServiceConfig2W(
goto done;
}
lpFailureActions->cActions = 0;
lpFailureActions->dwResetPeriod = 0;
lpFailureActions->lpCommand = NULL;
lpFailureActions->lpRebootMsg = NULL;
lpFailureActions->lpsaActions = NULL;
/* Now we can fill the buffer */
dwError = RegQueryValueExW(hServiceKey,
L"FailureActions",
NULL,
NULL,
(LPBYTE)lpFailureActions,
&dwRequiredSize);
if (dwError != ERROR_SUCCESS)
goto done;
if ((dwRequiredSize < sizeof(SERVICE_FAILURE_ACTIONSW)) ||
(dwRequiredSize > cbBufSize))
{
dwError = ERROR_BUFFER_OVERFLOW;
goto done;
}
if (dwError == ERROR_SUCCESS)
{
lpFailureActions->cActions = min(lpFailureActions->cActions, (dwRequiredSize - FIELD_OFFSET(SERVICE_FAILURE_ACTIONSW, lpsaActions)) / sizeof(SC_ACTION));
lpFailureActions->lpsaActions = (lpFailureActions->cActions > 0 ? (LPSC_ACTION)(lpFailureActions + 1) : NULL);
lpStr = (LPWSTR)((ULONG_PTR)(lpFailureActions + 1) + lpFailureActions->cActions * sizeof(SC_ACTION));
}
else
{
lpFailureActions->dwResetPeriod = 0;
lpFailureActions->cActions = 0;
lpFailureActions->lpsaActions = NULL;
lpStr = (LPWSTR)(lpFailureActions + 1);
}
lpFailureActions->lpRebootMsg = NULL;
lpFailureActions->lpCommand = NULL;
lpStr = (LPWSTR)(lpFailureActions + 1);
if (lpRebootMessage)
{
wcscpy(lpStr, lpRebootMessage);
lpFailureActions->lpRebootMsg = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpRebootMessage);
lpStr += wcslen(lpRebootMessage) + 1;
lpFailureActions->lpRebootMsg = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpFailureActions);
lpStr += wcslen(lpStr) + 1;
}
if (lpFailureCommand)
{
wcscpy(lpStr, lpFailureCommand);
lpFailureActions->lpCommand = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpFailureCommand);
lpStr += wcslen(lpRebootMessage) + 1;
lpFailureActions->lpCommand = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpFailureActions);
/* lpStr += wcslen(lpStr) + 1; */
}
dwError = STATUS_SUCCESS;
goto done;
dwError = ERROR_SUCCESS;
}
done: