[SERVICES]

... and for 61001st commit: Fix the ANSI version of the server-side of ChangeServiceConfig2A API, which broke at converting SERVICE_FAILURE_ACTIONS ANSI structures into UNICODE ones.
Fixes the VMWare Tools Installer; blame Sylvain if it doesn't ;)
Based on a patch by Sylvain Petreolle.
CORE-7539 #comment Fixed in revision 61001, thanks !

svn path=/trunk/; revision=61001
This commit is contained in:
Hermès Bélusca-Maïto 2013-11-15 21:03:01 +00:00
parent ccf756f902
commit f6762917ee

View file

@ -4712,9 +4712,6 @@ Done:
} }
//
// WARNING: This function is untested
//
/* Function 36 */ /* Function 36 */
DWORD RChangeServiceConfig2A( DWORD RChangeServiceConfig2A(
SC_RPC_HANDLE hService, SC_RPC_HANDLE hService,
@ -4731,48 +4728,57 @@ DWORD RChangeServiceConfig2A(
if (InfoW.dwInfoLevel == SERVICE_CONFIG_DESCRIPTION) if (InfoW.dwInfoLevel == SERVICE_CONFIG_DESCRIPTION)
{ {
LPSERVICE_DESCRIPTIONW lpServiceDescriptonW; LPSERVICE_DESCRIPTIONW lpServiceDescriptionW;
//LPSERVICE_DESCRIPTIONA lpServiceDescriptonA; //LPSERVICE_DESCRIPTIONA lpServiceDescriptionA;
//lpServiceDescriptonA = Info.psd; //lpServiceDescriptionA = Info.psd;
///if (lpServiceDescriptonA && ///if (lpServiceDescriptionA &&
///lpServiceDescriptonA->lpDescription) ///lpServiceDescriptionA->lpDescription)
///{ ///{
dwLength = (DWORD)((strlen(Info.lpDescription) + 1) * sizeof(WCHAR)); dwLength = (DWORD)((strlen(Info.lpDescription) + 1) * sizeof(WCHAR));
lpServiceDescriptonW = HeapAlloc(GetProcessHeap(), lpServiceDescriptionW = HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY, HEAP_ZERO_MEMORY,
dwLength + sizeof(SERVICE_DESCRIPTIONW)); dwLength + sizeof(SERVICE_DESCRIPTIONW));
if (!lpServiceDescriptonW) if (!lpServiceDescriptionW)
{ {
return ERROR_NOT_ENOUGH_MEMORY; return ERROR_NOT_ENOUGH_MEMORY;
} }
lpServiceDescriptonW->lpDescription = (LPWSTR)(lpServiceDescriptonW + 1); lpServiceDescriptionW->lpDescription = (LPWSTR)(lpServiceDescriptionW + 1);
MultiByteToWideChar(CP_ACP, MultiByteToWideChar(CP_ACP,
0, 0,
Info.lpDescription, Info.lpDescription,
-1, -1,
lpServiceDescriptonW->lpDescription, lpServiceDescriptionW->lpDescription,
dwLength); dwLength);
ptr = lpServiceDescriptonW; ptr = lpServiceDescriptionW;
InfoW.psd = lpServiceDescriptonW; InfoW.psd = lpServiceDescriptionW;
///} ///}
} }
else if (Info.dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS) else if (Info.dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS)
{ {
LPSERVICE_FAILURE_ACTIONSW lpServiceFailureActionsW; LPSERVICE_FAILURE_ACTIONSW lpServiceFailureActionsW;
LPSERVICE_FAILURE_ACTIONSA lpServiceFailureActionsA; LPSERVICE_FAILURE_ACTIONSA lpServiceFailureActionsA;
DWORD dwRebootLen = 0; DWORD dwRebootLen = 0;
DWORD dwCommandLen = 0; DWORD dwCommandLen = 0;
DWORD dwActionArrayLen = 0;
LPWSTR lpStr = NULL;
lpServiceFailureActionsA = Info.psfa; lpServiceFailureActionsA = Info.psfa;
if (lpServiceFailureActionsA) if (lpServiceFailureActionsA)
{ {
/*
* The following code is inspired by the
* SERVICE_CONFIG_FAILURE_ACTIONS case of
* the RQueryServiceConfig2W function.
*/
/* Retrieve the needed length for the two data strings */
if (lpServiceFailureActionsA->lpRebootMsg) if (lpServiceFailureActionsA->lpRebootMsg)
{ {
dwRebootLen = (DWORD)((strlen(lpServiceFailureActionsA->lpRebootMsg) + 1) * sizeof(WCHAR)); dwRebootLen = (DWORD)((strlen(lpServiceFailureActionsA->lpRebootMsg) + 1) * sizeof(WCHAR));
@ -4781,8 +4787,22 @@ DWORD RChangeServiceConfig2A(
{ {
dwCommandLen = (DWORD)((strlen(lpServiceFailureActionsA->lpCommand) + 1) * sizeof(WCHAR)); dwCommandLen = (DWORD)((strlen(lpServiceFailureActionsA->lpCommand) + 1) * sizeof(WCHAR));
} }
dwLength = dwRebootLen + dwCommandLen + sizeof(SERVICE_FAILURE_ACTIONSW);
/*
* Retrieve the size of the lpsaActions array if needed.
* We will copy the lpsaActions array only if there is at
* least one action AND that the original array is valid.
*/
if (lpServiceFailureActionsA->cActions > 0 && lpServiceFailureActionsA->lpsaActions)
{
dwActionArrayLen = lpServiceFailureActionsA->cActions * sizeof(SC_ACTION);
}
/* Compute the total length for the UNICODE structure, including data */
dwLength = sizeof(SERVICE_FAILURE_ACTIONSW) +
dwActionArrayLen + dwRebootLen + dwCommandLen;
/* Allocate the structure */
lpServiceFailureActionsW = HeapAlloc(GetProcessHeap(), lpServiceFailureActionsW = HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY, HEAP_ZERO_MEMORY,
dwLength); dwLength);
@ -4791,22 +4811,56 @@ DWORD RChangeServiceConfig2A(
return ERROR_NOT_ENOUGH_MEMORY; return ERROR_NOT_ENOUGH_MEMORY;
} }
lpServiceFailureActionsW->cActions = lpServiceFailureActionsA->cActions; /* Copy the members */
lpServiceFailureActionsW->dwResetPeriod = lpServiceFailureActionsA->dwResetPeriod; lpServiceFailureActionsW->dwResetPeriod = lpServiceFailureActionsA->dwResetPeriod;
CopyMemory(lpServiceFailureActionsW->lpsaActions, lpServiceFailureActionsA->lpsaActions, sizeof(SC_ACTION)); lpServiceFailureActionsW->cActions = lpServiceFailureActionsA->cActions;
if (lpServiceFailureActionsA->lpRebootMsg) /* Copy the lpsaActions array if needed */
if (dwActionArrayLen > 0)
{ {
/* The storage zone is just after the end of the SERVICE_FAILURE_ACTIONSW structure */
lpServiceFailureActionsW->lpsaActions = (LPSC_ACTION)((ULONG_PTR)(lpServiceFailureActionsW + 1));
/* dwActionArrayLen == lpServiceFailureActionsW->cActions * sizeof(SC_ACTION) */
RtlCopyMemory(lpServiceFailureActionsW->lpsaActions,
lpServiceFailureActionsA->lpsaActions,
dwActionArrayLen);
}
else
{
/* No lpsaActions array */
lpServiceFailureActionsW->lpsaActions = NULL;
}
/* The data strings are stored just after the lpsaActions array */
lpStr = (LPWSTR)((ULONG_PTR)(lpServiceFailureActionsW + 1) + dwActionArrayLen);
/*
* Convert the data strings to UNICODE
*/
lpServiceFailureActionsW->lpRebootMsg = NULL;
lpServiceFailureActionsW->lpCommand = NULL;
if (dwRebootLen)
{
/* lpRebootMsg points just after the lpsaActions array */
lpServiceFailureActionsW->lpRebootMsg = lpStr;
MultiByteToWideChar(CP_ACP, MultiByteToWideChar(CP_ACP,
0, 0,
lpServiceFailureActionsA->lpRebootMsg, lpServiceFailureActionsA->lpRebootMsg,
-1, -1,
lpServiceFailureActionsW->lpRebootMsg, lpServiceFailureActionsW->lpRebootMsg,
dwRebootLen); dwRebootLen);
lpStr += dwRebootLen / sizeof(WCHAR);
} }
if (lpServiceFailureActionsA->lpCommand) if (dwCommandLen)
{ {
/* lpRebootMsg points just after the lpRebootMsg data string */
lpServiceFailureActionsW->lpCommand = lpStr;
MultiByteToWideChar(CP_ACP, MultiByteToWideChar(CP_ACP,
0, 0,
lpServiceFailureActionsA->lpCommand, lpServiceFailureActionsA->lpCommand,
@ -4815,7 +4869,9 @@ DWORD RChangeServiceConfig2A(
dwCommandLen); dwCommandLen);
} }
/* Set the pointers */
ptr = lpServiceFailureActionsW; ptr = lpServiceFailureActionsW;
InfoW.psfa = lpServiceFailureActionsW;
} }
} }