From: Jacek Caban jacek@codeweavers.com
--- dlls/user32/message.c | 39 ++++++++++++++++++++++++++++++++++-- dlls/win32u/hook.c | 2 +- dlls/win32u/message.c | 26 +++++++++++++++++++++--- dlls/win32u/tests/win32u.c | 4 ++-- dlls/win32u/win32u_private.h | 1 + 5 files changed, 64 insertions(+), 8 deletions(-)
diff --git a/dlls/user32/message.c b/dlls/user32/message.c index 40babb71eba..71c0f339b54 100644 --- a/dlls/user32/message.c +++ b/dlls/user32/message.c @@ -597,12 +597,41 @@ LRESULT WINAPI SendMessageTimeoutA( HWND hwnd, UINT msg, WPARAM wparam, LPARAM l }
+static LRESULT dispatch_send_message( struct win_proc_params *params ) +{ + struct user_thread_info *thread_info = get_user_thread_info(); + INPUT_MESSAGE_SOURCE prev_source = thread_info->msg_source; + LRESULT retval = 0; + + static const INPUT_MESSAGE_SOURCE msg_source_unavailable = { IMDT_UNAVAILABLE, IMO_UNAVAILABLE }; + + thread_info->recursion_count++; + + params->result = &retval; + thread_info->msg_source = msg_source_unavailable; + SPY_EnterMessage( SPY_SENDMESSAGE, params->hwnd, params->msg, params->wparam, params->lparam ); + + dispatch_win_proc_params( params ); + + SPY_ExitMessage( SPY_RESULT_OK, params->hwnd, params->msg, retval, params->wparam, params->lparam ); + thread_info->msg_source = prev_source; + thread_info->recursion_count--; + return retval; +} + + /*********************************************************************** * SendMessageW (USER32.@) */ LRESULT WINAPI SendMessageW( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) { - return NtUserMessageCall( hwnd, msg, wparam, lparam, NULL, NtUserSendMessage, FALSE ); + struct win_proc_params params; + LRESULT retval; + + params.hwnd = 0; + retval = NtUserMessageCall( hwnd, msg, wparam, lparam, ¶ms, NtUserSendMessage, FALSE ); + if (params.hwnd) retval = dispatch_send_message( ¶ms ); + return retval; }
@@ -611,6 +640,9 @@ LRESULT WINAPI SendMessageW( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) */ LRESULT WINAPI SendMessageA( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) { + struct win_proc_params params; + LRESULT retval; + if (msg == WM_CHAR && !WIN_IsCurrentThread( hwnd )) { if (!map_wparam_AtoW( msg, &wparam, WMCHAR_MAP_SENDMESSAGE )) @@ -618,7 +650,10 @@ LRESULT WINAPI SendMessageA( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) return NtUserMessageCall( hwnd, msg, wparam, lparam, NULL, NtUserSendMessage, FALSE ); }
- return NtUserMessageCall( hwnd, msg, wparam, lparam, NULL, NtUserSendMessage, TRUE ); + params.hwnd = 0; + retval = NtUserMessageCall( hwnd, msg, wparam, lparam, ¶ms, NtUserSendMessage, TRUE ); + if (params.hwnd) retval = dispatch_send_message( ¶ms ); + return retval; }
diff --git a/dlls/win32u/hook.c b/dlls/win32u/hook.c index a271693622a..dcf2bb9f865 100644 --- a/dlls/win32u/hook.c +++ b/dlls/win32u/hook.c @@ -60,7 +60,7 @@ static const char *debugstr_hook_id( unsigned int id ) return hook_names[id - WH_MINHOOK]; }
-static BOOL is_hooked( INT id ) +BOOL is_hooked( INT id ) { struct user_thread_info *thread_info = get_user_thread_info();
diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index 49dc3fd6d08..1b9585c4178 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -109,6 +109,7 @@ struct send_message_info SENDASYNCPROC callback; /* callback function for SendMessageCallback */ ULONG_PTR data; /* callback data */ enum wm_char_mapping wm_char; + struct win_proc_params *params; };
static const INPUT_MESSAGE_SOURCE msg_source_unavailable = { IMDT_UNAVAILABLE, IMO_UNAVAILABLE }; @@ -2374,6 +2375,7 @@ LRESULT send_internal_message_timeout( DWORD dest_pid, DWORD dest_tid, info.lparam = lparam; info.flags = flags; info.timeout = timeout; + info.params = NULL;
ret = send_inter_thread_message( &info, &result ); } @@ -2399,6 +2401,7 @@ NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, const RAWINPUT *r info.hwnd = hwnd; info.flags = 0; info.timeout = 0; + info.params = NULL;
if (input->type == INPUT_HARDWARE && rawinput->header.dwType == RIM_TYPEHID) { @@ -2635,6 +2638,16 @@ static BOOL process_message( struct send_message_info *info, DWORD_PTR *res_ptr, if (!(info->dest_tid = get_window_thread( info->hwnd, &dest_pid ))) return FALSE; if (is_exiting_thread( info->dest_tid )) return FALSE;
+ if (info->params && info->dest_tid == GetCurrentThreadId() && + !is_hooked( WH_CALLWNDPROC ) && !is_hooked( WH_CALLWNDPROCRET ) && + thread_info->recursion_count <= MAX_WINPROC_RECURSION) + { + /* if we're called from client side and need just a simple winproc call, + * just fill dispatch params and let user32 do the rest */ + return init_window_call_params( info->params, info->hwnd, info->msg, info->wparam, info->lparam, + NULL, ansi, info->wm_char ); + } + thread_info->msg_source = msg_source_unavailable; spy_enter_message( SPY_SENDMESSAGE, info->hwnd, info->msg, info->wparam, info->lparam );
@@ -2755,7 +2768,8 @@ BOOL kill_system_timer( HWND hwnd, UINT_PTR id ) return ret; }
-static LRESULT send_window_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, BOOL ansi ) +static LRESULT send_window_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, + struct win_proc_params *client_params, BOOL ansi ) { struct send_message_info info; DWORD_PTR res = 0; @@ -2768,6 +2782,7 @@ static LRESULT send_window_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM l info.flags = SMTO_NORMAL; info.timeout = 0; info.wm_char = WMCHAR_MAP_SENDMESSAGETIMEOUT; + info.params = client_params;
process_message( &info, &res, ansi ); return res; @@ -2787,6 +2802,7 @@ LRESULT send_message_timeout( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, info.flags = flags; info.timeout = timeout; info.wm_char = WMCHAR_MAP_SENDMESSAGETIMEOUT; + info.params = NULL;
return process_message( &info, res_ptr, ansi ); } @@ -2794,7 +2810,7 @@ LRESULT send_message_timeout( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, /* see SendMessageW */ LRESULT send_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) { - return send_window_message( hwnd, msg, wparam, lparam, FALSE ); + return send_window_message( hwnd, msg, wparam, lparam, NULL, FALSE ); }
/* see SendNotifyMessageW */ @@ -2815,6 +2831,7 @@ static BOOL send_notify_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpar info.lparam = lparam; info.flags = 0; info.wm_char = WMCHAR_MAP_SENDMESSAGETIMEOUT; + info.params = NULL;
return process_message( &info, NULL, ansi ); } @@ -2840,6 +2857,7 @@ static BOOL send_message_callback( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lp info.data = params->data; info.flags = 0; info.wm_char = WMCHAR_MAP_SENDMESSAGETIMEOUT; + info.params = NULL;
return process_message( &info, NULL, ansi ); } @@ -2866,6 +2884,7 @@ BOOL WINAPI NtUserPostMessage( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam info.wparam = wparam; info.lparam = lparam; info.flags = 0; + info.params = NULL;
if (is_broadcast(hwnd)) return broadcast_message( &info, NULL );
@@ -2899,6 +2918,7 @@ BOOL WINAPI NtUserPostThreadMessage( DWORD thread, UINT msg, WPARAM wparam, LPAR info.wparam = wparam; info.lparam = lparam; info.flags = 0; + info.params = NULL; return put_message_in_queue( &info, NULL ); }
@@ -2924,7 +2944,7 @@ LRESULT WINAPI NtUserMessageCall( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpa wparam, lparam, ansi );
case NtUserSendMessage: - return send_window_message( hwnd, msg, wparam, lparam, ansi ); + return send_window_message( hwnd, msg, wparam, lparam, result_info, ansi );
case NtUserSendMessageTimeout: { diff --git a/dlls/win32u/tests/win32u.c b/dlls/win32u/tests/win32u.c index dc1638f37ab..07179e6cdb9 100644 --- a/dlls/win32u/tests/win32u.c +++ b/dlls/win32u/tests/win32u.c @@ -425,10 +425,10 @@ static void test_message_call(void)
hwnd = CreateWindowExW( 0, L"TestClass", NULL, WS_POPUP, 0,0,0,0,0,0,0, NULL );
- res = NtUserMessageCall( hwnd, WM_USER, 1, 2, (void *)0xdeadbeef, NtUserSendMessage, FALSE ); + res = NtUserMessageCall( hwnd, WM_USER, 1, 2, NULL, NtUserSendMessage, FALSE ); ok( res == 3, "res = %Iu\n", res );
- res = NtUserMessageCall( hwnd, WM_USER, 1, 2, (void *)0xdeadbeef, NtUserSendMessage, TRUE ); + res = NtUserMessageCall( hwnd, WM_USER, 1, 2, NULL, NtUserSendMessage, TRUE ); ok( res == 3, "res = %Iu\n", res );
res = NtUserMessageCall( hwnd, WM_SETTEXT, 0, (LPARAM)L"test", NULL, NtUserSendMessage, FALSE ); diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index a7f0624fdba..914a02ffd52 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -391,6 +391,7 @@ extern LRESULT handle_nc_hit_test( HWND hwnd, POINT pt ) DECLSPEC_HIDDEN; /* hook.c */ 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, BOOL unicode ) DECLSPEC_HIDDEN; +extern BOOL is_hooked( INT id ) DECLSPEC_HIDDEN; extern BOOL unhook_windows_hook( INT id, HOOKPROC proc ) DECLSPEC_HIDDEN;
/* imm.c */