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>
12 #include <user32testhelpers.h>
14 static DWORD dwThread1
;
15 static DWORD dwThread2
;
16 static HANDLE hThread1
;
17 static HANDLE hThread2
;
18 static HWND hWndThread1
;
19 static HWND hWndThread2
;
23 TestSendMessageTimeout(
30 ret
= SendMessageTimeoutW(hWnd
, Msg
, 0, 0, SMTO_NORMAL
, 0, NULL
);
31 ok(ret
== 0, "ret = %Id\n", ret
);
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
);
38 ret
= SendMessageTimeoutA(hWnd
, Msg
, 0, 0, SMTO_NORMAL
, 0, NULL
);
39 ok(ret
== 0, "ret = %Id\n", ret
);
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
);
47 #define WM_SENDTOOTHERTHREAD (WM_USER + 14)
49 #define KILL_THREAD1_FLAG 0x40000000
50 #define KILL_THREAD2_FLAG 0x20000000
51 #define KILL_THREAD_FLAGS (KILL_THREAD1_FLAG | KILL_THREAD2_FLAG)
62 if (IsDWmMsg(message
) || IseKeyMsg(message
))
63 return DefWindowProcW(hWnd
, message
, wParam
, lParam
);
65 if (hWnd
== hWndThread1
)
67 RECORD_MESSAGE(1, message
, SENT
, wParam
, lParam
);
69 else if (hWnd
== hWndThread2
)
71 RECORD_MESSAGE(2, message
, SENT
, wParam
, lParam
);
75 RECORD_MESSAGE(3, message
, SENT
, wParam
, lParam
);
80 case WM_SENDTOOTHERTHREAD
:
81 if (GetCurrentThreadId() == dwThread1
)
83 if ((wParam
& KILL_THREAD2_FLAG
) &&
84 (wParam
& ~KILL_THREAD_FLAGS
) > 10)
86 TerminateThread(hThread2
, 123);
88 if ((wParam
& KILL_THREAD1_FLAG
) &&
89 (wParam
& ~KILL_THREAD_FLAGS
) > 10)
91 TerminateThread(hThread1
, 456);
93 ok(lParam
== dwThread2
, "lParam = %Iu, expected %lu\n", lParam
, dwThread2
);
94 return SendMessage(hWndThread2
, WM_SENDTOOTHERTHREAD
, wParam
+ 1, GetCurrentThreadId());
98 ok(lParam
== dwThread1
, "lParam = %Iu, expected %lu\n", lParam
, dwThread1
);
99 return SendMessage(hWndThread1
, WM_SENDTOOTHERTHREAD
, wParam
+ 1, GetCurrentThreadId());
103 return DefWindowProcW(hWnd
, message
, wParam
, lParam
);
110 _Inout_opt_ PVOID Parameter
)
114 hWndThread1
= CreateWindowExW(0, L
"SendTest", NULL
, 0, 10, 10, 20, 20, NULL
, NULL
, 0, NULL
);
115 ok(hWndThread1
!= NULL
, "CreateWindow failed\n");
117 while (PeekMessage(&msg
, 0, 0, 0, PM_REMOVE
))
119 if (!(msg
.message
> WM_USER
|| IsDWmMsg(msg
.message
) || IseKeyMsg(msg
.message
)))
120 RECORD_MESSAGE(1, msg
.message
, POST
, 0, 0);
121 DispatchMessageA(&msg
);
124 ResumeThread(hThread2
);
126 while (MsgWaitForMultipleObjectsEx(1, &hThread2
, FALSE
, QS_ALLEVENTS
, MWMO_ALERTABLE
) != WAIT_OBJECT_0
)
128 while (PeekMessage(&msg
, 0, 0, 0, PM_REMOVE
))
130 if (!(msg
.message
> WM_USER
|| IsDWmMsg(msg
.message
) || IseKeyMsg(msg
.message
)))
131 RECORD_MESSAGE(1, msg
.message
, POST
, 0, 0);
132 DispatchMessageA(&msg
);
136 DestroyWindow(hWndThread1
);
137 while (PeekMessage(&msg
, 0, 0, 0, PM_REMOVE
))
139 if (!(msg
.message
> WM_USER
|| IsDWmMsg(msg
.message
) || IseKeyMsg(msg
.message
)))
140 RECORD_MESSAGE(1, msg
.message
, POST
, 0, 0);
141 DispatchMessageA(&msg
);
151 _Inout_opt_ PVOID Parameter
)
157 hWndThread2
= CreateWindowExW(0, L
"SendTest", NULL
, 0, 10, 10, 20, 20, NULL
, NULL
, 0, NULL
);
158 ok(hWndThread2
!= NULL
, "CreateWindow failed\n");
160 while (PeekMessage(&msg
, 0, 0, 0, PM_REMOVE
))
162 if (!(msg
.message
> WM_USER
|| IsDWmMsg(msg
.message
) || IseKeyMsg(msg
.message
)))
163 RECORD_MESSAGE(2, msg
.message
, POST
, 0, 0);
164 DispatchMessageA(&msg
);
167 wParam
= (WPARAM
)Parameter
;
168 ret
= SendMessage(hWndThread1
, WM_SENDTOOTHERTHREAD
, wParam
, dwThread2
);
169 ok(ret
== 0, "ret = %lu\n", ret
);
171 while (PeekMessage(&msg
, 0, 0, 0, PM_REMOVE
))
173 if (!(msg
.message
> WM_USER
|| IsDWmMsg(msg
.message
) || IseKeyMsg(msg
.message
)))
174 RECORD_MESSAGE(2, msg
.message
, POST
, 0, 0);
175 DispatchMessageA(&msg
);
178 DestroyWindow(hWndThread2
);
179 while (PeekMessage(&msg
, 0, 0, 0, PM_REMOVE
))
181 if (!(msg
.message
> WM_USER
|| IsDWmMsg(msg
.message
) || IseKeyMsg(msg
.message
)))
182 RECORD_MESSAGE(2, msg
.message
, POST
, 0, 0);
183 DispatchMessageA(&msg
);
191 TestRecursiveInterThreadMessages(
192 _In_ BOOL KillThread1
,
193 _In_ BOOL KillThread2
)
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
);
205 ResumeThread(hThread1
);
207 Handles
[0] = hThread1
;
208 Handles
[1] = hThread2
;
209 WaitForMultipleObjects(2, Handles
, TRUE
, INFINITE
);
211 Ret
= GetExitCodeThread(hThread1
, &ExitCode
);
212 ok(Ret
== TRUE
, "GetExitCodeThread failed with %lu\n", GetLastError());
214 ok(ExitCode
== 456, "Thread1 exit code is %lu\n", ExitCode
);
216 ok(ExitCode
== 6, "Thread1 exit code is %lu\n", ExitCode
);
218 Ret
= GetExitCodeThread(hThread2
, &ExitCode
);
219 ok(Ret
== TRUE
, "GetExitCodeThread failed with %lu\n", GetLastError());
221 ok(ExitCode
== 123, "Thread2 exit code is %lu\n", ExitCode
);
223 ok(ExitCode
== 7, "Thread2 exit code is %lu\n", ExitCode
);
225 CloseHandle(hThread2
);
226 CloseHandle(hThread1
);
231 START_TEST(SendMessageTimeout
)
233 TestSendMessageTimeout(NULL
, WM_USER
);
234 TestSendMessageTimeout(NULL
, WM_PAINT
);
235 TestSendMessageTimeout(NULL
, WM_GETICON
);
237 RegisterSimpleClass(WndProc
, L
"SendTest");
239 TestRecursiveInterThreadMessages(FALSE
, FALSE
);
240 TestRecursiveInterThreadMessages(FALSE
, TRUE
);
241 TestRecursiveInterThreadMessages(TRUE
, FALSE
);
242 TestRecursiveInterThreadMessages(TRUE
, TRUE
);