Jacek Caban : win32u: Avoid using client callbacks for NtUserSendMessage.
Alexandre Julliard
julliard at winehq.org
Thu Jul 21 17:04:08 CDT 2022
Module: wine
Branch: master
Commit: c1c57bd75014d660abbe456d926320e80b088d67
URL: https://gitlab.winehq.org/wine/wine/-/commit/c1c57bd75014d660abbe456d926320e80b088d67
Author: Jacek Caban <jacek at codeweavers.com>
Date: Tue Jul 19 19:19:56 2022 +0200
win32u: Avoid using client callbacks for NtUserSendMessage.
---
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 */
More information about the wine-cvs
mailing list