Commit 37097ce9 authored by Sebastian Lackner's avatar Sebastian Lackner Committed by Alexandre Julliard

services: Track services and processes separately.

parent 50ab36ac
...@@ -100,23 +100,22 @@ struct timeout_queue_elem ...@@ -100,23 +100,22 @@ struct timeout_queue_elem
struct list entry; struct list entry;
FILETIME time; FILETIME time;
void (*func)(struct service_entry*); void (*func)(struct process_entry *);
struct service_entry *service_entry; struct process_entry *process;
}; };
static void run_after_timeout(void (*func)(struct service_entry*), struct service_entry *service, DWORD timeout) static void run_after_timeout(void (*func)(struct process_entry *), struct process_entry *process, DWORD timeout)
{ {
struct timeout_queue_elem *elem = HeapAlloc(GetProcessHeap(), 0, sizeof(struct timeout_queue_elem)); struct timeout_queue_elem *elem = HeapAlloc(GetProcessHeap(), 0, sizeof(struct timeout_queue_elem));
ULARGE_INTEGER time; ULARGE_INTEGER time;
if(!elem) { if(!elem) {
func(service); func(process);
return; return;
} }
InterlockedIncrement(&service->ref_count);
elem->func = func; elem->func = func;
elem->service_entry = service; elem->process = grab_process(process);
GetSystemTimeAsFileTime(&elem->time); GetSystemTimeAsFileTime(&elem->time);
time.u.LowPart = elem->time.dwLowDateTime; time.u.LowPart = elem->time.dwLowDateTime;
...@@ -751,6 +750,7 @@ DWORD __cdecl svcctl_SetServiceStatus( ...@@ -751,6 +750,7 @@ DWORD __cdecl svcctl_SetServiceStatus(
LPSERVICE_STATUS lpServiceStatus) LPSERVICE_STATUS lpServiceStatus)
{ {
struct sc_service_handle *service; struct sc_service_handle *service;
struct process_entry *process;
DWORD err; DWORD err;
WINE_TRACE("(%p, %p)\n", hServiceStatus, lpServiceStatus); WINE_TRACE("(%p, %p)\n", hServiceStatus, lpServiceStatus);
...@@ -768,13 +768,15 @@ DWORD __cdecl svcctl_SetServiceStatus( ...@@ -768,13 +768,15 @@ DWORD __cdecl svcctl_SetServiceStatus(
service->service_entry->status.dwServiceSpecificExitCode = lpServiceStatus->dwServiceSpecificExitCode; service->service_entry->status.dwServiceSpecificExitCode = lpServiceStatus->dwServiceSpecificExitCode;
service->service_entry->status.dwCheckPoint = lpServiceStatus->dwCheckPoint; service->service_entry->status.dwCheckPoint = lpServiceStatus->dwCheckPoint;
service->service_entry->status.dwWaitHint = lpServiceStatus->dwWaitHint; service->service_entry->status.dwWaitHint = lpServiceStatus->dwWaitHint;
if ((process = service->service_entry->process))
{
if (lpServiceStatus->dwCurrentState == SERVICE_STOPPED)
run_after_timeout(process_terminate, process, service_kill_timeout);
else
SetEvent(process->status_changed_event);
}
service_unlock(service->service_entry); service_unlock(service->service_entry);
if (lpServiceStatus->dwCurrentState == SERVICE_STOPPED)
run_after_timeout(service_terminate, service->service_entry, service_kill_timeout);
else if (service->service_entry->process->status_changed_event)
SetEvent(service->service_entry->process->status_changed_event);
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
...@@ -1173,6 +1175,9 @@ DWORD __cdecl svcctl_ControlService( ...@@ -1173,6 +1175,9 @@ DWORD __cdecl svcctl_ControlService(
process = grab_process(service->service_entry->process); process = grab_process(service->service_entry->process);
service_unlock(service->service_entry); service_unlock(service->service_entry);
if (!process)
return ERROR_SERVICE_CANNOT_ACCEPT_CTRL;
ret = WaitForSingleObject(process->control_mutex, 30000); ret = WaitForSingleObject(process->control_mutex, 30000);
if (ret != WAIT_OBJECT_0) if (ret != WAIT_OBJECT_0)
{ {
...@@ -1930,7 +1935,7 @@ DWORD events_loop(void) ...@@ -1930,7 +1935,7 @@ DWORD events_loop(void)
WINE_TRACE("Exceeded maximum wait object count\n"); WINE_TRACE("Exceeded maximum wait object count\n");
break; break;
} }
wait_handles[num_handles] = iter->service_entry->process->process; wait_handles[num_handles] = iter->process->process;
num_handles++; num_handles++;
} }
LeaveCriticalSection(&timeout_queue_cs); LeaveCriticalSection(&timeout_queue_cs);
...@@ -1956,10 +1961,10 @@ DWORD events_loop(void) ...@@ -1956,10 +1961,10 @@ DWORD events_loop(void)
(err > WAIT_OBJECT_0 + 1 && idx == err - WAIT_OBJECT_0 - 2)) (err > WAIT_OBJECT_0 + 1 && idx == err - WAIT_OBJECT_0 - 2))
{ {
LeaveCriticalSection(&timeout_queue_cs); LeaveCriticalSection(&timeout_queue_cs);
iter->func(iter->service_entry); iter->func(iter->process);
EnterCriticalSection(&timeout_queue_cs); EnterCriticalSection(&timeout_queue_cs);
release_service(iter->service_entry); release_process(iter->process);
list_remove(&iter->entry); list_remove(&iter->entry);
HeapFree(GetProcessHeap(), 0, iter); HeapFree(GetProcessHeap(), 0, iter);
} }
...@@ -1988,10 +1993,10 @@ DWORD events_loop(void) ...@@ -1988,10 +1993,10 @@ DWORD events_loop(void)
LIST_FOR_EACH_ENTRY_SAFE(iter, iter_safe, &timeout_queue, struct timeout_queue_elem, entry) LIST_FOR_EACH_ENTRY_SAFE(iter, iter_safe, &timeout_queue, struct timeout_queue_elem, entry)
{ {
LeaveCriticalSection(&timeout_queue_cs); LeaveCriticalSection(&timeout_queue_cs);
iter->func(iter->service_entry); iter->func(iter->process);
EnterCriticalSection(&timeout_queue_cs); EnterCriticalSection(&timeout_queue_cs);
release_service(iter->service_entry); release_process(iter->process);
list_remove(&iter->entry); list_remove(&iter->entry);
HeapFree(GetProcessHeap(), 0, iter); HeapFree(GetProcessHeap(), 0, iter);
} }
......
...@@ -27,12 +27,15 @@ struct scmdatabase ...@@ -27,12 +27,15 @@ struct scmdatabase
{ {
HKEY root_key; HKEY root_key;
LONG service_start_lock; LONG service_start_lock;
struct list processes;
struct list services; struct list services;
CRITICAL_SECTION cs; CRITICAL_SECTION cs;
}; };
struct process_entry struct process_entry
{ {
struct list entry;
struct scmdatabase *db;
LONG ref_count; LONG ref_count;
HANDLE process; HANDLE process;
HANDLE control_mutex; HANDLE control_mutex;
...@@ -91,6 +94,7 @@ void service_terminate(struct service_entry *service); ...@@ -91,6 +94,7 @@ void service_terminate(struct service_entry *service);
struct process_entry *grab_process(struct process_entry *process); struct process_entry *grab_process(struct process_entry *process);
void release_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); BOOL process_send_command(struct process_entry *process, const void *data, DWORD size, DWORD *result);
void process_terminate(struct process_entry *process);
extern HANDLE g_hStartedEvent; extern HANDLE g_hStartedEvent;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment