[winetests]
[reactos.git] / 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 #define _WIN32_WINNT 0x0501
22
23 #include <assert.h>
24 #include <stdarg.h>
25 #include <stdio.h>
26
27 #include "windef.h"
28 #include "winbase.h"
29 #include "wingdi.h"
30 #include "winuser.h"
31 #include "winnls.h"
32
33 #include "wine/test.h"
34
35 typedef LONG (WINAPI *PBROADCAST)( DWORD,LPDWORD,UINT,WPARAM,LPARAM );
36 typedef LONG (WINAPI *PBROADCASTEX)( DWORD,LPDWORD,UINT,WPARAM,LPARAM,PBSMINFO );
37 static PBROADCAST pBroadcastA;
38 static PBROADCAST pBroadcastW;
39 static PBROADCASTEX pBroadcastExA;
40 static PBROADCASTEX pBroadcastExW;
41 static HANDLE hevent;
42
43 static LRESULT WINAPI main_window_procA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
44 {
45 if (msg == WM_NULL)
46 {
47 trace("main_window_procA: Sleeping for %lu ms\n", wparam);
48 if (wparam)
49 {
50 if (WaitForSingleObject(hevent, wparam) == WAIT_TIMEOUT)
51 SetEvent(hevent);
52 }
53 trace("main_window_procA: Returning WM_NULL with parameter %08lx\n", lparam);
54 return lparam;
55 }
56
57 return DefWindowProcA(hwnd, msg, wparam, lparam);
58 }
59
60 static BOOL init_procs(void)
61 {
62 WNDCLASSA cls;
63 HANDLE user32 = GetModuleHandle("user32");
64 pBroadcastA = (PBROADCAST)GetProcAddress(user32, "BroadcastSystemMessageA");
65 if (!pBroadcastA)
66 pBroadcastA = (PBROADCAST)GetProcAddress(user32, "BroadcastSystemMessage");
67 ok(pBroadcastA != NULL, "No BroadcastSystemMessage found\n");
68 if (!pBroadcastA)
69 {
70 win_skip("BroadcastA is not available\n");
71 return FALSE;
72 }
73
74 pBroadcastW = (PBROADCAST)GetProcAddress(user32, "BroadcastSystemMessageW");
75 pBroadcastExA = (PBROADCASTEX)GetProcAddress(user32, "BroadcastSystemMessageExA");
76 pBroadcastExW = (PBROADCASTEX)GetProcAddress(user32, "BroadcastSystemMessageExW");
77
78 hevent = CreateEventA(NULL, TRUE, FALSE, "Asynchronous checking event");
79
80 cls.style = CS_DBLCLKS;
81 cls.lpfnWndProc = main_window_procA;
82 cls.cbClsExtra = 0;
83 cls.cbWndExtra = 0;
84 cls.hInstance = GetModuleHandleA(0);
85 cls.hIcon = 0;
86 cls.hCursor = LoadCursorA(0, IDC_ARROW);
87 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
88 cls.lpszMenuName = NULL;
89 cls.lpszClassName = "MainWindowClass";
90
91 if (!RegisterClassA(&cls))
92 return FALSE;
93
94 if (!CreateWindowExA(0, "MainWindowClass", "Main window", WS_CAPTION | WS_SYSMENU |
95 WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP, 100, 100, 200,
96 200, 0, 0, GetModuleHandle(0), NULL))
97 return FALSE;
98 return TRUE;
99 }
100
101 static void test_parameters(PBROADCAST broadcast, const char *functionname)
102 {
103 LONG ret;
104 DWORD recips;
105
106 SetLastError(0xcafebabe);
107 recips = BSM_APPLICATIONS;
108 ret = broadcast( 0x80000000, &recips, WM_NULL, 0, 0 );
109 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
110 {
111 win_skip("%s is not implemented\n", functionname);
112 return;
113 }
114 ok(!ret || broken(ret), "Returned: %d\n", ret);
115 if (!ret) ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error: %08x\n", GetLastError());
116
117 SetLastError(0xcafebabe);
118 recips = BSM_APPLICATIONS;
119 ret = broadcast( 0x80000000, &recips, WM_NULL, 0, 0 );
120 ok(!ret || broken(ret), "Returned: %d\n", ret);
121 if (!ret) ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error: %08x\n", GetLastError());
122
123 #if 0 /* TODO: Check the hang flags */
124 SetLastError(0xcafebabe);
125 recips = BSM_APPLICATIONS;
126 ret = broadcast( BSF_QUERY|(BSF_NOHANG|BSF_FORCEIFHUNG), &recips, WM_NULL, 30000, 0 );
127 ok(0, "Last error: %08x\n", GetLastError());
128 ok(0, "Returned: %d\n", ret);
129
130 SetLastError(0xcafebabe);
131 recips = BSM_APPLICATIONS;
132 ret = broadcast( BSF_QUERY|(BSF_NOHANG|BSF_NOTIMEOUTIFNOTHUNG), &recips, WM_NULL, 30000, 0 );
133 ok(0, "Last error: %08x\n", GetLastError());
134 ok(0, "Returned: %d\n", ret);
135
136 SetLastError(0xcafebabe);
137 recips = BSM_APPLICATIONS;
138 ret = broadcast( BSF_QUERY|(BSF_NOTIMEOUTIFNOTHUNG|BSF_FORCEIFHUNG), &recips, WM_NULL, 30000, 0 );
139 ok(0, "Last error: %08x\n", GetLastError());
140 ok(0, "Returned: %d\n", ret);
141
142 SetLastError(0xcafebabe);
143 recips = BSM_APPLICATIONS;
144 ret = broadcast( BSF_POSTMESSAGE|(BSF_NOTIMEOUTIFNOTHUNG|BSF_FORCEIFHUNG), &recips, WM_NULL, 30000, 0 );
145 ok(0, "Last error: %08x\n", GetLastError());
146 ok(0, "Returned: %d\n", ret);
147 #endif
148
149 recips = BSM_APPLICATIONS;
150 ResetEvent(hevent);
151 ret = broadcast( BSF_POSTMESSAGE|BSF_QUERY, &recips, WM_NULL, 100, 0 );
152 ok(ret==1, "Returned: %d\n", ret);
153 ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n");
154 PulseEvent(hevent);
155
156 SetLastError( 0xdeadbeef );
157 recips = BSM_APPLICATIONS;
158 ret = broadcast( BSF_POSTMESSAGE|BSF_SENDNOTIFYMESSAGE, &recips, WM_NULL, 100, 0 );
159 if (ret)
160 {
161 ok(ret==1, "Returned: %d\n", ret);
162 ok(WaitForSingleObject(hevent, 0) != WAIT_OBJECT_0, "Synchronous message sent instead\n");
163 PulseEvent(hevent);
164
165 recips = BSM_APPLICATIONS;
166 ret = broadcast( BSF_SENDNOTIFYMESSAGE, &recips, WM_NULL, 100, BROADCAST_QUERY_DENY );
167 ok(ret==1, "Returned: %d\n", ret);
168 ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n");
169 PulseEvent(hevent);
170
171 recips = BSM_APPLICATIONS;
172 ret = broadcast( BSF_SENDNOTIFYMESSAGE|BSF_QUERY, &recips, WM_NULL, 100, BROADCAST_QUERY_DENY );
173 ok(!ret, "Returned: %d\n", ret);
174 ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n");
175 PulseEvent(hevent);
176 }
177 else /* BSF_SENDNOTIFYMESSAGE not supported on NT4 */
178 ok( GetLastError() == ERROR_INVALID_PARAMETER, "failed with err %u\n", GetLastError() );
179
180 recips = BSM_APPLICATIONS;
181 ret = broadcast( 0, &recips, WM_NULL, 100, 0 );
182 ok(ret==1, "Returned: %d\n", ret);
183 ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n");
184 PulseEvent(hevent);
185 }
186
187 /* BSF_SENDNOTIFYMESSAGE and BSF_QUERY are both synchronous within the same process
188 * However you should be able to distinguish them by sending the BROADCAST_QUERY_DENY flag
189 */
190
191 static void test_parametersEx(PBROADCASTEX broadcastex)
192 {
193 LONG ret;
194 DWORD recips;
195
196 SetLastError(0xcafebabe);
197 recips = BSM_APPLICATIONS;
198 ret = broadcastex( 0x80000000, &recips, WM_NULL, 0, 0, NULL );
199 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error: %08x\n", GetLastError());
200 ok(!ret, "Returned: %d\n", ret);
201
202 SetLastError(0xcafebabe);
203 recips = BSM_APPLICATIONS;
204 ret = broadcastex( 0x80000000, &recips, WM_NULL, 0, 0, NULL );
205 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error: %08x\n", GetLastError());
206 ok(!ret, "Returned: %d\n", ret);
207
208 #if 0 /* TODO: Check the hang flags */
209 SetLastError(0xcafebabe);
210 recips = BSM_APPLICATIONS;
211 ret = broadcast( BSF_QUERY|(BSF_NOHANG|BSF_FORCEIFHUNG), &recips, WM_NULL, 30000, 0, NULL );
212 ok(0, "Last error: %08x\n", GetLastError());
213 ok(0, "Returned: %d\n", ret);
214
215 SetLastError(0xcafebabe);
216 recips = BSM_APPLICATIONS;
217 ret = broadcast( BSF_QUERY|(BSF_NOHANG|BSF_NOTIMEOUTIFNOTHUNG), &recips, WM_NULL, 30000, 0, NULL );
218 ok(0, "Last error: %08x\n", GetLastError());
219 ok(0, "Returned: %d\n", ret);
220
221 SetLastError(0xcafebabe);
222 recips = BSM_APPLICATIONS;
223 ret = broadcast( BSF_QUERY|(BSF_NOTIMEOUTIFNOTHUNG|BSF_FORCEIFHUNG), &recips, WM_NULL, 30000, 0, NULL );
224 ok(0, "Last error: %08x\n", GetLastError());
225 ok(0, "Returned: %d\n", ret);
226
227 SetLastError(0xcafebabe);
228 recips = BSM_APPLICATIONS;
229 ret = broadcast( BSF_POSTMESSAGE|(BSF_NOTIMEOUTIFNOTHUNG|BSF_FORCEIFHUNG), &recips, WM_NULL, 30000, 0, NULL );
230 ok(0, "Last error: %08x\n", GetLastError());
231 ok(0, "Returned: %d\n", ret);
232 #endif
233
234 recips = BSM_APPLICATIONS;
235 ResetEvent(hevent);
236 ret = broadcastex( BSF_POSTMESSAGE|BSF_QUERY, &recips, WM_NULL, 100, 0, NULL );
237 ok(ret==1, "Returned: %d\n", ret);
238 ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n");
239 PulseEvent(hevent);
240
241 recips = BSM_APPLICATIONS;
242 ret = broadcastex( BSF_POSTMESSAGE|BSF_SENDNOTIFYMESSAGE, &recips, WM_NULL, 100, 0, NULL );
243 ok(ret==1, "Returned: %d\n", ret);
244 ok(WaitForSingleObject(hevent, 0) != WAIT_OBJECT_0, "Synchronous message sent instead\n");
245 PulseEvent(hevent);
246
247 recips = BSM_APPLICATIONS;
248 ret = broadcastex( BSF_SENDNOTIFYMESSAGE, &recips, WM_NULL, 100, BROADCAST_QUERY_DENY, NULL );
249 ok(ret==1, "Returned: %d\n", ret);
250 ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n");
251 PulseEvent(hevent);
252
253 recips = BSM_APPLICATIONS;
254 ret = broadcastex( BSF_SENDNOTIFYMESSAGE|BSF_QUERY, &recips, WM_NULL, 100, BROADCAST_QUERY_DENY, NULL );
255 ok(!ret, "Returned: %d\n", ret);
256 ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n");
257 PulseEvent(hevent);
258
259 recips = BSM_APPLICATIONS;
260 ret = broadcastex( 0, &recips, WM_NULL, 100, 0, NULL );
261 ok(ret==1, "Returned: %d\n", ret);
262 ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n");
263 PulseEvent(hevent);
264 }
265
266 static BOOL (WINAPI *pOpenProcessToken)(HANDLE, DWORD, HANDLE*);
267 static BOOL (WINAPI *pAdjustTokenPrivileges)(HANDLE, BOOL, PTOKEN_PRIVILEGES, DWORD, PTOKEN_PRIVILEGES, PDWORD);
268
269 static void test_noprivileges(void)
270 {
271 HANDLE advapi32 = GetModuleHandleA("advapi32");
272 HANDLE token;
273 DWORD recips;
274 BOOL ret;
275
276 static const DWORD BSM_ALL_RECIPS = BSM_VXDS | BSM_NETDRIVER |
277 BSM_INSTALLABLEDRIVERS | BSM_APPLICATIONS;
278
279 pOpenProcessToken = (void *)GetProcAddress(advapi32, "OpenProcessToken");
280 pAdjustTokenPrivileges = (void *)GetProcAddress(advapi32, "AdjustTokenPrivileges");
281 if (!pOpenProcessToken || !pAdjustTokenPrivileges || !pOpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token))
282 {
283 skip("Can't open security token for process\n");
284 return;
285 }
286 if (!pAdjustTokenPrivileges(token, TRUE, NULL, 0, NULL, NULL))
287 {
288 skip("Can't adjust security token for process\n");
289 return;
290 }
291
292 trace("Trying privileged edition!\n");
293 SetLastError(0xcafebabe);
294 recips = BSM_ALLDESKTOPS;
295 ResetEvent(hevent);
296 ret = pBroadcastExW( BSF_QUERY, &recips, WM_NULL, 100, 0, NULL );
297 ok(ret==1, "Returned: %d error %u\n", ret, GetLastError());
298 ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n");
299 ok(recips == BSM_ALLDESKTOPS ||
300 recips == BSM_ALL_RECIPS, /* win2k3 */
301 "Received by: %08x\n", recips);
302 PulseEvent(hevent);
303
304 SetLastError(0xcafebabe);
305 recips = BSM_ALLCOMPONENTS;
306 ResetEvent(hevent);
307 ret = pBroadcastExW( BSF_QUERY, &recips, WM_NULL, 100, 0, NULL );
308 ok(ret==1, "Returned: %d error %u\n", ret, GetLastError());
309 ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n");
310 ok(recips == BSM_ALLCOMPONENTS ||
311 recips == BSM_ALL_RECIPS, /* win2k3 */
312 "Received by: %08x\n", recips);
313 PulseEvent(hevent);
314
315 SetLastError(0xcafebabe);
316 recips = BSM_ALLDESKTOPS|BSM_APPLICATIONS;
317 ResetEvent(hevent);
318 ret = pBroadcastExW( BSF_QUERY, &recips, WM_NULL, 100, 0, NULL );
319 ok(ret==1, "Returned: %d error %u\n", ret, GetLastError());
320 ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n");
321 ok(recips == (BSM_ALLDESKTOPS|BSM_APPLICATIONS) ||
322 recips == BSM_APPLICATIONS, /* win2k3 */
323 "Received by: %08x\n", recips);
324 PulseEvent(hevent);
325
326 SetLastError(0xcafebabe);
327 recips = BSM_ALLDESKTOPS|BSM_APPLICATIONS;
328 ResetEvent(hevent);
329 ret = pBroadcastExW( BSF_QUERY, &recips, WM_NULL, 100, BROADCAST_QUERY_DENY, NULL );
330 ok(!ret, "Returned: %d\n", ret);
331 ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n");
332 ok(recips == (BSM_ALLDESKTOPS|BSM_APPLICATIONS) ||
333 recips == BSM_APPLICATIONS, /* win2k3 */
334 "Received by: %08x\n", recips);
335 PulseEvent(hevent);
336 }
337
338 START_TEST(broadcast)
339 {
340 if (!init_procs())
341 return;
342
343 trace("Running BroadcastSystemMessageA tests\n");
344 test_parameters(pBroadcastA, "BroadcastSystemMessageA");
345 if (pBroadcastW)
346 {
347 trace("Running BroadcastSystemMessageW tests\n");
348 test_parameters(pBroadcastW, "BroadcastSystemMessageW");
349 }
350 else
351 win_skip("No BroadcastSystemMessageW, skipping\n");
352 if (pBroadcastExA)
353 {
354 trace("Running BroadcastSystemMessageExA tests\n");
355 test_parametersEx(pBroadcastExA);
356 }
357 else
358 win_skip("No BroadcastSystemMessageExA, skipping\n");
359 if (pBroadcastExW)
360 {
361 trace("Running BroadcastSystemMessageExW tests\n");
362 test_parametersEx(pBroadcastExW);
363 trace("Attempting privileges checking tests\n");
364 test_noprivileges();
365 }
366 else
367 win_skip("No BroadcastSystemMessageExW, skipping\n");
368 }