winex11: add owned windows to taskbar if owner is not mapped
[wine] / dlls / user32 / tests / 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 #include <assert.h>
22 #include <stdarg.h>
23 #include <stdio.h>
24
25 #define _WIN32_WINNT 0x0501
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         return FALSE;
70
71     pBroadcastW = (PBROADCAST)GetProcAddress(user32, "BroadcastSystemMessageW");
72     pBroadcastExA = (PBROADCASTEX)GetProcAddress(user32, "BroadcastSystemMessageExA");
73     pBroadcastExW = (PBROADCASTEX)GetProcAddress(user32, "BroadcastSystemMessageExW");
74
75     hevent = CreateEventA(NULL, TRUE, FALSE, "Asynchronous checking event");
76
77     cls.style = CS_DBLCLKS;
78     cls.lpfnWndProc = main_window_procA;
79     cls.cbClsExtra = 0;
80     cls.cbWndExtra = 0;
81     cls.hInstance = GetModuleHandleA(0);
82     cls.hIcon = 0;
83     cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
84     cls.hbrBackground = GetStockObject(WHITE_BRUSH);
85     cls.lpszMenuName = NULL;
86     cls.lpszClassName = "MainWindowClass";
87
88     if (!RegisterClassA(&cls))
89         return 0;
90
91     if (!CreateWindowExA(0, "MainWindowClass", "Main window", WS_CAPTION | WS_SYSMENU |
92                                WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP, 100, 100, 200,
93                                200, 0, 0, GetModuleHandle(0), NULL))
94         return FALSE;
95     return TRUE;
96 }
97
98 static void test_parameters(PBROADCAST broadcast)
99 {
100     LONG ret;
101     DWORD recips;
102
103     SetLastError(0xcafebabe);
104     recips = BSM_APPLICATIONS;
105     ret = broadcast( 0x80000000, &recips, WM_NULL, 0, 0 );
106     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error: %08x\n", GetLastError());
107     ok(!ret, "Returned: %d\n", ret);
108
109     SetLastError(0xcafebabe);
110     recips = BSM_APPLICATIONS;
111     ret = broadcast( 0x80000000, &recips, WM_NULL, 0, 0 );
112     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error: %08x\n", GetLastError());
113     ok(!ret, "Returned: %d\n", ret);
114
115 #if 0 /* TODO: Check the hang flags */
116     SetLastError(0xcafebabe);
117     recips = BSM_APPLICATIONS;
118     ret = broadcast( BSF_QUERY|(BSF_NOHANG|BSF_FORCEIFHUNG), &recips, WM_NULL, 30000, 0 );
119     ok(0, "Last error: %08x\n", GetLastError());
120     ok(0, "Returned: %d\n", ret);
121
122     SetLastError(0xcafebabe);
123     recips = BSM_APPLICATIONS;
124     ret = broadcast( BSF_QUERY|(BSF_NOHANG|BSF_NOTIMEOUTIFNOTHUNG), &recips, WM_NULL, 30000, 0 );
125     ok(0, "Last error: %08x\n", GetLastError());
126     ok(0, "Returned: %d\n", ret);
127
128     SetLastError(0xcafebabe);
129     recips = BSM_APPLICATIONS;
130     ret = broadcast( BSF_QUERY|(BSF_NOTIMEOUTIFNOTHUNG|BSF_FORCEIFHUNG), &recips, WM_NULL, 30000, 0 );
131     ok(0, "Last error: %08x\n", GetLastError());
132     ok(0, "Returned: %d\n", ret);
133
134     SetLastError(0xcafebabe);
135     recips = BSM_APPLICATIONS;
136     ret = broadcast( BSF_POSTMESSAGE|(BSF_NOTIMEOUTIFNOTHUNG|BSF_FORCEIFHUNG), &recips, WM_NULL, 30000, 0 );
137     ok(0, "Last error: %08x\n", GetLastError());
138     ok(0, "Returned: %d\n", ret);
139 #endif
140
141     recips = BSM_APPLICATIONS;
142     ResetEvent(hevent);
143     ret = broadcast( BSF_POSTMESSAGE|BSF_QUERY, &recips, WM_NULL, 100, 0 );
144     ok(ret==1, "Returned: %d\n", ret);
145     ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n");
146     PulseEvent(hevent);
147
148     recips = BSM_APPLICATIONS;
149     ret = broadcast( BSF_POSTMESSAGE|BSF_SENDNOTIFYMESSAGE, &recips, WM_NULL, 100, 0 );
150     ok(ret==1, "Returned: %d\n", ret);
151     ok(WaitForSingleObject(hevent, 0) != WAIT_OBJECT_0, "Synchronous message sent instead\n");
152     PulseEvent(hevent);
153
154     recips = BSM_APPLICATIONS;
155     ret = broadcast( BSF_SENDNOTIFYMESSAGE, &recips, WM_NULL, 100, BROADCAST_QUERY_DENY );
156     ok(ret==1, "Returned: %d\n", ret);
157     ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n");
158     PulseEvent(hevent);
159
160     recips = BSM_APPLICATIONS;
161     ret = broadcast( BSF_SENDNOTIFYMESSAGE|BSF_QUERY, &recips, WM_NULL, 100, BROADCAST_QUERY_DENY );
162     ok(!ret, "Returned: %d\n", ret);
163     ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n");
164     PulseEvent(hevent);
165
166     recips = BSM_APPLICATIONS;
167     ret = broadcast( 0, &recips, WM_NULL, 100, 0 );
168     ok(ret==1, "Returned: %d\n", ret);
169     ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n");
170     PulseEvent(hevent);
171 }
172
173 /* BSF_SENDNOTIFYMESSAGE and BSF_QUERY are both synchronous within the same process
174  * However you should be able to distinguish them by sending the BROADCAST_QUERY_DENY flag
175  */
176
177 static void test_parametersEx(PBROADCASTEX broadcastex)
178 {
179     LONG ret;
180     DWORD recips;
181
182     SetLastError(0xcafebabe);
183     recips = BSM_APPLICATIONS;
184     ret = broadcastex( 0x80000000, &recips, WM_NULL, 0, 0, NULL );
185     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error: %08x\n", GetLastError());
186     ok(!ret, "Returned: %d\n", ret);
187
188     SetLastError(0xcafebabe);
189     recips = BSM_APPLICATIONS;
190     ret = broadcastex( 0x80000000, &recips, WM_NULL, 0, 0, NULL );
191     ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error: %08x\n", GetLastError());
192     ok(!ret, "Returned: %d\n", ret);
193
194 #if 0 /* TODO: Check the hang flags */
195     SetLastError(0xcafebabe);
196     recips = BSM_APPLICATIONS;
197     ret = broadcast( BSF_QUERY|(BSF_NOHANG|BSF_FORCEIFHUNG), &recips, WM_NULL, 30000, 0, NULL );
198     ok(0, "Last error: %08x\n", GetLastError());
199     ok(0, "Returned: %d\n", ret);
200
201     SetLastError(0xcafebabe);
202     recips = BSM_APPLICATIONS;
203     ret = broadcast( BSF_QUERY|(BSF_NOHANG|BSF_NOTIMEOUTIFNOTHUNG), &recips, WM_NULL, 30000, 0, NULL );
204     ok(0, "Last error: %08x\n", GetLastError());
205     ok(0, "Returned: %d\n", ret);
206
207     SetLastError(0xcafebabe);
208     recips = BSM_APPLICATIONS;
209     ret = broadcast( BSF_QUERY|(BSF_NOTIMEOUTIFNOTHUNG|BSF_FORCEIFHUNG), &recips, WM_NULL, 30000, 0, NULL );
210     ok(0, "Last error: %08x\n", GetLastError());
211     ok(0, "Returned: %d\n", ret);
212
213     SetLastError(0xcafebabe);
214     recips = BSM_APPLICATIONS;
215     ret = broadcast( BSF_POSTMESSAGE|(BSF_NOTIMEOUTIFNOTHUNG|BSF_FORCEIFHUNG), &recips, WM_NULL, 30000, 0, NULL );
216     ok(0, "Last error: %08x\n", GetLastError());
217     ok(0, "Returned: %d\n", ret);
218 #endif
219
220     recips = BSM_APPLICATIONS;
221     ResetEvent(hevent);
222     ret = broadcastex( BSF_POSTMESSAGE|BSF_QUERY, &recips, WM_NULL, 100, 0, NULL );
223     ok(ret==1, "Returned: %d\n", ret);
224     ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n");
225     PulseEvent(hevent);
226
227     recips = BSM_APPLICATIONS;
228     ret = broadcastex( BSF_POSTMESSAGE|BSF_SENDNOTIFYMESSAGE, &recips, WM_NULL, 100, 0, NULL );
229     ok(ret==1, "Returned: %d\n", ret);
230     ok(WaitForSingleObject(hevent, 0) != WAIT_OBJECT_0, "Synchronous message sent instead\n");
231     PulseEvent(hevent);
232
233     recips = BSM_APPLICATIONS;
234     ret = broadcastex( BSF_SENDNOTIFYMESSAGE, &recips, WM_NULL, 100, BROADCAST_QUERY_DENY, NULL );
235     ok(ret==1, "Returned: %d\n", ret);
236     ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n");
237     PulseEvent(hevent);
238
239     recips = BSM_APPLICATIONS;
240     ret = broadcastex( BSF_SENDNOTIFYMESSAGE|BSF_QUERY, &recips, WM_NULL, 100, BROADCAST_QUERY_DENY, NULL );
241     ok(!ret, "Returned: %d\n", ret);
242     ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n");
243     PulseEvent(hevent);
244
245     recips = BSM_APPLICATIONS;
246     ret = broadcastex( 0, &recips, WM_NULL, 100, 0, NULL );
247     ok(ret==1, "Returned: %d\n", ret);
248     ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n");
249     PulseEvent(hevent);
250 }
251
252 static BOOL WINAPI (*pOpenProcessToken)(HANDLE, DWORD, HANDLE*);
253 static BOOL WINAPI (*pAdjustTokenPrivileges)(HANDLE, BOOL, PTOKEN_PRIVILEGES, DWORD, PTOKEN_PRIVILEGES, PDWORD);
254
255 static void test_noprivileges(void)
256 {
257     HANDLE advapi32 = GetModuleHandleA("advapi32");
258     HANDLE token;
259     DWORD recips;
260     BOOL ret;
261
262     pOpenProcessToken = (void *)GetProcAddress(advapi32, "OpenProcessToken");
263     pAdjustTokenPrivileges = (void *)GetProcAddress(advapi32, "AdjustTokenPrivileges");
264     if (!pOpenProcessToken || !pAdjustTokenPrivileges || !pOpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token))
265     {
266         skip("Can't open security token for process\n");
267         return;
268     }
269     if (!pAdjustTokenPrivileges(token, TRUE, NULL, 0, NULL, NULL))
270     {
271         skip("Can't adjust security token for process\n");
272         return;
273     }
274
275     trace("Trying privileged edition!\n");
276     SetLastError(0xcafebabe);
277     recips = BSM_ALLDESKTOPS;
278     ResetEvent(hevent);
279     ret = pBroadcastExW( BSF_QUERY, &recips, WM_NULL, 100, 0, NULL );
280     todo_wine ok(GetLastError() == ERROR_PRIVILEGE_NOT_HELD, "Last error: %08x\n", GetLastError());
281     ok(ret==1, "Returned: %d\n", ret);
282     ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n");
283     ok(recips == BSM_ALLDESKTOPS, "Received by: %08x\n", recips);
284     PulseEvent(hevent);
285
286     /* Wine sets last error to 0, so just use that one as token here so it doesn't fail */
287     SetLastError(0);
288     recips = BSM_ALLCOMPONENTS;
289     ResetEvent(hevent);
290     ret = pBroadcastExW( BSF_QUERY, &recips, WM_NULL, 100, 0, NULL );
291     ok(!GetLastError(), "Last error: %08x\n", GetLastError());
292     ok(ret==1, "Returned: %d\n", ret);
293     ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n");
294     ok(recips == BSM_ALLCOMPONENTS, "Received by: %08x\n", recips);
295     PulseEvent(hevent);
296
297     SetLastError(0xcafebabe);
298     recips = BSM_ALLDESKTOPS|BSM_APPLICATIONS;
299     ResetEvent(hevent);
300     ret = pBroadcastExW( BSF_QUERY, &recips, WM_NULL, 100, 0, NULL );
301     todo_wine ok(GetLastError() == ERROR_PRIVILEGE_NOT_HELD, "Last error: %08x\n", GetLastError());
302     ok(ret==1, "Returned: %d\n", ret);
303     ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n");
304     ok(recips == (BSM_ALLDESKTOPS|BSM_APPLICATIONS), "Received by: %08x\n", recips);
305     PulseEvent(hevent);
306
307     SetLastError(0xcafebabe);
308     recips = BSM_ALLDESKTOPS|BSM_APPLICATIONS;
309     ResetEvent(hevent);
310     ret = pBroadcastExW( BSF_QUERY, &recips, WM_NULL, 100, BROADCAST_QUERY_DENY, NULL );
311     todo_wine ok(GetLastError() == ERROR_PRIVILEGE_NOT_HELD, "Last error: %08x\n", GetLastError());
312     ok(!ret, "Returned: %d\n", ret);
313     ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n");
314     ok(recips == (BSM_ALLDESKTOPS|BSM_APPLICATIONS), "Received by: %08x\n", recips);
315     PulseEvent(hevent);
316 }
317
318 START_TEST(broadcast)
319 {
320     if (!init_procs())
321         return;
322
323     trace("Running BroadcastSystemMessageA tests\n");
324     test_parameters(pBroadcastA);
325     if (pBroadcastW)
326     {
327         trace("Running BroadcastSystemMessageW tests\n");
328         test_parameters(pBroadcastW);
329     }
330     else
331         skip("No BroadcastSystemMessageW, skipping\n");
332     if (pBroadcastExA)
333     {
334         trace("Running BroadcastSystemMessageExA tests\n");
335         test_parametersEx(pBroadcastExA);
336     }
337     else
338         skip("No BroadcastSystemMessageExA, skipping\n");
339     if (pBroadcastExW)
340     {
341         trace("Running BroadcastSystemMessageExW tests\n");
342         test_parametersEx(pBroadcastExW);
343         trace("Attempting privileges checking tests\n");
344         test_noprivileges();
345     }
346     else
347         skip("No BroadcastSystemMessageExW, skipping\n");
348 }