Author: hbelusca Date: Fri Nov 15 21:03:01 2013 New Revision: 61001
URL: http://svn.reactos.org/svn/reactos?rev=61001&view=rev Log: [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 !
Modified: trunk/reactos/base/system/services/rpcserver.c
Modified: trunk/reactos/base/system/services/rpcserver.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/system/services/rpcser... ============================================================================== --- trunk/reactos/base/system/services/rpcserver.c [iso-8859-1] (original) +++ trunk/reactos/base/system/services/rpcserver.c [iso-8859-1] Fri Nov 15 21:03:01 2013 @@ -4712,9 +4712,6 @@ }
-// -// WARNING: This function is untested -// /* Function 36 */ DWORD RChangeServiceConfig2A( SC_RPC_HANDLE hService, @@ -4731,48 +4728,57 @@
if (InfoW.dwInfoLevel == SERVICE_CONFIG_DESCRIPTION) { - LPSERVICE_DESCRIPTIONW lpServiceDescriptonW; - //LPSERVICE_DESCRIPTIONA lpServiceDescriptonA; - - //lpServiceDescriptonA = Info.psd; - - ///if (lpServiceDescriptonA && - ///lpServiceDescriptonA->lpDescription) + LPSERVICE_DESCRIPTIONW lpServiceDescriptionW; + //LPSERVICE_DESCRIPTIONA lpServiceDescriptionA; + + //lpServiceDescriptionA = Info.psd; + + ///if (lpServiceDescriptionA && + ///lpServiceDescriptionA->lpDescription) ///{ dwLength = (DWORD)((strlen(Info.lpDescription) + 1) * sizeof(WCHAR));
- lpServiceDescriptonW = HeapAlloc(GetProcessHeap(), - HEAP_ZERO_MEMORY, - dwLength + sizeof(SERVICE_DESCRIPTIONW)); - if (!lpServiceDescriptonW) + lpServiceDescriptionW = HeapAlloc(GetProcessHeap(), + HEAP_ZERO_MEMORY, + dwLength + sizeof(SERVICE_DESCRIPTIONW)); + if (!lpServiceDescriptionW) { return ERROR_NOT_ENOUGH_MEMORY; }
- lpServiceDescriptonW->lpDescription = (LPWSTR)(lpServiceDescriptonW + 1); + lpServiceDescriptionW->lpDescription = (LPWSTR)(lpServiceDescriptionW + 1);
MultiByteToWideChar(CP_ACP, 0, Info.lpDescription, -1, - lpServiceDescriptonW->lpDescription, + lpServiceDescriptionW->lpDescription, dwLength);
- ptr = lpServiceDescriptonW; - InfoW.psd = lpServiceDescriptonW; + ptr = lpServiceDescriptionW; + InfoW.psd = lpServiceDescriptionW; ///} } else if (Info.dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS) { LPSERVICE_FAILURE_ACTIONSW lpServiceFailureActionsW; LPSERVICE_FAILURE_ACTIONSA lpServiceFailureActionsA; - DWORD dwRebootLen = 0; + DWORD dwRebootLen = 0; DWORD dwCommandLen = 0; + DWORD dwActionArrayLen = 0; + LPWSTR lpStr = NULL;
lpServiceFailureActionsA = Info.psfa;
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) { dwRebootLen = (DWORD)((strlen(lpServiceFailureActionsA->lpRebootMsg) + 1) * sizeof(WCHAR)); @@ -4781,8 +4787,22 @@ { 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(), HEAP_ZERO_MEMORY, dwLength); @@ -4791,22 +4811,56 @@ return ERROR_NOT_ENOUGH_MEMORY; }
- lpServiceFailureActionsW->cActions = lpServiceFailureActionsA->cActions; + /* Copy the members */ lpServiceFailureActionsW->dwResetPeriod = lpServiceFailureActionsA->dwResetPeriod; - CopyMemory(lpServiceFailureActionsW->lpsaActions, lpServiceFailureActionsA->lpsaActions, sizeof(SC_ACTION)); - - if (lpServiceFailureActionsA->lpRebootMsg) + lpServiceFailureActionsW->cActions = lpServiceFailureActionsA->cActions; + + /* 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, 0, lpServiceFailureActionsA->lpRebootMsg, -1, lpServiceFailureActionsW->lpRebootMsg, dwRebootLen); + + lpStr += dwRebootLen / sizeof(WCHAR); }
- if (lpServiceFailureActionsA->lpCommand) + if (dwCommandLen) { + /* lpRebootMsg points just after the lpRebootMsg data string */ + lpServiceFailureActionsW->lpCommand = lpStr; + MultiByteToWideChar(CP_ACP, 0, lpServiceFailureActionsA->lpCommand, @@ -4815,7 +4869,9 @@ dwCommandLen); }
+ /* Set the pointers */ ptr = lpServiceFailureActionsW; + InfoW.psfa = lpServiceFailureActionsW; } }