diff --git a/dlls/user32/message.c b/dlls/user32/message.c index 63e7c42132c..138c8d73941 100644 --- a/dlls/user32/message.c +++ b/dlls/user32/message.c @@ -2183,17 +2183,12 @@ static BOOL send_message( struct send_message_info *info, DWORD_PTR *res_ptr, BO LRESULT WINAPI SendMessageTimeoutW( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, UINT flags, UINT timeout, PDWORD_PTR res_ptr ) { - struct send_message_info info; + struct send_message_timeout_params params = { .flags = flags, .timeout = timeout }; + LRESULT res; - info.type = MSG_UNICODE; - info.hwnd = hwnd; - info.msg = msg; - info.wparam = wparam; - info.lparam = lparam; - info.flags = flags; - info.timeout = timeout; - - return send_message( &info, res_ptr, TRUE ); + res = NtUserMessageCall( hwnd, msg, wparam, lparam, ¶ms, FNID_SENDMESSAGEWTOOPTION, FALSE ); + if (res_ptr) *res_ptr = res; + return params.result; } /*********************************************************************** diff --git a/dlls/user32/user_main.c b/dlls/user32/user_main.c index 72566f0fa03..789533329c3 100644 --- a/dlls/user32/user_main.c +++ b/dlls/user32/user_main.c @@ -165,7 +165,6 @@ static const struct user_callbacks user_funcs = EndMenu, HideCaret, PostMessageW, - SendMessageTimeoutW, SendMessageA, SendMessageW, SendNotifyMessageW, diff --git a/dlls/win32u/input.c b/dlls/win32u/input.c index 7fd9e7da720..0f5a80190fb 100644 --- a/dlls/win32u/input.c +++ b/dlls/win32u/input.c @@ -1352,9 +1352,9 @@ static BOOL set_active_window( HWND hwnd, HWND *prev, BOOL mouse, BOOL focus ) if (hwnd) { /* send palette messages */ - if (send_message( hwnd, WM_QUERYNEWPALETTE, 0, 0 ) && user_callbacks) - user_callbacks->pSendMessageTimeoutW( HWND_BROADCAST, WM_PALETTEISCHANGING, (WPARAM)hwnd, 0, - SMTO_ABORTIFHUNG, 2000, NULL ); + if (send_message( hwnd, WM_QUERYNEWPALETTE, 0, 0 )) + send_message_timeout( HWND_BROADCAST, WM_PALETTEISCHANGING, (WPARAM)hwnd, 0, + SMTO_ABORTIFHUNG, 2000, NULL, FALSE ); if (!is_window(hwnd)) return FALSE; } diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index 639372cc7c1..359a3cadbab 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -2035,6 +2035,105 @@ LRESULT WINAPI NtUserDispatchMessage( const MSG *msg ) return dispatch_message( msg, FALSE ); } +static BOOL is_message_broadcastable( UINT msg ) +{ + return msg < WM_USER || msg >= 0xc000; +} + +/*********************************************************************** + * broadcast_message + */ +static BOOL broadcast_message( struct send_message_info *info, DWORD_PTR *res_ptr ) +{ + if (is_message_broadcastable( info->msg )) + { + HWND *list = list_window_children( 0, get_desktop_window(), NULL, 0 ); + int i; + + for (i = 0; list[i]; i++) + { + if (!is_window(list[i])) continue; + if ((get_window_long( list[i], GWL_STYLE ) & (WS_POPUP|WS_CHILD)) == WS_CHILD) + continue; + + switch(info->type) + { + case MSG_UNICODE: + send_message_timeout( list[i], info->msg, info->wparam, info->lparam, + info->flags, info->timeout, NULL, FALSE ); + break; + case MSG_ASCII: + send_message_timeout( list[i], info->msg, info->wparam, info->lparam, + info->flags, info->timeout, NULL, TRUE ); + break; + case MSG_NOTIFY: + NtUserMessageCall( list[i], info->msg, info->wparam, info->lparam, + 0, FNID_SENDNOTIFYMESSAGE, FALSE ); + break; + case MSG_CALLBACK: + { + struct send_message_callback_params params = + { .callback = info->callback, .data = info->data }; + NtUserMessageCall( list[i], info->msg, info->wparam, info->lparam, + ¶ms, FNID_SENDMESSAGECALLBACK, FALSE ); + break; + } + case MSG_POSTED: + NtUserPostMessage( list[i], info->msg, info->wparam, info->lparam ); + break; + default: + ERR( "bad type %d\n", info->type ); + break; + } + } + } + + if (res_ptr) *res_ptr = 1; + return TRUE; +} + +/*********************************************************************** + * process_message + * + * Backend implementation of the various SendMessage functions. + */ +static BOOL process_message( struct send_message_info *info, DWORD_PTR *res_ptr, BOOL ansi ) +{ + struct user_thread_info *thread_info = get_user_thread_info(); + INPUT_MESSAGE_SOURCE prev_source = thread_info->msg_source; + DWORD dest_pid; + BOOL ret; + LRESULT result; + + if (is_broadcast( info->hwnd )) return broadcast_message( info, res_ptr ); + + if (!(info->dest_tid = get_window_thread( info->hwnd, &dest_pid ))) return FALSE; + if (is_exiting_thread( info->dest_tid )) return FALSE; + + thread_info->msg_source = msg_source_unavailable; + spy_enter_message( SPY_SENDMESSAGE, info->hwnd, info->msg, info->wparam, info->lparam ); + + if (info->dest_tid == GetCurrentThreadId()) + { + result = call_window_proc( info->hwnd, info->msg, info->wparam, info->lparam, + !ansi, TRUE, info->wm_char, FALSE, NULL, 0 ); + if (info->type == MSG_CALLBACK) + call_sendmsg_callback( info->callback, info->hwnd, info->msg, info->data, result ); + ret = TRUE; + } + else + { + if (dest_pid != GetCurrentProcessId() && (info->type == MSG_ASCII || info->type == MSG_UNICODE)) + info->type = MSG_OTHER_PROCESS; + ret = send_inter_thread_message( info, &result ); + } + + spy_exit_message( SPY_RESULT_OK, info->hwnd, info->msg, result, info->wparam, info->lparam ); + thread_info->msg_source = prev_source; + if (ret && res_ptr) *res_ptr = result; + return ret; +} + /*********************************************************************** * NtUserSetTimer (win32u.@) */ @@ -2142,6 +2241,24 @@ static LRESULT send_window_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM l : user_callbacks->pSendMessageW( hwnd, msg, wparam, lparam ); } +/* see SendMessageTimeoutW */ +LRESULT send_message_timeout( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, + UINT flags, UINT timeout, DWORD_PTR *res_ptr, BOOL ansi ) +{ + struct send_message_info info; + + info.type = ansi ? MSG_ASCII : MSG_UNICODE; + info.hwnd = hwnd; + info.msg = msg; + info.wparam = wparam; + info.lparam = lparam; + info.flags = flags; + info.timeout = timeout; + info.wm_char = WMCHAR_MAP_SENDMESSAGETIMEOUT; + + return process_message( &info, res_ptr, ansi ); +} + /* see SendMessageW */ LRESULT send_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) { @@ -2174,6 +2291,14 @@ LRESULT WINAPI NtUserMessageCall( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpa wparam, lparam, ansi ); case FNID_SENDMESSAGE: return send_window_message( hwnd, msg, wparam, lparam, ansi ); + case FNID_SENDMESSAGEWTOOPTION: + { + struct send_message_timeout_params *params = (void *)result_info; + DWORD_PTR res = 0; + params->result = send_message_timeout( hwnd, msg, wparam, lparam, params->flags, + params->timeout, &res, ansi ); + return res; + } case FNID_SENDNOTIFYMESSAGE: return send_notify_message( hwnd, msg, wparam, lparam, ansi ); case FNID_SPYENTER: diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h index 7f2747652b4..d69e24a1dab 100644 --- a/dlls/win32u/ntuser_private.h +++ b/dlls/win32u/ntuser_private.h @@ -38,7 +38,6 @@ struct user_callbacks BOOL (WINAPI *pEndMenu)(void); BOOL (WINAPI *pHideCaret)( HWND hwnd ); BOOL (WINAPI *pPostMessageW)( HWND, UINT, WPARAM, LPARAM ); - LRESULT (WINAPI *pSendMessageTimeoutW)( HWND, UINT, WPARAM, LPARAM, UINT, UINT, PDWORD_PTR ); LRESULT (WINAPI *pSendMessageA)( HWND, UINT, WPARAM, LPARAM ); LRESULT (WINAPI *pSendMessageW)( HWND, UINT, WPARAM, LPARAM ); BOOL (WINAPI *pSendNotifyMessageW)( HWND, UINT, WPARAM, LPARAM ); diff --git a/dlls/win32u/palette.c b/dlls/win32u/palette.c index 2a394ba7eba..95361eac5cc 100644 --- a/dlls/win32u/palette.c +++ b/dlls/win32u/palette.c @@ -583,9 +583,8 @@ UINT realize_palette( HDC hdc ) { /* send palette change notification */ HWND hwnd = NtUserWindowFromDC( hdc ); - if (hwnd) user_callbacks->pSendMessageTimeoutW( HWND_BROADCAST, WM_PALETTECHANGED, - HandleToUlong(hwnd), 0, SMTO_ABORTIFHUNG, - 2000, NULL ); + if (hwnd) send_message_timeout( HWND_BROADCAST, WM_PALETTECHANGED, HandleToUlong(hwnd), 0, + SMTO_ABORTIFHUNG, 2000, NULL, FALSE ); } return realized; } diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index 67d63db9742..1a9199c6ac7 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -4103,9 +4103,8 @@ BOOL WINAPI NtUserSystemParametersInfo( UINT action, UINT val, void *ptr, UINT w { static const WCHAR emptyW[1]; if (winini & (SPIF_SENDWININICHANGE | SPIF_SENDCHANGE)) - user_callbacks->pSendMessageTimeoutW( HWND_BROADCAST, WM_SETTINGCHANGE, - action, (LPARAM) emptyW, - SMTO_ABORTIFHUNG, 2000, NULL ); + send_message_timeout( HWND_BROADCAST, WM_SETTINGCHANGE, action, (LPARAM) emptyW, + SMTO_ABORTIFHUNG, 2000, NULL, FALSE ); } TRACE( "(%u, %u, %p, %u) ret %d\n", action, val, ptr, winini, ret ); return ret; @@ -4547,8 +4546,8 @@ BOOL WINAPI NtUserSetSysColors( INT count, const INT *colors, const COLORREF *va set_entry( &system_colors[colors[i]], values[i], 0, 0 ); /* Send WM_SYSCOLORCHANGE message to all windows */ - user_callbacks->pSendMessageTimeoutW( HWND_BROADCAST, WM_SYSCOLORCHANGE, 0, 0, - SMTO_ABORTIFHUNG, 2000, NULL ); + send_message_timeout( HWND_BROADCAST, WM_SYSCOLORCHANGE, 0, 0, + SMTO_ABORTIFHUNG, 2000, NULL, FALSE ); /* Repaint affected portions of all visible windows */ NtUserRedrawWindow( 0, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_ALLCHILDREN ); return TRUE; diff --git a/dlls/win32u/tests/win32u.c b/dlls/win32u/tests/win32u.c index 33b50ef53b1..e93ad416d2b 100644 --- a/dlls/win32u/tests/win32u.c +++ b/dlls/win32u/tests/win32u.c @@ -449,9 +449,7 @@ static void test_message_call(void) smp.timeout = 10; smp.result = 0xdeadbeef; res = NtUserMessageCall( hwnd, WM_USER, 1, 2, &smp, FNID_SENDMESSAGEWTOOPTION, FALSE ); - todo_wine ok( res == 3, "res = %Iu\n", res ); - todo_wine ok( smp.result == 1, "smp.result = %Iu\n", smp.result ); smp.flags = 0; @@ -459,9 +457,7 @@ static void test_message_call(void) smp.result = 0xdeadbeef; res = NtUserMessageCall( hwnd, WM_USER + 1, 0, large_lparam, &smp, FNID_SENDMESSAGEWTOOPTION, FALSE ); - todo_wine ok( res == large_lparam, "res = %Iu\n", res ); - todo_wine ok( smp.result == 1, "smp.result = %Iu\n", smp.result ); res = NtUserMessageCall( hwnd, WM_USER, 1, 2, (void *)0xdeadbeef, diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index d72ce3b8a0d..7be5f736d13 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -358,6 +358,8 @@ extern LRESULT send_internal_message_timeout( DWORD dest_pid, DWORD dest_tid, UI LPARAM lparam, UINT flags, UINT timeout, PDWORD_PTR res_ptr ) DECLSPEC_HIDDEN; extern LRESULT send_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) DECLSPEC_HIDDEN; +extern LRESULT send_message_timeout( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, + UINT flags, UINT timeout, PDWORD_PTR res_ptr, BOOL ansi ); /* sysparams.c */ extern BOOL enable_thunk_lock DECLSPEC_HIDDEN;