We currently try to preserve message's lparam value in win32u. This is inherited from user32 and it was needed in the past, but with !493 (and !646), this is mostly covered by leaving win32u out of winproc calls whenever possible. According to tests, native win32k almost never attempts to preserve lparam and copies its content instead (with a few exceptions for messages passing strings). Implementing that in Wine will provide a nice way to fix problem from bug 55152.
This is the first patch in the series that will implement it. Since user callback requirements are different than server communication, the series incrementally decouples them. I created https://gitlab.winehq.org/jacek/wine/-/commits/win32u-msg/ with complete conversion for a better context.
From: Jacek Caban jacek@codeweavers.com
--- dlls/user32/winproc.c | 54 ++++++------ dlls/win32u/message.c | 187 +++++++++++++++++++++++++++++++++++++----- dlls/wow64win/user.c | 72 +++++++++++++++- 3 files changed, 262 insertions(+), 51 deletions(-)
diff --git a/dlls/user32/winproc.c b/dlls/user32/winproc.c index 36acd7b6382..8b5b65296f4 100644 --- a/dlls/user32/winproc.c +++ b/dlls/user32/winproc.c @@ -789,13 +789,18 @@ static inline BOOL check_string( LPCWSTR str, size_t size ) return FALSE; }
+static size_t string_size( const void *str, BOOL ansi ) +{ + return ansi ? strlen( str ) + 1 : (wcslen( str ) + 1) * sizeof(WCHAR); +} + /*********************************************************************** * unpack_message * * Unpack a message received from another process. */ static BOOL unpack_message( HWND hwnd, UINT message, WPARAM *wparam, LPARAM *lparam, - void **buffer, size_t size ) + void **buffer, size_t size, BOOL ansi ) { size_t minsize = 0, prev_size = size; union packed_structs *ps = *buffer; @@ -805,35 +810,18 @@ static BOOL unpack_message( HWND hwnd, UINT message, WPARAM *wparam, LPARAM *lpa case WM_NCCREATE: case WM_CREATE: { - CREATESTRUCTW cs; - WCHAR *str = (WCHAR *)(&ps->cs + 1); - if (size < sizeof(ps->cs)) return FALSE; - size -= sizeof(ps->cs); - cs.lpCreateParams = unpack_ptr( ps->cs.lpCreateParams ); - cs.hInstance = unpack_ptr( ps->cs.hInstance ); - cs.hMenu = unpack_handle( ps->cs.hMenu ); - cs.hwndParent = unpack_handle( ps->cs.hwndParent ); - cs.cy = ps->cs.cy; - cs.cx = ps->cs.cx; - cs.y = ps->cs.y; - cs.x = ps->cs.x; - cs.style = ps->cs.style; - cs.dwExStyle = ps->cs.dwExStyle; - cs.lpszName = unpack_ptr( ps->cs.lpszName ); - cs.lpszClass = unpack_ptr( ps->cs.lpszClass ); - if (ps->cs.lpszName >> 16) + CREATESTRUCTA *cs = *buffer; + char *str = (char *)(cs + 1); + + if (!IS_INTRESOURCE(cs->lpszName)) { - if (!check_string( str, size )) return FALSE; - cs.lpszName = str; - size -= (lstrlenW(str) + 1) * sizeof(WCHAR); - str += lstrlenW(str) + 1; + cs->lpszName = str; + str += string_size( str, ansi ); } - if (ps->cs.lpszClass >> 16) + if (!IS_INTRESOURCE(cs->lpszClass)) { - if (!check_string( str, size )) return FALSE; - cs.lpszClass = str; + cs->lpszClass = str; } - memcpy( *buffer, &cs, sizeof(cs) ); break; } case WM_GETTEXT: @@ -1186,6 +1174,7 @@ BOOL WINAPI User32CallWindowProc( struct win_proc_params *params, ULONG size ) if (params->needs_unpack) { char stack_buffer[128]; + size_t msg_size = size - sizeof(*params); void *buffer;
if (size > sizeof(*params)) @@ -1199,11 +1188,22 @@ BOOL WINAPI User32CallWindowProc( struct win_proc_params *params, ULONG size ) buffer = stack_buffer; } if (!unpack_message( params->hwnd, params->msg, ¶ms->wparam, - ¶ms->lparam, &buffer, size )) + ¶ms->lparam, &buffer, size, params->ansi )) return 0;
result = dispatch_win_proc_params( params );
+ switch (params->msg) + { + case WM_NCCREATE: + case WM_CREATE: + { + LRESULT *result_ptr = (LRESULT *)buffer - 1; + *result_ptr = result; + return NtCallbackReturn( result_ptr, sizeof(*result_ptr) + msg_size, TRUE ); + } + } + NtUserMessageCall( params->hwnd, params->msg, params->wparam, params->lparam, (void *)result, NtUserWinProcResult, FALSE ); if (buffer != stack_buffer && buffer != params + 1) diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index 49ac4b2de94..3cb9c4107c1 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -255,7 +255,8 @@ static BOOL init_window_call_params( struct win_proc_params *params, HWND hwnd, return TRUE; }
-static LRESULT dispatch_win_proc_params( struct win_proc_params *params, size_t size ) +static LRESULT dispatch_win_proc_params( struct win_proc_params *params, size_t size, + void **client_ret, size_t *client_ret_size ) { struct ntuser_thread_info *thread_info = NtUserGetThreadInfo(); LRESULT result = 0; @@ -264,11 +265,19 @@ static LRESULT dispatch_win_proc_params( struct win_proc_params *params, size_t
if (thread_info->recursion_count > MAX_WINPROC_RECURSION) return 0; thread_info->recursion_count++; - KeUserModeCallback( NtUserCallWinProc, params, size, &ret_ptr, &ret_len ); - if (ret_len == sizeof(result)) result = *(LRESULT *)ret_ptr; - thread_info->recursion_count--; + + if (ret_len >= sizeof(result)) + { + result = *(LRESULT *)ret_ptr; + if (client_ret) + { + *client_ret = (LRESULT *)ret_ptr + 1; + *client_ret_size = ret_len - sizeof(result); + } + } + return result; }
@@ -346,6 +355,38 @@ static BOOL unpack_message( HWND hwnd, UINT message, WPARAM *wparam, LPARAM *lpa
switch(message) { + case WM_NCCREATE: + case WM_CREATE: + { + CREATESTRUCTW cs; + WCHAR *str = (WCHAR *)(&ps->cs + 1); + if (size < sizeof(ps->cs)) return FALSE; + size -= sizeof(ps->cs); + cs.lpCreateParams = unpack_ptr( ps->cs.lpCreateParams ); + cs.hInstance = unpack_ptr( ps->cs.hInstance ); + cs.hMenu = wine_server_ptr_handle( ps->cs.hMenu ); + cs.hwndParent = wine_server_ptr_handle( ps->cs.hwndParent ); + cs.cy = ps->cs.cy; + cs.cx = ps->cs.cx; + cs.y = ps->cs.y; + cs.x = ps->cs.x; + cs.style = ps->cs.style; + cs.dwExStyle = ps->cs.dwExStyle; + cs.lpszName = unpack_ptr( ps->cs.lpszName ); + cs.lpszClass = unpack_ptr( ps->cs.lpszClass ); + if (ps->cs.lpszName >> 16) + { + cs.lpszName = str; + size -= (lstrlenW(str) + 1) * sizeof(WCHAR); + str += lstrlenW(str) + 1; + } + if (ps->cs.lpszClass >> 16) + { + cs.lpszClass = str; + } + memcpy( *buffer, &cs, sizeof(cs) ); + break; + } case WM_WINE_SETWINDOWPOS: { WINDOWPOS wp; @@ -1076,23 +1117,100 @@ static void unpack_reply( HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam, } }
+static size_t string_size( const void *str, BOOL ansi ) +{ + return ansi ? strlen( str ) + 1 : (wcslen( str ) + 1) * sizeof(WCHAR); +} + +static size_t copy_string( void *ptr, const void *str, BOOL ansi ) +{ + size_t size = string_size( str, ansi ); + memcpy( ptr, str, size ); + return size; +} + /*********************************************************************** - * copy_reply + * user_message_size * - * Copy a message reply received from client. + * Calculate size of packed message buffer. */ -static void copy_reply( LRESULT result, HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam, - WPARAM wparam_src, LPARAM lparam_src ) +static size_t user_message_size( UINT message, LPARAM lparam, BOOL ansi ) { - size_t copy_size = 0; + const void *lparam_ptr = (const void *)lparam; + size_t size = 0;
- switch(message) + switch (message) { case WM_NCCREATE: case WM_CREATE: + { + const CREATESTRUCTW *cs = lparam_ptr; + size = sizeof(*cs); + if (!IS_INTRESOURCE(cs->lpszName)) size += string_size( cs->lpszName, ansi ); + if (!IS_INTRESOURCE(cs->lpszClass)) size += string_size( cs->lpszClass, ansi ); + break; + } + } + + return size; +} + +/*********************************************************************** + * pack_user_message + * + * Copy message to a buffer for passing to client. + */ +static void pack_user_message( void *buffer, size_t size, UINT message, LPARAM lparam, BOOL ansi ) +{ + const void *lparam_ptr = (const void *)lparam; + void const *inline_ptr = (void *)0xffffffff; + + if (!size) return; + + switch (message) + { + case WM_NCCREATE: + case WM_CREATE: + { + CREATESTRUCTW *cs = buffer; + char *ptr = (char *)(cs + 1); + + memcpy( cs, lparam_ptr, sizeof(*cs) ); + if (!IS_INTRESOURCE(cs->lpszName)) + { + ptr += copy_string( ptr, cs->lpszName, ansi ); + cs->lpszName = inline_ptr; + } + if (!IS_INTRESOURCE(cs->lpszClass)) { - CREATESTRUCTW *dst = (CREATESTRUCTW *)lparam; - CREATESTRUCTW *src = (CREATESTRUCTW *)lparam_src; + copy_string( ptr, cs->lpszClass, ansi ); + cs->lpszClass = inline_ptr; + } + return; + } + } + +} + +/*********************************************************************** + * copy_user_result + * + * Copy a message result received from client. + */ +static void copy_user_result( void *buffer, size_t size, UINT message, WPARAM wparam, LPARAM lparam ) +{ + void *lparam_ptr = (void *)lparam; + + if (!size) return; + + switch (message) + { + case WM_NCCREATE: + case WM_CREATE: + if (size >= sizeof(CREATESTRUCTW)) + { + CREATESTRUCTW *dst = lparam_ptr; + const CREATESTRUCTW *src = buffer; dst->lpCreateParams = src->lpCreateParams; dst->hInstance = src->hInstance; dst->hMenu = src->hMenu; @@ -1106,6 +1224,23 @@ static void copy_reply( LRESULT result, HWND hwnd, UINT message, WPARAM wparam, /* don't allow changing name and class pointers */ } return; + default: + return; + } +} + +/*********************************************************************** + * copy_reply + * + * Copy a message reply received from client. + */ +static void copy_reply( LRESULT result, HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam, + WPARAM wparam_src, LPARAM lparam_src ) +{ + size_t copy_size = 0; + + switch(message) + { case WM_GETTEXT: case CB_GETLBTEXT: case LB_GETTEXT: @@ -1373,9 +1508,13 @@ static LRESULT call_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpar BOOL needs_unpack, void *buffer, size_t size ) { struct win_proc_params p, *params = &p; + BOOL ansi = !unicode && !needs_unpack; LRESULT result = 0; CWPSTRUCT cwp; CWPRETSTRUCT cwpret; + size_t packed_size = 0; + void *ret_ptr; + size_t ret_len = 0;
if (msg & 0x80000000) return handle_internal_message( hwnd, msg, wparam, lparam ); @@ -1383,6 +1522,9 @@ static LRESULT call_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpar if (!needs_unpack) size = 0; if (!is_current_thread_window( hwnd )) return 0;
+ packed_size = user_message_size( msg, lparam, ansi ); + if (packed_size) size = packed_size; + /* first the WH_CALLWNDPROC hook */ cwp.lParam = lparam; cwp.wParam = wparam; @@ -1397,15 +1539,18 @@ static LRESULT call_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpar return 0; }
- if (needs_unpack) - { - params->needs_unpack = TRUE; - params->ansi = FALSE; - if (size) memcpy( params + 1, buffer, size ); - } - result = dispatch_win_proc_params( params, sizeof(*params) + size ); + if (needs_unpack) params->ansi = FALSE; + params->needs_unpack = needs_unpack || packed_size; + if (packed_size) + pack_user_message( params + 1, packed_size, msg, lparam, ansi ); + else if (size) + memcpy( params + 1, buffer, size ); + + result = dispatch_win_proc_params( params, sizeof(*params) + size, &ret_ptr, &ret_len ); if (params != &p) free( params );
+ copy_user_result( ret_ptr, min( ret_len, packed_size ), msg, wparam, lparam ); + /* and finally the WH_CALLWNDPROCRET hook */ cwpret.lResult = result; cwpret.lParam = lparam; @@ -2750,7 +2895,7 @@ LRESULT WINAPI NtUserDispatchMessage( const MSG *msg ) if (!init_win_proc_params( ¶ms, msg->hwnd, msg->message, msg->wParam, NtGetTickCount(), FALSE )) return 0; - return dispatch_win_proc_params( ¶ms, sizeof(params) ); + return dispatch_win_proc_params( ¶ms, sizeof(params), NULL, NULL ); } if (msg->message == WM_SYSTIMER) { @@ -2772,7 +2917,7 @@ LRESULT WINAPI NtUserDispatchMessage( const MSG *msg )
if (init_window_call_params( ¶ms, msg->hwnd, msg->message, msg->wParam, msg->lParam, FALSE, WMCHAR_MAP_DISPATCHMESSAGE )) - retval = dispatch_win_proc_params( ¶ms, sizeof(params) ); + retval = dispatch_win_proc_params( ¶ms, sizeof(params), NULL, NULL ); else if (!is_window( msg->hwnd )) RtlSetLastWin32Error( ERROR_INVALID_WINDOW_HANDLE ); else RtlSetLastWin32Error( ERROR_MESSAGE_SYNC_ONLY );
diff --git a/dlls/wow64win/user.c b/dlls/wow64win/user.c index fcd19c7f798..de221658a94 100644 --- a/dlls/wow64win/user.c +++ b/dlls/wow64win/user.c @@ -614,10 +614,66 @@ static NTSTATUS WINAPI wow64_NtUserCallWinEventHook( void *arg, ULONG size ) FIELD_OFFSET( struct win_event_hook_params32, module ) + size); }
+static size_t packed_message_64to32( UINT message, const void *params64, void *params32, size_t size ) +{ + if (!size) return 0; + + switch (message) + { + case WM_NCCREATE: + case WM_CREATE: + { + CREATESTRUCT32 *cs32 = params32; + const CREATESTRUCTW *cs64 = params64; + + createstruct_64to32( cs64, cs32 ); + size -= sizeof(*cs64); + if (size) memmove( cs32 + 1, cs64 + 1, size ); + return sizeof(*cs32) + size; + } + } + + memmove( params32, params64, size ); + return size; +} + +static size_t packed_result_32to64( UINT message, const void *params32, size_t size, void *params64 ) +{ + switch (message) + { + case WM_NCCREATE: + case WM_CREATE: + if (size >= sizeof(CREATESTRUCT32)) + { + const CREATESTRUCT32 *cs32 = params32; + CREATESTRUCTW *cs64 = params64; + + cs64->lpCreateParams = UlongToPtr( cs32->lpCreateParams ); + cs64->hInstance = UlongToPtr( cs32->hInstance ); + cs64->hMenu = LongToHandle( cs32->hMenu ); + cs64->hwndParent = LongToHandle( cs32->hwndParent ); + cs64->cy = cs32->cy; + cs64->cx = cs32->cx; + cs64->y = cs32->y; + cs64->x = cs32->x; + cs64->style = cs32->style; + cs64->dwExStyle = cs32->dwExStyle; + return sizeof(*cs64); + } + + default: + return 0; + } + + if (size) memcpy( params64, params32, size ); + return size; +} + static NTSTATUS WINAPI wow64_NtUserCallWinProc( void *arg, ULONG size ) { struct win_proc_params *params = arg; struct win_proc_params32 *params32 = arg; + size_t lparam_size = 0; LRESULT result = 0; void *ret_ptr; ULONG ret_len; @@ -625,13 +681,23 @@ static NTSTATUS WINAPI wow64_NtUserCallWinProc( void *arg, ULONG size )
win_proc_params_64to32( params, params32 ); if (size > sizeof(*params)) - memmove( params32 + 1, params + 1, size - sizeof(*params) ); + lparam_size = packed_message_64to32( params32->msg, params + 1, params32 + 1, + size - sizeof(*params) );
status = Wow64KiUserCallbackDispatcher( NtUserCallWinProc, params32, - size - sizeof(*params) + sizeof(*params32), + sizeof(*params32) + lparam_size, &ret_ptr, &ret_len );
- if (ret_len == sizeof(LONG)) result = *(LONG *)ret_ptr; + if (ret_len >= sizeof(LONG)) + { + LRESULT *result_ptr = arg; + result = *(LONG *)ret_ptr; + ret_len = packed_result_32to64( params32->msg, (LONG *)ret_ptr + 1, + ret_len - sizeof(LONG), result_ptr + 1 ); + *result_ptr = result; + return NtCallbackReturn( result_ptr, sizeof(*result_ptr) + ret_len, status ); + } + return NtCallbackReturn( &result, sizeof(result), status ); }
From: Jacek Caban jacek@codeweavers.com
--- dlls/user32/hook.c | 23 +++++------- dlls/user32/user_private.h | 2 ++ dlls/user32/winproc.c | 4 +-- dlls/win32u/hook.c | 70 ++++++++++++++++-------------------- dlls/win32u/message.c | 4 +-- dlls/win32u/win32u_private.h | 3 ++ dlls/wow64win/user.c | 9 +---- 7 files changed, 50 insertions(+), 65 deletions(-)
diff --git a/dlls/user32/hook.c b/dlls/user32/hook.c index e17f23fde5c..1465712adb2 100644 --- a/dlls/user32/hook.c +++ b/dlls/user32/hook.c @@ -471,23 +471,18 @@ BOOL WINAPI User32CallWindowsHook( struct win_hook_params *params, ULONG size ) ret_ptr = (char *)params + lparam_offset; params->lparam = (LPARAM)ret_ptr;
- if (params->id == WH_CBT && params->code == HCBT_CREATEWND) + switch (params->id) { - CREATESTRUCTW *cs = (CREATESTRUCTW *)params->lparam; - const WCHAR *ptr = (const WCHAR *)(cs + 1); - - if (!IS_INTRESOURCE(cs->lpszName)) + case WH_CBT: + if (params->code == HCBT_CREATEWND) { - cs->lpszName = ptr; - ptr += wcslen( ptr ) + 1; + cbtc.hwndInsertAfter = HWND_TOP; + unpack_message( (HWND)params->wparam, WM_CREATE, NULL, (LPARAM *)&cbtc.lpcs, + &ret_ptr, ret_size, FALSE ); + params->lparam = (LPARAM)&cbtc; + ret_size = sizeof(*cbtc.lpcs); } - if (!IS_INTRESOURCE(cs->lpszClass)) - cs->lpszClass = ptr; - - cbtc.hwndInsertAfter = HWND_TOP; - cbtc.lpcs = cs; - params->lparam = (LPARAM)&cbtc; - ret_size = sizeof(*cs); + break; } } if (params->module[0] && !(proc = get_hook_proc( proc, params->module, &free_module ))) diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h index 10f5d83b6f1..267c535defe 100644 --- a/dlls/user32/user_private.h +++ b/dlls/user32/user_private.h @@ -51,6 +51,8 @@ extern BOOL unpack_dde_message( HWND hwnd, UINT message, WPARAM *wparam, LPARAM const void *buffer, size_t size ) DECLSPEC_HIDDEN; extern void free_cached_data( UINT format, HANDLE handle ) DECLSPEC_HIDDEN; extern HANDLE render_synthesized_format( UINT format, UINT from ) DECLSPEC_HIDDEN; +extern BOOL unpack_message( HWND hwnd, UINT message, WPARAM *wparam, LPARAM *lparam, + void **buffer, size_t size, BOOL ansi );
extern void CLIPBOARD_ReleaseOwner( HWND hwnd ) DECLSPEC_HIDDEN; extern HDC get_display_dc(void) DECLSPEC_HIDDEN; diff --git a/dlls/user32/winproc.c b/dlls/user32/winproc.c index 8b5b65296f4..d79f37b80b8 100644 --- a/dlls/user32/winproc.c +++ b/dlls/user32/winproc.c @@ -799,8 +799,8 @@ static size_t string_size( const void *str, BOOL ansi ) * * Unpack a message received from another process. */ -static BOOL unpack_message( HWND hwnd, UINT message, WPARAM *wparam, LPARAM *lparam, - void **buffer, size_t size, BOOL ansi ) +BOOL unpack_message( HWND hwnd, UINT message, WPARAM *wparam, LPARAM *lparam, + void **buffer, size_t size, BOOL ansi ) { size_t minsize = 0, prev_size = size; union packed_structs *ps = *buffer; diff --git a/dlls/win32u/hook.c b/dlls/win32u/hook.c index 59c5df33f59..b880c8d37e0 100644 --- a/dlls/win32u/hook.c +++ b/dlls/win32u/hook.c @@ -230,12 +230,11 @@ static LRESULT call_hook( struct win_hook_params *info, const WCHAR *module, siz else if (info->proc) { struct user_thread_info *thread_info = get_user_thread_info(); + size_t size, lparam_offset = 0, message_offset = 0, message_size = 0; + size_t lparam_ret_size = lparam_size; 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); - CREATESTRUCTW *cs = NULL; void *ret_ptr; ULONG ret_len;
@@ -243,25 +242,29 @@ static LRESULT call_hook( struct win_hook_params *info, const WCHAR *module, siz
if (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; - lparam_size = sizeof(*cs); - if (!IS_INTRESOURCE( cs->lpszName )) - lparam_size += (wcslen( cs->lpszName ) + 1) * sizeof(WCHAR); - if (!IS_INTRESOURCE( cs->lpszClass )) - lparam_size += (wcslen( cs->lpszClass ) + 1) * sizeof(WCHAR); + CBT_CREATEWNDW *cbtc = (CBT_CREATEWNDW *)params->lparam; + message_size = user_message_size( WM_NCCREATE, (LPARAM)cbtc->lpcs, FALSE ); + lparam_size = lparam_ret_size = 0; + } + + if (lparam_size) + { + lparam_offset = (size + 15) & ~15; /* align offset */ + size = lparam_offset + lparam_size; + } + + if (message_size) + { + message_offset = (size + 15) & ~15; /* align offset */ + size = message_offset + message_size; } }
- if (size + lparam_size > sizeof(*info)) + if (size > sizeof(*info)) { - if (!(params = malloc( size + lparam_size ))) return 0; + if (!(params = malloc( size ))) return 0; memcpy( params, info, FIELD_OFFSET( struct win_hook_params, module )); } if (module) @@ -270,31 +273,20 @@ static LRESULT call_hook( struct win_hook_params *info, const WCHAR *module, siz params->module[0] = 0;
if (lparam_size) + memcpy( (char *)params + lparam_offset, (const void *)params->lparam, lparam_size ); + + if (message_size) { - void *lparam_ptr = (char *)params + size; - if (cs) + switch (params->id) { - CREATESTRUCTW *params_cs = lparam_ptr; - WCHAR *ptr = (WCHAR *)(params_cs + 1); - const void *inline_ptr = (void *)0xffffffff; - - *params_cs = *cs; - if (!IS_INTRESOURCE( cs->lpszName )) - { - UINT len = wcslen( cs->lpszName ) + 1; - memcpy( ptr, cs->lpszName, len * sizeof(WCHAR) ); - ptr += len; - params_cs->lpszName = inline_ptr; - } - if (!IS_INTRESOURCE( cs->lpszClass )) + case WH_CBT: { - wcscpy( ptr, cs->lpszClass ); - params_cs->lpszClass = inline_ptr; + CBT_CREATEWNDW *cbtc = (CBT_CREATEWNDW *)params->lparam; + LPARAM lp = (LPARAM)cbtc->lpcs; + pack_user_message( (char *)params + message_offset, message_size, + WM_CREATE, lp, FALSE ); } - } - else - { - memcpy( lparam_ptr, (const void *)params->lparam, lparam_size ); + break; } }
@@ -316,9 +308,9 @@ static LRESULT call_hook( struct win_hook_params *info, const WCHAR *module, siz thread_info->hook = params->handle; thread_info->hook_unicode = params->next_unicode; thread_info->hook_call_depth++; - ret = KeUserModeCallback( NtUserCallWindowsHook, params, size + lparam_size, &ret_ptr, &ret_len ); + ret = KeUserModeCallback( NtUserCallWindowsHook, params, size, &ret_ptr, &ret_len ); if (ret_len && ret_len == lparam_ret_size) - memcpy( (void *)params->lparam, ret_ptr, lparam_ret_size ); + memcpy( (void *)params->lparam, ret_ptr, ret_len ); thread_info->hook = prev; thread_info->hook_unicode = prev_unicode; thread_info->hook_call_depth--; diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index 3cb9c4107c1..fe048e0ee38 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -1134,7 +1134,7 @@ static size_t copy_string( void *ptr, const void *str, BOOL ansi ) * * Calculate size of packed message buffer. */ -static size_t user_message_size( UINT message, LPARAM lparam, BOOL ansi ) +size_t user_message_size( UINT message, LPARAM lparam, BOOL ansi ) { const void *lparam_ptr = (const void *)lparam; size_t size = 0; @@ -1160,7 +1160,7 @@ static size_t user_message_size( UINT message, LPARAM lparam, BOOL ansi ) * * Copy message to a buffer for passing to client. */ -static void pack_user_message( void *buffer, size_t size, UINT message, LPARAM lparam, BOOL ansi ) +void pack_user_message( void *buffer, size_t size, UINT message, LPARAM lparam, BOOL ansi ) { const void *lparam_ptr = (const void *)lparam; void const *inline_ptr = (void *)0xffffffff; diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index 005ab53cc01..8d6fb34776d 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -138,6 +138,9 @@ extern LRESULT send_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) extern BOOL send_notify_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, BOOL ansi ) DECLSPEC_HIDDEN; extern LRESULT send_message_timeout( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, UINT flags, UINT timeout, BOOL ansi ) DECLSPEC_HIDDEN; +extern size_t user_message_size( UINT message, LPARAM lparam, BOOL ansi ) DECLSPEC_HIDDEN; +extern void pack_user_message( void *buffer, size_t size, UINT message, LPARAM lparam, + BOOL ansi ) DECLSPEC_HIDDEN;
/* rawinput.c */ extern BOOL process_rawinput_message( MSG *msg, UINT hw_id, const struct hardware_msg_data *msg_data ) DECLSPEC_HIDDEN; diff --git a/dlls/wow64win/user.c b/dlls/wow64win/user.c index de221658a94..1fad0f566fd 100644 --- a/dlls/wow64win/user.c +++ b/dlls/wow64win/user.c @@ -717,14 +717,7 @@ static UINT hook_lparam_64to32( int id, int code, const void *lp, size_t size, v switch (code) { case HCBT_CREATEWND: - { - const CREATESTRUCTW *cs64 = lp; - CREATESTRUCT32 *cs32 = lp32; - createstruct_64to32( cs64, cs32 ); - size -= sizeof(*cs64); - if (size) memmove( cs32 + 1, cs64 + 1, size ); - return sizeof(*cs32) + size; - } + return packed_message_64to32( WM_CREATE, lp, lp32, size );
case HCBT_ACTIVATE: {
From: Jacek Caban jacek@codeweavers.com
--- dlls/user32/hook.c | 12 ++++++++++++ dlls/win32u/hook.c | 26 ++++++++++++++++++++------ dlls/win32u/message.c | 6 ++++-- dlls/win32u/win32u_private.h | 2 ++ dlls/wow64win/user.c | 9 +++++++++ 5 files changed, 47 insertions(+), 8 deletions(-)
diff --git a/dlls/user32/hook.c b/dlls/user32/hook.c index 1465712adb2..1ae49587688 100644 --- a/dlls/user32/hook.c +++ b/dlls/user32/hook.c @@ -483,6 +483,18 @@ BOOL WINAPI User32CallWindowsHook( struct win_hook_params *params, ULONG size ) ret_size = sizeof(*cbtc.lpcs); } break; + case WH_CALLWNDPROC: + if (ret_size > sizeof(CWPSTRUCT)) + { + CWPSTRUCT *cwp = (CWPSTRUCT *)params->lparam; + size_t offset = (lparam_offset + sizeof(*cwp) + 15) & ~15; + void *buffer = (char *)params + offset; + + unpack_message( cwp->hwnd, cwp->message, &cwp->wParam, &cwp->lParam, + &buffer, size - offset, !params->prev_unicode ); + ret_size = 0; + break; + } } } if (params->module[0] && !(proc = get_hook_proc( proc, params->module, &free_module ))) diff --git a/dlls/win32u/hook.c b/dlls/win32u/hook.c index b880c8d37e0..27b109ce545 100644 --- a/dlls/win32u/hook.c +++ b/dlls/win32u/hook.c @@ -195,7 +195,8 @@ 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, size_t lparam_size ) +static LRESULT call_hook( struct win_hook_params *info, const WCHAR *module, size_t lparam_size, + size_t message_size, BOOL ansi ) { DWORD_PTR ret = 0;
@@ -230,7 +231,7 @@ static LRESULT call_hook( struct win_hook_params *info, const WCHAR *module, siz else if (info->proc) { struct user_thread_info *thread_info = get_user_thread_info(); - size_t size, lparam_offset = 0, message_offset = 0, message_size = 0; + size_t size, lparam_offset = 0, message_offset = 0; size_t lparam_ret_size = lparam_size; HHOOK prev = thread_info->hook; BOOL prev_unicode = thread_info->hook_unicode; @@ -287,6 +288,13 @@ static LRESULT call_hook( struct win_hook_params *info, const WCHAR *module, siz WM_CREATE, lp, FALSE ); } break; + case WH_CALLWNDPROC: + { + CWPSTRUCT *cwp = (CWPSTRUCT *)((char *)params + lparam_offset); + pack_user_message( (char *)params + message_offset, message_size, + cwp->message, cwp->lParam, ansi ); + } + break; } }
@@ -357,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, 0 ); + return call_hook( &info, module, 0, 0, FALSE ); }
LRESULT call_current_hook( HHOOK hhook, INT code, WPARAM wparam, LPARAM lparam ) @@ -390,10 +398,11 @@ 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, 0 ); + return call_hook( &info, module, 0, 0, FALSE ); }
-LRESULT call_hooks( INT id, INT code, WPARAM wparam, LPARAM lparam, size_t lparam_size ) +LRESULT call_message_hooks( INT id, INT code, WPARAM wparam, LPARAM lparam, size_t lparam_size, + size_t message_size, BOOL ansi ) { struct user_thread_info *thread_info = get_user_thread_info(); struct win_hook_params info; @@ -434,7 +443,7 @@ LRESULT call_hooks( INT id, INT code, WPARAM wparam, LPARAM lparam, size_t lpara info.code = code; info.wparam = wparam; info.lparam = lparam; - ret = call_hook( &info, module, lparam_size ); + ret = call_hook( &info, module, lparam_size, message_size, ansi );
SERVER_START_REQ( finish_hook_chain ) { @@ -445,6 +454,11 @@ LRESULT call_hooks( INT id, INT code, WPARAM wparam, LPARAM lparam, size_t lpara return ret; }
+LRESULT call_hooks( INT id, INT code, WPARAM wparam, LPARAM lparam, size_t lparam_size ) +{ + return call_message_hooks( id, code, wparam, lparam, lparam_size, 0, FALSE ); +} + /*********************************************************************** * NtUserSetWinEventHook (win32u.@) */ diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index fe048e0ee38..5aec4c5eb95 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -1530,7 +1530,8 @@ static LRESULT call_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpar cwp.wParam = wparam; cwp.message = msg; cwp.hwnd = hwnd = get_full_window_handle( hwnd ); - call_hooks( WH_CALLWNDPROC, HC_ACTION, same_thread, (LPARAM)&cwp, sizeof(cwp) ); + call_message_hooks( WH_CALLWNDPROC, HC_ACTION, same_thread, (LPARAM)&cwp, sizeof(cwp), + packed_size, ansi );
if (size && !(params = malloc( sizeof(*params) + size ))) return 0; if (!init_window_call_params( params, hwnd, msg, wparam, lparam, !unicode, mapping )) @@ -1557,7 +1558,8 @@ static LRESULT call_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpar cwpret.wParam = wparam; cwpret.message = msg; cwpret.hwnd = hwnd; - call_hooks( WH_CALLWNDPROCRET, HC_ACTION, same_thread, (LPARAM)&cwpret, sizeof(cwpret) ); + call_message_hooks( WH_CALLWNDPROCRET, HC_ACTION, same_thread, (LPARAM)&cwpret, sizeof(cwpret), + packed_size, ansi ); return result; }
diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index 8d6fb34776d..b27ba7fab14 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -75,6 +75,8 @@ extern LRESULT handle_nc_hit_test( HWND hwnd, POINT pt ) DECLSPEC_HIDDEN; extern LRESULT call_current_hook( HHOOK hhook, INT code, WPARAM wparam, LPARAM lparam ) DECLSPEC_HIDDEN; extern LRESULT call_hooks( INT id, INT code, WPARAM wparam, LPARAM lparam, size_t lparam_size ) DECLSPEC_HIDDEN; +extern LRESULT call_message_hooks( INT id, INT code, WPARAM wparam, LPARAM lparam, + size_t lparam_size, size_t message_size, BOOL ansi ) DECLSPEC_HIDDEN; extern BOOL is_hooked( INT id ) DECLSPEC_HIDDEN; extern BOOL unhook_windows_hook( INT id, HOOKPROC proc ) DECLSPEC_HIDDEN;
diff --git a/dlls/wow64win/user.c b/dlls/wow64win/user.c index 1fad0f566fd..94df46cbb90 100644 --- a/dlls/wow64win/user.c +++ b/dlls/wow64win/user.c @@ -744,6 +744,15 @@ static UINT hook_lparam_64to32( int id, int code, const void *lp, size_t size, v cwp32.message = cwp->message; cwp32.hwnd = HandleToUlong( cwp->hwnd ); memcpy( lp32, &cwp32, sizeof(cwp32) ); + if (size > sizeof(*cwp)) + { + const size_t offset64 = (sizeof(*cwp) + 15) & ~15; + const size_t offset32 = (sizeof(cwp32) + 15) & ~15; + size = packed_message_64to32( cwp32.message, + (const char *)lp + offset64, + (char *)lp32 + offset32, size - offset64 ); + return offset32 + size; + } return sizeof(cwp32); }
From: Jacek Caban jacek@codeweavers.com
--- dlls/user32/hook.c | 12 ++++++++++++ dlls/win32u/hook.c | 7 +++++++ dlls/wow64win/user.c | 9 +++++++++ 3 files changed, 28 insertions(+)
diff --git a/dlls/user32/hook.c b/dlls/user32/hook.c index 1ae49587688..a21b11735ab 100644 --- a/dlls/user32/hook.c +++ b/dlls/user32/hook.c @@ -495,6 +495,18 @@ BOOL WINAPI User32CallWindowsHook( struct win_hook_params *params, ULONG size ) ret_size = 0; break; } + case WH_CALLWNDPROCRET: + if (ret_size > sizeof(CWPRETSTRUCT)) + { + CWPRETSTRUCT *cwpret = (CWPRETSTRUCT *)params->lparam; + size_t offset = (lparam_offset + sizeof(*cwpret) + 15) & ~15; + void *buffer = (char *)params + offset; + + unpack_message( cwpret->hwnd, cwpret->message, &cwpret->wParam, &cwpret->lParam, + &buffer, size - offset, !params->prev_unicode ); + ret_size = 0; + break; + } } } if (params->module[0] && !(proc = get_hook_proc( proc, params->module, &free_module ))) diff --git a/dlls/win32u/hook.c b/dlls/win32u/hook.c index 27b109ce545..e3c3a0ce5ba 100644 --- a/dlls/win32u/hook.c +++ b/dlls/win32u/hook.c @@ -295,6 +295,13 @@ static LRESULT call_hook( struct win_hook_params *info, const WCHAR *module, siz cwp->message, cwp->lParam, ansi ); } break; + case WH_CALLWNDPROCRET: + { + CWPRETSTRUCT *cwpret = (CWPRETSTRUCT *)((char *)params + lparam_offset); + pack_user_message( (char *)params + message_offset, message_size, + cwpret->message, cwpret->lParam, ansi ); + } + break; } }
diff --git a/dlls/wow64win/user.c b/dlls/wow64win/user.c index 94df46cbb90..7e77e5a2f73 100644 --- a/dlls/wow64win/user.c +++ b/dlls/wow64win/user.c @@ -766,6 +766,15 @@ static UINT hook_lparam_64to32( int id, int code, const void *lp, size_t size, v cwpret32.message = cwpret->message; cwpret32.hwnd = HandleToUlong( cwpret->hwnd ); memcpy( lp32, &cwpret32, sizeof(cwpret32) ); + if (size > sizeof(*cwpret)) + { + const size_t offset64 = (sizeof(*cwpret) + 15) & ~15; + const size_t offset32 = (sizeof(cwpret32) + 15) & ~15; + size = packed_message_64to32( cwpret32.message, + (const char *)lp + offset64, + (char *)lp32 + offset32, size - offset64 ); + return offset32 + size; + } return sizeof(cwpret32); }
From: Jacek Caban jacek@codeweavers.com
--- dlls/user32/winproc.c | 30 ++++----------- dlls/win32u/hook.c | 8 ++-- dlls/win32u/message.c | 74 +++++++++++++++++++++++++++--------- dlls/win32u/tests/win32u.c | 29 +++++++++++--- dlls/win32u/win32u_private.h | 6 +-- dlls/wow64win/user.c | 48 +++++++++++++++++++---- 6 files changed, 136 insertions(+), 59 deletions(-)
diff --git a/dlls/user32/winproc.c b/dlls/user32/winproc.c index d79f37b80b8..1f9b42d0c06 100644 --- a/dlls/user32/winproc.c +++ b/dlls/user32/winproc.c @@ -824,6 +824,13 @@ BOOL unpack_message( HWND hwnd, UINT message, WPARAM *wparam, LPARAM *lparam, } break; } + case WM_NCCALCSIZE: + if (*wparam) + { + NCCALCSIZE_PARAMS *ncp = *buffer; + ncp->lppos = (WINDOWPOS *)((NCCALCSIZE_PARAMS *)ncp + 1); + } + break; case WM_GETTEXT: case WM_ASKCBFORMATNAME: if (!get_buffer_space( buffer, (*wparam * sizeof(WCHAR)), size )) return FALSE; @@ -952,28 +959,6 @@ BOOL unpack_message( HWND hwnd, UINT message, WPARAM *wparam, LPARAM *lparam, case WM_STYLECHANGED: minsize = sizeof(STYLESTRUCT); break; - case WM_NCCALCSIZE: - if (!*wparam) minsize = sizeof(RECT); - else - { - NCCALCSIZE_PARAMS ncp; - WINDOWPOS wp; - if (size < sizeof(ps->ncp)) return FALSE; - ncp.rgrc[0] = ps->ncp.rgrc[0]; - ncp.rgrc[1] = ps->ncp.rgrc[1]; - ncp.rgrc[2] = ps->ncp.rgrc[2]; - wp.hwnd = unpack_handle( ps->ncp.hwnd ); - wp.hwndInsertAfter = unpack_handle( ps->ncp.hwndInsertAfter ); - wp.x = ps->ncp.x; - wp.y = ps->ncp.y; - wp.cx = ps->ncp.cx; - wp.cy = ps->ncp.cy; - wp.flags = ps->ncp.flags; - ncp.lppos = (WINDOWPOS *)((NCCALCSIZE_PARAMS *)&ps->ncp + 1); - memcpy( &ps->ncp, &ncp, sizeof(ncp) ); - *ncp.lppos = wp; - } - break; case WM_GETDLGCODE: if (*lparam) { @@ -1197,6 +1182,7 @@ BOOL WINAPI User32CallWindowProc( struct win_proc_params *params, ULONG size ) { case WM_NCCREATE: case WM_CREATE: + case WM_NCCALCSIZE: { LRESULT *result_ptr = (LRESULT *)buffer - 1; *result_ptr = result; diff --git a/dlls/win32u/hook.c b/dlls/win32u/hook.c index e3c3a0ce5ba..c53ec57c32b 100644 --- a/dlls/win32u/hook.c +++ b/dlls/win32u/hook.c @@ -246,7 +246,7 @@ static LRESULT call_hook( struct win_hook_params *info, const WCHAR *module, siz if (params->id == WH_CBT && params->code == HCBT_CREATEWND) { CBT_CREATEWNDW *cbtc = (CBT_CREATEWNDW *)params->lparam; - message_size = user_message_size( WM_NCCREATE, (LPARAM)cbtc->lpcs, FALSE ); + message_size = user_message_size( WM_NCCREATE, 0, (LPARAM)cbtc->lpcs, FALSE ); lparam_size = lparam_ret_size = 0; }
@@ -285,21 +285,21 @@ static LRESULT call_hook( struct win_hook_params *info, const WCHAR *module, siz CBT_CREATEWNDW *cbtc = (CBT_CREATEWNDW *)params->lparam; LPARAM lp = (LPARAM)cbtc->lpcs; pack_user_message( (char *)params + message_offset, message_size, - WM_CREATE, lp, FALSE ); + WM_CREATE, 0, lp, FALSE ); } break; case WH_CALLWNDPROC: { CWPSTRUCT *cwp = (CWPSTRUCT *)((char *)params + lparam_offset); pack_user_message( (char *)params + message_offset, message_size, - cwp->message, cwp->lParam, ansi ); + cwp->message, cwp->wParam, cwp->lParam, ansi ); } break; case WH_CALLWNDPROCRET: { CWPRETSTRUCT *cwpret = (CWPRETSTRUCT *)((char *)params + lparam_offset); pack_user_message( (char *)params + message_offset, message_size, - cwpret->message, cwpret->lParam, ansi ); + cwpret->message, cwpret->wParam, cwpret->lParam, ansi ); } break; } diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index 5aec4c5eb95..58294f4d385 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -387,6 +387,28 @@ static BOOL unpack_message( HWND hwnd, UINT message, WPARAM *wparam, LPARAM *lpa memcpy( *buffer, &cs, sizeof(cs) ); break; } + case WM_NCCALCSIZE: + if (!*wparam) minsize = sizeof(RECT); + else + { + NCCALCSIZE_PARAMS ncp; + WINDOWPOS wp; + if (size < sizeof(ps->ncp)) return FALSE; + ncp.rgrc[0] = ps->ncp.rgrc[0]; + ncp.rgrc[1] = ps->ncp.rgrc[1]; + ncp.rgrc[2] = ps->ncp.rgrc[2]; + wp.hwnd = wine_server_ptr_handle( ps->ncp.hwnd ); + wp.hwndInsertAfter = wine_server_ptr_handle( ps->ncp.hwndInsertAfter ); + wp.x = ps->ncp.x; + wp.y = ps->ncp.y; + wp.cx = ps->ncp.cx; + wp.cy = ps->ncp.cy; + wp.flags = ps->ncp.flags; + ncp.lppos = (WINDOWPOS *)((NCCALCSIZE_PARAMS *)&ps->ncp + 1); + memcpy( &ps->ncp, &ncp, sizeof(ncp) ); + *ncp.lppos = wp; + } + break; case WM_WINE_SETWINDOWPOS: { WINDOWPOS wp; @@ -1134,7 +1156,7 @@ static size_t copy_string( void *ptr, const void *str, BOOL ansi ) * * Calculate size of packed message buffer. */ -size_t user_message_size( UINT message, LPARAM lparam, BOOL ansi ) +size_t user_message_size( UINT message, WPARAM wparam, LPARAM lparam, BOOL ansi ) { const void *lparam_ptr = (const void *)lparam; size_t size = 0; @@ -1150,6 +1172,9 @@ size_t user_message_size( UINT message, LPARAM lparam, BOOL ansi ) if (!IS_INTRESOURCE(cs->lpszClass)) size += string_size( cs->lpszClass, ansi ); break; } + case WM_NCCALCSIZE: + size = wparam ? sizeof(NCCALCSIZE_PARAMS) + sizeof(WINDOWPOS) : sizeof(RECT); + break; }
return size; @@ -1160,7 +1185,8 @@ size_t user_message_size( UINT message, LPARAM lparam, BOOL ansi ) * * Copy message to a buffer for passing to client. */ -void pack_user_message( void *buffer, size_t size, UINT message, LPARAM lparam, BOOL ansi ) +void pack_user_message( void *buffer, size_t size, UINT message, + WPARAM wparam, LPARAM lparam, BOOL ansi ) { const void *lparam_ptr = (const void *)lparam; void const *inline_ptr = (void *)0xffffffff; @@ -1188,8 +1214,17 @@ void pack_user_message( void *buffer, size_t size, UINT message, LPARAM lparam, } return; } + case WM_NCCALCSIZE: + if (wparam) + { + const NCCALCSIZE_PARAMS *ncp = lparam_ptr; + memcpy( (char *)buffer + sizeof(*ncp), ncp->lppos, sizeof(*ncp->lppos) ); + size = sizeof(*ncp); + } + break; }
+ if (size) memcpy( buffer, lparam_ptr, size ); }
/*********************************************************************** @@ -1200,6 +1235,7 @@ void pack_user_message( void *buffer, size_t size, UINT message, LPARAM lparam, static void copy_user_result( void *buffer, size_t size, UINT message, WPARAM wparam, LPARAM lparam ) { void *lparam_ptr = (void *)lparam; + size_t copy_size = 0;
if (!size) return;
@@ -1224,9 +1260,26 @@ static void copy_user_result( void *buffer, size_t size, UINT message, WPARAM wp /* don't allow changing name and class pointers */ } return; + case WM_NCCALCSIZE: + if (wparam) + { + NCCALCSIZE_PARAMS *dst = lparam_ptr; + const NCCALCSIZE_PARAMS *src = buffer; + const WINDOWPOS *winpos = (const WINDOWPOS *)(src + 1); + dst->rgrc[0] = src->rgrc[0]; + dst->rgrc[1] = src->rgrc[1]; + dst->rgrc[2] = src->rgrc[2]; + *dst->lppos = *winpos; + return; + } + copy_size = sizeof(RECT); + break; default: return; } + + if (copy_size > size) copy_size = size; + if (copy_size) memcpy( lparam_ptr, buffer, copy_size ); }
/*********************************************************************** @@ -1290,19 +1343,6 @@ static void copy_reply( LRESULT result, HWND hwnd, UINT message, WPARAM wparam, case WM_MDIGETACTIVE: if (lparam) copy_size = sizeof(BOOL); break; - case WM_NCCALCSIZE: - if (wparam) - { - NCCALCSIZE_PARAMS *dst = (NCCALCSIZE_PARAMS *)lparam; - NCCALCSIZE_PARAMS *src = (NCCALCSIZE_PARAMS *)lparam_src; - dst->rgrc[0] = src->rgrc[0]; - dst->rgrc[1] = src->rgrc[1]; - dst->rgrc[2] = src->rgrc[2]; - *dst->lppos = *src->lppos; - return; - } - copy_size = sizeof(RECT); - break; case EM_GETSEL: case SBM_GETRANGE: case CB_GETEDITSEL: @@ -1522,7 +1562,7 @@ static LRESULT call_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpar if (!needs_unpack) size = 0; if (!is_current_thread_window( hwnd )) return 0;
- packed_size = user_message_size( msg, lparam, ansi ); + packed_size = user_message_size( msg, wparam, lparam, ansi ); if (packed_size) size = packed_size;
/* first the WH_CALLWNDPROC hook */ @@ -1543,7 +1583,7 @@ static LRESULT call_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpar if (needs_unpack) params->ansi = FALSE; params->needs_unpack = needs_unpack || packed_size; if (packed_size) - pack_user_message( params + 1, packed_size, msg, lparam, ansi ); + pack_user_message( params + 1, packed_size, msg, wparam, lparam, ansi ); else if (size) memcpy( params + 1, buffer, size );
diff --git a/dlls/win32u/tests/win32u.c b/dlls/win32u/tests/win32u.c index fc1b610063b..7ce6e990874 100644 --- a/dlls/win32u/tests/win32u.c +++ b/dlls/win32u/tests/win32u.c @@ -1364,6 +1364,7 @@ struct lparam_hook_test size_t lparam_size; size_t check_size; BOOL poison_lparam; + BOOL todo; };
static const struct lparam_hook_test *current_hook_test; @@ -1535,7 +1536,7 @@ static void test_msg_output( const struct lparam_hook_test *test, LRESULT result todo_wine_if( test->message == WM_GETTEXT && !test->msg_result ) ok( !memcmp( lparam_buffer, expected, test->lparam_size ), "unexpected lparam content\n" );
- todo_wine + todo_wine_if(test->todo) ok( wndproc_lparam != orig, "wndproc_lparam unmodified\n" ); if (!hooks_called) return; @@ -1545,13 +1546,13 @@ static void test_msg_output( const struct lparam_hook_test *test, LRESULT result ok( retwnd_hook_lparam, "retwnd_hook_lparam not called\n" ); ok( retwnd_hook_lparam2, "retwnd_hook_lparam2 not called\n" );
- todo_wine + todo_wine_if(test->todo) ok( orig != callwnd_hook_lparam, "callwnd_hook_lparam not modified\n" ); - todo_wine + todo_wine_if(test->todo) ok( orig != callwnd_hook_lparam2, "callwnd_hook_lparam2 not modified\n" ); - todo_wine + todo_wine_if(test->todo) ok( orig != retwnd_hook_lparam, "retwnd_hook_lparam not modified\n" ); - todo_wine + todo_wine_if(test->todo) ok( orig != retwnd_hook_lparam2, "retwnd_hook_lparam2 not modified\n" );
/* @@ -1609,67 +1610,83 @@ static void test_wndproc_hook(void) "WM_MOVING", WM_MOVING, .lparam = &rect_in, .lparam_size = sizeof(RECT), .check_size = sizeof(RECT), + .todo = TRUE }, { "LB_GETITEMRECT", LB_GETITEMRECT, .lparam = &rect_in, .lparam_size = sizeof(RECT), .change_lparam = &rect_out, .check_size = sizeof(RECT), + .todo = TRUE }, { "CB_GETDROPPEDCONTROLRECT", CB_GETDROPPEDCONTROLRECT, - .lparam = &rect_in, .lparam_size = sizeof(RECT), .change_lparam = &rect_out + .lparam = &rect_in, .lparam_size = sizeof(RECT), .change_lparam = &rect_out, + .todo = TRUE }, { "WM_GETTEXT", WM_GETTEXT, .wparam = 8, .lparam_size = sizeof(strbufW), .change_lparam = strbufW, .check_lparam = strbuf2W, + .todo = TRUE }, { "WM_GETTEXT2", WM_GETTEXT, .wparam = 8, .msg_result = 1, .lparam_size = sizeof(strbufW), .change_lparam = strbufW, .check_lparam = strbufW, + .todo = TRUE }, { "WM_GETTEXT3", WM_GETTEXT, .wparam = 8, .msg_result = 9, .lparam_size = sizeof(strbufW), .change_lparam = strbufW, .check_lparam = strbufW, + .todo = TRUE }, { "WM_ASKCBFORMATNAME", WM_ASKCBFORMATNAME, .wparam = 8, .lparam_size = sizeof(strbufW), .change_lparam = strbufW, .check_lparam = strbufW, + .todo = TRUE }, { "WM_ASKCBFORMATNAME2", WM_ASKCBFORMATNAME, .wparam = 8, .msg_result = 1, .lparam_size = sizeof(strbufW), .change_lparam = strbufW, .check_lparam = strbufW, + .todo = TRUE }, { "WM_ASKCBFORMATNAME3", WM_ASKCBFORMATNAME, .wparam = 8, .msg_result = 9, .lparam_size = sizeof(strbufW), .change_lparam = strbufW, .check_lparam = strbufW, + .todo = TRUE }, { "CB_GETLBTEXT", CB_GETLBTEXT, .msg_result = 7, .check_result = 4, .todo_result = TRUE, .lparam_size = sizeof(strbufW), .change_lparam = strbufW, .check_lparam = strbufW, + .todo = TRUE }, { "CB_GETLBTEXT2", CB_GETLBTEXT, .msg_result = 9, .check_result = 8, .todo_result = TRUE, .lparam_size = sizeof(strbufW), .change_lparam = strbuf3W, .check_lparam = strbuf3W, + .todo = TRUE }, { "CB_GETLBTEXT3", CB_GETLBTEXT, .lparam_size = sizeof(strbufW), .change_lparam = strbuf3W, .check_lparam = strbuf3W, + .todo = TRUE }, { "LB_GETTEXT", LB_GETTEXT, .msg_result = 7, .check_result = 4, .todo_result = TRUE, .lparam_size = sizeof(strbufW), .change_lparam = strbufW, .check_lparam = strbufW, + .todo = TRUE }, { "LB_GETTEXT2", LB_GETTEXT, .msg_result = 9, .check_result = 8, .todo_result = TRUE, .lparam_size = sizeof(strbufW), .change_lparam = strbuf3W, .check_lparam = strbuf3W, + .todo = TRUE }, { "LB_GETTEXT3", LB_GETTEXT, .lparam_size = sizeof(strbufW), .change_lparam = strbuf3W, .check_lparam = strbuf3W, + .todo = TRUE }, { "WM_MDIGETACTIVE", WM_MDIGETACTIVE, .lparam_size = sizeof(BOOL), .change_lparam = &false_lparam, + .todo = TRUE }, { "WM_USER", WM_USER }, { "WM_NOTIFY", WM_NOTIFY }, diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index b27ba7fab14..27a3d1a0305 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -140,9 +140,9 @@ extern LRESULT send_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) extern BOOL send_notify_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, BOOL ansi ) DECLSPEC_HIDDEN; extern LRESULT send_message_timeout( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, UINT flags, UINT timeout, BOOL ansi ) DECLSPEC_HIDDEN; -extern size_t user_message_size( UINT message, LPARAM lparam, BOOL ansi ) DECLSPEC_HIDDEN; -extern void pack_user_message( void *buffer, size_t size, UINT message, LPARAM lparam, - BOOL ansi ) DECLSPEC_HIDDEN; +extern size_t user_message_size( UINT message, WPARAM wparam, LPARAM lparam, BOOL ansi ) DECLSPEC_HIDDEN; +extern void pack_user_message( void *buffer, size_t size, UINT message, + WPARAM wparam, LPARAM lparam, BOOL ansi ) DECLSPEC_HIDDEN;
/* rawinput.c */ extern BOOL process_rawinput_message( MSG *msg, UINT hw_id, const struct hardware_msg_data *msg_data ) DECLSPEC_HIDDEN; diff --git a/dlls/wow64win/user.c b/dlls/wow64win/user.c index 7e77e5a2f73..7aea543ea6a 100644 --- a/dlls/wow64win/user.c +++ b/dlls/wow64win/user.c @@ -614,7 +614,8 @@ static NTSTATUS WINAPI wow64_NtUserCallWinEventHook( void *arg, ULONG size ) FIELD_OFFSET( struct win_event_hook_params32, module ) + size); }
-static size_t packed_message_64to32( UINT message, const void *params64, void *params32, size_t size ) +static size_t packed_message_64to32( UINT message, WPARAM wparam, + const void *params64, void *params32, size_t size ) { if (!size) return 0;
@@ -631,14 +632,33 @@ static size_t packed_message_64to32( UINT message, const void *params64, void *p if (size) memmove( cs32 + 1, cs64 + 1, size ); return sizeof(*cs32) + size; } + + case WM_NCCALCSIZE: + if (wparam) + { + NCCALCSIZE_PARAMS32 ncp32; + const NCCALCSIZE_PARAMS *ncp64 = params64; + + ncp32.rgrc[0] = ncp64->rgrc[0]; + ncp32.rgrc[1] = ncp64->rgrc[1]; + ncp32.rgrc[2] = ncp64->rgrc[2]; + winpos_64to32( (const WINDOWPOS *)(ncp64 + 1), + (WINDOWPOS32 *)((const char *)params32 + sizeof(ncp32)) ); + memcpy( params32, &ncp32, sizeof(ncp32) ); + return sizeof(ncp32) + sizeof(WINDOWPOS32); + } + break; }
memmove( params32, params64, size ); return size; }
-static size_t packed_result_32to64( UINT message, const void *params32, size_t size, void *params64 ) +static size_t packed_result_32to64( UINT message, WPARAM wparam, const void *params32, + size_t size, void *params64 ) { + if (!size) return 0; + switch (message) { case WM_NCCREATE: @@ -661,6 +681,20 @@ static size_t packed_result_32to64( UINT message, const void *params32, size_t s return sizeof(*cs64); }
+ case WM_NCCALCSIZE: + if (wparam) + { + const NCCALCSIZE_PARAMS32 *ncp32 = params32; + NCCALCSIZE_PARAMS *ncp64 = params64; + + ncp64->rgrc[0] = ncp32->rgrc[0]; + ncp64->rgrc[1] = ncp32->rgrc[1]; + ncp64->rgrc[2] = ncp32->rgrc[2]; + winpos_32to64( (WINDOWPOS *)(ncp64 + 1), (const WINDOWPOS32 *)(ncp32 + 1) ); + return sizeof(*ncp64) + sizeof(WINDOWPOS); + } + break; + default: return 0; } @@ -681,7 +715,7 @@ static NTSTATUS WINAPI wow64_NtUserCallWinProc( void *arg, ULONG size )
win_proc_params_64to32( params, params32 ); if (size > sizeof(*params)) - lparam_size = packed_message_64to32( params32->msg, params + 1, params32 + 1, + lparam_size = packed_message_64to32( params32->msg, params32->wparam, params + 1, params32 + 1, size - sizeof(*params) );
status = Wow64KiUserCallbackDispatcher( NtUserCallWinProc, params32, @@ -692,7 +726,7 @@ static NTSTATUS WINAPI wow64_NtUserCallWinProc( void *arg, ULONG size ) { LRESULT *result_ptr = arg; result = *(LONG *)ret_ptr; - ret_len = packed_result_32to64( params32->msg, (LONG *)ret_ptr + 1, + ret_len = packed_result_32to64( params32->msg, params32->wparam, (LONG *)ret_ptr + 1, ret_len - sizeof(LONG), result_ptr + 1 ); *result_ptr = result; return NtCallbackReturn( result_ptr, sizeof(*result_ptr) + ret_len, status ); @@ -717,7 +751,7 @@ static UINT hook_lparam_64to32( int id, int code, const void *lp, size_t size, v switch (code) { case HCBT_CREATEWND: - return packed_message_64to32( WM_CREATE, lp, lp32, size ); + return packed_message_64to32( WM_CREATE, 0, lp, lp32, size );
case HCBT_ACTIVATE: { @@ -748,7 +782,7 @@ static UINT hook_lparam_64to32( int id, int code, const void *lp, size_t size, v { const size_t offset64 = (sizeof(*cwp) + 15) & ~15; const size_t offset32 = (sizeof(cwp32) + 15) & ~15; - size = packed_message_64to32( cwp32.message, + size = packed_message_64to32( cwp32.message, cwp32.wParam, (const char *)lp + offset64, (char *)lp32 + offset32, size - offset64 ); return offset32 + size; @@ -770,7 +804,7 @@ static UINT hook_lparam_64to32( int id, int code, const void *lp, size_t size, v { const size_t offset64 = (sizeof(*cwpret) + 15) & ~15; const size_t offset32 = (sizeof(cwpret32) + 15) & ~15; - size = packed_message_64to32( cwpret32.message, + size = packed_message_64to32( cwpret32.message, cwpret32.wParam, (const char *)lp + offset64, (char *)lp32 + offset32, size - offset64 ); return offset32 + size;
This merge request was approved by Huw Davies.