1 /*
2 * 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 "ntstatus.h"
22 #define WIN32_NO_STATUS
23
24 #include <stdarg.h>
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winnls.h"
28 #include "winerror.h"
29 #include "wingdi.h"
30 #include "winuser.h"
31 #include "wine/server.h"
32 #include "wine/unicode.h"
33 #include "wine/debug.h"
34 #include "user_private.h"
35
36 WINE_DEFAULT_DEBUG_CHANNEL(winstation);
37
38
39 /* callback for enumeration functions */
40 struct enum_proc_lparam
41 {
42 NAMEENUMPROCA func;
43 LPARAM lparam;
44 };
45
46 static BOOL CALLBACK enum_names_WtoA( LPWSTR name, LPARAM lparam )
47 {
48 struct enum_proc_lparam *data = (struct enum_proc_lparam *)lparam;
49 char buffer[MAX_PATH];
50
51 if (!WideCharToMultiByte( CP_ACP, 0, name, -1, buffer, sizeof(buffer), NULL, NULL ))
52 return FALSE;
53 return data->func( buffer, data->lparam );
54 }
55
56
57 /***********************************************************************
58 * CreateWindowStationA (USER32.@)
59 */
60 HWINSTA WINAPI CreateWindowStationA( LPCSTR name, DWORD reserved, ACCESS_MASK access,
61 LPSECURITY_ATTRIBUTES sa )
62 {
63 WCHAR buffer[MAX_PATH];
64
65 if (!name) return CreateWindowStationW( NULL, reserved, access, sa );
66
67 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
68 {
69 SetLastError( ERROR_FILENAME_EXCED_RANGE );
70 return 0;
71 }
72 return CreateWindowStationW( buffer, reserved, access, sa );
73 }
74
75
76 /***********************************************************************
77 * CreateWindowStationW (USER32.@)
78 */
79 HWINSTA WINAPI CreateWindowStationW( LPCWSTR name, DWORD reserved, ACCESS_MASK access,
80 LPSECURITY_ATTRIBUTES sa )
81 {
82 HANDLE ret;
83 DWORD len = name ? strlenW(name) : 0;
84
85 if (len >= MAX_PATH)
86 {
87 SetLastError( ERROR_FILENAME_EXCED_RANGE );
88 return 0;
89 }
90 SERVER_START_REQ( create_winstation )
91 {
92 req->flags = 0;
93 req->access = access;
94 req->attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF |
95 ((sa && sa->bInheritHandle) ? OBJ_INHERIT : 0);
96 wine_server_add_data( req, name, len * sizeof(WCHAR) );
97 /* it doesn't seem to set last error */
98 wine_server_call( req );
99 ret = wine_server_ptr_handle( reply->handle );
100 }
101 SERVER_END_REQ;
102 return ret;
103 }
104
105
106 /******************************************************************************
107 * OpenWindowStationA (USER32.@)
108 */
109 HWINSTA WINAPI OpenWindowStationA( LPCSTR name, BOOL inherit, ACCESS_MASK access )
110 {
111 WCHAR buffer[MAX_PATH];
112
113 if (!name) return OpenWindowStationW( NULL, inherit, access );
114
115 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
116 {
117 SetLastError( ERROR_FILENAME_EXCED_RANGE );
118 return 0;
119 }
120 return OpenWindowStationW( buffer, inherit, access );
121 }
122
123
124 /******************************************************************************
125 * OpenWindowStationW (USER32.@)
126 */
127 HWINSTA WINAPI OpenWindowStationW( LPCWSTR name, BOOL inherit, ACCESS_MASK access )
128 {
129 HANDLE ret = 0;
130 DWORD len = name ? strlenW(name) : 0;
131 if (len >= MAX_PATH)
132 {
133 SetLastError( ERROR_FILENAME_EXCED_RANGE );
134 return 0;
135 }
136 SERVER_START_REQ( open_winstation )
137 {
138 req->access = access;
139 req->attributes = OBJ_CASE_INSENSITIVE | (inherit ? OBJ_INHERIT : 0);
140 wine_server_add_data( req, name, len * sizeof(WCHAR) );
141 if (!wine_server_call_err( req )) ret = wine_server_ptr_handle( reply->handle );
142 }
143 SERVER_END_REQ;
144 return ret;
145 }
146
147
148 /***********************************************************************
149 * CloseWindowStation (USER32.@)
150 */
151 BOOL WINAPI CloseWindowStation( HWINSTA handle )
152 {
153 BOOL ret;
154 SERVER_START_REQ( close_winstation )
155 {
156 req->handle = wine_server_obj_handle( handle );
157 ret = !wine_server_call_err( req );
158 }
159 SERVER_END_REQ;
160 return ret;
161 }
162
163
164 /******************************************************************************
165 * GetProcessWindowStation (USER32.@)
166 */
167 HWINSTA WINAPI GetProcessWindowStation(void)
168 {
169 HWINSTA ret = 0;
170
171 SERVER_START_REQ( get_process_winstation )
172 {
173 if (!wine_server_call_err( req ))
174 ret = wine_server_ptr_handle( reply->handle );
175 }
176 SERVER_END_REQ;
177 return ret;
178 }
179
180
181 /***********************************************************************
182 * SetProcessWindowStation (USER32.@)
183 */
184 BOOL WINAPI SetProcessWindowStation( HWINSTA handle )
185 {
186 BOOL ret;
187
188 SERVER_START_REQ( set_process_winstation )
189 {
190 req->handle = wine_server_obj_handle( handle );
191 ret = !wine_server_call_err( req );
192 }
193 SERVER_END_REQ;
194 return ret;
195 }
196
197
198 /******************************************************************************
199 * EnumWindowStationsA (USER32.@)
200 */
201 BOOL WINAPI EnumWindowStationsA( WINSTAENUMPROCA func, LPARAM lparam )
202 {
203 struct enum_proc_lparam data;
204 data.func = func;
205 data.lparam = lparam;
206 return EnumWindowStationsW( enum_names_WtoA, (LPARAM)&data );
207 }
208
209
210 /******************************************************************************
211 * EnumWindowStationsW (USER32.@)
212 */
213 BOOL WINAPI EnumWindowStationsW( WINSTAENUMPROCW func, LPARAM lparam )
214 {
215 unsigned int index = 0;
216 WCHAR name[MAX_PATH];
217 BOOL ret = TRUE;
218 NTSTATUS status;
219
220 while (ret)
221 {
222 SERVER_START_REQ( enum_winstation )
223 {
224 req->index = index;
225 wine_server_set_reply( req, name, sizeof(name) - sizeof(WCHAR) );
226 status = wine_server_call( req );
227 name[wine_server_reply_size(reply)/sizeof(WCHAR)] = 0;
228 index = reply->next;
229 }
230 SERVER_END_REQ;
231 if (status == STATUS_NO_MORE_ENTRIES)
232 break;
233 if (status)
234 {
235 SetLastError( RtlNtStatusToDosError( status ) );
236 return FALSE;
237 }
238 ret = func( name, lparam );
239 }
240 return ret;
241 }
242
243
244 /***********************************************************************
245 * CreateDesktopA (USER32.@)
246 */
247 HDESK WINAPI CreateDesktopA( LPCSTR name, LPCSTR device, LPDEVMODEA devmode,
248 DWORD flags, ACCESS_MASK access, LPSECURITY_ATTRIBUTES sa )
249 {
250 WCHAR buffer[MAX_PATH];
251
252 if (device || devmode)
253 {
254 SetLastError( ERROR_INVALID_PARAMETER );
255 return 0;
256 }
257 if (!name) return CreateDesktopW( NULL, NULL, NULL, flags, access, sa );
258
259 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
260 {
261 SetLastError( ERROR_FILENAME_EXCED_RANGE );
262 return 0;
263 }
264 return CreateDesktopW( buffer, NULL, NULL, flags, access, sa );
265 }
266
267
268 /***********************************************************************
269 * CreateDesktopW (USER32.@)
270 */
271 HDESK WINAPI CreateDesktopW( LPCWSTR name, LPCWSTR device, LPDEVMODEW devmode,
272 DWORD flags, ACCESS_MASK access, LPSECURITY_ATTRIBUTES sa )
273 {
274 HANDLE ret;
275 DWORD len = name ? strlenW(name) : 0;
276
277 if (device || devmode)
278 {
279 SetLastError( ERROR_INVALID_PARAMETER );
280 return 0;
281 }
282 if (len >= MAX_PATH)
283 {
284 SetLastError( ERROR_FILENAME_EXCED_RANGE );
285 return 0;
286 }
287 SERVER_START_REQ( create_desktop )
288 {
289 req->flags = flags;
290 req->access = access;
291 req->attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF |
292 ((sa && sa->bInheritHandle) ? OBJ_INHERIT : 0);
293 wine_server_add_data( req, name, len * sizeof(WCHAR) );
294 /* it doesn't seem to set last error */
295 wine_server_call( req );
296 ret = wine_server_ptr_handle( reply->handle );
297 }
298 SERVER_END_REQ;
299 return ret;
300 }
301
302
303 /******************************************************************************
304 * OpenDesktopA (USER32.@)
305 */
306 HDESK WINAPI OpenDesktopA( LPCSTR name, DWORD flags, BOOL inherit, ACCESS_MASK access )
307 {
308 WCHAR buffer[MAX_PATH];
309
310 if (!name) return OpenDesktopW( NULL, flags, inherit, access );
311
312 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
313 {
314 SetLastError( ERROR_FILENAME_EXCED_RANGE );
315 return 0;
316 }
317 return OpenDesktopW( buffer, flags, inherit, access );
318 }
319
320
321 HDESK open_winstation_desktop( HWINSTA hwinsta, LPCWSTR name, DWORD flags, BOOL inherit, ACCESS_MASK access )
322 {
323 HANDLE ret = 0;
324 DWORD len = name ? strlenW(name) : 0;
325 if (len >= MAX_PATH)
326 {
327 SetLastError( ERROR_FILENAME_EXCED_RANGE );
328 return 0;
329 }
330 SERVER_START_REQ( open_desktop )
331 {
332 req->winsta = wine_server_obj_handle( hwinsta );
333 req->flags = flags;
334 req->access = access;
335 req->attributes = OBJ_CASE_INSENSITIVE | (inherit ? OBJ_INHERIT : 0);
336 wine_server_add_data( req, name, len * sizeof(WCHAR) );
337 if (!wine_server_call( req )) ret = wine_server_ptr_handle( reply->handle );
338 }
339 SERVER_END_REQ;
340 return ret;
341 }
342
343
344 /******************************************************************************
345 * OpenDesktopW (USER32.@)
346 */
347 HDESK WINAPI OpenDesktopW( LPCWSTR name, DWORD flags, BOOL inherit, ACCESS_MASK access )
348 {
349 return open_winstation_desktop( NULL, name, flags, inherit, access );
350 }
351
352
353 /***********************************************************************
354 * CloseDesktop (USER32.@)
355 */
356 BOOL WINAPI CloseDesktop( HDESK handle )
357 {
358 BOOL ret;
359 SERVER_START_REQ( close_desktop )
360 {
361 req->handle = wine_server_obj_handle( handle );
362 ret = !wine_server_call_err( req );
363 }
364 SERVER_END_REQ;
365 return ret;
366 }
367
368
369 /******************************************************************************
370 * GetThreadDesktop (USER32.@)
371 */
372 HDESK WINAPI GetThreadDesktop( DWORD thread )
373 {
374 HDESK ret = 0;
375
376 SERVER_START_REQ( get_thread_desktop )
377 {
378 req->tid = thread;
379 if (!wine_server_call_err( req )) ret = wine_server_ptr_handle( reply->handle );
380 }
381 SERVER_END_REQ;
382 return ret;
383 }
384
385
386 /******************************************************************************
387 * SetThreadDesktop (USER32.@)
388 */
389 BOOL WINAPI SetThreadDesktop( HDESK handle )
390 {
391 BOOL ret;
392
393 SERVER_START_REQ( set_thread_desktop )
394 {
395 req->handle = wine_server_obj_handle( handle );
396 ret = !wine_server_call_err( req );
397 }
398 SERVER_END_REQ;
399 if (ret) /* reset the desktop windows */
400 {
401 struct user_thread_info *thread_info = get_user_thread_info();
402 thread_info->top_window = 0;
403 thread_info->msg_window = 0;
404 }
405 return ret;
406 }
407
408
409 /******************************************************************************
410 * EnumDesktopsA (USER32.@)
411 */
412 BOOL WINAPI EnumDesktopsA( HWINSTA winsta, DESKTOPENUMPROCA func, LPARAM lparam )
413 {
414 struct enum_proc_lparam data;
415 data.func = func;
416 data.lparam = lparam;
417 return EnumDesktopsW( winsta, enum_names_WtoA, (LPARAM)&data );
418 }
419
420
421 /******************************************************************************
422 * EnumDesktopsW (USER32.@)
423 */
424 BOOL WINAPI EnumDesktopsW( HWINSTA winsta, DESKTOPENUMPROCW func, LPARAM lparam )
425 {
426 unsigned int index = 0;
427 WCHAR name[MAX_PATH];
428 BOOL ret = TRUE;
429 NTSTATUS status;
430
431 if (!winsta)
432 winsta = GetProcessWindowStation();
433
434 while (ret)
435 {
436 SERVER_START_REQ( enum_desktop )
437 {
438 req->winstation = wine_server_obj_handle( winsta );
439 req->index = index;
440 wine_server_set_reply( req, name, sizeof(name) - sizeof(WCHAR) );
441 status = wine_server_call( req );
442 name[wine_server_reply_size(reply)/sizeof(WCHAR)] = 0;
443 index = reply->next;
444 }
445 SERVER_END_REQ;
446 if (status == STATUS_NO_MORE_ENTRIES)
447 break;
448 if (status)
449 {
450 SetLastError( RtlNtStatusToDosError( status ) );
451 return FALSE;
452 }
453 ret = func(name, lparam);
454 }
455 return ret;
456 }
457
458
459 /******************************************************************************
460 * OpenInputDesktop (USER32.@)
461 */
462 HDESK WINAPI OpenInputDesktop( DWORD flags, BOOL inherit, ACCESS_MASK access )
463 {
464 FIXME( "(%x,%i,%x): stub\n", flags, inherit, access );
465 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
466 return 0;
467 }
468
469
470 /***********************************************************************
471 * GetUserObjectInformationA (USER32.@)
472 */
473 BOOL WINAPI GetUserObjectInformationA( HANDLE handle, INT index, LPVOID info, DWORD len, LPDWORD needed )
474 {
475 /* check for information types returning strings */
476 if (index == UOI_TYPE || index == UOI_NAME)
477 {
478 WCHAR buffer[MAX_PATH];
479 DWORD lenA;
480
481 if (!GetUserObjectInformationW( handle, index, buffer, sizeof(buffer), NULL )) return FALSE;
482 lenA = WideCharToMultiByte( CP_ACP, 0, buffer, -1, NULL, 0, NULL, NULL );
483 if (needed) *needed = lenA;
484 if (lenA > len)
485 {
486 SetLastError( ERROR_MORE_DATA );
487 return FALSE;
488 }
489 if (info) WideCharToMultiByte( CP_ACP, 0, buffer, -1, info, len, NULL, NULL );
490 return TRUE;
491 }
492 return GetUserObjectInformationW( handle, index, info, len, needed );
493 }
494
495
496 /***********************************************************************
497 * GetUserObjectInformationW (USER32.@)
498 */
499 BOOL WINAPI GetUserObjectInformationW( HANDLE handle, INT index, LPVOID info, DWORD len, LPDWORD needed )
500 {
501 static const WCHAR desktopW[] = { 'D','e','s','k','t','o','p',0 };
502 static const WCHAR winstationW[] = { 'W','i','n','d','o','w','S','t','a','t','i','o','n',0 };
503 BOOL ret;
504
505 switch(index)
506 {
507 case UOI_FLAGS:
508 {
509 USEROBJECTFLAGS *obj_flags = info;
510 if (needed) *needed = sizeof(*obj_flags);
511 if (len < sizeof(*obj_flags))
512 {
513 SetLastError( ERROR_BUFFER_OVERFLOW );
514 return FALSE;
515 }
516 SERVER_START_REQ( set_user_object_info )
517 {
518 req->handle = wine_server_obj_handle( handle );
519 req->flags = 0;
520 ret = !wine_server_call_err( req );
521 if (ret)
522 {
523 /* FIXME: inherit flag */
524 obj_flags->dwFlags = reply->old_obj_flags;
525 }
526 }
527 SERVER_END_REQ;
528 }
529 return ret;
530
531 case UOI_TYPE:
532 SERVER_START_REQ( set_user_object_info )
533 {
534 req->handle = wine_server_obj_handle( handle );
535 req->flags = 0;
536 ret = !wine_server_call_err( req );
537 if (ret)
538 {
539 size_t size = reply->is_desktop ? sizeof(desktopW) : sizeof(winstationW);
540 if (needed) *needed = size;
541 if (len < size)
542 {
543 SetLastError( ERROR_MORE_DATA );
544 ret = FALSE;
545 }
546 else memcpy( info, reply->is_desktop ? desktopW : winstationW, size );
547 }
548 }
549 SERVER_END_REQ;
550 return ret;
551
552 case UOI_NAME:
553 {
554 WCHAR buffer[MAX_PATH];
555 SERVER_START_REQ( set_user_object_info )
556 {
557 req->handle = wine_server_obj_handle( handle );
558 req->flags = 0;
559 wine_server_set_reply( req, buffer, sizeof(buffer) - sizeof(WCHAR) );
560 ret = !wine_server_call_err( req );
561 if (ret)
562 {
563 size_t size = wine_server_reply_size( reply );
564 buffer[size / sizeof(WCHAR)] = 0;
565 size += sizeof(WCHAR);
566 if (needed) *needed = size;
567 if (len < size)
568 {
569 SetLastError( ERROR_MORE_DATA );
570 ret = FALSE;
571 }
572 else memcpy( info, buffer, size );
573 }
574 }
575 SERVER_END_REQ;
576 }
577 return ret;
578
579 case UOI_USER_SID:
580 FIXME( "not supported index %d\n", index );
581 /* fall through */
582 default:
583 SetLastError( ERROR_INVALID_PARAMETER );
584 return FALSE;
585 }
586 }
587
588
589 /******************************************************************************
590 * SetUserObjectInformationA (USER32.@)
591 */
592 BOOL WINAPI SetUserObjectInformationA( HANDLE handle, INT index, LPVOID info, DWORD len )
593 {
594 return SetUserObjectInformationW( handle, index, info, len );
595 }
596
597
598 /******************************************************************************
599 * SetUserObjectInformationW (USER32.@)
600 */
601 BOOL WINAPI SetUserObjectInformationW( HANDLE handle, INT index, LPVOID info, DWORD len )
602 {
603 BOOL ret;
604 const USEROBJECTFLAGS *obj_flags = info;
605
606 if (index != UOI_FLAGS || !info || len < sizeof(*obj_flags))
607 {
608 SetLastError( ERROR_INVALID_PARAMETER );
609 return FALSE;
610 }
611 /* FIXME: inherit flag */
612 SERVER_START_REQ( set_user_object_info )
613 {
614 req->handle = wine_server_obj_handle( handle );
615 req->flags = SET_USER_OBJECT_FLAGS;
616 req->obj_flags = obj_flags->dwFlags;
617 ret = !wine_server_call_err( req );
618 }
619 SERVER_END_REQ;
620 return ret;
621 }
622
623
624 /***********************************************************************
625 * GetUserObjectSecurity (USER32.@)
626 */
627 BOOL WINAPI GetUserObjectSecurity( HANDLE handle, PSECURITY_INFORMATION info,
628 PSECURITY_DESCRIPTOR sid, DWORD len, LPDWORD needed )
629 {
630 FIXME( "(%p %p %p len=%d %p),stub!\n", handle, info, sid, len, needed );
631 if (needed)
632 *needed = sizeof(SECURITY_DESCRIPTOR);
633 if (len < sizeof(SECURITY_DESCRIPTOR))
634 {
635 SetLastError( ERROR_INSUFFICIENT_BUFFER );
636 return FALSE;
637 }
638 return InitializeSecurityDescriptor(sid, SECURITY_DESCRIPTOR_REVISION);
639 }
640
641 /***********************************************************************
642 * SetUserObjectSecurity (USER32.@)
643 */
644 BOOL WINAPI SetUserObjectSecurity( HANDLE handle, PSECURITY_INFORMATION info,
645 PSECURITY_DESCRIPTOR sid )
646 {
647 FIXME( "(%p,%p,%p),stub!\n", handle, info, sid );
648 return TRUE;
649 }
650
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.