Module: wine Branch: master Commit: 9587214b205c6cabb8df9812a2e67f22c5531368 URL: https://gitlab.winehq.org/wine/wine/-/commit/9587214b205c6cabb8df9812a2e67f2...
Author: Esme Povirk esme@codeweavers.com Date: Fri Nov 24 20:29:35 2023 +0000
user32/tests: Add a simpler test for SetParent's internal message.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=54037
test_SendMessage_other_thread(2), which is supposed to show that Windows doesn't use an internal sent message for SetParent, tacks this onto another more complex test, which introduces a race condition (see Comment 2 on the bug). I am not sure if it can be fixed in the existing function, perhaps it can and I just can't keep track of all the moving parts well enough, but I see no need to make it so difficult.
---
dlls/user32/tests/msg.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+)
diff --git a/dlls/user32/tests/msg.c b/dlls/user32/tests/msg.c index 8517ede31dd..66db16f2392 100644 --- a/dlls/user32/tests/msg.c +++ b/dlls/user32/tests/msg.c @@ -19856,6 +19856,55 @@ static void test_SendMessage_other_thread(int thread_n) CloseHandle(wnd_event.getmessage_complete); }
+static DWORD WINAPI SetParent_thread(void *param) +{ + struct wnd_event *wnd_event = param; + + if (winetest_debug > 1) trace("thread: started\n"); + SetEvent(wnd_event->start_event); + + /* this leads to sending an internal message under Wine */ + if (winetest_debug > 1) trace("thread: call SetParent\n"); + SetParent(wnd_event->hwnd, wnd_event->hwnd); + + return 0; +} + +static void test_setparent_status(void) +{ + HANDLE hthread; + struct wnd_event wnd_event; + DWORD ret; + + wnd_event.start_event = CreateEventA(NULL, 0, 0, NULL); + + wnd_event.hwnd = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW, + 100, 100, 200, 200, 0, 0, 0, NULL); + ok(wnd_event.hwnd != 0, "CreateWindowEx failed\n"); + + ret = GetQueueStatus(QS_SENDMESSAGE); + ok(ret == 0, "wrong status %08lx\n", ret); + + hthread = CreateThread(NULL, 0, SetParent_thread, &wnd_event, 0, NULL); + ok(hthread != NULL, "CreateThread failed, error %ld\n", GetLastError()); + + WaitForSingleObject(wnd_event.start_event, INFINITE); + + /* background thread's SetParent should complete allowing the thread to exit */ + ret = MsgWaitForMultipleObjects(1, &hthread, FALSE, 1000, QS_SENDMESSAGE); + todo_wine ok(ret == WAIT_OBJECT_0, "MsgWaitForMultipleObjects returned %08lx\n", ret); + + /* QS_SENDMESSAGE status should not have been set by SetParent */ + ret = GetQueueStatus(QS_SENDMESSAGE); + todo_wine ok(ret == 0, "wrong status %08lx\n", ret); + + DestroyWindow(wnd_event.hwnd); + + WaitForSingleObject(hthread, INFINITE); + CloseHandle(hthread); + CloseHandle(wnd_event.start_event); +} + static LRESULT CALLBACK insendmessage_wnd_proc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp ) { DWORD flags = InSendMessageEx( NULL ); @@ -20248,6 +20297,7 @@ START_TEST(msg) test_winevents(); test_SendMessage_other_thread(1); test_SendMessage_other_thread(2); + test_setparent_status(); test_InSendMessage(); test_SetFocus(); test_SetParent();