[ADVAPI32] Take into account the service handler context when dispatching a control...
[reactos.git] / dll / win32 / advapi32 / service / sctrl.c
index a1289f7..5afa8df 100644 (file)
@@ -6,14 +6,13 @@
  * COPYRIGHT:   Copyright 1999 Emanuele Aliberti
  *              Copyright 2007 Ged Murphy <gedmurphy@reactos.org>
  *                             Gregor Brunmar <gregor.brunmar@home.se>
- *
  */
 
 
 /* INCLUDES ******************************************************************/
 
 #include <advapi32.h>
-WINE_DEFAULT_DEBUG_CHANNEL(advapi);
+WINE_DEFAULT_DEBUG_CHANNEL(advapi_service);
 
 
 /* TYPES *********************************************************************/
@@ -40,9 +39,9 @@ typedef struct _ACTIVE_SERVICE
     UNICODE_STRING ServiceName;
     union
     {
-        SERVICE_THREAD_PARAMSA A;
-        SERVICE_THREAD_PARAMSW W;
-    } ThreadParams;
+        LPSERVICE_MAIN_FUNCTIONA A;
+        LPSERVICE_MAIN_FUNCTIONW W;
+    } ServiceMain;
     LPHANDLER_FUNCTION HandlerFunction;
     LPHANDLER_FUNCTION_EX HandlerFunctionEx;
     LPVOID HandlerContext;
@@ -165,43 +164,42 @@ ScLookupServiceByServiceName(LPCWSTR lpServiceName)
 
 
 static DWORD WINAPI
-ScServiceMainStub(LPVOID Context)
+ScServiceMainStubA(LPVOID Context)
 {
-    PACTIVE_SERVICE lpService = (PACTIVE_SERVICE)Context;
+    PSERVICE_THREAD_PARAMSA ThreadParams = Context;
 
-    TRACE("ScServiceMainStub() called\n");
+    TRACE("ScServiceMainStubA() called\n");
 
     /* Call the main service routine and free the arguments vector */
-    if (lpService->bUnicode)
+    (ThreadParams->lpServiceMain)(ThreadParams->dwArgCount,
+                                  ThreadParams->lpArgVector);
+
+    if (ThreadParams->lpArgVector != NULL)
     {
-        (lpService->ThreadParams.W.lpServiceMain)(lpService->ThreadParams.W.dwArgCount,
-                                                  lpService->ThreadParams.W.lpArgVector);
+        HeapFree(GetProcessHeap(), 0, ThreadParams->lpArgVector);
+    }
+    HeapFree(GetProcessHeap(), 0, ThreadParams);
 
-        if (lpService->ThreadParams.W.lpArgVector != NULL)
-        {
-            HeapFree(GetProcessHeap(),
-                     0,
-                     lpService->ThreadParams.W.lpArgVector);
+    return ERROR_SUCCESS;
+}
 
-            lpService->ThreadParams.W.lpArgVector = NULL;
-            lpService->ThreadParams.W.dwArgCount = 0;
-        }
-    }
-    else
-    {
-        (lpService->ThreadParams.A.lpServiceMain)(lpService->ThreadParams.A.dwArgCount,
-                                                  lpService->ThreadParams.A.lpArgVector);
 
-        if (lpService->ThreadParams.A.lpArgVector != NULL)
-        {
-            HeapFree(GetProcessHeap(),
-                     0,
-                     lpService->ThreadParams.A.lpArgVector);
+static DWORD WINAPI
+ScServiceMainStubW(LPVOID Context)
+{
+    PSERVICE_THREAD_PARAMSW ThreadParams = Context;
 
-            lpService->ThreadParams.A.lpArgVector = NULL;
-            lpService->ThreadParams.A.dwArgCount = 0;
-        }
+    TRACE("ScServiceMainStubW() called\n");
+
+    /* Call the main service routine and free the arguments vector */
+    (ThreadParams->lpServiceMain)(ThreadParams->dwArgCount,
+                                  ThreadParams->lpArgVector);
+
+    if (ThreadParams->lpArgVector != NULL)
+    {
+        HeapFree(GetProcessHeap(), 0, ThreadParams->lpArgVector);
     }
+    HeapFree(GetProcessHeap(), 0, ThreadParams);
 
     return ERROR_SUCCESS;
 }
@@ -240,7 +238,7 @@ ScConnectControlPipe(HANDLE *hPipe)
 
     swprintf(NtControlPipeName, L"\\\\.\\pipe\\net\\NtControlPipe%u", dwServiceCurrent);
 
-    if (!WaitNamedPipeW(NtControlPipeName, 15000))
+    if (!WaitNamedPipeW(NtControlPipeName, 30000))
     {
         ERR("WaitNamedPipe(%S) failed (Error %lu)\n", NtControlPipeName, GetLastError());
         return ERROR_FAILED_SERVICE_CONTROLLER_CONNECT;
@@ -248,7 +246,7 @@ ScConnectControlPipe(HANDLE *hPipe)
 
     *hPipe = CreateFileW(NtControlPipeName,
                          GENERIC_READ | GENERIC_WRITE,
-                         0,
+                         FILE_SHARE_READ | FILE_SHARE_WRITE,
                          NULL,
                          OPEN_EXISTING,
                          FILE_ATTRIBUTE_NORMAL,
@@ -281,44 +279,90 @@ ScConnectControlPipe(HANDLE *hPipe)
 }
 
 
+/*
+ * Ansi/Unicode argument layout of the vector passed to a service at startup,
+ * depending on the different versions of Windows considered:
+ *
+ * - XP/2003:
+ *   [argv array of pointers][parameter 1][parameter 2]...[service name]
+ *
+ * - Vista:
+ *   [argv array of pointers][align to 8 bytes]
+ *   [parameter 1][parameter 2]...[service name]
+ *
+ * - Win7/8:
+ *   [argv array of pointers][service name]
+ *   [parameter 1][align to 4 bytes][parameter 2][align to 4 bytes]...
+ *
+ * Space for parameters and service name is always enough to store
+ * both the Ansi and the Unicode versions including NULL terminator.
+ */
+
 static DWORD
 ScBuildUnicodeArgsVector(PSCM_CONTROL_PACKET ControlPacket,
                          LPDWORD lpArgCount,
                          LPWSTR **lpArgVector)
 {
-    LPWSTR *lpVector;
-    LPWSTR *lpArg;
+    PWSTR *lpVector;
+    PWSTR pszServiceName;
+    DWORD cbServiceName;
+    DWORD cbArguments;
+    DWORD cbTotal;
     DWORD i;
 
     if (ControlPacket == NULL || lpArgCount == NULL || lpArgVector == NULL)
         return ERROR_INVALID_PARAMETER;
 
-    *lpArgCount = 0;
+    *lpArgCount  = 0;
     *lpArgVector = NULL;
 
+    /* Retrieve and count the start command line (NULL-terminated) */
+    pszServiceName = (PWSTR)((ULONG_PTR)ControlPacket + ControlPacket->dwServiceNameOffset);
+    cbServiceName  = lstrlenW(pszServiceName) * sizeof(WCHAR) + sizeof(UNICODE_NULL);
+
+    /*
+     * The total size of the argument vector is equal to the entry for
+     * the service name, plus the size of the original argument vector.
+     */
+    cbTotal = sizeof(PWSTR) + cbServiceName;
     if (ControlPacket->dwArgumentsCount > 0)
-    {
-        lpVector = HeapAlloc(GetProcessHeap(),
-                             HEAP_ZERO_MEMORY,
-                             ControlPacket->dwSize - ControlPacket->dwArgumentsOffset);
-        if (lpVector == NULL)
-            return ERROR_OUTOFMEMORY;
+        cbArguments = ControlPacket->dwSize - ControlPacket->dwArgumentsOffset;
+    else
+        cbArguments = 0;
+    cbTotal += cbArguments;
+
+    /* Allocate the new argument vector */
+    lpVector = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbTotal);
+    if (lpVector == NULL)
+        return ERROR_NOT_ENOUGH_MEMORY;
 
-        memcpy(lpVector,
-               ((PBYTE)ControlPacket + ControlPacket->dwArgumentsOffset),
-               ControlPacket->dwSize - ControlPacket->dwArgumentsOffset);
+    /*
+     * The first argument is reserved for the service name, which
+     * will be appended to the end of the argument string list.
+     */
+
+    /* Copy the remaining arguments */
+    if (ControlPacket->dwArgumentsCount > 0)
+    {
+        memcpy(&lpVector[1],
+               (PWSTR)((ULONG_PTR)ControlPacket + ControlPacket->dwArgumentsOffset),
+               cbArguments);
 
-        lpArg = lpVector;
         for (i = 0; i < ControlPacket->dwArgumentsCount; i++)
         {
-            *lpArg = (LPWSTR)((ULONG_PTR)lpArg + (ULONG_PTR)*lpArg);
-            lpArg++;
+            lpVector[i + 1] = (PWSTR)((ULONG_PTR)&lpVector[1] + (ULONG_PTR)lpVector[i + 1]);
+            TRACE("Unicode lpVector[%lu] = '%ls'\n", i + 1, lpVector[i + 1]);
         }
-
-        *lpArgCount = ControlPacket->dwArgumentsCount;
-        *lpArgVector = lpVector;
     }
 
+    /* Now copy the service name */
+    lpVector[0] = (PWSTR)((ULONG_PTR)&lpVector[1] + cbArguments);
+    memcpy(lpVector[0], pszServiceName, cbServiceName);
+    TRACE("Unicode lpVector[%lu] = '%ls'\n", 0, lpVector[0]);
+
+    *lpArgCount  = ControlPacket->dwArgumentsCount + 1;
+    *lpArgVector = lpVector;
+
     return ERROR_SUCCESS;
 }
 
@@ -328,71 +372,49 @@ 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;
+    DWORD dwError;
+    NTSTATUS Status;
+    DWORD ArgCount, i;
+    PWSTR *lpVectorW;
+    PSTR  *lpVectorA;
+    UNICODE_STRING UnicodeString;
+    ANSI_STRING AnsiString;
 
     if (ControlPacket == NULL || lpArgCount == NULL || lpArgVector == NULL)
         return ERROR_INVALID_PARAMETER;
 
-    *lpArgCount = 0;
+    *lpArgCount  = 0;
     *lpArgVector = NULL;
 
-    if (ControlPacket->dwArgumentsCount > 0)
-    {
-        dwVectorSize = ControlPacket->dwArgumentsCount * sizeof(LPWSTR);
-
-        lpUnicodeString = (LPWSTR)((PBYTE)ControlPacket +
-                                   ControlPacket->dwArgumentsOffset +
-                                   dwVectorSize);
-        dwUnicodeSize = (ControlPacket->dwSize -
-                         ControlPacket->dwArgumentsOffset -
-                         dwVectorSize) / sizeof(WCHAR);
-
-        dwAnsiSize = WideCharToMultiByte(CP_ACP,
-                                         0,
-                                         lpUnicodeString,
-                                         dwUnicodeSize,
-                                         NULL,
-                                         0,
-                                         NULL,
-                                         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,
-                            lpUnicodeString,
-                            dwUnicodeSize,
-                            lpAnsiString,
-                            dwAnsiSize,
-                            NULL,
-                            NULL);
+    /* Build the UNICODE arguments vector */
+    dwError = ScBuildUnicodeArgsVector(ControlPacket, &ArgCount, &lpVectorW);
+    if (dwError != ERROR_SUCCESS)
+        return dwError;
 
-        for (i = 0; i < ControlPacket->dwArgumentsCount; i++)
+    /* Convert the vector to ANSI in place */
+    lpVectorA = (PSTR*)lpVectorW;
+    for (i = 0; i < ArgCount; i++)
+    {
+        RtlInitUnicodeString(&UnicodeString, lpVectorW[i]);
+        RtlInitEmptyAnsiString(&AnsiString, lpVectorA[i], UnicodeString.MaximumLength);
+        Status = RtlUnicodeStringToAnsiString(&AnsiString, &UnicodeString, FALSE);
+        if (!NT_SUCCESS(Status))
         {
-            *lpPtr = lpAnsiString;
-
-            lpPtr++;
-            lpAnsiString += (strlen(lpAnsiString) + 1);
+            /* Failed to convert to ANSI; free the allocated vector and return */
+            dwError = RtlNtStatusToDosError(Status);
+            HeapFree(GetProcessHeap(), 0, lpVectorW);
+            return dwError;
         }
 
-        *lpArgCount = ControlPacket->dwArgumentsCount;
-        *lpArgVector = lpVector;
+        /* NULL-terminate the string */
+        AnsiString.Buffer[AnsiString.Length / sizeof(CHAR)] = ANSI_NULL;
+
+        TRACE("Ansi lpVector[%lu] = '%s'\n", i, lpVectorA[i]);
     }
 
+    *lpArgCount  = ArgCount;
+    *lpArgVector = lpVectorA;
+
     return ERROR_SUCCESS;
 }
 
@@ -404,6 +426,8 @@ ScStartService(PACTIVE_SERVICE lpService,
     HANDLE ThreadHandle;
     DWORD ThreadId;
     DWORD dwError;
+    PSERVICE_THREAD_PARAMSA ThreadParamsA;
+    PSERVICE_THREAD_PARAMSW ThreadParamsW;
 
     if (lpService == NULL || ControlPacket == NULL)
         return ERROR_INVALID_PARAMETER;
@@ -416,56 +440,67 @@ ScStartService(PACTIVE_SERVICE lpService,
     lpService->hServiceStatus = ControlPacket->hServiceStatus;
 
     /* Build the arguments vector */
-    if (lpService->bUnicode == TRUE)
+    if (lpService->bUnicode != FALSE)
     {
+        ThreadParamsW = HeapAlloc(GetProcessHeap(), 0, sizeof(*ThreadParamsW));
+        if (ThreadParamsW == NULL)
+            return ERROR_NOT_ENOUGH_MEMORY;
         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,
-                                0,
-                                ScServiceMainStub,
-                                lpService,
-                                CREATE_SUSPENDED,
-                                &ThreadId);
-    if (ThreadHandle == NULL)
-    {
-        /* Free the arguments vector */
-        if (lpService->bUnicode)
+                                           &ThreadParamsW->dwArgCount,
+                                           &ThreadParamsW->lpArgVector);
+        if (dwError != ERROR_SUCCESS)
         {
-            if (lpService->ThreadParams.W.lpArgVector != NULL)
+            HeapFree(GetProcessHeap(), 0, ThreadParamsW);
+            return dwError;
+        }
+        ThreadParamsW->lpServiceMain = lpService->ServiceMain.W;
+        ThreadHandle = CreateThread(NULL,
+                                    0,
+                                    ScServiceMainStubW,
+                                    ThreadParamsW,
+                                    CREATE_SUSPENDED,
+                                    &ThreadId);
+        if (ThreadHandle == NULL)
+        {
+            if (ThreadParamsW->lpArgVector != NULL)
             {
                 HeapFree(GetProcessHeap(),
                          0,
-                         lpService->ThreadParams.W.lpArgVector);
-                lpService->ThreadParams.W.lpArgVector = NULL;
-                lpService->ThreadParams.W.dwArgCount = 0;
+                         ThreadParamsW->lpArgVector);
             }
+            HeapFree(GetProcessHeap(), 0, ThreadParamsW);
         }
-        else
+    }
+    else
+    {
+        ThreadParamsA = HeapAlloc(GetProcessHeap(), 0, sizeof(*ThreadParamsA));
+        if (ThreadParamsA == NULL)
+            return ERROR_NOT_ENOUGH_MEMORY;
+        dwError = ScBuildAnsiArgsVector(ControlPacket,
+                                        &ThreadParamsA->dwArgCount,
+                                        &ThreadParamsA->lpArgVector);
+        if (dwError != ERROR_SUCCESS)
         {
-            if (lpService->ThreadParams.A.lpArgVector != NULL)
+            HeapFree(GetProcessHeap(), 0, ThreadParamsA);
+            return dwError;
+        }
+        ThreadParamsA->lpServiceMain = lpService->ServiceMain.A;
+        ThreadHandle = CreateThread(NULL,
+                                    0,
+                                    ScServiceMainStubA,
+                                    ThreadParamsA,
+                                    CREATE_SUSPENDED,
+                                    &ThreadId);
+        if (ThreadHandle == NULL)
+        {
+            if (ThreadParamsA->lpArgVector != NULL)
             {
                 HeapFree(GetProcessHeap(),
                          0,
-                         lpService->ThreadParams.A.lpArgVector);
-                lpService->ThreadParams.A.lpArgVector = NULL;
-                lpService->ThreadParams.A.dwArgCount = 0;
+                         ThreadParamsA->lpArgVector);
             }
+            HeapFree(GetProcessHeap(), 0, ThreadParamsA);
         }
-
-        return ERROR_SERVICE_NO_THREAD;
     }
 
     ResumeThread(ThreadHandle);
@@ -479,26 +514,31 @@ static DWORD
 ScControlService(PACTIVE_SERVICE lpService,
                  PSCM_CONTROL_PACKET ControlPacket)
 {
+    DWORD dwError;
+
     if (lpService == NULL || ControlPacket == NULL)
         return ERROR_INVALID_PARAMETER;
 
-    TRACE("ScControlService() called\n");
-    TRACE("Size: %lu\n", ControlPacket->dwSize);
-    TRACE("Service: %S\n", (PWSTR)((PBYTE)ControlPacket + ControlPacket->dwServiceNameOffset));
+    TRACE("ScControlService(Size: %lu, Service: '%S') called\n",
+          ControlPacket->dwSize,
+          (PWSTR)((ULONG_PTR)ControlPacket + ControlPacket->dwServiceNameOffset));
 
     if (lpService->HandlerFunction)
     {
         (lpService->HandlerFunction)(ControlPacket->dwControl);
+        dwError = ERROR_SUCCESS;
     }
     else if (lpService->HandlerFunctionEx)
     {
-        /* FIXME: send correct params */
-        (lpService->HandlerFunctionEx)(ControlPacket->dwControl, 0, NULL, NULL);
+        /* FIXME: Send correct 2nd and 3rd parameters */
+        dwError = (lpService->HandlerFunctionEx)(ControlPacket->dwControl,
+                                                 0, NULL,
+                                                 lpService->HandlerContext);
     }
 
-    TRACE("ScControlService() done\n");
+    TRACE("ScControlService() done (error %lu)\n", dwError);
 
-    return ERROR_SUCCESS;
+    return dwError;
 }
 
 
@@ -509,7 +549,7 @@ ScServiceDispatcher(HANDLE hPipe,
 {
     DWORD Count;
     BOOL bResult;
-    DWORD dwRunningServices = 0;
+    BOOL bRunning = TRUE;
     LPWSTR lpServiceName;
     PACTIVE_SERVICE lpService;
     SCM_REPLY_PACKET ReplyPacket;
@@ -520,7 +560,7 @@ ScServiceDispatcher(HANDLE hPipe,
     if (ControlPacket == NULL || dwBufferSize < sizeof(SCM_CONTROL_PACKET))
         return FALSE;
 
-    while (TRUE)
+    while (bRunning)
     {
         /* Read command from the control pipe */
         bResult = ReadFile(hPipe,
@@ -537,39 +577,44 @@ ScServiceDispatcher(HANDLE hPipe,
         lpServiceName = (LPWSTR)((PBYTE)ControlPacket + ControlPacket->dwServiceNameOffset);
         TRACE("Service: %S\n", lpServiceName);
 
-        if (ControlPacket->dwControl == SERVICE_CONTROL_START_OWN)
-            lpActiveServices[0].bOwnProcess = TRUE;
-
-        lpService = ScLookupServiceByServiceName(lpServiceName);
-        if (lpService != NULL)
+        if (lpServiceName[0] == UNICODE_NULL)
         {
-            /* Execute command */
-            switch (ControlPacket->dwControl)
-            {
-                case SERVICE_CONTROL_START_SHARE:
-                case SERVICE_CONTROL_START_OWN:
-                    TRACE("Start command - recieved SERVICE_CONTROL_START\n");
-                    dwError = ScStartService(lpService, ControlPacket);
-                    if (dwError == ERROR_SUCCESS)
-                        dwRunningServices++;
-                    break;
-
-                case SERVICE_CONTROL_STOP:
-                    TRACE("Stop command - recieved SERVICE_CONTROL_STOP\n");
-                    dwError = ScControlService(lpService, ControlPacket);
-                    if (dwError == ERROR_SUCCESS)
-                        dwRunningServices--;
-                    break;
-
-                default:
-                    TRACE("Command %lu received", ControlPacket->dwControl);
-                    dwError = ScControlService(lpService, ControlPacket);
-                    break;
-            }
+            ERR("Stop dispatcher thread\n");
+            bRunning = FALSE;
+            dwError = ERROR_SUCCESS;
         }
         else
         {
-            dwError = ERROR_SERVICE_DOES_NOT_EXIST;
+            if (ControlPacket->dwControl == SERVICE_CONTROL_START_OWN)
+                lpActiveServices[0].bOwnProcess = TRUE;
+
+            lpService = ScLookupServiceByServiceName(lpServiceName);
+            if (lpService != NULL)
+            {
+                /* Execute command */
+                switch (ControlPacket->dwControl)
+                {
+                    case SERVICE_CONTROL_START_SHARE:
+                    case SERVICE_CONTROL_START_OWN:
+                        TRACE("Start command - received SERVICE_CONTROL_START\n");
+                        dwError = ScStartService(lpService, ControlPacket);
+                        break;
+
+                    case SERVICE_CONTROL_STOP:
+                        TRACE("Stop command - received SERVICE_CONTROL_STOP\n");
+                        dwError = ScControlService(lpService, ControlPacket);
+                        break;
+
+                    default:
+                        TRACE("Command %lu received", ControlPacket->dwControl);
+                        dwError = ScControlService(lpService, ControlPacket);
+                        break;
+                }
+            }
+            else
+            {
+                dwError = ERROR_SERVICE_DOES_NOT_EXIST;
+            }
         }
 
         ReplyPacket.dwError = dwError;
@@ -585,9 +630,6 @@ ScServiceDispatcher(HANDLE hPipe,
             ERR("Pipe write failed (Error: %lu)\n", GetLastError());
             return FALSE;
         }
-
-        if (dwRunningServices == 0)
-            break;
     }
 
     return TRUE;
@@ -708,6 +750,48 @@ RegisterServiceCtrlHandlerExW(LPCWSTR lpServiceName,
 }
 
 
+/**********************************************************************
+ *     I_ScIsSecurityProcess
+ *
+ * Undocumented
+ *
+ * @unimplemented
+ */
+VOID
+WINAPI
+I_ScIsSecurityProcess(VOID)
+{
+}
+
+
+/**********************************************************************
+ *     I_ScPnPGetServiceName
+ *
+ * Undocumented
+ *
+ * @implemented
+ */
+DWORD
+WINAPI
+I_ScPnPGetServiceName(IN SERVICE_STATUS_HANDLE hServiceStatus,
+                      OUT LPWSTR lpServiceName,
+                      IN DWORD cchServiceName)
+{
+    DWORD i;
+
+    for (i = 0; i < dwActiveServiceCount; i++)
+    {
+        if (lpActiveServices[i].hServiceStatus == hServiceStatus)
+        {
+            wcscpy(lpServiceName, lpActiveServices[i].ServiceName.Buffer);
+            return ERROR_SUCCESS;
+        }
+    }
+
+    return ERROR_SERVICE_NOT_IN_EXE;
+}
+
+
 /**********************************************************************
  *     I_ScSetServiceBitsA
  *
@@ -875,7 +959,7 @@ StartServiceCtrlDispatcherA(const SERVICE_TABLE_ENTRYA *lpServiceStartTable)
     {
         RtlCreateUnicodeStringFromAsciiz(&lpActiveServices[i].ServiceName,
                                          lpServiceStartTable[i].lpServiceName);
-        lpActiveServices[i].ThreadParams.A.lpServiceMain = lpServiceStartTable[i].lpServiceProc;
+        lpActiveServices[i].ServiceMain.A = lpServiceStartTable[i].lpServiceProc;
         lpActiveServices[i].hServiceStatus = 0;
         lpActiveServices[i].bUnicode = FALSE;
         lpActiveServices[i].bOwnProcess = FALSE;
@@ -962,7 +1046,7 @@ StartServiceCtrlDispatcherW(const SERVICE_TABLE_ENTRYW *lpServiceStartTable)
     {
         RtlCreateUnicodeString(&lpActiveServices[i].ServiceName,
                                lpServiceStartTable[i].lpServiceName);
-        lpActiveServices[i].ThreadParams.W.lpServiceMain = lpServiceStartTable[i].lpServiceProc;
+        lpActiveServices[i].ServiceMain.W = lpServiceStartTable[i].lpServiceProc;
         lpActiveServices[i].hServiceStatus = 0;
         lpActiveServices[i].bUnicode = TRUE;
         lpActiveServices[i].bOwnProcess = FALSE;