services: Associate notify handle with service handle instead of service entry.
Signed-off-by: Jacek Caban <jacek@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
ac3f571e56
commit
8a2347baff
|
@ -2383,7 +2383,6 @@ static void test_servicenotify(SC_HANDLE scm_handle, const char *servicename)
|
|||
|
||||
/* it's possible to have multiple notifications using different service handles */
|
||||
dr = pNotifyServiceStatusChangeW(svc2, SERVICE_NOTIFY_STOPPED, &data2.notify);
|
||||
todo_wine
|
||||
ok(dr == ERROR_SUCCESS, "NotifyServiceStatusChangeW gave wrong result: %u\n", dr);
|
||||
|
||||
/* stop service and receive notifiction */
|
||||
|
@ -2394,7 +2393,6 @@ static void test_servicenotify(SC_HANDLE scm_handle, const char *servicename)
|
|||
dr2 = SleepEx(100, TRUE);
|
||||
ok(dr == WAIT_IO_COMPLETION || dr2 == WAIT_IO_COMPLETION, "Got wrong SleepEx result: %u\n", dr);
|
||||
ok(data.was_called == TRUE, "APC wasn't called\n");
|
||||
todo_wine
|
||||
ok(data2.was_called == TRUE, "APC wasn't called\n");
|
||||
|
||||
/* test cancelation: create notify on svc that will block until service
|
||||
|
|
|
@ -75,23 +75,24 @@ struct sc_manager_handle /* service control manager handle */
|
|||
struct scmdatabase *db;
|
||||
};
|
||||
|
||||
struct sc_service_handle /* service handle */
|
||||
{
|
||||
struct sc_handle hdr;
|
||||
struct list entry;
|
||||
struct service_entry *service_entry;
|
||||
};
|
||||
|
||||
struct sc_notify_handle
|
||||
{
|
||||
struct sc_handle hdr;
|
||||
struct sc_service_handle *service;
|
||||
HANDLE event;
|
||||
DWORD notify_mask;
|
||||
LONG ref;
|
||||
SC_RPC_NOTIFY_PARAMS_LIST *params_list;
|
||||
};
|
||||
|
||||
struct sc_service_handle /* service handle */
|
||||
{
|
||||
struct sc_handle hdr;
|
||||
struct list entry;
|
||||
BOOL status_notified;
|
||||
struct service_entry *service_entry;
|
||||
struct sc_notify_handle *notify;
|
||||
};
|
||||
|
||||
static void sc_notify_retain(struct sc_notify_handle *notify)
|
||||
{
|
||||
InterlockedIncrement(¬ify->ref);
|
||||
|
@ -313,12 +314,10 @@ static void SC_RPC_HANDLE_destroy(SC_RPC_HANDLE handle)
|
|||
struct sc_service_handle *service = (struct sc_service_handle *)hdr;
|
||||
service_lock(service->service_entry);
|
||||
list_remove(&service->entry);
|
||||
if (service->service_entry->notify &&
|
||||
service->service_entry->notify->service == service)
|
||||
if (service->notify)
|
||||
{
|
||||
SetEvent(service->service_entry->notify->event);
|
||||
sc_notify_release(service->service_entry->notify);
|
||||
service->service_entry->notify = NULL;
|
||||
SetEvent(service->notify->event);
|
||||
sc_notify_release(service->notify);
|
||||
}
|
||||
service_unlock(service->service_entry);
|
||||
release_service(service->service_entry);
|
||||
|
@ -432,6 +431,8 @@ static DWORD create_handle_for_service(struct service_entry *entry, DWORD dwDesi
|
|||
|
||||
service->hdr.type = SC_HTYPE_SERVICE;
|
||||
service->hdr.access = dwDesiredAccess;
|
||||
service->notify = NULL;
|
||||
service->status_notified = FALSE;
|
||||
RtlMapGenericMask(&service->hdr.access, &g_svc_generic);
|
||||
|
||||
service_lock(entry);
|
||||
|
@ -835,7 +836,7 @@ static void fill_status_process(SERVICE_STATUS_PROCESS *status, struct service_e
|
|||
status->dwServiceFlags = 0;
|
||||
}
|
||||
|
||||
static void fill_notify(struct sc_notify_handle *notify)
|
||||
static void fill_notify(struct sc_notify_handle *notify, struct service_entry *service)
|
||||
{
|
||||
SC_RPC_NOTIFY_PARAMS_LIST *list;
|
||||
SERVICE_NOTIFY_STATUS_CHANGE_PARAMS_2 *cparams;
|
||||
|
@ -848,7 +849,7 @@ static void fill_notify(struct sc_notify_handle *notify)
|
|||
cparams = (SERVICE_NOTIFY_STATUS_CHANGE_PARAMS_2 *)(list + 1);
|
||||
|
||||
cparams->dwNotifyMask = notify->notify_mask;
|
||||
fill_status_process(&cparams->ServiceStatus, notify->service->service_entry);
|
||||
fill_status_process(&cparams->ServiceStatus, service);
|
||||
cparams->dwNotificationStatus = ERROR_SUCCESS;
|
||||
cparams->dwNotificationTriggered = 1 << (cparams->ServiceStatus.dwCurrentState - SERVICE_STOPPED);
|
||||
cparams->pszServiceNames = NULL;
|
||||
|
@ -867,7 +868,7 @@ DWORD __cdecl svcctl_SetServiceStatus(
|
|||
SC_RPC_HANDLE hServiceStatus,
|
||||
LPSERVICE_STATUS lpServiceStatus)
|
||||
{
|
||||
struct sc_service_handle *service;
|
||||
struct sc_service_handle *service, *service_handle;
|
||||
struct process_entry *process;
|
||||
DWORD err, mask;
|
||||
|
||||
|
@ -895,17 +896,19 @@ DWORD __cdecl svcctl_SetServiceStatus(
|
|||
}
|
||||
|
||||
mask = 1 << (service->service_entry->status.dwCurrentState - SERVICE_STOPPED);
|
||||
if (service->service_entry->notify &&
|
||||
(service->service_entry->notify->notify_mask & mask))
|
||||
LIST_FOR_EACH_ENTRY(service_handle, &service->service_entry->handles, struct sc_service_handle, entry)
|
||||
{
|
||||
struct sc_notify_handle *notify = service->service_entry->notify;
|
||||
fill_notify(notify);
|
||||
service->service_entry->notify = NULL;
|
||||
sc_notify_release(notify);
|
||||
service->service_entry->status_notified = TRUE;
|
||||
struct sc_notify_handle *notify = service_handle->notify;
|
||||
if (notify && (notify->notify_mask & mask))
|
||||
{
|
||||
fill_notify(notify, service->service_entry);
|
||||
sc_notify_release(notify);
|
||||
service_handle->notify = NULL;
|
||||
service_handle->status_notified = TRUE;
|
||||
}
|
||||
else
|
||||
service_handle->status_notified = FALSE;
|
||||
}
|
||||
else
|
||||
service->service_entry->status_notified = FALSE;
|
||||
|
||||
service_unlock(service->service_entry);
|
||||
|
||||
|
@ -1736,32 +1739,29 @@ DWORD __cdecl svcctl_NotifyServiceStatusChange(
|
|||
notify->hdr.type = SC_HTYPE_NOTIFY;
|
||||
notify->hdr.access = 0;
|
||||
|
||||
notify->service = service;
|
||||
|
||||
notify->event = CreateEventW(NULL, TRUE, FALSE, NULL);
|
||||
|
||||
notify->notify_mask = params.u.params->dwNotifyMask;
|
||||
|
||||
service_lock(service->service_entry);
|
||||
|
||||
if (service->service_entry->notify)
|
||||
if (service->notify)
|
||||
{
|
||||
service_unlock(service->service_entry);
|
||||
HeapFree(GetProcessHeap(), 0, notify);
|
||||
sc_notify_release(notify);
|
||||
return ERROR_ALREADY_REGISTERED;
|
||||
}
|
||||
|
||||
mask = 1 << (service->service_entry->status.dwCurrentState - SERVICE_STOPPED);
|
||||
if (!service->service_entry->status_notified &&
|
||||
(notify->notify_mask & mask))
|
||||
if (!service->status_notified && (notify->notify_mask & mask))
|
||||
{
|
||||
fill_notify(notify);
|
||||
service->service_entry->status_notified = TRUE;
|
||||
fill_notify(notify, service->service_entry);
|
||||
service->status_notified = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
sc_notify_retain(notify);
|
||||
service->service_entry->notify = notify;
|
||||
service->notify = notify;
|
||||
}
|
||||
|
||||
sc_notify_retain(notify);
|
||||
|
|
|
@ -45,8 +45,6 @@ struct process_entry
|
|||
HANDLE overlapped_event;
|
||||
};
|
||||
|
||||
struct sc_notify_handle;
|
||||
|
||||
struct service_entry
|
||||
{
|
||||
struct list entry;
|
||||
|
@ -65,8 +63,6 @@ struct service_entry
|
|||
BOOL force_shutdown;
|
||||
BOOL marked_for_delete;
|
||||
BOOL is_wow64;
|
||||
BOOL status_notified;
|
||||
struct sc_notify_handle *notify;
|
||||
struct list handles;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue