diff --git a/programs/services/rpc.c b/programs/services/rpc.c index 2337667e28d..0de183a5a72 100644 --- a/programs/services/rpc.c +++ b/programs/services/rpc.c @@ -1062,6 +1062,11 @@ DWORD __cdecl svcctl_ControlService( break; } + if (result==ERROR_SUCCESS && !service->service_entry->control_mutex) { + result = ERROR_SERVICE_CANNOT_ACCEPT_CTRL; + service_terminate(service->service_entry); + } + if (result != ERROR_SUCCESS) { if (lpServiceStatus) diff --git a/programs/services/services.c b/programs/services/services.c index 865cb55e606..86d4d8ca704 100644 --- a/programs/services/services.c +++ b/programs/services/services.c @@ -847,22 +847,7 @@ DWORD service_start(struct service_entry *service, DWORD service_argc, LPCWSTR * if (err == ERROR_SUCCESS) ReleaseMutex(service->control_mutex); else - { - CloseHandle(service->overlapped_event); - service->overlapped_event = NULL; - CloseHandle(service->status_changed_event); - service->status_changed_event = NULL; - CloseHandle(service->control_mutex); - service->control_mutex = NULL; - if (service->control_pipe != INVALID_HANDLE_VALUE) - CloseHandle(service->control_pipe); - service->control_pipe = INVALID_HANDLE_VALUE; - - service->status.dwProcessId = 0; - service_lock_exclusive(service); - service->status.dwCurrentState = SERVICE_STOPPED; - service_unlock(service); - } + service_terminate(service); scmdatabase_unlock_startup(service->db); WINE_TRACE("returning %d\n", err); @@ -870,6 +855,26 @@ DWORD service_start(struct service_entry *service, DWORD service_argc, LPCWSTR * return err; } +void service_terminate(struct service_entry *service) +{ + service_lock_exclusive(service); + TerminateProcess(service->process, 0); + CloseHandle(service->process); + service->process = NULL; + CloseHandle(service->overlapped_event); + service->overlapped_event = NULL; + CloseHandle(service->status_changed_event); + service->status_changed_event = NULL; + CloseHandle(service->control_mutex); + service->control_mutex = NULL; + CloseHandle(service->control_pipe); + service->control_pipe = INVALID_HANDLE_VALUE; + + service->status.dwProcessId = 0; + service->status.dwCurrentState = SERVICE_STOPPED; + service_unlock(service); +} + static void load_registry_parameters(void) { static const WCHAR controlW[] = diff --git a/programs/services/services.h b/programs/services/services.h index 6a968d9168c..b4b895eaf38 100644 --- a/programs/services/services.h +++ b/programs/services/services.h @@ -78,6 +78,7 @@ void service_lock_shared(struct service_entry *service); void service_lock_exclusive(struct service_entry *service); void service_unlock(struct service_entry *service); DWORD service_start(struct service_entry *service, DWORD service_argc, LPCWSTR *service_argv); +void service_terminate(struct service_entry *service); BOOL service_send_command( struct service_entry *service, HANDLE pipe, const void *data, DWORD size, DWORD *result );