[2/2] server: Allow multiple registry notifications per key.
Sebastian Lackner
sebastian at fds-team.de
Tue Nov 10 16:01:54 CST 2015
Signed-off-by: Sebastian Lackner <sebastian at fds-team.de>
---
After this patch there are still a couple of remaining problems:
* Notifications should wake up when the original thread calling NtNotifyChangeKey
terminates.
* The WatchSubtree Flag and the filters parameter should be stored somewhere in the
key object itself? It seems like its not possible to change it anymore after
the first notification.
* Missing threadpool support.
dlls/ntdll/tests/reg.c | 6 ++---
server/registry.c | 54 ++++++++++++++++++-------------------------------
2 files changed, 23 insertions(+), 37 deletions(-)
diff --git a/dlls/ntdll/tests/reg.c b/dlls/ntdll/tests/reg.c
index 5cd58b0..08f4ed6 100644
--- a/dlls/ntdll/tests/reg.c
+++ b/dlls/ntdll/tests/reg.c
@@ -1546,7 +1546,7 @@ static void test_notify(void)
ok(status == STATUS_SUCCESS, "NtCreateKey failed: 0x%08x\n", status);
status = pNtWaitForSingleObject(events[0], FALSE, &timeout);
- todo_wine ok(status == STATUS_SUCCESS, "NtWaitForSingleObject returned %x\n", status);
+ ok(status == STATUS_SUCCESS, "NtWaitForSingleObject returned %x\n", status);
status = pNtWaitForSingleObject(events[1], FALSE, &timeout);
ok(status == STATUS_SUCCESS, "NtWaitForSingleObject returned %x\n", status);
@@ -1559,7 +1559,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 == STATUS_SUCCESS, "NtWaitForSingleObject returned %x\n", status);
+ ok(status == STATUS_SUCCESS, "NtWaitForSingleObject returned %x\n", status);
status = pNtWaitForSingleObject(events[1], FALSE, &timeout);
ok(status == STATUS_SUCCESS, "NtWaitForSingleObject returned %x\n", status);
@@ -1573,7 +1573,7 @@ static void test_notify(void)
pNtClose(key);
status = pNtWaitForSingleObject(events[0], FALSE, &timeout);
- todo_wine ok(status == STATUS_SUCCESS, "NtWaitForSingleObject returned %x\n", status);
+ ok(status == STATUS_SUCCESS, "NtWaitForSingleObject returned %x\n", status);
status = pNtWaitForSingleObject(events[1], FALSE, &timeout);
ok(status == STATUS_SUCCESS, "NtWaitForSingleObject returned %x\n", status);
diff --git a/server/registry.c b/server/registry.c
index 3c9ae70..05d5bde 100644
--- a/server/registry.c
+++ b/server/registry.c
@@ -316,17 +316,6 @@ static void do_notification( struct key *key, struct notify *notify, int del )
}
}
-static inline struct notify *find_notify( struct key *key, struct process *process, obj_handle_t hkey )
-{
- struct notify *notify;
-
- LIST_FOR_EACH_ENTRY( notify, &key->notify_list, struct notify, entry )
- {
- if (notify->process == process && notify->hkey == hkey) return notify;
- }
- return NULL;
-}
-
static unsigned int key_map_access( struct object *obj, unsigned int access )
{
if (access & GENERIC_READ) access |= KEY_READ;
@@ -388,8 +377,18 @@ static struct security_descriptor *key_get_sd( struct object *obj )
static int key_close_handle( struct object *obj, struct process *process, obj_handle_t handle )
{
struct key * key = (struct key *) obj;
- struct notify *notify = find_notify( key, process, handle );
- if (notify) do_notification( key, notify, 1 );
+ struct list *ptr;
+
+ LIST_FOR_EACH( ptr, &key->notify_list )
+ {
+ struct notify *notify = LIST_ENTRY( ptr, struct notify, entry );
+ if (notify->process != process) continue;
+ if (notify->hkey != handle) continue;
+ do_notification( key, notify, 1 );
+ /* restart at the head of the list, the wake_up could have killed some processes */
+ ptr = &key->notify_list;
+ }
+
return 1; /* ok to close */
}
@@ -2268,30 +2267,17 @@ DECL_HANDLER(set_registry_notification)
event = get_event_obj( current->process, req->event, SYNCHRONIZE );
if (event)
{
- notify = find_notify( key, current->process, req->hkey );
+ notify = mem_alloc( sizeof(*notify) );
if (notify)
{
- if (notify->event)
- release_object( notify->event );
grab_object( event );
- notify->event = event;
- }
- else
- {
- notify = mem_alloc( sizeof(*notify) );
- if (notify)
- {
- grab_object( event );
- notify->event = event;
- notify->subtree = req->subtree;
- notify->filter = req->filter;
- notify->hkey = req->hkey;
- notify->process = current->process;
- list_add_head( &key->notify_list, ¬ify->entry );
- }
- }
- if (notify)
- {
+ notify->event = event;
+ notify->subtree = req->subtree;
+ notify->filter = req->filter;
+ notify->hkey = req->hkey;
+ notify->process = current->process;
+ list_add_head( &key->notify_list, ¬ify->entry );
+
reset_event( event );
set_error( STATUS_PENDING );
}
--
2.6.2
More information about the wine-patches
mailing list