From: Zebediah Figura Subject: [PATCH] user32: Always process sent messages when sending inter-thread messages. Message-Id: <1516753113-19529-1-git-send-email-z.figura12@gmail.com> Date: Tue, 23 Jan 2018 18:18:33 -0600 Signed-off-by: Zebediah Figura --- Sometimes the sent message will be processed before the loop has had time to execute once, and sent messages will remain in the queue unprocessed. This never happens on Windows, although it is not quite clear whether this is guaranteed or whether it is simply due to consistency in thread scheduling. MSDN states: However, the sending thread will process incoming nonqueued messages while waiting for its message to be processed. which is somewhat ambiguous. We have tests in Wine (namely in ole32:clipboard) which were failing intermittently because sent messages were sometimes not being processed while executing SendMessageTimeout(). This test has never failed on Windows, in any configuration tracked on test.winehq.org, and so I am inclined to conclude that this logic matches Windows' behaviour. dlls/user32/message.c | 2 +- dlls/user32/tests/msg.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/dlls/user32/message.c b/dlls/user32/message.c index 172d659..81844e3 100644 --- a/dlls/user32/message.c +++ b/dlls/user32/message.c @@ -3015,13 +3015,13 @@ static void wait_message_reply( UINT flags ) thread_info->wake_mask = thread_info->changed_mask = 0; - if (wake_bits & QS_SMRESULT) return; /* got a result */ if (wake_bits & QS_SENDMESSAGE) { /* Process the sent message immediately */ process_sent_messages(); continue; } + if (wake_bits & QS_SMRESULT) return; /* got a result */ wow_handlers.wait_message( 1, &server_queue, INFINITE, wake_mask, 0 ); } diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c index f391ab9..082b560 100644 --- a/dlls/user32/tests/msg.c +++ b/dlls/user32/tests/msg.c @@ -16633,6 +16633,37 @@ static void test_DoubleSetCapture(void) DestroyWindow(hwnd); } +static DWORD WINAPI send_notify_message_thread(void *param) +{ + SendNotifyMessageA((HWND) param, WM_USER, 0, 0); + return 0; +} + +static void test_SendMessage_pump(void) +{ + /* Sending a message to another thread's window should process sent messages + * currently in the queue. On Windows this always happens, i.e. we never + * fail to do so if we've already received a reply. */ + + HWND hwnd; + HANDLE thread; + + hwnd = CreateWindowA("TestWindowClass", "test_SendMessage_pump", 0, + 100, 100, 200, 200, 0, 0, 0, 0); + ok(hwnd != NULL, "Failed to create window\n"); + flush_sequence(); + + thread = CreateThread(0, 0, send_notify_message_thread, hwnd, 0, 0); + ok(WaitForSingleObject(thread, 1000) == WAIT_OBJECT_0, "wait failed\n"); + ok_sequence(WmEmptySeq, "no messages", FALSE); + + SendMessageA(GetDesktopWindow(), WM_NULL, 0, 0); + ok_sequence(WmUser, "SendMessage() pump", FALSE); + + CloseHandle(thread); + DestroyWindow(hwnd); +} + static void init_funcs(void) { HMODULE hKernel32 = GetModuleHandleA("kernel32.dll"); @@ -16777,6 +16808,7 @@ START_TEST(msg) test_TrackPopupMenu(); test_TrackPopupMenuEmpty(); test_DoubleSetCapture(); + test_SendMessage_pump(); /* keep it the last test, under Windows it tends to break the tests * which rely on active/foreground windows being correct. */ -- 2.7.4