[PATCH 2/2] server: Store and notify all notification events associated with a given registry handle.

Zebediah Figura z.figura12 at gmail.com
Tue Jan 26 22:41:43 CST 2021


From: Sebastian Lackner <sebastian at fds-team.de>

Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
The original wine-staging patch uses a linked list here. I changed it to use a
flat array instead, as the latter seemed simpler.

The original wine-staging patch is also accompanied by a subsequent patch
introducing reference counting, which as far as I can tell has no effect.

I have been unable to locate any reference to an application related to this
patch.

 dlls/ntdll/tests/reg.c |  6 +++---
 server/registry.c      | 41 ++++++++++++++++++++++++-----------------
 2 files changed, 27 insertions(+), 20 deletions(-)

diff --git a/dlls/ntdll/tests/reg.c b/dlls/ntdll/tests/reg.c
index a619bc45cb8..ac1dec9f2f8 100644
--- a/dlls/ntdll/tests/reg.c
+++ b/dlls/ntdll/tests/reg.c
@@ -1887,7 +1887,7 @@ static void test_notify(void)
     pRtlFreeUnicodeString(&str);
 
     status = pNtWaitForSingleObject(events[0], FALSE, &timeout);
-    todo_wine ok(!status, "got %#x\n", status);
+    ok(!status, "got %#x\n", status);
     status = pNtWaitForSingleObject(events[1], FALSE, &timeout);
     ok(!status, "got %#x\n", status);
     status = pNtWaitForSingleObject(events[2], FALSE, &timeout);
@@ -1917,7 +1917,7 @@ static void test_notify(void)
     ok(status == STATUS_SUCCESS, "NtDeleteSubkey failed: %x\n", status);
 
     status = pNtWaitForSingleObject(events[0], FALSE, &timeout);
-    todo_wine ok(!status, "got %#x\n", status);
+    ok(!status, "got %#x\n", status);
     status = pNtWaitForSingleObject(events[1], FALSE, &timeout);
     ok(!status, "got %#x\n", status);
     status = pNtWaitForSingleObject(events[2], FALSE, &timeout);
@@ -1935,7 +1935,7 @@ static void test_notify(void)
     pNtClose(key);
 
     status = pNtWaitForSingleObject(events[0], FALSE, &timeout);
-    todo_wine ok(!status, "got %#x\n", status);
+    ok(!status, "got %#x\n", status);
     status = pNtWaitForSingleObject(events[1], FALSE, &timeout);
     ok(!status, "got %#x\n", status);
     status = pNtWaitForSingleObject(events[2], FALSE, &timeout);
diff --git a/server/registry.c b/server/registry.c
index c937e051597..64aec1d83c9 100644
--- a/server/registry.c
+++ b/server/registry.c
@@ -52,7 +52,8 @@
 struct notify
 {
     struct list       entry;    /* entry in list of notifications */
-    struct event     *event;    /* event to set when changing this key */
+    struct event    **events;   /* events to set when changing this key */
+    unsigned int      event_count; /* number of events */
     int               subtree;  /* true if subtree notification */
     unsigned int      filter;   /* which events to notify on */
     obj_handle_t      hkey;     /* hkey associated with this notification */
@@ -314,12 +315,17 @@ static struct object_type *key_get_type( struct object *obj )
 /* notify waiter and maybe delete the notification */
 static void do_notification( struct key *key, struct notify *notify, int del )
 {
-    if (notify->event)
+    unsigned int i;
+
+    for (i = 0; i < notify->event_count; ++i)
     {
-        set_event( notify->event );
-        release_object( notify->event );
-        notify->event = NULL;
+        set_event( notify->events[i] );
+        release_object( notify->events[i] );
     }
+    free( notify->events );
+    notify->events = NULL;
+    notify->event_count = 0;
+
     if (del)
     {
         list_remove( &notify->entry );
@@ -2283,20 +2289,13 @@ DECL_HANDLER(set_registry_notification)
         if (event)
         {
             notify = find_notify( key, current->process, req->hkey );
-            if (notify)
-            {
-                if (notify->event)
-                    release_object( notify->event );
-                grab_object( event );
-                notify->event = event;
-            }
-            else
+            if (!notify)
             {
                 notify = mem_alloc( sizeof(*notify) );
                 if (notify)
                 {
-                    grab_object( event );
-                    notify->event   = event;
+                    notify->events  = NULL;
+                    notify->event_count = 0;
                     notify->subtree = req->subtree;
                     notify->filter  = req->filter;
                     notify->hkey    = req->hkey;
@@ -2306,8 +2305,16 @@ DECL_HANDLER(set_registry_notification)
             }
             if (notify)
             {
-                reset_event( event );
-                set_error( STATUS_PENDING );
+                struct event **new_array;
+
+                if ((new_array = realloc( notify->events, (notify->event_count + 1) * sizeof(*notify->events) )))
+                {
+                    notify->events = new_array;
+                    notify->events[notify->event_count++] = (struct event *)grab_object( event );
+                    reset_event( event );
+                    set_error( STATUS_PENDING );
+                }
+                else set_error( STATUS_NO_MEMORY );
             }
             release_object( event );
         }
-- 
2.30.0




More information about the wine-devel mailing list