ReactOS  0.4.13-dev-92-gf251225
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 #include "wine/test.h"
22 #include "winbase.h"
23 #include "wingdi.h"
24 #include "winuser.h"
25 #include "winnls.h"
26 #include "wine/winternl.h"
27 
29 
30 #define DESKTOP_ALL_ACCESS 0x01ff
31 
32 static void print_object( HANDLE obj )
33 {
34  char buffer[100];
35  DWORD size;
36 
37  strcpy( buffer, "foobar" );
39  trace( "could not get info for %p\n", obj );
40  else
41  trace( "obj %p name '%s'\n", obj, buffer );
42  strcpy( buffer, "foobar" );
44  trace( "could not get type for %p\n", obj );
45  else
46  trace( "obj %p type '%s'\n", obj, buffer );
47 }
48 
49 static void register_class(void)
50 {
51  WNDCLASSA cls;
52 
53  cls.style = CS_DBLCLKS;
55  cls.cbClsExtra = 0;
56  cls.cbWndExtra = 0;
57  cls.hInstance = GetModuleHandleA(0);
58  cls.hIcon = 0;
61  cls.lpszMenuName = NULL;
62  cls.lpszClassName = "WinStationClass";
63  RegisterClassA(&cls);
64 }
65 
66 static HDESK initial_desktop;
67 
69 {
70  HDESK d1, d2;
71  HWND hwnd = CreateWindowExA(0,"WinStationClass","test",WS_POPUP,0,0,100,100,GetDesktopWindow(),0,0,0);
72  ok( hwnd != 0, "CreateWindow failed\n" );
74  trace( "thread %p desktop: %p\n", arg, d1 );
75  ok( d1 == initial_desktop, "thread %p doesn't use initial desktop\n", arg );
76 
77  SetLastError( 0xdeadbeef );
78  ok( !CloseHandle( d1 ), "CloseHandle succeeded\n" );
79  ok( GetLastError() == ERROR_INVALID_HANDLE, "bad last error %d\n", GetLastError() );
80  SetLastError( 0xdeadbeef );
81  ok( !CloseDesktop( d1 ), "CloseDesktop succeeded\n" );
82  ok( GetLastError() == ERROR_BUSY || broken(GetLastError() == 0xdeadbeef), /* wow64 */
83  "bad last error %d\n", GetLastError() );
84  print_object( d1 );
85  d2 = CreateDesktopA( "foobar2", NULL, NULL, 0, DESKTOP_ALL_ACCESS, NULL );
86  trace( "created desktop %p\n", d2 );
87  ok( d2 != 0, "CreateDesktop failed\n" );
88 
89  SetLastError( 0xdeadbeef );
90  ok( !SetThreadDesktop( d2 ), "set thread desktop succeeded with existing window\n" );
91  ok( GetLastError() == ERROR_BUSY || broken(GetLastError() == 0xdeadbeef), /* wow64 */
92  "bad last error %d\n", GetLastError() );
93 
95  ok( SetThreadDesktop( d2 ), "set thread desktop failed\n" );
97  ok( d1 == d2, "GetThreadDesktop did not return set desktop %p/%p\n", d1, d2 );
98  print_object( d2 );
99  if (arg < (LPVOID)5)
100  {
101  HANDLE hthread = CreateThread( NULL, 0, thread, (char *)arg + 1, 0, NULL );
102  Sleep(1000);
103  WaitForSingleObject( hthread, INFINITE );
104  CloseHandle( hthread );
105  }
106  return 0;
107 }
108 
109 static void test_handles(void)
110 {
111  HWINSTA w1, w2, w3;
112  HDESK d1, d2, d3;
113  HANDLE hthread;
114  DWORD id, flags, le;
115  ATOM atom;
116  char buffer[20];
117  DWORD size;
118  BOOL ret;
119 
120  /* win stations */
121 
123  ok( GetProcessWindowStation() == w1, "GetProcessWindowStation returned different handles\n" );
124  ok( !CloseWindowStation(w1), "closing process win station succeeded\n" );
125  SetLastError( 0xdeadbeef );
126  ok( !CloseHandle(w1), "closing process win station handle succeeded\n" );
127  ok( GetLastError() == ERROR_INVALID_HANDLE, "bad last error %d\n", GetLastError() );
128  print_object( w1 );
129 
130  flags = 0;
131  ok( GetHandleInformation( w1, &flags ), "GetHandleInformation failed\n" );
133  broken(flags & HANDLE_FLAG_PROTECT_FROM_CLOSE), /* set on nt4 */
134  "handle %p PROTECT_FROM_CLOSE set\n", w1 );
135 
137  TRUE, DUPLICATE_SAME_ACCESS ), "DuplicateHandle failed\n" );
138  ok( CloseWindowStation(w2), "closing dup win station failed\n" );
139 
141  TRUE, DUPLICATE_SAME_ACCESS ), "DuplicateHandle failed\n" );
142  ok( CloseHandle(w2), "closing dup win station handle failed\n" );
143 
144  w2 = CreateWindowStationA("WinSta0", 0, WINSTA_ALL_ACCESS, NULL );
145  le = GetLastError();
146  ok( w2 != 0 || le == ERROR_ACCESS_DENIED, "CreateWindowStation failed (%u)\n", le );
147  if (w2 != 0)
148  {
149  ok( w2 != w1, "CreateWindowStation returned default handle\n" );
150  SetLastError( 0xdeadbeef );
151  ok( !CloseDesktop( (HDESK)w2 ), "CloseDesktop succeeded on win station\n" );
152  ok( GetLastError() == ERROR_INVALID_HANDLE || broken(GetLastError() == 0xdeadbeef), /* wow64 */
153  "bad last error %d\n", GetLastError() );
154  ok( CloseWindowStation( w2 ), "CloseWindowStation failed\n" );
155 
156  w2 = CreateWindowStationA("WinSta0", 0, WINSTA_ALL_ACCESS, NULL );
157  ok( CloseHandle( w2 ), "CloseHandle failed\n" );
158  }
159  else if (le == ERROR_ACCESS_DENIED)
160  win_skip( "Not enough privileges for CreateWindowStation\n" );
161 
163  ok( w2 != 0, "OpenWindowStation failed\n" );
164  ok( w2 != w1, "OpenWindowStation returned default handle\n" );
165  ok( CloseWindowStation( w2 ), "CloseWindowStation failed\n" );
166 
167  w2 = OpenWindowStationA("dummy name", TRUE, WINSTA_ALL_ACCESS );
168  ok( !w2, "open dummy win station succeeded\n" );
169 
170  CreateMutexA( NULL, 0, "foobar" );
171  w2 = CreateWindowStationA("foobar", 0, WINSTA_ALL_ACCESS, NULL );
172  le = GetLastError();
173  ok( w2 != 0 || le == ERROR_ACCESS_DENIED, "create foobar station failed (%u)\n", le );
174 
175  if (w2 != 0)
176  {
177  w3 = OpenWindowStationA("foobar", TRUE, WINSTA_ALL_ACCESS );
178  ok( w3 != 0, "open foobar station failed\n" );
179  ok( w3 != w2, "open foobar station returned same handle\n" );
180  ok( CloseWindowStation( w2 ), "CloseWindowStation failed\n" );
181  ok( CloseWindowStation( w3 ), "CloseWindowStation failed\n" );
182 
183  w3 = OpenWindowStationA("foobar", TRUE, WINSTA_ALL_ACCESS );
184  ok( !w3, "open foobar station succeeded\n" );
185 
186  w2 = CreateWindowStationA("foobar1", 0, WINSTA_ALL_ACCESS, NULL );
187  ok( w2 != 0, "create foobar station failed\n" );
188  w3 = CreateWindowStationA("foobar2", 0, WINSTA_ALL_ACCESS, NULL );
189  ok( w3 != 0, "create foobar station failed\n" );
190  ok( GetHandleInformation( w2, &flags ), "GetHandleInformation failed\n" );
191  ok( GetHandleInformation( w3, &flags ), "GetHandleInformation failed\n" );
192 
194  atom = GlobalAddAtomA("foo");
195  ok( GlobalGetAtomNameA( atom, buffer, sizeof(buffer) ) == 3, "GlobalGetAtomName failed\n" );
196  ok( !lstrcmpiA( buffer, "foo" ), "bad atom value %s\n", buffer );
197 
198  ok( !CloseWindowStation( w2 ), "CloseWindowStation succeeded\n" );
199  ok( GetHandleInformation( w2, &flags ), "GetHandleInformation failed\n" );
200 
202  ok( GetHandleInformation( w2, &flags ), "GetHandleInformation failed\n" );
203  ok( CloseWindowStation( w2 ), "CloseWindowStation failed\n" );
204  ok( GlobalGetAtomNameA( atom, buffer, sizeof(buffer) ) == 3, "GlobalGetAtomName failed\n" );
205  ok( !lstrcmpiA( buffer, "foo" ), "bad atom value %s\n", buffer );
206  }
207  else if (le == ERROR_ACCESS_DENIED)
208  win_skip( "Not enough privileges for CreateWindowStation\n" );
209 
210  SetLastError( 0xdeadbeef );
212  ok( !w2, "open station succeeded\n" );
213  todo_wine
214  ok( GetLastError() == ERROR_FILE_NOT_FOUND, "wrong error %u\n", GetLastError() );
215 
216  SetLastError( 0xdeadbeef );
218  ok( w2 != 0, "create station failed err %u\n", GetLastError() );
219 
220  memset( buffer, 0, sizeof(buffer) );
222  ok( ret, "GetUserObjectInformationA failed with error %u\n", GetLastError() );
223  ok( !memcmp(buffer, "Service-0x0-", 12), "unexpected window station name '%s'\n", buffer );
224  ok( buffer[strlen(buffer) - 1] == '$', "unexpected window station name '%s'\n", buffer );
225 
226  SetLastError( 0xdeadbeef );
228  todo_wine
229  ok( w3 != 0, "open station failed err %u\n", GetLastError() );
230  CloseWindowStation( w3 );
232 
233  SetLastError( 0xdeadbeef );
234  w2 = CreateWindowStationA( "foo\\bar", 0, WINSTA_ALL_ACCESS, NULL );
235  ok( !w2, "create station succeeded\n" );
237  "wrong error %u\n", GetLastError() );
238 
239  SetLastError( 0xdeadbeef );
240  w2 = OpenWindowStationA( "foo\\bar", TRUE, WINSTA_ALL_ACCESS );
241  ok( !w2, "create station succeeded\n" );
242  ok( GetLastError() == ERROR_PATH_NOT_FOUND, "wrong error %u\n", GetLastError() );
243 
244  /* desktops */
246  initial_desktop = d1;
248  "GetThreadDesktop returned different handles\n" );
249 
250  flags = 0;
251  ok( GetHandleInformation( d1, &flags ), "GetHandleInformation failed\n" );
252  ok( !(flags & HANDLE_FLAG_PROTECT_FROM_CLOSE), "handle %p PROTECT_FROM_CLOSE set\n", d1 );
253 
254  SetLastError( 0xdeadbeef );
255  ok( !CloseDesktop(d1), "closing thread desktop succeeded\n" );
256  ok( GetLastError() == ERROR_BUSY || broken(GetLastError() == 0xdeadbeef), /* wow64 */
257  "bad last error %d\n", GetLastError() );
258 
259  SetLastError( 0xdeadbeef );
260  if (CloseHandle( d1 )) /* succeeds on nt4 */
261  {
262  win_skip( "NT4 desktop handle management is completely different\n" );
263  return;
264  }
265  ok( GetLastError() == ERROR_INVALID_HANDLE, "bad last error %d\n", GetLastError() );
266 
268  TRUE, DUPLICATE_SAME_ACCESS ), "DuplicateHandle failed\n" );
269  ok( CloseDesktop(d2), "closing dup desktop failed\n" );
270 
272  TRUE, DUPLICATE_SAME_ACCESS ), "DuplicateHandle failed\n" );
273  ok( CloseHandle(d2), "closing dup desktop handle failed\n" );
274 
275  d2 = OpenDesktopA( "dummy name", 0, TRUE, DESKTOP_ALL_ACCESS );
276  ok( !d2, "open dummy desktop succeeded\n" );
277 
278  SetLastError( 0xdeadbeef );
279  d2 = CreateDesktopA( "", NULL, NULL, 0, DESKTOP_ALL_ACCESS, NULL );
280  todo_wine
281  ok( !d2, "create empty desktop succeeded\n" );
282  todo_wine
283  ok( GetLastError() == ERROR_INVALID_HANDLE, "wrong error %u\n", GetLastError() );
284 
285  SetLastError( 0xdeadbeef );
286  d2 = OpenDesktopA( "", 0, TRUE, DESKTOP_ALL_ACCESS );
287  ok( !d2, "open empty desktop succeeded\n" );
288  ok( GetLastError() == ERROR_INVALID_HANDLE, "wrong error %u\n", GetLastError() );
289 
290  SetLastError( 0xdeadbeef );
291  d2 = CreateDesktopA( "foo\\bar", NULL, NULL, 0, DESKTOP_ALL_ACCESS, NULL );
292  ok( !d2, "create desktop succeeded\n" );
293  ok( GetLastError() == ERROR_BAD_PATHNAME, "wrong error %u\n", GetLastError() );
294 
295  SetLastError( 0xdeadbeef );
296  d2 = OpenDesktopA( "foo\\bar", 0, TRUE, DESKTOP_ALL_ACCESS );
297  ok( !d2, "open desktop succeeded\n" );
298  ok( GetLastError() == ERROR_BAD_PATHNAME, "wrong error %u\n", GetLastError() );
299 
300  d2 = CreateDesktopA( "foobar", NULL, NULL, 0, DESKTOP_ALL_ACCESS, NULL );
301  ok( d2 != 0, "create foobar desktop failed\n" );
302  SetLastError( 0xdeadbeef );
303  ok( !CloseWindowStation( (HWINSTA)d2 ), "CloseWindowStation succeeded on desktop\n" );
304  ok( GetLastError() == ERROR_INVALID_HANDLE || broken(GetLastError() == 0xdeadbeef), /* wow64 */
305  "bad last error %d\n", GetLastError() );
306 
307  SetLastError( 0xdeadbeef );
308  d3 = CreateDesktopA( "foobar", NULL, NULL, 0, DESKTOP_ALL_ACCESS, NULL );
309  ok( d3 != 0, "create foobar desktop again failed\n" );
310  ok( GetLastError() == 0xdeadbeef, "bad last error %d\n", GetLastError() );
311  ok( CloseDesktop( d3 ), "CloseDesktop failed\n" );
312 
313  d3 = OpenDesktopA( "foobar", 0, TRUE, DESKTOP_ALL_ACCESS );
314  ok( d3 != 0, "open foobar desktop failed\n" );
315  ok( d3 != d2, "open foobar desktop returned same handle\n" );
316  ok( CloseDesktop( d2 ), "CloseDesktop failed\n" );
317  ok( CloseDesktop( d3 ), "CloseDesktop failed\n" );
318 
319  d3 = OpenDesktopA( "foobar", 0, TRUE, DESKTOP_ALL_ACCESS );
320  ok( !d3, "open foobar desktop succeeded\n" );
321 
322  ok( !CloseHandle(d1), "closing thread desktop handle succeeded\n" );
324  ok( d1 == d2, "got different handles after close\n" );
325 
326  register_class();
327  trace( "thread 1 desktop: %p\n", d1 );
328  print_object( d1 );
329  hthread = CreateThread( NULL, 0, thread, (LPVOID)2, 0, &id );
330  Sleep(1000);
331  trace( "get other thread desktop: %p\n", GetThreadDesktop(id) );
332  WaitForSingleObject( hthread, INFINITE );
333  CloseHandle( hthread );
334 
335  /* clean side effect */
337 }
338 
339 /* Enumeration tests */
340 
342 {
343  trace("window_station_callbackA called with argument %s\n", winsta);
344  return lp;
345 }
346 
348 {
349  HWINSTA hwinsta;
350 
351  trace("open_window_station_callbackA called with argument %s\n", winsta);
352  hwinsta = OpenWindowStationA(winsta, FALSE, WINSTA_ENUMERATE);
353  ok(hwinsta != NULL, "Could not open desktop %s!\n", winsta);
354  if (hwinsta)
355  CloseWindowStation(hwinsta);
356  return lp;
357 }
358 
359 static void test_enumstations(void)
360 {
361  DWORD ret;
362  HWINSTA hwinsta;
363 
364  if (0) /* Crashes instead */
365  {
366  SetLastError(0xbabefeed);
368  ok(!ret, "EnumWindowStationsA returned successfully!\n");
369  ok(GetLastError() == ERROR_INVALID_PARAMETER, "LastError is set to %08x\n", GetLastError());
370  }
371 
372  hwinsta = CreateWindowStationA("winsta_test", 0, WINSTA_ALL_ACCESS, NULL);
373  ret = GetLastError();
374  ok(hwinsta != NULL || ret == ERROR_ACCESS_DENIED, "CreateWindowStation failed (%u)\n", ret);
375  if (!hwinsta)
376  {
377  win_skip("Not enough privileges for CreateWindowStation\n");
378  return;
379  }
380 
381  SetLastError(0xdeadbeef);
383  ok(ret == 0x12345, "EnumWindowStationsA returned %x\n", ret);
384  ok(GetLastError() == 0xdeadbeef, "LastError is set to %08x\n", GetLastError());
385 
386  SetLastError(0xdeadbeef);
388  ok(!ret, "EnumWindowStationsA returned %x\n", ret);
389  ok(GetLastError() == 0xdeadbeef, "LastError is set to %08x\n", GetLastError());
390 }
391 
393 {
394  trace("desktop_callbackA called with argument %s\n", desktop);
395  return lp;
396 }
397 
399 {
400  HDESK hdesk;
401  static int once;
402 
403  trace("open_desktop_callbackA called with argument %s\n", desktop);
404  /* Only try to open one desktop */
405  if (once++)
406  return lp;
407 
408  hdesk = OpenDesktopA(desktop, 0, FALSE, DESKTOP_ENUMERATE);
409  ok(hdesk != NULL, "Could not open desktop %s!\n", desktop);
410  if (hdesk)
411  CloseDesktop(hdesk);
412  return lp;
413 }
414 
415 static void test_enumdesktops(void)
416 {
417  BOOL ret;
418 
419  if (0) /* Crashes instead */
420  {
421  SetLastError(0xbabefeed);
423  ok(!ret, "EnumDesktopsA returned successfully!\n");
424  ok(GetLastError() == ERROR_INVALID_PARAMETER, "LastError is set to %08x\n", GetLastError());
425  }
426 
427  SetLastError(0xdeadbeef);
429  ok(ret == 0x12345, "EnumDesktopsA returned %x\n", ret);
430  ok(GetLastError() == 0xdeadbeef, "LastError is set to %08x\n", GetLastError());
431 
432  SetLastError(0xdeadbeef);
434  ok(ret == 0x12345, "EnumDesktopsA returned %x\n", ret);
435  ok(GetLastError() == 0xdeadbeef, "LastError is set to %08x\n", GetLastError());
436 
437  SetLastError(0xdeadbeef);
439  ok(!ret, "EnumDesktopsA returned %x\n", ret);
440  ok(GetLastError() == ERROR_INVALID_HANDLE, "LastError is set to %08x\n", GetLastError());
441 
442  SetLastError(0xdeadbeef);
444  ok(!ret, "EnumDesktopsA returned %x\n", ret);
445  ok(GetLastError() == 0xdeadbeef, "LastError is set to %08x\n", GetLastError());
446 }
447 
448 /* Miscellaneous tests */
449 
451 {
452  WCHAR foobarTestW[] = {'\\','f','o','o','b','a','r','T','e','s','t',0};
453  WCHAR DesktopW[] = {'D','e','s','k','t','o','p',0};
454  OBJECT_NAME_INFORMATION *name_info;
455  WCHAR bufferW[20];
456  char buffer[64];
458  DWORD size;
459  HDESK desk;
460  BOOL ret;
461 
462  desk = CreateDesktopA("foobarTest", NULL, NULL, 0, DESKTOP_ALL_ACCESS, NULL);
463  ok(desk != 0, "open foobarTest desktop failed\n");
464 
465  strcpy(buffer, "blahblah");
466 
469  /* Get size, test size and return value/error code */
470  SetLastError(0xdeadbeef);
471  size = 0xdeadbeef;
473 
474  ok(!ret, "GetUserObjectInformationA returned %x\n", ret);
475  ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "LastError is set to %08x\n", GetLastError());
476  ok(size == 22, "size is set to %d\n", size); /* Windows returns Unicode length (11*2) */
477 
478  /* Get string */
479  SetLastError(0xdeadbeef);
480  size = 0xdeadbeef;
482 
483  ok(ret, "GetUserObjectInformationA returned %x\n", ret);
484  ok(GetLastError() == 0xdeadbeef, "LastError is set to %08x\n", GetLastError());
485 
486  ok(strcmp(buffer, "foobarTest") == 0, "Buffer is set to '%s'\n", buffer);
487  ok(size == 11, "size is set to %d\n", size); /* 11 bytes in 'foobarTest\0' */
488 
489  /* Get size, test size and return value/error code (Unicode) */
490  SetLastError(0xdeadbeef);
491  size = 0xdeadbeef;
493 
494  ok(!ret, "GetUserObjectInformationW returned %x\n", ret);
495  ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "LastError is set to %08x\n", GetLastError());
496  ok(size == 22, "size is set to %d\n", size); /* 22 bytes in 'foobarTest\0' in Unicode */
497 
498  /* Get string (Unicode) */
499  SetLastError(0xdeadbeef);
500  size = 0xdeadbeef;
501  ret = GetUserObjectInformationW(desk, UOI_NAME, bufferW, sizeof(bufferW), &size);
502 
503  ok(ret, "GetUserObjectInformationW returned %x\n", ret);
504  ok(GetLastError() == 0xdeadbeef, "LastError is set to %08x\n", GetLastError());
505 
506  ok(lstrcmpW(bufferW, foobarTestW + 1) == 0, "Buffer is not set to 'foobarTest'\n");
507  ok(size == 22, "size is set to %d\n", size); /* 22 bytes in 'foobarTest\0' in Unicode */
508 
509  /* ObjectNameInformation does not return the full desktop name */
510  name_info = (OBJECT_NAME_INFORMATION *)buffer;
511  status = pNtQueryObject(desk, ObjectNameInformation, name_info, sizeof(buffer), NULL);
512  ok(!status, "expected STATUS_SUCCESS, got %08x\n", status);
513  ok(lstrcmpW(name_info->Name.Buffer, foobarTestW) == 0,
514  "expected '\\foobarTest', got %s\n", wine_dbgstr_w(name_info->Name.Buffer));
515 
518  /* Get size, test size and return value/error code */
519  SetLastError(0xdeadbeef);
520  size = 0xdeadbeef;
522 
523  ok(!ret, "GetUserObjectInformationA returned %x\n", ret);
524  ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "LastError is set to %08x\n", GetLastError());
525  ok(size == 16, "size is set to %d\n", size); /* Windows returns Unicode length (8*2) */
526 
527  /* Get string */
528  SetLastError(0xdeadbeef);
529  size = 0xdeadbeef;
531 
532  ok(ret, "GetUserObjectInformationA returned %x\n", ret);
533  ok(GetLastError() == 0xdeadbeef, "LastError is set to %08x\n", GetLastError());
534 
535  ok(strcmp(buffer, "Desktop") == 0, "Buffer is set to '%s'\n", buffer);
536  ok(size == 8, "size is set to %d\n", size); /* 8 bytes in 'Desktop\0' */
537 
538  /* Get size, test size and return value/error code (Unicode) */
539  size = 0xdeadbeef;
540  SetLastError(0xdeadbeef);
542 
543  ok(!ret, "GetUserObjectInformationW returned %x\n", ret);
544  ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "LastError is set to %08x\n", GetLastError());
545  ok(size == 16, "size is set to %d\n", size); /* 16 bytes in 'Desktop\0' in Unicode */
546 
547  /* Get string (Unicode) */
548  SetLastError(0xdeadbeef);
549  size = 0xdeadbeef;
550  ret = GetUserObjectInformationW(desk, UOI_TYPE, bufferW, sizeof(bufferW), &size);
551 
552  ok(ret, "GetUserObjectInformationW returned %x\n", ret);
553  ok(GetLastError() == 0xdeadbeef, "LastError is set to %08x\n", GetLastError());
554 
555  ok(lstrcmpW(bufferW, DesktopW) == 0, "Buffer is not set to 'Desktop'\n");
556  ok(size == 16, "size is set to %d\n", size); /* 16 bytes in 'Desktop\0' in Unicode */
557 
558  ok(CloseDesktop(desk), "CloseDesktop failed\n");
559 }
560 
561 static void test_inputdesktop(void)
562 {
563  HDESK input_desk, old_input_desk, thread_desk, old_thread_desk, new_desk;
564  DWORD ret;
565  CHAR name[1024];
566  INPUT inputs[1];
567 
568  inputs[0].type = INPUT_KEYBOARD;
569  U(inputs[0]).ki.wVk = 0;
570  U(inputs[0]).ki.wScan = 0x3c0;
571  U(inputs[0]).ki.dwFlags = KEYEVENTF_UNICODE;
572 
573  /* OpenInputDesktop creates new handles for each calls */
574  old_input_desk = OpenInputDesktop(0, FALSE, DESKTOP_ALL_ACCESS);
575  ok(old_input_desk != NULL, "OpenInputDesktop failed!\n");
576  memset(name, 0, sizeof(name));
577  ret = GetUserObjectInformationA(old_input_desk, UOI_NAME, name, 1024, NULL);
578  ok(ret, "GetUserObjectInformation failed!\n");
579  ok(!strcmp(name, "Default"), "unexpected desktop %s\n", name);
580 
581  input_desk = OpenInputDesktop(0, FALSE, DESKTOP_ALL_ACCESS);
582  ok(input_desk != NULL, "OpenInputDesktop failed!\n");
583  memset(name, 0, sizeof(name));
584  ret = GetUserObjectInformationA(input_desk, UOI_NAME, name, 1024, NULL);
585  ok(ret, "GetUserObjectInformation failed!\n");
586  ok(!strcmp(name, "Default"), "unexpected desktop %s\n", name);
587 
588  ok(old_input_desk != input_desk, "returned the same handle!\n");
589  ret = CloseDesktop(input_desk);
590  ok(ret, "CloseDesktop failed!\n");
591 
592  /* by default, GetThreadDesktop is the input desktop, SendInput should succeed. */
593  old_thread_desk = GetThreadDesktop(GetCurrentThreadId());
594  ok(old_thread_desk != NULL, "GetThreadDesktop faile!\n");
595  memset(name, 0, sizeof(name));
596  ret = GetUserObjectInformationA(old_thread_desk, UOI_NAME, name, 1024, NULL);
597  ok(!strcmp(name, "Default"), "unexpected desktop %s\n", name);
598 
599  SetLastError(0xdeadbeef);
600  ret = SendInput(1, inputs, sizeof(INPUT));
601  ok(GetLastError() == 0xdeadbeef, "unexpected last error %08x\n", GetLastError());
602  ok(ret == 1, "unexpected return count %d\n", ret);
603 
604  /* Set thread desktop to the new desktop, SendInput should fail. */
605  new_desk = CreateDesktopA("new_desk", NULL, NULL, 0, DESKTOP_ALL_ACCESS, NULL);
606  ok(new_desk != NULL, "CreateDesktop failed!\n");
607  ret = SetThreadDesktop(new_desk);
608  ok(ret, "SetThreadDesktop failed!\n");
609  thread_desk = GetThreadDesktop(GetCurrentThreadId());
610  ok(thread_desk == new_desk, "thread desktop doesn't match!\n");
611  memset(name, 0, sizeof(name));
612  ret = GetUserObjectInformationA(thread_desk, UOI_NAME, name, 1024, NULL);
613  ok(!strcmp(name, "new_desk"), "unexpected desktop %s\n", name);
614 
615  SetLastError(0xdeadbeef);
616  ret = SendInput(1, inputs, sizeof(INPUT));
617  if(broken(GetLastError() == 0xdeadbeef))
618  {
619  SetThreadDesktop(old_thread_desk);
620  CloseDesktop(old_input_desk);
621  CloseDesktop(input_desk);
622  CloseDesktop(new_desk);
623  win_skip("Skip tests on NT4\n");
624  return;
625  }
626 todo_wine
627  ok(GetLastError() == ERROR_ACCESS_DENIED, "unexpected last error %08x\n", GetLastError());
628  ok(ret == 1 || broken(ret == 0) /* Win64 */, "unexpected return count %d\n", ret);
629 
630  /* Set thread desktop back to the old thread desktop, SendInput should success. */
631  ret = SetThreadDesktop(old_thread_desk);
632  ok(ret, "SetThreadDesktop failed!\n");
633  thread_desk = GetThreadDesktop(GetCurrentThreadId());
634  ok(thread_desk == old_thread_desk, "thread desktop doesn't match!\n");
635  memset(name, 0, sizeof(name));
636  ret = GetUserObjectInformationA(thread_desk, UOI_NAME, name, 1024, NULL);
637  ok(!strcmp(name, "Default"), "unexpected desktop %s\n", name);
638 
639  SetLastError(0xdeadbeef);
640  ret = SendInput(1, inputs, sizeof(INPUT));
641  ok(GetLastError() == 0xdeadbeef, "unexpected last error %08x\n", GetLastError());
642  ok(ret == 1, "unexpected return count %d\n", ret);
643 
644  /* Set thread desktop to the input desktop, SendInput should success. */
645  ret = SetThreadDesktop(old_input_desk);
646  ok(ret, "SetThreadDesktop failed!\n");
647  thread_desk = GetThreadDesktop(GetCurrentThreadId());
648  ok(thread_desk == old_input_desk, "thread desktop doesn't match!\n");
649  memset(name, 0, sizeof(name));
650  ret = GetUserObjectInformationA(thread_desk, UOI_NAME, name, 1024, NULL);
651  ok(!strcmp(name, "Default"), "unexpected desktop %s\n", name);
652 
653  SetLastError(0xdeadbeef);
654  ret = SendInput(1, inputs, sizeof(INPUT));
655  ok(GetLastError() == 0xdeadbeef, "unexpected last error %08x\n", GetLastError());
656  ok(ret == 1, "unexpected return count %d\n", ret);
657 
658  /* Switch input desktop to the new desktop, SendInput should fail. */
659  ret = SwitchDesktop(new_desk);
660  ok(ret, "SwitchDesktop failed!\n");
661  input_desk = OpenInputDesktop(0, FALSE, DESKTOP_ALL_ACCESS);
662  ok(input_desk != NULL, "OpenInputDesktop failed!\n");
663  ok(input_desk != new_desk, "returned the same handle!\n");
664  memset(name, 0, sizeof(name));
665  ret = GetUserObjectInformationA(input_desk, UOI_NAME, name, 1024, NULL);
666  ok(ret, "GetUserObjectInformation failed!\n");
667 todo_wine
668  ok(!strcmp(name, "new_desk"), "unexpected desktop %s\n", name);
669  ret = CloseDesktop(input_desk);
670  ok(ret, "CloseDesktop failed!\n");
671 
672  SetLastError(0xdeadbeef);
673  ret = SendInput(1, inputs, sizeof(INPUT));
674 todo_wine
675  ok(GetLastError() == ERROR_ACCESS_DENIED, "unexpected last error %08x\n", GetLastError());
676  ok(ret == 1 || broken(ret == 0) /* Win64 */, "unexpected return count %d\n", ret);
677 
678  /* Set thread desktop to the new desktop, SendInput should success. */
679  ret = SetThreadDesktop(new_desk);
680  ok(ret, "SetThreadDesktop failed!\n");
681  thread_desk = GetThreadDesktop(GetCurrentThreadId());
682  ok(thread_desk == new_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, "new_desk"), "unexpected desktop %s\n", name);
686 
687  SetLastError(0xdeadbeef);
688  ret = SendInput(1, inputs, sizeof(INPUT));
689  ok(GetLastError() == 0xdeadbeef, "unexpected last error %08x\n", GetLastError());
690  ok(ret == 1, "unexpected return count %d\n", ret);
691 
692  /* Switch input desktop to the old input desktop, set thread desktop to the old
693  * thread desktop, clean side effects. SendInput should success. */
694  ret = SwitchDesktop(old_input_desk);
695  input_desk = OpenInputDesktop(0, FALSE, DESKTOP_ALL_ACCESS);
696  ok(input_desk != NULL, "OpenInputDesktop failed!\n");
697  ok(input_desk != old_input_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, "Default"), "unexpected desktop %s\n", name);
702 
703  ret = SetThreadDesktop(old_thread_desk);
704  ok(ret, "SetThreadDesktop failed!\n");
705  thread_desk = GetThreadDesktop(GetCurrentThreadId());
706  ok(thread_desk == old_thread_desk, "thread desktop doesn't match!\n");
707  memset(name, 0, sizeof(name));
708  ret = GetUserObjectInformationA(thread_desk, UOI_NAME, name, 1024, NULL);
709  ok(!strcmp(name, "Default"), "unexpected desktop %s\n", name);
710 
711  SetLastError(0xdeadbeef);
712  ret = SendInput(1, inputs, sizeof(INPUT));
713  ok(GetLastError() == 0xdeadbeef, "unexpected last error %08x\n", GetLastError());
714  ok(ret == 1, "unexpected return count %d\n", ret);
715 
716  /* free resources */
717  ret = CloseDesktop(input_desk);
718  ok(ret, "CloseDesktop failed!\n");
719  ret = CloseDesktop(old_input_desk);
720  ok(ret, "CloseDesktop failed!\n");
721  ret = CloseDesktop(new_desk);
722  ok(ret, "CloseDesktop failed!\n");
723 }
724 
725 static void test_inputdesktop2(void)
726 {
727  HWINSTA w1, w2;
728  HDESK thread_desk, new_desk, input_desk, hdesk;
729  DWORD ret;
730 
731  thread_desk = GetThreadDesktop(GetCurrentThreadId());
732  ok(thread_desk != NULL, "GetThreadDesktop failed!\n");
734  ok(w1 != NULL, "GetProcessWindowStation failed!\n");
735  SetLastError(0xdeadbeef);
736  w2 = CreateWindowStationA("winsta_test", 0, WINSTA_ALL_ACCESS, NULL);
737  ret = GetLastError();
738  ok(w2 != NULL || ret == ERROR_ACCESS_DENIED, "CreateWindowStation failed (%u)\n", ret);
739  if (!w2)
740  {
741  win_skip("Not enough privileges for CreateWindowStation\n");
742  return;
743  }
744 
746  ok(!ret, "EnumDesktopsA failed!\n");
747  input_desk = OpenInputDesktop(0, FALSE, DESKTOP_ALL_ACCESS);
748  ok(input_desk != NULL, "OpenInputDesktop failed!\n");
749  ret = CloseDesktop(input_desk);
750  ok(ret, "CloseDesktop failed!\n");
751 
753  ok(ret, "SetProcessWindowStation failed!\n");
755  ok(hdesk != NULL, "GetThreadDesktop failed!\n");
756  ok(hdesk == thread_desk, "thread desktop should not change after winstation changed!\n");
758 
759  new_desk = CreateDesktopA("desk_test", NULL, NULL, 0, DESKTOP_ALL_ACCESS, NULL);
760  ok(new_desk != NULL, "CreateDesktop failed!\n");
762  ok(!ret, "EnumDesktopsA failed!\n");
763  SetLastError(0xdeadbeef);
764  input_desk = OpenInputDesktop(0, FALSE, DESKTOP_ALL_ACCESS);
765  ok(input_desk == NULL, "OpenInputDesktop should fail on non default winstation!\n");
766  ok(GetLastError() == ERROR_INVALID_FUNCTION || broken(GetLastError() == 0xdeadbeef), "last error %08x\n", GetLastError());
767 
768  hdesk = OpenDesktopA("desk_test", 0, TRUE, DESKTOP_ALL_ACCESS);
769  ok(hdesk != NULL, "OpenDesktop failed!\n");
770  SetLastError(0xdeadbeef);
771  ret = SwitchDesktop(hdesk);
772 todo_wine
773  ok(!ret, "Switch to desktop belong to non default winstation should fail!\n");
774 todo_wine
775  ok(GetLastError() == ERROR_ACCESS_DENIED || broken(GetLastError() == 0xdeadbeef), "last error %08x\n", GetLastError());
776  ret = SetThreadDesktop(hdesk);
777  ok(ret, "SetThreadDesktop failed!\n");
778 
779  /* clean side effect */
780  ret = SetThreadDesktop(thread_desk);
781 todo_wine
782  ok(ret, "SetThreadDesktop should success even desktop is not belong to process winstation!\n");
784  ok(ret, "SetProcessWindowStation failed!\n");
785  ret = SetThreadDesktop(thread_desk);
786  ok(ret, "SetThreadDesktop failed!\n");
788  ok(ret, "CloseWindowStation failed!\n");
789  ret = CloseDesktop(new_desk);
790  ok(ret, "CloseDesktop failed!\n");
791  ret = CloseDesktop(hdesk);
792  ok(ret, "CloseDesktop failed!\n");
793 }
794 
796 {
797  if (msg == WM_DESTROY)
798  {
799  trace("destroying hwnd %p\n", hWnd);
800  PostQuitMessage(0);
801  return 0;
802  }
803  return DefWindowProcA( hWnd, msg, wParam, lParam );
804 }
805 
806 typedef struct tag_wnd_param
807 {
808  const char *wnd_name;
810  HDESK hdesk;
812 } wnd_param;
813 
815 {
816  wnd_param *param1 = param;
817  DWORD ret;
818  MSG msg;
819 
820  ret = SetThreadDesktop(param1->hdesk);
821  ok(ret, "SetThreadDesktop failed!\n");
822  param1->hwnd = CreateWindowA("test_class", param1->wnd_name, WS_POPUP, 0, 0, 100, 100, NULL, NULL, NULL, NULL);
823  ok(param1->hwnd != 0, "CreateWindowA failed!\n");
824  ret = SetEvent(param1->hevent);
825  ok(ret, "SetEvent failed!\n");
826 
827  while (GetMessageA(&msg, 0, 0, 0))
828  {
831  }
832 
833  return 0;
834 }
835 
837 {
838  HWND hwnd_fore;
839  DWORD set_id, fore_id, ret;
840  char win_text[1024];
841 
842  hwnd_fore = GetForegroundWindow();
843  GetWindowTextA(hwnd_fore, win_text, 1024);
845  fore_id = GetWindowThreadProcessId(hwnd_fore, NULL);
846  trace("\"%s\" %p %08x hwnd %p %08x\n", win_text, hwnd_fore, fore_id, hwnd, set_id);
847  ret = AttachThreadInput(set_id, fore_id, TRUE);
848  trace("AttachThreadInput returned %08x\n", ret);
850  trace("ShowWindow returned %08x\n", ret);
852  trace("set topmost returned %08x\n", ret);
854  trace("set notopmost returned %08x\n", ret);
856  trace("SetForegroundWindow returned %08x\n", ret);
857  Sleep(250);
858  AttachThreadInput(set_id, fore_id, FALSE);
859  return ret;
860 }
861 
862 static void test_foregroundwindow(void)
863 {
864  HWND hwnd, hwnd_test, partners[2], hwnds[2];
865  HDESK hdesks[2];
866  int thread_desk_id, input_desk_id, hwnd_id;
867  WNDCLASSA wclass;
869  DWORD ret, timeout, timeout_old;
870  char win_text[1024];
871 
872 #define DESKTOPS 2
873 
874  memset( &wclass, 0, sizeof(wclass) );
875  wclass.lpszClassName = "test_class";
876  wclass.lpfnWndProc = WndProc;
877  RegisterClassA(&wclass);
878  param.wnd_name = "win_name";
879 
880  hdesks[0] = GetThreadDesktop(GetCurrentThreadId());
881  ok(hdesks[0] != NULL, "OpenDesktop failed!\n");
882  SetLastError(0xdeadbeef);
883  hdesks[1] = CreateDesktopA("desk2", NULL, NULL, 0, DESKTOP_ALL_ACCESS, NULL);
884  ret = GetLastError();
885  ok(hdesks[1] != NULL || ret == ERROR_ACCESS_DENIED, "CreateDesktop failed (%u)\n", ret);
886  if(!hdesks[1])
887  {
888  win_skip("Not enough privileges for CreateDesktop\n");
889  return;
890  }
891 
892  ret = SystemParametersInfoA(SPI_GETFOREGROUNDLOCKTIMEOUT, 0, &timeout_old, 0);
893  if(!ret)
894  {
895  win_skip("Skip tests on NT4\n");
896  CloseDesktop(hdesks[1]);
897  return;
898  }
899  trace("old timeout %d\n", timeout_old);
900  timeout = 0;
901  ret = SystemParametersInfoA(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, 0, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
902  ok(ret, "set foreground lock timeout failed!\n");
903  ret = SystemParametersInfoA(SPI_GETFOREGROUNDLOCKTIMEOUT, 0, &timeout, 0);
904  ok(ret, "get foreground lock timeout failed!\n");
905  ok(timeout == 0, "unexpected timeout %d\n", timeout);
906 
907  for (thread_desk_id = 0; thread_desk_id < DESKTOPS; thread_desk_id++)
908  {
909  param.hdesk = hdesks[thread_desk_id];
910  param.hevent = CreateEventA(NULL, TRUE, FALSE, NULL);
913  ok(ret == WAIT_OBJECT_0, "wait failed!\n");
914  hwnds[thread_desk_id] = param.hwnd;
915  }
916 
917  for (thread_desk_id = 0; thread_desk_id < DESKTOPS; thread_desk_id++)
918  {
919  param.hdesk = hdesks[thread_desk_id];
920  param.hevent = CreateEventA(NULL, TRUE, FALSE, NULL);
923  ok(ret == WAIT_OBJECT_0, "wait failed!\n");
924  partners[thread_desk_id] = param.hwnd;
925  }
926 
927  trace("hwnd0 %p hwnd1 %p partner0 %p partner1 %p\n", hwnds[0], hwnds[1], partners[0], partners[1]);
928 
929  for (hwnd_id = 0; hwnd_id < DESKTOPS; hwnd_id++)
930  for (thread_desk_id = 0; thread_desk_id < DESKTOPS; thread_desk_id++)
931  for (input_desk_id = 0; input_desk_id < DESKTOPS; input_desk_id++)
932  {
933  trace("testing thread_desk %d input_desk %d hwnd %d\n",
934  thread_desk_id, input_desk_id, hwnd_id);
935  hwnd_test = hwnds[hwnd_id];
936  ret = SetThreadDesktop(hdesks[thread_desk_id]);
937  ok(ret, "set thread desktop failed!\n");
938  ret = SwitchDesktop(hdesks[input_desk_id]);
939  ok(ret, "switch desktop failed!\n");
940  set_foreground(partners[0]);
941  set_foreground(partners[1]);
943  ok(hwnd != hwnd_test, "unexpected foreground window %p\n", hwnd);
944  ret = set_foreground(hwnd_test);
946  GetWindowTextA(hwnd, win_text, 1024);
947  trace("hwnd %p name %s\n", hwnd, win_text);
948  if (input_desk_id == hwnd_id)
949  {
950  if (input_desk_id == thread_desk_id)
951  {
952  ok(ret, "SetForegroundWindow failed!\n");
953  todo_wine_if (!hwnd)
954  ok(hwnd == hwnd_test , "unexpected foreground window %p\n", hwnd);
955  }
956  else
957  {
958  todo_wine ok(ret, "SetForegroundWindow failed!\n");
959  todo_wine ok(hwnd == 0, "unexpected foreground window %p\n", hwnd);
960  }
961  }
962  else
963  {
964  if (input_desk_id == thread_desk_id)
965  {
966  ok(!ret, "SetForegroundWindow should fail!\n");
967  todo_wine_if (!hwnd)
968  ok(hwnd == partners[input_desk_id] , "unexpected foreground window %p\n", hwnd);
969  }
970  else
971  {
972  todo_wine ok(!ret, "SetForegroundWindow should fail!\n");
974  ok(hwnd == 0, "unexpected foreground window %p\n", hwnd);
975  }
976  }
977  }
978 
979  /* Clean up */
980 
981  for (thread_desk_id = DESKTOPS - 1; thread_desk_id >= 0; thread_desk_id--)
982  {
983  ret = SetThreadDesktop(hdesks[thread_desk_id]);
984  ok(ret, "set thread desktop failed!\n");
985  SendMessageA(hwnds[thread_desk_id], WM_DESTROY, 0, 0);
986  SendMessageA(partners[thread_desk_id], WM_DESTROY, 0, 0);
987  }
988 
989  ret = SwitchDesktop(hdesks[0]);
990  ok(ret, "switch desktop failed!\n");
991  CloseDesktop(hdesks[1]);
992 
993  ret = SystemParametersInfoA(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, UlongToPtr(timeout_old), SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
994  ok(ret, "set foreground lock timeout failed!\n");
995  ret = SystemParametersInfoA(SPI_GETFOREGROUNDLOCKTIMEOUT, 0, &timeout, 0);
996  ok(ret, "get foreground lock timeout failed!\n");
997  ok(timeout == timeout_old, "unexpected timeout %d\n", timeout);
998 }
999 
1000 START_TEST(winstation)
1001 {
1002  HMODULE hntdll = GetModuleHandleA("ntdll.dll");
1003  pNtQueryObject = (void *)GetProcAddress(hntdll, "NtQueryObject");
1004 
1005  /* Check whether this platform supports WindowStation calls */
1006 
1007  SetLastError( 0xdeadbeef );
1010  {
1011  win_skip("WindowStation calls not supported on this platform\n");
1012  return;
1013  }
1014 
1019  test_handles();
1022 }
HGDIOBJ WINAPI GetStockObject(_In_ int)
#define ERROR_INVALID_PARAMETER
Definition: compat.h:91
const DOCKBAR PVOID HWND HWND * hwnd
Definition: tooldock.h:22
#define trace(...)
Definition: kmt_test.h:217
BOOL WINAPI TranslateMessage(_In_ const MSG *)
LRESULT WINAPI DispatchMessageA(_In_ const MSG *)
#define TRUE
Definition: types.h:120
#define CloseHandle
Definition: compat.h:398
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
Definition: synch.c:736
BOOL WINAPI GetUserObjectInformationW(_In_ HANDLE hObj, _In_ int nIndex, _Out_writes_bytes_opt_(nLength) PVOID pvInfo, _In_ DWORD nLength, _Out_opt_ LPDWORD lpnLengthNeeded)
int WINAPI GetWindowTextA(HWND hWnd, LPSTR lpString, int nMaxCount)
Definition: window.c:1296
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
int WINAPI lstrcmpiA(LPCSTR lpString1, LPCSTR lpString2)
Definition: lstring.c:42
static void register_class(void)
Definition: winstation.c:49
BOOL WINAPI AttachThreadInput(_In_ DWORD, _In_ DWORD, _In_ BOOL)
const char * wnd_name
Definition: winstation.c:808
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define ERROR_INVALID_FUNCTION
Definition: dderror.h:6
WORD ATOM
Definition: dimm.idl:113
static BOOL CALLBACK open_desktop_callbackA(LPSTR desktop, LPARAM lp)
Definition: winstation.c:398
LRESULT WINAPI SendMessageA(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
int WINAPI lstrcmpW(LPCWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:170
HWINSTA WINAPI OpenWindowStationA(_In_ LPCSTR, _In_ BOOL, _In_ DWORD)
char CHAR
Definition: xmlstorage.h:175
TW_UINT32 TW_UINT16 TW_UINT16 MSG
Definition: twain.h:1827
#define U(x)
Definition: wordpad.c:44
#define ERROR_INVALID_HANDLE
Definition: compat.h:88
LONG NTSTATUS
Definition: precomp.h:26
static OBJECT_INFORMATION_CLASS
Definition: winstation.c:28
#define CALLBACK
Definition: compat.h:27
HWND hWnd
Definition: settings.c:17
HDESK WINAPI GetThreadDesktop(_In_ DWORD)
#define DESKTOP_ENUMERATE
Definition: winuser.h:218
#define wine_dbgstr_w
Definition: kernel32.h:34
BOOL WINAPI GetMessageA(_Out_ LPMSG, _In_opt_ HWND, _In_ UINT, _In_ UINT)
ATOM WINAPI GlobalAddAtomA(LPCSTR lpString)
Definition: atom.c:434
int cbClsExtra
Definition: winuser.h:3118
#define INVALID_HANDLE_VALUE
Definition: compat.h:391
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:679
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
LPCSTR lpszMenuName
Definition: winuser.h:3124
#define HWND_TOPMOST
Definition: winuser.h:1194
GLuint buffer
Definition: glext.h:5915
static void test_inputdesktop(void)
Definition: winstation.c:561
#define WHITE_BRUSH
Definition: wingdi.h:901
static PVOID
Definition: winstation.c:28
Definition: dhcpd.h:245
BOOL WINAPI SetProcessWindowStation(_In_ HWINSTA)
UINT_PTR WPARAM
Definition: windef.h:207
HBRUSH hbrBackground
Definition: winuser.h:3123
#define WINSTA_ENUMERATE
Definition: winuser.h:412
BOOL WINAPI ShowWindow(_In_ HWND, _In_ int)
UNICODE_STRING Name
Definition: nt_native.h:1270
char * LPSTR
Definition: xmlstorage.h:182
BOOL WINAPI DestroyWindow(_In_ HWND)
#define ERROR_BUSY
Definition: dderror.h:12
GLbitfield GLuint64 timeout
Definition: glext.h:7164
WPARAM wParam
Definition: combotst.c:138
BOOL WINAPI SetThreadDesktop(_In_ HDESK)
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
int cbWndExtra
Definition: winuser.h:3119
#define INPUT_KEYBOARD
Definition: winable.h:10
#define DUPLICATE_SAME_ACCESS
HDESK WINAPI OpenInputDesktop(_In_ DWORD, _In_ BOOL, _In_ DWORD)
#define ERROR_ACCESS_DENIED
Definition: compat.h:87
unsigned int BOOL
Definition: ntddk_ex.h:94
static void test_foregroundwindow(void)
Definition: winstation.c:862
#define ok(value,...)
#define CreateWindowA(a, b, c, d, e, f, g, h, i, j, k)
Definition: winuser.h:4184
HCURSOR hCursor
Definition: winuser.h:3122
DWORD WINAPI GetWindowThreadProcessId(HWND, PDWORD)
BOOL WINAPI SystemParametersInfoA(_In_ UINT, _In_ UINT, _Inout_opt_ PVOID, _In_ UINT)
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:112
smooth NULL
Definition: ftsmooth.c:416
HWND WINAPI GetDesktopWindow(void)
Definition: window.c:622
BOOL WINAPI EnumDesktopsA(_In_opt_ HWINSTA, _In_ DESKTOPENUMPROCA, _In_ LPARAM)
static DWORD CALLBACK thread(LPVOID arg)
Definition: winstation.c:68
#define DESKTOP_ALL_ACCESS
Definition: winstation.c:30
LONG_PTR LPARAM
Definition: windef.h:208
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventA(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCSTR lpName OPTIONAL)
Definition: synch.c:583
const char * LPCSTR
Definition: xmlstorage.h:183
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
DWORD WINAPI GetCurrentThreadId(VOID)
Definition: thread.c:421
#define UlongToPtr(u)
Definition: config.h:106
#define WM_DESTROY
Definition: winuser.h:1591
static void test_enumdesktops(void)
Definition: winstation.c:415
#define todo_wine_if(is_todo)
Definition: test.h:155
static void test_getuserobjectinformation(void)
Definition: winstation.c:450
struct tag_wnd_param wnd_param
#define WAIT_OBJECT_0
Definition: winbase.h:387
GLsizeiptr size
Definition: glext.h:5919
HANDLE hevent
Definition: winstation.c:811
__wchar_t WCHAR
Definition: xmlstorage.h:180
static HDESK initial_desktop
Definition: winstation.c:66
#define UOI_NAME
Definition: winuser.h:1074
HANDLE WINAPI GetCurrentProcess(VOID)
Definition: proc.c:1168
HDESK WINAPI CreateDesktopA(LPCSTR lpszDesktop, LPCSTR lpszDevice, LPDEVMODEA pDevmode, DWORD dwFlags, ACCESS_MASK dwDesiredAccess, LPSECURITY_ATTRIBUTES lpsa)
Definition: desktop.c:431
GLfloat param
Definition: glext.h:5796
#define WINAPI
Definition: msvc.h:8
START_TEST(winstation)
Definition: winstation.c:1000
unsigned long DWORD
Definition: ntddk_ex.h:95
PVOID HANDLE
Definition: typedefs.h:71
#define SetLastError(x)
Definition: compat.h:409
BOOL WINAPI SwitchDesktop(_In_ HDESK)
static BOOL CALLBACK desktop_callbackA(LPSTR desktop, LPARAM lp)
Definition: winstation.c:392
GLbitfield flags
Definition: glext.h:7161
static void test_handles(void)
Definition: winstation.c:109
static BOOL CALLBACK window_station_callbackA(LPSTR winsta, LPARAM lp)
Definition: winstation.c:341
HDESK WINAPI OpenDesktopA(_In_ LPCSTR, _In_ DWORD, _In_ BOOL, _In_ DWORD)
BOOL WINAPI EnumWindowStationsA(_In_ WINSTAENUMPROCA, _In_ LPARAM)
static DWORD set_foreground(HWND hwnd)
Definition: winstation.c:836
int ret
static void test_enumstations(void)
Definition: winstation.c:359
#define todo_wine
Definition: test.h:154
static BOOL CALLBACK open_window_station_callbackA(LPSTR winsta, LPARAM lp)
Definition: winstation.c:347
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:414
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:819
GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint GLdouble GLdouble w2
Definition: glext.h:8308
#define CS_DBLCLKS
Definition: winuser.h:646
LRESULT WINAPI DefWindowProcA(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
LPCSTR lpszClassName
Definition: winuser.h:3125
HCURSOR WINAPI LoadCursorA(_In_opt_ HINSTANCE, _In_ LPCSTR)
Definition: cursoricon.c:2059
#define broken(x)
Definition: _sntprintf.h:21
UINT style
Definition: winuser.h:3116
#define SWP_NOSIZE
Definition: winuser.h:1230
static const WCHAR DesktopW[]
Definition: shellpath.c:555
#define SPIF_UPDATEINIFILE
Definition: winuser.h:1553
HWINSTA WINAPI CreateWindowStationA(_In_opt_ LPCSTR lpwinsta, _In_ DWORD dwFlags, _In_ ACCESS_MASK dwDesiredAccess, _In_opt_ LPSECURITY_ATTRIBUTES lpsa)
DWORD type
Definition: winable.h:59
#define SW_SHOWNORMAL
Definition: winuser.h:764
static void print_object(HANDLE obj)
Definition: winstation.c:32
#define WINSTA_ALL_ACCESS
Definition: winuser.h:417
static PULONG
Definition: winstation.c:28
#define DESKTOPS
HINSTANCE hInstance
Definition: winuser.h:3120
#define UOI_TYPE
Definition: winuser.h:1075
#define WS_POPUP
Definition: pedump.c:616
unsigned int UINT
Definition: ndis.h:50
#define SPIF_SENDCHANGE
Definition: winuser.h:1555
HWND WINAPI GetForegroundWindow(void)
Definition: ntwrapper.h:392
HWINSTA WINAPI GetProcessWindowStation(void)
Definition: ntwrapper.h:124
static DWORD WINAPI create_window(LPVOID param)
Definition: winstation.c:814
#define HANDLE_FLAG_PROTECT_FROM_CLOSE
Definition: winbase.h:262
static HINSTANCE hntdll
Definition: process.c:66
static LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
Definition: winstation.c:795
WNDPROC lpfnWndProc
Definition: winuser.h:3117
#define msg(x)
Definition: auth_time.c:54
#define IDC_ARROW
Definition: winuser.h:682
Definition: name.c:36
BOOL WINAPI CloseDesktop(_In_ HDESK)
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
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 GetUserObjectInformationA(_In_ HANDLE hObj, _In_ int nIndex, _Out_writes_bytes_opt_(nLength) PVOID pvInfo, _In_ DWORD nLength, _Out_opt_ LPDWORD lpnLengthNeeded)
GLenum GLuint id
Definition: glext.h:5579
BOOL WINAPI GetHandleInformation(IN HANDLE hObject, OUT LPDWORD lpdwFlags)
Definition: handle.c:40
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
#define ERROR_CALL_NOT_IMPLEMENTED
Definition: compat.h:92
BOOL WINAPI SetForegroundWindow(_In_ HWND)
HANDLE WINAPI DECLSPEC_HOTPATCH CreateMutexA(IN LPSECURITY_ATTRIBUTES lpMutexAttributes OPTIONAL, IN BOOL bInitialOwner, IN LPCSTR lpName OPTIONAL)
Definition: synch.c:509
#define GetProcAddress(x, y)
Definition: compat.h:410
#define SWP_NOMOVE
Definition: winuser.h:1229
BOOL WINAPI SetWindowPos(_In_ HWND, _In_opt_ HWND, _In_ int, _In_ int, _In_ int, _In_ int, _In_ UINT)
#define HWND_NOTOPMOST
Definition: winuser.h:1192
#define ERROR_PATH_NOT_FOUND
Definition: winerror.h:106
UINT WINAPI GlobalGetAtomNameA(ATOM nAtom, LPSTR lpBuffer, int nSize)
Definition: atom.c:484
LONG_PTR LRESULT
Definition: windef.h:209
#define INFINITE
Definition: serial.h:102
#define memset(x, y, z)
Definition: compat.h:39
static SERVICE_STATUS status
Definition: service.c:31
#define ERROR_BAD_PATHNAME
Definition: winerror.h:233
#define win_skip
Definition: test.h:141
LPARAM lParam
Definition: combotst.c:139
ATOM WINAPI RegisterClassA(_In_ CONST WNDCLASSA *)
__analysis_noreturn void WINAPI PostQuitMessage(_In_ int)
UINT WINAPI SendInput(UINT, LPINPUT, int)
Definition: ntwrapper.h:344
static ULONG
Definition: winstation.c:28
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
static void test_inputdesktop2(void)
Definition: winstation.c:725
static NTSTATUS(WINAPI *pNtQueryObject)(HANDLE
BOOL WINAPI CloseWindowStation(_In_ HWINSTA)
GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint GLdouble w1
Definition: glext.h:8308
HICON hIcon
Definition: winuser.h:3121
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10
Definition: ps.c:97