2 * Window stations and desktops
4 * Copyright 2002 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #define WIN32_NO_STATUS
33 #include "wine/server.h"
34 #include "wine/unicode.h"
35 #include "wine/debug.h"
36 #include "user_private.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(winstation
);
41 /* callback for enumeration functions */
42 struct enum_proc_lparam
48 static BOOL CALLBACK
enum_names_WtoA( LPWSTR name
, LPARAM lparam
)
50 struct enum_proc_lparam
*data
= (struct enum_proc_lparam
*)lparam
;
51 char buffer
[MAX_PATH
];
53 if (!WideCharToMultiByte( CP_ACP
, 0, name
, -1, buffer
, sizeof(buffer
), NULL
, NULL
))
55 return data
->func( buffer
, data
->lparam
);
58 /* return a handle to the directory where window station objects are created */
59 static HANDLE
get_winstations_dir_handle(void)
61 static HANDLE handle
= NULL
;
62 static const WCHAR basenameW
[] = {'\\','W','i','n','d','o','w','s','\\',
63 'W','i','n','d','o','w','S','t','a','t','i','o','n','s',0};
65 OBJECT_ATTRIBUTES attr
;
71 RtlInitUnicodeString( &str
, basenameW
);
72 InitializeObjectAttributes( &attr
, &str
, 0, 0, NULL
);
73 NtOpenDirectoryObject( &dir
, DIRECTORY_CREATE_OBJECT
| DIRECTORY_TRAVERSE
, &attr
);
74 if (InterlockedCompareExchangePointer( &handle
, dir
, 0 ) != 0) /* someone beat us here */
80 /***********************************************************************
81 * CreateWindowStationA (USER32.@)
83 HWINSTA WINAPI
CreateWindowStationA( LPCSTR name
, DWORD reserved
, ACCESS_MASK access
,
84 LPSECURITY_ATTRIBUTES sa
)
86 WCHAR buffer
[MAX_PATH
];
88 if (!name
) return CreateWindowStationW( NULL
, reserved
, access
, sa
);
90 if (!MultiByteToWideChar( CP_ACP
, 0, name
, -1, buffer
, MAX_PATH
))
92 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
95 return CreateWindowStationW( buffer
, reserved
, access
, sa
);
99 /***********************************************************************
100 * CreateWindowStationW (USER32.@)
102 HWINSTA WINAPI
CreateWindowStationW( LPCWSTR name
, DWORD reserved
, ACCESS_MASK access
,
103 LPSECURITY_ATTRIBUTES sa
)
106 DWORD len
= name
? strlenW(name
) : 0;
110 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
113 SERVER_START_REQ( create_winstation
)
116 req
->access
= access
;
117 req
->attributes
= OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
|
118 ((sa
&& sa
->bInheritHandle
) ? OBJ_INHERIT
: 0);
119 req
->rootdir
= wine_server_obj_handle( get_winstations_dir_handle() );
120 wine_server_add_data( req
, name
, len
* sizeof(WCHAR
) );
121 wine_server_call_err( req
);
122 ret
= wine_server_ptr_handle( reply
->handle
);
129 /******************************************************************************
130 * OpenWindowStationA (USER32.@)
132 HWINSTA WINAPI
OpenWindowStationA( LPCSTR name
, BOOL inherit
, ACCESS_MASK access
)
134 WCHAR buffer
[MAX_PATH
];
136 if (!name
) return OpenWindowStationW( NULL
, inherit
, access
);
138 if (!MultiByteToWideChar( CP_ACP
, 0, name
, -1, buffer
, MAX_PATH
))
140 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
143 return OpenWindowStationW( buffer
, inherit
, access
);
147 /******************************************************************************
148 * OpenWindowStationW (USER32.@)
150 HWINSTA WINAPI
OpenWindowStationW( LPCWSTR name
, BOOL inherit
, ACCESS_MASK access
)
153 DWORD len
= name
? strlenW(name
) : 0;
156 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
159 SERVER_START_REQ( open_winstation
)
161 req
->access
= access
;
162 req
->attributes
= OBJ_CASE_INSENSITIVE
| (inherit
? OBJ_INHERIT
: 0);
163 req
->rootdir
= wine_server_obj_handle( get_winstations_dir_handle() );
164 wine_server_add_data( req
, name
, len
* sizeof(WCHAR
) );
165 if (!wine_server_call_err( req
)) ret
= wine_server_ptr_handle( reply
->handle
);
172 /***********************************************************************
173 * CloseWindowStation (USER32.@)
175 BOOL WINAPI
CloseWindowStation( HWINSTA handle
)
178 SERVER_START_REQ( close_winstation
)
180 req
->handle
= wine_server_obj_handle( handle
);
181 ret
= !wine_server_call_err( req
);
188 /******************************************************************************
189 * GetProcessWindowStation (USER32.@)
191 HWINSTA WINAPI
GetProcessWindowStation(void)
195 SERVER_START_REQ( get_process_winstation
)
197 if (!wine_server_call_err( req
))
198 ret
= wine_server_ptr_handle( reply
->handle
);
205 /***********************************************************************
206 * SetProcessWindowStation (USER32.@)
208 BOOL WINAPI
SetProcessWindowStation( HWINSTA handle
)
212 SERVER_START_REQ( set_process_winstation
)
214 req
->handle
= wine_server_obj_handle( handle
);
215 ret
= !wine_server_call_err( req
);
222 /******************************************************************************
223 * EnumWindowStationsA (USER32.@)
225 BOOL WINAPI
EnumWindowStationsA( WINSTAENUMPROCA func
, LPARAM lparam
)
227 struct enum_proc_lparam data
;
229 data
.lparam
= lparam
;
230 return EnumWindowStationsW( enum_names_WtoA
, (LPARAM
)&data
);
234 /******************************************************************************
235 * EnumWindowStationsW (USER32.@)
237 BOOL WINAPI
EnumWindowStationsW( WINSTAENUMPROCW func
, LPARAM lparam
)
239 unsigned int index
= 0;
240 WCHAR name
[MAX_PATH
];
246 SERVER_START_REQ( enum_winstation
)
249 wine_server_set_reply( req
, name
, sizeof(name
) - sizeof(WCHAR
) );
250 status
= wine_server_call( req
);
251 name
[wine_server_reply_size(reply
)/sizeof(WCHAR
)] = 0;
255 if (status
== STATUS_NO_MORE_ENTRIES
)
259 SetLastError( RtlNtStatusToDosError( status
) );
262 ret
= func( name
, lparam
);
268 /***********************************************************************
269 * CreateDesktopA (USER32.@)
271 HDESK WINAPI
CreateDesktopA( LPCSTR name
, LPCSTR device
, LPDEVMODEA devmode
,
272 DWORD flags
, ACCESS_MASK access
, LPSECURITY_ATTRIBUTES sa
)
274 WCHAR buffer
[MAX_PATH
];
276 if (device
|| devmode
)
278 SetLastError( ERROR_INVALID_PARAMETER
);
281 if (!name
) return CreateDesktopW( NULL
, NULL
, NULL
, flags
, access
, sa
);
283 if (!MultiByteToWideChar( CP_ACP
, 0, name
, -1, buffer
, MAX_PATH
))
285 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
288 return CreateDesktopW( buffer
, NULL
, NULL
, flags
, access
, sa
);
292 /***********************************************************************
293 * CreateDesktopW (USER32.@)
295 HDESK WINAPI
CreateDesktopW( LPCWSTR name
, LPCWSTR device
, LPDEVMODEW devmode
,
296 DWORD flags
, ACCESS_MASK access
, LPSECURITY_ATTRIBUTES sa
)
299 DWORD len
= name
? strlenW(name
) : 0;
301 if (device
|| devmode
)
303 SetLastError( ERROR_INVALID_PARAMETER
);
308 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
311 SERVER_START_REQ( create_desktop
)
314 req
->access
= access
;
315 req
->attributes
= OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
|
316 ((sa
&& sa
->bInheritHandle
) ? OBJ_INHERIT
: 0);
317 wine_server_add_data( req
, name
, len
* sizeof(WCHAR
) );
318 wine_server_call_err( req
);
319 ret
= wine_server_ptr_handle( reply
->handle
);
326 /******************************************************************************
327 * OpenDesktopA (USER32.@)
329 HDESK WINAPI
OpenDesktopA( LPCSTR name
, DWORD flags
, BOOL inherit
, ACCESS_MASK access
)
331 WCHAR buffer
[MAX_PATH
];
333 if (!name
) return OpenDesktopW( NULL
, flags
, inherit
, access
);
335 if (!MultiByteToWideChar( CP_ACP
, 0, name
, -1, buffer
, MAX_PATH
))
337 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
340 return OpenDesktopW( buffer
, flags
, inherit
, access
);
344 HDESK
open_winstation_desktop( HWINSTA hwinsta
, LPCWSTR name
, DWORD flags
, BOOL inherit
, ACCESS_MASK access
)
347 DWORD len
= name
? strlenW(name
) : 0;
350 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
353 SERVER_START_REQ( open_desktop
)
355 req
->winsta
= wine_server_obj_handle( hwinsta
);
357 req
->access
= access
;
358 req
->attributes
= OBJ_CASE_INSENSITIVE
| (inherit
? OBJ_INHERIT
: 0);
359 wine_server_add_data( req
, name
, len
* sizeof(WCHAR
) );
360 if (!wine_server_call_err( req
)) ret
= wine_server_ptr_handle( reply
->handle
);
367 /******************************************************************************
368 * OpenDesktopW (USER32.@)
370 HDESK WINAPI
OpenDesktopW( LPCWSTR name
, DWORD flags
, BOOL inherit
, ACCESS_MASK access
)
372 return open_winstation_desktop( NULL
, name
, flags
, inherit
, access
);
376 /***********************************************************************
377 * CloseDesktop (USER32.@)
379 BOOL WINAPI
CloseDesktop( HDESK handle
)
382 SERVER_START_REQ( close_desktop
)
384 req
->handle
= wine_server_obj_handle( handle
);
385 ret
= !wine_server_call_err( req
);
392 /******************************************************************************
393 * GetThreadDesktop (USER32.@)
395 HDESK WINAPI
GetThreadDesktop( DWORD thread
)
399 SERVER_START_REQ( get_thread_desktop
)
402 if (!wine_server_call_err( req
)) ret
= wine_server_ptr_handle( reply
->handle
);
409 /******************************************************************************
410 * SetThreadDesktop (USER32.@)
412 BOOL WINAPI
SetThreadDesktop( HDESK handle
)
416 SERVER_START_REQ( set_thread_desktop
)
418 req
->handle
= wine_server_obj_handle( handle
);
419 ret
= !wine_server_call_err( req
);
422 if (ret
) /* reset the desktop windows */
424 struct user_thread_info
*thread_info
= get_user_thread_info();
425 struct user_key_state_info
*key_state_info
= thread_info
->key_state
;
426 thread_info
->top_window
= 0;
427 thread_info
->msg_window
= 0;
428 if (key_state_info
) key_state_info
->time
= 0;
434 /******************************************************************************
435 * EnumDesktopsA (USER32.@)
437 BOOL WINAPI
EnumDesktopsA( HWINSTA winsta
, DESKTOPENUMPROCA func
, LPARAM lparam
)
439 struct enum_proc_lparam data
;
441 data
.lparam
= lparam
;
442 return EnumDesktopsW( winsta
, enum_names_WtoA
, (LPARAM
)&data
);
446 /******************************************************************************
447 * EnumDesktopsW (USER32.@)
449 BOOL WINAPI
EnumDesktopsW( HWINSTA winsta
, DESKTOPENUMPROCW func
, LPARAM lparam
)
451 unsigned int index
= 0;
452 WCHAR name
[MAX_PATH
];
457 winsta
= GetProcessWindowStation();
461 SERVER_START_REQ( enum_desktop
)
463 req
->winstation
= wine_server_obj_handle( winsta
);
465 wine_server_set_reply( req
, name
, sizeof(name
) - sizeof(WCHAR
) );
466 status
= wine_server_call( req
);
467 name
[wine_server_reply_size(reply
)/sizeof(WCHAR
)] = 0;
471 if (status
== STATUS_NO_MORE_ENTRIES
)
475 SetLastError( RtlNtStatusToDosError( status
) );
478 ret
= func(name
, lparam
);
484 /******************************************************************************
485 * OpenInputDesktop (USER32.@)
487 HDESK WINAPI
OpenInputDesktop( DWORD flags
, BOOL inherit
, ACCESS_MASK access
)
491 TRACE( "(%x,%i,%x)\n", flags
, inherit
, access
);
494 FIXME( "partial stub flags %08x\n", flags
);
496 SERVER_START_REQ( open_input_desktop
)
499 req
->access
= access
;
500 req
->attributes
= inherit
? OBJ_INHERIT
: 0;
501 if (!wine_server_call_err( req
)) ret
= wine_server_ptr_handle( reply
->handle
);
509 /***********************************************************************
510 * GetUserObjectInformationA (USER32.@)
512 BOOL WINAPI
GetUserObjectInformationA( HANDLE handle
, INT index
, LPVOID info
, DWORD len
, LPDWORD needed
)
514 /* check for information types returning strings */
515 if (index
== UOI_TYPE
|| index
== UOI_NAME
)
517 WCHAR buffer
[MAX_PATH
];
520 if (!GetUserObjectInformationW( handle
, index
, buffer
, sizeof(buffer
), &lenW
)) return FALSE
;
521 lenA
= WideCharToMultiByte( CP_ACP
, 0, buffer
, -1, NULL
, 0, NULL
, NULL
);
522 if (needed
) *needed
= lenA
;
525 /* If the buffer length supplied by the caller is insufficient, Windows returns a
526 'needed' length based upon the Unicode byte length, so we should do similarly. */
527 if (needed
) *needed
= lenW
;
529 SetLastError( ERROR_INSUFFICIENT_BUFFER
);
532 if (info
) WideCharToMultiByte( CP_ACP
, 0, buffer
, -1, info
, len
, NULL
, NULL
);
535 return GetUserObjectInformationW( handle
, index
, info
, len
, needed
);
539 /***********************************************************************
540 * GetUserObjectInformationW (USER32.@)
542 BOOL WINAPI
GetUserObjectInformationW( HANDLE handle
, INT index
, LPVOID info
, DWORD len
, LPDWORD needed
)
544 static const WCHAR desktopW
[] = { 'D','e','s','k','t','o','p',0 };
545 static const WCHAR winstationW
[] = { 'W','i','n','d','o','w','S','t','a','t','i','o','n',0 };
552 USEROBJECTFLAGS
*obj_flags
= info
;
553 if (needed
) *needed
= sizeof(*obj_flags
);
554 if (len
< sizeof(*obj_flags
))
556 SetLastError( ERROR_BUFFER_OVERFLOW
);
559 SERVER_START_REQ( set_user_object_info
)
561 req
->handle
= wine_server_obj_handle( handle
);
563 ret
= !wine_server_call_err( req
);
566 /* FIXME: inherit flag */
567 obj_flags
->dwFlags
= reply
->old_obj_flags
;
575 SERVER_START_REQ( set_user_object_info
)
577 req
->handle
= wine_server_obj_handle( handle
);
579 ret
= !wine_server_call_err( req
);
582 size_t size
= reply
->is_desktop
? sizeof(desktopW
) : sizeof(winstationW
);
583 if (needed
) *needed
= size
;
586 SetLastError( ERROR_INSUFFICIENT_BUFFER
);
589 else memcpy( info
, reply
->is_desktop
? desktopW
: winstationW
, size
);
597 WCHAR buffer
[MAX_PATH
];
598 SERVER_START_REQ( set_user_object_info
)
600 req
->handle
= wine_server_obj_handle( handle
);
602 wine_server_set_reply( req
, buffer
, sizeof(buffer
) - sizeof(WCHAR
) );
603 ret
= !wine_server_call_err( req
);
606 size_t size
= wine_server_reply_size( reply
);
607 buffer
[size
/ sizeof(WCHAR
)] = 0;
608 size
+= sizeof(WCHAR
);
609 if (needed
) *needed
= size
;
612 SetLastError( ERROR_INSUFFICIENT_BUFFER
);
615 else memcpy( info
, buffer
, size
);
623 FIXME( "not supported index %d\n", index
);
626 SetLastError( ERROR_INVALID_PARAMETER
);
632 /******************************************************************************
633 * SetUserObjectInformationA (USER32.@)
635 BOOL WINAPI
SetUserObjectInformationA( HANDLE handle
, INT index
, LPVOID info
, DWORD len
)
637 return SetUserObjectInformationW( handle
, index
, info
, len
);
641 /******************************************************************************
642 * SetUserObjectInformationW (USER32.@)
644 BOOL WINAPI
SetUserObjectInformationW( HANDLE handle
, INT index
, LPVOID info
, DWORD len
)
647 const USEROBJECTFLAGS
*obj_flags
= info
;
649 if (index
!= UOI_FLAGS
|| !info
|| len
< sizeof(*obj_flags
))
651 SetLastError( ERROR_INVALID_PARAMETER
);
654 /* FIXME: inherit flag */
655 SERVER_START_REQ( set_user_object_info
)
657 req
->handle
= wine_server_obj_handle( handle
);
658 req
->flags
= SET_USER_OBJECT_SET_FLAGS
;
659 req
->obj_flags
= obj_flags
->dwFlags
;
660 ret
= !wine_server_call_err( req
);
667 /***********************************************************************
668 * GetUserObjectSecurity (USER32.@)
670 BOOL WINAPI
GetUserObjectSecurity( HANDLE handle
, PSECURITY_INFORMATION info
,
671 PSECURITY_DESCRIPTOR sid
, DWORD len
, LPDWORD needed
)
673 FIXME( "(%p %p %p len=%d %p),stub!\n", handle
, info
, sid
, len
, needed
);
675 *needed
= sizeof(SECURITY_DESCRIPTOR
);
676 if (len
< sizeof(SECURITY_DESCRIPTOR
))
678 SetLastError( ERROR_INSUFFICIENT_BUFFER
);
681 return InitializeSecurityDescriptor(sid
, SECURITY_DESCRIPTOR_REVISION
);
684 /***********************************************************************
685 * SetUserObjectSecurity (USER32.@)
687 BOOL WINAPI
SetUserObjectSecurity( HANDLE handle
, PSECURITY_INFORMATION info
,
688 PSECURITY_DESCRIPTOR sid
)
690 FIXME( "(%p,%p,%p),stub!\n", handle
, info
, sid
);