user32: Implement BroadcastSystemMessage.

This commit is contained in:
Maarten Lankhorst 2008-04-01 12:15:55 -07:00 committed by Alexandre Julliard
parent f54570fdbd
commit 70a6495a31
10 changed files with 533 additions and 30 deletions

View File

@ -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.@)

View File

@ -6,6 +6,7 @@ TESTDLL = user32.dll
IMPORTS = user32 gdi32 advapi32 kernel32
CTESTS = \
broadcast.c \
class.c \
clipboard.c \
combo.c \

View File

@ -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");
}

View File

@ -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)

View File

@ -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;

View File

@ -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.@)
*/

View File

@ -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 */

View File

@ -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 */

View File

@ -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 );

View File

@ -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;