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 recips = BSM_APPLICATIONS; 134 ResetEvent(hevent); 135 ret = broadcast( BSF_POSTMESSAGE|BSF_QUERY, &recips, WM_NULL, 100, 0 ); 136 ok(ret==1, "Returned: %d\n", ret); 137 ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n"); 138 PulseEvent(hevent); 139 140 SetLastError( 0xdeadbeef ); 141 recips = BSM_APPLICATIONS; 142 ret = broadcast( BSF_POSTMESSAGE|BSF_SENDNOTIFYMESSAGE, &recips, WM_NULL, 100, 0 ); 143 if (ret) 144 { 145 ok(ret==1, "Returned: %d\n", ret); 146 ok(WaitForSingleObject(hevent, 0) != WAIT_OBJECT_0, "Synchronous message sent instead\n"); 147 PulseEvent(hevent); 148 149 recips = BSM_APPLICATIONS; 150 ret = broadcast( BSF_SENDNOTIFYMESSAGE, &recips, WM_NULL, 100, BROADCAST_QUERY_DENY ); 151 ok(ret==1, "Returned: %d\n", ret); 152 ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n"); 153 PulseEvent(hevent); 154 155 recips = BSM_APPLICATIONS; 156 ret = broadcast( BSF_SENDNOTIFYMESSAGE|BSF_QUERY, &recips, WM_NULL, 100, BROADCAST_QUERY_DENY ); 157 ok(!ret, "Returned: %d\n", ret); 158 ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n"); 159 PulseEvent(hevent); 160 } 161 else /* BSF_SENDNOTIFYMESSAGE not supported on NT4 */ 162 ok( GetLastError() == ERROR_INVALID_PARAMETER, "failed with err %u\n", GetLastError() ); 163 164 recips = BSM_APPLICATIONS; 165 ret = broadcast( 0, &recips, WM_NULL, 100, 0 ); 166 ok(ret==1, "Returned: %d\n", ret); 167 ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n"); 168 PulseEvent(hevent); 169 } 170 171 /* BSF_SENDNOTIFYMESSAGE and BSF_QUERY are both synchronous within the same process 172 * However you should be able to distinguish them by sending the BROADCAST_QUERY_DENY flag 173 */ 174 175 static void test_parametersEx(PBROADCASTEX broadcastex) 176 { 177 LONG ret; 178 DWORD recips; 179 180 SetLastError(0xcafebabe); 181 recips = BSM_APPLICATIONS; 182 ret = broadcastex( 0x80000000, &recips, WM_NULL, 0, 0, NULL ); 183 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error: %08x\n", GetLastError()); 184 ok(!ret, "Returned: %d\n", ret); 185 186 SetLastError(0xcafebabe); 187 recips = BSM_APPLICATIONS; 188 ret = broadcastex( 0x80000000, &recips, WM_NULL, 0, 0, NULL ); 189 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error: %08x\n", GetLastError()); 190 ok(!ret, "Returned: %d\n", ret); 191 192 if (0) /* TODO: Check the hang flags */ 193 { 194 SetLastError(0xcafebabe); 195 recips = BSM_APPLICATIONS; 196 ret = broadcastex( BSF_QUERY|(BSF_NOHANG|BSF_FORCEIFHUNG), &recips, WM_NULL, 30000, 0, NULL ); 197 ok(0, "Last error: %08x\n", GetLastError()); 198 ok(0, "Returned: %d\n", ret); 199 200 SetLastError(0xcafebabe); 201 recips = BSM_APPLICATIONS; 202 ret = broadcastex( BSF_QUERY|(BSF_NOHANG|BSF_NOTIMEOUTIFNOTHUNG), &recips, WM_NULL, 30000, 0, NULL ); 203 ok(0, "Last error: %08x\n", GetLastError()); 204 ok(0, "Returned: %d\n", ret); 205 206 SetLastError(0xcafebabe); 207 recips = BSM_APPLICATIONS; 208 ret = broadcastex( BSF_QUERY|(BSF_NOTIMEOUTIFNOTHUNG|BSF_FORCEIFHUNG), &recips, WM_NULL, 30000, 0, NULL ); 209 ok(0, "Last error: %08x\n", GetLastError()); 210 ok(0, "Returned: %d\n", ret); 211 212 SetLastError(0xcafebabe); 213 recips = BSM_APPLICATIONS; 214 ret = broadcastex( BSF_POSTMESSAGE|(BSF_NOTIMEOUTIFNOTHUNG|BSF_FORCEIFHUNG), &recips, WM_NULL, 30000, 0, NULL ); 215 ok(0, "Last error: %08x\n", GetLastError()); 216 ok(0, "Returned: %d\n", ret); 217 } 218 219 recips = BSM_APPLICATIONS; 220 ResetEvent(hevent); 221 ret = broadcastex( BSF_POSTMESSAGE|BSF_QUERY, &recips, WM_NULL, 100, 0, NULL ); 222 ok(ret==1, "Returned: %d\n", ret); 223 ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n"); 224 PulseEvent(hevent); 225 226 recips = BSM_APPLICATIONS; 227 ret = broadcastex( BSF_POSTMESSAGE|BSF_SENDNOTIFYMESSAGE, &recips, WM_NULL, 100, 0, NULL ); 228 ok(ret==1, "Returned: %d\n", ret); 229 ok(WaitForSingleObject(hevent, 0) != WAIT_OBJECT_0, "Synchronous message sent instead\n"); 230 PulseEvent(hevent); 231 232 recips = BSM_APPLICATIONS; 233 ret = broadcastex( BSF_SENDNOTIFYMESSAGE, &recips, WM_NULL, 100, BROADCAST_QUERY_DENY, NULL ); 234 ok(ret==1, "Returned: %d\n", ret); 235 ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n"); 236 PulseEvent(hevent); 237 238 recips = BSM_APPLICATIONS; 239 ret = broadcastex( BSF_SENDNOTIFYMESSAGE|BSF_QUERY, &recips, WM_NULL, 100, BROADCAST_QUERY_DENY, NULL ); 240 ok(!ret, "Returned: %d\n", ret); 241 ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n"); 242 PulseEvent(hevent); 243 244 recips = BSM_APPLICATIONS; 245 ret = broadcastex( 0, &recips, WM_NULL, 100, 0, NULL ); 246 ok(ret==1, "Returned: %d\n", ret); 247 ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n"); 248 PulseEvent(hevent); 249 } 250 251 static void test_noprivileges(void) 252 { 253 HANDLE token; 254 DWORD recips; 255 BOOL ret; 256 257 static const DWORD BSM_ALL_RECIPS = BSM_VXDS | BSM_NETDRIVER | 258 BSM_INSTALLABLEDRIVERS | BSM_APPLICATIONS; 259 260 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token)) 261 { 262 skip("Can't open security token for process\n"); 263 return; 264 } 265 if (!AdjustTokenPrivileges(token, TRUE, NULL, 0, NULL, NULL)) 266 { 267 skip("Can't adjust security token for process\n"); 268 return; 269 } 270 271 trace("Trying privileged edition!\n"); 272 SetLastError(0xcafebabe); 273 recips = BSM_ALLDESKTOPS; 274 ResetEvent(hevent); 275 ret = BroadcastSystemMessageExW( BSF_QUERY, &recips, WM_NULL, 100, 0, NULL ); 276 ok(ret==1, "Returned: %d error %u\n", ret, GetLastError()); 277 ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n"); 278 ok(recips == BSM_ALLDESKTOPS || 279 recips == BSM_ALL_RECIPS, /* win2k3 */ 280 "Received by: %08x\n", recips); 281 PulseEvent(hevent); 282 283 SetLastError(0xcafebabe); 284 recips = BSM_ALLCOMPONENTS; 285 ResetEvent(hevent); 286 ret = BroadcastSystemMessageExW( BSF_QUERY, &recips, WM_NULL, 100, 0, NULL ); 287 ok(ret==1, "Returned: %d error %u\n", ret, GetLastError()); 288 ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n"); 289 ok(recips == BSM_ALLCOMPONENTS || 290 recips == BSM_ALL_RECIPS, /* win2k3 */ 291 "Received by: %08x\n", recips); 292 PulseEvent(hevent); 293 294 SetLastError(0xcafebabe); 295 recips = BSM_ALLDESKTOPS|BSM_APPLICATIONS; 296 ResetEvent(hevent); 297 ret = BroadcastSystemMessageExW( BSF_QUERY, &recips, WM_NULL, 100, 0, NULL ); 298 ok(ret==1, "Returned: %d error %u\n", ret, GetLastError()); 299 ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n"); 300 ok(recips == (BSM_ALLDESKTOPS|BSM_APPLICATIONS) || 301 recips == BSM_APPLICATIONS, /* win2k3 */ 302 "Received by: %08x\n", recips); 303 PulseEvent(hevent); 304 305 SetLastError(0xcafebabe); 306 recips = BSM_ALLDESKTOPS|BSM_APPLICATIONS; 307 ResetEvent(hevent); 308 ret = BroadcastSystemMessageExW( BSF_QUERY, &recips, WM_NULL, 100, BROADCAST_QUERY_DENY, NULL ); 309 ok(!ret, "Returned: %d\n", ret); 310 ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n"); 311 ok(recips == (BSM_ALLDESKTOPS|BSM_APPLICATIONS) || 312 recips == BSM_APPLICATIONS, /* win2k3 */ 313 "Received by: %08x\n", recips); 314 PulseEvent(hevent); 315 } 316 317 START_TEST(broadcast) 318 { 319 if (!init_procs()) 320 return; 321 322 trace("Running BroadcastSystemMessageA tests\n"); 323 test_parameters(BroadcastSystemMessageA, "BroadcastSystemMessageA"); 324 325 trace("Running BroadcastSystemMessageW tests\n"); 326 test_parameters(BroadcastSystemMessageW, "BroadcastSystemMessageW"); 327 328 trace("Running BroadcastSystemMessageExA tests\n"); 329 test_parametersEx(BroadcastSystemMessageExA); 330 331 trace("Running BroadcastSystemMessageExW tests\n"); 332 test_parametersEx(BroadcastSystemMessageExW); 333 334 trace("Attempting privileges checking tests\n"); 335 test_noprivileges(); 336 } 337