mshtml: Better timer handling.
[wine/wine-jacek.git] / dlls / user32 / winstation.c
blobabee28656dc0f49c9ae6587d5304a463bfc77695
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 "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
42 NAMEENUMPROCA func;
43 LPARAM 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 ))
52 return FALSE;
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 );
70 return 0;
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 )
82 HANDLE ret;
83 DWORD len = name ? strlenW(name) : 0;
85 if (len >= MAX_PATH)
87 SetLastError( ERROR_FILENAME_EXCED_RANGE );
88 return 0;
90 SERVER_START_REQ( create_winstation )
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 = reply->handle;
101 SERVER_END_REQ;
102 return ret;
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 );
118 return 0;
120 return OpenWindowStationW( buffer, inherit, access );
124 /******************************************************************************
125 * OpenWindowStationW (USER32.@)
127 HWINSTA WINAPI OpenWindowStationW( LPCWSTR name, BOOL inherit, ACCESS_MASK access )
129 HANDLE ret = 0;
130 DWORD len = name ? strlenW(name) : 0;
131 if (len >= MAX_PATH)
133 SetLastError( ERROR_FILENAME_EXCED_RANGE );
134 return 0;
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 = reply->handle;
143 SERVER_END_REQ;
144 return ret;
148 /***********************************************************************
149 * CloseWindowStation (USER32.@)
151 BOOL WINAPI CloseWindowStation( HWINSTA handle )
153 BOOL ret;
154 SERVER_START_REQ( close_winstation )
156 req->handle = handle;
157 ret = !wine_server_call_err( req );
159 SERVER_END_REQ;
160 return ret;
164 /******************************************************************************
165 * GetProcessWindowStation (USER32.@)
167 HWINSTA WINAPI GetProcessWindowStation(void)
169 HWINSTA ret = 0;
171 SERVER_START_REQ( get_process_winstation )
173 if (!wine_server_call_err( req )) ret = reply->handle;
175 SERVER_END_REQ;
176 return ret;
180 /***********************************************************************
181 * SetProcessWindowStation (USER32.@)
183 BOOL WINAPI SetProcessWindowStation( HWINSTA handle )
185 BOOL ret;
187 SERVER_START_REQ( set_process_winstation )
189 req->handle = handle;
190 ret = !wine_server_call_err( req );
192 SERVER_END_REQ;
193 return ret;
197 /******************************************************************************
198 * EnumWindowStationsA (USER32.@)
200 BOOL WINAPI EnumWindowStationsA( WINSTAENUMPROCA func, LPARAM lparam )
202 struct enum_proc_lparam data;
203 data.func = func;
204 data.lparam = lparam;
205 return EnumWindowStationsW( enum_names_WtoA, (LPARAM)&data );
209 /******************************************************************************
210 * EnumWindowStationsW (USER32.@)
212 BOOL WINAPI EnumWindowStationsW( WINSTAENUMPROCW func, LPARAM lparam )
214 unsigned int index = 0;
215 WCHAR name[MAX_PATH];
216 BOOL ret = TRUE;
217 NTSTATUS status;
219 while (ret)
221 SERVER_START_REQ( enum_winstation )
223 req->index = index;
224 wine_server_set_reply( req, name, sizeof(name) - sizeof(WCHAR) );
225 status = wine_server_call( req );
226 name[wine_server_reply_size(reply)/sizeof(WCHAR)] = 0;
227 index = reply->next;
229 SERVER_END_REQ;
230 if (status == STATUS_NO_MORE_ENTRIES)
231 break;
232 if (status)
234 SetLastError( RtlNtStatusToDosError( status ) );
235 return FALSE;
237 ret = func( name, lparam );
239 return ret;
243 /***********************************************************************
244 * CreateDesktopA (USER32.@)
246 HDESK WINAPI CreateDesktopA( LPCSTR name, LPCSTR device, LPDEVMODEA devmode,
247 DWORD flags, ACCESS_MASK access, LPSECURITY_ATTRIBUTES sa )
249 WCHAR buffer[MAX_PATH];
251 if (device || devmode)
253 SetLastError( ERROR_INVALID_PARAMETER );
254 return 0;
256 if (!name) return CreateDesktopW( NULL, NULL, NULL, flags, access, sa );
258 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
260 SetLastError( ERROR_FILENAME_EXCED_RANGE );
261 return 0;
263 return CreateDesktopW( buffer, NULL, NULL, flags, access, sa );
267 /***********************************************************************
268 * CreateDesktopW (USER32.@)
270 HDESK WINAPI CreateDesktopW( LPCWSTR name, LPCWSTR device, LPDEVMODEW devmode,
271 DWORD flags, ACCESS_MASK access, LPSECURITY_ATTRIBUTES sa )
273 HANDLE ret;
274 DWORD len = name ? strlenW(name) : 0;
276 if (device || devmode)
278 SetLastError( ERROR_INVALID_PARAMETER );
279 return 0;
281 if (len >= MAX_PATH)
283 SetLastError( ERROR_FILENAME_EXCED_RANGE );
284 return 0;
286 SERVER_START_REQ( create_desktop )
288 req->flags = flags;
289 req->access = access;
290 req->attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF |
291 ((sa && sa->bInheritHandle) ? OBJ_INHERIT : 0);
292 wine_server_add_data( req, name, len * sizeof(WCHAR) );
293 /* it doesn't seem to set last error */
294 wine_server_call( req );
295 ret = reply->handle;
297 SERVER_END_REQ;
298 return ret;
302 /******************************************************************************
303 * OpenDesktopA (USER32.@)
305 HDESK WINAPI OpenDesktopA( LPCSTR name, DWORD flags, BOOL inherit, ACCESS_MASK access )
307 WCHAR buffer[MAX_PATH];
309 if (!name) return OpenDesktopW( NULL, flags, inherit, access );
311 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
313 SetLastError( ERROR_FILENAME_EXCED_RANGE );
314 return 0;
316 return OpenDesktopW( buffer, flags, inherit, access );
320 HDESK open_winstation_desktop( HWINSTA hwinsta, LPCWSTR name, DWORD flags, BOOL inherit, ACCESS_MASK access )
322 HANDLE ret = 0;
323 DWORD len = name ? strlenW(name) : 0;
324 if (len >= MAX_PATH)
326 SetLastError( ERROR_FILENAME_EXCED_RANGE );
327 return 0;
329 SERVER_START_REQ( open_desktop )
331 req->winsta = hwinsta;
332 req->flags = flags;
333 req->access = access;
334 req->attributes = OBJ_CASE_INSENSITIVE | (inherit ? OBJ_INHERIT : 0);
335 wine_server_add_data( req, name, len * sizeof(WCHAR) );
336 if (!wine_server_call( req )) ret = reply->handle;
338 SERVER_END_REQ;
339 return ret;
343 /******************************************************************************
344 * OpenDesktopW (USER32.@)
346 HDESK WINAPI OpenDesktopW( LPCWSTR name, DWORD flags, BOOL inherit, ACCESS_MASK access )
348 return open_winstation_desktop( NULL, name, flags, inherit, access );
352 /***********************************************************************
353 * CloseDesktop (USER32.@)
355 BOOL WINAPI CloseDesktop( HDESK handle )
357 BOOL ret;
358 SERVER_START_REQ( close_desktop )
360 req->handle = handle;
361 ret = !wine_server_call_err( req );
363 SERVER_END_REQ;
364 return ret;
368 /******************************************************************************
369 * GetThreadDesktop (USER32.@)
371 HDESK WINAPI GetThreadDesktop( DWORD thread )
373 HDESK ret = 0;
375 SERVER_START_REQ( get_thread_desktop )
377 req->tid = thread;
378 if (!wine_server_call_err( req )) ret = reply->handle;
380 SERVER_END_REQ;
381 return ret;
385 /******************************************************************************
386 * SetThreadDesktop (USER32.@)
388 BOOL WINAPI SetThreadDesktop( HDESK handle )
390 BOOL ret;
392 SERVER_START_REQ( set_thread_desktop )
394 req->handle = handle;
395 ret = !wine_server_call_err( req );
397 SERVER_END_REQ;
398 if (ret) get_user_thread_info()->desktop = 0; /* reset the desktop window */
399 return ret;
403 /******************************************************************************
404 * EnumDesktopsA (USER32.@)
406 BOOL WINAPI EnumDesktopsA( HWINSTA winsta, DESKTOPENUMPROCA func, LPARAM lparam )
408 struct enum_proc_lparam data;
409 data.func = func;
410 data.lparam = lparam;
411 return EnumDesktopsW( winsta, enum_names_WtoA, (LPARAM)&data );
415 /******************************************************************************
416 * EnumDesktopsW (USER32.@)
418 BOOL WINAPI EnumDesktopsW( HWINSTA winsta, DESKTOPENUMPROCW func, LPARAM lparam )
420 unsigned int index = 0;
421 WCHAR name[MAX_PATH];
422 BOOL ret = TRUE;
423 NTSTATUS status;
425 if (!winsta)
426 winsta = GetProcessWindowStation();
428 while (ret)
430 SERVER_START_REQ( enum_desktop )
432 req->winstation = winsta;
433 req->index = index;
434 wine_server_set_reply( req, name, sizeof(name) - sizeof(WCHAR) );
435 status = wine_server_call( req );
436 name[wine_server_reply_size(reply)/sizeof(WCHAR)] = 0;
437 index = reply->next;
439 SERVER_END_REQ;
440 if (status == STATUS_NO_MORE_ENTRIES)
441 break;
442 if (status)
444 SetLastError( RtlNtStatusToDosError( status ) );
445 return FALSE;
447 ret = func(name, lparam);
449 return ret;
453 /******************************************************************************
454 * OpenInputDesktop (USER32.@)
456 HDESK WINAPI OpenInputDesktop( DWORD flags, BOOL inherit, ACCESS_MASK access )
458 FIXME( "(%x,%i,%x): stub\n", flags, inherit, access );
459 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
460 return 0;
464 /***********************************************************************
465 * GetUserObjectInformationA (USER32.@)
467 BOOL WINAPI GetUserObjectInformationA( HANDLE handle, INT index, LPVOID info, DWORD len, LPDWORD needed )
469 /* check for information types returning strings */
470 if (index == UOI_TYPE || index == UOI_NAME)
472 WCHAR buffer[MAX_PATH];
473 DWORD lenA;
475 if (!GetUserObjectInformationW( handle, index, buffer, sizeof(buffer), NULL )) return FALSE;
476 lenA = WideCharToMultiByte( CP_ACP, 0, buffer, -1, NULL, 0, NULL, NULL );
477 if (needed) *needed = lenA;
478 if (lenA > len)
480 SetLastError( ERROR_MORE_DATA );
481 return FALSE;
483 if (info) WideCharToMultiByte( CP_ACP, 0, buffer, -1, info, len, NULL, NULL );
484 return TRUE;
486 return GetUserObjectInformationW( handle, index, info, len, needed );
490 /***********************************************************************
491 * GetUserObjectInformationW (USER32.@)
493 BOOL WINAPI GetUserObjectInformationW( HANDLE handle, INT index, LPVOID info, DWORD len, LPDWORD needed )
495 static const WCHAR desktopW[] = { 'D','e','s','k','t','o','p',0 };
496 static const WCHAR winstationW[] = { 'W','i','n','d','o','w','S','t','a','t','i','o','n',0 };
497 BOOL ret;
499 switch(index)
501 case UOI_FLAGS:
503 USEROBJECTFLAGS *obj_flags = info;
504 if (needed) *needed = sizeof(*obj_flags);
505 if (len < sizeof(*obj_flags))
507 SetLastError( ERROR_BUFFER_OVERFLOW );
508 return FALSE;
510 SERVER_START_REQ( set_user_object_info )
512 req->handle = handle;
513 req->flags = 0;
514 ret = !wine_server_call_err( req );
515 if (ret)
517 /* FIXME: inherit flag */
518 obj_flags->dwFlags = reply->old_obj_flags;
521 SERVER_END_REQ;
523 return ret;
525 case UOI_TYPE:
526 SERVER_START_REQ( set_user_object_info )
528 req->handle = handle;
529 req->flags = 0;
530 ret = !wine_server_call_err( req );
531 if (ret)
533 size_t size = reply->is_desktop ? sizeof(desktopW) : sizeof(winstationW);
534 if (needed) *needed = size;
535 if (len < size)
537 SetLastError( ERROR_MORE_DATA );
538 ret = FALSE;
540 else memcpy( info, reply->is_desktop ? desktopW : winstationW, size );
543 SERVER_END_REQ;
544 return ret;
546 case UOI_NAME:
548 WCHAR buffer[MAX_PATH];
549 SERVER_START_REQ( set_user_object_info )
551 req->handle = handle;
552 req->flags = 0;
553 wine_server_set_reply( req, buffer, sizeof(buffer) - sizeof(WCHAR) );
554 ret = !wine_server_call_err( req );
555 if (ret)
557 size_t size = wine_server_reply_size( reply );
558 buffer[size / sizeof(WCHAR)] = 0;
559 size += sizeof(WCHAR);
560 if (needed) *needed = size;
561 if (len < size)
563 SetLastError( ERROR_MORE_DATA );
564 ret = FALSE;
566 else memcpy( info, buffer, size );
569 SERVER_END_REQ;
571 return ret;
573 case UOI_USER_SID:
574 FIXME( "not supported index %d\n", index );
575 /* fall through */
576 default:
577 SetLastError( ERROR_INVALID_PARAMETER );
578 return FALSE;
583 /******************************************************************************
584 * SetUserObjectInformationA (USER32.@)
586 BOOL WINAPI SetUserObjectInformationA( HANDLE handle, INT index, LPVOID info, DWORD len )
588 return SetUserObjectInformationW( handle, index, info, len );
592 /******************************************************************************
593 * SetUserObjectInformationW (USER32.@)
595 BOOL WINAPI SetUserObjectInformationW( HANDLE handle, INT index, LPVOID info, DWORD len )
597 BOOL ret;
598 const USEROBJECTFLAGS *obj_flags = info;
600 if (index != UOI_FLAGS || !info || len < sizeof(*obj_flags))
602 SetLastError( ERROR_INVALID_PARAMETER );
603 return FALSE;
605 /* FIXME: inherit flag */
606 SERVER_START_REQ( set_user_object_info )
608 req->handle = handle;
609 req->flags = SET_USER_OBJECT_FLAGS;
610 req->obj_flags = obj_flags->dwFlags;
611 ret = !wine_server_call_err( req );
613 SERVER_END_REQ;
614 return ret;
618 /***********************************************************************
619 * GetUserObjectSecurity (USER32.@)
621 BOOL WINAPI GetUserObjectSecurity( HANDLE handle, PSECURITY_INFORMATION info,
622 PSECURITY_DESCRIPTOR sid, DWORD len, LPDWORD needed )
624 FIXME( "(%p %p %p len=%d %p),stub!\n", handle, info, sid, len, needed );
625 return TRUE;
628 /***********************************************************************
629 * SetUserObjectSecurity (USER32.@)
631 BOOL WINAPI SetUserObjectSecurity( HANDLE handle, PSECURITY_INFORMATION info,
632 PSECURITY_DESCRIPTOR sid )
634 FIXME( "(%p,%p,%p),stub!\n", handle, info, sid );
635 return TRUE;