services: Hold a reference to process in svcctl_ControlService.

Signed-off-by: Sebastian Lackner <sebastian@fds-team.de>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Sebastian Lackner 2016-04-18 17:08:37 +02:00 committed by Alexandre Julliard
parent 4f3f502886
commit 168af6e750
3 changed files with 18 additions and 5 deletions

View File

@ -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;
}

View File

@ -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)

View File

@ -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);