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
31 #include "wine/server.h"
32 #include "wine/unicode.h"
33 #include "wine/debug.h"
34 #include "user_private.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(winstation);
39 /* callback for enumeration functions */
40 struct enum_proc_lparam
46 static BOOL CALLBACK enum_names_WtoA( LPWSTR name, LPARAM lparam )
48 struct enum_proc_lparam *data = (struct enum_proc_lparam *)lparam;
49 char buffer[MAX_PATH];
51 if (!WideCharToMultiByte( CP_ACP, 0, name, -1, buffer, sizeof(buffer), NULL, NULL ))
53 return data->func( buffer, data->lparam );
57 /***********************************************************************
58 * CreateWindowStationA (USER32.@)
60 HWINSTA WINAPI CreateWindowStationA( LPCSTR name, DWORD reserved, ACCESS_MASK access,
61 LPSECURITY_ATTRIBUTES sa )
63 WCHAR buffer[MAX_PATH];
65 if (!name) return CreateWindowStationW( NULL, reserved, access, sa );
67 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
69 SetLastError( ERROR_FILENAME_EXCED_RANGE );
72 return CreateWindowStationW( buffer, reserved, access, sa );
76 /***********************************************************************
77 * CreateWindowStationW (USER32.@)
79 HWINSTA WINAPI CreateWindowStationW( LPCWSTR name, DWORD reserved, ACCESS_MASK access,
80 LPSECURITY_ATTRIBUTES sa )
83 DWORD len = name ? strlenW(name) : 0;
87 SetLastError( ERROR_FILENAME_EXCED_RANGE );
90 SERVER_START_REQ( create_winstation )
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 );
106 /******************************************************************************
107 * OpenWindowStationA (USER32.@)
109 HWINSTA WINAPI OpenWindowStationA( LPCSTR name, BOOL inherit, ACCESS_MASK access )
111 WCHAR buffer[MAX_PATH];
113 if (!name) return OpenWindowStationW( NULL, inherit, access );
115 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
117 SetLastError( ERROR_FILENAME_EXCED_RANGE );
120 return OpenWindowStationW( buffer, inherit, access );
124 /******************************************************************************
125 * OpenWindowStationW (USER32.@)
127 HWINSTA WINAPI OpenWindowStationW( LPCWSTR name, BOOL inherit, ACCESS_MASK access )
130 DWORD len = name ? strlenW(name) : 0;
133 SetLastError( ERROR_FILENAME_EXCED_RANGE );
136 SERVER_START_REQ( open_winstation )
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 );
148 /***********************************************************************
149 * CloseWindowStation (USER32.@)
151 BOOL WINAPI CloseWindowStation( HWINSTA handle )
154 SERVER_START_REQ( close_winstation )
156 req->handle = wine_server_obj_handle( handle );
157 ret = !wine_server_call_err( req );
164 /******************************************************************************
165 * GetProcessWindowStation (USER32.@)
167 HWINSTA WINAPI GetProcessWindowStation(void)
171 SERVER_START_REQ( get_process_winstation )
173 if (!wine_server_call_err( req ))
174 ret = wine_server_ptr_handle( reply->handle );
181 /***********************************************************************
182 * SetProcessWindowStation (USER32.@)
184 BOOL WINAPI SetProcessWindowStation( HWINSTA handle )
188 SERVER_START_REQ( set_process_winstation )
190 req->handle = wine_server_obj_handle( handle );
191 ret = !wine_server_call_err( req );
198 /******************************************************************************
199 * EnumWindowStationsA (USER32.@)
201 BOOL WINAPI EnumWindowStationsA( WINSTAENUMPROCA func, LPARAM lparam )
203 struct enum_proc_lparam data;
205 data.lparam = lparam;
206 return EnumWindowStationsW( enum_names_WtoA, (LPARAM)&data );
210 /******************************************************************************
211 * EnumWindowStationsW (USER32.@)
213 BOOL WINAPI EnumWindowStationsW( WINSTAENUMPROCW func, LPARAM lparam )
215 unsigned int index = 0;
216 WCHAR name[MAX_PATH];
222 SERVER_START_REQ( enum_winstation )
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;
231 if (status == STATUS_NO_MORE_ENTRIES)
235 SetLastError( RtlNtStatusToDosError( status ) );
238 ret = func( name, lparam );
244 /***********************************************************************
245 * CreateDesktopA (USER32.@)
247 HDESK WINAPI CreateDesktopA( LPCSTR name, LPCSTR device, LPDEVMODEA devmode,
248 DWORD flags, ACCESS_MASK access, LPSECURITY_ATTRIBUTES sa )
250 WCHAR buffer[MAX_PATH];
252 if (device || devmode)
254 SetLastError( ERROR_INVALID_PARAMETER );
257 if (!name) return CreateDesktopW( NULL, NULL, NULL, flags, access, sa );
259 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
261 SetLastError( ERROR_FILENAME_EXCED_RANGE );
264 return CreateDesktopW( buffer, NULL, NULL, flags, access, sa );
268 /***********************************************************************
269 * CreateDesktopW (USER32.@)
271 HDESK WINAPI CreateDesktopW( LPCWSTR name, LPCWSTR device, LPDEVMODEW devmode,
272 DWORD flags, ACCESS_MASK access, LPSECURITY_ATTRIBUTES sa )
275 DWORD len = name ? strlenW(name) : 0;
277 if (device || devmode)
279 SetLastError( ERROR_INVALID_PARAMETER );
284 SetLastError( ERROR_FILENAME_EXCED_RANGE );
287 SERVER_START_REQ( create_desktop )
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 );
303 /******************************************************************************
304 * OpenDesktopA (USER32.@)
306 HDESK WINAPI OpenDesktopA( LPCSTR name, DWORD flags, BOOL inherit, ACCESS_MASK access )
308 WCHAR buffer[MAX_PATH];
310 if (!name) return OpenDesktopW( NULL, flags, inherit, access );
312 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
314 SetLastError( ERROR_FILENAME_EXCED_RANGE );
317 return OpenDesktopW( buffer, flags, inherit, access );
321 HDESK open_winstation_desktop( HWINSTA hwinsta, LPCWSTR name, DWORD flags, BOOL inherit, ACCESS_MASK access )
324 DWORD len = name ? strlenW(name) : 0;
327 SetLastError( ERROR_FILENAME_EXCED_RANGE );
330 SERVER_START_REQ( open_desktop )
332 req->winsta = wine_server_obj_handle( hwinsta );
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 );
344 /******************************************************************************
345 * OpenDesktopW (USER32.@)
347 HDESK WINAPI OpenDesktopW( LPCWSTR name, DWORD flags, BOOL inherit, ACCESS_MASK access )
349 return open_winstation_desktop( NULL, name, flags, inherit, access );
353 /***********************************************************************
354 * CloseDesktop (USER32.@)
356 BOOL WINAPI CloseDesktop( HDESK handle )
359 SERVER_START_REQ( close_desktop )
361 req->handle = wine_server_obj_handle( handle );
362 ret = !wine_server_call_err( req );
369 /******************************************************************************
370 * GetThreadDesktop (USER32.@)
372 HDESK WINAPI GetThreadDesktop( DWORD thread )
376 SERVER_START_REQ( get_thread_desktop )
379 if (!wine_server_call_err( req )) ret = wine_server_ptr_handle( reply->handle );
386 /******************************************************************************
387 * SetThreadDesktop (USER32.@)
389 BOOL WINAPI SetThreadDesktop( HDESK handle )
393 SERVER_START_REQ( set_thread_desktop )
395 req->handle = wine_server_obj_handle( handle );
396 ret = !wine_server_call_err( req );
399 if (ret) /* reset the desktop windows */
401 struct user_thread_info *thread_info = get_user_thread_info();
402 thread_info->top_window = 0;
403 thread_info->msg_window = 0;
404 thread_info->key_state_time = 0;
410 /******************************************************************************
411 * EnumDesktopsA (USER32.@)
413 BOOL WINAPI EnumDesktopsA( HWINSTA winsta, DESKTOPENUMPROCA func, LPARAM lparam )
415 struct enum_proc_lparam data;
417 data.lparam = lparam;
418 return EnumDesktopsW( winsta, enum_names_WtoA, (LPARAM)&data );
422 /******************************************************************************
423 * EnumDesktopsW (USER32.@)
425 BOOL WINAPI EnumDesktopsW( HWINSTA winsta, DESKTOPENUMPROCW func, LPARAM lparam )
427 unsigned int index = 0;
428 WCHAR name[MAX_PATH];
433 winsta = GetProcessWindowStation();
437 SERVER_START_REQ( enum_desktop )
439 req->winstation = wine_server_obj_handle( winsta );
441 wine_server_set_reply( req, name, sizeof(name) - sizeof(WCHAR) );
442 status = wine_server_call( req );
443 name[wine_server_reply_size(reply)/sizeof(WCHAR)] = 0;
447 if (status == STATUS_NO_MORE_ENTRIES)
451 SetLastError( RtlNtStatusToDosError( status ) );
454 ret = func(name, lparam);
460 /******************************************************************************
461 * OpenInputDesktop (USER32.@)
463 HDESK WINAPI OpenInputDesktop( DWORD flags, BOOL inherit, ACCESS_MASK access )
465 FIXME( "(%x,%i,%x): stub\n", flags, inherit, access );
466 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
471 /***********************************************************************
472 * GetUserObjectInformationA (USER32.@)
474 BOOL WINAPI GetUserObjectInformationA( HANDLE handle, INT index, LPVOID info, DWORD len, LPDWORD needed )
476 /* check for information types returning strings */
477 if (index == UOI_TYPE || index == UOI_NAME)
479 WCHAR buffer[MAX_PATH];
482 if (!GetUserObjectInformationW( handle, index, buffer, sizeof(buffer), &lenW )) return FALSE;
483 lenA = WideCharToMultiByte( CP_ACP, 0, buffer, -1, NULL, 0, NULL, NULL );
484 if (needed) *needed = lenA;
487 /* If the buffer length supplied by the caller is insufficient, Windows returns a
488 'needed' length based upon the Unicode byte length, so we should do similarly. */
489 if (needed) *needed = lenW;
491 SetLastError( ERROR_INSUFFICIENT_BUFFER );
494 if (info) WideCharToMultiByte( CP_ACP, 0, buffer, -1, info, len, NULL, NULL );
497 return GetUserObjectInformationW( handle, index, info, len, needed );
501 /***********************************************************************
502 * GetUserObjectInformationW (USER32.@)
504 BOOL WINAPI GetUserObjectInformationW( HANDLE handle, INT index, LPVOID info, DWORD len, LPDWORD needed )
506 static const WCHAR desktopW[] = { 'D','e','s','k','t','o','p',0 };
507 static const WCHAR winstationW[] = { 'W','i','n','d','o','w','S','t','a','t','i','o','n',0 };
514 USEROBJECTFLAGS *obj_flags = info;
515 if (needed) *needed = sizeof(*obj_flags);
516 if (len < sizeof(*obj_flags))
518 SetLastError( ERROR_BUFFER_OVERFLOW );
521 SERVER_START_REQ( set_user_object_info )
523 req->handle = wine_server_obj_handle( handle );
525 ret = !wine_server_call_err( req );
528 /* FIXME: inherit flag */
529 obj_flags->dwFlags = reply->old_obj_flags;
537 SERVER_START_REQ( set_user_object_info )
539 req->handle = wine_server_obj_handle( handle );
541 ret = !wine_server_call_err( req );
544 size_t size = reply->is_desktop ? sizeof(desktopW) : sizeof(winstationW);
545 if (needed) *needed = size;
548 SetLastError( ERROR_INSUFFICIENT_BUFFER );
551 else memcpy( info, reply->is_desktop ? desktopW : winstationW, size );
559 WCHAR buffer[MAX_PATH];
560 SERVER_START_REQ( set_user_object_info )
562 req->handle = wine_server_obj_handle( handle );
564 wine_server_set_reply( req, buffer, sizeof(buffer) - sizeof(WCHAR) );
565 ret = !wine_server_call_err( req );
568 size_t size = wine_server_reply_size( reply );
569 buffer[size / sizeof(WCHAR)] = 0;
570 size += sizeof(WCHAR);
571 if (needed) *needed = size;
574 SetLastError( ERROR_INSUFFICIENT_BUFFER );
577 else memcpy( info, buffer, size );
585 FIXME( "not supported index %d\n", index );
588 SetLastError( ERROR_INVALID_PARAMETER );
594 /******************************************************************************
595 * SetUserObjectInformationA (USER32.@)
597 BOOL WINAPI SetUserObjectInformationA( HANDLE handle, INT index, LPVOID info, DWORD len )
599 return SetUserObjectInformationW( handle, index, info, len );
603 /******************************************************************************
604 * SetUserObjectInformationW (USER32.@)
606 BOOL WINAPI SetUserObjectInformationW( HANDLE handle, INT index, LPVOID info, DWORD len )
609 const USEROBJECTFLAGS *obj_flags = info;
611 if (index != UOI_FLAGS || !info || len < sizeof(*obj_flags))
613 SetLastError( ERROR_INVALID_PARAMETER );
616 /* FIXME: inherit flag */
617 SERVER_START_REQ( set_user_object_info )
619 req->handle = wine_server_obj_handle( handle );
620 req->flags = SET_USER_OBJECT_FLAGS;
621 req->obj_flags = obj_flags->dwFlags;
622 ret = !wine_server_call_err( req );
629 /***********************************************************************
630 * GetUserObjectSecurity (USER32.@)
632 BOOL WINAPI GetUserObjectSecurity( HANDLE handle, PSECURITY_INFORMATION info,
633 PSECURITY_DESCRIPTOR sid, DWORD len, LPDWORD needed )
635 FIXME( "(%p %p %p len=%d %p),stub!\n", handle, info, sid, len, needed );
637 *needed = sizeof(SECURITY_DESCRIPTOR);
638 if (len < sizeof(SECURITY_DESCRIPTOR))
640 SetLastError( ERROR_INSUFFICIENT_BUFFER );
643 return InitializeSecurityDescriptor(sid, SECURITY_DESCRIPTOR_REVISION);
646 /***********************************************************************
647 * SetUserObjectSecurity (USER32.@)
649 BOOL WINAPI SetUserObjectSecurity( HANDLE handle, PSECURITY_INFORMATION info,
650 PSECURITY_DESCRIPTOR sid )
652 FIXME( "(%p,%p,%p),stub!\n", handle, info, sid );