Sebastian Lackner : user32: Avoid race-condition when unloading module while hook is still active.

Alexandre Julliard julliard at winehq.org
Tue Jun 17 14:40:50 CDT 2014


Module: wine
Branch: master
Commit: e9fbcc8360e9dcdc51add3efb9d0581c63a6cd09
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=e9fbcc8360e9dcdc51add3efb9d0581c63a6cd09

Author: Sebastian Lackner <sebastian at fds-team.de>
Date:   Fri Jun 13 20:35:41 2014 +0200

user32: Avoid race-condition when unloading module while hook is still active.

Based on a patch by Sam Revitch.

---

 dlls/user32/hook.c         |   16 ++++++++++++----
 dlls/user32/message.c      |    5 ++++-
 dlls/user32/user_private.h |    2 +-
 3 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/dlls/user32/hook.c b/dlls/user32/hook.c
index 633704b..2f6b42c 100644
--- a/dlls/user32/hook.c
+++ b/dlls/user32/hook.c
@@ -359,11 +359,13 @@ static LRESULT call_hook_proc( HOOKPROC proc, INT id, INT code, WPARAM wparam, L
  *
  * Retrieve the hook procedure real value for a module-relative proc
  */
-void *get_hook_proc( void *proc, const WCHAR *module )
+void *get_hook_proc( void *proc, const WCHAR *module, HMODULE *free_module )
 {
     HMODULE mod;
 
-    if (!(mod = GetModuleHandleW(module)))
+    GetModuleHandleExW( 0, module, &mod );
+    *free_module = mod;
+    if (!mod)
     {
         TRACE( "loading %s\n", debugstr_w(module) );
         /* FIXME: the library will never be freed */
@@ -411,12 +413,13 @@ static LRESULT call_hook( struct hook_info *info, INT code, WPARAM wparam, LPARA
     }
     else if (info->proc)
     {
+        HMODULE free_module = 0;
         TRACE( "calling hook %p %s code %x wp %lx lp %lx module %s\n",
                info->proc, hook_names[info->id-WH_MINHOOK], code, wparam,
                lparam, debugstr_w(info->module) );
 
         if (!info->module[0] ||
-            (info->proc = get_hook_proc( info->proc, info->module )) != NULL)
+            (info->proc = get_hook_proc( info->proc, info->module, &free_module )) != NULL)
         {
             struct user_thread_info *thread_info = get_user_thread_info();
             HHOOK prev = thread_info->hook;
@@ -428,6 +431,8 @@ static LRESULT call_hook( struct hook_info *info, INT code, WPARAM wparam, LPARA
                                   info->prev_unicode, info->next_unicode );
             thread_info->hook = prev;
             thread_info->hook_unicode = prev_unicode;
+
+            if (free_module) FreeLibrary(free_module);
         }
     }
 
@@ -897,10 +902,11 @@ void WINAPI NotifyWinEvent(DWORD event, HWND hwnd, LONG object_id, LONG child_id
         WINEVENTPROC proc = info.proc;
         if (proc)
         {
+            HMODULE free_module = 0;
             TRACE( "calling WH_WINEVENT hook %p event %x hwnd %p %x %x module %s\n",
                    proc, event, hwnd, object_id, child_id, debugstr_w(info.module) );
 
-            if (!info.module[0] || (proc = get_hook_proc( proc, info.module )) != NULL)
+            if (!info.module[0] || (proc = get_hook_proc( proc, info.module, &free_module )) != NULL)
             {
                 if (TRACE_ON(relay))
                     DPRINTF( "%04x:Call winevent hook proc %p (hhook=%p,event=%x,hwnd=%p,object_id=%x,child_id=%x,tid=%04x,time=%x)\n",
@@ -914,6 +920,8 @@ void WINAPI NotifyWinEvent(DWORD event, HWND hwnd, LONG object_id, LONG child_id
                     DPRINTF( "%04x:Ret  winevent hook proc %p (hhook=%p,event=%x,hwnd=%p,object_id=%x,child_id=%x,tid=%04x,time=%x)\n",
                              GetCurrentThreadId(), proc, info.handle, event, hwnd, object_id,
                              child_id, GetCurrentThreadId(), GetCurrentTime());
+
+                if (free_module) FreeLibrary(free_module);
             }
         }
         else
diff --git a/dlls/user32/message.c b/dlls/user32/message.c
index be5d995..3167a2f 100644
--- a/dlls/user32/message.c
+++ b/dlls/user32/message.c
@@ -2815,6 +2815,7 @@ static BOOL peek_message( MSG *msg, HWND hwnd, UINT first, UINT last, UINT flags
             if (size >= sizeof(msg_data->winevent))
             {
                 WINEVENTPROC hook_proc;
+                HMODULE free_module = 0;
 
                 hook_proc = wine_server_get_ptr( msg_data->winevent.hook_proc );
                 size -= sizeof(msg_data->winevent);
@@ -2825,7 +2826,7 @@ static BOOL peek_message( MSG *msg, HWND hwnd, UINT first, UINT last, UINT flags
                     size = min( size, (MAX_PATH - 1) * sizeof(WCHAR) );
                     memcpy( module, &msg_data->winevent + 1, size );
                     module[size / sizeof(WCHAR)] = 0;
-                    if (!(hook_proc = get_hook_proc( hook_proc, module )))
+                    if (!(hook_proc = get_hook_proc( hook_proc, module, &free_module )))
                     {
                         ERR( "invalid winevent hook module name %s\n", debugstr_w(module) );
                         continue;
@@ -2847,6 +2848,8 @@ static BOOL peek_message( MSG *msg, HWND hwnd, UINT first, UINT last, UINT flags
                              GetCurrentThreadId(), hook_proc,
                              msg_data->winevent.hook, info.msg.message, info.msg.hwnd, info.msg.wParam,
                              info.msg.lParam, msg_data->winevent.tid, info.msg.time);
+
+                if (free_module) FreeLibrary(free_module);
             }
             continue;
         case MSG_HOOK_LL:
diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h
index 2bb869a..adf3f7d 100644
--- a/dlls/user32/user_private.h
+++ b/dlls/user32/user_private.h
@@ -225,7 +225,7 @@ extern void move_window_bits( HWND hwnd, struct window_surface *old_surface,
                               struct window_surface *new_surface,
                               const RECT *visible_rect, const RECT *old_visible_rect,
                               const RECT *client_rect, const RECT *valid_rects ) DECLSPEC_HIDDEN;
-extern void *get_hook_proc( void *proc, const WCHAR *module ) DECLSPEC_HIDDEN;
+extern void *get_hook_proc( void *proc, const WCHAR *module, HMODULE *free_module ) DECLSPEC_HIDDEN;
 extern RECT get_virtual_screen_rect(void) DECLSPEC_HIDDEN;
 extern LRESULT call_current_hook( HHOOK hhook, INT code, WPARAM wparam, LPARAM lparam ) DECLSPEC_HIDDEN;
 extern DWORD get_input_codepage( void ) DECLSPEC_HIDDEN;




More information about the wine-cvs mailing list