596e9ffd8d65f1a6c315471e20259ffbaeb30b0a
[reactos.git] / rostests / winetests / user32 / winstation.c
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
27 #define DESKTOP_ALL_ACCESS 0x01ff
28
29 static void print_object( HANDLE obj )
30 {
31 char buffer[100];
32 DWORD size;
33
34 strcpy( buffer, "foobar" );
35 if (!GetUserObjectInformationA( obj, UOI_NAME, buffer, sizeof(buffer), &size ))
36 trace( "could not get info for %p\n", obj );
37 else
38 trace( "obj %p name '%s'\n", obj, buffer );
39 strcpy( buffer, "foobar" );
40 if (!GetUserObjectInformationA( obj, UOI_TYPE, buffer, sizeof(buffer), &size ))
41 trace( "could not get type for %p\n", obj );
42 else
43 trace( "obj %p type '%s'\n", obj, buffer );
44 }
45
46 static void register_class(void)
47 {
48 WNDCLASSA cls;
49
50 cls.style = CS_DBLCLKS;
51 cls.lpfnWndProc = DefWindowProcA;
52 cls.cbClsExtra = 0;
53 cls.cbWndExtra = 0;
54 cls.hInstance = GetModuleHandleA(0);
55 cls.hIcon = 0;
56 cls.hCursor = LoadCursorA(0, IDC_ARROW);
57 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
58 cls.lpszMenuName = NULL;
59 cls.lpszClassName = "WinStationClass";
60 RegisterClassA(&cls);
61 }
62
63 static HDESK initial_desktop;
64
65 static DWORD CALLBACK thread( LPVOID arg )
66 {
67 HDESK d1, d2;
68 HWND hwnd = CreateWindowExA(0,"WinStationClass","test",WS_POPUP,0,0,100,100,GetDesktopWindow(),0,0,0);
69 ok( hwnd != 0, "CreateWindow failed\n" );
70 d1 = GetThreadDesktop(GetCurrentThreadId());
71 trace( "thread %p desktop: %p\n", arg, d1 );
72 ok( d1 == initial_desktop, "thread %p doesn't use initial desktop\n", arg );
73
74 SetLastError( 0xdeadbeef );
75 ok( !CloseHandle( d1 ), "CloseHandle succeeded\n" );
76 ok( GetLastError() == ERROR_INVALID_HANDLE, "bad last error %d\n", GetLastError() );
77 SetLastError( 0xdeadbeef );
78 ok( !CloseDesktop( d1 ), "CloseDesktop succeeded\n" );
79 ok( GetLastError() == ERROR_BUSY, "bad last error %d\n", GetLastError() );
80 print_object( d1 );
81 d2 = CreateDesktop( "foobar2", NULL, NULL, 0, DESKTOP_ALL_ACCESS, NULL );
82 trace( "created desktop %p\n", d2 );
83 ok( d2 != 0, "CreateDesktop failed\n" );
84
85 SetLastError( 0xdeadbeef );
86 ok( !SetThreadDesktop( d2 ), "set thread desktop succeeded with existing window\n" );
87 ok( GetLastError() == ERROR_BUSY, "bad last error %d\n", GetLastError() );
88
89 DestroyWindow( hwnd );
90 ok( SetThreadDesktop( d2 ), "set thread desktop failed\n" );
91 d1 = GetThreadDesktop(GetCurrentThreadId());
92 ok( d1 == d2, "GetThreadDesktop did not return set desktop %p/%p\n", d1, d2 );
93 print_object( d2 );
94 if (arg < (LPVOID)5)
95 {
96 HANDLE hthread = CreateThread( NULL, 0, thread, (char *)arg + 1, 0, NULL );
97 Sleep(1000);
98 WaitForSingleObject( hthread, INFINITE );
99 CloseHandle( hthread );
100 }
101 return 0;
102 }
103
104 static void test_handles(void)
105 {
106 HWINSTA w1, w2, w3;
107 HDESK d1, d2, d3;
108 HANDLE hthread;
109 DWORD id, flags;
110 ATOM atom;
111 char buffer[20];
112
113 /* win stations */
114
115 w1 = GetProcessWindowStation();
116 ok( GetProcessWindowStation() == w1, "GetProcessWindowStation returned different handles\n" );
117 ok( !CloseWindowStation(w1), "closing process win station succeeded\n" );
118 SetLastError( 0xdeadbeef );
119 ok( !CloseHandle(w1), "closing process win station handle succeeded\n" );
120 ok( GetLastError() == ERROR_INVALID_HANDLE, "bad last error %d\n", GetLastError() );
121 print_object( w1 );
122
123 flags = 0;
124 ok( GetHandleInformation( w1, &flags ), "GetHandleInformation failed\n" );
125 ok( !(flags & HANDLE_FLAG_PROTECT_FROM_CLOSE) ||
126 broken(flags & HANDLE_FLAG_PROTECT_FROM_CLOSE), /* set on nt4 */
127 "handle %p PROTECT_FROM_CLOSE set\n", w1 );
128
129 ok( DuplicateHandle( GetCurrentProcess(), w1, GetCurrentProcess(), (PHANDLE)&w2, 0,
130 TRUE, DUPLICATE_SAME_ACCESS ), "DuplicateHandle failed\n" );
131 ok( CloseWindowStation(w2), "closing dup win station failed\n" );
132
133 ok( DuplicateHandle( GetCurrentProcess(), w1, GetCurrentProcess(), (PHANDLE)&w2, 0,
134 TRUE, DUPLICATE_SAME_ACCESS ), "DuplicateHandle failed\n" );
135 ok( CloseHandle(w2), "closing dup win station handle failed\n" );
136
137 w2 = CreateWindowStation("WinSta0", 0, WINSTA_ALL_ACCESS, NULL );
138 ok( w2 != 0, "CreateWindowStation failed\n" );
139 ok( w2 != w1, "CreateWindowStation returned default handle\n" );
140 SetLastError( 0xdeadbeef );
141 ok( !CloseDesktop( (HDESK)w2 ), "CloseDesktop succeeded on win station\n" );
142 ok( GetLastError() == ERROR_INVALID_HANDLE, "bad last error %d\n", GetLastError() );
143 ok( CloseWindowStation( w2 ), "CloseWindowStation failed\n" );
144
145 w2 = CreateWindowStation("WinSta0", 0, WINSTA_ALL_ACCESS, NULL );
146 ok( CloseHandle( w2 ), "CloseHandle failed\n" );
147
148 w2 = OpenWindowStation("winsta0", TRUE, WINSTA_ALL_ACCESS );
149 ok( w2 != 0, "OpenWindowStation failed\n" );
150 ok( w2 != w1, "OpenWindowStation returned default handle\n" );
151 ok( CloseWindowStation( w2 ), "CloseWindowStation failed\n" );
152
153 w2 = OpenWindowStation("dummy name", TRUE, WINSTA_ALL_ACCESS );
154 ok( !w2, "open dummy win station succeeded\n" );
155
156 CreateMutexA( NULL, 0, "foobar" );
157 w2 = CreateWindowStation("foobar", 0, WINSTA_ALL_ACCESS, NULL );
158 ok( w2 != 0, "create foobar station failed\n" );
159
160 w3 = OpenWindowStation("foobar", TRUE, WINSTA_ALL_ACCESS );
161 ok( w3 != 0, "open foobar station failed\n" );
162 ok( w3 != w2, "open foobar station returned same handle\n" );
163 ok( CloseWindowStation( w2 ), "CloseWindowStation failed\n" );
164 ok( CloseWindowStation( w3 ), "CloseWindowStation failed\n" );
165
166 w3 = OpenWindowStation("foobar", TRUE, WINSTA_ALL_ACCESS );
167 ok( !w3, "open foobar station succeeded\n" );
168
169 w2 = CreateWindowStation("foobar1", 0, WINSTA_ALL_ACCESS, NULL );
170 ok( w2 != 0, "create foobar station failed\n" );
171 w3 = CreateWindowStation("foobar2", 0, WINSTA_ALL_ACCESS, NULL );
172 ok( w3 != 0, "create foobar station failed\n" );
173 ok( GetHandleInformation( w2, &flags ), "GetHandleInformation failed\n" );
174 ok( GetHandleInformation( w3, &flags ), "GetHandleInformation failed\n" );
175
176 SetProcessWindowStation( w2 );
177 register_class();
178 atom = GlobalAddAtomA("foo");
179 ok( GlobalGetAtomNameA( atom, buffer, sizeof(buffer) ) == 3, "GlobalGetAtomName failed\n" );
180 ok( !lstrcmpiA( buffer, "foo" ), "bad atom value %s\n", buffer );
181
182 ok( !CloseWindowStation( w2 ), "CloseWindowStation succeeded\n" );
183 ok( GetHandleInformation( w2, &flags ), "GetHandleInformation failed\n" );
184
185 SetProcessWindowStation( w3 );
186 ok( GetHandleInformation( w2, &flags ), "GetHandleInformation failed\n" );
187 ok( CloseWindowStation( w2 ), "CloseWindowStation failed\n" );
188 ok( GlobalGetAtomNameA( atom, buffer, sizeof(buffer) ) == 3, "GlobalGetAtomName failed\n" );
189 ok( !lstrcmpiA( buffer, "foo" ), "bad atom value %s\n", buffer );
190
191 /* desktops */
192 d1 = GetThreadDesktop(GetCurrentThreadId());
193 initial_desktop = d1;
194 ok( GetThreadDesktop(GetCurrentThreadId()) == d1,
195 "GetThreadDesktop returned different handles\n" );
196
197 flags = 0;
198 ok( GetHandleInformation( d1, &flags ), "GetHandleInformation failed\n" );
199 ok( !(flags & HANDLE_FLAG_PROTECT_FROM_CLOSE), "handle %p PROTECT_FROM_CLOSE set\n", d1 );
200
201 SetLastError( 0xdeadbeef );
202 ok( !CloseDesktop(d1), "closing thread desktop succeeded\n" );
203 ok( GetLastError() == ERROR_BUSY, "bad last error %d\n", GetLastError() );
204
205 SetLastError( 0xdeadbeef );
206 if (CloseHandle( d1 )) /* succeeds on nt4 */
207 {
208 win_skip( "NT4 desktop handle management is completely different\n" );
209 return;
210 }
211 ok( GetLastError() == ERROR_INVALID_HANDLE, "bad last error %d\n", GetLastError() );
212
213 ok( DuplicateHandle( GetCurrentProcess(), d1, GetCurrentProcess(), (PHANDLE)&d2, 0,
214 TRUE, DUPLICATE_SAME_ACCESS ), "DuplicateHandle failed\n" );
215 ok( CloseDesktop(d2), "closing dup desktop failed\n" );
216
217 ok( DuplicateHandle( GetCurrentProcess(), d1, GetCurrentProcess(), (PHANDLE)&d2, 0,
218 TRUE, DUPLICATE_SAME_ACCESS ), "DuplicateHandle failed\n" );
219 ok( CloseHandle(d2), "closing dup desktop handle failed\n" );
220
221 d2 = OpenDesktop( "dummy name", 0, TRUE, DESKTOP_ALL_ACCESS );
222 ok( !d2, "open dummy desktop succeeded\n" );
223
224 d2 = CreateDesktop( "foobar", NULL, NULL, 0, DESKTOP_ALL_ACCESS, NULL );
225 ok( d2 != 0, "create foobar desktop failed\n" );
226 SetLastError( 0xdeadbeef );
227 ok( !CloseWindowStation( (HWINSTA)d2 ), "CloseWindowStation succeeded on desktop\n" );
228 ok( GetLastError() == ERROR_INVALID_HANDLE, "bad last error %d\n", GetLastError() );
229
230 SetLastError( 0xdeadbeef );
231 d3 = CreateDesktop( "foobar", NULL, NULL, 0, DESKTOP_ALL_ACCESS, NULL );
232 ok( d3 != 0, "create foobar desktop again failed\n" );
233 ok( GetLastError() == 0xdeadbeef, "bad last error %d\n", GetLastError() );
234 ok( CloseDesktop( d3 ), "CloseDesktop failed\n" );
235
236 d3 = OpenDesktop( "foobar", 0, TRUE, DESKTOP_ALL_ACCESS );
237 ok( d3 != 0, "open foobar desktop failed\n" );
238 ok( d3 != d2, "open foobar desktop returned same handle\n" );
239 ok( CloseDesktop( d2 ), "CloseDesktop failed\n" );
240 ok( CloseDesktop( d3 ), "CloseDesktop failed\n" );
241
242 d3 = OpenDesktop( "foobar", 0, TRUE, DESKTOP_ALL_ACCESS );
243 ok( !d3, "open foobar desktop succeeded\n" );
244
245 ok( !CloseHandle(d1), "closing thread desktop handle succeeded\n" );
246 d2 = GetThreadDesktop(GetCurrentThreadId());
247 ok( d1 == d2, "got different handles after close\n" );
248
249 trace( "thread 1 desktop: %p\n", d1 );
250 print_object( d1 );
251 hthread = CreateThread( NULL, 0, thread, (LPVOID)2, 0, &id );
252 Sleep(1000);
253 trace( "get other thread desktop: %p\n", GetThreadDesktop(id) );
254 WaitForSingleObject( hthread, INFINITE );
255 CloseHandle( hthread );
256 }
257
258 /* Enumeration tests */
259
260 static BOOL CALLBACK window_station_callbackA(LPSTR winsta, LPARAM lp)
261 {
262 trace("window_station_callbackA called with argument %s\n", winsta);
263 return lp;
264 }
265
266 static BOOL CALLBACK open_window_station_callbackA(LPSTR winsta, LPARAM lp)
267 {
268 HWINSTA hwinsta;
269
270 trace("open_window_station_callbackA called with argument %s\n", winsta);
271 hwinsta = OpenWindowStationA(winsta, FALSE, WINSTA_ENUMERATE);
272 ok(hwinsta != NULL, "Could not open desktop %s!\n", winsta);
273 if (hwinsta)
274 CloseWindowStation(hwinsta);
275 return lp;
276 }
277
278 static void test_enumstations(void)
279 {
280 BOOL ret;
281
282 if (0) /* Crashes instead */
283 {
284 SetLastError(0xbabefeed);
285 ret = EnumWindowStationsA(NULL, 0);
286 ok(!ret, "EnumWindowStationsA returned successfully!\n");
287 ok(GetLastError() == ERROR_INVALID_PARAMETER, "LastError is set to %08x\n", GetLastError());
288 }
289
290 SetLastError(0xdeadbeef);
291 ret = EnumWindowStationsA(open_window_station_callbackA, 0x12345);
292 ok(ret == 0x12345, "EnumWindowStationsA returned %x\n", ret);
293 ok(GetLastError() == 0xdeadbeef, "LastError is set to %08x\n", GetLastError());
294
295 SetLastError(0xdeadbeef);
296 ret = EnumWindowStationsA(window_station_callbackA, 0);
297 ok(!ret, "EnumWindowStationsA returned %x\n", ret);
298 ok(GetLastError() == 0xdeadbeef, "LastError is set to %08x\n", GetLastError());
299 }
300
301 static BOOL CALLBACK desktop_callbackA(LPSTR desktop, LPARAM lp)
302 {
303 trace("desktop_callbackA called with argument %s\n", desktop);
304 return lp;
305 }
306
307 static BOOL CALLBACK open_desktop_callbackA(LPSTR desktop, LPARAM lp)
308 {
309 HDESK hdesk;
310 static int once;
311
312 trace("open_desktop_callbackA called with argument %s\n", desktop);
313 /* Only try to open one desktop */
314 if (once++)
315 return lp;
316
317 hdesk = OpenDesktopA(desktop, 0, FALSE, DESKTOP_ENUMERATE);
318 ok(hdesk != NULL, "Could not open desktop %s!\n", desktop);
319 if (hdesk)
320 CloseDesktop(hdesk);
321 return lp;
322 }
323
324 static void test_enumdesktops(void)
325 {
326 BOOL ret;
327
328 if (0) /* Crashes instead */
329 {
330 SetLastError(0xbabefeed);
331 ret = EnumDesktopsA(GetProcessWindowStation(), NULL, 0);
332 ok(!ret, "EnumDesktopsA returned successfully!\n");
333 ok(GetLastError() == ERROR_INVALID_PARAMETER, "LastError is set to %08x\n", GetLastError());
334 }
335
336 SetLastError(0xdeadbeef);
337 ret = EnumDesktopsA(NULL, desktop_callbackA, 0x12345);
338 ok(ret == 0x12345, "EnumDesktopsA returned %x\n", ret);
339 ok(GetLastError() == 0xdeadbeef, "LastError is set to %08x\n", GetLastError());
340
341 SetLastError(0xdeadbeef);
342 ret = EnumDesktopsA(GetProcessWindowStation(), open_desktop_callbackA, 0x12345);
343 ok(ret == 0x12345, "EnumDesktopsA returned %x\n", ret);
344 ok(GetLastError() == 0xdeadbeef, "LastError is set to %08x\n", GetLastError());
345
346 SetLastError(0xdeadbeef);
347 ret = EnumDesktopsA(INVALID_HANDLE_VALUE, desktop_callbackA, 0x12345);
348 ok(!ret, "EnumDesktopsA returned %x\n", ret);
349 ok(GetLastError() == ERROR_INVALID_HANDLE, "LastError is set to %08x\n", GetLastError());
350
351 SetLastError(0xdeadbeef);
352 ret = EnumDesktopsA(GetProcessWindowStation(), desktop_callbackA, 0);
353 ok(!ret, "EnumDesktopsA returned %x\n", ret);
354 ok(GetLastError() == 0xdeadbeef, "LastError is set to %08x\n", GetLastError());
355 }
356
357 START_TEST(winstation)
358 {
359 /* Check whether this platform supports WindowStation calls */
360
361 SetLastError( 0xdeadbeef );
362 GetProcessWindowStation();
363 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
364 {
365 skip("WindowStation calls not supported on this platform\n");
366 return;
367 }
368
369 test_enumstations();
370 test_enumdesktops();
371 test_handles();
372 }