[Wine-patches] [eterhack] advapi32: Do not terminate a regular program if it calls StartServiceCtrlDispatcher (eterbug #7573).

Alexander Morozov amorozov на etersoft.ru
Вт Апр 17 17:23:24 MSK 2012


---
 dlls/advapi32/service.c |   87 ++++++++++++++++++++++++++++++++---------------
 1 file changed, 60 insertions(+), 27 deletions(-)

diff --git a/dlls/advapi32/service.c b/dlls/advapi32/service.c
index 39abcc7..dc3b140 100644
--- a/dlls/advapi32/service.c
+++ b/dlls/advapi32/service.c
@@ -71,6 +71,12 @@ typedef struct service_data_t
     WCHAR name[1];
 } service_data;
 
+typedef struct dispatcher_data_t
+{
+    SC_HANDLE manager;
+    HANDLE pipe;
+} dispatcher_data;
+
 static CRITICAL_SECTION service_cs;
 static CRITICAL_SECTION_DEBUG service_cs_debug =
 {
@@ -378,22 +384,7 @@ static DWORD service_handle_control(const service_data *service, DWORD dwControl
  */
 static DWORD WINAPI service_control_dispatcher(LPVOID arg)
 {
-    SC_HANDLE manager;
-    HANDLE pipe;
-
-    if (!(manager = OpenSCManagerW( NULL, NULL, SC_MANAGER_CONNECT )))
-    {
-        ERR("failed to open service manager error %u\n", GetLastError());
-        return 0;
-    }
-
-    pipe = service_open_pipe();
-
-    if (pipe==INVALID_HANDLE_VALUE)
-    {
-        WARN("failed to create control pipe error = %d\n", GetLastError());
-        return 0;
-    }
+    dispatcher_data *disp = arg;
 
     /* dispatcher loop */
     while (1)
@@ -404,7 +395,7 @@ static DWORD WINAPI service_control_dispatcher(LPVOID arg)
         BOOL r;
         DWORD data_size = 0, count, result;
 
-        r = ReadFile( pipe, &info, FIELD_OFFSET(service_start_info,data), &count, NULL );
+        r = ReadFile( disp->pipe, &info, FIELD_OFFSET(service_start_info,data), &count, NULL );
         if (!r)
         {
             if (GetLastError() != ERROR_BROKEN_PIPE)
@@ -420,7 +411,7 @@ static DWORD WINAPI service_control_dispatcher(LPVOID arg)
         {
             data_size = info.total_size - FIELD_OFFSET(service_start_info,data);
             data = HeapAlloc( GetProcessHeap(), 0, data_size );
-            r = ReadFile( pipe, data, data_size, &count, NULL );
+            r = ReadFile( disp->pipe, data, data_size, &count, NULL );
             if (!r)
             {
                 if (GetLastError() != ERROR_BROKEN_PIPE)
@@ -451,8 +442,9 @@ static DWORD WINAPI service_control_dispatcher(LPVOID arg)
         case WINESERV_STARTINFO:
             if (!service->handle)
             {
-                if (!(service->handle = OpenServiceW( manager, data, SERVICE_SET_STATUS )) ||
-                    !(service->full_access_handle = OpenServiceW( manager, data, GENERIC_READ|GENERIC_WRITE )))
+                if (!(service->handle = OpenServiceW( disp->manager, data, SERVICE_SET_STATUS )) ||
+                    !(service->full_access_handle = OpenServiceW( disp->manager, data,
+                            GENERIC_READ|GENERIC_WRITE )))
                     TRACE( "failed to open service %s\n", debugstr_w(data) );
             }
             result = service_handle_start(service, data + info.name_size,
@@ -468,19 +460,20 @@ static DWORD WINAPI service_control_dispatcher(LPVOID arg)
         }
 
     done:
-        WriteFile(pipe, &result, sizeof(result), &count, NULL);
+        WriteFile( disp->pipe, &result, sizeof(result), &count, NULL );
         HeapFree( GetProcessHeap(), 0, data );
     }
 
-    CloseHandle(pipe);
-    CloseServiceHandle( manager );
+    CloseHandle( disp->pipe );
+    CloseServiceHandle( disp->manager );
+    HeapFree( GetProcessHeap(), 0, disp );
     return 1;
 }
 
 /******************************************************************************
  * service_run_main_thread
  */
-static BOOL service_run_main_thread(void)
+static BOOL service_run_main_thread( dispatcher_data *disp )
 {
     DWORD i, n, ret;
     HANDLE wait_handles[MAXIMUM_WAIT_OBJECTS];
@@ -490,7 +483,7 @@ static BOOL service_run_main_thread(void)
 
     /* FIXME: service_control_dispatcher should be merged into the main thread */
     wait_handles[0] = __wine_make_process_system();
-    wait_handles[1] = CreateThread( NULL, 0, service_control_dispatcher, NULL, 0, NULL );
+    wait_handles[1] = CreateThread( NULL, 0, service_control_dispatcher, disp, 0, NULL );
     wait_handles[2] = service_event;
 
     TRACE("Starting %d services running as process %d\n",
@@ -576,6 +569,7 @@ static BOOL service_run_main_thread(void)
 BOOL WINAPI StartServiceCtrlDispatcherA( const SERVICE_TABLE_ENTRYA *servent )
 {
     service_data *info;
+    dispatcher_data *disp;
     unsigned int i;
     BOOL ret = TRUE;
 
@@ -600,7 +594,26 @@ BOOL WINAPI StartServiceCtrlDispatcherA( const SERVICE_TABLE_ENTRYA *servent )
         services[i] = info;
     }
 
-    service_run_main_thread();
+    disp = HeapAlloc( GetProcessHeap(), 0, sizeof(*disp) );
+
+    if (!(disp->manager = OpenSCManagerW( NULL, NULL, SC_MANAGER_CONNECT )))
+    {
+        ERR("failed to open service manager error %u\n", GetLastError());
+        HeapFree( GetProcessHeap(), 0, disp );
+        return FALSE;
+    }
+
+    disp->pipe = service_open_pipe();
+    if (disp->pipe == INVALID_HANDLE_VALUE)
+    {
+        WARN("failed to create control pipe error %u\n", GetLastError());
+        CloseServiceHandle( disp->manager );
+        HeapFree( GetProcessHeap(), 0, disp );
+        SetLastError( ERROR_FAILED_SERVICE_CONTROLLER_CONNECT );
+        return FALSE;
+    }
+
+    service_run_main_thread( disp );
 
     return ret;
 }
@@ -621,6 +634,7 @@ BOOL WINAPI StartServiceCtrlDispatcherA( const SERVICE_TABLE_ENTRYA *servent )
 BOOL WINAPI StartServiceCtrlDispatcherW( const SERVICE_TABLE_ENTRYW *servent )
 {
     service_data *info;
+    dispatcher_data *disp;
     unsigned int i;
     BOOL ret = TRUE;
 
@@ -645,7 +659,26 @@ BOOL WINAPI StartServiceCtrlDispatcherW( const SERVICE_TABLE_ENTRYW *servent )
         services[i] = info;
     }
 
-    service_run_main_thread();
+    disp = HeapAlloc( GetProcessHeap(), 0, sizeof(*disp) );
+
+    if (!(disp->manager = OpenSCManagerW( NULL, NULL, SC_MANAGER_CONNECT )))
+    {
+        ERR("failed to open service manager error %u\n", GetLastError());
+        HeapFree( GetProcessHeap(), 0, disp );
+        return FALSE;
+    }
+
+    disp->pipe = service_open_pipe();
+    if (disp->pipe == INVALID_HANDLE_VALUE)
+    {
+        WARN("failed to create control pipe error %u\n", GetLastError());
+        CloseServiceHandle( disp->manager );
+        HeapFree( GetProcessHeap(), 0, disp );
+        SetLastError( ERROR_FAILED_SERVICE_CONTROLLER_CONNECT );
+        return FALSE;
+    }
+
+    service_run_main_thread( disp );
 
     return ret;
 }
-- 
1.7.9.4



Подробная информация о списке рассылки Wine-patches