From 36384097c7e8c4420eaedfac271e10b23b90df4f Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Tue, 11 Jul 2023 16:03:26 +0200 Subject: [PATCH] win32u: Pass module name before packed lparam in win_hook_params. --- dlls/user32/hook.c | 15 +++++++------- dlls/win32u/hook.c | 49 ++++++++++++++++++++++---------------------- dlls/wow64win/user.c | 30 +++++++++++++++------------ include/ntuser.h | 2 +- 4 files changed, 51 insertions(+), 45 deletions(-) diff --git a/dlls/user32/hook.c b/dlls/user32/hook.c index 6f202a0f5d9..e17f23fde5c 100644 --- a/dlls/user32/hook.c +++ b/dlls/user32/hook.c @@ -455,20 +455,20 @@ BOOL WINAPI User32CallWinEventHook( const struct win_event_hook_params *params, BOOL WINAPI User32CallWindowsHook( struct win_hook_params *params, ULONG size ) { HOOKPROC proc = params->proc; - const WCHAR *module = NULL; HMODULE free_module = 0; void *ret_ptr = NULL; CBT_CREATEWNDW cbtc; UINT ret_size = 0; + size_t lparam_offset; LRESULT ret; - if (size > sizeof(*params) + params->lparam_size) - module = (const WCHAR *)((const char *)(params + 1) + params->lparam_size); + lparam_offset = FIELD_OFFSET( struct win_hook_params, module[wcslen( params->module ) + 1]); - if (params->lparam_size) + if (lparam_offset < size) { - ret_size = params->lparam_size; - ret_ptr = params + 1; + lparam_offset = (lparam_offset + 15) & ~15; /* align */ + ret_size = size - lparam_offset; + ret_ptr = (char *)params + lparam_offset; params->lparam = (LPARAM)ret_ptr; if (params->id == WH_CBT && params->code == HCBT_CREATEWND) @@ -490,7 +490,8 @@ BOOL WINAPI User32CallWindowsHook( struct win_hook_params *params, ULONG size ) ret_size = sizeof(*cs); } } - if (module && !(proc = get_hook_proc( proc, module, &free_module ))) return FALSE; + if (params->module[0] && !(proc = get_hook_proc( proc, params->module, &free_module ))) + return FALSE; ret = call_hook_proc( proc, params->id, params->code, params->wparam, params->lparam, params->prev_unicode, params->next_unicode ); diff --git a/dlls/win32u/hook.c b/dlls/win32u/hook.c index 4b9f22f7afd..59c5df33f59 100644 --- a/dlls/win32u/hook.c +++ b/dlls/win32u/hook.c @@ -195,7 +195,7 @@ static UINT get_ll_hook_timeout(void) * Call hook either in current thread or send message to the destination * thread. */ -static LRESULT call_hook( struct win_hook_params *info, const WCHAR *module ) +static LRESULT call_hook( struct win_hook_params *info, const WCHAR *module, size_t lparam_size ) { DWORD_PTR ret = 0; @@ -233,43 +233,48 @@ static LRESULT call_hook( struct win_hook_params *info, const WCHAR *module ) HHOOK prev = thread_info->hook; BOOL prev_unicode = thread_info->hook_unicode; struct win_hook_params *params = info; + ULONG lparam_ret_size = lparam_size; ULONG size = sizeof(*params); - ULONG lparam_ret_size = params->lparam_size; CREATESTRUCTW *cs = NULL; void *ret_ptr; ULONG ret_len; - if (params->lparam_size) + size = FIELD_OFFSET( struct win_hook_params, module[module ? lstrlenW( module ) + 1 : 1] ); + + if (lparam_size) { - lparam_ret_size = params->lparam_size; + size = (size + 15) & ~15; /* align offset */ + lparam_ret_size = lparam_size; if (params->id == WH_CBT && params->code == HCBT_CREATEWND) { cs = ((CBT_CREATEWNDW *)params->lparam)->lpcs; params->lparam = 0; lparam_ret_size = 0; - params->lparam_size = sizeof(*cs); + lparam_size = sizeof(*cs); if (!IS_INTRESOURCE( cs->lpszName )) - params->lparam_size += (wcslen( cs->lpszName ) + 1) * sizeof(WCHAR); + lparam_size += (wcslen( cs->lpszName ) + 1) * sizeof(WCHAR); if (!IS_INTRESOURCE( cs->lpszClass )) - params->lparam_size += (wcslen( cs->lpszClass ) + 1) * sizeof(WCHAR); + lparam_size += (wcslen( cs->lpszClass ) + 1) * sizeof(WCHAR); } - - size += params->lparam_size; } - if (module && module[0]) size += (lstrlenW( module ) + 1) * sizeof(WCHAR); - if (size != sizeof(*params)) + if (size + lparam_size > sizeof(*info)) { - if (!(params = malloc( size ))) return 0; - *params = *info; + if (!(params = malloc( size + lparam_size ))) return 0; + memcpy( params, info, FIELD_OFFSET( struct win_hook_params, module )); } + if (module) + wcscpy( params->module, module ); + else + params->module[0] = 0; - if (params->lparam_size) + if (lparam_size) { + void *lparam_ptr = (char *)params + size; if (cs) { - CREATESTRUCTW *params_cs = (CREATESTRUCTW *)(params + 1); + CREATESTRUCTW *params_cs = lparam_ptr; WCHAR *ptr = (WCHAR *)(params_cs + 1); const void *inline_ptr = (void *)0xffffffff; @@ -289,13 +294,10 @@ static LRESULT call_hook( struct win_hook_params *info, const WCHAR *module ) } else { - memcpy( params + 1, (const void *)params->lparam, params->lparam_size ); + memcpy( lparam_ptr, (const void *)params->lparam, lparam_size ); } } - if (module && module[0]) - wcscpy( (WCHAR *)((char *)(params + 1) + params->lparam_size), module ); - /* * Windows protects from stack overflow in recursive hook calls. Different Windows * allow different depths. @@ -314,7 +316,7 @@ static LRESULT call_hook( struct win_hook_params *info, const WCHAR *module ) thread_info->hook = params->handle; thread_info->hook_unicode = params->next_unicode; thread_info->hook_call_depth++; - ret = KeUserModeCallback( NtUserCallWindowsHook, params, size, &ret_ptr, &ret_len ); + ret = KeUserModeCallback( NtUserCallWindowsHook, params, size + lparam_size, &ret_ptr, &ret_len ); if (ret_len && ret_len == lparam_ret_size) memcpy( (void *)params->lparam, ret_ptr, lparam_ret_size ); thread_info->hook = prev; @@ -363,7 +365,7 @@ LRESULT WINAPI NtUserCallNextHookEx( HHOOK hhook, INT code, WPARAM wparam, LPARA info.wparam = wparam; info.lparam = lparam; info.prev_unicode = thread_info->hook_unicode; - return call_hook( &info, module ); + return call_hook( &info, module, 0 ); } LRESULT call_current_hook( HHOOK hhook, INT code, WPARAM wparam, LPARAM lparam ) @@ -396,7 +398,7 @@ LRESULT call_current_hook( HHOOK hhook, INT code, WPARAM wparam, LPARAM lparam ) info.wparam = wparam; info.lparam = lparam; info.prev_unicode = TRUE; /* assume Unicode for this function */ - return call_hook( &info, module ); + return call_hook( &info, module, 0 ); } LRESULT call_hooks( INT id, INT code, WPARAM wparam, LPARAM lparam, size_t lparam_size ) @@ -440,8 +442,7 @@ LRESULT call_hooks( INT id, INT code, WPARAM wparam, LPARAM lparam, size_t lpara info.code = code; info.wparam = wparam; info.lparam = lparam; - info.lparam_size = lparam_size; - ret = call_hook( &info, module ); + ret = call_hook( &info, module, lparam_size ); SERVER_START_REQ( finish_hook_chain ) { diff --git a/dlls/wow64win/user.c b/dlls/wow64win/user.c index c60df5052dc..fcd19c7f798 100644 --- a/dlls/wow64win/user.c +++ b/dlls/wow64win/user.c @@ -349,9 +349,9 @@ struct win_hook_params32 int code; ULONG wparam; ULONG lparam; - UINT lparam_size; BOOL prev_unicode; BOOL next_unicode; + WCHAR module[1]; }; struct win_event_hook_params32 @@ -754,13 +754,14 @@ static NTSTATUS WINAPI wow64_NtUserCallWindowsHook( void *arg, ULONG size ) { struct win_hook_params *params = arg; struct win_hook_params32 params32; - UINT lparam64_size, module_size; + UINT module_len, size32, offset; void *ret_ptr; ULONG ret_len; NTSTATUS ret; - module_size = size - params->lparam_size - sizeof(*params); - lparam64_size = params->lparam_size; + module_len = wcslen( params->module ); + size32 = FIELD_OFFSET( struct win_hook_params32, module[module_len + 1] ); + offset = FIELD_OFFSET( struct win_hook_params, module[module_len + 1] ); params32.proc = PtrToUlong( params->proc ); params32.handle = HandleToUlong( params->handle ); @@ -772,16 +773,19 @@ static NTSTATUS WINAPI wow64_NtUserCallWindowsHook( void *arg, ULONG size ) params32.lparam = params->lparam; params32.prev_unicode = params->prev_unicode; params32.next_unicode = params->next_unicode; - params32.lparam_size = hook_lparam_64to32( params32.id, params32.code, params + 1, - lparam64_size, (char *)arg + sizeof(params32) ); - memcpy( arg, ¶ms32, sizeof(params32) ); - if (module_size) - memmove( (char *)arg + sizeof(params32) + params32.lparam_size, - (const char *)arg + size - module_size, module_size ); + memcpy( arg, ¶ms32, FIELD_OFFSET( struct win_hook_params32, module )); + memmove( ((struct win_hook_params32 *)arg)->module, params->module, + (module_len + 1) * sizeof(WCHAR) ); - ret = Wow64KiUserCallbackDispatcher( NtUserCallWindowsHook, arg, - sizeof(params32) + params32.lparam_size + module_size, - &ret_ptr, &ret_len ); + if (size > offset) + { + size32 = (size32 + 15) & ~15; + offset = (offset + 15) & ~15; + size32 += hook_lparam_64to32( params32.id, params32.code, (char *)params + offset, + size - offset, (char *)arg + size32 ); + } + + ret = Wow64KiUserCallbackDispatcher( NtUserCallWindowsHook, arg, size32, &ret_ptr, &ret_len ); switch (params32.id) { diff --git a/include/ntuser.h b/include/ntuser.h index 195d4e1322a..7d679e9ede1 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -167,9 +167,9 @@ struct win_hook_params int code; WPARAM wparam; LPARAM lparam; - UINT lparam_size; BOOL prev_unicode; BOOL next_unicode; + WCHAR module[1]; }; /* NtUserCopyImage params */