Module: wine Branch: master Commit: a792a5b4867c7cdefb1de7da3ef87bea06b1b3de URL: http://source.winehq.org/git/wine.git/?a=commit;h=a792a5b4867c7cdefb1de7da3e...
Author: Alexander Morozov amorozov@etersoft.ru Date: Mon Apr 1 22:43:33 2013 +0400
advapi32: Do not terminate a regular program if it calls StartServiceCtrlDispatcher.
---
dlls/advapi32/service.c | 70 +++++++++++++++++++++++++--------------------- 1 files changed, 38 insertions(+), 32 deletions(-)
diff --git a/dlls/advapi32/service.c b/dlls/advapi32/service.c index b591449..5f3f15f 100644 --- a/dlls/advapi32/service.c +++ b/dlls/advapi32/service.c @@ -75,6 +75,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 = { @@ -358,22 +364,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) @@ -384,7 +375,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) @@ -400,7 +391,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) @@ -433,8 +424,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 ))) FIXME( "failed to open service %s\n", debugstr_w(data) ); } result = service_handle_start(service, data, data_size / sizeof(WCHAR)); @@ -449,12 +441,13 @@ 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; }
@@ -466,13 +459,32 @@ static BOOL service_run_main_thread(void) DWORD i, n, ret; HANDLE wait_handles[MAXIMUM_WAIT_OBJECTS]; UINT wait_services[MAXIMUM_WAIT_OBJECTS]; + dispatcher_data *disp = HeapAlloc( GetProcessHeap(), 0, sizeof(*disp) ); + + disp->manager = OpenSCManagerW( NULL, NULL, SC_MANAGER_CONNECT ); + if (!disp->manager) + { + 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_event = CreateEventW( NULL, FALSE, FALSE, NULL ); stop_event = CreateEventW( NULL, FALSE, FALSE, NULL );
/* 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; wait_handles[3] = stop_event;
@@ -563,7 +575,6 @@ BOOL WINAPI StartServiceCtrlDispatcherA( const SERVICE_TABLE_ENTRYA *servent ) { service_data *info; unsigned int i; - BOOL ret = TRUE;
TRACE("%p\n", servent);
@@ -592,9 +603,7 @@ BOOL WINAPI StartServiceCtrlDispatcherA( const SERVICE_TABLE_ENTRYA *servent ) services[i] = info; }
- service_run_main_thread(); - - return ret; + return service_run_main_thread(); }
/****************************************************************************** @@ -614,7 +623,6 @@ BOOL WINAPI StartServiceCtrlDispatcherW( const SERVICE_TABLE_ENTRYW *servent ) { service_data *info; unsigned int i; - BOOL ret = TRUE;
TRACE("%p\n", servent);
@@ -643,9 +651,7 @@ BOOL WINAPI StartServiceCtrlDispatcherW( const SERVICE_TABLE_ENTRYW *servent ) services[i] = info; }
- service_run_main_thread(); - - return ret; + return service_run_main_thread(); }
/******************************************************************************