367 lines
14 KiB
C
367 lines
14 KiB
C
/*
|
|
* Unit tests for window stations and desktops
|
|
*
|
|
* Copyright 2002 Alexandre Julliard
|
|
*
|
|
* 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 "wine/test.h"
|
|
#include "winbase.h"
|
|
#include "wingdi.h"
|
|
#include "winuser.h"
|
|
#include "winnls.h"
|
|
|
|
#define DESKTOP_ALL_ACCESS 0x01ff
|
|
|
|
static void print_object( HANDLE obj )
|
|
{
|
|
char buffer[100];
|
|
DWORD size;
|
|
|
|
strcpy( buffer, "foobar" );
|
|
if (!GetUserObjectInformationA( obj, UOI_NAME, buffer, sizeof(buffer), &size ))
|
|
trace( "could not get info for %p\n", obj );
|
|
else
|
|
trace( "obj %p name '%s'\n", obj, buffer );
|
|
strcpy( buffer, "foobar" );
|
|
if (!GetUserObjectInformationA( obj, UOI_TYPE, buffer, sizeof(buffer), &size ))
|
|
trace( "could not get type for %p\n", obj );
|
|
else
|
|
trace( "obj %p type '%s'\n", obj, buffer );
|
|
}
|
|
|
|
static void register_class(void)
|
|
{
|
|
WNDCLASSA cls;
|
|
|
|
cls.style = CS_DBLCLKS;
|
|
cls.lpfnWndProc = DefWindowProcA;
|
|
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 = "WinStationClass";
|
|
RegisterClassA(&cls);
|
|
}
|
|
|
|
static HDESK initial_desktop;
|
|
|
|
static DWORD CALLBACK thread( LPVOID arg )
|
|
{
|
|
HDESK d1, d2;
|
|
HWND hwnd = CreateWindowExA(0,"WinStationClass","test",WS_POPUP,0,0,100,100,GetDesktopWindow(),0,0,0);
|
|
ok( hwnd != 0, "CreateWindow failed\n" );
|
|
d1 = GetThreadDesktop(GetCurrentThreadId());
|
|
trace( "thread %p desktop: %p\n", arg, d1 );
|
|
ok( d1 == initial_desktop, "thread %p doesn't use initial desktop\n", arg );
|
|
|
|
SetLastError( 0xdeadbeef );
|
|
ok( !CloseHandle( d1 ), "CloseHandle succeeded\n" );
|
|
ok( GetLastError() == ERROR_INVALID_HANDLE, "bad last error %d\n", GetLastError() );
|
|
SetLastError( 0xdeadbeef );
|
|
ok( !CloseDesktop( d1 ), "CloseDesktop succeeded\n" );
|
|
ok( GetLastError() == ERROR_BUSY, "bad last error %d\n", GetLastError() );
|
|
print_object( d1 );
|
|
d2 = CreateDesktop( "foobar2", NULL, NULL, 0, DESKTOP_ALL_ACCESS, NULL );
|
|
trace( "created desktop %p\n", d2 );
|
|
ok( d2 != 0, "CreateDesktop failed\n" );
|
|
|
|
SetLastError( 0xdeadbeef );
|
|
ok( !SetThreadDesktop( d2 ), "set thread desktop succeeded with existing window\n" );
|
|
ok( GetLastError() == ERROR_BUSY, "bad last error %d\n", GetLastError() );
|
|
|
|
DestroyWindow( hwnd );
|
|
ok( SetThreadDesktop( d2 ), "set thread desktop failed\n" );
|
|
d1 = GetThreadDesktop(GetCurrentThreadId());
|
|
ok( d1 == d2, "GetThreadDesktop did not return set desktop %p/%p\n", d1, d2 );
|
|
print_object( d2 );
|
|
if (arg < (LPVOID)5)
|
|
{
|
|
HANDLE hthread = CreateThread( NULL, 0, thread, (char *)arg + 1, 0, NULL );
|
|
Sleep(1000);
|
|
WaitForSingleObject( hthread, INFINITE );
|
|
CloseHandle( hthread );
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static void test_handles(void)
|
|
{
|
|
HWINSTA w1, w2, w3;
|
|
HDESK d1, d2, d3;
|
|
HANDLE hthread;
|
|
DWORD id, flags;
|
|
ATOM atom;
|
|
char buffer[20];
|
|
|
|
/* win stations */
|
|
|
|
w1 = GetProcessWindowStation();
|
|
ok( GetProcessWindowStation() == w1, "GetProcessWindowStation returned different handles\n" );
|
|
ok( !CloseWindowStation(w1), "closing process win station succeeded\n" );
|
|
SetLastError( 0xdeadbeef );
|
|
ok( !CloseHandle(w1), "closing process win station handle succeeded\n" );
|
|
ok( GetLastError() == ERROR_INVALID_HANDLE, "bad last error %d\n", GetLastError() );
|
|
print_object( w1 );
|
|
|
|
flags = 0;
|
|
ok( GetHandleInformation( w1, &flags ), "GetHandleInformation failed\n" );
|
|
ok( !(flags & HANDLE_FLAG_PROTECT_FROM_CLOSE), "handle %p PROTECT_FROM_CLOSE set\n", w1 );
|
|
|
|
ok( DuplicateHandle( GetCurrentProcess(), w1, GetCurrentProcess(), (PHANDLE)&w2, 0,
|
|
TRUE, DUPLICATE_SAME_ACCESS ), "DuplicateHandle failed\n" );
|
|
ok( CloseWindowStation(w2), "closing dup win station failed\n" );
|
|
|
|
ok( DuplicateHandle( GetCurrentProcess(), w1, GetCurrentProcess(), (PHANDLE)&w2, 0,
|
|
TRUE, DUPLICATE_SAME_ACCESS ), "DuplicateHandle failed\n" );
|
|
ok( CloseHandle(w2), "closing dup win station handle failed\n" );
|
|
|
|
w2 = CreateWindowStation("WinSta0", 0, WINSTA_ALL_ACCESS, NULL );
|
|
ok( w2 != 0, "CreateWindowStation failed\n" );
|
|
ok( w2 != w1, "CreateWindowStation returned default handle\n" );
|
|
SetLastError( 0xdeadbeef );
|
|
ok( !CloseDesktop( (HDESK)w2 ), "CloseDesktop succeeded on win station\n" );
|
|
ok( GetLastError() == ERROR_INVALID_HANDLE, "bad last error %d\n", GetLastError() );
|
|
ok( CloseWindowStation( w2 ), "CloseWindowStation failed\n" );
|
|
|
|
w2 = CreateWindowStation("WinSta0", 0, WINSTA_ALL_ACCESS, NULL );
|
|
ok( CloseHandle( w2 ), "CloseHandle failed\n" );
|
|
|
|
w2 = OpenWindowStation("winsta0", TRUE, WINSTA_ALL_ACCESS );
|
|
ok( w2 != 0, "OpenWindowStation failed\n" );
|
|
ok( w2 != w1, "OpenWindowStation returned default handle\n" );
|
|
ok( CloseWindowStation( w2 ), "CloseWindowStation failed\n" );
|
|
|
|
w2 = OpenWindowStation("dummy name", TRUE, WINSTA_ALL_ACCESS );
|
|
ok( !w2, "open dummy win station succeeded\n" );
|
|
|
|
CreateMutexA( NULL, 0, "foobar" );
|
|
w2 = CreateWindowStation("foobar", 0, WINSTA_ALL_ACCESS, NULL );
|
|
ok( w2 != 0, "create foobar station failed\n" );
|
|
|
|
w3 = OpenWindowStation("foobar", TRUE, WINSTA_ALL_ACCESS );
|
|
ok( w3 != 0, "open foobar station failed\n" );
|
|
ok( w3 != w2, "open foobar station returned same handle\n" );
|
|
ok( CloseWindowStation( w2 ), "CloseWindowStation failed\n" );
|
|
ok( CloseWindowStation( w3 ), "CloseWindowStation failed\n" );
|
|
|
|
w3 = OpenWindowStation("foobar", TRUE, WINSTA_ALL_ACCESS );
|
|
ok( !w3, "open foobar station succeeded\n" );
|
|
|
|
w2 = CreateWindowStation("foobar1", 0, WINSTA_ALL_ACCESS, NULL );
|
|
ok( w2 != 0, "create foobar station failed\n" );
|
|
w3 = CreateWindowStation("foobar2", 0, WINSTA_ALL_ACCESS, NULL );
|
|
ok( w3 != 0, "create foobar station failed\n" );
|
|
ok( GetHandleInformation( w2, &flags ), "GetHandleInformation failed\n" );
|
|
ok( GetHandleInformation( w3, &flags ), "GetHandleInformation failed\n" );
|
|
|
|
SetProcessWindowStation( w2 );
|
|
register_class();
|
|
atom = GlobalAddAtomA("foo");
|
|
ok( GlobalGetAtomNameA( atom, buffer, sizeof(buffer) ) == 3, "GlobalGetAtomName failed\n" );
|
|
ok( !lstrcmpiA( buffer, "foo" ), "bad atom value %s\n", buffer );
|
|
|
|
ok( !CloseWindowStation( w2 ), "CloseWindowStation succeeded\n" );
|
|
ok( GetHandleInformation( w2, &flags ), "GetHandleInformation failed\n" );
|
|
|
|
SetProcessWindowStation( w3 );
|
|
ok( GetHandleInformation( w2, &flags ), "GetHandleInformation failed\n" );
|
|
ok( CloseWindowStation( w2 ), "CloseWindowStation failed\n" );
|
|
ok( GlobalGetAtomNameA( atom, buffer, sizeof(buffer) ) == 3, "GlobalGetAtomName failed\n" );
|
|
ok( !lstrcmpiA( buffer, "foo" ), "bad atom value %s\n", buffer );
|
|
|
|
/* desktops */
|
|
d1 = GetThreadDesktop(GetCurrentThreadId());
|
|
initial_desktop = d1;
|
|
ok( GetThreadDesktop(GetCurrentThreadId()) == d1,
|
|
"GetThreadDesktop returned different handles\n" );
|
|
|
|
flags = 0;
|
|
ok( GetHandleInformation( d1, &flags ), "GetHandleInformation failed\n" );
|
|
ok( !(flags & HANDLE_FLAG_PROTECT_FROM_CLOSE), "handle %p PROTECT_FROM_CLOSE set\n", d1 );
|
|
|
|
SetLastError( 0xdeadbeef );
|
|
ok( !CloseDesktop(d1), "closing thread desktop succeeded\n" );
|
|
ok( GetLastError() == ERROR_BUSY, "bad last error %d\n", GetLastError() );
|
|
|
|
SetLastError( 0xdeadbeef );
|
|
ok( !CloseHandle(d1), "closing thread desktop handle failed\n" );
|
|
ok( GetLastError() == ERROR_INVALID_HANDLE, "bad last error %d\n", GetLastError() );
|
|
|
|
ok( DuplicateHandle( GetCurrentProcess(), d1, GetCurrentProcess(), (PHANDLE)&d2, 0,
|
|
TRUE, DUPLICATE_SAME_ACCESS ), "DuplicateHandle failed\n" );
|
|
ok( CloseDesktop(d2), "closing dup desktop failed\n" );
|
|
|
|
ok( DuplicateHandle( GetCurrentProcess(), d1, GetCurrentProcess(), (PHANDLE)&d2, 0,
|
|
TRUE, DUPLICATE_SAME_ACCESS ), "DuplicateHandle failed\n" );
|
|
ok( CloseHandle(d2), "closing dup desktop handle failed\n" );
|
|
|
|
d2 = OpenDesktop( "dummy name", 0, TRUE, DESKTOP_ALL_ACCESS );
|
|
ok( !d2, "open dummy desktop succeeded\n" );
|
|
|
|
d2 = CreateDesktop( "foobar", NULL, NULL, 0, DESKTOP_ALL_ACCESS, NULL );
|
|
ok( d2 != 0, "create foobar desktop failed\n" );
|
|
SetLastError( 0xdeadbeef );
|
|
ok( !CloseWindowStation( (HWINSTA)d2 ), "CloseWindowStation succeeded on desktop\n" );
|
|
ok( GetLastError() == ERROR_INVALID_HANDLE, "bad last error %d\n", GetLastError() );
|
|
|
|
SetLastError( 0xdeadbeef );
|
|
d3 = CreateDesktop( "foobar", NULL, NULL, 0, DESKTOP_ALL_ACCESS, NULL );
|
|
ok( d3 != 0, "create foobar desktop again failed\n" );
|
|
ok( GetLastError() == 0xdeadbeef, "bad last error %d\n", GetLastError() );
|
|
ok( CloseDesktop( d3 ), "CloseDesktop failed\n" );
|
|
|
|
d3 = OpenDesktop( "foobar", 0, TRUE, DESKTOP_ALL_ACCESS );
|
|
ok( d3 != 0, "open foobar desktop failed\n" );
|
|
ok( d3 != d2, "open foobar desktop returned same handle\n" );
|
|
ok( CloseDesktop( d2 ), "CloseDesktop failed\n" );
|
|
ok( CloseDesktop( d3 ), "CloseDesktop failed\n" );
|
|
|
|
d3 = OpenDesktop( "foobar", 0, TRUE, DESKTOP_ALL_ACCESS );
|
|
ok( !d3, "open foobar desktop succeeded\n" );
|
|
|
|
ok( !CloseHandle(d1), "closing thread desktop handle succeeded\n" );
|
|
d2 = GetThreadDesktop(GetCurrentThreadId());
|
|
ok( d1 == d2, "got different handles after close\n" );
|
|
|
|
trace( "thread 1 desktop: %p\n", d1 );
|
|
print_object( d1 );
|
|
hthread = CreateThread( NULL, 0, thread, (LPVOID)2, 0, &id );
|
|
Sleep(1000);
|
|
trace( "get other thread desktop: %p\n", GetThreadDesktop(id) );
|
|
WaitForSingleObject( hthread, INFINITE );
|
|
CloseHandle( hthread );
|
|
}
|
|
|
|
/* Enumeration tests */
|
|
|
|
static BOOL CALLBACK window_station_callbackA(LPSTR winsta, LPARAM lp)
|
|
{
|
|
trace("window_station_callbackA called with argument %s\n", winsta);
|
|
return lp;
|
|
}
|
|
|
|
static BOOL CALLBACK open_window_station_callbackA(LPSTR winsta, LPARAM lp)
|
|
{
|
|
HWINSTA hwinsta;
|
|
|
|
trace("open_window_station_callbackA called with argument %s\n", winsta);
|
|
hwinsta = OpenWindowStationA(winsta, FALSE, WINSTA_ENUMERATE);
|
|
ok(hwinsta != NULL, "Could not open desktop %s!\n", winsta);
|
|
if (hwinsta)
|
|
CloseWindowStation(hwinsta);
|
|
return lp;
|
|
}
|
|
|
|
static void test_enumstations(void)
|
|
{
|
|
BOOL ret;
|
|
|
|
if (0) /* Crashes instead */
|
|
{
|
|
SetLastError(0xbabefeed);
|
|
ret = EnumWindowStationsA(NULL, 0);
|
|
ok(!ret, "EnumWindowStationsA returned successfully!\n");
|
|
ok(GetLastError() == ERROR_INVALID_PARAMETER, "LastError is set to %08x\n", GetLastError());
|
|
}
|
|
|
|
SetLastError(0xdeadbeef);
|
|
ret = EnumWindowStationsA(open_window_station_callbackA, 0x12345);
|
|
ok(ret == 0x12345, "EnumWindowStationsA returned %x\n", ret);
|
|
ok(GetLastError() == 0xdeadbeef, "LastError is set to %08x\n", GetLastError());
|
|
|
|
SetLastError(0xdeadbeef);
|
|
ret = EnumWindowStationsA(window_station_callbackA, 0);
|
|
ok(!ret, "EnumWindowStationsA returned %x\n", ret);
|
|
ok(GetLastError() == 0xdeadbeef, "LastError is set to %08x\n", GetLastError());
|
|
}
|
|
|
|
static BOOL CALLBACK desktop_callbackA(LPSTR desktop, LPARAM lp)
|
|
{
|
|
trace("desktop_callbackA called with argument %s\n", desktop);
|
|
return lp;
|
|
}
|
|
|
|
static BOOL CALLBACK open_desktop_callbackA(LPSTR desktop, LPARAM lp)
|
|
{
|
|
HDESK hdesk;
|
|
static int once;
|
|
|
|
trace("open_desktop_callbackA called with argument %s\n", desktop);
|
|
/* Only try to open one desktop */
|
|
if (once++)
|
|
return lp;
|
|
|
|
hdesk = OpenDesktopA(desktop, 0, FALSE, DESKTOP_ENUMERATE);
|
|
ok(hdesk != NULL, "Could not open desktop %s!\n", desktop);
|
|
if (hdesk)
|
|
CloseDesktop(hdesk);
|
|
return lp;
|
|
}
|
|
|
|
static void test_enumdesktops(void)
|
|
{
|
|
BOOL ret;
|
|
|
|
if (0) /* Crashes instead */
|
|
{
|
|
SetLastError(0xbabefeed);
|
|
ret = EnumDesktopsA(GetProcessWindowStation(), NULL, 0);
|
|
ok(!ret, "EnumDesktopsA returned successfully!\n");
|
|
ok(GetLastError() == ERROR_INVALID_PARAMETER, "LastError is set to %08x\n", GetLastError());
|
|
}
|
|
|
|
SetLastError(0xdeadbeef);
|
|
ret = EnumDesktopsA(NULL, desktop_callbackA, 0x12345);
|
|
ok(ret == 0x12345, "EnumDesktopsA returned %x\n", ret);
|
|
ok(GetLastError() == 0xdeadbeef, "LastError is set to %08x\n", GetLastError());
|
|
|
|
SetLastError(0xdeadbeef);
|
|
ret = EnumDesktopsA(GetProcessWindowStation(), open_desktop_callbackA, 0x12345);
|
|
ok(ret == 0x12345, "EnumDesktopsA returned %x\n", ret);
|
|
ok(GetLastError() == 0xdeadbeef, "LastError is set to %08x\n", GetLastError());
|
|
|
|
SetLastError(0xdeadbeef);
|
|
ret = EnumDesktopsA(INVALID_HANDLE_VALUE, desktop_callbackA, 0x12345);
|
|
ok(!ret, "EnumDesktopsA returned %x\n", ret);
|
|
ok(GetLastError() == ERROR_INVALID_HANDLE, "LastError is set to %08x\n", GetLastError());
|
|
|
|
SetLastError(0xdeadbeef);
|
|
ret = EnumDesktopsA(GetProcessWindowStation(), desktop_callbackA, 0);
|
|
ok(!ret, "EnumDesktopsA returned %x\n", ret);
|
|
ok(GetLastError() == 0xdeadbeef, "LastError is set to %08x\n", GetLastError());
|
|
}
|
|
|
|
START_TEST(winstation)
|
|
{
|
|
/* Check whether this platform supports WindowStation calls */
|
|
|
|
SetLastError( 0xdeadbeef );
|
|
GetProcessWindowStation();
|
|
if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
|
|
{
|
|
skip("WindowStation calls not supported on this platform\n");
|
|
return;
|
|
}
|
|
|
|
test_enumstations();
|
|
test_enumdesktops();
|
|
test_handles();
|
|
}
|