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>
10 static DWORD dwThread1
;
11 static DWORD dwThread2
;
12 static HANDLE hThread1
;
13 static HANDLE hThread2
;
14 static HWND hWndThread1
;
15 static HWND hWndThread2
;
19 TestSendMessageTimeout(
26 ret
= SendMessageTimeoutW(hWnd
, Msg
, 0, 0, SMTO_NORMAL
, 0, NULL
);
27 ok(ret
== 0, "ret = %Id\n", ret
);
30 ret
= SendMessageTimeoutW(hWnd
, Msg
, 0, 0, SMTO_NORMAL
, 0, &result
);
31 ok(ret
== 0, "ret = %Id\n", ret
);
32 ok(result
== 0, "result = %Iu\n", result
);
34 ret
= SendMessageTimeoutA(hWnd
, Msg
, 0, 0, SMTO_NORMAL
, 0, NULL
);
35 ok(ret
== 0, "ret = %Id\n", ret
);
38 ret
= SendMessageTimeoutA(hWnd
, Msg
, 0, 0, SMTO_NORMAL
, 0, &result
);
39 ok(ret
== 0, "ret = %Id\n", ret
);
40 ok(result
== 0, "result = %Iu\n", result
);
43 #define WM_SENDTOOTHERTHREAD (WM_USER + 14)
45 #define KILL_THREAD1_FLAG 0x40000000
46 #define KILL_THREAD2_FLAG 0x20000000
47 #define KILL_THREAD_FLAGS (KILL_THREAD1_FLAG | KILL_THREAD2_FLAG)
58 if (IsDWmMsg(message
) || IseKeyMsg(message
))
59 return DefWindowProcW(hWnd
, message
, wParam
, lParam
);
61 if (hWnd
== hWndThread1
)
63 RECORD_MESSAGE(1, message
, SENT
, wParam
, lParam
);
65 else if (hWnd
== hWndThread2
)
67 RECORD_MESSAGE(2, message
, SENT
, wParam
, lParam
);
71 RECORD_MESSAGE(3, message
, SENT
, wParam
, lParam
);
76 case WM_SENDTOOTHERTHREAD
:
77 if (GetCurrentThreadId() == dwThread1
)
79 if ((wParam
& KILL_THREAD2_FLAG
) &&
80 (wParam
& ~KILL_THREAD_FLAGS
) > 10)
82 TerminateThread(hThread2
, 123);
84 if ((wParam
& KILL_THREAD1_FLAG
) &&
85 (wParam
& ~KILL_THREAD_FLAGS
) > 10)
87 TerminateThread(hThread1
, 456);
89 ok(lParam
== dwThread2
, "lParam = %Iu, expected %lu\n", lParam
, dwThread2
);
90 return SendMessage(hWndThread2
, WM_SENDTOOTHERTHREAD
, wParam
+ 1, GetCurrentThreadId());
94 ok(lParam
== dwThread1
, "lParam = %Iu, expected %lu\n", lParam
, dwThread1
);
95 return SendMessage(hWndThread1
, WM_SENDTOOTHERTHREAD
, wParam
+ 1, GetCurrentThreadId());
99 return DefWindowProcW(hWnd
, message
, wParam
, lParam
);
106 _Inout_opt_ PVOID Parameter
)
110 hWndThread1
= CreateWindowExW(0, L
"SendTest", NULL
, 0, 10, 10, 20, 20, NULL
, NULL
, 0, NULL
);
111 ok(hWndThread1
!= NULL
, "CreateWindow failed\n");
113 while (PeekMessage(&msg
, 0, 0, 0, PM_REMOVE
))
115 if (!(msg
.message
> WM_USER
|| IsDWmMsg(msg
.message
) || IseKeyMsg(msg
.message
)))
116 RECORD_MESSAGE(1, msg
.message
, POST
, 0, 0);
117 DispatchMessageA(&msg
);
120 ResumeThread(hThread2
);
122 while (MsgWaitForMultipleObjectsEx(1, &hThread2
, FALSE
, QS_ALLEVENTS
, MWMO_ALERTABLE
) != WAIT_OBJECT_0
)
124 while (PeekMessage(&msg
, 0, 0, 0, PM_REMOVE
))
126 if (!(msg
.message
> WM_USER
|| IsDWmMsg(msg
.message
) || IseKeyMsg(msg
.message
)))
127 RECORD_MESSAGE(1, msg
.message
, POST
, 0, 0);
128 DispatchMessageA(&msg
);
132 DestroyWindow(hWndThread1
);
133 while (PeekMessage(&msg
, 0, 0, 0, PM_REMOVE
))
135 if (!(msg
.message
> WM_USER
|| IsDWmMsg(msg
.message
) || IseKeyMsg(msg
.message
)))
136 RECORD_MESSAGE(1, msg
.message
, POST
, 0, 0);
137 DispatchMessageA(&msg
);
147 _Inout_opt_ PVOID Parameter
)
153 hWndThread2
= CreateWindowExW(0, L
"SendTest", NULL
, 0, 10, 10, 20, 20, NULL
, NULL
, 0, NULL
);
154 ok(hWndThread2
!= NULL
, "CreateWindow failed\n");
156 while (PeekMessage(&msg
, 0, 0, 0, PM_REMOVE
))
158 if (!(msg
.message
> WM_USER
|| IsDWmMsg(msg
.message
) || IseKeyMsg(msg
.message
)))
159 RECORD_MESSAGE(2, msg
.message
, POST
, 0, 0);
160 DispatchMessageA(&msg
);
163 wParam
= (WPARAM
)Parameter
;
164 ret
= SendMessage(hWndThread1
, WM_SENDTOOTHERTHREAD
, wParam
, dwThread2
);
165 ok(ret
== 0, "ret = %lu\n", ret
);
167 while (PeekMessage(&msg
, 0, 0, 0, PM_REMOVE
))
169 if (!(msg
.message
> WM_USER
|| IsDWmMsg(msg
.message
) || IseKeyMsg(msg
.message
)))
170 RECORD_MESSAGE(2, msg
.message
, POST
, 0, 0);
171 DispatchMessageA(&msg
);
174 DestroyWindow(hWndThread2
);
175 while (PeekMessage(&msg
, 0, 0, 0, PM_REMOVE
))
177 if (!(msg
.message
> WM_USER
|| IsDWmMsg(msg
.message
) || IseKeyMsg(msg
.message
)))
178 RECORD_MESSAGE(2, msg
.message
, POST
, 0, 0);
179 DispatchMessageA(&msg
);
187 TestRecursiveInterThreadMessages(
188 _In_ BOOL KillThread1
,
189 _In_ BOOL KillThread2
)
196 Parameter
= UlongToPtr((KillThread1
? KILL_THREAD1_FLAG
: 0) |
197 (KillThread2
? KILL_THREAD2_FLAG
: 0));
198 hThread1
= CreateThread(NULL
, 0, Thread1
, Parameter
, CREATE_SUSPENDED
, &dwThread1
);
199 hThread2
= CreateThread(NULL
, 0, Thread2
, Parameter
, CREATE_SUSPENDED
, &dwThread2
);
201 ResumeThread(hThread1
);
203 Handles
[0] = hThread1
;
204 Handles
[1] = hThread2
;
205 WaitForMultipleObjects(2, Handles
, TRUE
, INFINITE
);
207 Ret
= GetExitCodeThread(hThread1
, &ExitCode
);
208 ok(Ret
== TRUE
, "GetExitCodeThread failed with %lu\n", GetLastError());
210 ok(ExitCode
== 456, "Thread1 exit code is %lu\n", ExitCode
);
212 ok(ExitCode
== 6, "Thread1 exit code is %lu\n", ExitCode
);
214 Ret
= GetExitCodeThread(hThread2
, &ExitCode
);
215 ok(Ret
== TRUE
, "GetExitCodeThread failed with %lu\n", GetLastError());
217 ok(ExitCode
== 123, "Thread2 exit code is %lu\n", ExitCode
);
219 ok(ExitCode
== 7, "Thread2 exit code is %lu\n", ExitCode
);
221 CloseHandle(hThread2
);
222 CloseHandle(hThread1
);
227 START_TEST(SendMessageTimeout
)
229 TestSendMessageTimeout(NULL
, WM_USER
);
230 TestSendMessageTimeout(NULL
, WM_PAINT
);
231 TestSendMessageTimeout(NULL
, WM_GETICON
);
233 RegisterSimpleClass(WndProc
, L
"SendTest");
235 TestRecursiveInterThreadMessages(FALSE
, FALSE
);
236 TestRecursiveInterThreadMessages(FALSE
, TRUE
);
237 TestRecursiveInterThreadMessages(TRUE
, FALSE
);
238 TestRecursiveInterThreadMessages(TRUE
, TRUE
);