From 7744b352346a097282ec9db2d912714780c103b9 Mon Sep 17 00:00:00 2001 From: Thomas Faber Date: Tue, 3 Nov 2015 20:40:19 +0000 Subject: [PATCH] [USER32_APITEST] - Add a test for sending recursive inter-thread messages CORE-9210 svn path=/trunk/; revision=69797 --- rostests/apitests/user32/SendMessageTimeout.c | 203 +++++++++++++++++- 1 file changed, 202 insertions(+), 1 deletion(-) diff --git a/rostests/apitests/user32/SendMessageTimeout.c b/rostests/apitests/user32/SendMessageTimeout.c index 7cf82d6baa4..28d0136f598 100644 --- a/rostests/apitests/user32/SendMessageTimeout.c +++ b/rostests/apitests/user32/SendMessageTimeout.c @@ -7,10 +7,20 @@ #include #include +#include "helper.h" + +static DWORD dwThread1; +static DWORD dwThread2; +static HANDLE hThread1; +static HANDLE hThread2; +static HWND hWndThread1; +static HWND hWndThread2; static void -TestSendMessageTimeout(HWND hWnd, UINT Msg) +TestSendMessageTimeout( + _In_ HWND hWnd, + _In_ UINT Msg) { LRESULT ret; DWORD_PTR result; @@ -32,9 +42,200 @@ TestSendMessageTimeout(HWND hWnd, UINT Msg) ok(result == 0, "result = %Iu\n", result); } +#define WM_SENDTOOTHERTHREAD (WM_USER + 14) + +#define KILL_THREAD1_FLAG 0x40000000 +#define KILL_THREAD2_FLAG 0x20000000 +#define KILL_THREAD_FLAGS (KILL_THREAD1_FLAG | KILL_THREAD2_FLAG) + +static +LRESULT +CALLBACK +WndProc( + _In_ HWND hWnd, + _In_ UINT message, + _In_ WPARAM wParam, + _In_ LPARAM lParam) +{ + if (IsDWmMsg(message) || IseKeyMsg(message)) + return DefWindowProcW(hWnd, message, wParam, lParam); + + if (hWnd == hWndThread1) + { + RECOND_MESSAGE(1, message, SENT, wParam, lParam); + } + else if (hWnd == hWndThread2) + { + RECOND_MESSAGE(2, message, SENT, wParam, lParam); + } + else + { + RECOND_MESSAGE(3, message, SENT, wParam, lParam); + } + + switch (message) + { + case WM_SENDTOOTHERTHREAD: + if (GetCurrentThreadId() == dwThread1) + { + if ((wParam & KILL_THREAD2_FLAG) && + (wParam & ~KILL_THREAD_FLAGS) > 10) + { + TerminateThread(hThread2, 123); + } + if ((wParam & KILL_THREAD1_FLAG) && + (wParam & ~KILL_THREAD_FLAGS) > 10) + { + TerminateThread(hThread1, 456); + } + ok(lParam == dwThread2, "lParam = %Iu, expected %lu\n", lParam, dwThread2); + return SendMessage(hWndThread2, WM_SENDTOOTHERTHREAD, wParam + 1, GetCurrentThreadId()); + } + else + { + ok(lParam == dwThread1, "lParam = %Iu, expected %lu\n", lParam, dwThread1); + return SendMessage(hWndThread1, WM_SENDTOOTHERTHREAD, wParam + 1, GetCurrentThreadId()); + } + } + + return DefWindowProcW(hWnd, message, wParam, lParam); +} + +static +DWORD +WINAPI +Thread1( + _Inout_opt_ PVOID Parameter) +{ + MSG msg; + + hWndThread1 = CreateWindowExW(0, L"SendTest", NULL, 0, 10, 10, 20, 20, NULL, NULL, 0, NULL); + ok(hWndThread1 != NULL, "CreateWindow failed\n"); + + while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) + { + if (!(msg.message > WM_USER || IsDWmMsg(msg.message) || IseKeyMsg(msg.message))) + RECOND_MESSAGE(1, msg.message, POST, 0, 0); + DispatchMessageA(&msg); + } + + ResumeThread(hThread2); + + while (MsgWaitForMultipleObjectsEx(1, &hThread2, FALSE, QS_ALLEVENTS, MWMO_ALERTABLE) != WAIT_OBJECT_0) + { + while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) + { + if (!(msg.message > WM_USER || IsDWmMsg(msg.message) || IseKeyMsg(msg.message))) + RECOND_MESSAGE(1, msg.message, POST, 0, 0); + DispatchMessageA(&msg); + } + } + + DestroyWindow(hWndThread1); + while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) + { + if (!(msg.message > WM_USER || IsDWmMsg(msg.message) || IseKeyMsg(msg.message))) + RECOND_MESSAGE(1, msg.message, POST, 0, 0); + DispatchMessageA(&msg); + } + + return 6; +} + +static +DWORD +WINAPI +Thread2( + _Inout_opt_ PVOID Parameter) +{ + MSG msg; + LRESULT ret; + WPARAM wParam; + + hWndThread2 = CreateWindowExW(0, L"SendTest", NULL, 0, 10, 10, 20, 20, NULL, NULL, 0, NULL); + ok(hWndThread2 != NULL, "CreateWindow failed\n"); + + while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) + { + if (!(msg.message > WM_USER || IsDWmMsg(msg.message) || IseKeyMsg(msg.message))) + RECOND_MESSAGE(2, msg.message, POST, 0, 0); + DispatchMessageA(&msg); + } + + wParam = (WPARAM)Parameter; + ret = SendMessage(hWndThread1, WM_SENDTOOTHERTHREAD, wParam, dwThread2); + ok(ret == 0, "ret = %lu\n", ret); + + while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) + { + if (!(msg.message > WM_USER || IsDWmMsg(msg.message) || IseKeyMsg(msg.message))) + RECOND_MESSAGE(2, msg.message, POST, 0, 0); + DispatchMessageA(&msg); + } + + DestroyWindow(hWndThread2); + while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) + { + if (!(msg.message > WM_USER || IsDWmMsg(msg.message) || IseKeyMsg(msg.message))) + RECOND_MESSAGE(2, msg.message, POST, 0, 0); + DispatchMessageA(&msg); + } + + return 7; +} + +static +void +TestRecursiveInterThreadMessages( + _In_ BOOL KillThread1, + _In_ BOOL KillThread2) +{ + PVOID Parameter; + HANDLE Handles[2]; + BOOL Ret; + DWORD ExitCode; + + Parameter = (PVOID)((KillThread1 ? KILL_THREAD1_FLAG : 0) | + (KillThread2 ? KILL_THREAD2_FLAG : 0)); + hThread1 = CreateThread(NULL, 0, Thread1, Parameter, CREATE_SUSPENDED, &dwThread1); + hThread2 = CreateThread(NULL, 0, Thread2, Parameter, CREATE_SUSPENDED, &dwThread2); + + ResumeThread(hThread1); + + Handles[0] = hThread1; + Handles[1] = hThread2; + WaitForMultipleObjects(2, Handles, TRUE, INFINITE); + + Ret = GetExitCodeThread(hThread1, &ExitCode); + ok(Ret == TRUE, "GetExitCodeThread failed with %lu\n", GetLastError()); + if (KillThread1) + ok(ExitCode == 456, "Thread1 exit code is %lu\n", ExitCode); + else + ok(ExitCode == 6, "Thread1 exit code is %lu\n", ExitCode); + + Ret = GetExitCodeThread(hThread2, &ExitCode); + ok(Ret == TRUE, "GetExitCodeThread failed with %lu\n", GetLastError()); + if (KillThread2) + ok(ExitCode == 123, "Thread2 exit code is %lu\n", ExitCode); + else + ok(ExitCode == 7, "Thread2 exit code is %lu\n", ExitCode); + + CloseHandle(hThread2); + CloseHandle(hThread1); + + //TRACE_CACHE(); +} + START_TEST(SendMessageTimeout) { TestSendMessageTimeout(NULL, WM_USER); TestSendMessageTimeout(NULL, WM_PAINT); TestSendMessageTimeout(NULL, WM_GETICON); + + RegisterSimpleClass(WndProc, L"SendTest"); + + TestRecursiveInterThreadMessages(FALSE, FALSE); + TestRecursiveInterThreadMessages(FALSE, TRUE); + TestRecursiveInterThreadMessages(TRUE, FALSE); + TestRecursiveInterThreadMessages(TRUE, TRUE); } -- 2.17.1