win32u: Pass module name before packed lparam in win_hook_params.

This commit is contained in:
Jacek Caban 2023-07-11 16:03:26 +02:00 committed by Alexandre Julliard
parent 730d462b7f
commit 36384097c7
4 changed files with 51 additions and 45 deletions

View file

@ -455,20 +455,20 @@ BOOL WINAPI User32CallWinEventHook( const struct win_event_hook_params *params,
BOOL WINAPI User32CallWindowsHook( struct win_hook_params *params, ULONG size ) BOOL WINAPI User32CallWindowsHook( struct win_hook_params *params, ULONG size )
{ {
HOOKPROC proc = params->proc; HOOKPROC proc = params->proc;
const WCHAR *module = NULL;
HMODULE free_module = 0; HMODULE free_module = 0;
void *ret_ptr = NULL; void *ret_ptr = NULL;
CBT_CREATEWNDW cbtc; CBT_CREATEWNDW cbtc;
UINT ret_size = 0; UINT ret_size = 0;
size_t lparam_offset;
LRESULT ret; LRESULT ret;
if (size > sizeof(*params) + params->lparam_size) lparam_offset = FIELD_OFFSET( struct win_hook_params, module[wcslen( params->module ) + 1]);
module = (const WCHAR *)((const char *)(params + 1) + params->lparam_size);
if (params->lparam_size) if (lparam_offset < size)
{ {
ret_size = params->lparam_size; lparam_offset = (lparam_offset + 15) & ~15; /* align */
ret_ptr = params + 1; ret_size = size - lparam_offset;
ret_ptr = (char *)params + lparam_offset;
params->lparam = (LPARAM)ret_ptr; params->lparam = (LPARAM)ret_ptr;
if (params->id == WH_CBT && params->code == HCBT_CREATEWND) 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); 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, ret = call_hook_proc( proc, params->id, params->code, params->wparam, params->lparam,
params->prev_unicode, params->next_unicode ); params->prev_unicode, params->next_unicode );

View file

@ -195,7 +195,7 @@ static UINT get_ll_hook_timeout(void)
* Call hook either in current thread or send message to the destination * Call hook either in current thread or send message to the destination
* thread. * 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; 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; HHOOK prev = thread_info->hook;
BOOL prev_unicode = thread_info->hook_unicode; BOOL prev_unicode = thread_info->hook_unicode;
struct win_hook_params *params = info; struct win_hook_params *params = info;
ULONG lparam_ret_size = lparam_size;
ULONG size = sizeof(*params); ULONG size = sizeof(*params);
ULONG lparam_ret_size = params->lparam_size;
CREATESTRUCTW *cs = NULL; CREATESTRUCTW *cs = NULL;
void *ret_ptr; void *ret_ptr;
ULONG ret_len; 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) if (params->id == WH_CBT && params->code == HCBT_CREATEWND)
{ {
cs = ((CBT_CREATEWNDW *)params->lparam)->lpcs; cs = ((CBT_CREATEWNDW *)params->lparam)->lpcs;
params->lparam = 0; params->lparam = 0;
lparam_ret_size = 0; lparam_ret_size = 0;
params->lparam_size = sizeof(*cs); lparam_size = sizeof(*cs);
if (!IS_INTRESOURCE( cs->lpszName )) 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 )) 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 + lparam_size > sizeof(*info))
if (size != sizeof(*params))
{ {
if (!(params = malloc( size ))) return 0; if (!(params = malloc( size + lparam_size ))) return 0;
*params = *info; 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) if (cs)
{ {
CREATESTRUCTW *params_cs = (CREATESTRUCTW *)(params + 1); CREATESTRUCTW *params_cs = lparam_ptr;
WCHAR *ptr = (WCHAR *)(params_cs + 1); WCHAR *ptr = (WCHAR *)(params_cs + 1);
const void *inline_ptr = (void *)0xffffffff; const void *inline_ptr = (void *)0xffffffff;
@ -289,13 +294,10 @@ static LRESULT call_hook( struct win_hook_params *info, const WCHAR *module )
} }
else 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 * Windows protects from stack overflow in recursive hook calls. Different Windows
* allow different depths. * 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 = params->handle;
thread_info->hook_unicode = params->next_unicode; thread_info->hook_unicode = params->next_unicode;
thread_info->hook_call_depth++; 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) if (ret_len && ret_len == lparam_ret_size)
memcpy( (void *)params->lparam, ret_ptr, lparam_ret_size ); memcpy( (void *)params->lparam, ret_ptr, lparam_ret_size );
thread_info->hook = prev; thread_info->hook = prev;
@ -363,7 +365,7 @@ LRESULT WINAPI NtUserCallNextHookEx( HHOOK hhook, INT code, WPARAM wparam, LPARA
info.wparam = wparam; info.wparam = wparam;
info.lparam = lparam; info.lparam = lparam;
info.prev_unicode = thread_info->hook_unicode; 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 ) 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.wparam = wparam;
info.lparam = lparam; info.lparam = lparam;
info.prev_unicode = TRUE; /* assume Unicode for this function */ 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 ) 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.code = code;
info.wparam = wparam; info.wparam = wparam;
info.lparam = lparam; info.lparam = lparam;
info.lparam_size = lparam_size; ret = call_hook( &info, module, lparam_size );
ret = call_hook( &info, module );
SERVER_START_REQ( finish_hook_chain ) SERVER_START_REQ( finish_hook_chain )
{ {

View file

@ -349,9 +349,9 @@ struct win_hook_params32
int code; int code;
ULONG wparam; ULONG wparam;
ULONG lparam; ULONG lparam;
UINT lparam_size;
BOOL prev_unicode; BOOL prev_unicode;
BOOL next_unicode; BOOL next_unicode;
WCHAR module[1];
}; };
struct win_event_hook_params32 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_params *params = arg;
struct win_hook_params32 params32; struct win_hook_params32 params32;
UINT lparam64_size, module_size; UINT module_len, size32, offset;
void *ret_ptr; void *ret_ptr;
ULONG ret_len; ULONG ret_len;
NTSTATUS ret; NTSTATUS ret;
module_size = size - params->lparam_size - sizeof(*params); module_len = wcslen( params->module );
lparam64_size = params->lparam_size; 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.proc = PtrToUlong( params->proc );
params32.handle = HandleToUlong( params->handle ); params32.handle = HandleToUlong( params->handle );
@ -772,16 +773,19 @@ static NTSTATUS WINAPI wow64_NtUserCallWindowsHook( void *arg, ULONG size )
params32.lparam = params->lparam; params32.lparam = params->lparam;
params32.prev_unicode = params->prev_unicode; params32.prev_unicode = params->prev_unicode;
params32.next_unicode = params->next_unicode; params32.next_unicode = params->next_unicode;
params32.lparam_size = hook_lparam_64to32( params32.id, params32.code, params + 1, memcpy( arg, &params32, FIELD_OFFSET( struct win_hook_params32, module ));
lparam64_size, (char *)arg + sizeof(params32) ); memmove( ((struct win_hook_params32 *)arg)->module, params->module,
memcpy( arg, &params32, sizeof(params32) ); (module_len + 1) * sizeof(WCHAR) );
if (module_size)
memmove( (char *)arg + sizeof(params32) + params32.lparam_size,
(const char *)arg + size - module_size, module_size );
ret = Wow64KiUserCallbackDispatcher( NtUserCallWindowsHook, arg, if (size > offset)
sizeof(params32) + params32.lparam_size + module_size, {
&ret_ptr, &ret_len ); 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) switch (params32.id)
{ {

View file

@ -167,9 +167,9 @@ struct win_hook_params
int code; int code;
WPARAM wparam; WPARAM wparam;
LPARAM lparam; LPARAM lparam;
UINT lparam_size;
BOOL prev_unicode; BOOL prev_unicode;
BOOL next_unicode; BOOL next_unicode;
WCHAR module[1];
}; };
/* NtUserCopyImage params */ /* NtUserCopyImage params */