[USER32_APITEST] -Move the helper functions in the common include directory
[reactos.git] / rostests / apitests / user32 / SendMessageTimeout.c
1 /*
2 * PROJECT: ReactOS API tests
3 * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory
4 * PURPOSE: Test for SendMessageTimeout
5 * PROGRAMMERS: Thomas Faber <thomas.faber@reactos.org>
6 */
7
8 #include <apitest.h>
9 #include <winuser.h>
10
11 #include <msgtrace.h>
12 #include <user32testhelpers.h>
13
14 static DWORD dwThread1;
15 static DWORD dwThread2;
16 static HANDLE hThread1;
17 static HANDLE hThread2;
18 static HWND hWndThread1;
19 static HWND hWndThread2;
20
21 static
22 void
23 TestSendMessageTimeout(
24 _In_ HWND hWnd,
25 _In_ UINT Msg)
26 {
27 LRESULT ret;
28 DWORD_PTR result;
29
30 ret = SendMessageTimeoutW(hWnd, Msg, 0, 0, SMTO_NORMAL, 0, NULL);
31 ok(ret == 0, "ret = %Id\n", ret);
32
33 result = 0x55555555;
34 ret = SendMessageTimeoutW(hWnd, Msg, 0, 0, SMTO_NORMAL, 0, &result);
35 ok(ret == 0, "ret = %Id\n", ret);
36 ok(result == 0, "result = %Iu\n", result);
37
38 ret = SendMessageTimeoutA(hWnd, Msg, 0, 0, SMTO_NORMAL, 0, NULL);
39 ok(ret == 0, "ret = %Id\n", ret);
40
41 result = 0x55555555;
42 ret = SendMessageTimeoutA(hWnd, Msg, 0, 0, SMTO_NORMAL, 0, &result);
43 ok(ret == 0, "ret = %Id\n", ret);
44 ok(result == 0, "result = %Iu\n", result);
45 }
46
47 #define WM_SENDTOOTHERTHREAD (WM_USER + 14)
48
49 #define KILL_THREAD1_FLAG 0x40000000
50 #define KILL_THREAD2_FLAG 0x20000000
51 #define KILL_THREAD_FLAGS (KILL_THREAD1_FLAG | KILL_THREAD2_FLAG)
52
53 static
54 LRESULT
55 CALLBACK
56 WndProc(
57 _In_ HWND hWnd,
58 _In_ UINT message,
59 _In_ WPARAM wParam,
60 _In_ LPARAM lParam)
61 {
62 if (IsDWmMsg(message) || IseKeyMsg(message))
63 return DefWindowProcW(hWnd, message, wParam, lParam);
64
65 if (hWnd == hWndThread1)
66 {
67 RECORD_MESSAGE(1, message, SENT, wParam, lParam);
68 }
69 else if (hWnd == hWndThread2)
70 {
71 RECORD_MESSAGE(2, message, SENT, wParam, lParam);
72 }
73 else
74 {
75 RECORD_MESSAGE(3, message, SENT, wParam, lParam);
76 }
77
78 switch (message)
79 {
80 case WM_SENDTOOTHERTHREAD:
81 if (GetCurrentThreadId() == dwThread1)
82 {
83 if ((wParam & KILL_THREAD2_FLAG) &&
84 (wParam & ~KILL_THREAD_FLAGS) > 10)
85 {
86 TerminateThread(hThread2, 123);
87 }
88 if ((wParam & KILL_THREAD1_FLAG) &&
89 (wParam & ~KILL_THREAD_FLAGS) > 10)
90 {
91 TerminateThread(hThread1, 456);
92 }
93 ok(lParam == dwThread2, "lParam = %Iu, expected %lu\n", lParam, dwThread2);
94 return SendMessage(hWndThread2, WM_SENDTOOTHERTHREAD, wParam + 1, GetCurrentThreadId());
95 }
96 else
97 {
98 ok(lParam == dwThread1, "lParam = %Iu, expected %lu\n", lParam, dwThread1);
99 return SendMessage(hWndThread1, WM_SENDTOOTHERTHREAD, wParam + 1, GetCurrentThreadId());
100 }
101 }
102
103 return DefWindowProcW(hWnd, message, wParam, lParam);
104 }
105
106 static
107 DWORD
108 WINAPI
109 Thread1(
110 _Inout_opt_ PVOID Parameter)
111 {
112 MSG msg;
113
114 hWndThread1 = CreateWindowExW(0, L"SendTest", NULL, 0, 10, 10, 20, 20, NULL, NULL, 0, NULL);
115 ok(hWndThread1 != NULL, "CreateWindow failed\n");
116
117 while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
118 {
119 if (!(msg.message > WM_USER || IsDWmMsg(msg.message) || IseKeyMsg(msg.message)))
120 RECORD_MESSAGE(1, msg.message, POST, 0, 0);
121 DispatchMessageA(&msg);
122 }
123
124 ResumeThread(hThread2);
125
126 while (MsgWaitForMultipleObjectsEx(1, &hThread2, FALSE, QS_ALLEVENTS, MWMO_ALERTABLE) != WAIT_OBJECT_0)
127 {
128 while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
129 {
130 if (!(msg.message > WM_USER || IsDWmMsg(msg.message) || IseKeyMsg(msg.message)))
131 RECORD_MESSAGE(1, msg.message, POST, 0, 0);
132 DispatchMessageA(&msg);
133 }
134 }
135
136 DestroyWindow(hWndThread1);
137 while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
138 {
139 if (!(msg.message > WM_USER || IsDWmMsg(msg.message) || IseKeyMsg(msg.message)))
140 RECORD_MESSAGE(1, msg.message, POST, 0, 0);
141 DispatchMessageA(&msg);
142 }
143
144 return 6;
145 }
146
147 static
148 DWORD
149 WINAPI
150 Thread2(
151 _Inout_opt_ PVOID Parameter)
152 {
153 MSG msg;
154 LRESULT ret;
155 WPARAM wParam;
156
157 hWndThread2 = CreateWindowExW(0, L"SendTest", NULL, 0, 10, 10, 20, 20, NULL, NULL, 0, NULL);
158 ok(hWndThread2 != NULL, "CreateWindow failed\n");
159
160 while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
161 {
162 if (!(msg.message > WM_USER || IsDWmMsg(msg.message) || IseKeyMsg(msg.message)))
163 RECORD_MESSAGE(2, msg.message, POST, 0, 0);
164 DispatchMessageA(&msg);
165 }
166
167 wParam = (WPARAM)Parameter;
168 ret = SendMessage(hWndThread1, WM_SENDTOOTHERTHREAD, wParam, dwThread2);
169 ok(ret == 0, "ret = %lu\n", ret);
170
171 while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
172 {
173 if (!(msg.message > WM_USER || IsDWmMsg(msg.message) || IseKeyMsg(msg.message)))
174 RECORD_MESSAGE(2, msg.message, POST, 0, 0);
175 DispatchMessageA(&msg);
176 }
177
178 DestroyWindow(hWndThread2);
179 while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
180 {
181 if (!(msg.message > WM_USER || IsDWmMsg(msg.message) || IseKeyMsg(msg.message)))
182 RECORD_MESSAGE(2, msg.message, POST, 0, 0);
183 DispatchMessageA(&msg);
184 }
185
186 return 7;
187 }
188
189 static
190 void
191 TestRecursiveInterThreadMessages(
192 _In_ BOOL KillThread1,
193 _In_ BOOL KillThread2)
194 {
195 PVOID Parameter;
196 HANDLE Handles[2];
197 BOOL Ret;
198 DWORD ExitCode;
199
200 Parameter = (PVOID)((KillThread1 ? KILL_THREAD1_FLAG : 0) |
201 (KillThread2 ? KILL_THREAD2_FLAG : 0));
202 hThread1 = CreateThread(NULL, 0, Thread1, Parameter, CREATE_SUSPENDED, &dwThread1);
203 hThread2 = CreateThread(NULL, 0, Thread2, Parameter, CREATE_SUSPENDED, &dwThread2);
204
205 ResumeThread(hThread1);
206
207 Handles[0] = hThread1;
208 Handles[1] = hThread2;
209 WaitForMultipleObjects(2, Handles, TRUE, INFINITE);
210
211 Ret = GetExitCodeThread(hThread1, &ExitCode);
212 ok(Ret == TRUE, "GetExitCodeThread failed with %lu\n", GetLastError());
213 if (KillThread1)
214 ok(ExitCode == 456, "Thread1 exit code is %lu\n", ExitCode);
215 else
216 ok(ExitCode == 6, "Thread1 exit code is %lu\n", ExitCode);
217
218 Ret = GetExitCodeThread(hThread2, &ExitCode);
219 ok(Ret == TRUE, "GetExitCodeThread failed with %lu\n", GetLastError());
220 if (KillThread2)
221 ok(ExitCode == 123, "Thread2 exit code is %lu\n", ExitCode);
222 else
223 ok(ExitCode == 7, "Thread2 exit code is %lu\n", ExitCode);
224
225 CloseHandle(hThread2);
226 CloseHandle(hThread1);
227
228 //TRACE_CACHE();
229 }
230
231 START_TEST(SendMessageTimeout)
232 {
233 TestSendMessageTimeout(NULL, WM_USER);
234 TestSendMessageTimeout(NULL, WM_PAINT);
235 TestSendMessageTimeout(NULL, WM_GETICON);
236
237 RegisterSimpleClass(WndProc, L"SendTest");
238
239 TestRecursiveInterThreadMessages(FALSE, FALSE);
240 TestRecursiveInterThreadMessages(FALSE, TRUE);
241 TestRecursiveInterThreadMessages(TRUE, FALSE);
242 TestRecursiveInterThreadMessages(TRUE, TRUE);
243 }