[SERVICES/ADVAPI32]
[reactos.git] / reactos / dll / win32 / advapi32 / service / sctrl.c
index f1e5ede..53a9aef 100644 (file)
 /* INCLUDES ******************************************************************/
 
 #include <advapi32.h>
-#include "wine/debug.h"
-
 WINE_DEFAULT_DEBUG_CHANNEL(advapi);
 
 
 /* TYPES *********************************************************************/
 
+typedef struct _SERVICE_THREAD_PARAMSA
+{
+    LPSERVICE_MAIN_FUNCTIONA lpServiceMain;
+    DWORD dwArgCount;
+    LPSTR *lpArgVector;
+} SERVICE_THREAD_PARAMSA, *PSERVICE_THREAD_PARAMSA;
+
+
+typedef struct _SERVICE_THREAD_PARAMSW
+{
+    LPSERVICE_MAIN_FUNCTIONW lpServiceMain;
+    DWORD dwArgCount;
+    LPWSTR *lpArgVector;
+} SERVICE_THREAD_PARAMSW, *PSERVICE_THREAD_PARAMSW;
+
+
 typedef struct _ACTIVE_SERVICE
 {
-    CLIENT_HANDLE hService;
+    SERVICE_STATUS_HANDLE hServiceStatus;
     UNICODE_STRING ServiceName;
     union
     {
-        LPSERVICE_MAIN_FUNCTIONA lpFuncA;
-        LPSERVICE_MAIN_FUNCTIONW lpFuncW;
-    } Main;
+        SERVICE_THREAD_PARAMSA A;
+        SERVICE_THREAD_PARAMSW W;
+    } ThreadParams;
     LPHANDLER_FUNCTION HandlerFunction;
     LPHANDLER_FUNCTION_EX HandlerFunctionEx;
     LPVOID HandlerContext;
-    SERVICE_STATUS ServiceStatus;
     BOOL bUnicode;
-    LPWSTR Arguments;
 } ACTIVE_SERVICE, *PACTIVE_SERVICE;
 
 
@@ -42,23 +54,106 @@ typedef struct _ACTIVE_SERVICE
 
 static DWORD dwActiveServiceCount = 0;
 static PACTIVE_SERVICE lpActiveServices = NULL;
+static handle_t hStatusBinding = NULL;
 
 
 /* FUNCTIONS *****************************************************************/
 
+handle_t __RPC_USER
+RPC_SERVICE_STATUS_HANDLE_bind(RPC_SERVICE_STATUS_HANDLE hServiceStatus)
+{
+    return hStatusBinding;
+}
+
+
+void __RPC_USER
+RPC_SERVICE_STATUS_HANDLE_unbind(RPC_SERVICE_STATUS_HANDLE hServiceStatus,
+                                 handle_t hBinding)
+{
+}
+
+
+static RPC_STATUS
+ScCreateStatusBinding(VOID)
+{
+    LPWSTR pszStringBinding;
+    RPC_STATUS status;
+
+    TRACE("ScCreateStatusBinding() called\n");
+
+    status = RpcStringBindingComposeW(NULL,
+                                      L"ncacn_np",
+                                      NULL,
+                                      L"\\pipe\\ntsvcs",
+                                      NULL,
+                                      &pszStringBinding);
+    if (status != RPC_S_OK)
+    {
+        ERR("RpcStringBindingCompose returned 0x%x\n", status);
+        return status;
+    }
+
+    /* Set the binding handle that will be used to bind to the server. */
+    status = RpcBindingFromStringBindingW(pszStringBinding,
+                                          &hStatusBinding);
+    if (status != RPC_S_OK)
+    {
+        ERR("RpcBindingFromStringBinding returned 0x%x\n", status);
+    }
+
+    status = RpcStringFreeW(&pszStringBinding);
+    if (status != RPC_S_OK)
+    {
+        ERR("RpcStringFree returned 0x%x\n", status);
+    }
+
+    return status;
+}
+
+
+static RPC_STATUS
+ScDestroyStatusBinding(VOID)
+{
+    RPC_STATUS status;
+
+    TRACE("ScDestroyStatusBinding() called\n");
+
+    if (hStatusBinding == NULL)
+        return RPC_S_OK;
+
+    status = RpcBindingFree(&hStatusBinding);
+    if (status != RPC_S_OK)
+    {
+        ERR("RpcBindingFree returned 0x%x\n", status);
+    }
+    else
+    {
+        hStatusBinding = NULL;
+    }
+
+    return status;
+}
+
+
 static PACTIVE_SERVICE
 ScLookupServiceByServiceName(LPCWSTR lpServiceName)
 {
     DWORD i;
 
+    TRACE("ScLookupServiceByServiceName(%S) called\n", lpServiceName);
+
     for (i = 0; i < dwActiveServiceCount; i++)
     {
+        TRACE("Checking %S\n", lpActiveServices[i].ServiceName.Buffer);
         if (_wcsicmp(lpActiveServices[i].ServiceName.Buffer, lpServiceName) == 0)
         {
+            TRACE("Found!\n");
             return &lpActiveServices[i];
         }
     }
 
+    TRACE("No service found!\n");
+
     SetLastError(ERROR_SERVICE_DOES_NOT_EXIST);
 
     return NULL;
@@ -68,122 +163,40 @@ ScLookupServiceByServiceName(LPCWSTR lpServiceName)
 static DWORD WINAPI
 ScServiceMainStub(LPVOID Context)
 {
-    PACTIVE_SERVICE lpService;
-    DWORD dwArgCount = 0;
-    DWORD dwLength = 0;
-    DWORD dwLen;
-    LPWSTR lpPtr;
-
-    lpService = (PACTIVE_SERVICE)Context;
+    PACTIVE_SERVICE lpService = (PACTIVE_SERVICE)Context;
 
     TRACE("ScServiceMainStub() called\n");
 
-    /* Count arguments */
-    lpPtr = lpService->Arguments;
-    while (*lpPtr)
-    {
-        TRACE("arg: %S\n", lpPtr);
-        dwLen = wcslen(lpPtr) + 1;
-        dwArgCount++;
-        dwLength += dwLen;
-        lpPtr += dwLen;
-    }
-    TRACE("dwArgCount: %ld\ndwLength: %ld\n", dwArgCount, dwLength);
-
-    /* Build the argument vector and call the main service routine */
+    /* Call the main service routine and free the arguments vector */
     if (lpService->bUnicode)
     {
-        LPWSTR *lpArgVector;
-        LPWSTR Ptr;
+        (lpService->ThreadParams.W.lpServiceMain)(lpService->ThreadParams.W.dwArgCount,
+                                                  lpService->ThreadParams.W.lpArgVector);
 
-        lpArgVector = HeapAlloc(GetProcessHeap(),
-                                HEAP_ZERO_MEMORY,
-                                (dwArgCount + 1) * sizeof(LPWSTR));
-        if (lpArgVector == NULL)
-            return ERROR_OUTOFMEMORY;
-
-        dwArgCount = 0;
-        Ptr = lpService->Arguments;
-        while (*Ptr)
+        if (lpService->ThreadParams.A.lpArgVector != NULL)
         {
-            lpArgVector[dwArgCount] = Ptr;
+            HeapFree(GetProcessHeap(),
+                     0,
+                     lpService->ThreadParams.W.lpArgVector);
 
-            dwArgCount++;
-            Ptr += (wcslen(Ptr) + 1);
+            lpService->ThreadParams.W.lpArgVector = NULL;
+            lpService->ThreadParams.W.dwArgCount = 0;
         }
-        lpArgVector[dwArgCount] = NULL;
-
-        (lpService->Main.lpFuncW)(dwArgCount, lpArgVector);
-
-        HeapFree(GetProcessHeap(),
-                 0,
-                 lpArgVector);
     }
     else
     {
-        LPSTR *lpArgVector;
-        LPSTR Ptr;
-        LPSTR AnsiString;
-        DWORD AnsiLength;
-
-        AnsiLength = WideCharToMultiByte(CP_ACP,
-                                         0,
-                                         lpService->Arguments,
-                                         dwLength,
-                                         NULL,
-                                         0,
-                                         NULL,
-                                         NULL);
-        if (AnsiLength == 0)
-            return ERROR_INVALID_PARAMETER; /* ? */
+        (lpService->ThreadParams.A.lpServiceMain)(lpService->ThreadParams.A.dwArgCount,
+                                                  lpService->ThreadParams.A.lpArgVector);
 
-        AnsiString = HeapAlloc(GetProcessHeap(),
-                               0,
-                               AnsiLength + 1);
-        if (AnsiString == NULL)
-            return ERROR_OUTOFMEMORY;
-
-        WideCharToMultiByte(CP_ACP,
-                            0,
-                            lpService->Arguments,
-                            dwLength,
-                            AnsiString,
-                            AnsiLength,
-                            NULL,
-                            NULL);
-
-        AnsiString[AnsiLength] = ANSI_NULL;
-
-        lpArgVector = HeapAlloc(GetProcessHeap(),
-                                0,
-                                (dwArgCount + 1) * sizeof(LPSTR));
-        if (lpArgVector == NULL)
+        if (lpService->ThreadParams.A.lpArgVector != NULL)
         {
             HeapFree(GetProcessHeap(),
-                        0,
-                        AnsiString);
-            return ERROR_OUTOFMEMORY;
-        }
+                     0,
+                     lpService->ThreadParams.A.lpArgVector);
 
-        dwArgCount = 0;
-        Ptr = AnsiString;
-        while (*Ptr)
-        {
-            lpArgVector[dwArgCount] = Ptr;
-
-            dwArgCount++;
-            Ptr += (strlen(Ptr) + 1);
+            lpService->ThreadParams.A.lpArgVector = NULL;
+            lpService->ThreadParams.A.dwArgCount = 0;
         }
-        lpArgVector[dwArgCount] = NULL;
-
-        (lpService->Main.lpFuncA)(dwArgCount, lpArgVector);
-
-        HeapFree(GetProcessHeap(),
-                 0,
-                 lpArgVector);
-        HeapFree(GetProcessHeap(),
-                 0,
-                 AnsiString);
     }
 
     return ERROR_SUCCESS;
@@ -199,6 +212,7 @@ ScConnectControlPipe(HANDLE *hPipe)
     NTSTATUS Status;
     WCHAR NtControlPipeName[MAX_PATH + 1];
     RTL_QUERY_REGISTRY_TABLE QueryTable[2];
+    DWORD dwProcessId;
 
     /* Get the service number and create the named pipe */
     RtlZeroMemory(&QueryTable,
@@ -249,49 +263,136 @@ ScConnectControlPipe(HANDLE *hPipe)
         return ERROR_FAILED_SERVICE_CONTROLLER_CONNECT;
     }
 
-    /* Share the SERVICE_HANDLE handle with the SCM */
+    /* Pass the ProcessId to the SCM */
+    dwProcessId = GetCurrentProcessId();
     WriteFile(*hPipe,
-              (DWORD *)&lpActiveServices->hService,
-              sizeof(CLIENT_HANDLE),
+              &dwProcessId,
+              sizeof(DWORD),
               &dwBytesWritten,
               NULL);
 
-    TRACE("Sent SERVICE_HANDLE %lu\n", lpActiveServices->hService);
+    TRACE("Sent Process ID %lu\n", dwProcessId);
 
     return ERROR_SUCCESS;
 }
 
 
 static DWORD
-ScStartService(PSCM_CONTROL_PACKET ControlPacket)
+ScStartService(PACTIVE_SERVICE lpService,
+               PSCM_CONTROL_PACKET ControlPacket)
 {
-    PACTIVE_SERVICE lpService;
     HANDLE ThreadHandle;
     DWORD ThreadId;
+    LPWSTR *lpArgW;
+    DWORD i;
 
     TRACE("ScStartService() called\n");
-    TRACE("client handle: %lu\n", ControlPacket->hClient);
     TRACE("Size: %lu\n", ControlPacket->dwSize);
-    TRACE("Service: %S\n", &ControlPacket->szArguments[0]);
+    TRACE("Service: %S\n", (PWSTR)((PBYTE)ControlPacket + ControlPacket->dwServiceNameOffset));
+
+    /* Set the service status handle */
+    lpService->hServiceStatus = ControlPacket->hServiceStatus;
 
-    lpService = (PACTIVE_SERVICE)(ULONG_PTR)ControlPacket->hClient;
-    if (lpService == NULL)
+    if (lpService->bUnicode == TRUE)
     {
-        TRACE("Service not found\n");
-        return ERROR_SERVICE_DOES_NOT_EXIST;
+        lpService->ThreadParams.W.dwArgCount = ControlPacket->dwArgumentsCount;
+        lpService->ThreadParams.W.lpArgVector = NULL;
+
+        if (ControlPacket->dwArgumentsOffset > 0)
+        {
+            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++;
+            }
+        }
     }
+    else
+    {
+        /* FIXME */
+        lpService->ThreadParams.A.dwArgCount = 0;
+        lpService->ThreadParams.A.lpArgVector = NULL;
+
+#if 0
+        LPSTR *lpArgVector;
+        LPSTR Ptr;
+        LPSTR AnsiString;
+        DWORD AnsiLength;
+
+        AnsiLength = WideCharToMultiByte(CP_ACP,
+                                         0,
+                                         lpService->Arguments,
+                                         dwLength,
+                                         NULL,
+                                         0,
+                                         NULL,
+                                         NULL);
+        if (AnsiLength == 0)
+            return ERROR_INVALID_PARAMETER; /* ? */
+
+        AnsiString = HeapAlloc(GetProcessHeap(),
+                               0,
+                               AnsiLength + 1);
+        if (AnsiString == NULL)
+            return ERROR_OUTOFMEMORY;
 
-    lpService->Arguments = HeapAlloc(GetProcessHeap(),
-                                     HEAP_ZERO_MEMORY,
-                                     (ControlPacket->dwSize + 1) * sizeof(WCHAR));
-    if (lpService->Arguments == NULL)
-        return ERROR_OUTOFMEMORY;
+        WideCharToMultiByte(CP_ACP,
+                            0,
+                            lpService->Arguments,
+                            dwLength,
+                            AnsiString,
+                            AnsiLength,
+                            NULL,
+                            NULL);
+
+        AnsiString[AnsiLength] = ANSI_NULL;
+
+        lpArgVector = HeapAlloc(GetProcessHeap(),
+                                0,
+                                (dwArgCount + 1) * sizeof(LPSTR));
+        if (lpArgVector == NULL)
+        {
+            HeapFree(GetProcessHeap(),
+                        0,
+                        AnsiString);
+            return ERROR_OUTOFMEMORY;
+        }
 
-    memcpy(lpService->Arguments,
-           ControlPacket->szArguments,
-           ControlPacket->dwSize * sizeof(WCHAR));
+        dwArgCount = 0;
+        Ptr = AnsiString;
+        while (*Ptr)
+        {
+            lpArgVector[dwArgCount] = Ptr;
 
-    /* invoke the services entry point and implement the command loop */
+            dwArgCount++;
+            Ptr += (strlen(Ptr) + 1);
+        }
+        lpArgVector[dwArgCount] = NULL;
+
+        (lpService->ThreadParams.A.lpServiceMain)(dwArgCount, lpArgVector);
+
+        HeapFree(GetProcessHeap(),
+                 0,
+                 lpArgVector);
+        HeapFree(GetProcessHeap(),
+                 0,
+                 AnsiString);
+#endif
+    }
+
+    /* Invoke the services entry point and implement the command loop */
     ThreadHandle = CreateThread(NULL,
                                 0,
                                 ScServiceMainStub,
@@ -299,7 +400,33 @@ ScStartService(PSCM_CONTROL_PACKET ControlPacket)
                                 CREATE_SUSPENDED,
                                 &ThreadId);
     if (ThreadHandle == NULL)
+    {
+        /* Free the arguments vector */
+        if (lpService->bUnicode)
+        {
+            if (lpService->ThreadParams.W.lpArgVector != NULL)
+            {
+                HeapFree(GetProcessHeap(),
+                         0,
+                         lpService->ThreadParams.W.lpArgVector);
+                lpService->ThreadParams.W.lpArgVector = NULL;
+                lpService->ThreadParams.W.dwArgCount = 0;
+            }
+        }
+        else
+        {
+            if (lpService->ThreadParams.A.lpArgVector != NULL)
+            {
+                HeapFree(GetProcessHeap(),
+                         0,
+                         lpService->ThreadParams.A.lpArgVector);
+                lpService->ThreadParams.A.lpArgVector = NULL;
+                lpService->ThreadParams.A.dwArgCount = 0;
+            }
+        }
+
         return ERROR_SERVICE_NO_THREAD;
+    }
 
     ResumeThread(ThreadHandle);
     CloseHandle(ThreadHandle);
@@ -309,20 +436,12 @@ ScStartService(PSCM_CONTROL_PACKET ControlPacket)
 
 
 static DWORD
-ScControlService(PSCM_CONTROL_PACKET ControlPacket)
+ScControlService(PACTIVE_SERVICE lpService,
+                 PSCM_CONTROL_PACKET ControlPacket)
 {
-    PACTIVE_SERVICE lpService;
-
     TRACE("ScControlService() called\n");
     TRACE("Size: %lu\n", ControlPacket->dwSize);
-    TRACE("Service: %S\n", &ControlPacket->szArguments[0]);
-
-    lpService = (PACTIVE_SERVICE)(ULONG_PTR)ControlPacket->hClient;
-    if (lpService == NULL)
-    {
-        TRACE("Service not found\n");
-        return ERROR_SERVICE_DOES_NOT_EXIST;
-    }
+    TRACE("Service: %S\n", (PWSTR)((PBYTE)ControlPacket + ControlPacket->dwServiceNameOffset));
 
     if (lpService->HandlerFunction)
     {
@@ -334,13 +453,6 @@ ScControlService(PSCM_CONTROL_PACKET ControlPacket)
         (lpService->HandlerFunctionEx)(ControlPacket->dwControl, 0, NULL, NULL);
     }
 
-    if (ControlPacket->dwControl == SERVICE_CONTROL_STOP)
-    {
-        HeapFree(GetProcessHeap(),
-                 0,
-                 lpService->Arguments);
-    }
-
     TRACE("ScControlService() done\n");
 
     return ERROR_SUCCESS;
@@ -356,6 +468,10 @@ ScServiceDispatcher(HANDLE hPipe,
     DWORD Count;
     BOOL bResult;
     DWORD dwRunningServices = 0;
+    LPWSTR lpServiceName;
+    PACTIVE_SERVICE lpService;
+    SCM_REPLY_PACKET ReplyPacket;
+    DWORD dwError;
 
     TRACE("ScDispatcherLoop() called\n");
 
@@ -379,25 +495,52 @@ ScServiceDispatcher(HANDLE hPipe,
             return FALSE;
         }
 
-        /* Execute command */
-        switch (ControlPacket->dwControl)
+        lpServiceName = (LPWSTR)((PBYTE)ControlPacket + ControlPacket->dwServiceNameOffset);
+        TRACE("Service: %S\n", lpServiceName);
+
+        lpService = ScLookupServiceByServiceName(lpServiceName);
+        if (lpService != NULL)
+        {
+            /* Execute command */
+            switch (ControlPacket->dwControl)
+            {
+                case SERVICE_CONTROL_START:
+                    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;
+            }
+        }
+        else
         {
-            case SERVICE_CONTROL_START:
-                TRACE("Start command - recieved SERVICE_CONTROL_START\n");
-                if (ScStartService(ControlPacket) == ERROR_SUCCESS)
-                    dwRunningServices++;
-                break;
-
-            case SERVICE_CONTROL_STOP:
-                TRACE("Stop command - recieved SERVICE_CONTROL_STOP\n");
-                if (ScControlService(ControlPacket) == ERROR_SUCCESS)
-                    dwRunningServices--;
-                break;
-
-            default:
-                TRACE("Command %lu received", ControlPacket->dwControl);
-                ScControlService(ControlPacket);
-                continue;
+            dwError = ERROR_SERVICE_DOES_NOT_EXIST;
+        }
+
+        ReplyPacket.dwError = dwError;
+
+        /* Send the reply packet */
+        bResult = WriteFile(hPipe,
+                            &ReplyPacket,
+                            sizeof(ReplyPacket),
+                            &Count,
+                            NULL);
+        if (bResult == FALSE)
+        {
+            ERR("Pipe write failed (Error: %lu)\n", GetLastError());
+            return FALSE;
         }
 
         if (dwRunningServices == 0)
@@ -461,9 +604,9 @@ RegisterServiceCtrlHandlerW(LPCWSTR lpServiceName,
     Service->HandlerFunction = lpHandlerProc;
     Service->HandlerFunctionEx = NULL;
 
-    TRACE("RegisterServiceCtrlHandler returning %lu\n", Service->hService);
+    TRACE("RegisterServiceCtrlHandler returning %lu\n", Service->hServiceStatus);
 
-    return (SERVICE_STATUS_HANDLE)Service->hService;
+    return Service->hServiceStatus;
 }
 
 
@@ -520,9 +663,9 @@ RegisterServiceCtrlHandlerExW(LPCWSTR lpServiceName,
     Service->HandlerFunctionEx = lpHandlerProc;
     Service->HandlerContext = lpContext;
 
-    TRACE("RegisterServiceCtrlHandlerEx returning %lu\n", Service->hService);
+    TRACE("RegisterServiceCtrlHandlerEx returning %lu\n", Service->hServiceStatus);
 
-    return (SERVICE_STATUS_HANDLE)Service->hService;
+    return Service->hServiceStatus;
 }
 
 
@@ -631,9 +774,18 @@ SetServiceStatus(SERVICE_STATUS_HANDLE hServiceStatus,
     TRACE("SetServiceStatus() called\n");
     TRACE("hServiceStatus %lu\n", hServiceStatus);
 
-    /* Call to services.exe using RPC */
-    dwError = RSetServiceStatus((RPC_SERVICE_STATUS_HANDLE)hServiceStatus,
-                                lpServiceStatus);
+    RpcTryExcept
+    {
+        /* Call to services.exe using RPC */
+        dwError = RSetServiceStatus((RPC_SERVICE_STATUS_HANDLE)hServiceStatus,
+                                    lpServiceStatus);
+    }
+    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
+    {
+        dwError = ScmRpcStatusToWinError(RpcExceptionCode());
+    }
+    RpcEndExcept;
+
     if (dwError != ERROR_SUCCESS)
     {
         ERR("ScmrSetServiceStatus() failed (Error %lu)\n", dwError);
@@ -682,8 +834,8 @@ StartServiceCtrlDispatcherA(const SERVICE_TABLE_ENTRYA * lpServiceStartTable)
     {
         RtlCreateUnicodeStringFromAsciiz(&lpActiveServices[i].ServiceName,
                                          lpServiceStartTable[i].lpServiceName);
-        lpActiveServices[i].Main.lpFuncA = lpServiceStartTable[i].lpServiceProc;
-        lpActiveServices[i].hService = (CLIENT_HANDLE)&lpActiveServices[i];
+        lpActiveServices[i].ThreadParams.A.lpServiceMain = lpServiceStartTable[i].lpServiceProc;
+        lpActiveServices[i].hServiceStatus = 0;
         lpActiveServices[i].bUnicode = FALSE;
     }
 
@@ -718,7 +870,12 @@ StartServiceCtrlDispatcherA(const SERVICE_TABLE_ENTRYA * lpServiceStartTable)
         return FALSE;
     }
 
+    ScCreateStatusBinding();
+
     ScServiceDispatcher(hPipe, lpMessageBuffer, 256);
+
+    ScDestroyStatusBinding();
+
     CloseHandle(hPipe);
 
     /* Free the message buffer */
@@ -772,8 +929,8 @@ StartServiceCtrlDispatcherW(const SERVICE_TABLE_ENTRYW * lpServiceStartTable)
     {
         RtlCreateUnicodeString(&lpActiveServices[i].ServiceName,
                                lpServiceStartTable[i].lpServiceName);
-        lpActiveServices[i].Main.lpFuncW = lpServiceStartTable[i].lpServiceProc;
-        lpActiveServices[i].hService = (CLIENT_HANDLE)&lpActiveServices[i];
+        lpActiveServices[i].ThreadParams.W.lpServiceMain = lpServiceStartTable[i].lpServiceProc;
+        lpActiveServices[i].hServiceStatus = 0;
         lpActiveServices[i].bUnicode = TRUE;
     }
 
@@ -808,7 +965,12 @@ StartServiceCtrlDispatcherW(const SERVICE_TABLE_ENTRYW * lpServiceStartTable)
         return FALSE;
     }
 
+    ScCreateStatusBinding();
+
     ScServiceDispatcher(hPipe, lpMessageBuffer, 256);
+
+    ScDestroyStatusBinding();
+
     CloseHandle(hPipe);
 
     /* Free the message buffer */