2 * Unit tests for window stations and desktops
4 * Copyright 2002 Alexandre Julliard
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.
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.
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
21 #include "wine/test.h"
28 static NTSTATUS (WINAPI
*pNtQueryObject
)(HANDLE
, OBJECT_INFORMATION_CLASS
, PVOID
, ULONG
, PULONG
);
30 #define DESKTOP_ALL_ACCESS 0x01ff
32 static void print_object( HANDLE obj
)
37 strcpy( buffer
, "foobar" );
38 if (!GetUserObjectInformationA( obj
, UOI_NAME
, buffer
, sizeof(buffer
), &size
))
39 trace( "could not get info for %p\n", obj
);
41 trace( "obj %p name '%s'\n", obj
, buffer
);
42 strcpy( buffer
, "foobar" );
43 if (!GetUserObjectInformationA( obj
, UOI_TYPE
, buffer
, sizeof(buffer
), &size
))
44 trace( "could not get type for %p\n", obj
);
46 trace( "obj %p type '%s'\n", obj
, buffer
);
49 static void register_class(void)
53 cls
.style
= CS_DBLCLKS
;
54 /* Windows < Vista apparently checks lpfnWndProc against the address of
55 * DefWindowProcA(), and for some reason fails to change the thread desktop
56 * after creating and destroying a window if it doesn't match. Using an IAT
57 * (as is default) or a wrapper triggers this, so use GetProcAddress() as
59 cls
.lpfnWndProc
= (void *)GetProcAddress(GetModuleHandleA("user32"), "DefWindowProcA");
62 cls
.hInstance
= GetModuleHandleA(0);
64 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
65 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
66 cls
.lpszMenuName
= NULL
;
67 cls
.lpszClassName
= "WinStationClass";
71 static HDESK initial_desktop
;
73 static DWORD CALLBACK
thread( LPVOID arg
)
76 HWND hwnd
= CreateWindowExA(0,"WinStationClass","test",WS_POPUP
,0,0,100,100,GetDesktopWindow(),0,0,0);
77 ok( hwnd
!= 0, "CreateWindow failed\n" );
78 d1
= GetThreadDesktop(GetCurrentThreadId());
79 trace( "thread %p desktop: %p\n", arg
, d1
);
80 ok( d1
== initial_desktop
, "thread %p doesn't use initial desktop\n", arg
);
82 SetLastError( 0xdeadbeef );
83 ok( !CloseHandle( d1
), "CloseHandle succeeded\n" );
84 ok( GetLastError() == ERROR_INVALID_HANDLE
, "bad last error %d\n", GetLastError() );
85 SetLastError( 0xdeadbeef );
86 ok( !CloseDesktop( d1
), "CloseDesktop succeeded\n" );
87 ok( GetLastError() == ERROR_BUSY
|| broken(GetLastError() == 0xdeadbeef), /* wow64 */
88 "bad last error %d\n", GetLastError() );
90 d2
= CreateDesktopA( "foobar2", NULL
, NULL
, 0, DESKTOP_ALL_ACCESS
, NULL
);
91 trace( "created desktop %p\n", d2
);
92 ok( d2
!= 0, "CreateDesktop failed\n" );
94 SetLastError( 0xdeadbeef );
95 ok( !SetThreadDesktop( d2
), "set thread desktop succeeded with existing window\n" );
96 ok( GetLastError() == ERROR_BUSY
|| broken(GetLastError() == 0xdeadbeef), /* wow64 */
97 "bad last error %d\n", GetLastError() );
99 DestroyWindow( hwnd
);
100 ok( SetThreadDesktop( d2
), "set thread desktop failed\n" );
101 d1
= GetThreadDesktop(GetCurrentThreadId());
102 ok( d1
== d2
, "GetThreadDesktop did not return set desktop %p/%p\n", d1
, d2
);
106 HANDLE hthread
= CreateThread( NULL
, 0, thread
, (char *)arg
+ 1, 0, NULL
);
108 WaitForSingleObject( hthread
, INFINITE
);
109 CloseHandle( hthread
);
114 static void test_handles(void)
121 char buffer
[29], default_name
[29] = "";
124 TOKEN_STATISTICS token_stats
;
128 w1
= GetProcessWindowStation();
129 ok( GetProcessWindowStation() == w1
, "GetProcessWindowStation returned different handles\n" );
130 ok( !CloseWindowStation(w1
), "closing process win station succeeded\n" );
131 SetLastError( 0xdeadbeef );
132 ok( !CloseHandle(w1
), "closing process win station handle succeeded\n" );
133 ok( GetLastError() == ERROR_INVALID_HANDLE
, "bad last error %d\n", GetLastError() );
137 ok( GetHandleInformation( w1
, &flags
), "GetHandleInformation failed\n" );
138 ok( !(flags
& HANDLE_FLAG_PROTECT_FROM_CLOSE
) ||
139 broken(flags
& HANDLE_FLAG_PROTECT_FROM_CLOSE
), /* set on nt4 */
140 "handle %p PROTECT_FROM_CLOSE set\n", w1
);
142 ok( DuplicateHandle( GetCurrentProcess(), w1
, GetCurrentProcess(), (PHANDLE
)&w2
, 0,
143 TRUE
, DUPLICATE_SAME_ACCESS
), "DuplicateHandle failed\n" );
144 ok( CloseWindowStation(w2
), "closing dup win station failed\n" );
146 ok( DuplicateHandle( GetCurrentProcess(), w1
, GetCurrentProcess(), (PHANDLE
)&w2
, 0,
147 TRUE
, DUPLICATE_SAME_ACCESS
), "DuplicateHandle failed\n" );
148 ok( CloseHandle(w2
), "closing dup win station handle failed\n" );
150 w2
= CreateWindowStationA("WinSta0", 0, WINSTA_ALL_ACCESS
, NULL
);
152 ok( w2
!= 0 || le
== ERROR_ACCESS_DENIED
, "CreateWindowStation failed (%u)\n", le
);
155 ok( w2
!= w1
, "CreateWindowStation returned default handle\n" );
156 SetLastError( 0xdeadbeef );
157 ok( !CloseDesktop( (HDESK
)w2
), "CloseDesktop succeeded on win station\n" );
158 ok( GetLastError() == ERROR_INVALID_HANDLE
|| broken(GetLastError() == 0xdeadbeef), /* wow64 */
159 "bad last error %d\n", GetLastError() );
160 ok( CloseWindowStation( w2
), "CloseWindowStation failed\n" );
162 w2
= CreateWindowStationA("WinSta0", 0, WINSTA_ALL_ACCESS
, NULL
);
163 ok( CloseHandle( w2
), "CloseHandle failed\n" );
165 else if (le
== ERROR_ACCESS_DENIED
)
166 win_skip( "Not enough privileges for CreateWindowStation\n" );
168 w2
= OpenWindowStationA("winsta0", TRUE
, WINSTA_ALL_ACCESS
);
169 ok( w2
!= 0, "OpenWindowStation failed\n" );
170 ok( w2
!= w1
, "OpenWindowStation returned default handle\n" );
171 ok( CloseWindowStation( w2
), "CloseWindowStation failed\n" );
173 w2
= OpenWindowStationA("dummy name", TRUE
, WINSTA_ALL_ACCESS
);
174 ok( !w2
, "open dummy win station succeeded\n" );
176 CreateMutexA( NULL
, 0, "foobar" );
177 w2
= CreateWindowStationA("foobar", 0, WINSTA_ALL_ACCESS
, NULL
);
179 ok( w2
!= 0 || le
== ERROR_ACCESS_DENIED
, "create foobar station failed (%u)\n", le
);
183 w3
= OpenWindowStationA("foobar", TRUE
, WINSTA_ALL_ACCESS
);
184 ok( w3
!= 0, "open foobar station failed\n" );
185 ok( w3
!= w2
, "open foobar station returned same handle\n" );
186 ok( CloseWindowStation( w2
), "CloseWindowStation failed\n" );
187 ok( CloseWindowStation( w3
), "CloseWindowStation failed\n" );
189 w3
= OpenWindowStationA("foobar", TRUE
, WINSTA_ALL_ACCESS
);
190 ok( !w3
, "open foobar station succeeded\n" );
192 w2
= CreateWindowStationA("foobar1", 0, WINSTA_ALL_ACCESS
, NULL
);
193 ok( w2
!= 0, "create foobar station failed\n" );
194 w3
= CreateWindowStationA("foobar2", 0, WINSTA_ALL_ACCESS
, NULL
);
195 ok( w3
!= 0, "create foobar station failed\n" );
196 ok( GetHandleInformation( w2
, &flags
), "GetHandleInformation failed\n" );
197 ok( GetHandleInformation( w3
, &flags
), "GetHandleInformation failed\n" );
199 SetProcessWindowStation( w2
);
200 atom
= GlobalAddAtomA("foo");
201 ok( GlobalGetAtomNameA( atom
, buffer
, sizeof(buffer
) ) == 3, "GlobalGetAtomName failed\n" );
202 ok( !lstrcmpiA( buffer
, "foo" ), "bad atom value %s\n", buffer
);
204 ok( !CloseWindowStation( w2
), "CloseWindowStation succeeded\n" );
205 ok( GetHandleInformation( w2
, &flags
), "GetHandleInformation failed\n" );
207 SetProcessWindowStation( w3
);
208 ok( GetHandleInformation( w2
, &flags
), "GetHandleInformation failed\n" );
209 ok( CloseWindowStation( w2
), "CloseWindowStation failed\n" );
210 ok( GlobalGetAtomNameA( atom
, buffer
, sizeof(buffer
) ) == 3, "GlobalGetAtomName failed\n" );
211 ok( !lstrcmpiA( buffer
, "foo" ), "bad atom value %s\n", buffer
);
213 else if (le
== ERROR_ACCESS_DENIED
)
214 win_skip( "Not enough privileges for CreateWindowStation\n" );
216 SetLastError( 0xdeadbeef );
217 w2
= OpenWindowStationA( "", TRUE
, WINSTA_ALL_ACCESS
);
218 ok( !w2
, "open station succeeded\n" );
219 ok( GetLastError() == ERROR_FILE_NOT_FOUND
, "wrong error %u\n", GetLastError() );
221 SetLastError( 0xdeadbeef );
222 w2
= CreateWindowStationA( "", 0, WINSTA_ALL_ACCESS
, NULL
);
223 ok( w2
!= 0, "create station failed err %u\n", GetLastError() );
225 memset( buffer
, 0, sizeof(buffer
) );
226 ret
= GetUserObjectInformationA( w2
, UOI_NAME
, buffer
, sizeof(buffer
), &size
);
227 ok( ret
, "GetUserObjectInformationA failed with error %u\n", GetLastError() );
228 /* Get the logon session LUID */
229 ret
= GetTokenInformation( GetCurrentProcessToken(), TokenStatistics
, &token_stats
, sizeof(token_stats
), NULL
);
231 sprintf( default_name
, "Service-0x%x-%x$", token_stats
.AuthenticationId
.HighPart
,
232 token_stats
.AuthenticationId
.LowPart
);
234 ok( !strcmp( buffer
, default_name
), "unexpected window station name '%s' expected '%s'\n", buffer
, default_name
);
236 SetLastError( 0xdeadbeef );
237 w3
= OpenWindowStationA( "", TRUE
, WINSTA_ALL_ACCESS
);
238 ok( w3
!= 0, "open station failed err %u\n", GetLastError() );
239 CloseWindowStation( w3
);
240 CloseWindowStation( w2
);
242 w2
= CreateWindowStationA( NULL
, 0, WINSTA_ALL_ACCESS
, NULL
);
243 ok( w2
!= 0, "create station failed err %u\n", GetLastError() );
245 memset( buffer
, 0, sizeof(buffer
) );
246 ret
= GetUserObjectInformationA( w2
, UOI_NAME
, buffer
, sizeof(buffer
), &size
);
247 ok( ret
, "GetUserObjectInformationA failed with error %u\n", GetLastError() );
249 ok( !strcmp( buffer
, default_name
), "unexpected window station name '%s' expected '%s'\n", buffer
, default_name
);
250 CloseWindowStation( w2
);
252 SetLastError( 0xdeadbeef );
253 w2
= CreateWindowStationA( "foo\\bar", 0, WINSTA_ALL_ACCESS
, NULL
);
254 ok( !w2
, "create station succeeded\n" );
255 ok( GetLastError() == ERROR_PATH_NOT_FOUND
|| GetLastError() == ERROR_ACCESS_DENIED
,
256 "wrong error %u\n", GetLastError() );
258 SetLastError( 0xdeadbeef );
259 w2
= OpenWindowStationA( "foo\\bar", TRUE
, WINSTA_ALL_ACCESS
);
260 ok( !w2
, "create station succeeded\n" );
261 ok( GetLastError() == ERROR_PATH_NOT_FOUND
, "wrong error %u\n", GetLastError() );
264 d1
= GetThreadDesktop(GetCurrentThreadId());
265 initial_desktop
= d1
;
266 ok( GetThreadDesktop(GetCurrentThreadId()) == d1
,
267 "GetThreadDesktop returned different handles\n" );
270 ok( GetHandleInformation( d1
, &flags
), "GetHandleInformation failed\n" );
271 ok( !(flags
& HANDLE_FLAG_PROTECT_FROM_CLOSE
), "handle %p PROTECT_FROM_CLOSE set\n", d1
);
273 SetLastError( 0xdeadbeef );
274 ok( !CloseDesktop(d1
), "closing thread desktop succeeded\n" );
275 ok( GetLastError() == ERROR_BUSY
|| broken(GetLastError() == 0xdeadbeef), /* wow64 */
276 "bad last error %d\n", GetLastError() );
278 SetLastError( 0xdeadbeef );
279 if (CloseHandle( d1
)) /* succeeds on nt4 */
281 win_skip( "NT4 desktop handle management is completely different\n" );
284 ok( GetLastError() == ERROR_INVALID_HANDLE
, "bad last error %d\n", GetLastError() );
286 ok( DuplicateHandle( GetCurrentProcess(), d1
, GetCurrentProcess(), (PHANDLE
)&d2
, 0,
287 TRUE
, DUPLICATE_SAME_ACCESS
), "DuplicateHandle failed\n" );
288 ok( CloseDesktop(d2
), "closing dup desktop failed\n" );
290 ok( DuplicateHandle( GetCurrentProcess(), d1
, GetCurrentProcess(), (PHANDLE
)&d2
, 0,
291 TRUE
, DUPLICATE_SAME_ACCESS
), "DuplicateHandle failed\n" );
292 ok( CloseHandle(d2
), "closing dup desktop handle failed\n" );
294 d2
= OpenDesktopA( "dummy name", 0, TRUE
, DESKTOP_ALL_ACCESS
);
295 ok( !d2
, "open dummy desktop succeeded\n" );
297 SetLastError( 0xdeadbeef );
298 d2
= CreateDesktopA( "", NULL
, NULL
, 0, DESKTOP_ALL_ACCESS
, NULL
);
299 ok( !d2
, "create empty desktop succeeded\n" );
300 ok( GetLastError() == ERROR_INVALID_HANDLE
, "wrong error %u\n", GetLastError() );
302 SetLastError( 0xdeadbeef );
303 d2
= OpenDesktopA( "", 0, TRUE
, DESKTOP_ALL_ACCESS
);
304 ok( !d2
, "open empty desktop succeeded\n" );
305 ok( GetLastError() == ERROR_INVALID_HANDLE
, "wrong error %u\n", GetLastError() );
307 SetLastError( 0xdeadbeef );
308 d2
= CreateDesktopA( "foo\\bar", NULL
, NULL
, 0, DESKTOP_ALL_ACCESS
, NULL
);
309 ok( !d2
, "create desktop succeeded\n" );
310 ok( GetLastError() == ERROR_BAD_PATHNAME
, "wrong error %u\n", GetLastError() );
312 SetLastError( 0xdeadbeef );
313 d2
= OpenDesktopA( "foo\\bar", 0, TRUE
, DESKTOP_ALL_ACCESS
);
314 ok( !d2
, "open desktop succeeded\n" );
315 ok( GetLastError() == ERROR_BAD_PATHNAME
, "wrong error %u\n", GetLastError() );
317 d2
= CreateDesktopA( "foobar", NULL
, NULL
, 0, DESKTOP_ALL_ACCESS
, NULL
);
318 ok( d2
!= 0, "create foobar desktop failed\n" );
319 SetLastError( 0xdeadbeef );
320 ok( !CloseWindowStation( (HWINSTA
)d2
), "CloseWindowStation succeeded on desktop\n" );
321 ok( GetLastError() == ERROR_INVALID_HANDLE
|| broken(GetLastError() == 0xdeadbeef), /* wow64 */
322 "bad last error %d\n", GetLastError() );
324 SetLastError( 0xdeadbeef );
325 d3
= CreateDesktopA( "foobar", NULL
, NULL
, 0, DESKTOP_ALL_ACCESS
, NULL
);
326 ok( d3
!= 0, "create foobar desktop again failed\n" );
327 ok( GetLastError() == 0xdeadbeef, "bad last error %d\n", GetLastError() );
328 ok( CloseDesktop( d3
), "CloseDesktop failed\n" );
330 d3
= OpenDesktopA( "foobar", 0, TRUE
, DESKTOP_ALL_ACCESS
);
331 ok( d3
!= 0, "open foobar desktop failed\n" );
332 ok( d3
!= d2
, "open foobar desktop returned same handle\n" );
333 ok( CloseDesktop( d2
), "CloseDesktop failed\n" );
334 ok( CloseDesktop( d3
), "CloseDesktop failed\n" );
336 d3
= OpenDesktopA( "foobar", 0, TRUE
, DESKTOP_ALL_ACCESS
);
337 ok( !d3
, "open foobar desktop succeeded\n" );
339 ok( !CloseHandle(d1
), "closing thread desktop handle succeeded\n" );
340 d2
= GetThreadDesktop(GetCurrentThreadId());
341 ok( d1
== d2
, "got different handles after close\n" );
344 trace( "thread 1 desktop: %p\n", d1
);
346 hthread
= CreateThread( NULL
, 0, thread
, (LPVOID
)2, 0, &id
);
348 trace( "get other thread desktop: %p\n", GetThreadDesktop(id
) );
349 WaitForSingleObject( hthread
, INFINITE
);
350 CloseHandle( hthread
);
352 /* clean side effect */
353 SetProcessWindowStation( w1
);
356 /* Enumeration tests */
358 static BOOL CALLBACK
window_station_callbackA(LPSTR winsta
, LPARAM lp
)
360 trace("window_station_callbackA called with argument %s\n", winsta
);
364 static BOOL CALLBACK
open_window_station_callbackA(LPSTR winsta
, LPARAM lp
)
368 trace("open_window_station_callbackA called with argument %s\n", winsta
);
369 hwinsta
= OpenWindowStationA(winsta
, FALSE
, WINSTA_ENUMERATE
);
370 ok(hwinsta
!= NULL
, "Could not open desktop %s!\n", winsta
);
372 CloseWindowStation(hwinsta
);
376 static void test_enumstations(void)
381 if (0) /* Crashes instead */
383 SetLastError(0xbabefeed);
384 ret
= EnumWindowStationsA(NULL
, 0);
385 ok(!ret
, "EnumWindowStationsA returned successfully!\n");
386 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "LastError is set to %08x\n", GetLastError());
389 hwinsta
= CreateWindowStationA("winsta_test", 0, WINSTA_ALL_ACCESS
, NULL
);
390 ret
= GetLastError();
391 ok(hwinsta
!= NULL
|| ret
== ERROR_ACCESS_DENIED
, "CreateWindowStation failed (%u)\n", ret
);
394 win_skip("Not enough privileges for CreateWindowStation\n");
398 SetLastError(0xdeadbeef);
399 ret
= EnumWindowStationsA(open_window_station_callbackA
, 0x12345);
400 ok(ret
== 0x12345, "EnumWindowStationsA returned %x\n", ret
);
401 ok(GetLastError() == 0xdeadbeef, "LastError is set to %08x\n", GetLastError());
403 SetLastError(0xdeadbeef);
404 ret
= EnumWindowStationsA(window_station_callbackA
, 0);
405 ok(!ret
, "EnumWindowStationsA returned %x\n", ret
);
406 ok(GetLastError() == 0xdeadbeef, "LastError is set to %08x\n", GetLastError());
409 static BOOL CALLBACK
desktop_callbackA(LPSTR desktop
, LPARAM lp
)
411 trace("desktop_callbackA called with argument %s\n", desktop
);
415 static BOOL CALLBACK
open_desktop_callbackA(LPSTR desktop
, LPARAM lp
)
420 trace("open_desktop_callbackA called with argument %s\n", desktop
);
421 /* Only try to open one desktop */
425 hdesk
= OpenDesktopA(desktop
, 0, FALSE
, DESKTOP_ENUMERATE
);
426 ok(hdesk
!= NULL
, "Could not open desktop %s!\n", desktop
);
432 static void test_enumdesktops(void)
436 if (0) /* Crashes instead */
438 SetLastError(0xbabefeed);
439 ret
= EnumDesktopsA(GetProcessWindowStation(), NULL
, 0);
440 ok(!ret
, "EnumDesktopsA returned successfully!\n");
441 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "LastError is set to %08x\n", GetLastError());
444 SetLastError(0xdeadbeef);
445 ret
= EnumDesktopsA(NULL
, desktop_callbackA
, 0x12345);
446 ok(ret
== 0x12345, "EnumDesktopsA returned %x\n", ret
);
447 ok(GetLastError() == 0xdeadbeef, "LastError is set to %08x\n", GetLastError());
449 SetLastError(0xdeadbeef);
450 ret
= EnumDesktopsA(GetProcessWindowStation(), open_desktop_callbackA
, 0x12345);
451 ok(ret
== 0x12345, "EnumDesktopsA returned %x\n", ret
);
452 ok(GetLastError() == 0xdeadbeef, "LastError is set to %08x\n", GetLastError());
454 SetLastError(0xdeadbeef);
455 ret
= EnumDesktopsA(INVALID_HANDLE_VALUE
, desktop_callbackA
, 0x12345);
456 ok(!ret
, "EnumDesktopsA returned %x\n", ret
);
457 ok(GetLastError() == ERROR_INVALID_HANDLE
, "LastError is set to %08x\n", GetLastError());
459 SetLastError(0xdeadbeef);
460 ret
= EnumDesktopsA(GetProcessWindowStation(), desktop_callbackA
, 0);
461 ok(!ret
, "EnumDesktopsA returned %x\n", ret
);
462 ok(GetLastError() == 0xdeadbeef, "LastError is set to %08x\n", GetLastError());
465 /* Miscellaneous tests */
467 static void test_getuserobjectinformation(void)
469 WCHAR foobarTestW
[] = {'\\','f','o','o','b','a','r','T','e','s','t',0};
470 WCHAR DesktopW
[] = {'D','e','s','k','t','o','p',0};
471 OBJECT_NAME_INFORMATION
*name_info
;
479 desk
= CreateDesktopA("foobarTest", NULL
, NULL
, 0, DESKTOP_ALL_ACCESS
, NULL
);
480 ok(desk
!= 0, "open foobarTest desktop failed\n");
482 strcpy(buffer
, "blahblah");
484 /** Tests for UOI_NAME **/
486 /* Get size, test size and return value/error code */
487 SetLastError(0xdeadbeef);
489 ret
= GetUserObjectInformationA(desk
, UOI_NAME
, NULL
, 0, &size
);
491 ok(!ret
, "GetUserObjectInformationA returned %x\n", ret
);
492 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
, "LastError is set to %08x\n", GetLastError());
493 ok(size
== 22, "size is set to %d\n", size
); /* Windows returns Unicode length (11*2) */
496 SetLastError(0xdeadbeef);
498 ret
= GetUserObjectInformationA(desk
, UOI_NAME
, buffer
, sizeof(buffer
), &size
);
500 ok(ret
, "GetUserObjectInformationA returned %x\n", ret
);
501 ok(GetLastError() == 0xdeadbeef, "LastError is set to %08x\n", GetLastError());
503 ok(strcmp(buffer
, "foobarTest") == 0, "Buffer is set to '%s'\n", buffer
);
504 ok(size
== 11, "size is set to %d\n", size
); /* 11 bytes in 'foobarTest\0' */
506 /* Get size, test size and return value/error code (Unicode) */
507 SetLastError(0xdeadbeef);
509 ret
= GetUserObjectInformationW(desk
, UOI_NAME
, NULL
, 0, &size
);
511 ok(!ret
, "GetUserObjectInformationW returned %x\n", ret
);
512 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
, "LastError is set to %08x\n", GetLastError());
513 ok(size
== 22, "size is set to %d\n", size
); /* 22 bytes in 'foobarTest\0' in Unicode */
515 /* Get string (Unicode) */
516 SetLastError(0xdeadbeef);
518 ret
= GetUserObjectInformationW(desk
, UOI_NAME
, bufferW
, sizeof(bufferW
), &size
);
520 ok(ret
, "GetUserObjectInformationW returned %x\n", ret
);
521 ok(GetLastError() == 0xdeadbeef, "LastError is set to %08x\n", GetLastError());
523 ok(lstrcmpW(bufferW
, foobarTestW
+ 1) == 0, "Buffer is not set to 'foobarTest'\n");
524 ok(size
== 22, "size is set to %d\n", size
); /* 22 bytes in 'foobarTest\0' in Unicode */
526 /* ObjectNameInformation does not return the full desktop name */
527 name_info
= (OBJECT_NAME_INFORMATION
*)buffer
;
528 status
= pNtQueryObject(desk
, ObjectNameInformation
, name_info
, sizeof(buffer
), NULL
);
529 ok(!status
, "expected STATUS_SUCCESS, got %08x\n", status
);
530 ok(lstrcmpW(name_info
->Name
.Buffer
, foobarTestW
) == 0,
531 "expected '\\foobarTest', got %s\n", wine_dbgstr_w(name_info
->Name
.Buffer
));
533 /** Tests for UOI_TYPE **/
535 /* Get size, test size and return value/error code */
536 SetLastError(0xdeadbeef);
538 ret
= GetUserObjectInformationA(desk
, UOI_TYPE
, NULL
, 0, &size
);
540 ok(!ret
, "GetUserObjectInformationA returned %x\n", ret
);
541 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
, "LastError is set to %08x\n", GetLastError());
542 ok(size
== 16, "size is set to %d\n", size
); /* Windows returns Unicode length (8*2) */
545 SetLastError(0xdeadbeef);
547 ret
= GetUserObjectInformationA(desk
, UOI_TYPE
, buffer
, sizeof(buffer
), &size
);
549 ok(ret
, "GetUserObjectInformationA returned %x\n", ret
);
550 ok(GetLastError() == 0xdeadbeef, "LastError is set to %08x\n", GetLastError());
552 ok(strcmp(buffer
, "Desktop") == 0, "Buffer is set to '%s'\n", buffer
);
553 ok(size
== 8, "size is set to %d\n", size
); /* 8 bytes in 'Desktop\0' */
555 /* Get size, test size and return value/error code (Unicode) */
557 SetLastError(0xdeadbeef);
558 ret
= GetUserObjectInformationW(desk
, UOI_TYPE
, NULL
, 0, &size
);
560 ok(!ret
, "GetUserObjectInformationW returned %x\n", ret
);
561 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER
, "LastError is set to %08x\n", GetLastError());
562 ok(size
== 16, "size is set to %d\n", size
); /* 16 bytes in 'Desktop\0' in Unicode */
564 /* Get string (Unicode) */
565 SetLastError(0xdeadbeef);
567 ret
= GetUserObjectInformationW(desk
, UOI_TYPE
, bufferW
, sizeof(bufferW
), &size
);
569 ok(ret
, "GetUserObjectInformationW returned %x\n", ret
);
570 ok(GetLastError() == 0xdeadbeef, "LastError is set to %08x\n", GetLastError());
572 ok(lstrcmpW(bufferW
, DesktopW
) == 0, "Buffer is not set to 'Desktop'\n");
573 ok(size
== 16, "size is set to %d\n", size
); /* 16 bytes in 'Desktop\0' in Unicode */
575 ok(CloseDesktop(desk
), "CloseDesktop failed\n");
578 static void test_inputdesktop(void)
580 HDESK input_desk
, old_input_desk
, thread_desk
, old_thread_desk
, new_desk
;
585 inputs
[0].type
= INPUT_KEYBOARD
;
586 U(inputs
[0]).ki
.wVk
= 0;
587 U(inputs
[0]).ki
.wScan
= 0x3c0;
588 U(inputs
[0]).ki
.dwFlags
= KEYEVENTF_UNICODE
;
590 /* OpenInputDesktop creates new handles for each calls */
591 old_input_desk
= OpenInputDesktop(0, FALSE
, DESKTOP_ALL_ACCESS
);
592 ok(old_input_desk
!= NULL
, "OpenInputDesktop failed!\n");
593 memset(name
, 0, sizeof(name
));
594 ret
= GetUserObjectInformationA(old_input_desk
, UOI_NAME
, name
, 1024, NULL
);
595 ok(ret
, "GetUserObjectInformation failed!\n");
596 ok(!strcmp(name
, "Default"), "unexpected desktop %s\n", name
);
598 input_desk
= OpenInputDesktop(0, FALSE
, DESKTOP_ALL_ACCESS
);
599 ok(input_desk
!= NULL
, "OpenInputDesktop failed!\n");
600 memset(name
, 0, sizeof(name
));
601 ret
= GetUserObjectInformationA(input_desk
, UOI_NAME
, name
, 1024, NULL
);
602 ok(ret
, "GetUserObjectInformation failed!\n");
603 ok(!strcmp(name
, "Default"), "unexpected desktop %s\n", name
);
605 ok(old_input_desk
!= input_desk
, "returned the same handle!\n");
606 ret
= CloseDesktop(input_desk
);
607 ok(ret
, "CloseDesktop failed!\n");
609 /* by default, GetThreadDesktop is the input desktop, SendInput should succeed. */
610 old_thread_desk
= GetThreadDesktop(GetCurrentThreadId());
611 ok(old_thread_desk
!= NULL
, "GetThreadDesktop failed!\n");
612 memset(name
, 0, sizeof(name
));
613 ret
= GetUserObjectInformationA(old_thread_desk
, UOI_NAME
, name
, 1024, NULL
);
614 ok(!strcmp(name
, "Default"), "unexpected desktop %s\n", name
);
616 SetLastError(0xdeadbeef);
617 ret
= SendInput(1, inputs
, sizeof(INPUT
));
618 ok(GetLastError() == 0xdeadbeef, "unexpected last error %08x\n", GetLastError());
619 ok(ret
== 1, "unexpected return count %d\n", ret
);
621 /* Set thread desktop to the new desktop, SendInput should fail. */
622 new_desk
= CreateDesktopA("new_desk", NULL
, NULL
, 0, DESKTOP_ALL_ACCESS
, NULL
);
623 ok(new_desk
!= NULL
, "CreateDesktop failed!\n");
624 ret
= SetThreadDesktop(new_desk
);
625 ok(ret
, "SetThreadDesktop failed!\n");
626 thread_desk
= GetThreadDesktop(GetCurrentThreadId());
627 ok(thread_desk
== new_desk
, "thread desktop doesn't match!\n");
628 memset(name
, 0, sizeof(name
));
629 ret
= GetUserObjectInformationA(thread_desk
, UOI_NAME
, name
, 1024, NULL
);
630 ok(!strcmp(name
, "new_desk"), "unexpected desktop %s\n", name
);
632 SetLastError(0xdeadbeef);
633 ret
= SendInput(1, inputs
, sizeof(INPUT
));
634 if(broken(GetLastError() == 0xdeadbeef))
636 SetThreadDesktop(old_thread_desk
);
637 CloseDesktop(old_input_desk
);
638 CloseDesktop(input_desk
);
639 CloseDesktop(new_desk
);
640 win_skip("Skip tests on NT4\n");
644 ok(GetLastError() == ERROR_ACCESS_DENIED
, "unexpected last error %08x\n", GetLastError());
645 ok(ret
== 1 || broken(ret
== 0) /* Win64 */, "unexpected return count %d\n", ret
);
647 /* Set thread desktop back to the old thread desktop, SendInput should success. */
648 ret
= SetThreadDesktop(old_thread_desk
);
649 ok(ret
, "SetThreadDesktop failed!\n");
650 thread_desk
= GetThreadDesktop(GetCurrentThreadId());
651 ok(thread_desk
== old_thread_desk
, "thread desktop doesn't match!\n");
652 memset(name
, 0, sizeof(name
));
653 ret
= GetUserObjectInformationA(thread_desk
, UOI_NAME
, name
, 1024, NULL
);
654 ok(!strcmp(name
, "Default"), "unexpected desktop %s\n", name
);
656 SetLastError(0xdeadbeef);
657 ret
= SendInput(1, inputs
, sizeof(INPUT
));
658 ok(GetLastError() == 0xdeadbeef, "unexpected last error %08x\n", GetLastError());
659 ok(ret
== 1, "unexpected return count %d\n", ret
);
661 /* Set thread desktop to the input desktop, SendInput should success. */
662 ret
= SetThreadDesktop(old_input_desk
);
663 ok(ret
, "SetThreadDesktop failed!\n");
664 thread_desk
= GetThreadDesktop(GetCurrentThreadId());
665 ok(thread_desk
== old_input_desk
, "thread desktop doesn't match!\n");
666 memset(name
, 0, sizeof(name
));
667 ret
= GetUserObjectInformationA(thread_desk
, UOI_NAME
, name
, 1024, NULL
);
668 ok(!strcmp(name
, "Default"), "unexpected desktop %s\n", name
);
670 SetLastError(0xdeadbeef);
671 ret
= SendInput(1, inputs
, sizeof(INPUT
));
672 ok(GetLastError() == 0xdeadbeef, "unexpected last error %08x\n", GetLastError());
673 ok(ret
== 1, "unexpected return count %d\n", ret
);
675 /* Switch input desktop to the new desktop, SendInput should fail. */
676 ret
= SwitchDesktop(new_desk
);
677 ok(ret
, "SwitchDesktop failed!\n");
678 input_desk
= OpenInputDesktop(0, FALSE
, DESKTOP_ALL_ACCESS
);
679 ok(input_desk
!= NULL
, "OpenInputDesktop failed!\n");
680 ok(input_desk
!= new_desk
, "returned the same handle!\n");
681 memset(name
, 0, sizeof(name
));
682 ret
= GetUserObjectInformationA(input_desk
, UOI_NAME
, name
, 1024, NULL
);
683 ok(ret
, "GetUserObjectInformation failed!\n");
685 ok(!strcmp(name
, "new_desk"), "unexpected desktop %s\n", name
);
686 ret
= CloseDesktop(input_desk
);
687 ok(ret
, "CloseDesktop failed!\n");
689 SetLastError(0xdeadbeef);
690 ret
= SendInput(1, inputs
, sizeof(INPUT
));
692 ok(GetLastError() == ERROR_ACCESS_DENIED
, "unexpected last error %08x\n", GetLastError());
693 ok(ret
== 1 || broken(ret
== 0) /* Win64 */, "unexpected return count %d\n", ret
);
695 /* Set thread desktop to the new desktop, SendInput should success. */
696 ret
= SetThreadDesktop(new_desk
);
697 ok(ret
, "SetThreadDesktop failed!\n");
698 thread_desk
= GetThreadDesktop(GetCurrentThreadId());
699 ok(thread_desk
== new_desk
, "thread desktop doesn't match!\n");
700 memset(name
, 0, sizeof(name
));
701 ret
= GetUserObjectInformationA(thread_desk
, UOI_NAME
, name
, 1024, NULL
);
702 ok(!strcmp(name
, "new_desk"), "unexpected desktop %s\n", name
);
704 SetLastError(0xdeadbeef);
705 ret
= SendInput(1, inputs
, sizeof(INPUT
));
706 ok(GetLastError() == 0xdeadbeef, "unexpected last error %08x\n", GetLastError());
707 ok(ret
== 1, "unexpected return count %d\n", ret
);
709 /* Switch input desktop to the old input desktop, set thread desktop to the old
710 * thread desktop, clean side effects. SendInput should success. */
711 ret
= SwitchDesktop(old_input_desk
);
712 input_desk
= OpenInputDesktop(0, FALSE
, DESKTOP_ALL_ACCESS
);
713 ok(input_desk
!= NULL
, "OpenInputDesktop failed!\n");
714 ok(input_desk
!= old_input_desk
, "returned the same handle!\n");
715 memset(name
, 0, sizeof(name
));
716 ret
= GetUserObjectInformationA(input_desk
, UOI_NAME
, name
, 1024, NULL
);
717 ok(ret
, "GetUserObjectInformation failed!\n");
718 ok(!strcmp(name
, "Default"), "unexpected desktop %s\n", name
);
720 ret
= SetThreadDesktop(old_thread_desk
);
721 ok(ret
, "SetThreadDesktop failed!\n");
722 thread_desk
= GetThreadDesktop(GetCurrentThreadId());
723 ok(thread_desk
== old_thread_desk
, "thread desktop doesn't match!\n");
724 memset(name
, 0, sizeof(name
));
725 ret
= GetUserObjectInformationA(thread_desk
, UOI_NAME
, name
, 1024, NULL
);
726 ok(!strcmp(name
, "Default"), "unexpected desktop %s\n", name
);
728 SetLastError(0xdeadbeef);
729 ret
= SendInput(1, inputs
, sizeof(INPUT
));
730 ok(GetLastError() == 0xdeadbeef, "unexpected last error %08x\n", GetLastError());
731 ok(ret
== 1, "unexpected return count %d\n", ret
);
734 ret
= CloseDesktop(input_desk
);
735 ok(ret
, "CloseDesktop failed!\n");
736 ret
= CloseDesktop(old_input_desk
);
737 ok(ret
, "CloseDesktop failed!\n");
738 ret
= CloseDesktop(new_desk
);
739 ok(ret
, "CloseDesktop failed!\n");
742 static void test_inputdesktop2(void)
745 HDESK thread_desk
, new_desk
, input_desk
, hdesk
;
748 thread_desk
= GetThreadDesktop(GetCurrentThreadId());
749 ok(thread_desk
!= NULL
, "GetThreadDesktop failed!\n");
750 w1
= GetProcessWindowStation();
751 ok(w1
!= NULL
, "GetProcessWindowStation failed!\n");
752 SetLastError(0xdeadbeef);
753 w2
= CreateWindowStationA("winsta_test", 0, WINSTA_ALL_ACCESS
, NULL
);
754 ret
= GetLastError();
755 ok(w2
!= NULL
|| ret
== ERROR_ACCESS_DENIED
, "CreateWindowStation failed (%u)\n", ret
);
758 win_skip("Not enough privileges for CreateWindowStation\n");
762 ret
= EnumDesktopsA(GetProcessWindowStation(), desktop_callbackA
, 0);
763 ok(!ret
, "EnumDesktopsA failed!\n");
764 input_desk
= OpenInputDesktop(0, FALSE
, DESKTOP_ALL_ACCESS
);
765 ok(input_desk
!= NULL
, "OpenInputDesktop failed!\n");
766 ret
= CloseDesktop(input_desk
);
767 ok(ret
, "CloseDesktop failed!\n");
769 ret
= SetProcessWindowStation(w2
);
770 ok(ret
, "SetProcessWindowStation failed!\n");
771 hdesk
= GetThreadDesktop(GetCurrentThreadId());
772 ok(hdesk
!= NULL
, "GetThreadDesktop failed!\n");
773 ok(hdesk
== thread_desk
, "thread desktop should not change after winstation changed!\n");
774 ret
= EnumDesktopsA(GetProcessWindowStation(), desktop_callbackA
, 0);
776 new_desk
= CreateDesktopA("desk_test", NULL
, NULL
, 0, DESKTOP_ALL_ACCESS
, NULL
);
777 ok(new_desk
!= NULL
, "CreateDesktop failed!\n");
778 ret
= EnumDesktopsA(GetProcessWindowStation(), desktop_callbackA
, 0);
779 ok(!ret
, "EnumDesktopsA failed!\n");
780 SetLastError(0xdeadbeef);
781 input_desk
= OpenInputDesktop(0, FALSE
, DESKTOP_ALL_ACCESS
);
782 ok(input_desk
== NULL
, "OpenInputDesktop should fail on non default winstation!\n");
783 ok(GetLastError() == ERROR_INVALID_FUNCTION
|| broken(GetLastError() == 0xdeadbeef), "last error %08x\n", GetLastError());
785 hdesk
= OpenDesktopA("desk_test", 0, TRUE
, DESKTOP_ALL_ACCESS
);
786 ok(hdesk
!= NULL
, "OpenDesktop failed!\n");
787 SetLastError(0xdeadbeef);
788 ret
= SwitchDesktop(hdesk
);
790 ok(!ret
, "Switch to desktop belong to non default winstation should fail!\n");
792 ok(GetLastError() == ERROR_ACCESS_DENIED
|| broken(GetLastError() == 0xdeadbeef), "last error %08x\n", GetLastError());
793 ret
= SetThreadDesktop(hdesk
);
794 ok(ret
, "SetThreadDesktop failed!\n");
796 /* clean side effect */
797 ret
= SetThreadDesktop(thread_desk
);
799 ok(ret
, "SetThreadDesktop should success even desktop is not belong to process winstation!\n");
800 ret
= SetProcessWindowStation(w1
);
801 ok(ret
, "SetProcessWindowStation failed!\n");
802 ret
= SetThreadDesktop(thread_desk
);
803 ok(ret
, "SetThreadDesktop failed!\n");
804 ret
= CloseWindowStation(w2
);
805 ok(ret
, "CloseWindowStation failed!\n");
806 ret
= CloseDesktop(new_desk
);
807 ok(ret
, "CloseDesktop failed!\n");
808 ret
= CloseDesktop(hdesk
);
809 ok(ret
, "CloseDesktop failed!\n");
812 static LRESULT CALLBACK
WndProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
814 if (msg
== WM_DESTROY
)
816 trace("destroying hwnd %p\n", hWnd
);
820 return DefWindowProcA( hWnd
, msg
, wParam
, lParam
);
823 typedef struct tag_wnd_param
825 const char *wnd_name
;
831 static DWORD WINAPI
create_window(LPVOID param
)
833 wnd_param
*param1
= param
;
837 ret
= SetThreadDesktop(param1
->hdesk
);
838 ok(ret
, "SetThreadDesktop failed!\n");
839 param1
->hwnd
= CreateWindowA("test_class", param1
->wnd_name
, WS_POPUP
, 0, 0, 100, 100, NULL
, NULL
, NULL
, NULL
);
840 ok(param1
->hwnd
!= 0, "CreateWindowA failed!\n");
841 ret
= SetEvent(param1
->hevent
);
842 ok(ret
, "SetEvent failed!\n");
844 while (GetMessageA(&msg
, 0, 0, 0))
846 TranslateMessage(&msg
);
847 DispatchMessageA(&msg
);
853 static DWORD
set_foreground(HWND hwnd
)
856 DWORD set_id
, fore_id
, ret
;
859 hwnd_fore
= GetForegroundWindow();
860 GetWindowTextA(hwnd_fore
, win_text
, 1024);
861 set_id
= GetWindowThreadProcessId(hwnd
, NULL
);
862 fore_id
= GetWindowThreadProcessId(hwnd_fore
, NULL
);
863 trace("\"%s\" %p %08x hwnd %p %08x\n", win_text
, hwnd_fore
, fore_id
, hwnd
, set_id
);
864 ret
= AttachThreadInput(set_id
, fore_id
, TRUE
);
865 trace("AttachThreadInput returned %08x\n", ret
);
866 ret
= ShowWindow(hwnd
, SW_SHOWNORMAL
);
867 trace("ShowWindow returned %08x\n", ret
);
868 ret
= SetWindowPos(hwnd
, HWND_TOPMOST
, 0,0,0,0, SWP_NOSIZE
|SWP_NOMOVE
);
869 trace("set topmost returned %08x\n", ret
);
870 ret
= SetWindowPos(hwnd
, HWND_NOTOPMOST
, 0,0,0,0, SWP_NOSIZE
|SWP_NOMOVE
);
871 trace("set notopmost returned %08x\n", ret
);
872 ret
= SetForegroundWindow(hwnd
);
873 trace("SetForegroundWindow returned %08x\n", ret
);
875 AttachThreadInput(set_id
, fore_id
, FALSE
);
879 static void test_foregroundwindow(void)
881 HWND hwnd
, hwnd_test
, partners
[2], hwnds
[2];
883 int thread_desk_id
, input_desk_id
, hwnd_id
;
886 DWORD ret
, timeout
, timeout_old
;
891 memset( &wclass
, 0, sizeof(wclass
) );
892 wclass
.lpszClassName
= "test_class";
893 wclass
.lpfnWndProc
= WndProc
;
894 RegisterClassA(&wclass
);
895 param
.wnd_name
= "win_name";
897 hdesks
[0] = GetThreadDesktop(GetCurrentThreadId());
898 ok(hdesks
[0] != NULL
, "OpenDesktop failed!\n");
899 SetLastError(0xdeadbeef);
900 hdesks
[1] = CreateDesktopA("desk2", NULL
, NULL
, 0, DESKTOP_ALL_ACCESS
, NULL
);
901 ret
= GetLastError();
902 ok(hdesks
[1] != NULL
|| ret
== ERROR_ACCESS_DENIED
, "CreateDesktop failed (%u)\n", ret
);
905 win_skip("Not enough privileges for CreateDesktop\n");
909 ret
= SystemParametersInfoA(SPI_GETFOREGROUNDLOCKTIMEOUT
, 0, &timeout_old
, 0);
912 win_skip("Skip tests on NT4\n");
913 CloseDesktop(hdesks
[1]);
916 trace("old timeout %d\n", timeout_old
);
918 ret
= SystemParametersInfoA(SPI_SETFOREGROUNDLOCKTIMEOUT
, 0, 0, SPIF_SENDCHANGE
| SPIF_UPDATEINIFILE
);
919 ok(ret
, "set foreground lock timeout failed!\n");
920 ret
= SystemParametersInfoA(SPI_GETFOREGROUNDLOCKTIMEOUT
, 0, &timeout
, 0);
921 ok(ret
, "get foreground lock timeout failed!\n");
922 ok(timeout
== 0, "unexpected timeout %d\n", timeout
);
924 for (thread_desk_id
= 0; thread_desk_id
< DESKTOPS
; thread_desk_id
++)
926 param
.hdesk
= hdesks
[thread_desk_id
];
927 param
.hevent
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
928 CreateThread(NULL
, 0, create_window
, ¶m
, 0, NULL
);
929 ret
= WaitForSingleObject(param
.hevent
, INFINITE
);
930 ok(ret
== WAIT_OBJECT_0
, "wait failed!\n");
931 hwnds
[thread_desk_id
] = param
.hwnd
;
934 for (thread_desk_id
= 0; thread_desk_id
< DESKTOPS
; thread_desk_id
++)
936 param
.hdesk
= hdesks
[thread_desk_id
];
937 param
.hevent
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
938 CreateThread(NULL
, 0, create_window
, ¶m
, 0, NULL
);
939 ret
= WaitForSingleObject(param
.hevent
, INFINITE
);
940 ok(ret
== WAIT_OBJECT_0
, "wait failed!\n");
941 partners
[thread_desk_id
] = param
.hwnd
;
944 trace("hwnd0 %p hwnd1 %p partner0 %p partner1 %p\n", hwnds
[0], hwnds
[1], partners
[0], partners
[1]);
946 for (hwnd_id
= 0; hwnd_id
< DESKTOPS
; hwnd_id
++)
947 for (thread_desk_id
= 0; thread_desk_id
< DESKTOPS
; thread_desk_id
++)
948 for (input_desk_id
= 0; input_desk_id
< DESKTOPS
; input_desk_id
++)
950 trace("testing thread_desk %d input_desk %d hwnd %d\n",
951 thread_desk_id
, input_desk_id
, hwnd_id
);
952 hwnd_test
= hwnds
[hwnd_id
];
953 ret
= SetThreadDesktop(hdesks
[thread_desk_id
]);
954 ok(ret
, "set thread desktop failed!\n");
955 ret
= SwitchDesktop(hdesks
[input_desk_id
]);
956 ok(ret
, "switch desktop failed!\n");
957 set_foreground(partners
[0]);
958 set_foreground(partners
[1]);
959 hwnd
= GetForegroundWindow();
960 ok(hwnd
!= hwnd_test
, "unexpected foreground window %p\n", hwnd
);
961 ret
= set_foreground(hwnd_test
);
962 hwnd
= GetForegroundWindow();
963 GetWindowTextA(hwnd
, win_text
, 1024);
964 trace("hwnd %p name %s\n", hwnd
, win_text
);
965 if (input_desk_id
== hwnd_id
)
967 if (input_desk_id
== thread_desk_id
)
969 ok(ret
, "SetForegroundWindow failed!\n");
971 ok(hwnd
== hwnd_test
, "unexpected foreground window %p\n", hwnd
);
975 todo_wine
ok(ret
, "SetForegroundWindow failed!\n");
976 todo_wine
ok(hwnd
== 0, "unexpected foreground window %p\n", hwnd
);
981 if (input_desk_id
== thread_desk_id
)
983 ok(!ret
, "SetForegroundWindow should fail!\n");
985 ok(hwnd
== partners
[input_desk_id
] , "unexpected foreground window %p\n", hwnd
);
989 todo_wine
ok(!ret
, "SetForegroundWindow should fail!\n");
991 ok(hwnd
== 0, "unexpected foreground window %p\n", hwnd
);
998 for (thread_desk_id
= DESKTOPS
- 1; thread_desk_id
>= 0; thread_desk_id
--)
1000 ret
= SetThreadDesktop(hdesks
[thread_desk_id
]);
1001 ok(ret
, "set thread desktop failed!\n");
1002 SendMessageA(hwnds
[thread_desk_id
], WM_DESTROY
, 0, 0);
1003 SendMessageA(partners
[thread_desk_id
], WM_DESTROY
, 0, 0);
1006 ret
= SwitchDesktop(hdesks
[0]);
1007 ok(ret
, "switch desktop failed!\n");
1008 CloseDesktop(hdesks
[1]);
1010 ret
= SystemParametersInfoA(SPI_SETFOREGROUNDLOCKTIMEOUT
, 0, UlongToPtr(timeout_old
), SPIF_SENDCHANGE
| SPIF_UPDATEINIFILE
);
1011 ok(ret
, "set foreground lock timeout failed!\n");
1012 ret
= SystemParametersInfoA(SPI_GETFOREGROUNDLOCKTIMEOUT
, 0, &timeout
, 0);
1013 ok(ret
, "get foreground lock timeout failed!\n");
1014 ok(timeout
== timeout_old
, "unexpected timeout %d\n", timeout
);
1017 START_TEST(winstation
)
1019 HMODULE hntdll
= GetModuleHandleA("ntdll.dll");
1020 pNtQueryObject
= (void *)GetProcAddress(hntdll
, "NtQueryObject");
1022 /* Check whether this platform supports WindowStation calls */
1024 SetLastError( 0xdeadbeef );
1025 GetProcessWindowStation();
1026 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
1028 win_skip("WindowStation calls not supported on this platform\n");
1032 test_inputdesktop();
1033 test_inputdesktop2();
1034 test_enumstations();
1035 test_enumdesktops();
1037 test_getuserobjectinformation();
1038 test_foregroundwindow();