Jacek Caban : services: Associate notify handle with service handle instead of service entry.

Alexandre Julliard julliard at winehq.org
Mon Jan 28 16:17:02 CST 2019


Module: wine
Branch: master
Commit: 8a2347baffb64f6d2b2901e5a87c926e498671d3
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=8a2347baffb64f6d2b2901e5a87c926e498671d3

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Mon Jan 28 15:54:00 2019 +0100

services: Associate notify handle with service handle instead of service entry.

Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/advapi32/tests/service.c |  2 --
 programs/services/rpc.c       | 68 +++++++++++++++++++++----------------------
 programs/services/services.h  |  4 ---
 3 files changed, 34 insertions(+), 40 deletions(-)

diff --git a/dlls/advapi32/tests/service.c b/dlls/advapi32/tests/service.c
index 1552791..e4ff7d7 100644
--- a/dlls/advapi32/tests/service.c
+++ b/dlls/advapi32/tests/service.c
@@ -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
diff --git a/programs/services/rpc.c b/programs/services/rpc.c
index 623e1fa..8299dbf 100644
--- a/programs/services/rpc.c
+++ b/programs/services/rpc.c
@@ -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(&notify->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);
diff --git a/programs/services/services.h b/programs/services/services.h
index c78f71c..e1481d9 100644
--- a/programs/services/services.h
+++ b/programs/services/services.h
@@ -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;
 };
 




More information about the wine-cvs mailing list