ReactOS 0.4.16-dev-2491-g3dc6630
winstation.c
Go to the documentation of this file.
1/*
2 * Unit tests for window stations and desktops
3 *
4 * Copyright 2002 Alexandre Julliard
5 *
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.
10 *
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.
15 *
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
19 */
20
21#ifdef __REACTOS__
22#define WIN32_NO_STATUS
23#include <ntndk.h>
24#endif
25#include "wine/test.h"
26#include "winbase.h"
27#include "wingdi.h"
28#include "winuser.h"
29#include "winnls.h"
30#ifndef __REACTOS__
31#include "winternl.h"
32#endif
33
35
36#define DESKTOP_ALL_ACCESS 0x01ff
37
38static void print_object( HANDLE obj )
39{
40 char buffer[100];
41 DWORD size;
42
43 strcpy( buffer, "foobar" );
45 trace( "could not get info for %p\n", obj );
46 else
47 trace( "obj %p name '%s'\n", obj, buffer );
48 strcpy( buffer, "foobar" );
50 trace( "could not get type for %p\n", obj );
51 else
52 trace( "obj %p type '%s'\n", obj, buffer );
53}
54
55static void register_class(void)
56{
57 WNDCLASSA cls;
58
59 cls.style = CS_DBLCLKS;
60 /* Windows < Vista apparently checks lpfnWndProc against the address of
61 * DefWindowProcA(), and for some reason fails to change the thread desktop
62 * after creating and destroying a window if it doesn't match. Using an IAT
63 * (as is default) or a wrapper triggers this, so use GetProcAddress() as
64 * a workaround. */
65 cls.lpfnWndProc = (void *)GetProcAddress(GetModuleHandleA("user32"), "DefWindowProcA");
66 cls.cbClsExtra = 0;
67 cls.cbWndExtra = 0;
69 cls.hIcon = 0;
72 cls.lpszMenuName = NULL;
73 cls.lpszClassName = "WinStationClass";
74 RegisterClassA(&cls);
75}
76
77static HDESK initial_desktop;
78
80{
81 HDESK d1, d2;
82 HWND hwnd = CreateWindowExA(0,"WinStationClass","test",WS_POPUP,0,0,100,100,GetDesktopWindow(),0,0,0);
83 ok( hwnd != 0, "CreateWindow failed\n" );
85 trace( "thread %p desktop: %p\n", arg, d1 );
86 ok( d1 == initial_desktop, "thread %p doesn't use initial desktop\n", arg );
87
88 SetLastError( 0xdeadbeef );
89 ok( !CloseHandle( d1 ), "CloseHandle succeeded\n" );
90 ok( GetLastError() == ERROR_INVALID_HANDLE, "bad last error %ld\n", GetLastError() );
91 SetLastError( 0xdeadbeef );
92 ok( !CloseDesktop( d1 ), "CloseDesktop succeeded\n" );
93 ok( GetLastError() == ERROR_BUSY || broken(GetLastError() == 0xdeadbeef), /* wow64 */
94 "bad last error %ld\n", GetLastError() );
95 print_object( d1 );
96 d2 = CreateDesktopA( "foobar2", NULL, NULL, 0, DESKTOP_ALL_ACCESS, NULL );
97 trace( "created desktop %p\n", d2 );
98 ok( d2 != 0, "CreateDesktop failed\n" );
99
100 SetLastError( 0xdeadbeef );
101 ok( !SetThreadDesktop( d2 ), "set thread desktop succeeded with existing window\n" );
102 ok( GetLastError() == ERROR_BUSY || broken(GetLastError() == 0xdeadbeef), /* wow64 */
103 "bad last error %ld\n", GetLastError() );
104
106 ok( SetThreadDesktop( d2 ), "set thread desktop failed\n" );
108 ok( d1 == d2, "GetThreadDesktop did not return set desktop %p/%p\n", d1, d2 );
109 print_object( d2 );
110 if (arg < (LPVOID)5)
111 {
112 HANDLE hthread = CreateThread( NULL, 0, thread, (char *)arg + 1, 0, NULL );
113 Sleep(1000);
114 WaitForSingleObject( hthread, INFINITE );
115 CloseHandle( hthread );
116 }
117 return 0;
118}
119
120static void test_handles(void)
121{
122 HWINSTA w1, w2, w3;
123 HDESK d1, d2, d3;
124 HANDLE hthread;
125 DWORD id, flags, le;
126 ATOM atom;
127 char buffer[29], default_name[29] = "";
128 DWORD size;
129 BOOL ret;
131 TOKEN_STATISTICS token_stats;
133
134 /* win stations */
135
137 ok( GetProcessWindowStation() == w1, "GetProcessWindowStation returned different handles\n" );
138 ok( !CloseWindowStation(w1), "closing process win station succeeded\n" );
139 SetLastError( 0xdeadbeef );
140 ok( !CloseHandle(w1), "closing process win station handle succeeded\n" );
141 ok( GetLastError() == ERROR_INVALID_HANDLE, "bad last error %ld\n", GetLastError() );
142 print_object( w1 );
143
145 ok( !status, "NtQueryObject failed, status %#lx\n", status );
147 "Got unexpected access %#lx\n", info.GrantedAccess );
148
149 flags = 0;
150 ok( GetHandleInformation( w1, &flags ), "GetHandleInformation failed\n" );
152 broken(flags & HANDLE_FLAG_PROTECT_FROM_CLOSE), /* set on nt4 */
153 "handle %p PROTECT_FROM_CLOSE set\n", w1 );
154
156 TRUE, DUPLICATE_SAME_ACCESS ), "DuplicateHandle failed\n" );
157 ok( CloseWindowStation(w2), "closing dup win station failed\n" );
158
160 TRUE, DUPLICATE_SAME_ACCESS ), "DuplicateHandle failed\n" );
161 ok( CloseHandle(w2), "closing dup win station handle failed\n" );
162
164 le = GetLastError();
165 ok( w2 != 0 || le == ERROR_ACCESS_DENIED, "CreateWindowStation failed (%lu)\n", le );
166 if (w2 != 0)
167 {
168 ok( w2 != w1, "CreateWindowStation returned default handle\n" );
169 SetLastError( 0xdeadbeef );
170 ok( !CloseDesktop( (HDESK)w2 ), "CloseDesktop succeeded on win station\n" );
171 ok( GetLastError() == ERROR_INVALID_HANDLE || broken(GetLastError() == 0xdeadbeef), /* wow64 */
172 "bad last error %ld\n", GetLastError() );
173 ok( CloseWindowStation( w2 ), "CloseWindowStation failed\n" );
174
176 ok( CloseHandle( w2 ), "CloseHandle failed\n" );
177 }
178 else if (le == ERROR_ACCESS_DENIED)
179 win_skip( "Not enough privileges for CreateWindowStation\n" );
180
182 ok( w2 != 0, "OpenWindowStation failed\n" );
183 ok( w2 != w1, "OpenWindowStation returned default handle\n" );
184 ok( CloseWindowStation( w2 ), "CloseWindowStation failed\n" );
185
186 w2 = OpenWindowStationA("dummy name", TRUE, WINSTA_ALL_ACCESS );
187 ok( !w2, "open dummy win station succeeded\n" );
188
189 CreateMutexA( NULL, 0, "foobar" );
191 le = GetLastError();
192 ok( w2 != 0 || le == ERROR_ACCESS_DENIED, "create foobar station failed (%lu)\n", le );
193
194 if (w2 != 0)
195 {
196 w3 = OpenWindowStationA("foobar", TRUE, WINSTA_ALL_ACCESS );
197 ok( w3 != 0, "open foobar station failed\n" );
198 ok( w3 != w2, "open foobar station returned same handle\n" );
199 ok( CloseWindowStation( w2 ), "CloseWindowStation failed\n" );
200 ok( CloseWindowStation( w3 ), "CloseWindowStation failed\n" );
201
202 w3 = OpenWindowStationA("foobar", TRUE, WINSTA_ALL_ACCESS );
203 ok( !w3, "open foobar station succeeded\n" );
204
206 ok( w2 != 0, "create foobar station failed\n" );
207 w3 = CreateWindowStationA("foobar2", 0, WINSTA_ALL_ACCESS, NULL );
208 ok( w3 != 0, "create foobar station failed\n" );
209 ok( GetHandleInformation( w2, &flags ), "GetHandleInformation failed\n" );
210 ok( GetHandleInformation( w3, &flags ), "GetHandleInformation failed\n" );
211
213 atom = GlobalAddAtomA("foo");
214 ok( GlobalGetAtomNameA( atom, buffer, sizeof(buffer) ) == 3, "GlobalGetAtomName failed\n" );
215 ok( !lstrcmpiA( buffer, "foo" ), "bad atom value %s\n", buffer );
216
217 ok( !CloseWindowStation( w2 ), "CloseWindowStation succeeded\n" );
218 ok( GetHandleInformation( w2, &flags ), "GetHandleInformation failed\n" );
219
221 ok( GetHandleInformation( w2, &flags ), "GetHandleInformation failed\n" );
222 ok( CloseWindowStation( w2 ), "CloseWindowStation failed\n" );
223 ok( GlobalGetAtomNameA( atom, buffer, sizeof(buffer) ) == 3, "GlobalGetAtomName failed\n" );
224 ok( !lstrcmpiA( buffer, "foo" ), "bad atom value %s\n", buffer );
225 }
226 else if (le == ERROR_ACCESS_DENIED)
227 win_skip( "Not enough privileges for CreateWindowStation\n" );
228
229 SetLastError( 0xdeadbeef );
231 ok( !w2, "open station succeeded\n" );
232 ok( GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %lu\n", GetLastError() );
233
234 SetLastError( 0xdeadbeef );
236 ok( w2 != 0, "create station failed err %lu\n", GetLastError() );
237
238 memset( buffer, 0, sizeof(buffer) );
240 ok( ret, "GetUserObjectInformationA failed with error %lu\n", GetLastError() );
241 /* Get the logon session LUID */
242 ret = GetTokenInformation( GetCurrentProcessToken(), TokenStatistics, &token_stats, sizeof(token_stats), NULL );
243 if (ret)
244 sprintf( default_name, "Service-0x%lx-%lx$", token_stats.AuthenticationId.HighPart,
245 token_stats.AuthenticationId.LowPart );
246 if (*default_name)
247 ok( !strcmp( buffer, default_name ), "unexpected window station name '%s' expected '%s'\n", buffer, default_name );
248
249 SetLastError( 0xdeadbeef );
251 ok( w3 != 0, "open station failed err %lu\n", GetLastError() );
252 CloseWindowStation( w3 );
254
256 ok( w2 != 0, "create station failed err %lu\n", GetLastError() );
257
258 memset( buffer, 0, sizeof(buffer) );
260 ok( ret, "GetUserObjectInformationA failed with error %lu\n", GetLastError() );
261 if (*default_name)
262 ok( !strcmp( buffer, default_name ), "unexpected window station name '%s' expected '%s'\n", buffer, default_name );
264
265 SetLastError( 0xdeadbeef );
266 w2 = CreateWindowStationA( "foo\\bar", 0, WINSTA_ALL_ACCESS, NULL );
267 ok( !w2, "create station succeeded\n" );
269 "wrong error %lu\n", GetLastError() );
270
271 SetLastError( 0xdeadbeef );
273 ok( !w2, "create station succeeded\n" );
274 ok( GetLastError() == ERROR_PATH_NOT_FOUND, "wrong error %lu\n", GetLastError() );
275
276 /* desktops */
278 initial_desktop = d1;
280 "GetThreadDesktop returned different handles\n" );
281
282 flags = 0;
283 ok( GetHandleInformation( d1, &flags ), "GetHandleInformation failed\n" );
284 ok( !(flags & HANDLE_FLAG_PROTECT_FROM_CLOSE), "handle %p PROTECT_FROM_CLOSE set\n", d1 );
285
287 ok( !status, "NtQueryObject failed, status %#lx\n", status );
289 "Got unexpected access %#lx\n", info.GrantedAccess );
290
291 SetLastError( 0xdeadbeef );
292 ok( !CloseDesktop(d1), "closing thread desktop succeeded\n" );
293 ok( GetLastError() == ERROR_BUSY || broken(GetLastError() == 0xdeadbeef), /* wow64 */
294 "bad last error %ld\n", GetLastError() );
295
296 SetLastError( 0xdeadbeef );
297 if (CloseHandle( d1 )) /* succeeds on nt4 */
298 {
299 win_skip( "NT4 desktop handle management is completely different\n" );
300 return;
301 }
302 ok( GetLastError() == ERROR_INVALID_HANDLE, "bad last error %ld\n", GetLastError() );
303
305 TRUE, DUPLICATE_SAME_ACCESS ), "DuplicateHandle failed\n" );
306 ok( CloseDesktop(d2), "closing dup desktop failed\n" );
307
309 TRUE, DUPLICATE_SAME_ACCESS ), "DuplicateHandle failed\n" );
310 ok( CloseHandle(d2), "closing dup desktop handle failed\n" );
311
312 d2 = OpenDesktopA( "dummy name", 0, TRUE, DESKTOP_ALL_ACCESS );
313 ok( !d2, "open dummy desktop succeeded\n" );
314
315 SetLastError( 0xdeadbeef );
317 ok( !d2, "create empty desktop succeeded\n" );
318 ok( GetLastError() == ERROR_INVALID_HANDLE, "wrong error %lu\n", GetLastError() );
319
320 SetLastError( 0xdeadbeef );
321 d2 = OpenDesktopA( "", 0, TRUE, DESKTOP_ALL_ACCESS );
322 ok( !d2, "open empty desktop succeeded\n" );
323 ok( GetLastError() == ERROR_INVALID_HANDLE, "wrong error %lu\n", GetLastError() );
324
325 SetLastError( 0xdeadbeef );
326 d2 = CreateDesktopA( "foo\\bar", NULL, NULL, 0, DESKTOP_ALL_ACCESS, NULL );
327 ok( !d2, "create desktop succeeded\n" );
328 ok( GetLastError() == ERROR_BAD_PATHNAME, "wrong error %lu\n", GetLastError() );
329
330 SetLastError( 0xdeadbeef );
331 d2 = OpenDesktopA( "foo\\bar", 0, TRUE, DESKTOP_ALL_ACCESS );
332 ok( !d2, "open desktop succeeded\n" );
333 ok( GetLastError() == ERROR_BAD_PATHNAME, "wrong error %lu\n", GetLastError() );
334
335 d2 = CreateDesktopA( "foobar", NULL, NULL, 0, DESKTOP_ALL_ACCESS, NULL );
336 ok( d2 != 0, "create foobar desktop failed\n" );
337 SetLastError( 0xdeadbeef );
338 ok( !CloseWindowStation( (HWINSTA)d2 ), "CloseWindowStation succeeded on desktop\n" );
339 ok( GetLastError() == ERROR_INVALID_HANDLE || broken(GetLastError() == 0xdeadbeef), /* wow64 */
340 "bad last error %ld\n", GetLastError() );
341
342 SetLastError( 0xdeadbeef );
343 d3 = CreateDesktopA( "foobar", NULL, NULL, 0, DESKTOP_ALL_ACCESS, NULL );
344 ok( d3 != 0, "create foobar desktop again failed\n" );
345 ok( GetLastError() == 0xdeadbeef, "bad last error %ld\n", GetLastError() );
346 ok( CloseDesktop( d3 ), "CloseDesktop failed\n" );
347
348 d3 = OpenDesktopA( "foobar", 0, TRUE, DESKTOP_ALL_ACCESS );
349 ok( d3 != 0, "open foobar desktop failed\n" );
350 ok( d3 != d2, "open foobar desktop returned same handle\n" );
351 ok( CloseDesktop( d2 ), "CloseDesktop failed\n" );
352 ok( CloseDesktop( d3 ), "CloseDesktop failed\n" );
353
354 d3 = OpenDesktopA( "foobar", 0, TRUE, DESKTOP_ALL_ACCESS );
355 ok( !d3, "open foobar desktop succeeded\n" );
356
357 ok( !CloseHandle(d1), "closing thread desktop handle succeeded\n" );
359 ok( d1 == d2, "got different handles after close\n" );
360
362 trace( "thread 1 desktop: %p\n", d1 );
363 print_object( d1 );
364 hthread = CreateThread( NULL, 0, thread, (LPVOID)2, 0, &id );
365 Sleep(1000);
366 trace( "get other thread desktop: %p\n", GetThreadDesktop(id) );
367 WaitForSingleObject( hthread, INFINITE );
368 CloseHandle( hthread );
369
370 /* clean side effect */
372}
373
374/* Enumeration tests */
375
377{
378 trace("window_station_callbackA called with argument %s\n", winsta);
379 return lp;
380}
381
383{
384 HWINSTA hwinsta;
385
386 trace("open_window_station_callbackA called with argument %s\n", winsta);
387 hwinsta = OpenWindowStationA(winsta, FALSE, WINSTA_ENUMERATE);
388 ok(hwinsta != NULL, "Could not open desktop %s!\n", winsta);
389 if (hwinsta)
390 CloseWindowStation(hwinsta);
391 return lp;
392}
393
394static void test_enumstations(void)
395{
396 DWORD ret;
397 HWINSTA hwinsta;
398
399 if (0) /* Crashes instead */
400 {
401 SetLastError(0xbabefeed);
403 ok(!ret, "EnumWindowStationsA returned successfully!\n");
404 ok(GetLastError() == ERROR_INVALID_PARAMETER, "LastError is set to %08lx\n", GetLastError());
405 }
406
407 hwinsta = CreateWindowStationA("winsta_test", 0, WINSTA_ALL_ACCESS, NULL);
408 ret = GetLastError();
409 ok(hwinsta != NULL || ret == ERROR_ACCESS_DENIED, "CreateWindowStation failed (%lu)\n", ret);
410 if (!hwinsta)
411 {
412 win_skip("Not enough privileges for CreateWindowStation\n");
413 return;
414 }
415
416 SetLastError(0xdeadbeef);
418 ok(ret == 0x12345, "EnumWindowStationsA returned %lx\n", ret);
419 ok(GetLastError() == 0xdeadbeef, "LastError is set to %08lx\n", GetLastError());
420
421 SetLastError(0xdeadbeef);
423 ok(!ret, "EnumWindowStationsA returned %lx\n", ret);
424 ok(GetLastError() == 0xdeadbeef, "LastError is set to %08lx\n", GetLastError());
425}
426
428{
429 trace("desktop_callbackA called with argument %s\n", desktop);
430 return lp;
431}
432
434{
435 HDESK hdesk;
436 static int once;
437
438 trace("open_desktop_callbackA called with argument %s\n", desktop);
439 /* Only try to open one desktop */
440 if (once++)
441 return lp;
442
443 hdesk = OpenDesktopA(desktop, 0, FALSE, DESKTOP_ENUMERATE);
444 ok(hdesk != NULL, "Could not open desktop %s!\n", desktop);
445 if (hdesk)
446 CloseDesktop(hdesk);
447 return lp;
448}
449
450static void test_enumdesktops(void)
451{
452 BOOL ret;
453
454 if (0) /* Crashes instead */
455 {
456 SetLastError(0xbabefeed);
458 ok(!ret, "EnumDesktopsA returned successfully!\n");
459 ok(GetLastError() == ERROR_INVALID_PARAMETER, "LastError is set to %08lx\n", GetLastError());
460 }
461
462 SetLastError(0xdeadbeef);
464 ok(ret == 0x12345, "EnumDesktopsA returned %x\n", ret);
465 ok(GetLastError() == 0xdeadbeef, "LastError is set to %08lx\n", GetLastError());
466
467 SetLastError(0xdeadbeef);
469 ok(ret == 0x12345, "EnumDesktopsA returned %x\n", ret);
470 ok(GetLastError() == 0xdeadbeef, "LastError is set to %08lx\n", GetLastError());
471
472 SetLastError(0xdeadbeef);
474 ok(!ret, "EnumDesktopsA returned %x\n", ret);
475 ok(GetLastError() == ERROR_INVALID_HANDLE, "LastError is set to %08lx\n", GetLastError());
476
477 SetLastError(0xdeadbeef);
479 ok(!ret, "EnumDesktopsA returned %x\n", ret);
480 ok(GetLastError() == 0xdeadbeef, "LastError is set to %08lx\n", GetLastError());
481}
482
483/* Miscellaneous tests */
484
486{
487 WCHAR foobarTestW[] = {'\\','f','o','o','b','a','r','T','e','s','t',0};
488 WCHAR DesktopW[] = {'D','e','s','k','t','o','p',0};
489 OBJECT_NAME_INFORMATION *name_info;
490 WCHAR bufferW[20];
491 char buffer[64];
493 DWORD size;
494 HDESK desk;
495 BOOL ret;
496
497 desk = CreateDesktopA("foobarTest", NULL, NULL, 0, DESKTOP_ALL_ACCESS, NULL);
498 ok(desk != 0, "open foobarTest desktop failed\n");
499
500 strcpy(buffer, "blahblah");
501
504 /* Get size, test size and return value/error code */
505 SetLastError(0xdeadbeef);
506 size = 0xdeadbeef;
508
509 ok(!ret, "GetUserObjectInformationA returned %x\n", ret);
510 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "LastError is set to %08lx\n", GetLastError());
511 ok(size == 22, "size is set to %ld\n", size); /* Windows returns Unicode length (11*2) */
512
513 /* Get string */
514 SetLastError(0xdeadbeef);
515 size = 0xdeadbeef;
517
518 ok(ret, "GetUserObjectInformationA returned %x\n", ret);
519 ok(GetLastError() == 0xdeadbeef, "LastError is set to %08lx\n", GetLastError());
520
521 ok(strcmp(buffer, "foobarTest") == 0, "Buffer is set to '%s'\n", buffer);
522 ok(size == 11, "size is set to %ld\n", size); /* 11 bytes in 'foobarTest\0' */
523
524 /* Get size, test size and return value/error code (Unicode) */
525 SetLastError(0xdeadbeef);
526 size = 0xdeadbeef;
528
529 ok(!ret, "GetUserObjectInformationW returned %x\n", ret);
530 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "LastError is set to %08lx\n", GetLastError());
531 ok(size == 22, "size is set to %ld\n", size); /* 22 bytes in 'foobarTest\0' in Unicode */
532
533 /* Get string (Unicode) */
534 SetLastError(0xdeadbeef);
535 size = 0xdeadbeef;
536 ret = GetUserObjectInformationW(desk, UOI_NAME, bufferW, sizeof(bufferW), &size);
537
538 ok(ret, "GetUserObjectInformationW returned %x\n", ret);
539 ok(GetLastError() == 0xdeadbeef, "LastError is set to %08lx\n", GetLastError());
540
541 ok(lstrcmpW(bufferW, foobarTestW + 1) == 0, "Buffer is not set to 'foobarTest'\n");
542 ok(size == 22, "size is set to %ld\n", size); /* 22 bytes in 'foobarTest\0' in Unicode */
543
544 /* ObjectNameInformation does not return the full desktop name */
545 name_info = (OBJECT_NAME_INFORMATION *)buffer;
546 status = pNtQueryObject(desk, ObjectNameInformation, name_info, sizeof(buffer), NULL);
547 ok(!status, "expected STATUS_SUCCESS, got %08lx\n", status);
548 ok(lstrcmpW(name_info->Name.Buffer, foobarTestW) == 0,
549 "expected '\\foobarTest', got %s\n", wine_dbgstr_w(name_info->Name.Buffer));
550
553 /* Get size, test size and return value/error code */
554 SetLastError(0xdeadbeef);
555 size = 0xdeadbeef;
557
558 ok(!ret, "GetUserObjectInformationA returned %x\n", ret);
559 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "LastError is set to %08lx\n", GetLastError());
560 ok(size == 16, "size is set to %ld\n", size); /* Windows returns Unicode length (8*2) */
561
562 /* Get string */
563 SetLastError(0xdeadbeef);
564 size = 0xdeadbeef;
566
567 ok(ret, "GetUserObjectInformationA returned %x\n", ret);
568 ok(GetLastError() == 0xdeadbeef, "LastError is set to %08lx\n", GetLastError());
569
570 ok(strcmp(buffer, "Desktop") == 0, "Buffer is set to '%s'\n", buffer);
571 ok(size == 8, "size is set to %ld\n", size); /* 8 bytes in 'Desktop\0' */
572
573 /* Get size, test size and return value/error code (Unicode) */
574 size = 0xdeadbeef;
575 SetLastError(0xdeadbeef);
577
578 ok(!ret, "GetUserObjectInformationW returned %x\n", ret);
579 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "LastError is set to %08lx\n", GetLastError());
580 ok(size == 16, "size is set to %ld\n", size); /* 16 bytes in 'Desktop\0' in Unicode */
581
582 /* Get string (Unicode) */
583 SetLastError(0xdeadbeef);
584 size = 0xdeadbeef;
585 ret = GetUserObjectInformationW(desk, UOI_TYPE, bufferW, sizeof(bufferW), &size);
586
587 ok(ret, "GetUserObjectInformationW returned %x\n", ret);
588 ok(GetLastError() == 0xdeadbeef, "LastError is set to %08lx\n", GetLastError());
589
590 ok(lstrcmpW(bufferW, DesktopW) == 0, "Buffer is not set to 'Desktop'\n");
591 ok(size == 16, "size is set to %ld\n", size); /* 16 bytes in 'Desktop\0' in Unicode */
592
593 ok(CloseDesktop(desk), "CloseDesktop failed\n");
594}
595
596static void test_inputdesktop(void)
597{
598 HDESK input_desk, old_input_desk, thread_desk, old_thread_desk, new_desk;
599 DWORD ret;
600 CHAR name[1024];
601 INPUT inputs[1];
602
603 inputs[0].type = INPUT_KEYBOARD;
604 inputs[0].ki.wVk = 0;
605 inputs[0].ki.wScan = 0x3c0;
606 inputs[0].ki.dwFlags = KEYEVENTF_UNICODE;
607
608 /* OpenInputDesktop creates new handles for each calls */
609 old_input_desk = OpenInputDesktop(0, FALSE, DESKTOP_ALL_ACCESS);
610 ok(old_input_desk != NULL, "OpenInputDesktop failed!\n");
611 memset(name, 0, sizeof(name));
612 ret = GetUserObjectInformationA(old_input_desk, UOI_NAME, name, 1024, NULL);
613 ok(ret, "GetUserObjectInformation failed!\n");
614 ok(!strcmp(name, "Default"), "unexpected desktop %s\n", name);
615
616 input_desk = OpenInputDesktop(0, FALSE, DESKTOP_ALL_ACCESS);
617 ok(input_desk != NULL, "OpenInputDesktop failed!\n");
618 memset(name, 0, sizeof(name));
619 ret = GetUserObjectInformationA(input_desk, UOI_NAME, name, 1024, NULL);
620 ok(ret, "GetUserObjectInformation failed!\n");
621 ok(!strcmp(name, "Default"), "unexpected desktop %s\n", name);
622
623 ok(old_input_desk != input_desk, "returned the same handle!\n");
624 ret = CloseDesktop(input_desk);
625 ok(ret, "CloseDesktop failed!\n");
626
627 /* by default, GetThreadDesktop is the input desktop, SendInput should succeed. */
628 old_thread_desk = GetThreadDesktop(GetCurrentThreadId());
629 ok(old_thread_desk != NULL, "GetThreadDesktop failed!\n");
630 memset(name, 0, sizeof(name));
631 ret = GetUserObjectInformationA(old_thread_desk, UOI_NAME, name, 1024, NULL);
632 ok(!strcmp(name, "Default"), "unexpected desktop %s\n", name);
633
634 SetLastError(0xdeadbeef);
635 ret = SendInput(1, inputs, sizeof(INPUT));
636 ok(GetLastError() == 0xdeadbeef, "unexpected last error %08lx\n", GetLastError());
637 ok(ret == 1, "unexpected return count %ld\n", ret);
638
639 /* Set thread desktop to the new desktop, SendInput should fail. */
640 new_desk = CreateDesktopA("new_desk", NULL, NULL, 0, DESKTOP_ALL_ACCESS, NULL);
641 ok(new_desk != NULL, "CreateDesktop failed!\n");
642 ret = SetThreadDesktop(new_desk);
643 ok(ret, "SetThreadDesktop failed!\n");
644 thread_desk = GetThreadDesktop(GetCurrentThreadId());
645 ok(thread_desk == new_desk, "thread desktop doesn't match!\n");
646 memset(name, 0, sizeof(name));
647 ret = GetUserObjectInformationA(thread_desk, UOI_NAME, name, 1024, NULL);
648 ok(!strcmp(name, "new_desk"), "unexpected desktop %s\n", name);
649
650 SetLastError(0xdeadbeef);
651 ret = SendInput(1, inputs, sizeof(INPUT));
652 if(broken(GetLastError() == 0xdeadbeef))
653 {
654 SetThreadDesktop(old_thread_desk);
655 CloseDesktop(old_input_desk);
656 CloseDesktop(input_desk);
657 CloseDesktop(new_desk);
658 win_skip("Skip tests on NT4\n");
659 return;
660 }
661 ok(GetLastError() == ERROR_ACCESS_DENIED, "unexpected last error %08lx\n", GetLastError());
662 ok(ret == 0 || broken(ret == 1) /* Win32 */, "unexpected return count %ld\n", ret);
663
664 /* Set thread desktop back to the old thread desktop, SendInput should success. */
665 ret = SetThreadDesktop(old_thread_desk);
666 ok(ret, "SetThreadDesktop failed!\n");
667 thread_desk = GetThreadDesktop(GetCurrentThreadId());
668 ok(thread_desk == old_thread_desk, "thread desktop doesn't match!\n");
669 memset(name, 0, sizeof(name));
670 ret = GetUserObjectInformationA(thread_desk, UOI_NAME, name, 1024, NULL);
671 ok(!strcmp(name, "Default"), "unexpected desktop %s\n", name);
672
673 SetLastError(0xdeadbeef);
674 ret = SendInput(1, inputs, sizeof(INPUT));
675 ok(GetLastError() == 0xdeadbeef, "unexpected last error %08lx\n", GetLastError());
676 ok(ret == 1, "unexpected return count %ld\n", ret);
677
678 /* Set thread desktop to the input desktop, SendInput should success. */
679 ret = SetThreadDesktop(old_input_desk);
680 ok(ret, "SetThreadDesktop failed!\n");
681 thread_desk = GetThreadDesktop(GetCurrentThreadId());
682 ok(thread_desk == old_input_desk, "thread desktop doesn't match!\n");
683 memset(name, 0, sizeof(name));
684 ret = GetUserObjectInformationA(thread_desk, UOI_NAME, name, 1024, NULL);
685 ok(!strcmp(name, "Default"), "unexpected desktop %s\n", name);
686
687 SetLastError(0xdeadbeef);
688 ret = SendInput(1, inputs, sizeof(INPUT));
689 ok(GetLastError() == 0xdeadbeef, "unexpected last error %08lx\n", GetLastError());
690 ok(ret == 1, "unexpected return count %ld\n", ret);
691
692 /* Switch input desktop to the new desktop, SendInput should fail. */
693 ret = SwitchDesktop(new_desk);
694 ok(ret, "SwitchDesktop failed!\n");
695 input_desk = OpenInputDesktop(0, FALSE, DESKTOP_ALL_ACCESS);
696 ok(input_desk != NULL, "OpenInputDesktop failed!\n");
697 ok(input_desk != new_desk, "returned the same handle!\n");
698 memset(name, 0, sizeof(name));
699 ret = GetUserObjectInformationA(input_desk, UOI_NAME, name, 1024, NULL);
700 ok(ret, "GetUserObjectInformation failed!\n");
701 ok(!strcmp(name, "new_desk"), "unexpected desktop %s\n", name);
702 ret = CloseDesktop(input_desk);
703 ok(ret, "CloseDesktop failed!\n");
704
705 SetLastError(0xdeadbeef);
706 ret = SendInput(1, inputs, sizeof(INPUT));
707 ok(GetLastError() == ERROR_ACCESS_DENIED, "unexpected last error %08lx\n", GetLastError());
708 ok(ret == 0 || broken(ret == 1) /* Win32 */, "unexpected return count %ld\n", ret);
709
710 /* Set thread desktop to the new desktop, SendInput should success. */
711 ret = SetThreadDesktop(new_desk);
712 ok(ret, "SetThreadDesktop failed!\n");
713 thread_desk = GetThreadDesktop(GetCurrentThreadId());
714 ok(thread_desk == new_desk, "thread desktop doesn't match!\n");
715 memset(name, 0, sizeof(name));
716 ret = GetUserObjectInformationA(thread_desk, UOI_NAME, name, 1024, NULL);
717 ok(!strcmp(name, "new_desk"), "unexpected desktop %s\n", name);
718
719 SetLastError(0xdeadbeef);
720 ret = SendInput(1, inputs, sizeof(INPUT));
721 ok(GetLastError() == 0xdeadbeef, "unexpected last error %08lx\n", GetLastError());
722 ok(ret == 1, "unexpected return count %ld\n", ret);
723
724 /* Switch input desktop to the old input desktop, set thread desktop to the old
725 * thread desktop, clean side effects. SendInput should success. */
726 ret = SwitchDesktop(old_input_desk);
727 input_desk = OpenInputDesktop(0, FALSE, DESKTOP_ALL_ACCESS);
728 ok(input_desk != NULL, "OpenInputDesktop failed!\n");
729 ok(input_desk != old_input_desk, "returned the same handle!\n");
730 memset(name, 0, sizeof(name));
731 ret = GetUserObjectInformationA(input_desk, UOI_NAME, name, 1024, NULL);
732 ok(ret, "GetUserObjectInformation failed!\n");
733 ok(!strcmp(name, "Default"), "unexpected desktop %s\n", name);
734
735 ret = SetThreadDesktop(old_thread_desk);
736 ok(ret, "SetThreadDesktop failed!\n");
737 thread_desk = GetThreadDesktop(GetCurrentThreadId());
738 ok(thread_desk == old_thread_desk, "thread desktop doesn't match!\n");
739 memset(name, 0, sizeof(name));
740 ret = GetUserObjectInformationA(thread_desk, UOI_NAME, name, 1024, NULL);
741 ok(!strcmp(name, "Default"), "unexpected desktop %s\n", name);
742
743 SetLastError(0xdeadbeef);
744 ret = SendInput(1, inputs, sizeof(INPUT));
745 ok(GetLastError() == 0xdeadbeef, "unexpected last error %08lx\n", GetLastError());
746 ok(ret == 1, "unexpected return count %ld\n", ret);
747
748 /* free resources */
749 ret = CloseDesktop(input_desk);
750 ok(ret, "CloseDesktop failed!\n");
751 ret = CloseDesktop(old_input_desk);
752 ok(ret, "CloseDesktop failed!\n");
753 ret = CloseDesktop(new_desk);
754 ok(ret, "CloseDesktop failed!\n");
755}
756
757static void test_inputdesktop2(void)
758{
759 HWINSTA w1, w2;
760 HDESK thread_desk, new_desk, input_desk, hdesk;
761 DWORD ret;
762
763 thread_desk = GetThreadDesktop(GetCurrentThreadId());
764 ok(thread_desk != NULL, "GetThreadDesktop failed!\n");
766 ok(w1 != NULL, "GetProcessWindowStation failed!\n");
767 SetLastError(0xdeadbeef);
768 w2 = CreateWindowStationA("winsta_test", 0, WINSTA_ALL_ACCESS, NULL);
769 ret = GetLastError();
770 ok(w2 != NULL || ret == ERROR_ACCESS_DENIED, "CreateWindowStation failed (%lu)\n", ret);
771 if (!w2)
772 {
773 win_skip("Not enough privileges for CreateWindowStation\n");
774 return;
775 }
776
778 ok(!ret, "EnumDesktopsA failed!\n");
779 input_desk = OpenInputDesktop(0, FALSE, DESKTOP_ALL_ACCESS);
780 ok(input_desk != NULL, "OpenInputDesktop failed!\n");
781 ret = CloseDesktop(input_desk);
782 ok(ret, "CloseDesktop failed!\n");
783
785 ok(ret, "SetProcessWindowStation failed!\n");
787 ok(hdesk != NULL, "GetThreadDesktop failed!\n");
788 ok(hdesk == thread_desk, "thread desktop should not change after winstation changed!\n");
790
791 new_desk = CreateDesktopA("desk_test", NULL, NULL, 0, DESKTOP_ALL_ACCESS, NULL);
792 ok(new_desk != NULL, "CreateDesktop failed!\n");
794 ok(!ret, "EnumDesktopsA failed!\n");
795 SetLastError(0xdeadbeef);
796 input_desk = OpenInputDesktop(0, FALSE, DESKTOP_ALL_ACCESS);
797 ok(input_desk == NULL, "OpenInputDesktop should fail on non default winstation!\n");
798 ok(GetLastError() == ERROR_INVALID_FUNCTION || broken(GetLastError() == 0xdeadbeef), "last error %08lx\n", GetLastError());
799
800 hdesk = OpenDesktopA("desk_test", 0, TRUE, DESKTOP_ALL_ACCESS);
801 ok(hdesk != NULL, "OpenDesktop failed!\n");
802 SetLastError(0xdeadbeef);
803 ret = SwitchDesktop(hdesk);
804 ok(!ret, "Switch to desktop belong to non default winstation should fail!\n");
806 ok(GetLastError() == ERROR_ACCESS_DENIED || broken(GetLastError() == 0xdeadbeef), "last error %08lx\n", GetLastError());
807 ret = SetThreadDesktop(hdesk);
808 ok(ret, "SetThreadDesktop failed!\n");
809
810 /* clean side effect */
811 ret = SetThreadDesktop(thread_desk);
813 ok(ret, "SetThreadDesktop should success even desktop is not belong to process winstation!\n");
815 ok(ret, "SetProcessWindowStation failed!\n");
816 ret = SetThreadDesktop(thread_desk);
817 ok(ret, "SetThreadDesktop failed!\n");
819 ok(ret, "CloseWindowStation failed!\n");
820 ret = CloseDesktop(new_desk);
821 ok(ret, "CloseDesktop failed!\n");
822 ret = CloseDesktop(hdesk);
823 ok(ret, "CloseDesktop failed!\n");
824}
825
827{
828 if (msg == WM_DESTROY)
829 {
830 trace("destroying hwnd %p\n", hWnd);
832 return 0;
833 }
834 return DefWindowProcA( hWnd, msg, wParam, lParam );
835}
836
837typedef struct tag_wnd_param
838{
839 const char *wnd_name;
841 HDESK hdesk;
844
846{
847 wnd_param *param1 = param;
848 DWORD ret;
849 MSG msg;
850
851 ret = SetThreadDesktop(param1->hdesk);
852 ok(ret, "SetThreadDesktop failed!\n");
853 param1->hwnd = CreateWindowA("test_class", param1->wnd_name, WS_POPUP, 0, 0, 100, 100, NULL, NULL, NULL, NULL);
854 ok(param1->hwnd != 0, "CreateWindowA failed!\n");
855 ret = SetEvent(param1->hevent);
856 ok(ret, "SetEvent failed!\n");
857
858 while (GetMessageA(&msg, 0, 0, 0))
859 {
862 }
863
864 return 0;
865}
866
868{
869 HWND hwnd_fore;
870 DWORD set_id, fore_id, ret;
871 char win_text[1024];
872
873 hwnd_fore = GetForegroundWindow();
874 GetWindowTextA(hwnd_fore, win_text, 1024);
876 fore_id = GetWindowThreadProcessId(hwnd_fore, NULL);
877 trace("\"%s\" %p %08lx hwnd %p %08lx\n", win_text, hwnd_fore, fore_id, hwnd, set_id);
878 ret = AttachThreadInput(set_id, fore_id, TRUE);
879 trace("AttachThreadInput returned %08lx\n", ret);
881 trace("ShowWindow returned %08lx\n", ret);
883 trace("set topmost returned %08lx\n", ret);
885 trace("set notopmost returned %08lx\n", ret);
887 trace("SetForegroundWindow returned %08lx\n", ret);
888 Sleep(250);
889 AttachThreadInput(set_id, fore_id, FALSE);
890 return ret;
891}
892
893static void test_foregroundwindow(void)
894{
895 HWND hwnd, hwnd_test, partners[2], hwnds[2];
896 HDESK hdesks[2];
897 int thread_desk_id, input_desk_id, hwnd_id;
898 WNDCLASSA wclass;
900 DWORD ret, timeout, timeout_old;
901 char win_text[1024];
902
903#define DESKTOPS 2
904
905 memset( &wclass, 0, sizeof(wclass) );
906 wclass.lpszClassName = "test_class";
907 wclass.lpfnWndProc = WndProc;
908 RegisterClassA(&wclass);
909 param.wnd_name = "win_name";
910
912 ok(hdesks[0] != NULL, "OpenDesktop failed!\n");
913 SetLastError(0xdeadbeef);
914 hdesks[1] = CreateDesktopA("desk2", NULL, NULL, 0, DESKTOP_ALL_ACCESS, NULL);
915 ret = GetLastError();
916 ok(hdesks[1] != NULL || ret == ERROR_ACCESS_DENIED, "CreateDesktop failed (%lu)\n", ret);
917 if(!hdesks[1])
918 {
919 win_skip("Not enough privileges for CreateDesktop\n");
920 return;
921 }
922
923 ret = SystemParametersInfoA(SPI_GETFOREGROUNDLOCKTIMEOUT, 0, &timeout_old, 0);
924 if(!ret)
925 {
926 win_skip("Skip tests on NT4\n");
927 CloseDesktop(hdesks[1]);
928 return;
929 }
930 trace("old timeout %ld\n", timeout_old);
931 timeout = 0;
932 ret = SystemParametersInfoA(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, 0, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
933 ok(ret, "set foreground lock timeout failed!\n");
934 ret = SystemParametersInfoA(SPI_GETFOREGROUNDLOCKTIMEOUT, 0, &timeout, 0);
935 ok(ret, "get foreground lock timeout failed!\n");
936 ok(timeout == 0, "unexpected timeout %ld\n", timeout);
937
938 for (thread_desk_id = 0; thread_desk_id < DESKTOPS; thread_desk_id++)
939 {
940 param.hdesk = hdesks[thread_desk_id];
941 param.hevent = CreateEventA(NULL, TRUE, FALSE, NULL);
944 ok(ret == WAIT_OBJECT_0, "wait failed!\n");
945 hwnds[thread_desk_id] = param.hwnd;
946 }
947
948 for (thread_desk_id = 0; thread_desk_id < DESKTOPS; thread_desk_id++)
949 {
950 param.hdesk = hdesks[thread_desk_id];
951 param.hevent = CreateEventA(NULL, TRUE, FALSE, NULL);
954 ok(ret == WAIT_OBJECT_0, "wait failed!\n");
955 partners[thread_desk_id] = param.hwnd;
956 }
957
958 trace("hwnd0 %p hwnd1 %p partner0 %p partner1 %p\n", hwnds[0], hwnds[1], partners[0], partners[1]);
959
960 for (hwnd_id = 0; hwnd_id < DESKTOPS; hwnd_id++)
961 for (thread_desk_id = 0; thread_desk_id < DESKTOPS; thread_desk_id++)
962 for (input_desk_id = 0; input_desk_id < DESKTOPS; input_desk_id++)
963 {
964 trace("testing thread_desk %d input_desk %d hwnd %d\n",
965 thread_desk_id, input_desk_id, hwnd_id);
966 hwnd_test = hwnds[hwnd_id];
967 ret = SetThreadDesktop(hdesks[thread_desk_id]);
968 ok(ret, "set thread desktop failed!\n");
969 ret = SwitchDesktop(hdesks[input_desk_id]);
970 ok(ret, "switch desktop failed!\n");
971 set_foreground(partners[0]);
972 set_foreground(partners[1]);
974 ok(hwnd != hwnd_test, "unexpected foreground window %p\n", hwnd);
975 ret = set_foreground(hwnd_test);
977 GetWindowTextA(hwnd, win_text, 1024);
978 trace("hwnd %p name %s\n", hwnd, win_text);
979 if (input_desk_id == hwnd_id)
980 {
981 if (input_desk_id == thread_desk_id)
982 {
983 ok(ret, "SetForegroundWindow failed!\n");
985 ok(hwnd == hwnd_test , "unexpected foreground window %p\n", hwnd);
986 }
987 else
988 {
989 todo_wine ok(ret, "SetForegroundWindow failed!\n");
990 todo_wine ok(hwnd == 0, "unexpected foreground window %p\n", hwnd);
991 }
992 }
993 else
994 {
995 if (input_desk_id == thread_desk_id)
996 {
997 ok(!ret, "SetForegroundWindow should fail!\n");
999 ok(hwnd == partners[input_desk_id] , "unexpected foreground window %p\n", hwnd);
1000 }
1001 else
1002 {
1003 todo_wine ok(!ret, "SetForegroundWindow should fail!\n");
1005 ok(hwnd == 0, "unexpected foreground window %p\n", hwnd);
1006 }
1007 }
1008 }
1009
1010 /* Clean up */
1011
1012 for (thread_desk_id = DESKTOPS - 1; thread_desk_id >= 0; thread_desk_id--)
1013 {
1014 ret = SetThreadDesktop(hdesks[thread_desk_id]);
1015 ok(ret, "set thread desktop failed!\n");
1016 SendMessageA(hwnds[thread_desk_id], WM_DESTROY, 0, 0);
1017 SendMessageA(partners[thread_desk_id], WM_DESTROY, 0, 0);
1018 }
1019
1020 ret = SwitchDesktop(hdesks[0]);
1021 ok(ret, "switch desktop failed!\n");
1022 CloseDesktop(hdesks[1]);
1023
1024 ret = SystemParametersInfoA(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, UlongToPtr(timeout_old), SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
1025 ok(ret, "set foreground lock timeout failed!\n");
1026 ret = SystemParametersInfoA(SPI_GETFOREGROUNDLOCKTIMEOUT, 0, &timeout, 0);
1027 ok(ret, "get foreground lock timeout failed!\n");
1028 ok(timeout == timeout_old, "unexpected timeout %ld\n", timeout);
1029}
1030
1031static void test_invisible_winstation_child(char *expected_info)
1032{
1033 char buffer[MAX_PATH];
1034 HDESK desktop;
1035 HWND hwnd;
1036 int ret;
1037
1039 ok(!!desktop, "GetThreadDesktop failed, error %lu.\n", GetLastError());
1040
1041 ret = GetUserObjectInformationA(desktop, UOI_NAME, &buffer, sizeof(buffer), NULL);
1042 ok(ret, "GetUserObjectInformationA failed, error %lu.\n", GetLastError());
1043 ok(!strcmp(buffer, "invisible_winstation_desktop"), "Got unexpected desktop %s.\n", buffer);
1044
1048 ok(!strcmp(buffer, expected_info), "Expected %s, got %s.\n", expected_info, buffer);
1049
1051 ok(!!hwnd, "GetDesktopWindow failed, error %lu.\n", GetLastError());
1052
1054 ok(ret == HTCLIENT, "SendMessageW failed, error %lu.\n", GetLastError());
1055}
1056
1058{
1059 char buffer[MAX_PATH], desktop_name[MAX_PATH];
1060 HWINSTA old_winstation, winstation;
1061 PROCESS_INFORMATION pi = {0};
1062 STARTUPINFOA si = {0};
1063 HDESK desktop;
1064 BOOL ret;
1065
1066 old_winstation = GetProcessWindowStation();
1067 ok(!!old_winstation, "GetProcessWindowStation failed, error %lu.\n", GetLastError());
1069 ok(!!winstation, "CreateWindowStationW failed, error %lu.\n", GetLastError());
1070 ret = SetProcessWindowStation(winstation);
1071 ok(ret, "SetProcessWindowStation failed, error %lu.\n", GetLastError());
1072 desktop = CreateDesktopA("invisible_winstation_desktop", NULL, NULL, 0, DESKTOP_CREATEWINDOW, NULL);
1073 ok(!!desktop, "CreateDesktopA failed, error %lu.\n", GetLastError());
1074
1075 ret = GetUserObjectInformationA(winstation, UOI_NAME, buffer, sizeof(buffer), NULL);
1076 ok(ret, "GetUserObjectInformationA failed, error %lu.\n", GetLastError());
1077 strcpy(desktop_name, buffer);
1078 strcat(desktop_name, "\\invisible_winstation_desktop");
1079
1080 si.cb = sizeof(si);
1081 si.lpDesktop = desktop_name;
1082
1083 sprintf(buffer, "\"%s\" %s invisible %d,%d,%d,%d,%d", argv[0], argv[1],
1087 ret = CreateProcessA(argv[0], buffer, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
1088 ok(ret, "CreateProcessA failed, error %lu.\n", GetLastError());
1089
1093 CloseDesktop(desktop);
1094 CloseWindowStation(winstation);
1095 SetProcessWindowStation(old_winstation);
1096}
1097
1098static void test_get_security(void)
1099{
1101 HDESK desktop = GetThreadDesktop(GetCurrentThreadId());
1102 DWORD size, expect_size;
1103 char buffer[500];
1104 BOOL ret;
1105
1106 size = 0xdeadbeef;
1107 SetLastError(0xdeadbeef);
1108 ret = GetUserObjectSecurity( desktop, &info, NULL, 0, &size );
1109 ok( !ret, "got %#x\n", ret );
1110 ok( GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got error %lu\n", GetLastError() );
1111 ok( size && size < sizeof(buffer), "got size %lu\n", size );
1112 expect_size = size;
1113
1114 size = 0xdeadbeef;
1115 SetLastError(0xdeadbeef);
1116 ret = GetUserObjectSecurity( desktop, &info, buffer, sizeof(buffer), &size );
1117 ok( ret == TRUE, "got %#x\n", ret );
1118 ok( GetLastError() == 0xdeadbeef, "got error %lu\n", GetLastError() );
1119 ok( size == expect_size, "got size %lu\n", size );
1120 ok( IsValidSecurityDescriptor(buffer), "expected valid SD\n" );
1121}
1122
1123START_TEST(winstation)
1124{
1125 char **argv;
1126 int argc;
1127 HMODULE hntdll = GetModuleHandleA("ntdll.dll");
1128 pNtQueryObject = (void *)GetProcAddress(hntdll, "NtQueryObject");
1129
1130 /* Check whether this platform supports WindowStation calls */
1131
1132 SetLastError( 0xdeadbeef );
1135 {
1136 win_skip("WindowStation calls not supported on this platform\n");
1137 return;
1138 }
1139
1141 if (argc > 2)
1142 {
1143 if (!lstrcmpA(argv[2], "invisible"))
1145
1146 return;
1147 }
1152 test_handles();
1157}
@ ObjectBasicInformation
Definition: DriverTester.h:54
@ ObjectNameInformation
Definition: DriverTester.h:55
#define trace
Definition: atltest.h:70
#define ok(value,...)
Definition: atltest.h:57
#define broken(x)
Definition: atltest.h:178
#define START_TEST(x)
Definition: atltest.h:75
ATOM WINAPI GlobalAddAtomA(LPCSTR lpString)
Definition: atomansi.c:23
#define msg(x)
Definition: auth_time.c:54
HWND hWnd
Definition: settings.c:17
LONG NTSTATUS
Definition: precomp.h:26
EXTERN_C NTSTATUS WINAPI NtQueryObject(HANDLE, OBJECT_INFORMATION_CLASS, PVOID, ULONG, PULONG)
static HANDLE thread
Definition: service.c:33
WPARAM wParam
Definition: combotst.c:138
LPARAM lParam
Definition: combotst.c:139
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10
#define ERROR_BUSY
Definition: dderror.h:12
#define ERROR_INVALID_FUNCTION
Definition: dderror.h:6
WORD ATOM
Definition: dimm.idl:113
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NTSTATUS
Definition: precomp.h:19
BOOL WINAPI GetTokenInformation(HANDLE TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, LPVOID TokenInformation, DWORD TokenInformationLength, PDWORD ReturnLength)
Definition: security.c:411
#define CloseHandle
Definition: compat.h:739
#define ERROR_CALL_NOT_IMPLEMENTED
Definition: compat.h:102
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define SetLastError(x)
Definition: compat.h:752
#define GetProcAddress(x, y)
Definition: compat.h:753
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define GetCurrentProcess()
Definition: compat.h:759
#define GENERIC_READ
Definition: compat.h:135
#define MAX_PATH
Definition: compat.h:34
#define ERROR_INVALID_HANDLE
Definition: compat.h:98
#define CALLBACK
Definition: compat.h:35
#define ERROR_ACCESS_DENIED
Definition: compat.h:97
UINT WINAPI GlobalGetAtomNameA(ATOM nAtom, LPSTR lpBuffer, int nSize)
Definition: atom.c:464
BOOL WINAPI GetHandleInformation(IN HANDLE hObject, OUT LPDWORD lpdwFlags)
Definition: handle.c:40
BOOL WINAPI DuplicateHandle(IN HANDLE hSourceProcessHandle, IN HANDLE hSourceHandle, IN HANDLE hTargetProcessHandle, OUT LPHANDLE lpTargetHandle, IN DWORD dwDesiredAccess, IN BOOL bInheritHandle, IN DWORD dwOptions)
Definition: handle.c:149
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:812
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:137
int WINAPI lstrcmpW(LPCWSTR str1, LPCWSTR str2)
Definition: locale.c:4152
int WINAPI lstrcmpA(LPCSTR str1, LPCSTR str2)
Definition: locale.c:4104
int WINAPI lstrcmpiA(LPCSTR str1, LPCSTR str2)
Definition: locale.c:4133
BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessA(const char *app_name, char *cmd_line, SECURITY_ATTRIBUTES *process_attr, SECURITY_ATTRIBUTES *thread_attr, BOOL inherit, DWORD flags, void *env, const char *cur_dir, STARTUPINFOA *startup_info, PROCESS_INFORMATION *info)
Definition: process.c:686
MonoAssembly int argc
Definition: metahost.c:107
_ACRTIMP int __cdecl strcmp(const char *, const char *)
Definition: string.c:3319
return ret
Definition: mutex.c:146
#define INFINITE
Definition: serial.h:102
#define UlongToPtr(u)
Definition: config.h:106
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint GLdouble GLdouble w2
Definition: glext.h:8308
GLuint buffer
Definition: glext.h:5915
GLsizeiptr size
Definition: glext.h:5919
GLbitfield flags
Definition: glext.h:7161
GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint GLdouble w1
Definition: glext.h:8308
GLfloat param
Definition: glext.h:5796
GLuint id
Definition: glext.h:5910
#define wine_dbgstr_w
Definition: kernel32.h:34
#define win_skip
Definition: minitest.h:67
#define todo_wine_if(is_todo)
Definition: minitest.h:81
#define todo_wine
Definition: minitest.h:80
LONG_PTR LPARAM
Definition: minwindef.h:175
LONG_PTR LRESULT
Definition: minwindef.h:176
UINT_PTR WPARAM
Definition: minwindef.h:174
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
#define sprintf
Definition: sprintf.c:45
static HWND create_window(void)
Definition: imagelist.c:159
static PROCESS_INFORMATION pi
Definition: debugger.c:2303
static HINSTANCE hntdll
Definition: process.c:68
static SYSTEM_INFO si
Definition: virtual.c:39
#define argv
Definition: mplay32.c:18
DWORD SECURITY_INFORMATION
Definition: ms-dtyp.idl:311
unsigned int UINT
Definition: ndis.h:50
#define STANDARD_RIGHTS_REQUIRED
Definition: nt_native.h:63
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:455
#define WS_POPUP
Definition: pedump.c:616
strcat
Definition: string.h:92
strcpy
Definition: string.h:131
int winetest_get_mainargs(char ***pargv)
#define wait_child_process
Definition: test.h:159
#define memset(x, y, z)
Definition: compat.h:39
BOOL WINAPI IsValidSecurityDescriptor(PSECURITY_DESCRIPTOR pSecurityDescriptor)
Definition: sec.c:176
LONG HighPart
DWORD LowPart
UNICODE_STRING Name
Definition: nt_native.h:1273
LUID AuthenticationId
Definition: setypes.h:1099
HBRUSH hbrBackground
Definition: winuser.h:3278
HICON hIcon
Definition: winuser.h:3276
HINSTANCE hInstance
Definition: winuser.h:3275
HCURSOR hCursor
Definition: winuser.h:3277
int cbWndExtra
Definition: winuser.h:3274
UINT style
Definition: winuser.h:3271
LPCSTR lpszMenuName
Definition: winuser.h:3279
LPCSTR lpszClassName
Definition: winuser.h:3280
WNDPROC lpfnWndProc
Definition: winuser.h:3272
int cbClsExtra
Definition: winuser.h:3273
Definition: name.c:39
Definition: ps.c:97
KEYBDINPUT ki
Definition: winable.h:62
DWORD type
Definition: winable.h:59
DWORD dwFlags
Definition: winable.h:49
WORD wVk
Definition: winable.h:47
WORD wScan
Definition: winable.h:48
const char * wnd_name
Definition: winstation.c:839
HANDLE hevent
Definition: winstation.c:842
Definition: dhcpd.h:248
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
Definition: synch.c:726
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventA(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCSTR lpName OPTIONAL)
Definition: synch.c:573
HANDLE WINAPI DECLSPEC_HOTPATCH CreateMutexA(IN LPSECURITY_ATTRIBUTES lpMutexAttributes OPTIONAL, IN BOOL bInitialOwner, IN LPCSTR lpName OPTIONAL)
Definition: synch.c:512
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:669
TW_UINT32 TW_UINT16 TW_UINT16 MSG
Definition: twain.h:1829
PVOID HANDLE
Definition: typedefs.h:73
HDESK WINAPI CreateDesktopA(LPCSTR lpszDesktop, LPCSTR lpszDevice, LPDEVMODEA pDevmode, DWORD dwFlags, ACCESS_MASK dwDesiredAccess, LPSECURITY_ATTRIBUTES lpsa)
Definition: desktop.c:431
int WINAPI GetWindowTextA(HWND hWnd, LPSTR lpString, int nMaxCount)
Definition: window.c:1300
UINT WINAPI SendInput(UINT, LPINPUT, int)
Definition: ntwrapper.h:344
#define INPUT_KEYBOARD
Definition: winable.h:10
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
DWORD WINAPI GetCurrentThreadId(void)
Definition: thread.c:459
#define HANDLE_FLAG_PROTECT_FROM_CLOSE
Definition: winbase.h:289
DWORD WINAPI GetWindowThreadProcessId(HWND hWnd, PDWORD lpdwProcessId)
HWINSTA WINAPI GetProcessWindowStation(void)
Definition: ntwrapper.h:124
#define WAIT_OBJECT_0
Definition: winbase.h:383
_In_ LONG _In_ HWND hwnd
Definition: winddi.h:4023
#define WINAPI
Definition: msvc.h:6
#define ERROR_PATH_NOT_FOUND
Definition: winerror.h:228
#define ERROR_BAD_PATHNAME
Definition: winerror.h:355
static void register_class(void)
Definition: winstation.c:55
static BOOL CALLBACK desktop_callbackA(LPSTR desktop, LPARAM lp)
Definition: winstation.c:427
static void test_inputdesktop(void)
Definition: winstation.c:596
#define DESKTOPS
static void test_invisible_winstation(char **argv)
Definition: winstation.c:1057
static void test_foregroundwindow(void)
Definition: winstation.c:893
static void test_invisible_winstation_child(char *expected_info)
Definition: winstation.c:1031
static BOOL CALLBACK window_station_callbackA(LPSTR winsta, LPARAM lp)
Definition: winstation.c:376
static void test_get_security(void)
Definition: winstation.c:1098
static DWORD set_foreground(HWND hwnd)
Definition: winstation.c:867
static void test_enumdesktops(void)
Definition: winstation.c:450
static ULONG
Definition: winstation.c:34
static void test_getuserobjectinformation(void)
Definition: winstation.c:485
static BOOL CALLBACK open_window_station_callbackA(LPSTR winsta, LPARAM lp)
Definition: winstation.c:382
static void test_inputdesktop2(void)
Definition: winstation.c:757
static void test_enumstations(void)
Definition: winstation.c:394
static PVOID
Definition: winstation.c:34
struct tag_wnd_param wnd_param
#define DESKTOP_ALL_ACCESS
Definition: winstation.c:36
static OBJECT_INFORMATION_CLASS
Definition: winstation.c:34
static void print_object(HANDLE obj)
Definition: winstation.c:38
static LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
Definition: winstation.c:826
static BOOL CALLBACK open_desktop_callbackA(LPSTR desktop, LPARAM lp)
Definition: winstation.c:433
static PULONG
Definition: winstation.c:34
static HDESK initial_desktop
Definition: winstation.c:77
static void test_handles(void)
Definition: winstation.c:120
HGDIOBJ WINAPI GetStockObject(_In_ int)
#define WHITE_BRUSH
Definition: wingdi.h:902
#define SW_SHOWNORMAL
Definition: winuser.h:781
HDESK WINAPI GetThreadDesktop(_In_ DWORD)
LRESULT WINAPI DispatchMessageA(_In_ const MSG *)
#define SM_CYVIRTUALSCREEN
Definition: winuser.h:1050
#define DESKTOP_CREATEWINDOW
Definition: winuser.h:217
BOOL WINAPI TranslateMessage(_In_ const MSG *)
HWND WINAPI CreateWindowExA(_In_ DWORD dwExStyle, _In_opt_ LPCSTR lpClassName, _In_opt_ LPCSTR lpWindowName, _In_ DWORD dwStyle, _In_ int X, _In_ int Y, _In_ int nWidth, _In_ int nHeight, _In_opt_ HWND hWndParent, _In_opt_ HMENU hMenu, _In_opt_ HINSTANCE hInstance, _In_opt_ LPVOID lpParam)
BOOL WINAPI ShowWindow(_In_ HWND, _In_ int)
HWND WINAPI GetForegroundWindow(void)
Definition: ntwrapper.h:392
BOOL WINAPI SwitchDesktop(_In_ HDESK)
HWINSTA WINAPI OpenWindowStationA(_In_ LPCSTR, _In_ BOOL, _In_ DWORD)
#define HWND_TOPMOST
Definition: winuser.h:1219
BOOL WINAPI AttachThreadInput(_In_ DWORD, _In_ DWORD, _In_ BOOL)
LRESULT WINAPI DefWindowProcA(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
BOOL WINAPI SetThreadDesktop(_In_ HDESK)
HWINSTA WINAPI CreateWindowStationW(_In_opt_ LPCWSTR lpwinsta, _In_ DWORD dwFlags, _In_ ACCESS_MASK dwDesiredAccess, _In_opt_ LPSECURITY_ATTRIBUTES lpsa)
#define CreateWindowA(a, b, c, d, e, f, g, h, i, j, k)
Definition: winuser.h:4469
BOOL WINAPI SetWindowPos(_In_ HWND, _In_opt_ HWND, _In_ int, _In_ int, _In_ int, _In_ int, _In_ UINT)
#define UOI_NAME
Definition: winuser.h:1095
__analysis_noreturn void WINAPI PostQuitMessage(_In_ int)
HDESK WINAPI OpenInputDesktop(_In_ DWORD, _In_ BOOL, _In_ DWORD)
HDESK WINAPI OpenDesktopA(_In_ LPCSTR, _In_ DWORD, _In_ BOOL, _In_ DWORD)
#define SWP_NOMOVE
Definition: winuser.h:1255
#define DESKTOP_ENUMERATE
Definition: winuser.h:218
BOOL WINAPI SetForegroundWindow(_In_ HWND)
#define IDC_ARROW
Definition: winuser.h:695
#define WM_NCHITTEST
Definition: winuser.h:1714
#define UOI_TYPE
Definition: winuser.h:1096
LRESULT WINAPI SendMessageA(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
HWINSTA WINAPI CreateWindowStationA(_In_opt_ LPCSTR lpwinsta, _In_ DWORD dwFlags, _In_ ACCESS_MASK dwDesiredAccess, _In_opt_ LPSECURITY_ATTRIBUTES lpsa)
#define SWP_NOSIZE
Definition: winuser.h:1256
BOOL WINAPI CloseWindowStation(_In_ HWINSTA)
#define CS_DBLCLKS
Definition: winuser.h:659
BOOL WINAPI EnumWindowStationsA(_In_ WINSTAENUMPROCA, _In_ LPARAM lParam)
BOOL WINAPI SetProcessWindowStation(_In_ HWINSTA)
#define SPIF_SENDCHANGE
Definition: winuser.h:1600
HWND WINAPI GetDesktopWindow(void)
Definition: window.c:628
#define SM_CXVIRTUALSCREEN
Definition: winuser.h:1049
#define WINSTA_ALL_ACCESS
Definition: winuser.h:417
#define SPIF_UPDATEINIFILE
Definition: winuser.h:1599
ATOM WINAPI RegisterClassA(_In_ CONST WNDCLASSA *)
#define WINSTA_ENUMERATE
Definition: winuser.h:412
#define HTCLIENT
Definition: winuser.h:2511
BOOL WINAPI GetUserObjectInformationW(_In_ HANDLE hObj, _In_ int nIndex, _Out_writes_bytes_opt_(nLength) PVOID pvInfo, _In_ DWORD nLength, _Out_opt_ LPDWORD lpnLengthNeeded)
BOOL WINAPI GetUserObjectInformationA(_In_ HANDLE hObj, _In_ int nIndex, _Out_writes_bytes_opt_(nLength) PVOID pvInfo, _In_ DWORD nLength, _Out_opt_ LPDWORD lpnLengthNeeded)
BOOL WINAPI SystemParametersInfoA(_In_ UINT uiAction, _In_ UINT uiParam, _Inout_opt_ PVOID pvParam, _In_ UINT fWinIni)
#define WM_DESTROY
Definition: winuser.h:1637
#define SM_XVIRTUALSCREEN
Definition: winuser.h:1047
BOOL WINAPI CloseDesktop(_In_ HDESK)
BOOL WINAPI GetMessageA(_Out_ LPMSG, _In_opt_ HWND, _In_ UINT, _In_ UINT)
#define SM_CMONITORS
Definition: winuser.h:1051
#define HWND_NOTOPMOST
Definition: winuser.h:1217
BOOL WINAPI DestroyWindow(_In_ HWND)
int WINAPI GetSystemMetrics(_In_ int)
LRESULT WINAPI SendMessageW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
#define SM_YVIRTUALSCREEN
Definition: winuser.h:1048
#define WINSTA_CREATEDESKTOP
Definition: winuser.h:410
HCURSOR WINAPI LoadCursorA(_In_opt_ HINSTANCE, _In_ LPCSTR)
Definition: cursoricon.c:2459
BOOL WINAPI EnumDesktopsA(_In_opt_ HWINSTA, _In_ DESKTOPENUMPROCA, _In_ LPARAM)
BOOL WINAPI GetUserObjectSecurity(_In_ HANDLE hObj, _In_ PSECURITY_INFORMATION pSIRequested, _Out_writes_bytes_opt_(nLength) PSECURITY_DESCRIPTOR pSID, _In_ DWORD nLength, _Out_ LPDWORD lpnLengthNeeded)
#define DUPLICATE_SAME_ACCESS
#define DACL_SECURITY_INFORMATION
Definition: setypes.h:125
@ TokenStatistics
Definition: setypes.h:987
const char * LPCSTR
Definition: xmlstorage.h:183
__wchar_t WCHAR
Definition: xmlstorage.h:180
char * LPSTR
Definition: xmlstorage.h:182
char CHAR
Definition: xmlstorage.h:175