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, &params, NtUserSendMessage, FALSE );
+    if (params.hwnd) retval = dispatch_send_message( &params );
+    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, &params, NtUserSendMessage, TRUE );
+    if (params.hwnd) retval = dispatch_send_message( &params );
+    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