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