[ADVAPI32]
[reactos.git] / reactos / dll / win32 / advapi32 / service / sctrl.c
index 53a9aef..c6dfcf2 100644 (file)
@@ -278,119 +278,146 @@ ScConnectControlPipe(HANDLE *hPipe)
 
 
 static DWORD
-ScStartService(PACTIVE_SERVICE lpService,
-               PSCM_CONTROL_PACKET ControlPacket)
+ScBuildUnicodeArgsVector(PSCM_CONTROL_PACKET ControlPacket,
+                         LPDWORD lpArgCount,
+                         LPWSTR **lpArgVector)
 {
-    HANDLE ThreadHandle;
-    DWORD ThreadId;
-    LPWSTR *lpArgW;
+    LPWSTR *lpVector;
+    LPWSTR *lpArg;
     DWORD i;
 
-    TRACE("ScStartService() called\n");
-    TRACE("Size: %lu\n", ControlPacket->dwSize);
-    TRACE("Service: %S\n", (PWSTR)((PBYTE)ControlPacket + ControlPacket->dwServiceNameOffset));
+    *lpArgCount = 0;
+    *lpArgVector = NULL;
 
-    /* Set the service status handle */
-    lpService->hServiceStatus = ControlPacket->hServiceStatus;
-
-    if (lpService->bUnicode == TRUE)
+    if (ControlPacket->dwArgumentsCount > 0)
     {
-        lpService->ThreadParams.W.dwArgCount = ControlPacket->dwArgumentsCount;
-        lpService->ThreadParams.W.lpArgVector = NULL;
+        lpVector = HeapAlloc(GetProcessHeap(),
+                             HEAP_ZERO_MEMORY,
+                             ControlPacket->dwSize - ControlPacket->dwArgumentsOffset);
+        if (lpVector == NULL)
+            return ERROR_OUTOFMEMORY;
 
-        if (ControlPacket->dwArgumentsOffset > 0)
+        memcpy(lpVector,
+               ((PBYTE)ControlPacket + ControlPacket->dwArgumentsOffset),
+               ControlPacket->dwSize - ControlPacket->dwArgumentsOffset);
+
+        lpArg = lpVector;
+        for (i = 0; i < ControlPacket->dwArgumentsCount; i++)
         {
-            lpService->ThreadParams.W.lpArgVector =
-                HeapAlloc(GetProcessHeap(),
-                          HEAP_ZERO_MEMORY,
-                          ControlPacket->dwSize - ControlPacket->dwArgumentsOffset);
-            if (lpService->ThreadParams.W.lpArgVector == NULL)
-                return ERROR_OUTOFMEMORY;
-
-            memcpy(lpService->ThreadParams.W.lpArgVector,
-                   ((PBYTE)ControlPacket + ControlPacket->dwArgumentsOffset),
-                   ControlPacket->dwSize - ControlPacket->dwArgumentsOffset);
-
-            lpArgW = lpService->ThreadParams.W.lpArgVector;
-            for (i = 0; i < lpService->ThreadParams.W.dwArgCount; i++)
-            {
-                *lpArgW = (LPWSTR)((ULONG_PTR)lpArgW + (ULONG_PTR)*lpArgW);
-                lpArgW++;
-            }
+            *lpArg = (LPWSTR)((ULONG_PTR)lpArg + (ULONG_PTR)*lpArg);
+            lpArg++;
         }
+
+        *lpArgCount = ControlPacket->dwArgumentsCount;
+        *lpArgVector = lpVector;
     }
-    else
+
+    return ERROR_SUCCESS;
+}
+
+
+static DWORD
+ScBuildAnsiArgsVector(PSCM_CONTROL_PACKET ControlPacket,
+                      LPDWORD lpArgCount,
+                      LPSTR **lpArgVector)
+{
+    LPSTR *lpVector;
+    LPSTR *lpPtr;
+    LPWSTR lpUnicodeString;
+    LPSTR lpAnsiString;
+    DWORD dwVectorSize;
+    DWORD dwUnicodeSize;
+    DWORD dwAnsiSize;
+    DWORD i;
+
+    *lpArgCount = 0;
+    *lpArgVector = NULL;
+
+    if (ControlPacket->dwArgumentsCount > 0)
     {
-        /* FIXME */
-        lpService->ThreadParams.A.dwArgCount = 0;
-        lpService->ThreadParams.A.lpArgVector = NULL;
+        dwVectorSize = ControlPacket->dwArgumentsCount * sizeof(LPWSTR);
 
-#if 0
-        LPSTR *lpArgVector;
-        LPSTR Ptr;
-        LPSTR AnsiString;
-        DWORD AnsiLength;
+        lpUnicodeString = (LPWSTR)((PBYTE)ControlPacket +
+                                   ControlPacket->dwArgumentsOffset +
+                                   dwVectorSize);
+        dwUnicodeSize = (ControlPacket->dwSize -
+                         ControlPacket->dwArgumentsOffset -
+                         dwVectorSize) / sizeof(WCHAR);
 
-        AnsiLength = WideCharToMultiByte(CP_ACP,
+        dwAnsiSize = WideCharToMultiByte(CP_ACP,
                                          0,
-                                         lpService->Arguments,
-                                         dwLength,
+                                         lpUnicodeString,
+                                         dwUnicodeSize,
                                          NULL,
                                          0,
                                          NULL,
                                          NULL);
-        if (AnsiLength == 0)
-            return ERROR_INVALID_PARAMETER; /* ? */
 
-        AnsiString = HeapAlloc(GetProcessHeap(),
-                               0,
-                               AnsiLength + 1);
-        if (AnsiString == NULL)
+        lpVector = HeapAlloc(GetProcessHeap(),
+                             HEAP_ZERO_MEMORY,
+                             dwVectorSize + dwAnsiSize);
+        if (lpVector == NULL)
             return ERROR_OUTOFMEMORY;
 
+        lpPtr = (LPSTR*)lpVector;
+        lpAnsiString = (LPSTR)((ULONG_PTR)lpVector + dwVectorSize);
+
         WideCharToMultiByte(CP_ACP,
                             0,
-                            lpService->Arguments,
-                            dwLength,
-                            AnsiString,
-                            AnsiLength,
+                            lpUnicodeString,
+                            dwUnicodeSize,
+                            lpAnsiString,
+                            dwAnsiSize,
                             NULL,
                             NULL);
 
-        AnsiString[AnsiLength] = ANSI_NULL;
-
-        lpArgVector = HeapAlloc(GetProcessHeap(),
-                                0,
-                                (dwArgCount + 1) * sizeof(LPSTR));
-        if (lpArgVector == NULL)
+        for (i = 0; i < ControlPacket->dwArgumentsCount; i++)
         {
-            HeapFree(GetProcessHeap(),
-                        0,
-                        AnsiString);
-            return ERROR_OUTOFMEMORY;
+            *lpPtr = lpAnsiString;
+
+            lpPtr++;
+            lpAnsiString += (strlen(lpAnsiString) + 1);
         }
 
-        dwArgCount = 0;
-        Ptr = AnsiString;
-        while (*Ptr)
-        {
-            lpArgVector[dwArgCount] = Ptr;
+        *lpArgCount = ControlPacket->dwArgumentsCount;
+        *lpArgVector = lpVector;
+    }
 
-            dwArgCount++;
-            Ptr += (strlen(Ptr) + 1);
-        }
-        lpArgVector[dwArgCount] = NULL;
+    return ERROR_SUCCESS;
+}
+
+
+static DWORD
+ScStartService(PACTIVE_SERVICE lpService,
+               PSCM_CONTROL_PACKET ControlPacket)
+{
+    HANDLE ThreadHandle;
+    DWORD ThreadId;
+    DWORD dwError;
+
+    TRACE("ScStartService() called\n");
+    TRACE("Size: %lu\n", ControlPacket->dwSize);
+    TRACE("Service: %S\n", (PWSTR)((PBYTE)ControlPacket + ControlPacket->dwServiceNameOffset));
 
-        (lpService->ThreadParams.A.lpServiceMain)(dwArgCount, lpArgVector);
+    /* Set the service status handle */
+    lpService->hServiceStatus = ControlPacket->hServiceStatus;
 
-        HeapFree(GetProcessHeap(),
-                 0,
-                 lpArgVector);
-        HeapFree(GetProcessHeap(),
-                 0,
-                 AnsiString);
-#endif
+    /* Build the arguments vector */
+    if (lpService->bUnicode == TRUE)
+    {
+        dwError = ScBuildUnicodeArgsVector(ControlPacket,
+                                           &lpService->ThreadParams.W.dwArgCount,
+                                           &lpService->ThreadParams.W.lpArgVector);
     }
+    else
+    {
+        dwError = ScBuildAnsiArgsVector(ControlPacket,
+                                        &lpService->ThreadParams.A.dwArgCount,
+                                        &lpService->ThreadParams.A.lpArgVector);
+    }
+
+    if (dwError != ERROR_SUCCESS)
+        return dwError;
 
     /* Invoke the services entry point and implement the command loop */
     ThreadHandle = CreateThread(NULL,