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/rpcserver.c?rev=61001&r1=61000&r2=61001&view=diff
==============================================================================
--- 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;
         }
     }
 


Reply via email to