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 <stdarg.h> 22 #include <stdio.h> 23 24 #include "windef.h" 25 #include "winbase.h" 26 #include "wingdi.h" 27 #include "winuser.h" 28 #include "winnls.h" 29 30 #include "wine/test.h" 31 32 typedef LONG (WINAPI *PBROADCAST)( DWORD,LPDWORD,UINT,WPARAM,LPARAM ); 33 typedef LONG (WINAPI *PBROADCASTEX)( DWORD,LPDWORD,UINT,WPARAM,LPARAM,PBSMINFO ); 34 static HANDLE hevent; 35 36 static LRESULT WINAPI main_window_procA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) 37 { 38 if (msg == WM_NULL) 39 { 40 trace("main_window_procA: Sleeping for %lu ms\n", wparam); 41 if (wparam) 42 { 43 if (WaitForSingleObject(hevent, wparam) == WAIT_TIMEOUT) 44 SetEvent(hevent); 45 } 46 trace("main_window_procA: Returning WM_NULL with parameter %08lx\n", lparam); 47 return lparam; 48 } 49 50 return DefWindowProcA(hwnd, msg, wparam, lparam); 51 } 52 53 static BOOL init_procs(void) 54 { 55 WNDCLASSA cls; 56 57 hevent = CreateEventA(NULL, TRUE, FALSE, "Asynchronous checking event"); 58 59 cls.style = CS_DBLCLKS; 60 cls.lpfnWndProc = main_window_procA; 61 cls.cbClsExtra = 0; 62 cls.cbWndExtra = 0; 63 cls.hInstance = GetModuleHandleA(0); 64 cls.hIcon = 0; 65 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW); 66 cls.hbrBackground = GetStockObject(WHITE_BRUSH); 67 cls.lpszMenuName = NULL; 68 cls.lpszClassName = "MainWindowClass"; 69 70 if (!RegisterClassA(&cls)) 71 return FALSE; 72 73 if (!CreateWindowExA(0, "MainWindowClass", "Main window", WS_CAPTION | WS_SYSMENU | 74 WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP, 100, 100, 200, 75 200, 0, 0, GetModuleHandleA(NULL), NULL)) 76 return FALSE; 77 return TRUE; 78 } 79 80 static void test_parameters(PBROADCAST broadcast, const char *functionname) 81 { 82 LONG ret; 83 DWORD recips; 84 85 SetLastError(0xcafebabe); 86 recips = BSM_APPLICATIONS; 87 ret = broadcast( 0x80000000, &recips, WM_NULL, 0, 0 ); 88 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) 89 { 90 win_skip("%s is not implemented\n", functionname); 91 return; 92 } 93 ok(!ret || broken(ret), "Returned: %d\n", ret); 94 if (!ret) ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error: %08x\n", GetLastError()); 95 96 SetLastError(0xcafebabe); 97 recips = BSM_APPLICATIONS; 98 ret = broadcast( 0x80000000, &recips, WM_NULL, 0, 0 ); 99 ok(!ret || broken(ret), "Returned: %d\n", ret); 100 if (!ret) ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error: %08x\n", GetLastError()); 101 102 if (0) /* TODO: Check the hang flags */ 103 { 104 SetLastError(0xcafebabe); 105 recips = BSM_APPLICATIONS; 106 ret = broadcast( BSF_QUERY|(BSF_NOHANG|BSF_FORCEIFHUNG), &recips, WM_NULL, 30000, 0 ); 107 ok(0, "Last error: %08x\n", GetLastError()); 108 ok(0, "Returned: %d\n", ret); 109 110 SetLastError(0xcafebabe); 111 recips = BSM_APPLICATIONS; 112 ret = broadcast( BSF_QUERY|(BSF_NOHANG|BSF_NOTIMEOUTIFNOTHUNG), &recips, WM_NULL, 30000, 0 ); 113 ok(0, "Last error: %08x\n", GetLastError()); 114 ok(0, "Returned: %d\n", ret); 115 116 SetLastError(0xcafebabe); 117 recips = BSM_APPLICATIONS; 118 ret = broadcast( BSF_QUERY|(BSF_NOTIMEOUTIFNOTHUNG|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_POSTMESSAGE|(BSF_NOTIMEOUTIFNOTHUNG|BSF_FORCEIFHUNG), &recips, WM_NULL, 30000, 0 ); 125 ok(0, "Last error: %08x\n", GetLastError()); 126 ok(0, "Returned: %d\n", ret); 127 } 128 129 SetLastError( 0xdeadbeef ); 130 recips = BSM_APPLICATIONS; 131 ret = broadcast( BSF_POSTMESSAGE|BSF_SENDNOTIFYMESSAGE, &recips, WM_NULL, 100, 0 ); 132 ok(ret==1, "Returned: %d\n", ret); 133 ok(WaitForSingleObject(hevent, 0) != WAIT_OBJECT_0, "Synchronous message sent instead\n"); 134 PulseEvent(hevent); 135 136 recips = BSM_APPLICATIONS; 137 ret = broadcast( BSF_SENDNOTIFYMESSAGE, &recips, WM_NULL, 100, BROADCAST_QUERY_DENY ); 138 ok(ret==1, "Returned: %d\n", ret); 139 ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n"); 140 PulseEvent(hevent); 141 } 142 143 /* BSF_SENDNOTIFYMESSAGE and BSF_QUERY are both synchronous within the same process 144 * However you should be able to distinguish them by sending the BROADCAST_QUERY_DENY flag 145 */ 146 147 static void test_parametersEx(PBROADCASTEX broadcastex) 148 { 149 LONG ret; 150 DWORD recips; 151 152 SetLastError(0xcafebabe); 153 recips = BSM_APPLICATIONS; 154 ret = broadcastex( 0x80000000, &recips, WM_NULL, 0, 0, NULL ); 155 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error: %08x\n", GetLastError()); 156 ok(!ret, "Returned: %d\n", ret); 157 158 SetLastError(0xcafebabe); 159 recips = BSM_APPLICATIONS; 160 ret = broadcastex( 0x80000000, &recips, WM_NULL, 0, 0, NULL ); 161 ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error: %08x\n", GetLastError()); 162 ok(!ret, "Returned: %d\n", ret); 163 164 if (0) /* TODO: Check the hang flags */ 165 { 166 SetLastError(0xcafebabe); 167 recips = BSM_APPLICATIONS; 168 ret = broadcastex( BSF_QUERY|(BSF_NOHANG|BSF_FORCEIFHUNG), &recips, WM_NULL, 30000, 0, NULL ); 169 ok(0, "Last error: %08x\n", GetLastError()); 170 ok(0, "Returned: %d\n", ret); 171 172 SetLastError(0xcafebabe); 173 recips = BSM_APPLICATIONS; 174 ret = broadcastex( BSF_QUERY|(BSF_NOHANG|BSF_NOTIMEOUTIFNOTHUNG), &recips, WM_NULL, 30000, 0, NULL ); 175 ok(0, "Last error: %08x\n", GetLastError()); 176 ok(0, "Returned: %d\n", ret); 177 178 SetLastError(0xcafebabe); 179 recips = BSM_APPLICATIONS; 180 ret = broadcastex( BSF_QUERY|(BSF_NOTIMEOUTIFNOTHUNG|BSF_FORCEIFHUNG), &recips, WM_NULL, 30000, 0, NULL ); 181 ok(0, "Last error: %08x\n", GetLastError()); 182 ok(0, "Returned: %d\n", ret); 183 184 SetLastError(0xcafebabe); 185 recips = BSM_APPLICATIONS; 186 ret = broadcastex( BSF_POSTMESSAGE|(BSF_NOTIMEOUTIFNOTHUNG|BSF_FORCEIFHUNG), &recips, WM_NULL, 30000, 0, NULL ); 187 ok(0, "Last error: %08x\n", GetLastError()); 188 ok(0, "Returned: %d\n", ret); 189 } 190 191 recips = BSM_APPLICATIONS; 192 ret = broadcastex( BSF_POSTMESSAGE|BSF_SENDNOTIFYMESSAGE, &recips, WM_NULL, 100, 0, NULL ); 193 ok(ret==1, "Returned: %d\n", ret); 194 ok(WaitForSingleObject(hevent, 0) != WAIT_OBJECT_0, "Synchronous message sent instead\n"); 195 PulseEvent(hevent); 196 197 recips = BSM_APPLICATIONS; 198 ret = broadcastex( BSF_SENDNOTIFYMESSAGE, &recips, WM_NULL, 100, BROADCAST_QUERY_DENY, NULL ); 199 ok(ret==1, "Returned: %d\n", ret); 200 ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n"); 201 PulseEvent(hevent); 202 } 203 204 START_TEST(broadcast) 205 { 206 if (!init_procs()) 207 return; 208 209 trace("Running BroadcastSystemMessageA tests\n"); 210 test_parameters(BroadcastSystemMessageA, "BroadcastSystemMessageA"); 211 212 trace("Running BroadcastSystemMessageW tests\n"); 213 test_parameters(BroadcastSystemMessageW, "BroadcastSystemMessageW"); 214 215 trace("Running BroadcastSystemMessageExA tests\n"); 216 test_parametersEx(BroadcastSystemMessageExA); 217 218 trace("Running BroadcastSystemMessageExW tests\n"); 219 test_parametersEx(BroadcastSystemMessageExW); 220 } 221