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/rpcse…
==============================================================================
--- 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;
}
}