Added patch to properly handle multiple registry notifications per key.

This commit is contained in:
Sebastian Lackner 2015-11-13 23:33:19 +01:00
parent 19d466a729
commit dbce23ab3b
6 changed files with 220 additions and 1 deletions

View File

@ -34,11 +34,12 @@ Wine. All those differences are also documented on the
Included bug fixes and improvements
-----------------------------------
**Bug fixes and features included in the next upcoming release [4]:**
**Bug fixes and features included in the next upcoming release [5]:**
* Add partial implementation of ITfThreadMgrEx_ActivateEx ([Wine Bug #39564](https://bugs.winehq.org/show_bug.cgi?id=39564))
* Implement stub for hid.HidP_TranslateUsagesToI8042ScanCodes ([Wine Bug #39447](https://bugs.winehq.org/show_bug.cgi?id=39447))
* Implement support for "Purist Mode" (override for all dlls)
* Properly handle multiple registry notifications per key
* Revert patch to prepare GL resources before calling context_apply_fbo_state ([Wine Bug #39536](https://bugs.winehq.org/show_bug.cgi?id=39536))

1
debian/changelog vendored
View File

@ -4,6 +4,7 @@ wine-staging (1.7.55) UNRELEASED; urgency=low
* Added patch to implement support for "Purist Mode" (override for all dlls).
* Added patch for partial implementation of ITfThreadMgrEx_ActivateEx.
* Added patch for stub of hid.HidP_TranslateUsagesToI8042ScanCodes.
* Added patch to properly handle multiple registry notifications per key.
* Remove disabled shell32-Quoted_ShellExecute patchset (bug already fixed and
all tests pass).
* Remove disabled reg-Cleanup patchset (only cleanup and not actively

View File

@ -243,6 +243,7 @@ patch_enable_all ()
enable_server_PeekMessage="$1"
enable_server_Pipe_ObjectName="$1"
enable_server_Realtime_Priority="$1"
enable_server_Registry_Notifications="$1"
enable_server_Shared_Memory="$1"
enable_server_Signal_Thread="$1"
enable_server_Stored_ACLs="$1"
@ -829,6 +830,9 @@ patch_enable ()
server-Realtime_Priority)
enable_server_Realtime_Priority="$2"
;;
server-Registry_Notifications)
enable_server_Registry_Notifications="$2"
;;
server-Shared_Memory)
enable_server_Shared_Memory="$2"
;;
@ -4887,6 +4891,20 @@ if test "$enable_server_Realtime_Priority" -eq 1; then
) >> "$patchlist"
fi
# Patchset server-Registry_Notifications
# |
# | Modified files:
# | * dlls/ntdll/tests/reg.c, server/registry.c
# |
if test "$enable_server_Registry_Notifications" -eq 1; then
patch_apply server-Registry_Notifications/0001-server-Allow-multiple-registry-notifications-for-the.patch
patch_apply server-Registry_Notifications/0002-server-Introduce-refcounting-for-registry-notificati.patch
(
echo '+ { "Sebastian Lackner", "server: Allow multiple registry notifications for the same key.", 1 },';
echo '+ { "Sebastian Lackner", "server: Introduce refcounting for registry notifications.", 1 },';
) >> "$patchlist"
fi
# Patchset server-Signal_Thread
# |
# | Modified files:

View File

@ -0,0 +1,137 @@
From b556ce4de01cf5e98a486aa13c26d5d5f651d33d Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Fri, 13 Nov 2015 22:39:00 +0100
Subject: server: Allow multiple registry notifications for the same key.
---
dlls/ntdll/tests/reg.c | 6 +++---
server/registry.c | 53 ++++++++++++++++++++++++++------------------------
2 files changed, 31 insertions(+), 28 deletions(-)
diff --git a/dlls/ntdll/tests/reg.c b/dlls/ntdll/tests/reg.c
index 96f190b..e0a58f2 100644
--- a/dlls/ntdll/tests/reg.c
+++ b/dlls/ntdll/tests/reg.c
@@ -1611,7 +1611,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);
@@ -1624,7 +1624,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);
@@ -1638,7 +1638,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 c95e103..ead9749 100644
--- a/server/registry.c
+++ b/server/registry.c
@@ -50,10 +50,16 @@
#include "winternl.h"
#include "wine/library.h"
+struct notify_event
+{
+ struct list entry; /* entry in list of events */
+ struct event *event; /* event to set */
+};
+
struct notify
{
struct list entry; /* entry in list of notifications */
- struct event *event; /* event to set when changing this key */
+ struct list events; /* list of events to set when changing this key */
int subtree; /* true if subtree notification */
unsigned int filter; /* which events to notify on */
obj_handle_t hkey; /* hkey associated with this notification */
@@ -303,12 +309,17 @@ static void key_dump( struct object *obj, int verbose )
/* notify waiter and maybe delete the notification */
static void do_notification( struct key *key, struct notify *notify, int del )
{
- if (notify->event)
+ void *ptr;
+
+ while ((ptr = list_head( &notify->events )))
{
- set_event( notify->event );
- release_object( notify->event );
- notify->event = NULL;
+ struct notify_event *notify_event = LIST_ENTRY( ptr, struct notify_event, entry );
+ list_remove( &notify_event->entry );
+ set_event( notify_event->event );
+ release_object( notify_event->event );
+ free( notify_event );
}
+
if (del)
{
list_remove( &notify->entry );
@@ -2260,6 +2271,7 @@ DECL_HANDLER(set_registry_notification)
struct key *key;
struct event *event;
struct notify *notify;
+ struct notify_event *notify_event;
key = get_hkey_obj( req->hkey, KEY_NOTIFY );
if (key)
@@ -2268,29 +2280,20 @@ 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) )))
{
- 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, &notify->entry );
- }
+ list_init( &notify->events );
+ notify->subtree = req->subtree;
+ notify->filter = req->filter;
+ notify->hkey = req->hkey;
+ notify->process = current->process;
+ list_add_head( &key->notify_list, &notify->entry );
}
- if (notify)
+ if (notify && (notify_event = mem_alloc( sizeof(*notify_event) )))
{
+ grab_object(event);
+ notify_event->event = event;
+ list_add_tail( &notify->events, &notify_event->entry );
reset_event( event );
set_error( STATUS_PENDING );
}
--
2.6.2

View File

@ -0,0 +1,61 @@
From aedc8d40763b059b996bdfc95d4974ac2f793b63 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Fri, 13 Nov 2015 23:30:27 +0100
Subject: server: Introduce refcounting for registry notifications.
---
server/registry.c | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/server/registry.c b/server/registry.c
index ead9749..5c70b8d 100644
--- a/server/registry.c
+++ b/server/registry.c
@@ -58,6 +58,7 @@ struct notify_event
struct notify
{
+ unsigned int refcount; /* number of references */
struct list entry; /* entry in list of notifications */
struct list events; /* list of events to set when changing this key */
int subtree; /* true if subtree notification */
@@ -311,6 +312,14 @@ static void do_notification( struct key *key, struct notify *notify, int del )
{
void *ptr;
+ if (del)
+ list_remove( &notify->entry );
+ else
+ {
+ assert( notify->refcount < INT_MAX );
+ notify->refcount++;
+ }
+
while ((ptr = list_head( &notify->events )))
{
struct notify_event *notify_event = LIST_ENTRY( ptr, struct notify_event, entry );
@@ -320,11 +329,9 @@ static void do_notification( struct key *key, struct notify *notify, int del )
free( notify_event );
}
- if (del)
- {
- list_remove( &notify->entry );
+ assert( notify->refcount );
+ if (!--notify->refcount)
free( notify );
- }
}
static inline struct notify *find_notify( struct key *key, struct process *process, obj_handle_t hkey )
@@ -2282,6 +2289,7 @@ DECL_HANDLER(set_registry_notification)
notify = find_notify( key, current->process, req->hkey );
if (!notify && (notify = mem_alloc( sizeof(*notify) )))
{
+ notify->refcount = 1;
list_init( &notify->events );
notify->subtree = req->subtree;
notify->filter = req->filter;
--
2.6.2

View File

@ -0,0 +1 @@
Fixes: Properly handle multiple registry notifications per key