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
)
467 TRACE( "(%x,%i,%x)\n", flags
, inherit
, access
);
470 FIXME( "partial stub flags %08x\n", flags
);
472 SERVER_START_REQ( open_input_desktop
)
475 req
->access
= access
;
476 req
->attributes
= inherit
? OBJ_INHERIT
: 0;
477 if (!wine_server_call_err( req
)) ret
= wine_server_ptr_handle( reply
->handle
);
485 /***********************************************************************
486 * GetUserObjectInformationA (USER32.@)
488 BOOL WINAPI
GetUserObjectInformationA( HANDLE handle
, INT index
, LPVOID info
, DWORD len
, LPDWORD needed
)
490 /* check for information types returning strings */
491 if (index
== UOI_TYPE
|| index
== UOI_NAME
)
493 WCHAR buffer
[MAX_PATH
];
496 if (!GetUserObjectInformationW( handle
, index
, buffer
, sizeof(buffer
), &lenW
)) return FALSE
;
497 lenA
= WideCharToMultiByte( CP_ACP
, 0, buffer
, -1, NULL
, 0, NULL
, NULL
);
498 if (needed
) *needed
= lenA
;
501 /* If the buffer length supplied by the caller is insufficient, Windows returns a
502 'needed' length based upon the Unicode byte length, so we should do similarly. */
503 if (needed
) *needed
= lenW
;
505 SetLastError( ERROR_INSUFFICIENT_BUFFER
);
508 if (info
) WideCharToMultiByte( CP_ACP
, 0, buffer
, -1, info
, len
, NULL
, NULL
);
511 return GetUserObjectInformationW( handle
, index
, info
, len
, needed
);
515 /***********************************************************************
516 * GetUserObjectInformationW (USER32.@)
518 BOOL WINAPI
GetUserObjectInformationW( HANDLE handle
, INT index
, LPVOID info
, DWORD len
, LPDWORD needed
)
520 static const WCHAR desktopW
[] = { 'D','e','s','k','t','o','p',0 };
521 static const WCHAR winstationW
[] = { 'W','i','n','d','o','w','S','t','a','t','i','o','n',0 };
528 USEROBJECTFLAGS
*obj_flags
= info
;
529 if (needed
) *needed
= sizeof(*obj_flags
);
530 if (len
< sizeof(*obj_flags
))
532 SetLastError( ERROR_BUFFER_OVERFLOW
);
535 SERVER_START_REQ( set_user_object_info
)
537 req
->handle
= wine_server_obj_handle( handle
);
539 ret
= !wine_server_call_err( req
);
542 /* FIXME: inherit flag */
543 obj_flags
->dwFlags
= reply
->old_obj_flags
;
551 SERVER_START_REQ( set_user_object_info
)
553 req
->handle
= wine_server_obj_handle( handle
);
555 ret
= !wine_server_call_err( req
);
558 size_t size
= reply
->is_desktop
? sizeof(desktopW
) : sizeof(winstationW
);
559 if (needed
) *needed
= size
;
562 SetLastError( ERROR_INSUFFICIENT_BUFFER
);
565 else memcpy( info
, reply
->is_desktop
? desktopW
: winstationW
, size
);
573 WCHAR buffer
[MAX_PATH
];
574 SERVER_START_REQ( set_user_object_info
)
576 req
->handle
= wine_server_obj_handle( handle
);
578 wine_server_set_reply( req
, buffer
, sizeof(buffer
) - sizeof(WCHAR
) );
579 ret
= !wine_server_call_err( req
);
582 size_t size
= wine_server_reply_size( reply
);
583 buffer
[size
/ sizeof(WCHAR
)] = 0;
584 size
+= sizeof(WCHAR
);
585 if (needed
) *needed
= size
;
588 SetLastError( ERROR_INSUFFICIENT_BUFFER
);
591 else memcpy( info
, buffer
, size
);
599 FIXME( "not supported index %d\n", index
);
602 SetLastError( ERROR_INVALID_PARAMETER
);
608 /******************************************************************************
609 * SetUserObjectInformationA (USER32.@)
611 BOOL WINAPI
SetUserObjectInformationA( HANDLE handle
, INT index
, LPVOID info
, DWORD len
)
613 return SetUserObjectInformationW( handle
, index
, info
, len
);
617 /******************************************************************************
618 * SetUserObjectInformationW (USER32.@)
620 BOOL WINAPI
SetUserObjectInformationW( HANDLE handle
, INT index
, LPVOID info
, DWORD len
)
623 const USEROBJECTFLAGS
*obj_flags
= info
;
625 if (index
!= UOI_FLAGS
|| !info
|| len
< sizeof(*obj_flags
))
627 SetLastError( ERROR_INVALID_PARAMETER
);
630 /* FIXME: inherit flag */
631 SERVER_START_REQ( set_user_object_info
)
633 req
->handle
= wine_server_obj_handle( handle
);
634 req
->flags
= SET_USER_OBJECT_FLAGS
;
635 req
->obj_flags
= obj_flags
->dwFlags
;
636 ret
= !wine_server_call_err( req
);
643 /***********************************************************************
644 * GetUserObjectSecurity (USER32.@)
646 BOOL WINAPI
GetUserObjectSecurity( HANDLE handle
, PSECURITY_INFORMATION info
,
647 PSECURITY_DESCRIPTOR sid
, DWORD len
, LPDWORD needed
)
649 FIXME( "(%p %p %p len=%d %p),stub!\n", handle
, info
, sid
, len
, needed
);
651 *needed
= sizeof(SECURITY_DESCRIPTOR
);
652 if (len
< sizeof(SECURITY_DESCRIPTOR
))
654 SetLastError( ERROR_INSUFFICIENT_BUFFER
);
657 return InitializeSecurityDescriptor(sid
, SECURITY_DESCRIPTOR_REVISION
);
660 /***********************************************************************
661 * SetUserObjectSecurity (USER32.@)
663 BOOL WINAPI
SetUserObjectSecurity( HANDLE handle
, PSECURITY_INFORMATION info
,
664 PSECURITY_DESCRIPTOR sid
)
666 FIXME( "(%p,%p,%p),stub!\n", handle
, info
, sid
);