user32: Implement BroadcastSystemMessage.
This commit is contained in:
parent
f54570fdbd
commit
70a6495a31
|
@ -2,6 +2,7 @@
|
|||
* Window messaging support
|
||||
*
|
||||
* Copyright 2001 Alexandre Julliard
|
||||
* 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
|
||||
|
@ -3343,6 +3344,105 @@ UINT WINAPI RegisterWindowMessageW( LPCWSTR str )
|
|||
return ret;
|
||||
}
|
||||
|
||||
typedef struct BroadcastParm
|
||||
{
|
||||
DWORD flags;
|
||||
LPDWORD recipients;
|
||||
UINT msg;
|
||||
WPARAM wp;
|
||||
LPARAM lp;
|
||||
DWORD success;
|
||||
HWINSTA winsta;
|
||||
} BroadcastParm;
|
||||
|
||||
static BOOL CALLBACK bcast_childwindow( HWND hw, LPARAM lp )
|
||||
{
|
||||
BroadcastParm *parm = (BroadcastParm*)lp;
|
||||
DWORD_PTR retval = 0;
|
||||
LONG lresult;
|
||||
|
||||
if (parm->flags & BSF_IGNORECURRENTTASK && WIN_IsCurrentProcess(hw))
|
||||
{
|
||||
TRACE("Not telling myself %p\n", hw);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* I don't know 100% for sure if this is what Windows does, but it fits the tests */
|
||||
if (parm->flags & BSF_QUERY)
|
||||
{
|
||||
TRACE("Telling window %p using SendMessageTimeout\n", hw);
|
||||
|
||||
/* Not tested for conflicting flags */
|
||||
if (parm->flags & BSF_FORCEIFHUNG || parm->flags & BSF_NOHANG)
|
||||
lresult = SendMessageTimeoutW( hw, parm->msg, parm->wp, parm->lp, SMTO_ABORTIFHUNG, 2000, &retval );
|
||||
else if (parm->flags & BSF_NOTIMEOUTIFNOTHUNG)
|
||||
lresult = SendMessageTimeoutW( hw, parm->msg, parm->wp, parm->lp, SMTO_NOTIMEOUTIFNOTHUNG, 2000, &retval );
|
||||
else
|
||||
lresult = SendMessageTimeoutW( hw, parm->msg, parm->wp, parm->lp, SMTO_NORMAL, 2000, &retval );
|
||||
|
||||
if (!lresult && GetLastError() == ERROR_TIMEOUT)
|
||||
{
|
||||
WARN("Timed out!\n");
|
||||
if (!(parm->flags & BSF_FORCEIFHUNG))
|
||||
goto fail;
|
||||
}
|
||||
if (retval == BROADCAST_QUERY_DENY)
|
||||
goto fail;
|
||||
|
||||
return TRUE;
|
||||
|
||||
fail:
|
||||
parm->success = 0;
|
||||
return FALSE;
|
||||
}
|
||||
else if (parm->flags & BSF_POSTMESSAGE)
|
||||
{
|
||||
TRACE("Telling window %p using PostMessage\n", hw);
|
||||
PostMessageW( hw, parm->msg, parm->wp, parm->lp );
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACE("Telling window %p using SendNotifyMessage\n", hw);
|
||||
SendNotifyMessageW( hw, parm->msg, parm->wp, parm->lp );
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL CALLBACK bcast_desktop( LPWSTR desktop, LPARAM lp )
|
||||
{
|
||||
BOOL ret;
|
||||
HDESK hdesktop;
|
||||
BroadcastParm *parm = (BroadcastParm*)lp;
|
||||
|
||||
TRACE("desktop: %s\n", debugstr_w( desktop ));
|
||||
|
||||
hdesktop = open_winstation_desktop( parm->winsta, desktop, 0, FALSE, DESKTOP_ENUMERATE|DESKTOP_WRITEOBJECTS|STANDARD_RIGHTS_WRITE );
|
||||
if (!hdesktop)
|
||||
{
|
||||
FIXME("Could not open desktop %s\n", debugstr_w(desktop));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
ret = EnumDesktopWindows( hdesktop, bcast_childwindow, lp );
|
||||
CloseDesktop(hdesktop);
|
||||
TRACE("-->%d\n", ret);
|
||||
return parm->success;
|
||||
}
|
||||
|
||||
static BOOL CALLBACK bcast_winsta( LPWSTR winsta, LPARAM lp )
|
||||
{
|
||||
BOOL ret;
|
||||
HWINSTA hwinsta = OpenWindowStationW( winsta, FALSE, WINSTA_ENUMDESKTOPS );
|
||||
TRACE("hwinsta: %p/%s/%08x\n", hwinsta, debugstr_w( winsta ), GetLastError());
|
||||
if (!hwinsta)
|
||||
return TRUE;
|
||||
((BroadcastParm *)lp)->winsta = hwinsta;
|
||||
ret = EnumDesktopsW( hwinsta, bcast_desktop, lp );
|
||||
CloseWindowStation( hwinsta );
|
||||
TRACE("-->%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* BroadcastSystemMessageA (USER32.@)
|
||||
|
@ -3350,17 +3450,7 @@ UINT WINAPI RegisterWindowMessageW( LPCWSTR str )
|
|||
*/
|
||||
LONG WINAPI BroadcastSystemMessageA( DWORD flags, LPDWORD recipients, UINT msg, WPARAM wp, LPARAM lp )
|
||||
{
|
||||
if ((*recipients & BSM_APPLICATIONS) || (*recipients == BSM_ALLCOMPONENTS))
|
||||
{
|
||||
FIXME( "(%08x,%08x,%08x,%08lx,%08lx): semi-stub!\n", flags, *recipients, msg, wp, lp );
|
||||
PostMessageA( HWND_BROADCAST, msg, wp, lp );
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
FIXME( "(%08x,%08x,%08x,%08lx,%08lx): stub!\n", flags, *recipients, msg, wp, lp);
|
||||
return -1;
|
||||
}
|
||||
return BroadcastSystemMessageExA( flags, recipients, msg, wp, lp, NULL );
|
||||
}
|
||||
|
||||
|
||||
|
@ -3369,19 +3459,65 @@ LONG WINAPI BroadcastSystemMessageA( DWORD flags, LPDWORD recipients, UINT msg,
|
|||
*/
|
||||
LONG WINAPI BroadcastSystemMessageW( DWORD flags, LPDWORD recipients, UINT msg, WPARAM wp, LPARAM lp )
|
||||
{
|
||||
if ((*recipients & BSM_APPLICATIONS) || (*recipients == BSM_ALLCOMPONENTS))
|
||||
{
|
||||
FIXME( "(%08x,%08x,%08x,%08lx,%08lx): semi-stub!\n", flags, *recipients, msg, wp, lp );
|
||||
PostMessageW( HWND_BROADCAST, msg, wp, lp );
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
FIXME( "(%08x,%08x,%08x,%08lx,%08lx): stub!\n", flags, *recipients, msg, wp, lp );
|
||||
return -1;
|
||||
}
|
||||
return BroadcastSystemMessageExW( flags, recipients, msg, wp, lp, NULL );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* BroadcastSystemMessageExA (USER32.@)
|
||||
*/
|
||||
LONG WINAPI BroadcastSystemMessageExA( DWORD flags, LPDWORD recipients, UINT msg, WPARAM wp, LPARAM lp, PBSMINFO pinfo )
|
||||
{
|
||||
map_wparam_AtoW( msg, &wp, WMCHAR_MAP_NOMAPPING );
|
||||
return BroadcastSystemMessageExW( flags, recipients, msg, wp, lp, NULL );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* BroadcastSystemMessageExW (USER32.@)
|
||||
*/
|
||||
LONG WINAPI BroadcastSystemMessageExW( DWORD flags, LPDWORD recipients, UINT msg, WPARAM wp, LPARAM lp, PBSMINFO pinfo )
|
||||
{
|
||||
BroadcastParm parm;
|
||||
DWORD recips = BSM_ALLCOMPONENTS;
|
||||
BOOL ret = TRUE;
|
||||
static const DWORD all_flags = ( BSF_QUERY | BSF_IGNORECURRENTTASK | BSF_FLUSHDISK | BSF_NOHANG
|
||||
| BSF_POSTMESSAGE | BSF_FORCEIFHUNG | BSF_NOTIMEOUTIFNOTHUNG
|
||||
| BSF_ALLOWSFW | BSF_SENDNOTIFYMESSAGE | BSF_RETURNHDESK | BSF_LUID );
|
||||
|
||||
TRACE("Flags: %08x, recipients: %p(0x%x), msg: %04x, wparam: %08lx, lparam: %08lx\n", flags, recipients,
|
||||
(recipients ? *recipients : recips), msg, wp, lp);
|
||||
|
||||
if (flags & ~all_flags)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!recipients)
|
||||
recipients = &recips;
|
||||
|
||||
if ( pinfo && flags & BSF_QUERY )
|
||||
FIXME("Not returning PBSMINFO information yet\n");
|
||||
|
||||
parm.flags = flags;
|
||||
parm.recipients = recipients;
|
||||
parm.msg = msg;
|
||||
parm.wp = wp;
|
||||
parm.lp = lp;
|
||||
parm.success = TRUE;
|
||||
|
||||
if (*recipients & BSM_ALLDESKTOPS || *recipients == BSM_ALLCOMPONENTS)
|
||||
ret = EnumWindowStationsW(bcast_winsta, (LONG_PTR)&parm);
|
||||
else if (*recipients & BSM_APPLICATIONS)
|
||||
{
|
||||
EnumWindows(bcast_childwindow, (LONG_PTR)&parm);
|
||||
ret = parm.success;
|
||||
}
|
||||
else
|
||||
FIXME("Recipients %08x not supported!\n", *recipients);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* SetMessageQueue (USER32.@)
|
||||
|
|
|
@ -6,6 +6,7 @@ TESTDLL = user32.dll
|
|||
IMPORTS = user32 gdi32 advapi32 kernel32
|
||||
|
||||
CTESTS = \
|
||||
broadcast.c \
|
||||
class.c \
|
||||
clipboard.c \
|
||||
combo.c \
|
||||
|
|
|
@ -0,0 +1,348 @@
|
|||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define _WIN32_WINNT 0x0501
|
||||
|
||||
#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)
|
||||
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, (LPSTR)IDC_ARROW);
|
||||
cls.hbrBackground = GetStockObject(WHITE_BRUSH);
|
||||
cls.lpszMenuName = NULL;
|
||||
cls.lpszClassName = "MainWindowClass";
|
||||
|
||||
if (!RegisterClassA(&cls))
|
||||
return 0;
|
||||
|
||||
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)
|
||||
{
|
||||
LONG ret;
|
||||
DWORD recips;
|
||||
|
||||
SetLastError(0xcafebabe);
|
||||
recips = BSM_APPLICATIONS;
|
||||
ret = broadcast( 0x80000000, &recips, WM_NULL, 0, 0 );
|
||||
ok(GetLastError() == ERROR_INVALID_PARAMETER, "Last error: %08x\n", GetLastError());
|
||||
ok(!ret, "Returned: %d\n", ret);
|
||||
|
||||
SetLastError(0xcafebabe);
|
||||
recips = BSM_APPLICATIONS;
|
||||
ret = broadcast( 0x80000000, &recips, WM_NULL, 0, 0 );
|
||||
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 );
|
||||
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);
|
||||
|
||||
recips = BSM_APPLICATIONS;
|
||||
ret = broadcast( BSF_POSTMESSAGE|BSF_SENDNOTIFYMESSAGE, &recips, WM_NULL, 100, 0 );
|
||||
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);
|
||||
|
||||
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;
|
||||
|
||||
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 );
|
||||
todo_wine ok(GetLastError() == ERROR_PRIVILEGE_NOT_HELD, "Last error: %08x\n", GetLastError());
|
||||
ok(ret==1, "Returned: %d\n", ret);
|
||||
ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n");
|
||||
ok(recips == BSM_ALLDESKTOPS, "Received by: %08x\n", recips);
|
||||
PulseEvent(hevent);
|
||||
|
||||
/* Wine sets last error to 0, so just use that one as token here so it doesn't fail */
|
||||
SetLastError(0);
|
||||
recips = BSM_ALLCOMPONENTS;
|
||||
ResetEvent(hevent);
|
||||
ret = pBroadcastExW( BSF_QUERY, &recips, WM_NULL, 100, 0, NULL );
|
||||
ok(!GetLastError(), "Last error: %08x\n", GetLastError());
|
||||
ok(ret==1, "Returned: %d\n", ret);
|
||||
ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n");
|
||||
ok(recips == BSM_ALLCOMPONENTS, "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 );
|
||||
todo_wine ok(GetLastError() == ERROR_PRIVILEGE_NOT_HELD, "Last error: %08x\n", GetLastError());
|
||||
ok(ret==1, "Returned: %d\n", ret);
|
||||
ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n");
|
||||
ok(recips == (BSM_ALLDESKTOPS|BSM_APPLICATIONS), "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 );
|
||||
todo_wine ok(GetLastError() == ERROR_PRIVILEGE_NOT_HELD, "Last error: %08x\n", GetLastError());
|
||||
ok(!ret, "Returned: %d\n", ret);
|
||||
ok(WaitForSingleObject(hevent, 0) != WAIT_TIMEOUT, "Asynchronous message sent instead\n");
|
||||
ok(recips == (BSM_ALLDESKTOPS|BSM_APPLICATIONS), "Received by: %08x\n", recips);
|
||||
PulseEvent(hevent);
|
||||
}
|
||||
|
||||
START_TEST(broadcast)
|
||||
{
|
||||
if (!init_procs())
|
||||
return;
|
||||
|
||||
trace("Running BroadcastSystemMessageA tests\n");
|
||||
test_parameters(pBroadcastA);
|
||||
if (pBroadcastW)
|
||||
{
|
||||
trace("Running BroadcastSystemMessageW tests\n");
|
||||
test_parameters(pBroadcastW);
|
||||
}
|
||||
else
|
||||
skip("No BroadcastSystemMessageW, skipping\n");
|
||||
if (pBroadcastExA)
|
||||
{
|
||||
trace("Running BroadcastSystemMessageExA tests\n");
|
||||
test_parametersEx(pBroadcastExA);
|
||||
}
|
||||
else
|
||||
skip("No BroadcastSystemMessageExA, skipping\n");
|
||||
if (pBroadcastExW)
|
||||
{
|
||||
trace("Running BroadcastSystemMessageExW tests\n");
|
||||
test_parametersEx(pBroadcastExW);
|
||||
trace("Attempting privileges checking tests\n");
|
||||
test_noprivileges();
|
||||
}
|
||||
else
|
||||
skip("No BroadcastSystemMessageExW, skipping\n");
|
||||
}
|
|
@ -16,8 +16,8 @@
|
|||
@ stdcall BringWindowToTop(long)
|
||||
@ stdcall BroadcastSystemMessage(long ptr long long long) BroadcastSystemMessageA
|
||||
@ stdcall BroadcastSystemMessageA(long ptr long long long)
|
||||
# @ stub BroadcastSystemMessageExA
|
||||
# @ stub BroadcastSystemMessageExW
|
||||
@ stdcall BroadcastSystemMessageExA(long ptr long long long ptr)
|
||||
@ stdcall BroadcastSystemMessageExW(long ptr long long long ptr)
|
||||
@ stdcall BroadcastSystemMessageW(long ptr long long long)
|
||||
# @ stub BuildReasonArray
|
||||
@ stdcall CalcChildScroll(long long)
|
||||
|
|
|
@ -89,6 +89,7 @@ extern BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL ) DECLSPEC_HIDDEN;
|
|||
extern HWND *WIN_ListChildren( HWND hwnd ) DECLSPEC_HIDDEN;
|
||||
extern LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, UINT size, LONG_PTR newval, BOOL unicode ) DECLSPEC_HIDDEN;
|
||||
extern void MDI_CalcDefaultChildPos( HWND hwndClient, INT total, LPPOINT lpPos, INT delta, UINT *id ) DECLSPEC_HIDDEN;
|
||||
extern HDESK open_winstation_desktop( HWINSTA hwinsta, LPCWSTR name, DWORD flags, BOOL inherit, ACCESS_MASK access ) DECLSPEC_HIDDEN;
|
||||
|
||||
/* user lock */
|
||||
extern void USER_Lock(void) DECLSPEC_HIDDEN;
|
||||
|
|
|
@ -317,10 +317,7 @@ HDESK WINAPI OpenDesktopA( LPCSTR name, DWORD flags, BOOL inherit, ACCESS_MASK a
|
|||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* OpenDesktopW (USER32.@)
|
||||
*/
|
||||
HDESK WINAPI OpenDesktopW( LPCWSTR name, DWORD flags, BOOL inherit, ACCESS_MASK access )
|
||||
HDESK open_winstation_desktop( HWINSTA hwinsta, LPCWSTR name, DWORD flags, BOOL inherit, ACCESS_MASK access )
|
||||
{
|
||||
HANDLE ret = 0;
|
||||
DWORD len = name ? strlenW(name) : 0;
|
||||
|
@ -331,6 +328,7 @@ HDESK WINAPI OpenDesktopW( LPCWSTR name, DWORD flags, BOOL inherit, ACCESS_MASK
|
|||
}
|
||||
SERVER_START_REQ( open_desktop )
|
||||
{
|
||||
req->winsta = hwinsta;
|
||||
req->flags = flags;
|
||||
req->access = access;
|
||||
req->attributes = OBJ_CASE_INSENSITIVE | (inherit ? OBJ_INHERIT : 0);
|
||||
|
@ -342,6 +340,15 @@ HDESK WINAPI OpenDesktopW( LPCWSTR name, DWORD flags, BOOL inherit, ACCESS_MASK
|
|||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* OpenDesktopW (USER32.@)
|
||||
*/
|
||||
HDESK WINAPI OpenDesktopW( LPCWSTR name, DWORD flags, BOOL inherit, ACCESS_MASK access )
|
||||
{
|
||||
return open_winstation_desktop( NULL, name, flags, inherit, access );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* CloseDesktop (USER32.@)
|
||||
*/
|
||||
|
|
|
@ -3299,6 +3299,7 @@ struct create_desktop_reply
|
|||
struct open_desktop_request
|
||||
{
|
||||
struct request_header __header;
|
||||
obj_handle_t winsta;
|
||||
unsigned int flags;
|
||||
unsigned int access;
|
||||
unsigned int attributes;
|
||||
|
@ -4995,6 +4996,6 @@ union generic_reply
|
|||
struct add_fd_completion_reply add_fd_completion_reply;
|
||||
};
|
||||
|
||||
#define SERVER_PROTOCOL_VERSION 338
|
||||
#define SERVER_PROTOCOL_VERSION 339
|
||||
|
||||
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
||||
|
|
|
@ -2399,6 +2399,7 @@ enum message_type
|
|||
|
||||
/* Open a handle to a desktop */
|
||||
@REQ(open_desktop)
|
||||
obj_handle_t winsta; /* window station to open (null allowed) */
|
||||
unsigned int flags; /* desktop flags */
|
||||
unsigned int access; /* wanted access rights */
|
||||
unsigned int attributes; /* object attributes */
|
||||
|
|
|
@ -2972,6 +2972,7 @@ static void dump_create_desktop_reply( const struct create_desktop_reply *req )
|
|||
|
||||
static void dump_open_desktop_request( const struct open_desktop_request *req )
|
||||
{
|
||||
fprintf( stderr, " winsta=%p,", req->winsta );
|
||||
fprintf( stderr, " flags=%08x,", req->flags );
|
||||
fprintf( stderr, " access=%08x,", req->access );
|
||||
fprintf( stderr, " attributes=%08x,", req->attributes );
|
||||
|
|
|
@ -508,7 +508,14 @@ DECL_HANDLER(open_desktop)
|
|||
struct unicode_str name;
|
||||
|
||||
get_req_unicode_str( &name );
|
||||
if ((winstation = get_process_winstation( current->process, 0 /* FIXME: access rights? */ )))
|
||||
|
||||
/* FIXME: check access rights */
|
||||
if (!req->winsta)
|
||||
winstation = get_process_winstation( current->process, 0 );
|
||||
else
|
||||
winstation = (struct winstation *)get_handle_obj( current->process, req->winsta, 0, &winstation_ops );
|
||||
|
||||
if (winstation)
|
||||
{
|
||||
struct unicode_str full_str;
|
||||
WCHAR *full_name;
|
||||
|
|
Loading…
Reference in New Issue