msi: WriteEnvironmentStrings should also write to REG_EXPAND_SZ strings.
[wine/wine-kai.git] / dlls / user32 / winstation.c
blob75cb286c9f03ee62942c824203734a22c100fabd
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 <stdarg.h>
22 #include "windef.h"
23 #include "winbase.h"
24 #include "winnls.h"
25 #include "winerror.h"
26 #include "wingdi.h"
27 #include "winuser.h"
28 #include "wine/server.h"
29 #include "wine/unicode.h"
30 #include "wine/debug.h"
31 #include "user_private.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(winstation);
36 /* callback for enumeration functions */
37 struct enum_proc_lparam
39 NAMEENUMPROCA func;
40 LPARAM lparam;
43 static BOOL CALLBACK enum_names_WtoA( LPWSTR name, LPARAM lparam )
45 struct enum_proc_lparam *data = (struct enum_proc_lparam *)lparam;
46 char buffer[MAX_PATH];
48 if (!WideCharToMultiByte( CP_ACP, 0, name, -1, buffer, sizeof(buffer), NULL, NULL ))
49 return FALSE;
50 return data->func( buffer, data->lparam );
54 /***********************************************************************
55 * CreateWindowStationA (USER32.@)
57 HWINSTA WINAPI CreateWindowStationA( LPCSTR name, DWORD reserved, ACCESS_MASK access,
58 LPSECURITY_ATTRIBUTES sa )
60 WCHAR buffer[MAX_PATH];
62 if (!name) return CreateWindowStationW( NULL, reserved, access, sa );
64 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
66 SetLastError( ERROR_FILENAME_EXCED_RANGE );
67 return 0;
69 return CreateWindowStationW( buffer, reserved, access, sa );
73 /***********************************************************************
74 * CreateWindowStationW (USER32.@)
76 HWINSTA WINAPI CreateWindowStationW( LPCWSTR name, DWORD reserved, ACCESS_MASK access,
77 LPSECURITY_ATTRIBUTES sa )
79 HANDLE ret;
80 DWORD len = name ? strlenW(name) : 0;
82 if (len >= MAX_PATH)
84 SetLastError( ERROR_FILENAME_EXCED_RANGE );
85 return 0;
87 SERVER_START_REQ( create_winstation )
89 req->flags = 0;
90 req->access = access;
91 req->attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF |
92 ((sa && sa->bInheritHandle) ? OBJ_INHERIT : 0);
93 wine_server_add_data( req, name, len * sizeof(WCHAR) );
94 /* it doesn't seem to set last error */
95 wine_server_call( req );
96 ret = reply->handle;
98 SERVER_END_REQ;
99 return ret;
103 /******************************************************************************
104 * OpenWindowStationA (USER32.@)
106 HWINSTA WINAPI OpenWindowStationA( LPCSTR name, BOOL inherit, ACCESS_MASK access )
108 WCHAR buffer[MAX_PATH];
110 if (!name) return OpenWindowStationW( NULL, inherit, access );
112 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
114 SetLastError( ERROR_FILENAME_EXCED_RANGE );
115 return 0;
117 return OpenWindowStationW( buffer, inherit, access );
121 /******************************************************************************
122 * OpenWindowStationW (USER32.@)
124 HWINSTA WINAPI OpenWindowStationW( LPCWSTR name, BOOL inherit, ACCESS_MASK access )
126 HANDLE ret = 0;
127 DWORD len = name ? strlenW(name) : 0;
128 if (len >= MAX_PATH)
130 SetLastError( ERROR_FILENAME_EXCED_RANGE );
131 return 0;
133 SERVER_START_REQ( open_winstation )
135 req->access = access;
136 req->attributes = OBJ_CASE_INSENSITIVE | (inherit ? OBJ_INHERIT : 0);
137 wine_server_add_data( req, name, len * sizeof(WCHAR) );
138 if (!wine_server_call_err( req )) ret = reply->handle;
140 SERVER_END_REQ;
141 return ret;
145 /***********************************************************************
146 * CloseWindowStation (USER32.@)
148 BOOL WINAPI CloseWindowStation( HWINSTA handle )
150 BOOL ret;
151 SERVER_START_REQ( close_winstation )
153 req->handle = handle;
154 ret = !wine_server_call_err( req );
156 SERVER_END_REQ;
157 return ret;
161 /******************************************************************************
162 * GetProcessWindowStation (USER32.@)
164 HWINSTA WINAPI GetProcessWindowStation(void)
166 HWINSTA ret = 0;
168 SERVER_START_REQ( get_process_winstation )
170 if (!wine_server_call_err( req )) ret = reply->handle;
172 SERVER_END_REQ;
173 return ret;
177 /***********************************************************************
178 * SetProcessWindowStation (USER32.@)
180 BOOL WINAPI SetProcessWindowStation( HWINSTA handle )
182 BOOL ret;
184 SERVER_START_REQ( set_process_winstation )
186 req->handle = handle;
187 ret = !wine_server_call_err( req );
189 SERVER_END_REQ;
190 return ret;
194 /******************************************************************************
195 * EnumWindowStationsA (USER32.@)
197 BOOL WINAPI EnumWindowStationsA( WINSTAENUMPROCA func, LPARAM lparam )
199 struct enum_proc_lparam data;
200 data.func = func;
201 data.lparam = lparam;
202 return EnumWindowStationsW( enum_names_WtoA, (LPARAM)&data );
206 /******************************************************************************
207 * EnumWindowStationsW (USER32.@)
209 BOOL WINAPI EnumWindowStationsW( WINSTAENUMPROCW func, LPARAM lparam )
211 unsigned int index = 0;
212 WCHAR name[MAX_PATH];
213 BOOL ret = TRUE;
215 while (ret)
217 SERVER_START_REQ( enum_winstation )
219 req->index = index;
220 wine_server_set_reply( req, name, sizeof(name) );
221 ret = !wine_server_call( req );
222 index = reply->next;
224 SERVER_END_REQ;
225 if (ret) ret = func( name, lparam );
227 return ret;
231 /***********************************************************************
232 * CreateDesktopA (USER32.@)
234 HDESK WINAPI CreateDesktopA( LPCSTR name, LPCSTR device, LPDEVMODEA devmode,
235 DWORD flags, ACCESS_MASK access, LPSECURITY_ATTRIBUTES sa )
237 WCHAR buffer[MAX_PATH];
239 if (device || devmode)
241 SetLastError( ERROR_INVALID_PARAMETER );
242 return 0;
244 if (!name) return CreateDesktopW( NULL, NULL, NULL, flags, access, sa );
246 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
248 SetLastError( ERROR_FILENAME_EXCED_RANGE );
249 return 0;
251 return CreateDesktopW( buffer, NULL, NULL, flags, access, sa );
255 /***********************************************************************
256 * CreateDesktopW (USER32.@)
258 HDESK WINAPI CreateDesktopW( LPCWSTR name, LPCWSTR device, LPDEVMODEW devmode,
259 DWORD flags, ACCESS_MASK access, LPSECURITY_ATTRIBUTES sa )
261 HANDLE ret;
262 DWORD len = name ? strlenW(name) : 0;
264 if (device || devmode)
266 SetLastError( ERROR_INVALID_PARAMETER );
267 return 0;
269 if (len >= MAX_PATH)
271 SetLastError( ERROR_FILENAME_EXCED_RANGE );
272 return 0;
274 SERVER_START_REQ( create_desktop )
276 req->flags = flags;
277 req->access = access;
278 req->attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF |
279 ((sa && sa->bInheritHandle) ? OBJ_INHERIT : 0);
280 wine_server_add_data( req, name, len * sizeof(WCHAR) );
281 /* it doesn't seem to set last error */
282 wine_server_call( req );
283 ret = reply->handle;
285 SERVER_END_REQ;
286 return ret;
290 /******************************************************************************
291 * OpenDesktopA (USER32.@)
293 HDESK WINAPI OpenDesktopA( LPCSTR name, DWORD flags, BOOL inherit, ACCESS_MASK access )
295 WCHAR buffer[MAX_PATH];
297 if (!name) return OpenDesktopW( NULL, flags, inherit, access );
299 if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
301 SetLastError( ERROR_FILENAME_EXCED_RANGE );
302 return 0;
304 return OpenDesktopW( buffer, flags, inherit, access );
308 /******************************************************************************
309 * OpenDesktopW (USER32.@)
311 HDESK WINAPI OpenDesktopW( LPCWSTR name, DWORD flags, BOOL inherit, ACCESS_MASK access )
313 HANDLE ret = 0;
314 DWORD len = name ? strlenW(name) : 0;
315 if (len >= MAX_PATH)
317 SetLastError( ERROR_FILENAME_EXCED_RANGE );
318 return 0;
320 SERVER_START_REQ( open_desktop )
322 req->flags = flags;
323 req->access = access;
324 req->attributes = OBJ_CASE_INSENSITIVE | (inherit ? OBJ_INHERIT : 0);
325 wine_server_add_data( req, name, len * sizeof(WCHAR) );
326 if (!wine_server_call( req )) ret = reply->handle;
328 SERVER_END_REQ;
329 return ret;
333 /***********************************************************************
334 * CloseDesktop (USER32.@)
336 BOOL WINAPI CloseDesktop( HDESK handle )
338 BOOL ret;
339 SERVER_START_REQ( close_desktop )
341 req->handle = handle;
342 ret = !wine_server_call_err( req );
344 SERVER_END_REQ;
345 return ret;
349 /******************************************************************************
350 * GetThreadDesktop (USER32.@)
352 HDESK WINAPI GetThreadDesktop( DWORD thread )
354 HDESK ret = 0;
356 SERVER_START_REQ( get_thread_desktop )
358 req->tid = thread;
359 if (!wine_server_call_err( req )) ret = reply->handle;
361 SERVER_END_REQ;
362 return ret;
366 /******************************************************************************
367 * SetThreadDesktop (USER32.@)
369 BOOL WINAPI SetThreadDesktop( HDESK handle )
371 BOOL ret;
373 SERVER_START_REQ( set_thread_desktop )
375 req->handle = handle;
376 ret = !wine_server_call_err( req );
378 SERVER_END_REQ;
379 if (ret) get_user_thread_info()->desktop = 0; /* reset the desktop window */
380 return ret;
384 /******************************************************************************
385 * EnumDesktopsA (USER32.@)
387 BOOL WINAPI EnumDesktopsA( HWINSTA winsta, DESKTOPENUMPROCA func, LPARAM lparam )
389 struct enum_proc_lparam data;
390 data.func = func;
391 data.lparam = lparam;
392 return EnumDesktopsW( winsta, enum_names_WtoA, (LPARAM)&data );
396 /******************************************************************************
397 * EnumDesktopsW (USER32.@)
399 BOOL WINAPI EnumDesktopsW( HWINSTA winsta, DESKTOPENUMPROCW func, LPARAM lparam )
401 unsigned int index = 0;
402 WCHAR name[MAX_PATH];
403 BOOL ret = TRUE;
405 while (ret)
407 SERVER_START_REQ( enum_desktop )
409 req->winstation = winsta;
410 req->index = index;
411 wine_server_set_reply( req, name, sizeof(name) );
412 ret = !wine_server_call( req );
413 index = reply->next;
415 SERVER_END_REQ;
416 if (ret) ret = func( name, lparam );
418 return ret;
422 /******************************************************************************
423 * OpenInputDesktop (USER32.@)
425 HDESK WINAPI OpenInputDesktop( DWORD flags, BOOL inherit, ACCESS_MASK access )
427 FIXME( "(%x,%i,%x): stub\n", flags, inherit, access );
428 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
429 return 0;
433 /***********************************************************************
434 * EnumDesktopWindows (USER32.@)
436 BOOL WINAPI EnumDesktopWindows( HDESK desktop, WNDENUMPROC func, LPARAM lparam )
438 FIXME( "(%p,%p,0x%lx): stub!\n", desktop, func, lparam );
439 return TRUE;
443 /***********************************************************************
444 * GetUserObjectInformationA (USER32.@)
446 BOOL WINAPI GetUserObjectInformationA( HANDLE handle, INT index, LPVOID info, DWORD len, LPDWORD needed )
448 /* check for information types returning strings */
449 if (index == UOI_TYPE || index == UOI_NAME)
451 WCHAR buffer[MAX_PATH];
452 DWORD lenA;
454 if (!GetUserObjectInformationW( handle, index, buffer, sizeof(buffer), NULL )) return FALSE;
455 lenA = WideCharToMultiByte( CP_ACP, 0, buffer, -1, NULL, 0, NULL, NULL );
456 if (needed) *needed = lenA;
457 if (lenA > len)
459 SetLastError( ERROR_MORE_DATA );
460 return FALSE;
462 if (info) WideCharToMultiByte( CP_ACP, 0, buffer, -1, info, len, NULL, NULL );
463 return TRUE;
465 return GetUserObjectInformationW( handle, index, info, len, needed );
469 /***********************************************************************
470 * GetUserObjectInformationW (USER32.@)
472 BOOL WINAPI GetUserObjectInformationW( HANDLE handle, INT index, LPVOID info, DWORD len, LPDWORD needed )
474 static const WCHAR desktopW[] = { 'D','e','s','k','t','o','p',0 };
475 static const WCHAR winstationW[] = { 'W','i','n','d','o','w','S','t','a','t','i','o','n',0 };
476 BOOL ret;
478 switch(index)
480 case UOI_FLAGS:
482 USEROBJECTFLAGS *obj_flags = info;
483 if (needed) *needed = sizeof(*obj_flags);
484 if (len < sizeof(*obj_flags))
486 SetLastError( ERROR_BUFFER_OVERFLOW );
487 return FALSE;
489 SERVER_START_REQ( set_user_object_info )
491 req->handle = handle;
492 req->flags = 0;
493 ret = !wine_server_call_err( req );
494 if (ret)
496 /* FIXME: inherit flag */
497 obj_flags->dwFlags = reply->old_obj_flags;
500 SERVER_END_REQ;
502 return ret;
504 case UOI_TYPE:
505 SERVER_START_REQ( set_user_object_info )
507 req->handle = handle;
508 req->flags = 0;
509 ret = !wine_server_call_err( req );
510 if (ret)
512 size_t size = reply->is_desktop ? sizeof(desktopW) : sizeof(winstationW);
513 if (needed) *needed = size;
514 if (len < size)
516 SetLastError( ERROR_MORE_DATA );
517 ret = FALSE;
519 else memcpy( info, reply->is_desktop ? desktopW : winstationW, size );
522 SERVER_END_REQ;
523 return ret;
525 case UOI_NAME:
527 WCHAR buffer[MAX_PATH];
528 SERVER_START_REQ( set_user_object_info )
530 req->handle = handle;
531 req->flags = 0;
532 wine_server_set_reply( req, buffer, sizeof(buffer) - sizeof(WCHAR) );
533 ret = !wine_server_call_err( req );
534 if (ret)
536 size_t size = wine_server_reply_size( reply );
537 buffer[size / sizeof(WCHAR)] = 0;
538 size += sizeof(WCHAR);
539 if (needed) *needed = size;
540 if (len < size)
542 SetLastError( ERROR_MORE_DATA );
543 ret = FALSE;
545 else memcpy( info, buffer, size );
548 SERVER_END_REQ;
550 return ret;
552 case UOI_USER_SID:
553 FIXME( "not supported index %d\n", index );
554 /* fall through */
555 default:
556 SetLastError( ERROR_INVALID_PARAMETER );
557 return FALSE;
562 /******************************************************************************
563 * SetUserObjectInformationA (USER32.@)
565 BOOL WINAPI SetUserObjectInformationA( HANDLE handle, INT index, LPVOID info, DWORD len )
567 return SetUserObjectInformationW( handle, index, info, len );
571 /******************************************************************************
572 * SetUserObjectInformationW (USER32.@)
574 BOOL WINAPI SetUserObjectInformationW( HANDLE handle, INT index, LPVOID info, DWORD len )
576 BOOL ret;
577 const USEROBJECTFLAGS *obj_flags = info;
579 if (index != UOI_FLAGS || !info || len < sizeof(*obj_flags))
581 SetLastError( ERROR_INVALID_PARAMETER );
582 return FALSE;
584 /* FIXME: inherit flag */
585 SERVER_START_REQ( set_user_object_info )
587 req->handle = handle;
588 req->flags = SET_USER_OBJECT_FLAGS;
589 req->obj_flags = obj_flags->dwFlags;
590 ret = !wine_server_call_err( req );
592 SERVER_END_REQ;
593 return ret;
597 /***********************************************************************
598 * GetUserObjectSecurity (USER32.@)
600 BOOL WINAPI GetUserObjectSecurity( HANDLE handle, PSECURITY_INFORMATION info,
601 PSECURITY_DESCRIPTOR sid, DWORD len, LPDWORD needed )
603 FIXME( "(%p %p %p len=%d %p),stub!\n", handle, info, sid, len, needed );
604 return TRUE;
607 /***********************************************************************
608 * SetUserObjectSecurity (USER32.@)
610 BOOL WINAPI SetUserObjectSecurity( HANDLE handle, PSECURITY_INFORMATION info,
611 PSECURITY_DESCRIPTOR sid )
613 FIXME( "(%p,%p,%p),stub!\n", handle, info, sid );
614 return TRUE;