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 static DWORD dwThread1
;
13 static DWORD dwThread2
;
14 static HANDLE hThread1
;
15 static HANDLE hThread2
;
16 static HWND hWndThread1
;
17 static HWND hWndThread2
;
21 TestSendMessageTimeout(
28 ret
= SendMessageTimeoutW(hWnd
, Msg
, 0, 0, SMTO_NORMAL
, 0, NULL
);
29 ok(ret
== 0, "ret = %Id\n", ret
);
32 ret
= SendMessageTimeoutW(hWnd
, Msg
, 0, 0, SMTO_NORMAL
, 0, &result
);
33 ok(ret
== 0, "ret = %Id\n", ret
);
34 ok(result
== 0, "result = %Iu\n", result
);
36 ret
= SendMessageTimeoutA(hWnd
, Msg
, 0, 0, SMTO_NORMAL
, 0, NULL
);
37 ok(ret
== 0, "ret = %Id\n", ret
);
40 ret
= SendMessageTimeoutA(hWnd
, Msg
, 0, 0, SMTO_NORMAL
, 0, &result
);
41 ok(ret
== 0, "ret = %Id\n", ret
);
42 ok(result
== 0, "result = %Iu\n", result
);
45 #define WM_SENDTOOTHERTHREAD (WM_USER + 14)
47 #define KILL_THREAD1_FLAG 0x40000000
48 #define KILL_THREAD2_FLAG 0x20000000
49 #define KILL_THREAD_FLAGS (KILL_THREAD1_FLAG | KILL_THREAD2_FLAG)
60 if (IsDWmMsg(message
) || IseKeyMsg(message
))
61 return DefWindowProcW(hWnd
, message
, wParam
, lParam
);
63 if (hWnd
== hWndThread1
)
65 RECORD_MESSAGE(1, message
, SENT
, wParam
, lParam
);
67 else if (hWnd
== hWndThread2
)
69 RECORD_MESSAGE(2, message
, SENT
, wParam
, lParam
);
73 RECORD_MESSAGE(3, message
, SENT
, wParam
, lParam
);
78 case WM_SENDTOOTHERTHREAD
:
79 if (GetCurrentThreadId() == dwThread1
)
81 if ((wParam
& KILL_THREAD2_FLAG
) &&
82 (wParam
& ~KILL_THREAD_FLAGS
) > 10)
84 TerminateThread(hThread2
, 123);
86 if ((wParam
& KILL_THREAD1_FLAG
) &&
87 (wParam
& ~KILL_THREAD_FLAGS
) > 10)
89 TerminateThread(hThread1
, 456);
91 ok(lParam
== dwThread2
, "lParam = %Iu, expected %lu\n", lParam
, dwThread2
);
92 return SendMessage(hWndThread2
, WM_SENDTOOTHERTHREAD
, wParam
+ 1, GetCurrentThreadId());
96 ok(lParam
== dwThread1
, "lParam = %Iu, expected %lu\n", lParam
, dwThread1
);
97 return SendMessage(hWndThread1
, WM_SENDTOOTHERTHREAD
, wParam
+ 1, GetCurrentThreadId());
101 return DefWindowProcW(hWnd
, message
, wParam
, lParam
);
108 _Inout_opt_ PVOID Parameter
)
112 hWndThread1
= CreateWindowExW(0, L
"SendTest", NULL
, 0, 10, 10, 20, 20, NULL
, NULL
, 0, NULL
);
113 ok(hWndThread1
!= NULL
, "CreateWindow failed\n");
115 while (PeekMessage(&msg
, 0, 0, 0, PM_REMOVE
))
117 if (!(msg
.message
> WM_USER
|| IsDWmMsg(msg
.message
) || IseKeyMsg(msg
.message
)))
118 RECORD_MESSAGE(1, msg
.message
, POST
, 0, 0);
119 DispatchMessageA(&msg
);
122 ResumeThread(hThread2
);
124 while (MsgWaitForMultipleObjectsEx(1, &hThread2
, FALSE
, QS_ALLEVENTS
, MWMO_ALERTABLE
) != WAIT_OBJECT_0
)
126 while (PeekMessage(&msg
, 0, 0, 0, PM_REMOVE
))
128 if (!(msg
.message
> WM_USER
|| IsDWmMsg(msg
.message
) || IseKeyMsg(msg
.message
)))
129 RECORD_MESSAGE(1, msg
.message
, POST
, 0, 0);
130 DispatchMessageA(&msg
);
134 DestroyWindow(hWndThread1
);
135 while (PeekMessage(&msg
, 0, 0, 0, PM_REMOVE
))
137 if (!(msg
.message
> WM_USER
|| IsDWmMsg(msg
.message
) || IseKeyMsg(msg
.message
)))
138 RECORD_MESSAGE(1, msg
.message
, POST
, 0, 0);
139 DispatchMessageA(&msg
);
149 _Inout_opt_ PVOID Parameter
)
155 hWndThread2
= CreateWindowExW(0, L
"SendTest", NULL
, 0, 10, 10, 20, 20, NULL
, NULL
, 0, NULL
);
156 ok(hWndThread2
!= NULL
, "CreateWindow failed\n");
158 while (PeekMessage(&msg
, 0, 0, 0, PM_REMOVE
))
160 if (!(msg
.message
> WM_USER
|| IsDWmMsg(msg
.message
) || IseKeyMsg(msg
.message
)))
161 RECORD_MESSAGE(2, msg
.message
, POST
, 0, 0);
162 DispatchMessageA(&msg
);
165 wParam
= (WPARAM
)Parameter
;
166 ret
= SendMessage(hWndThread1
, WM_SENDTOOTHERTHREAD
, wParam
, dwThread2
);
167 ok(ret
== 0, "ret = %lu\n", ret
);
169 while (PeekMessage(&msg
, 0, 0, 0, PM_REMOVE
))
171 if (!(msg
.message
> WM_USER
|| IsDWmMsg(msg
.message
) || IseKeyMsg(msg
.message
)))
172 RECORD_MESSAGE(2, msg
.message
, POST
, 0, 0);
173 DispatchMessageA(&msg
);
176 DestroyWindow(hWndThread2
);
177 while (PeekMessage(&msg
, 0, 0, 0, PM_REMOVE
))
179 if (!(msg
.message
> WM_USER
|| IsDWmMsg(msg
.message
) || IseKeyMsg(msg
.message
)))
180 RECORD_MESSAGE(2, msg
.message
, POST
, 0, 0);
181 DispatchMessageA(&msg
);
189 TestRecursiveInterThreadMessages(
190 _In_ BOOL KillThread1
,
191 _In_ BOOL KillThread2
)
198 Parameter
= (PVOID
)((KillThread1
? KILL_THREAD1_FLAG
: 0) |
199 (KillThread2
? KILL_THREAD2_FLAG
: 0));
200 hThread1
= CreateThread(NULL
, 0, Thread1
, Parameter
, CREATE_SUSPENDED
, &dwThread1
);
201 hThread2
= CreateThread(NULL
, 0, Thread2
, Parameter
, CREATE_SUSPENDED
, &dwThread2
);
203 ResumeThread(hThread1
);
205 Handles
[0] = hThread1
;
206 Handles
[1] = hThread2
;
207 WaitForMultipleObjects(2, Handles
, TRUE
, INFINITE
);
209 Ret
= GetExitCodeThread(hThread1
, &ExitCode
);
210 ok(Ret
== TRUE
, "GetExitCodeThread failed with %lu\n", GetLastError());
212 ok(ExitCode
== 456, "Thread1 exit code is %lu\n", ExitCode
);
214 ok(ExitCode
== 6, "Thread1 exit code is %lu\n", ExitCode
);
216 Ret
= GetExitCodeThread(hThread2
, &ExitCode
);
217 ok(Ret
== TRUE
, "GetExitCodeThread failed with %lu\n", GetLastError());
219 ok(ExitCode
== 123, "Thread2 exit code is %lu\n", ExitCode
);
221 ok(ExitCode
== 7, "Thread2 exit code is %lu\n", ExitCode
);
223 CloseHandle(hThread2
);
224 CloseHandle(hThread1
);
229 START_TEST(SendMessageTimeout
)
231 TestSendMessageTimeout(NULL
, WM_USER
);
232 TestSendMessageTimeout(NULL
, WM_PAINT
);
233 TestSendMessageTimeout(NULL
, WM_GETICON
);
235 RegisterSimpleClass(WndProc
, L
"SendTest");
237 TestRecursiveInterThreadMessages(FALSE
, FALSE
);
238 TestRecursiveInterThreadMessages(FALSE
, TRUE
);
239 TestRecursiveInterThreadMessages(TRUE
, FALSE
);
240 TestRecursiveInterThreadMessages(TRUE
, TRUE
);