From 168af6e7501202088cd6105ea798f97e145a06fd Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Mon, 18 Apr 2016 17:08:37 +0200 Subject: [PATCH] services: Hold a reference to process in svcctl_ControlService. Signed-off-by: Sebastian Lackner Signed-off-by: Alexandre Julliard --- programs/services/rpc.c | 15 ++++++++++----- programs/services/services.c | 7 +++++++ programs/services/services.h | 1 + 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/programs/services/rpc.c b/programs/services/rpc.c index 59bbe7f66e8..babb2b54846 100644 --- a/programs/services/rpc.c +++ b/programs/services/rpc.c @@ -1086,9 +1086,9 @@ DWORD __cdecl svcctl_ControlService( { DWORD access_required; struct sc_service_handle *service; + struct process_entry *process; DWORD result; BOOL ret; - HANDLE control_mutex; WINE_TRACE("(%p, %d, %p)\n", hService, dwControl, lpServiceStatus); @@ -1169,14 +1169,18 @@ DWORD __cdecl svcctl_ControlService( if (dwControl == SERVICE_CONTROL_STOP) service->service_entry->force_shutdown = TRUE; - control_mutex = service->service_entry->process->control_mutex; + /* Hold a reference to the process while sending the command. */ + process = grab_process(service->service_entry->process); service_unlock(service->service_entry); - ret = WaitForSingleObject(control_mutex, 30000); + ret = WaitForSingleObject(process->control_mutex, 30000); if (ret != WAIT_OBJECT_0) + { + release_process(process); return ERROR_SERVICE_REQUEST_TIMEOUT; + } - process_send_control(service->service_entry->process, service->service_entry->name, dwControl, &result); + process_send_control(process, service->service_entry->name, dwControl, &result); if (lpServiceStatus) { @@ -1191,7 +1195,8 @@ DWORD __cdecl svcctl_ControlService( service_unlock(service->service_entry); } - ReleaseMutex(control_mutex); + ReleaseMutex(process->control_mutex); + release_process(process); return result; } diff --git a/programs/services/services.c b/programs/services/services.c index 5be6f5cc7c1..234c0ac7cbf 100644 --- a/programs/services/services.c +++ b/programs/services/services.c @@ -457,6 +457,13 @@ struct service_entry *scmdatabase_find_service_by_displayname(struct scmdatabase return NULL; } +struct process_entry *grab_process(struct process_entry *process) +{ + if (process) + InterlockedIncrement(&process->ref_count); + return process; +} + void release_process(struct process_entry *process) { if (InterlockedDecrement(&process->ref_count) == 0) diff --git a/programs/services/services.h b/programs/services/services.h index b8f4774be2a..3d6c486c932 100644 --- a/programs/services/services.h +++ b/programs/services/services.h @@ -88,6 +88,7 @@ void service_terminate(struct service_entry *service); /* Process functions */ +struct process_entry *grab_process(struct process_entry *process); void release_process(struct process_entry *process); BOOL process_send_command(struct process_entry *process, const void *data, DWORD size, DWORD *result);