Commit e9fbcc83 authored by Sebastian Lackner's avatar Sebastian Lackner Committed by Alexandre Julliard

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

Based on a patch by Sam Revitch.
parent 25b069c4
...@@ -359,11 +359,13 @@ static LRESULT call_hook_proc( HOOKPROC proc, INT id, INT code, WPARAM wparam, L ...@@ -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 * 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; HMODULE mod;
if (!(mod = GetModuleHandleW(module))) GetModuleHandleExW( 0, module, &mod );
*free_module = mod;
if (!mod)
{ {
TRACE( "loading %s\n", debugstr_w(module) ); TRACE( "loading %s\n", debugstr_w(module) );
/* FIXME: the library will never be freed */ /* FIXME: the library will never be freed */
...@@ -411,12 +413,13 @@ static LRESULT call_hook( struct hook_info *info, INT code, WPARAM wparam, LPARA ...@@ -411,12 +413,13 @@ static LRESULT call_hook( struct hook_info *info, INT code, WPARAM wparam, LPARA
} }
else if (info->proc) else if (info->proc)
{ {
HMODULE free_module = 0;
TRACE( "calling hook %p %s code %x wp %lx lp %lx module %s\n", TRACE( "calling hook %p %s code %x wp %lx lp %lx module %s\n",
info->proc, hook_names[info->id-WH_MINHOOK], code, wparam, info->proc, hook_names[info->id-WH_MINHOOK], code, wparam,
lparam, debugstr_w(info->module) ); lparam, debugstr_w(info->module) );
if (!info->module[0] || 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(); struct user_thread_info *thread_info = get_user_thread_info();
HHOOK prev = thread_info->hook; HHOOK prev = thread_info->hook;
...@@ -428,6 +431,8 @@ static LRESULT call_hook( struct hook_info *info, INT code, WPARAM wparam, LPARA ...@@ -428,6 +431,8 @@ static LRESULT call_hook( struct hook_info *info, INT code, WPARAM wparam, LPARA
info->prev_unicode, info->next_unicode ); info->prev_unicode, info->next_unicode );
thread_info->hook = prev; thread_info->hook = prev;
thread_info->hook_unicode = prev_unicode; 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 ...@@ -897,10 +902,11 @@ void WINAPI NotifyWinEvent(DWORD event, HWND hwnd, LONG object_id, LONG child_id
WINEVENTPROC proc = info.proc; WINEVENTPROC proc = info.proc;
if (proc) if (proc)
{ {
HMODULE free_module = 0;
TRACE( "calling WH_WINEVENT hook %p event %x hwnd %p %x %x module %s\n", 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) ); 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)) 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", 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 ...@@ -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", 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, GetCurrentThreadId(), proc, info.handle, event, hwnd, object_id,
child_id, GetCurrentThreadId(), GetCurrentTime()); child_id, GetCurrentThreadId(), GetCurrentTime());
if (free_module) FreeLibrary(free_module);
} }
} }
else else
......
...@@ -2815,6 +2815,7 @@ static BOOL peek_message( MSG *msg, HWND hwnd, UINT first, UINT last, UINT flags ...@@ -2815,6 +2815,7 @@ static BOOL peek_message( MSG *msg, HWND hwnd, UINT first, UINT last, UINT flags
if (size >= sizeof(msg_data->winevent)) if (size >= sizeof(msg_data->winevent))
{ {
WINEVENTPROC hook_proc; WINEVENTPROC hook_proc;
HMODULE free_module = 0;
hook_proc = wine_server_get_ptr( msg_data->winevent.hook_proc ); hook_proc = wine_server_get_ptr( msg_data->winevent.hook_proc );
size -= sizeof(msg_data->winevent); size -= sizeof(msg_data->winevent);
...@@ -2825,7 +2826,7 @@ static BOOL peek_message( MSG *msg, HWND hwnd, UINT first, UINT last, UINT flags ...@@ -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) ); size = min( size, (MAX_PATH - 1) * sizeof(WCHAR) );
memcpy( module, &msg_data->winevent + 1, size ); memcpy( module, &msg_data->winevent + 1, size );
module[size / sizeof(WCHAR)] = 0; 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) ); ERR( "invalid winevent hook module name %s\n", debugstr_w(module) );
continue; continue;
...@@ -2847,6 +2848,8 @@ static BOOL peek_message( MSG *msg, HWND hwnd, UINT first, UINT last, UINT flags ...@@ -2847,6 +2848,8 @@ static BOOL peek_message( MSG *msg, HWND hwnd, UINT first, UINT last, UINT flags
GetCurrentThreadId(), hook_proc, GetCurrentThreadId(), hook_proc,
msg_data->winevent.hook, info.msg.message, info.msg.hwnd, info.msg.wParam, msg_data->winevent.hook, info.msg.message, info.msg.hwnd, info.msg.wParam,
info.msg.lParam, msg_data->winevent.tid, info.msg.time); info.msg.lParam, msg_data->winevent.tid, info.msg.time);
if (free_module) FreeLibrary(free_module);
} }
continue; continue;
case MSG_HOOK_LL: case MSG_HOOK_LL:
......
...@@ -225,7 +225,7 @@ extern void move_window_bits( HWND hwnd, struct window_surface *old_surface, ...@@ -225,7 +225,7 @@ extern void move_window_bits( HWND hwnd, struct window_surface *old_surface,
struct window_surface *new_surface, struct window_surface *new_surface,
const RECT *visible_rect, const RECT *old_visible_rect, const RECT *visible_rect, const RECT *old_visible_rect,
const RECT *client_rect, const RECT *valid_rects ) DECLSPEC_HIDDEN; 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 RECT get_virtual_screen_rect(void) DECLSPEC_HIDDEN;
extern LRESULT call_current_hook( HHOOK hhook, INT code, WPARAM wparam, LPARAM lparam ) 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; extern DWORD get_input_codepage( void ) DECLSPEC_HIDDEN;
......
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