[2/3] services: Hold a reference to process in svcctl_ControlService.

Sebastian Lackner sebastian at fds-team.de
Mon Apr 18 10:08:37 CDT 2016


Signed-off-by: Sebastian Lackner <sebastian at fds-team.de>
---
 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 59bbe7f..babb2b5 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 5be6f5c..234c0ac 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 b8f4774..3d6c486 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);
 
-- 
2.7.1



More information about the wine-patches mailing list