[SHELL32_APITEST] Follow-up to #6796 (25e2f5f)
[reactos.git] / modules / rostests / winetests / user32 / broadcast.c
1 /*
2 * Unit tests for BroadcastSystemMessage
3 *
4 * Copyright 2008 Maarten Lankhorst
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #ifndef __REACTOS__
22 #define _WIN32_WINNT 0x0501
23 #endif
24
25 #include <stdarg.h>
26 #include <stdio.h>
27
28 #include "windef.h"
29 #include "winbase.h"
30 #include "wingdi.h"
31 #include "winuser.h"
32 #include "winnls.h"
33
34 #include "wine/test.h"
35
36 typedef LONG (WINAPI *PBROADCAST)( DWORD,LPDWORD,UINT,WPARAM,LPARAM );
37 typedef LONG (WINAPI *PBROADCASTEX)( DWORD,LPDWORD,UINT,WPARAM,LPARAM,PBSMINFO );
38 static HANDLE hevent;
39
40 static LRESULT WINAPI main_window_procA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
41 {
42 if (msg == WM_NULL)
43 {
44 trace("main_window_procA: Sleeping for %lu ms\n", wparam);
45 if (wparam)
46 {
47 if (WaitForSingleObject(hevent, wparam) == WAIT_TIMEOUT)
48 SetEvent(hevent);
49 }
50 trace("main_window_procA: Returning WM_NULL with parameter %08lx\n", lparam);
51 return lparam;
52 }
53
54 return DefWindowProcA(hwnd, msg, wparam, lparam);
55 }
56
57 static BOOL init_procs(void)
58 {
59 WNDCLASSA cls;
60
61 hevent = CreateEventA(NULL, TRUE, FALSE, "Asynchronous checking event");
62
63 cls.style = CS_DBLCLKS;
64 cls.lpfnWndProc = main_window_procA;
65 cls.cbClsExtra = 0;
66 cls.cbWndExtra = 0;
67 cls.hInstance = GetModuleHandleA(0);
68 cls.hIcon = 0;
69 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
70 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
71 cls.lpszMenuName = NULL;
72 cls.lpszClassName = "MainWindowClass";
73
74 if (!RegisterClassA(&cls))
75 return FALSE;
76
77 if (!CreateWindowExA(0, "MainWindowClass", "Main window", WS_CAPTION | WS_SYSMENU |
78 WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP, 100, 100, 200,
79 200, 0, 0, GetModuleHandleA(NULL), NULL))
80 return FALSE;
81 return TRUE;
82 }
83
84 static void test_parameters(PBROADCAST broadcast, const char *functionname)
85 {
86 LONG ret;
87 DWORD recips;
88
89 SetLastError(0xcafebabe);
90 recips = BSM_APPLICATIONS;
91 ret = broadcast( 0x80000000, &recips, WM_NULL, 0, 0 );
92 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
93 {
94 win_skip("%s is not implemented\n", functionname);
95 return;
96 }
97 ok(!ret || broken(ret), "Returned: %d\n", ret);
98 if (!ret) ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error: %08x\n", GetLastError());
99
100 SetLastError(0xcafebabe);
101 recips = BSM_APPLICATIONS;
102 ret = broadcast( 0x80000000, &recips, WM_NULL, 0, 0 );
103 ok(!ret || broken(ret), "Returned: %d\n", ret);
104 if (!ret) ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error: %08x\n", GetLastError());
105
106 if (0) /* TODO: Check the hang flags */
107 {
108 SetLastError(0xcafebabe);
109 recips = BSM_APPLICATIONS;
110 ret = broadcast( BSF_QUERY|(BSF_NOHANG|BSF_FORCEIFHUNG), &recips, WM_NULL, 30000, 0 );
111 ok(0, "Last error: %08x\n", GetLastError());
112 ok(0, "Returned: %d\n", ret);
113
114 SetLastError(0xcafebabe);
115 recips = BSM_APPLICATIONS;
116 ret = broadcast( BSF_QUERY|(BSF_NOHANG|BSF_NOTIMEOUTIFNOTHUNG), &recips, WM_NULL, 30000, 0 );
117 ok(0, "Last error: %08x\n", GetLastError());
118 ok(0, "Returned: %d\n", ret);
119
120 SetLastError(0xcafebabe);
121 recips = BSM_APPLICATIONS;
122 ret = broadcast( BSF_QUERY|(BSF_NOTIMEOUTIFNOTHUNG|BSF_FORCEIFHUNG), &recips, WM_NULL, 30000, 0 );
123 ok(0, "Last error: %08x\n", GetLastError());
124 ok(0, "Returned: %d\n", ret);
125
126 SetLastError(0xcafebabe);
127 recips = BSM_APPLICATIONS;
128 ret = broadcast( BSF_POSTMESSAGE|(BSF_NOTIMEOUTIFNOTHUNG|BSF_FORCEIFHUNG), &recips, WM_NULL, 30000, 0 );
129 ok(0, "Last error: %08x\n", GetLastError());
130 ok(0, "Returned: %d\n", ret);
131 }
132
133 SetLastError( 0xdeadbeef );
134 recips = BSM_APPLICATIONS;
135 ret = broadcast( BSF_POSTMESSAGE|BSF_SENDNOTIFYMESSAGE, &recips, WM_NULL, 100, 0 );
136 ok(ret==1, "Returned: %d\n", ret);
137 ok(WaitForSingleObject(hevent, 0) != WAIT_OBJECT_0, "Synchronous message sent instead\n");
138 PulseEvent(hevent);
139
140 recips = BSM_APPLICATIONS;
141 ret = broadcast( BSF_SENDNOTIFYMESSAGE, &recips, WM_NULL, 100, BROADCAST_QUERY_DENY );
142 ok(ret==1, "Returned: %d\n", ret);
143 ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n");
144 PulseEvent(hevent);
145 }
146
147 /* BSF_SENDNOTIFYMESSAGE and BSF_QUERY are both synchronous within the same process
148 * However you should be able to distinguish them by sending the BROADCAST_QUERY_DENY flag
149 */
150
151 static void test_parametersEx(PBROADCASTEX broadcastex)
152 {
153 LONG ret;
154 DWORD recips;
155
156 SetLastError(0xcafebabe);
157 recips = BSM_APPLICATIONS;
158 ret = broadcastex( 0x80000000, &recips, WM_NULL, 0, 0, NULL );
159 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error: %08x\n", GetLastError());
160 ok(!ret, "Returned: %d\n", ret);
161
162 SetLastError(0xcafebabe);
163 recips = BSM_APPLICATIONS;
164 ret = broadcastex( 0x80000000, &recips, WM_NULL, 0, 0, NULL );
165 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error: %08x\n", GetLastError());
166 ok(!ret, "Returned: %d\n", ret);
167
168 if (0) /* TODO: Check the hang flags */
169 {
170 SetLastError(0xcafebabe);
171 recips = BSM_APPLICATIONS;
172 ret = broadcastex( BSF_QUERY|(BSF_NOHANG|BSF_FORCEIFHUNG), &recips, WM_NULL, 30000, 0, NULL );
173 ok(0, "Last error: %08x\n", GetLastError());
174 ok(0, "Returned: %d\n", ret);
175
176 SetLastError(0xcafebabe);
177 recips = BSM_APPLICATIONS;
178 ret = broadcastex( BSF_QUERY|(BSF_NOHANG|BSF_NOTIMEOUTIFNOTHUNG), &recips, WM_NULL, 30000, 0, NULL );
179 ok(0, "Last error: %08x\n", GetLastError());
180 ok(0, "Returned: %d\n", ret);
181
182 SetLastError(0xcafebabe);
183 recips = BSM_APPLICATIONS;
184 ret = broadcastex( BSF_QUERY|(BSF_NOTIMEOUTIFNOTHUNG|BSF_FORCEIFHUNG), &recips, WM_NULL, 30000, 0, NULL );
185 ok(0, "Last error: %08x\n", GetLastError());
186 ok(0, "Returned: %d\n", ret);
187
188 SetLastError(0xcafebabe);
189 recips = BSM_APPLICATIONS;
190 ret = broadcastex( BSF_POSTMESSAGE|(BSF_NOTIMEOUTIFNOTHUNG|BSF_FORCEIFHUNG), &recips, WM_NULL, 30000, 0, NULL );
191 ok(0, "Last error: %08x\n", GetLastError());
192 ok(0, "Returned: %d\n", ret);
193 }
194
195 recips = BSM_APPLICATIONS;
196 ret = broadcastex( BSF_POSTMESSAGE|BSF_SENDNOTIFYMESSAGE, &recips, WM_NULL, 100, 0, NULL );
197 ok(ret==1, "Returned: %d\n", ret);
198 ok(WaitForSingleObject(hevent, 0) != WAIT_OBJECT_0, "Synchronous message sent instead\n");
199 PulseEvent(hevent);
200
201 recips = BSM_APPLICATIONS;
202 ret = broadcastex( BSF_SENDNOTIFYMESSAGE, &recips, WM_NULL, 100, BROADCAST_QUERY_DENY, NULL );
203 ok(ret==1, "Returned: %d\n", ret);
204 ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n");
205 PulseEvent(hevent);
206 }
207
208 START_TEST(broadcast)
209 {
210 if (!init_procs())
211 return;
212
213 trace("Running BroadcastSystemMessageA tests\n");
214 test_parameters(BroadcastSystemMessageA, "BroadcastSystemMessageA");
215
216 trace("Running BroadcastSystemMessageW tests\n");
217 test_parameters(BroadcastSystemMessageW, "BroadcastSystemMessageW");
218
219 trace("Running BroadcastSystemMessageExA tests\n");
220 test_parametersEx(BroadcastSystemMessageExA);
221
222 trace("Running BroadcastSystemMessageExW tests\n");
223 test_parametersEx(BroadcastSystemMessageExW);
224 }