[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