[ADVAPI32]
[reactos.git] / reactos / dll / win32 / advapi32 / service / sctrl.c
index 9511d6c..90810bc 100644 (file)
 /* INCLUDES ******************************************************************/
 
 #include <advapi32.h>
+#include "wine/debug.h"
 
-#define NDEBUG
-#include <debug.h>
+WINE_DEFAULT_DEBUG_CHANNEL(advapi);
 
 
 /* TYPES *********************************************************************/
 
-VOID HandleBind(VOID);
-
 typedef struct _ACTIVE_SERVICE
 {
-    CLIENT_HANDLE hService;
+    SERVICE_STATUS_HANDLE hServiceStatus;
     UNICODE_STRING ServiceName;
     union
     {
@@ -34,7 +32,6 @@ typedef struct _ACTIVE_SERVICE
     LPHANDLER_FUNCTION HandlerFunction;
     LPHANDLER_FUNCTION_EX HandlerFunctionEx;
     LPVOID HandlerContext;
-    SERVICE_STATUS ServiceStatus;
     BOOL bUnicode;
     LPWSTR Arguments;
 } ACTIVE_SERVICE, *PACTIVE_SERVICE;
@@ -42,13 +39,89 @@ typedef struct _ACTIVE_SERVICE
 
 /* GLOBALS *******************************************************************/
 
-extern handle_t BindingHandle;
 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)
 {
@@ -79,19 +152,19 @@ ScServiceMainStub(LPVOID Context)
 
     lpService = (PACTIVE_SERVICE)Context;
 
-    DPRINT("ScServiceMainStub() called\n");
+    TRACE("ScServiceMainStub() called\n");
 
     /* Count arguments */
     lpPtr = lpService->Arguments;
     while (*lpPtr)
     {
-        DPRINT("arg: %S\n", lpPtr);
+        TRACE("arg: %S\n", lpPtr);
         dwLen = wcslen(lpPtr) + 1;
         dwArgCount++;
         dwLength += dwLen;
         lpPtr += dwLen;
     }
-    DPRINT("dwArgCount: %ld\ndwLength: %ld\n", dwArgCount, dwLength);
+    TRACE("dwArgCount: %ld\ndwLength: %ld\n", dwArgCount, dwLength);
 
     /* Build the argument vector and call the main service routine */
     if (lpService->bUnicode)
@@ -202,6 +275,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,
@@ -219,7 +293,7 @@ ScConnectControlPipe(HANDLE *hPipe)
 
     if (!NT_SUCCESS(Status))
     {
-        DPRINT1("RtlQueryRegistryValues() failed (Status %lx)\n", Status);
+        ERR("RtlQueryRegistryValues() failed (Status %lx)\n", Status);
         return RtlNtStatusToDosError(Status);
     }
 
@@ -227,7 +301,7 @@ ScConnectControlPipe(HANDLE *hPipe)
 
     if (!WaitNamedPipeW(NtControlPipeName, 15000))
     {
-        DPRINT1("WaitNamedPipe(%S) failed (Error %lu)\n", NtControlPipeName, GetLastError());
+        ERR("WaitNamedPipe(%S) failed (Error %lu)\n", NtControlPipeName, GetLastError());
         return ERROR_FAILED_SERVICE_CONTROLLER_CONNECT;
     }
 
@@ -240,53 +314,49 @@ ScConnectControlPipe(HANDLE *hPipe)
                          NULL);
     if (*hPipe == INVALID_HANDLE_VALUE)
     {
-        DPRINT1("CreateFileW() failed (Error %lu)\n", GetLastError());
+        ERR("CreateFileW() failed for pipe %S (Error %lu)\n", NtControlPipeName, GetLastError());
         return ERROR_FAILED_SERVICE_CONTROLLER_CONNECT;
     }
 
     dwState = PIPE_READMODE_MESSAGE;
     if (!SetNamedPipeHandleState(*hPipe, &dwState, NULL, NULL))
     {
-        CloseHandle(hPipe);
+        CloseHandle(*hPipe);
         *hPipe = INVALID_HANDLE_VALUE;
         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);
 
-    DPRINT("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;
 
-    DPRINT("ScStartService() called\n");
-    DPRINT("client handle: %lu\n", ControlPacket->hClient);
-    DPRINT("Size: %lu\n", ControlPacket->dwSize);
-    DPRINT("Service: %S\n", &ControlPacket->szArguments[0]);
+    TRACE("ScStartService() called\n");
+    TRACE("Size: %lu\n", ControlPacket->dwSize);
+    TRACE("Service: %S\n", &ControlPacket->szArguments[0]);
 
-    lpService = (PACTIVE_SERVICE)ControlPacket->hClient;
-    if (lpService == NULL)
-    {
-        DPRINT1("Service not found\n");
-        return ERROR_SERVICE_DOES_NOT_EXIST;
-    }
+    /* Set the service status handle */
+    lpService->hServiceStatus = ControlPacket->hServiceStatus;
 
     lpService->Arguments = HeapAlloc(GetProcessHeap(),
                                      HEAP_ZERO_MEMORY,
-                                     ControlPacket->dwSize * sizeof(WCHAR));
+                                     (ControlPacket->dwSize + 1) * sizeof(WCHAR));
     if (lpService->Arguments == NULL)
         return ERROR_OUTOFMEMORY;
 
@@ -312,20 +382,12 @@ ScStartService(PSCM_CONTROL_PACKET ControlPacket)
 
 
 static DWORD
-ScControlService(PSCM_CONTROL_PACKET ControlPacket)
+ScControlService(PACTIVE_SERVICE lpService,
+                 PSCM_CONTROL_PACKET ControlPacket)
 {
-    PACTIVE_SERVICE lpService;
-
-    DPRINT("ScControlService() called\n");
-    DPRINT("Size: %lu\n", ControlPacket->dwSize);
-    DPRINT("Service: %S\n", &ControlPacket->szArguments[0]);
-
-    lpService = (PACTIVE_SERVICE)ControlPacket->hClient;
-    if (lpService == NULL)
-    {
-        DPRINT1("Service not found\n");
-        return ERROR_SERVICE_DOES_NOT_EXIST;
-    }
+    TRACE("ScControlService() called\n");
+    TRACE("Size: %lu\n", ControlPacket->dwSize);
+    TRACE("Service: %S\n", &ControlPacket->szArguments[0]);
 
     if (lpService->HandlerFunction)
     {
@@ -344,7 +406,7 @@ ScControlService(PSCM_CONTROL_PACKET ControlPacket)
                  lpService->Arguments);
     }
 
-    DPRINT("ScControlService() done\n");
+    TRACE("ScControlService() done\n");
 
     return ERROR_SUCCESS;
 }
@@ -359,8 +421,12 @@ ScServiceDispatcher(HANDLE hPipe,
     DWORD Count;
     BOOL bResult;
     DWORD dwRunningServices = 0;
+    LPWSTR lpServiceName;
+    PACTIVE_SERVICE lpService;
+    SCM_REPLY_PACKET ReplyPacket;
+    DWORD dwError;
 
-    DPRINT("ScDispatcherLoop() called\n");
+    TRACE("ScDispatcherLoop() called\n");
 
     ControlPacket = HeapAlloc(GetProcessHeap(),
                               HEAP_ZERO_MEMORY,
@@ -378,28 +444,56 @@ ScServiceDispatcher(HANDLE hPipe,
                            NULL);
         if (bResult == FALSE)
         {
-            DPRINT1("Pipe read failed (Error: %lu)\n", GetLastError());
+            ERR("Pipe read failed (Error: %lu)\n", GetLastError());
             return FALSE;
         }
 
-        /* Execute command */
-        switch (ControlPacket->dwControl)
+        lpServiceName = &ControlPacket->szArguments[0];
+        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
+        {
+            dwError = ERROR_SERVICE_DOES_NOT_EXIST;
+        }
+
+        ReplyPacket.dwError = dwError;
+
+        /* Send the reply packet */
+        bResult = WriteFile(hPipe,
+                            &ReplyPacket,
+                            sizeof(ReplyPacket),
+                            &Count,
+                            NULL);
+        if (bResult == FALSE)
         {
-            case SERVICE_CONTROL_START:
-                DPRINT("Start command - recieved SERVICE_CONTROL_START\n");
-                if (ScStartService(ControlPacket) == ERROR_SUCCESS)
-                    dwRunningServices++;
-                break;
-
-            case SERVICE_CONTROL_STOP:
-                DPRINT("Stop command - recieved SERVICE_CONTROL_STOP\n");
-                if (ScControlService(ControlPacket) == ERROR_SUCCESS)
-                    dwRunningServices--;
-                break;
-
-            default:
-                DPRINT("Unknown command %lu", ControlPacket->dwControl);
-                continue;
+            ERR("Pipe write failed (Error: %lu)\n", GetLastError());
+            return FALSE;
         }
 
         if (dwRunningServices == 0)
@@ -419,7 +513,7 @@ ScServiceDispatcher(HANDLE hPipe,
  *
  * @implemented
  */
-SERVICE_STATUS_HANDLE STDCALL
+SERVICE_STATUS_HANDLE WINAPI
 RegisterServiceCtrlHandlerA(LPCSTR lpServiceName,
                             LPHANDLER_FUNCTION lpHandlerProc)
 {
@@ -448,7 +542,7 @@ RegisterServiceCtrlHandlerA(LPCSTR lpServiceName,
  *
  * @implemented
  */
-SERVICE_STATUS_HANDLE STDCALL
+SERVICE_STATUS_HANDLE WINAPI
 RegisterServiceCtrlHandlerW(LPCWSTR lpServiceName,
                             LPHANDLER_FUNCTION lpHandlerProc)
 {
@@ -463,9 +557,9 @@ RegisterServiceCtrlHandlerW(LPCWSTR lpServiceName,
     Service->HandlerFunction = lpHandlerProc;
     Service->HandlerFunctionEx = NULL;
 
-    DPRINT("RegisterServiceCtrlHandler returning %lu\n", Service->hService);
+    TRACE("RegisterServiceCtrlHandler returning %lu\n", Service->hServiceStatus);
 
-    return (SERVICE_STATUS_HANDLE)Service->hService;
+    return Service->hServiceStatus;
 }
 
 
@@ -474,7 +568,7 @@ RegisterServiceCtrlHandlerW(LPCWSTR lpServiceName,
  *
  * @implemented
  */
-SERVICE_STATUS_HANDLE STDCALL
+SERVICE_STATUS_HANDLE WINAPI
 RegisterServiceCtrlHandlerExA(LPCSTR lpServiceName,
                               LPHANDLER_FUNCTION_EX lpHandlerProc,
                               LPVOID lpContext)
@@ -505,7 +599,7 @@ RegisterServiceCtrlHandlerExA(LPCSTR lpServiceName,
  *
  * @implemented
  */
-SERVICE_STATUS_HANDLE STDCALL
+SERVICE_STATUS_HANDLE WINAPI
 RegisterServiceCtrlHandlerExW(LPCWSTR lpServiceName,
                               LPHANDLER_FUNCTION_EX lpHandlerProc,
                               LPVOID lpContext)
@@ -522,25 +616,100 @@ RegisterServiceCtrlHandlerExW(LPCWSTR lpServiceName,
     Service->HandlerFunctionEx = lpHandlerProc;
     Service->HandlerContext = lpContext;
 
-    DPRINT("RegisterServiceCtrlHandlerEx returning %lu", Service->hService);
+    TRACE("RegisterServiceCtrlHandlerEx returning %lu\n", Service->hServiceStatus);
 
-    return (SERVICE_STATUS_HANDLE)Service->hService;
+    return Service->hServiceStatus;
+}
+
+
+/**********************************************************************
+ *     I_ScSetServiceBitsA
+ *
+ * Undocumented
+ *
+ * @implemented
+ */
+BOOL WINAPI
+I_ScSetServiceBitsA(SERVICE_STATUS_HANDLE hServiceStatus,
+                    DWORD dwServiceBits,
+                    BOOL bSetBitsOn,
+                    BOOL bUpdateImmediately,
+                    LPSTR lpString)
+{
+    BOOL bResult;
+
+    RpcTryExcept
+    {
+        /* Call to services.exe using RPC */
+        bResult = RI_ScSetServiceBitsA((RPC_SERVICE_STATUS_HANDLE)hServiceStatus,
+                                       dwServiceBits,
+                                       bSetBitsOn,
+                                       bUpdateImmediately,
+                                       lpString);
+    }
+    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
+    {
+        SetLastError(ScmRpcStatusToWinError(RpcExceptionCode()));
+        bResult = FALSE;
+    }
+    RpcEndExcept;
+
+    return bResult;
+}
+
+
+/**********************************************************************
+ *     I_ScSetServiceBitsW
+ *
+ * Undocumented
+ *
+ * @implemented
+ */
+BOOL WINAPI
+I_ScSetServiceBitsW(SERVICE_STATUS_HANDLE hServiceStatus,
+                    DWORD dwServiceBits,
+                    BOOL bSetBitsOn,
+                    BOOL bUpdateImmediately,
+                    LPWSTR lpString)
+{
+    BOOL bResult;
+
+    RpcTryExcept
+    {
+        /* Call to services.exe using RPC */
+        bResult = RI_ScSetServiceBitsW((RPC_SERVICE_STATUS_HANDLE)hServiceStatus,
+                                       dwServiceBits,
+                                       bSetBitsOn,
+                                       bUpdateImmediately,
+                                       lpString);
+    }
+    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
+    {
+        SetLastError(ScmRpcStatusToWinError(RpcExceptionCode()));
+        bResult = FALSE;
+    }
+    RpcEndExcept;
+
+    return bResult;
 }
 
 
 /**********************************************************************
  *     SetServiceBits
  *
- * @unimplemented
+ * @implemented
  */
-BOOL STDCALL
+BOOL WINAPI
 SetServiceBits(SERVICE_STATUS_HANDLE hServiceStatus,
                DWORD dwServiceBits,
                BOOL bSetBitsOn,
                BOOL bUpdateImmediately)
 {
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return FALSE;
+    return I_ScSetServiceBitsW(hServiceStatus,
+                               dwServiceBits,
+                               bSetBitsOn,
+                               bUpdateImmediately,
+                               NULL);
 }
 
 
@@ -549,29 +718,35 @@ SetServiceBits(SERVICE_STATUS_HANDLE hServiceStatus,
  *
  * @implemented
  */
-BOOL STDCALL
+BOOL WINAPI
 SetServiceStatus(SERVICE_STATUS_HANDLE hServiceStatus,
                  LPSERVICE_STATUS lpServiceStatus)
 {
     DWORD dwError;
 
-    DPRINT("SetServiceStatus() called\n");
-    DPRINT("hServiceStatus %lu\n", hServiceStatus);
+    TRACE("SetServiceStatus() called\n");
+    TRACE("hServiceStatus %lu\n", hServiceStatus);
 
-    HandleBind();
+    RpcTryExcept
+    {
+        /* Call to services.exe using RPC */
+        dwError = RSetServiceStatus((RPC_SERVICE_STATUS_HANDLE)hServiceStatus,
+                                    lpServiceStatus);
+    }
+    RpcExcept(EXCEPTION_EXECUTE_HANDLER)
+    {
+        dwError = ScmRpcStatusToWinError(RpcExceptionCode());
+    }
+    RpcEndExcept;
 
-    /* Call to services.exe using RPC */
-    dwError = ScmrSetServiceStatus(BindingHandle,
-                                   (unsigned long)hServiceStatus,
-                                   lpServiceStatus);
     if (dwError != ERROR_SUCCESS)
     {
-        DPRINT1("ScmrSetServiceStatus() failed (Error %lu)\n", dwError);
+        ERR("ScmrSetServiceStatus() failed (Error %lu)\n", dwError);
         SetLastError(dwError);
         return FALSE;
     }
 
-    DPRINT("SetServiceStatus() done (ret %lu)\n", dwError);
+    TRACE("SetServiceStatus() done (ret %lu)\n", dwError);
 
     return TRUE;
 }
@@ -582,15 +757,15 @@ SetServiceStatus(SERVICE_STATUS_HANDLE hServiceStatus,
  *
  * @implemented
  */
-BOOL STDCALL
-StartServiceCtrlDispatcherA(LPSERVICE_TABLE_ENTRYA lpServiceStartTable)
+BOOL WINAPI
+StartServiceCtrlDispatcherA(const SERVICE_TABLE_ENTRYA * lpServiceStartTable)
 {
     ULONG i;
     HANDLE hPipe;
     DWORD dwError;
     PUCHAR lpMessageBuffer;
 
-    DPRINT("StartServiceCtrlDispatcherA() called\n");
+    TRACE("StartServiceCtrlDispatcherA() called\n");
 
     i = 0;
     while (lpServiceStartTable[i].lpServiceProc != NULL)
@@ -613,7 +788,7 @@ StartServiceCtrlDispatcherA(LPSERVICE_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].hServiceStatus = 0;
         lpActiveServices[i].bUnicode = FALSE;
     }
 
@@ -621,6 +796,10 @@ StartServiceCtrlDispatcherA(LPSERVICE_TABLE_ENTRYA lpServiceStartTable)
     if (dwError != ERROR_SUCCESS)
     {
         /* Free the service table */
+        for (i = 0; i < dwActiveServiceCount; i++)
+        {
+            RtlFreeUnicodeString(&lpActiveServices[i].ServiceName);
+        }
         RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices);
         lpActiveServices = NULL;
         dwActiveServiceCount = 0;
@@ -633,6 +812,10 @@ StartServiceCtrlDispatcherA(LPSERVICE_TABLE_ENTRYA lpServiceStartTable)
     if (lpMessageBuffer == NULL)
     {
         /* Free the service table */
+        for (i = 0; i < dwActiveServiceCount; i++)
+        {
+            RtlFreeUnicodeString(&lpActiveServices[i].ServiceName);
+        }
         RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices);
         lpActiveServices = NULL;
         dwActiveServiceCount = 0;
@@ -640,13 +823,22 @@ StartServiceCtrlDispatcherA(LPSERVICE_TABLE_ENTRYA lpServiceStartTable)
         return FALSE;
     }
 
+    ScCreateStatusBinding();
+
     ScServiceDispatcher(hPipe, lpMessageBuffer, 256);
+
+    ScDestroyStatusBinding();
+
     CloseHandle(hPipe);
 
     /* Free the message buffer */
     RtlFreeHeap(RtlGetProcessHeap(), 0, lpMessageBuffer);
 
     /* Free the service table */
+    for (i = 0; i < dwActiveServiceCount; i++)
+    {
+        RtlFreeUnicodeString(&lpActiveServices[i].ServiceName);
+    }
     RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices);
     lpActiveServices = NULL;
     dwActiveServiceCount = 0;
@@ -660,15 +852,15 @@ StartServiceCtrlDispatcherA(LPSERVICE_TABLE_ENTRYA lpServiceStartTable)
  *
  * @implemented
  */
-BOOL STDCALL
-StartServiceCtrlDispatcherW(LPSERVICE_TABLE_ENTRYW lpServiceStartTable)
+BOOL WINAPI
+StartServiceCtrlDispatcherW(const SERVICE_TABLE_ENTRYW * lpServiceStartTable)
 {
     ULONG i;
     HANDLE hPipe;
     DWORD dwError;
     PUCHAR lpMessageBuffer;
 
-    DPRINT("StartServiceCtrlDispatcherW() called\n");
+    TRACE("StartServiceCtrlDispatcherW() called\n");
 
     i = 0;
     while (lpServiceStartTable[i].lpServiceProc != NULL)
@@ -691,7 +883,7 @@ StartServiceCtrlDispatcherW(LPSERVICE_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].hServiceStatus = 0;
         lpActiveServices[i].bUnicode = TRUE;
     }
 
@@ -699,6 +891,10 @@ StartServiceCtrlDispatcherW(LPSERVICE_TABLE_ENTRYW lpServiceStartTable)
     if (dwError != ERROR_SUCCESS)
     {
         /* Free the service table */
+        for (i = 0; i < dwActiveServiceCount; i++)
+        {
+            RtlFreeUnicodeString(&lpActiveServices[i].ServiceName);
+        }
         RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices);
         lpActiveServices = NULL;
         dwActiveServiceCount = 0;
@@ -711,6 +907,10 @@ StartServiceCtrlDispatcherW(LPSERVICE_TABLE_ENTRYW lpServiceStartTable)
     if (lpMessageBuffer == NULL)
     {
         /* Free the service table */
+        for (i = 0; i < dwActiveServiceCount; i++)
+        {
+            RtlFreeUnicodeString(&lpActiveServices[i].ServiceName);
+        }
         RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices);
         lpActiveServices = NULL;
         dwActiveServiceCount = 0;
@@ -718,13 +918,22 @@ StartServiceCtrlDispatcherW(LPSERVICE_TABLE_ENTRYW lpServiceStartTable)
         return FALSE;
     }
 
+    ScCreateStatusBinding();
+
     ScServiceDispatcher(hPipe, lpMessageBuffer, 256);
+
+    ScDestroyStatusBinding();
+
     CloseHandle(hPipe);
 
     /* Free the message buffer */
     RtlFreeHeap(RtlGetProcessHeap(), 0, lpMessageBuffer);
 
     /* Free the service table */
+    for (i = 0; i < dwActiveServiceCount; i++)
+    {
+        RtlFreeUnicodeString(&lpActiveServices[i].ServiceName);
+    }
     RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices);
     lpActiveServices = NULL;
     dwActiveServiceCount = 0;