Commit 9c29cee6 authored by Sebastian Lackner's avatar Sebastian Lackner Committed by Alexandre Julliard

server: Store and notify all notification events associated with a given registry handle.

parent 3c72ad33
...@@ -1887,7 +1887,7 @@ static void test_notify(void) ...@@ -1887,7 +1887,7 @@ static void test_notify(void)
pRtlFreeUnicodeString(&str); pRtlFreeUnicodeString(&str);
status = pNtWaitForSingleObject(events[0], FALSE, &timeout); 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); status = pNtWaitForSingleObject(events[1], FALSE, &timeout);
ok(!status, "got %#x\n", status); ok(!status, "got %#x\n", status);
status = pNtWaitForSingleObject(events[2], FALSE, &timeout); status = pNtWaitForSingleObject(events[2], FALSE, &timeout);
...@@ -1917,7 +1917,7 @@ static void test_notify(void) ...@@ -1917,7 +1917,7 @@ static void test_notify(void)
ok(status == STATUS_SUCCESS, "NtDeleteSubkey failed: %x\n", status); ok(status == STATUS_SUCCESS, "NtDeleteSubkey failed: %x\n", status);
status = pNtWaitForSingleObject(events[0], FALSE, &timeout); 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); status = pNtWaitForSingleObject(events[1], FALSE, &timeout);
ok(!status, "got %#x\n", status); ok(!status, "got %#x\n", status);
status = pNtWaitForSingleObject(events[2], FALSE, &timeout); status = pNtWaitForSingleObject(events[2], FALSE, &timeout);
...@@ -1935,7 +1935,7 @@ static void test_notify(void) ...@@ -1935,7 +1935,7 @@ static void test_notify(void)
pNtClose(key); pNtClose(key);
status = pNtWaitForSingleObject(events[0], FALSE, &timeout); 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); status = pNtWaitForSingleObject(events[1], FALSE, &timeout);
ok(!status, "got %#x\n", status); ok(!status, "got %#x\n", status);
status = pNtWaitForSingleObject(events[2], FALSE, &timeout); status = pNtWaitForSingleObject(events[2], FALSE, &timeout);
......
...@@ -52,7 +52,8 @@ ...@@ -52,7 +52,8 @@
struct notify struct notify
{ {
struct list entry; /* entry in list of notifications */ 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 */ int subtree; /* true if subtree notification */
unsigned int filter; /* which events to notify on */ unsigned int filter; /* which events to notify on */
obj_handle_t hkey; /* hkey associated with this notification */ obj_handle_t hkey; /* hkey associated with this notification */
...@@ -314,12 +315,17 @@ static struct object_type *key_get_type( struct object *obj ) ...@@ -314,12 +315,17 @@ static struct object_type *key_get_type( struct object *obj )
/* notify waiter and maybe delete the notification */ /* notify waiter and maybe delete the notification */
static void do_notification( struct key *key, struct notify *notify, int del ) 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 ); set_event( notify->events[i] );
release_object( notify->event ); release_object( notify->events[i] );
notify->event = NULL;
} }
free( notify->events );
notify->events = NULL;
notify->event_count = 0;
if (del) if (del)
{ {
list_remove( &notify->entry ); list_remove( &notify->entry );
...@@ -2283,20 +2289,13 @@ DECL_HANDLER(set_registry_notification) ...@@ -2283,20 +2289,13 @@ DECL_HANDLER(set_registry_notification)
if (event) if (event)
{ {
notify = find_notify( key, current->process, req->hkey ); notify = find_notify( key, current->process, req->hkey );
if (notify) if (!notify)
{
if (notify->event)
release_object( notify->event );
grab_object( event );
notify->event = event;
}
else
{ {
notify = mem_alloc( sizeof(*notify) ); notify = mem_alloc( sizeof(*notify) );
if (notify) if (notify)
{ {
grab_object( event ); notify->events = NULL;
notify->event = event; notify->event_count = 0;
notify->subtree = req->subtree; notify->subtree = req->subtree;
notify->filter = req->filter; notify->filter = req->filter;
notify->hkey = req->hkey; notify->hkey = req->hkey;
...@@ -2306,8 +2305,16 @@ DECL_HANDLER(set_registry_notification) ...@@ -2306,8 +2305,16 @@ DECL_HANDLER(set_registry_notification)
} }
if (notify) if (notify)
{ {
reset_event( event ); struct event **new_array;
set_error( STATUS_PENDING );
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 ); release_object( event );
} }
......
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