jscript: Add Map.prototype.forEach implementation.
[wine.git] / dlls / user32 / winstation.c
blob95a9eb8509991fc4e2b02f3f445d8c9b05fbb2a3
1 /*
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
21 #include "ntstatus.h"
22 #define WIN32_NO_STATUS
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 "winternl.h"
32 #include "ddk/wdm.h"
33 #include "wine/server.h"
34 #include "wine/debug.h"
35 #include "user_private.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(winstation);
40 /* callback for enumeration functions */
41 struct enum_proc_lparam
43 NAMEENUMPROCA func;
44 LPARAM lparam;
47 static BOOL CALLBACK enum_names_WtoA( LPWSTR name, LPARAM lparam )
49 struct enum_proc_lparam *data = (struct enum_proc_lparam *)lparam;
50 char buffer[MAX_PATH];
52 if (!WideCharToMultiByte( CP_ACP, 0, name, -1, buffer, sizeof(buffer), NULL, NULL ))
53 return FALSE;
54 return data->func( buffer, data->lparam );
57 /* return a handle to the directory where window station objects are created */
58 static HANDLE get_winstations_dir_handle(void)
60 static HANDLE handle = NULL;
61 WCHAR buffer[64];
62 UNICODE_STRING str;
63 OBJECT_ATTRIBUTES attr;
65 if (!handle)
67 HANDLE dir;
69 swprintf( buffer, ARRAY_SIZE(buffer), L"\\Sessions\\%u\\Windows\\WindowStations", NtCurrentTeb()->Peb->SessionId );
70 RtlInitUnicodeString( &str, buffer );
71 InitializeObjectAttributes( &attr, &str, 0, 0, NULL );
72 NtOpenDirectoryObject( &dir, DIRECTORY_CREATE_OBJECT | DIRECTORY_TRAVERSE, &attr );
73 if (InterlockedCompareExchangePointer( &handle, dir, 0 ) != 0) /* someone beat us here */
74 CloseHandle( dir );
76 return handle;
79 static WCHAR default_name[29];
81 static BOOL WINAPI winstation_default_name_once( INIT_ONCE *once, void *param, void **context )
83 TOKEN_STATISTICS stats;
84 BOOL ret;
86 ret = GetTokenInformation( GetCurrentProcessToken(), TokenStatistics, &stats, sizeof(stats), NULL );
87 if (ret)
88 swprintf( default_name, ARRAY_SIZE(default_name), L"Service-0x%x-%x$",
89 stats.AuthenticationId.HighPart, stats.AuthenticationId.LowPart );
91 return ret;
94 static const WCHAR *get_winstation_default_name( void )
96 static INIT_ONCE once = INIT_ONCE_STATIC_INIT;
97 BOOL ret;
99 ret = InitOnceExecuteOnce( &once, winstation_default_name_once, NULL, NULL );
100 return ret ? default_name : NULL;
103 /***********************************************************************
104 * CreateWindowStationA (USER32.@)
106 HWINSTA WINAPI CreateWindowStationA( LPCSTR name, DWORD flags, ACCESS_MASK access,
107 LPSECURITY_ATTRIBUTES sa )
109 WCHAR buffer[MAX_PATH];
111 if (!name) return CreateWindowStationW( NULL, flags, access, sa );
113 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
115 SetLastError( ERROR_FILENAME_EXCED_RANGE );
116 return 0;
118 return CreateWindowStationW( buffer, flags, access, sa );
122 /***********************************************************************
123 * CreateWindowStationW (USER32.@)
125 HWINSTA WINAPI CreateWindowStationW( LPCWSTR name, DWORD flags, ACCESS_MASK access,
126 LPSECURITY_ATTRIBUTES sa )
128 HANDLE ret;
129 DWORD len = name ? lstrlenW(name) : 0;
131 if (len >= MAX_PATH)
133 SetLastError( ERROR_FILENAME_EXCED_RANGE );
134 return 0;
136 if (!len)
138 name = get_winstation_default_name();
139 len = lstrlenW( name );
141 SERVER_START_REQ( create_winstation )
143 req->flags = 0;
144 req->access = access;
145 req->attributes = OBJ_CASE_INSENSITIVE |
146 ((flags & CWF_CREATE_ONLY) ? 0 : OBJ_OPENIF) |
147 ((sa && sa->bInheritHandle) ? OBJ_INHERIT : 0);
148 req->rootdir = wine_server_obj_handle( get_winstations_dir_handle() );
149 wine_server_add_data( req, name, len * sizeof(WCHAR) );
150 wine_server_call_err( req );
151 ret = wine_server_ptr_handle( reply->handle );
153 SERVER_END_REQ;
154 return ret;
158 /******************************************************************************
159 * OpenWindowStationA (USER32.@)
161 HWINSTA WINAPI OpenWindowStationA( LPCSTR name, BOOL inherit, ACCESS_MASK access )
163 WCHAR buffer[MAX_PATH];
165 if (!name) return OpenWindowStationW( NULL, inherit, access );
167 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
169 SetLastError( ERROR_FILENAME_EXCED_RANGE );
170 return 0;
172 return OpenWindowStationW( buffer, inherit, access );
176 /******************************************************************************
177 * OpenWindowStationW (USER32.@)
179 HWINSTA WINAPI OpenWindowStationW( LPCWSTR name, BOOL inherit, ACCESS_MASK access )
181 HANDLE ret = 0;
182 DWORD len = name ? lstrlenW(name) : 0;
183 if (len >= MAX_PATH)
185 SetLastError( ERROR_FILENAME_EXCED_RANGE );
186 return 0;
188 if (!len)
190 name = get_winstation_default_name();
191 len = lstrlenW( name );
193 SERVER_START_REQ( open_winstation )
195 req->access = access;
196 req->attributes = OBJ_CASE_INSENSITIVE | (inherit ? OBJ_INHERIT : 0);
197 req->rootdir = wine_server_obj_handle( get_winstations_dir_handle() );
198 wine_server_add_data( req, name, len * sizeof(WCHAR) );
199 if (!wine_server_call_err( req )) ret = wine_server_ptr_handle( reply->handle );
201 SERVER_END_REQ;
202 return ret;
206 /***********************************************************************
207 * CloseWindowStation (USER32.@)
209 BOOL WINAPI CloseWindowStation( HWINSTA handle )
211 BOOL ret;
212 SERVER_START_REQ( close_winstation )
214 req->handle = wine_server_obj_handle( handle );
215 ret = !wine_server_call_err( req );
217 SERVER_END_REQ;
218 return ret;
222 /******************************************************************************
223 * GetProcessWindowStation (USER32.@)
225 HWINSTA WINAPI GetProcessWindowStation(void)
227 HWINSTA ret = 0;
229 SERVER_START_REQ( get_process_winstation )
231 if (!wine_server_call_err( req ))
232 ret = wine_server_ptr_handle( reply->handle );
234 SERVER_END_REQ;
235 return ret;
239 /***********************************************************************
240 * SetProcessWindowStation (USER32.@)
242 BOOL WINAPI SetProcessWindowStation( HWINSTA handle )
244 BOOL ret;
246 SERVER_START_REQ( set_process_winstation )
248 req->handle = wine_server_obj_handle( handle );
249 ret = !wine_server_call_err( req );
251 SERVER_END_REQ;
252 return ret;
256 /******************************************************************************
257 * EnumWindowStationsA (USER32.@)
259 BOOL WINAPI EnumWindowStationsA( WINSTAENUMPROCA func, LPARAM lparam )
261 struct enum_proc_lparam data;
262 data.func = func;
263 data.lparam = lparam;
264 return EnumWindowStationsW( enum_names_WtoA, (LPARAM)&data );
268 /******************************************************************************
269 * EnumWindowStationsW (USER32.@)
271 BOOL WINAPI EnumWindowStationsW( WINSTAENUMPROCW func, LPARAM lparam )
273 unsigned int index = 0;
274 WCHAR name[MAX_PATH];
275 BOOL ret = TRUE;
276 NTSTATUS status;
278 while (ret)
280 SERVER_START_REQ( enum_winstation )
282 req->index = index;
283 wine_server_set_reply( req, name, sizeof(name) - sizeof(WCHAR) );
284 status = wine_server_call( req );
285 name[wine_server_reply_size(reply)/sizeof(WCHAR)] = 0;
286 index = reply->next;
288 SERVER_END_REQ;
289 if (status == STATUS_NO_MORE_ENTRIES)
290 break;
291 if (status)
293 SetLastError( RtlNtStatusToDosError( status ) );
294 return FALSE;
296 ret = func( name, lparam );
298 return ret;
302 /***********************************************************************
303 * CreateDesktopA (USER32.@)
305 HDESK WINAPI CreateDesktopA( LPCSTR name, LPCSTR device, LPDEVMODEA devmode,
306 DWORD flags, ACCESS_MASK access, LPSECURITY_ATTRIBUTES sa )
308 WCHAR buffer[MAX_PATH];
310 if (device || devmode)
312 SetLastError( ERROR_INVALID_PARAMETER );
313 return 0;
315 if (!name) return CreateDesktopW( NULL, NULL, NULL, flags, access, sa );
317 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
319 SetLastError( ERROR_FILENAME_EXCED_RANGE );
320 return 0;
322 return CreateDesktopW( buffer, NULL, NULL, flags, access, sa );
326 /***********************************************************************
327 * CreateDesktopW (USER32.@)
329 HDESK WINAPI CreateDesktopW( LPCWSTR name, LPCWSTR device, LPDEVMODEW devmode,
330 DWORD flags, ACCESS_MASK access, LPSECURITY_ATTRIBUTES sa )
332 HANDLE ret;
333 DWORD len = name ? lstrlenW(name) : 0;
335 if (device || devmode)
337 SetLastError( ERROR_INVALID_PARAMETER );
338 return 0;
340 if (len >= MAX_PATH)
342 SetLastError( ERROR_FILENAME_EXCED_RANGE );
343 return 0;
345 SERVER_START_REQ( create_desktop )
347 req->flags = flags;
348 req->access = access;
349 req->attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF |
350 ((sa && sa->bInheritHandle) ? OBJ_INHERIT : 0);
351 wine_server_add_data( req, name, len * sizeof(WCHAR) );
352 wine_server_call_err( req );
353 ret = wine_server_ptr_handle( reply->handle );
355 SERVER_END_REQ;
356 return ret;
360 /******************************************************************************
361 * OpenDesktopA (USER32.@)
363 HDESK WINAPI OpenDesktopA( LPCSTR name, DWORD flags, BOOL inherit, ACCESS_MASK access )
365 WCHAR buffer[MAX_PATH];
367 if (!name) return OpenDesktopW( NULL, flags, inherit, access );
369 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
371 SetLastError( ERROR_FILENAME_EXCED_RANGE );
372 return 0;
374 return OpenDesktopW( buffer, flags, inherit, access );
378 HDESK open_winstation_desktop( HWINSTA hwinsta, LPCWSTR name, DWORD flags, BOOL inherit, ACCESS_MASK access )
380 HANDLE ret = 0;
381 DWORD len = name ? lstrlenW(name) : 0;
382 if (len >= MAX_PATH)
384 SetLastError( ERROR_FILENAME_EXCED_RANGE );
385 return 0;
387 SERVER_START_REQ( open_desktop )
389 req->winsta = wine_server_obj_handle( hwinsta );
390 req->flags = flags;
391 req->access = access;
392 req->attributes = OBJ_CASE_INSENSITIVE | (inherit ? OBJ_INHERIT : 0);
393 wine_server_add_data( req, name, len * sizeof(WCHAR) );
394 if (!wine_server_call_err( req )) ret = wine_server_ptr_handle( reply->handle );
396 SERVER_END_REQ;
397 return ret;
401 /******************************************************************************
402 * OpenDesktopW (USER32.@)
404 HDESK WINAPI OpenDesktopW( LPCWSTR name, DWORD flags, BOOL inherit, ACCESS_MASK access )
406 return open_winstation_desktop( NULL, name, flags, inherit, access );
410 /***********************************************************************
411 * CloseDesktop (USER32.@)
413 BOOL WINAPI CloseDesktop( HDESK handle )
415 BOOL ret;
416 SERVER_START_REQ( close_desktop )
418 req->handle = wine_server_obj_handle( handle );
419 ret = !wine_server_call_err( req );
421 SERVER_END_REQ;
422 return ret;
426 /******************************************************************************
427 * GetThreadDesktop (USER32.@)
429 HDESK WINAPI GetThreadDesktop( DWORD thread )
431 HDESK ret = 0;
433 SERVER_START_REQ( get_thread_desktop )
435 req->tid = thread;
436 if (!wine_server_call_err( req )) ret = wine_server_ptr_handle( reply->handle );
438 SERVER_END_REQ;
439 return ret;
443 /******************************************************************************
444 * SetThreadDesktop (USER32.@)
446 BOOL WINAPI SetThreadDesktop( HDESK handle )
448 BOOL ret;
450 SERVER_START_REQ( set_thread_desktop )
452 req->handle = wine_server_obj_handle( handle );
453 ret = !wine_server_call_err( req );
455 SERVER_END_REQ;
456 if (ret) /* reset the desktop windows */
458 struct user_thread_info *thread_info = get_user_thread_info();
459 struct user_key_state_info *key_state_info = thread_info->key_state;
460 thread_info->top_window = 0;
461 thread_info->msg_window = 0;
462 if (key_state_info) key_state_info->time = 0;
464 return ret;
468 /******************************************************************************
469 * EnumDesktopsA (USER32.@)
471 BOOL WINAPI EnumDesktopsA( HWINSTA winsta, DESKTOPENUMPROCA func, LPARAM lparam )
473 struct enum_proc_lparam data;
474 data.func = func;
475 data.lparam = lparam;
476 return EnumDesktopsW( winsta, enum_names_WtoA, (LPARAM)&data );
480 /******************************************************************************
481 * EnumDesktopsW (USER32.@)
483 BOOL WINAPI EnumDesktopsW( HWINSTA winsta, DESKTOPENUMPROCW func, LPARAM lparam )
485 unsigned int index = 0;
486 WCHAR name[MAX_PATH];
487 BOOL ret = TRUE;
488 NTSTATUS status;
490 if (!winsta)
491 winsta = GetProcessWindowStation();
493 while (ret)
495 SERVER_START_REQ( enum_desktop )
497 req->winstation = wine_server_obj_handle( winsta );
498 req->index = index;
499 wine_server_set_reply( req, name, sizeof(name) - sizeof(WCHAR) );
500 status = wine_server_call( req );
501 name[wine_server_reply_size(reply)/sizeof(WCHAR)] = 0;
502 index = reply->next;
504 SERVER_END_REQ;
505 if (status == STATUS_NO_MORE_ENTRIES)
506 break;
507 if (status)
509 SetLastError( RtlNtStatusToDosError( status ) );
510 return FALSE;
512 ret = func(name, lparam);
514 return ret;
518 /******************************************************************************
519 * OpenInputDesktop (USER32.@)
521 HDESK WINAPI OpenInputDesktop( DWORD flags, BOOL inherit, ACCESS_MASK access )
523 HANDLE ret = 0;
525 TRACE( "(%x,%i,%x)\n", flags, inherit, access );
527 if (flags)
528 FIXME( "partial stub flags %08x\n", flags );
530 SERVER_START_REQ( open_input_desktop )
532 req->flags = flags;
533 req->access = access;
534 req->attributes = inherit ? OBJ_INHERIT : 0;
535 if (!wine_server_call_err( req )) ret = wine_server_ptr_handle( reply->handle );
537 SERVER_END_REQ;
539 return ret;
543 /***********************************************************************
544 * GetUserObjectInformationA (USER32.@)
546 BOOL WINAPI GetUserObjectInformationA( HANDLE handle, INT index, LPVOID info, DWORD len, LPDWORD needed )
548 /* check for information types returning strings */
549 if (index == UOI_TYPE || index == UOI_NAME)
551 WCHAR buffer[MAX_PATH];
552 DWORD lenA, lenW;
554 if (!GetUserObjectInformationW( handle, index, buffer, sizeof(buffer), &lenW )) return FALSE;
555 lenA = WideCharToMultiByte( CP_ACP, 0, buffer, -1, NULL, 0, NULL, NULL );
556 if (needed) *needed = lenA;
557 if (lenA > len)
559 /* If the buffer length supplied by the caller is insufficient, Windows returns a
560 'needed' length based upon the Unicode byte length, so we should do similarly. */
561 if (needed) *needed = lenW;
563 SetLastError( ERROR_INSUFFICIENT_BUFFER );
564 return FALSE;
566 if (info) WideCharToMultiByte( CP_ACP, 0, buffer, -1, info, len, NULL, NULL );
567 return TRUE;
569 return GetUserObjectInformationW( handle, index, info, len, needed );
573 /***********************************************************************
574 * GetUserObjectInformationW (USER32.@)
576 BOOL WINAPI GetUserObjectInformationW( HANDLE handle, INT index, LPVOID info, DWORD len, LPDWORD needed )
578 BOOL ret;
580 switch(index)
582 case UOI_FLAGS:
584 USEROBJECTFLAGS *obj_flags = info;
585 if (needed) *needed = sizeof(*obj_flags);
586 if (len < sizeof(*obj_flags))
588 SetLastError( ERROR_BUFFER_OVERFLOW );
589 return FALSE;
591 SERVER_START_REQ( set_user_object_info )
593 req->handle = wine_server_obj_handle( handle );
594 req->flags = 0;
595 ret = !wine_server_call_err( req );
596 if (ret)
598 /* FIXME: inherit flag */
599 obj_flags->dwFlags = reply->old_obj_flags;
602 SERVER_END_REQ;
604 return ret;
606 case UOI_TYPE:
607 SERVER_START_REQ( set_user_object_info )
609 req->handle = wine_server_obj_handle( handle );
610 req->flags = 0;
611 ret = !wine_server_call_err( req );
612 if (ret)
614 size_t size = reply->is_desktop ? sizeof(L"Desktop") : sizeof(L"WindowStation");
615 if (needed) *needed = size;
616 if (len < size)
618 SetLastError( ERROR_INSUFFICIENT_BUFFER );
619 ret = FALSE;
621 else memcpy( info, reply->is_desktop ? L"Desktop" : L"WindowStation", size );
624 SERVER_END_REQ;
625 return ret;
627 case UOI_NAME:
629 WCHAR buffer[MAX_PATH];
630 SERVER_START_REQ( set_user_object_info )
632 req->handle = wine_server_obj_handle( handle );
633 req->flags = 0;
634 wine_server_set_reply( req, buffer, sizeof(buffer) - sizeof(WCHAR) );
635 ret = !wine_server_call_err( req );
636 if (ret)
638 size_t size = wine_server_reply_size( reply );
639 buffer[size / sizeof(WCHAR)] = 0;
640 size += sizeof(WCHAR);
641 if (needed) *needed = size;
642 if (len < size)
644 SetLastError( ERROR_INSUFFICIENT_BUFFER );
645 ret = FALSE;
647 else memcpy( info, buffer, size );
650 SERVER_END_REQ;
652 return ret;
654 case UOI_USER_SID:
655 FIXME( "not supported index %d\n", index );
656 /* fall through */
657 default:
658 SetLastError( ERROR_INVALID_PARAMETER );
659 return FALSE;
664 /******************************************************************************
665 * SetUserObjectInformationA (USER32.@)
667 BOOL WINAPI SetUserObjectInformationA( HANDLE handle, INT index, LPVOID info, DWORD len )
669 return SetUserObjectInformationW( handle, index, info, len );
673 /******************************************************************************
674 * SetUserObjectInformationW (USER32.@)
676 BOOL WINAPI SetUserObjectInformationW( HANDLE handle, INT index, LPVOID info, DWORD len )
678 BOOL ret;
679 const USEROBJECTFLAGS *obj_flags = info;
681 if (index != UOI_FLAGS || !info || len < sizeof(*obj_flags))
683 SetLastError( ERROR_INVALID_PARAMETER );
684 return FALSE;
686 /* FIXME: inherit flag */
687 SERVER_START_REQ( set_user_object_info )
689 req->handle = wine_server_obj_handle( handle );
690 req->flags = SET_USER_OBJECT_SET_FLAGS;
691 req->obj_flags = obj_flags->dwFlags;
692 ret = !wine_server_call_err( req );
694 SERVER_END_REQ;
695 return ret;
699 /***********************************************************************
700 * GetUserObjectSecurity (USER32.@)
702 BOOL WINAPI GetUserObjectSecurity( HANDLE handle, PSECURITY_INFORMATION info,
703 PSECURITY_DESCRIPTOR sid, DWORD len, LPDWORD needed )
705 FIXME( "(%p %p %p len=%d %p),stub!\n", handle, info, sid, len, needed );
706 if (needed)
707 *needed = sizeof(SECURITY_DESCRIPTOR);
708 if (len < sizeof(SECURITY_DESCRIPTOR))
710 SetLastError( ERROR_INSUFFICIENT_BUFFER );
711 return FALSE;
713 return InitializeSecurityDescriptor(sid, SECURITY_DESCRIPTOR_REVISION);
716 /***********************************************************************
717 * SetUserObjectSecurity (USER32.@)
719 BOOL WINAPI SetUserObjectSecurity( HANDLE handle, PSECURITY_INFORMATION info,
720 PSECURITY_DESCRIPTOR sid )
722 FIXME( "(%p,%p,%p),stub!\n", handle, info, sid );
723 return TRUE;