| /* |
| * Unit tests for BroadcastSystemMessage |
| * |
| * Copyright 2008 Maarten Lankhorst |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public |
| * License as published by the Free Software Foundation; either |
| * version 2.1 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public |
| * License along with this library; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA |
| */ |
| |
| #define _WIN32_WINNT 0x0501 |
| |
| #include <stdarg.h> |
| #include <stdio.h> |
| |
| #include "windef.h" |
| #include "winbase.h" |
| #include "wingdi.h" |
| #include "winuser.h" |
| #include "winnls.h" |
| |
| #include "wine/test.h" |
| |
| typedef LONG (WINAPI *PBROADCAST)( DWORD,LPDWORD,UINT,WPARAM,LPARAM ); |
| typedef LONG (WINAPI *PBROADCASTEX)( DWORD,LPDWORD,UINT,WPARAM,LPARAM,PBSMINFO ); |
| static PBROADCAST pBroadcastA; |
| static PBROADCAST pBroadcastW; |
| static PBROADCASTEX pBroadcastExA; |
| static PBROADCASTEX pBroadcastExW; |
| static HANDLE hevent; |
| |
| static LRESULT WINAPI main_window_procA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) |
| { |
| if (msg == WM_NULL) |
| { |
| trace("main_window_procA: Sleeping for %lu ms\n", wparam); |
| if (wparam) |
| { |
| if (WaitForSingleObject(hevent, wparam) == WAIT_TIMEOUT) |
| SetEvent(hevent); |
| } |
| trace("main_window_procA: Returning WM_NULL with parameter %08lx\n", lparam); |
| return lparam; |
| } |
| |
| return DefWindowProcA(hwnd, msg, wparam, lparam); |
| } |
| |
| static BOOL init_procs(void) |
| { |
| WNDCLASSA cls; |
| HANDLE user32 = GetModuleHandle("user32"); |
| pBroadcastA = (PBROADCAST)GetProcAddress(user32, "BroadcastSystemMessageA"); |
| if (!pBroadcastA) |
| pBroadcastA = (PBROADCAST)GetProcAddress(user32, "BroadcastSystemMessage"); |
| ok(pBroadcastA != NULL, "No BroadcastSystemMessage found\n"); |
| if (!pBroadcastA) |
| { |
| win_skip("BroadcastA is not available\n"); |
| return FALSE; |
| } |
| |
| pBroadcastW = (PBROADCAST)GetProcAddress(user32, "BroadcastSystemMessageW"); |
| pBroadcastExA = (PBROADCASTEX)GetProcAddress(user32, "BroadcastSystemMessageExA"); |
| pBroadcastExW = (PBROADCASTEX)GetProcAddress(user32, "BroadcastSystemMessageExW"); |
| |
| hevent = CreateEventA(NULL, TRUE, FALSE, "Asynchronous checking event"); |
| |
| cls.style = CS_DBLCLKS; |
| cls.lpfnWndProc = main_window_procA; |
| cls.cbClsExtra = 0; |
| cls.cbWndExtra = 0; |
| cls.hInstance = GetModuleHandleA(0); |
| cls.hIcon = 0; |
| cls.hCursor = LoadCursorA(0, IDC_ARROW); |
| cls.hbrBackground = GetStockObject(WHITE_BRUSH); |
| cls.lpszMenuName = NULL; |
| cls.lpszClassName = "MainWindowClass"; |
| |
| if (!RegisterClassA(&cls)) |
| return FALSE; |
| |
| if (!CreateWindowExA(0, "MainWindowClass", "Main window", WS_CAPTION | WS_SYSMENU | |
| WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP, 100, 100, 200, |
| 200, 0, 0, GetModuleHandle(0), NULL)) |
| return FALSE; |
| return TRUE; |
| } |
| |
| static void test_parameters(PBROADCAST broadcast, const char *functionname) |
| { |
| LONG ret; |
| DWORD recips; |
| |
| SetLastError(0xcafebabe); |
| recips = BSM_APPLICATIONS; |
| ret = broadcast( 0x80000000, &recips, WM_NULL, 0, 0 ); |
| if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) |
| { |
| win_skip("%s is not implemented\n", functionname); |
| return; |
| } |
| ok(!ret || broken(ret), "Returned: %d\n", ret); |
| if (!ret) ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error: %08x\n", GetLastError()); |
| |
| SetLastError(0xcafebabe); |
| recips = BSM_APPLICATIONS; |
| ret = broadcast( 0x80000000, &recips, WM_NULL, 0, 0 ); |
| ok(!ret || broken(ret), "Returned: %d\n", ret); |
| if (!ret) ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error: %08x\n", GetLastError()); |
| |
| #if 0 /* TODO: Check the hang flags */ |
| SetLastError(0xcafebabe); |
| recips = BSM_APPLICATIONS; |
| ret = broadcast( BSF_QUERY|(BSF_NOHANG|BSF_FORCEIFHUNG), &recips, WM_NULL, 30000, 0 ); |
| ok(0, "Last error: %08x\n", GetLastError()); |
| ok(0, "Returned: %d\n", ret); |
| |
| SetLastError(0xcafebabe); |
| recips = BSM_APPLICATIONS; |
| ret = broadcast( BSF_QUERY|(BSF_NOHANG|BSF_NOTIMEOUTIFNOTHUNG), &recips, WM_NULL, 30000, 0 ); |
| ok(0, "Last error: %08x\n", GetLastError()); |
| ok(0, "Returned: %d\n", ret); |
| |
| SetLastError(0xcafebabe); |
| recips = BSM_APPLICATIONS; |
| ret = broadcast( BSF_QUERY|(BSF_NOTIMEOUTIFNOTHUNG|BSF_FORCEIFHUNG), &recips, WM_NULL, 30000, 0 ); |
| ok(0, "Last error: %08x\n", GetLastError()); |
| ok(0, "Returned: %d\n", ret); |
| |
| SetLastError(0xcafebabe); |
| recips = BSM_APPLICATIONS; |
| ret = broadcast( BSF_POSTMESSAGE|(BSF_NOTIMEOUTIFNOTHUNG|BSF_FORCEIFHUNG), &recips, WM_NULL, 30000, 0 ); |
| ok(0, "Last error: %08x\n", GetLastError()); |
| ok(0, "Returned: %d\n", ret); |
| #endif |
| |
| recips = BSM_APPLICATIONS; |
| ResetEvent(hevent); |
| ret = broadcast( BSF_POSTMESSAGE|BSF_QUERY, &recips, WM_NULL, 100, 0 ); |
| ok(ret==1, "Returned: %d\n", ret); |
| ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n"); |
| PulseEvent(hevent); |
| |
| SetLastError( 0xdeadbeef ); |
| recips = BSM_APPLICATIONS; |
| ret = broadcast( BSF_POSTMESSAGE|BSF_SENDNOTIFYMESSAGE, &recips, WM_NULL, 100, 0 ); |
| if (ret) |
| { |
| ok(ret==1, "Returned: %d\n", ret); |
| ok(WaitForSingleObject(hevent, 0) != WAIT_OBJECT_0, "Synchronous message sent instead\n"); |
| PulseEvent(hevent); |
| |
| recips = BSM_APPLICATIONS; |
| ret = broadcast( BSF_SENDNOTIFYMESSAGE, &recips, WM_NULL, 100, BROADCAST_QUERY_DENY ); |
| ok(ret==1, "Returned: %d\n", ret); |
| ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n"); |
| PulseEvent(hevent); |
| |
| recips = BSM_APPLICATIONS; |
| ret = broadcast( BSF_SENDNOTIFYMESSAGE|BSF_QUERY, &recips, WM_NULL, 100, BROADCAST_QUERY_DENY ); |
| ok(!ret, "Returned: %d\n", ret); |
| ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n"); |
| PulseEvent(hevent); |
| } |
| else /* BSF_SENDNOTIFYMESSAGE not supported on NT4 */ |
| ok( GetLastError() == ERROR_INVALID_PARAMETER, "failed with err %u\n", GetLastError() ); |
| |
| recips = BSM_APPLICATIONS; |
| ret = broadcast( 0, &recips, WM_NULL, 100, 0 ); |
| ok(ret==1, "Returned: %d\n", ret); |
| ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n"); |
| PulseEvent(hevent); |
| } |
| |
| /* BSF_SENDNOTIFYMESSAGE and BSF_QUERY are both synchronous within the same process |
| * However you should be able to distinguish them by sending the BROADCAST_QUERY_DENY flag |
| */ |
| |
| static void test_parametersEx(PBROADCASTEX broadcastex) |
| { |
| LONG ret; |
| DWORD recips; |
| |
| SetLastError(0xcafebabe); |
| recips = BSM_APPLICATIONS; |
| ret = broadcastex( 0x80000000, &recips, WM_NULL, 0, 0, NULL ); |
| ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error: %08x\n", GetLastError()); |
| ok(!ret, "Returned: %d\n", ret); |
| |
| SetLastError(0xcafebabe); |
| recips = BSM_APPLICATIONS; |
| ret = broadcastex( 0x80000000, &recips, WM_NULL, 0, 0, NULL ); |
| ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error: %08x\n", GetLastError()); |
| ok(!ret, "Returned: %d\n", ret); |
| |
| #if 0 /* TODO: Check the hang flags */ |
| SetLastError(0xcafebabe); |
| recips = BSM_APPLICATIONS; |
| ret = broadcast( BSF_QUERY|(BSF_NOHANG|BSF_FORCEIFHUNG), &recips, WM_NULL, 30000, 0, NULL ); |
| ok(0, "Last error: %08x\n", GetLastError()); |
| ok(0, "Returned: %d\n", ret); |
| |
| SetLastError(0xcafebabe); |
| recips = BSM_APPLICATIONS; |
| ret = broadcast( BSF_QUERY|(BSF_NOHANG|BSF_NOTIMEOUTIFNOTHUNG), &recips, WM_NULL, 30000, 0, NULL ); |
| ok(0, "Last error: %08x\n", GetLastError()); |
| ok(0, "Returned: %d\n", ret); |
| |
| SetLastError(0xcafebabe); |
| recips = BSM_APPLICATIONS; |
| ret = broadcast( BSF_QUERY|(BSF_NOTIMEOUTIFNOTHUNG|BSF_FORCEIFHUNG), &recips, WM_NULL, 30000, 0, NULL ); |
| ok(0, "Last error: %08x\n", GetLastError()); |
| ok(0, "Returned: %d\n", ret); |
| |
| SetLastError(0xcafebabe); |
| recips = BSM_APPLICATIONS; |
| ret = broadcast( BSF_POSTMESSAGE|(BSF_NOTIMEOUTIFNOTHUNG|BSF_FORCEIFHUNG), &recips, WM_NULL, 30000, 0, NULL ); |
| ok(0, "Last error: %08x\n", GetLastError()); |
| ok(0, "Returned: %d\n", ret); |
| #endif |
| |
| recips = BSM_APPLICATIONS; |
| ResetEvent(hevent); |
| ret = broadcastex( BSF_POSTMESSAGE|BSF_QUERY, &recips, WM_NULL, 100, 0, NULL ); |
| ok(ret==1, "Returned: %d\n", ret); |
| ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n"); |
| PulseEvent(hevent); |
| |
| recips = BSM_APPLICATIONS; |
| ret = broadcastex( BSF_POSTMESSAGE|BSF_SENDNOTIFYMESSAGE, &recips, WM_NULL, 100, 0, NULL ); |
| ok(ret==1, "Returned: %d\n", ret); |
| ok(WaitForSingleObject(hevent, 0) != WAIT_OBJECT_0, "Synchronous message sent instead\n"); |
| PulseEvent(hevent); |
| |
| recips = BSM_APPLICATIONS; |
| ret = broadcastex( BSF_SENDNOTIFYMESSAGE, &recips, WM_NULL, 100, BROADCAST_QUERY_DENY, NULL ); |
| ok(ret==1, "Returned: %d\n", ret); |
| ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n"); |
| PulseEvent(hevent); |
| |
| recips = BSM_APPLICATIONS; |
| ret = broadcastex( BSF_SENDNOTIFYMESSAGE|BSF_QUERY, &recips, WM_NULL, 100, BROADCAST_QUERY_DENY, NULL ); |
| ok(!ret, "Returned: %d\n", ret); |
| ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n"); |
| PulseEvent(hevent); |
| |
| recips = BSM_APPLICATIONS; |
| ret = broadcastex( 0, &recips, WM_NULL, 100, 0, NULL ); |
| ok(ret==1, "Returned: %d\n", ret); |
| ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n"); |
| PulseEvent(hevent); |
| } |
| |
| static BOOL (WINAPI *pOpenProcessToken)(HANDLE, DWORD, HANDLE*); |
| static BOOL (WINAPI *pAdjustTokenPrivileges)(HANDLE, BOOL, PTOKEN_PRIVILEGES, DWORD, PTOKEN_PRIVILEGES, PDWORD); |
| |
| static void test_noprivileges(void) |
| { |
| HANDLE advapi32 = GetModuleHandleA("advapi32"); |
| HANDLE token; |
| DWORD recips; |
| BOOL ret; |
| |
| static const DWORD BSM_ALL_RECIPS = BSM_VXDS | BSM_NETDRIVER | |
| BSM_INSTALLABLEDRIVERS | BSM_APPLICATIONS; |
| |
| pOpenProcessToken = (void *)GetProcAddress(advapi32, "OpenProcessToken"); |
| pAdjustTokenPrivileges = (void *)GetProcAddress(advapi32, "AdjustTokenPrivileges"); |
| if (!pOpenProcessToken || !pAdjustTokenPrivileges || !pOpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token)) |
| { |
| skip("Can't open security token for process\n"); |
| return; |
| } |
| if (!pAdjustTokenPrivileges(token, TRUE, NULL, 0, NULL, NULL)) |
| { |
| skip("Can't adjust security token for process\n"); |
| return; |
| } |
| |
| trace("Trying privileged edition!\n"); |
| SetLastError(0xcafebabe); |
| recips = BSM_ALLDESKTOPS; |
| ResetEvent(hevent); |
| ret = pBroadcastExW( BSF_QUERY, &recips, WM_NULL, 100, 0, NULL ); |
| ok(ret==1, "Returned: %d error %u\n", ret, GetLastError()); |
| ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n"); |
| ok(recips == BSM_ALLDESKTOPS || |
| recips == BSM_ALL_RECIPS, /* win2k3 */ |
| "Received by: %08x\n", recips); |
| PulseEvent(hevent); |
| |
| SetLastError(0xcafebabe); |
| recips = BSM_ALLCOMPONENTS; |
| ResetEvent(hevent); |
| ret = pBroadcastExW( BSF_QUERY, &recips, WM_NULL, 100, 0, NULL ); |
| ok(ret==1, "Returned: %d error %u\n", ret, GetLastError()); |
| ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n"); |
| ok(recips == BSM_ALLCOMPONENTS || |
| recips == BSM_ALL_RECIPS, /* win2k3 */ |
| "Received by: %08x\n", recips); |
| PulseEvent(hevent); |
| |
| SetLastError(0xcafebabe); |
| recips = BSM_ALLDESKTOPS|BSM_APPLICATIONS; |
| ResetEvent(hevent); |
| ret = pBroadcastExW( BSF_QUERY, &recips, WM_NULL, 100, 0, NULL ); |
| ok(ret==1, "Returned: %d error %u\n", ret, GetLastError()); |
| ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n"); |
| ok(recips == (BSM_ALLDESKTOPS|BSM_APPLICATIONS) || |
| recips == BSM_APPLICATIONS, /* win2k3 */ |
| "Received by: %08x\n", recips); |
| PulseEvent(hevent); |
| |
| SetLastError(0xcafebabe); |
| recips = BSM_ALLDESKTOPS|BSM_APPLICATIONS; |
| ResetEvent(hevent); |
| ret = pBroadcastExW( BSF_QUERY, &recips, WM_NULL, 100, BROADCAST_QUERY_DENY, NULL ); |
| ok(!ret, "Returned: %d\n", ret); |
| ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n"); |
| ok(recips == (BSM_ALLDESKTOPS|BSM_APPLICATIONS) || |
| recips == BSM_APPLICATIONS, /* win2k3 */ |
| "Received by: %08x\n", recips); |
| PulseEvent(hevent); |
| } |
| |
| START_TEST(broadcast) |
| { |
| if (!init_procs()) |
| return; |
| |
| trace("Running BroadcastSystemMessageA tests\n"); |
| test_parameters(pBroadcastA, "BroadcastSystemMessageA"); |
| if (pBroadcastW) |
| { |
| trace("Running BroadcastSystemMessageW tests\n"); |
| test_parameters(pBroadcastW, "BroadcastSystemMessageW"); |
| } |
| else |
| win_skip("No BroadcastSystemMessageW, skipping\n"); |
| if (pBroadcastExA) |
| { |
| trace("Running BroadcastSystemMessageExA tests\n"); |
| test_parametersEx(pBroadcastExA); |
| } |
| else |
| win_skip("No BroadcastSystemMessageExA, skipping\n"); |
| if (pBroadcastExW) |
| { |
| trace("Running BroadcastSystemMessageExW tests\n"); |
| test_parametersEx(pBroadcastExW); |
| trace("Attempting privileges checking tests\n"); |
| test_noprivileges(); |
| } |
| else |
| win_skip("No BroadcastSystemMessageExW, skipping\n"); |
| } |