user32: Fix handling of '\b' right flush character in menus.
[wine] / dlls / user / winstation.c
1 /*
2  * Window stations and desktops
3  *
4  * Copyright 2002 Alexandre Julliard
5  *
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.
10  *
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.
15  *
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
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"
32
33 WINE_DEFAULT_DEBUG_CHANNEL(winstation);
34
35
36 /* callback for enumeration functions */
37 struct enum_proc_lparam
38 {
39     NAMEENUMPROCA func;
40     LPARAM        lparam;
41 };
42
43 static BOOL CALLBACK enum_names_WtoA( LPWSTR name, LPARAM lparam )
44 {
45     struct enum_proc_lparam *data = (struct enum_proc_lparam *)lparam;
46     char buffer[MAX_PATH];
47
48     if (!WideCharToMultiByte( CP_ACP, 0, name, -1, buffer, sizeof(buffer), NULL, NULL ))
49         return FALSE;
50     return data->func( buffer, data->lparam );
51 }
52
53
54 /***********************************************************************
55  *              CreateWindowStationA  (USER32.@)
56  */
57 HWINSTA WINAPI CreateWindowStationA( LPCSTR name, DWORD reserved, ACCESS_MASK access,
58                                      LPSECURITY_ATTRIBUTES sa )
59 {
60     WCHAR buffer[MAX_PATH];
61
62     if (!name) return CreateWindowStationW( NULL, reserved, access, sa );
63
64     if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
65     {
66         SetLastError( ERROR_FILENAME_EXCED_RANGE );
67         return 0;
68     }
69     return CreateWindowStationW( buffer, reserved, access, sa );
70 }
71
72
73 /***********************************************************************
74  *              CreateWindowStationW  (USER32.@)
75  */
76 HWINSTA WINAPI CreateWindowStationW( LPCWSTR name, DWORD reserved, ACCESS_MASK access,
77                                      LPSECURITY_ATTRIBUTES sa )
78 {
79     HANDLE ret;
80     DWORD len = name ? strlenW(name) : 0;
81
82     if (len >= MAX_PATH)
83     {
84         SetLastError( ERROR_FILENAME_EXCED_RANGE );
85         return 0;
86     }
87     SERVER_START_REQ( create_winstation )
88     {
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;
97     }
98     SERVER_END_REQ;
99     return ret;
100 }
101
102
103 /******************************************************************************
104  *              OpenWindowStationA  (USER32.@)
105  */
106 HWINSTA WINAPI OpenWindowStationA( LPCSTR name, BOOL inherit, ACCESS_MASK access )
107 {
108     WCHAR buffer[MAX_PATH];
109
110     if (!name) return OpenWindowStationW( NULL, inherit, access );
111
112     if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
113     {
114         SetLastError( ERROR_FILENAME_EXCED_RANGE );
115         return 0;
116     }
117     return OpenWindowStationW( buffer, inherit, access );
118 }
119
120
121 /******************************************************************************
122  *              OpenWindowStationW  (USER32.@)
123  */
124 HWINSTA WINAPI OpenWindowStationW( LPCWSTR name, BOOL inherit, ACCESS_MASK access )
125 {
126     HANDLE ret = 0;
127     DWORD len = name ? strlenW(name) : 0;
128     if (len >= MAX_PATH)
129     {
130         SetLastError( ERROR_FILENAME_EXCED_RANGE );
131         return 0;
132     }
133     SERVER_START_REQ( open_winstation )
134     {
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;
139     }
140     SERVER_END_REQ;
141     return ret;
142 }
143
144
145 /***********************************************************************
146  *              CloseWindowStation  (USER32.@)
147  */
148 BOOL WINAPI CloseWindowStation( HWINSTA handle )
149 {
150     BOOL ret;
151     SERVER_START_REQ( close_winstation )
152     {
153         req->handle = handle;
154         ret = !wine_server_call_err( req );
155     }
156     SERVER_END_REQ;
157     return ret;
158 }
159
160
161 /******************************************************************************
162  *              GetProcessWindowStation  (USER32.@)
163  */
164 HWINSTA WINAPI GetProcessWindowStation(void)
165 {
166     HWINSTA ret = 0;
167
168     SERVER_START_REQ( get_process_winstation )
169     {
170         if (!wine_server_call_err( req )) ret = reply->handle;
171     }
172     SERVER_END_REQ;
173     return ret;
174 }
175
176
177 /***********************************************************************
178  *              SetProcessWindowStation  (USER32.@)
179  */
180 BOOL WINAPI SetProcessWindowStation( HWINSTA handle )
181 {
182     BOOL ret;
183
184     SERVER_START_REQ( set_process_winstation )
185     {
186         req->handle = handle;
187         ret = !wine_server_call_err( req );
188     }
189     SERVER_END_REQ;
190     return ret;
191 }
192
193
194 /******************************************************************************
195  *              EnumWindowStationsA  (USER32.@)
196  */
197 BOOL WINAPI EnumWindowStationsA( WINSTAENUMPROCA func, LPARAM lparam )
198 {
199     struct enum_proc_lparam data;
200     data.func   = func;
201     data.lparam = lparam;
202     return EnumWindowStationsW( enum_names_WtoA, (LPARAM)&data );
203 }
204
205
206 /******************************************************************************
207  *              EnumWindowStationsA  (USER32.@)
208  */
209 BOOL WINAPI EnumWindowStationsW( WINSTAENUMPROCW func, LPARAM lparam )
210 {
211     FIXME( "(%p,%lx): stub\n", func, lparam );
212     SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
213     return FALSE;
214 }
215
216
217 /***********************************************************************
218  *              CreateDesktopA   (USER32.@)
219  */
220 HDESK WINAPI CreateDesktopA( LPCSTR name, LPCSTR device, LPDEVMODEA devmode,
221                              DWORD flags, ACCESS_MASK access, LPSECURITY_ATTRIBUTES sa )
222 {
223     WCHAR buffer[MAX_PATH];
224
225     if (device || devmode)
226     {
227         SetLastError( ERROR_INVALID_PARAMETER );
228         return 0;
229     }
230     if (!name) return CreateDesktopW( NULL, NULL, NULL, flags, access, sa );
231
232     if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
233     {
234         SetLastError( ERROR_FILENAME_EXCED_RANGE );
235         return 0;
236     }
237     return CreateDesktopW( buffer, NULL, NULL, flags, access, sa );
238 }
239
240
241 /***********************************************************************
242  *              CreateDesktopW   (USER32.@)
243  */
244 HDESK WINAPI CreateDesktopW( LPCWSTR name, LPCWSTR device, LPDEVMODEW devmode,
245                              DWORD flags, ACCESS_MASK access, LPSECURITY_ATTRIBUTES sa )
246 {
247     HANDLE ret;
248     DWORD len = name ? strlenW(name) : 0;
249
250     if (device || devmode)
251     {
252         SetLastError( ERROR_INVALID_PARAMETER );
253         return 0;
254     }
255     if (len >= MAX_PATH)
256     {
257         SetLastError( ERROR_FILENAME_EXCED_RANGE );
258         return 0;
259     }
260     SERVER_START_REQ( create_desktop )
261     {
262         req->flags      = flags;
263         req->access     = access;
264         req->attributes = OBJ_CASE_INSENSITIVE | OBJ_OPENIF |
265                           ((sa && sa->bInheritHandle) ? OBJ_INHERIT : 0);
266         wine_server_add_data( req, name, len * sizeof(WCHAR) );
267         /* it doesn't seem to set last error */
268         wine_server_call( req );
269         ret = reply->handle;
270     }
271     SERVER_END_REQ;
272     return ret;
273 }
274
275
276 /******************************************************************************
277  *              OpenDesktopA   (USER32.@)
278  */
279 HDESK WINAPI OpenDesktopA( LPCSTR name, DWORD flags, BOOL inherit, ACCESS_MASK access )
280 {
281     WCHAR buffer[MAX_PATH];
282
283     if (!name) return OpenDesktopW( NULL, flags, inherit, access );
284
285     if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
286     {
287         SetLastError( ERROR_FILENAME_EXCED_RANGE );
288         return 0;
289     }
290     return OpenDesktopW( buffer, flags, inherit, access );
291 }
292
293
294 /******************************************************************************
295  *              OpenDesktopW   (USER32.@)
296  */
297 HDESK WINAPI OpenDesktopW( LPCWSTR name, DWORD flags, BOOL inherit, ACCESS_MASK access )
298 {
299     HANDLE ret = 0;
300     DWORD len = name ? strlenW(name) : 0;
301     if (len >= MAX_PATH)
302     {
303         SetLastError( ERROR_FILENAME_EXCED_RANGE );
304         return 0;
305     }
306     SERVER_START_REQ( open_desktop )
307     {
308         req->flags      = flags;
309         req->access     = access;
310         req->attributes = OBJ_CASE_INSENSITIVE | (inherit ? OBJ_INHERIT : 0);
311         wine_server_add_data( req, name, len * sizeof(WCHAR) );
312         if (!wine_server_call( req )) ret = reply->handle;
313     }
314     SERVER_END_REQ;
315     return ret;
316 }
317
318
319 /***********************************************************************
320  *              CloseDesktop  (USER32.@)
321  */
322 BOOL WINAPI CloseDesktop( HDESK handle )
323 {
324     BOOL ret;
325     SERVER_START_REQ( close_desktop )
326     {
327         req->handle = handle;
328         ret = !wine_server_call_err( req );
329     }
330     SERVER_END_REQ;
331     return ret;
332 }
333
334
335 /******************************************************************************
336  *              GetThreadDesktop   (USER32.@)
337  */
338 HDESK WINAPI GetThreadDesktop( DWORD thread )
339 {
340     HDESK ret = 0;
341
342     SERVER_START_REQ( get_thread_desktop )
343     {
344         req->tid = thread;
345         if (!wine_server_call_err( req )) ret = reply->handle;
346     }
347     SERVER_END_REQ;
348     return ret;
349 }
350
351
352 /******************************************************************************
353  *              SetThreadDesktop   (USER32.@)
354  */
355 BOOL WINAPI SetThreadDesktop( HDESK handle )
356 {
357     BOOL ret;
358
359     SERVER_START_REQ( set_thread_desktop )
360     {
361         req->handle = handle;
362         ret = !wine_server_call_err( req );
363     }
364     SERVER_END_REQ;
365     if (ret) get_user_thread_info()->desktop = 0;  /* reset the desktop window */
366     return ret;
367 }
368
369
370 /******************************************************************************
371  *              EnumDesktopsA   (USER32.@)
372  */
373 BOOL WINAPI EnumDesktopsA( HWINSTA winsta, DESKTOPENUMPROCA func, LPARAM lparam )
374 {
375     struct enum_proc_lparam data;
376     data.func   = func;
377     data.lparam = lparam;
378     return EnumDesktopsW( winsta, enum_names_WtoA, (LPARAM)&data );
379 }
380
381
382 /******************************************************************************
383  *              EnumDesktopsW   (USER32.@)
384  */
385 BOOL WINAPI EnumDesktopsW( HWINSTA winsta, DESKTOPENUMPROCW func, LPARAM lparam )
386 {
387     FIXME( "(%p,%p,%lx): stub\n", winsta, func, lparam );
388     SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
389     return FALSE;
390 }
391
392
393 /******************************************************************************
394  *              OpenInputDesktop   (USER32.@)
395  */
396 HDESK WINAPI OpenInputDesktop( DWORD flags, BOOL inherit, ACCESS_MASK access )
397 {
398     FIXME( "(%lx,%i,%lx): stub\n", flags, inherit, access );
399     SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
400     return 0;
401 }
402
403
404 /***********************************************************************
405  *              EnumDesktopWindows   (USER32.@)
406  */
407 BOOL WINAPI EnumDesktopWindows( HDESK desktop, WNDENUMPROC func, LPARAM lparam )
408 {
409     FIXME( "(%p,%p,0x%lx): stub!\n", desktop, func, lparam );
410     return TRUE;
411 }
412
413
414 /***********************************************************************
415  *              GetUserObjectInformationA   (USER32.@)
416  */
417 BOOL WINAPI GetUserObjectInformationA( HANDLE handle, INT index, LPVOID info, DWORD len, LPDWORD needed )
418 {
419     /* check for information types returning strings */
420     if (index == UOI_TYPE || index == UOI_NAME)
421     {
422         WCHAR buffer[MAX_PATH];
423         DWORD lenA;
424
425         if (!GetUserObjectInformationW( handle, index, buffer, sizeof(buffer), NULL )) return FALSE;
426         lenA = WideCharToMultiByte( CP_ACP, 0, buffer, -1, NULL, 0, NULL, NULL );
427         if (needed) *needed = lenA;
428         if (lenA > len)
429         {
430             SetLastError( ERROR_MORE_DATA );
431             return FALSE;
432         }
433         if (info) WideCharToMultiByte( CP_ACP, 0, buffer, -1, info, len, NULL, NULL );
434         return TRUE;
435     }
436     return GetUserObjectInformationW( handle, index, info, len, needed );
437 }
438
439
440 /***********************************************************************
441  *              GetUserObjectInformationW   (USER32.@)
442  */
443 BOOL WINAPI GetUserObjectInformationW( HANDLE handle, INT index, LPVOID info, DWORD len, LPDWORD needed )
444 {
445     static const WCHAR desktopW[] = { 'D','e','s','k','t','o','p',0 };
446     static const WCHAR winstationW[] = { 'W','i','n','d','o','w','S','t','a','t','i','o','n',0 };
447     BOOL ret;
448
449     switch(index)
450     {
451     case UOI_FLAGS:
452         {
453             USEROBJECTFLAGS *obj_flags = info;
454             if (needed) *needed = sizeof(*obj_flags);
455             if (len < sizeof(*obj_flags))
456             {
457                 SetLastError( ERROR_BUFFER_OVERFLOW );
458                 return FALSE;
459             }
460             SERVER_START_REQ( set_user_object_info )
461             {
462                 req->handle    = handle;
463                 req->flags     = 0;
464                 ret = !wine_server_call_err( req );
465                 if (ret)
466                 {
467                     /* FIXME: inherit flag */
468                     obj_flags->dwFlags = reply->old_obj_flags;
469                 }
470             }
471             SERVER_END_REQ;
472         }
473         return ret;
474
475     case UOI_TYPE:
476         SERVER_START_REQ( set_user_object_info )
477         {
478             req->handle = handle;
479             req->flags  = 0;
480             ret = !wine_server_call_err( req );
481             if (ret)
482             {
483                 size_t size = reply->is_desktop ? sizeof(desktopW) : sizeof(winstationW);
484                 if (needed) *needed = size;
485                 if (len < size)
486                 {
487                     SetLastError( ERROR_MORE_DATA );
488                     ret = FALSE;
489                 }
490                 else memcpy( info, reply->is_desktop ? desktopW : winstationW, size );
491             }
492         }
493         SERVER_END_REQ;
494         return ret;
495
496     case UOI_NAME:
497         {
498             WCHAR buffer[MAX_PATH];
499             SERVER_START_REQ( set_user_object_info )
500             {
501                 req->handle = handle;
502                 req->flags  = 0;
503                 wine_server_set_reply( req, buffer, sizeof(buffer) - sizeof(WCHAR) );
504                 ret = !wine_server_call_err( req );
505                 if (ret)
506                 {
507                     size_t size = wine_server_reply_size( reply );
508                     buffer[size / sizeof(WCHAR)] = 0;
509                     size += sizeof(WCHAR);
510                     if (needed) *needed = size;
511                     if (len < size)
512                     {
513                         SetLastError( ERROR_MORE_DATA );
514                         ret = FALSE;
515                     }
516                     else memcpy( info, buffer, size );
517                 }
518             }
519             SERVER_END_REQ;
520         }
521         return ret;
522
523     case UOI_USER_SID:
524         FIXME( "not supported index %d\n", index );
525         /* fall through */
526     default:
527         SetLastError( ERROR_INVALID_PARAMETER );
528         return FALSE;
529     }
530 }
531
532
533 /******************************************************************************
534  *              SetUserObjectInformationA   (USER32.@)
535  */
536 BOOL WINAPI SetUserObjectInformationA( HANDLE handle, INT index, LPVOID info, DWORD len )
537 {
538     return SetUserObjectInformationW( handle, index, info, len );
539 }
540
541
542 /******************************************************************************
543  *              SetUserObjectInformationW   (USER32.@)
544  */
545 BOOL WINAPI SetUserObjectInformationW( HANDLE handle, INT index, LPVOID info, DWORD len )
546 {
547     BOOL ret;
548     const USEROBJECTFLAGS *obj_flags = info;
549
550     if (index != UOI_FLAGS || !info || len < sizeof(*obj_flags))
551     {
552         SetLastError( ERROR_INVALID_PARAMETER );
553         return FALSE;
554     }
555     /* FIXME: inherit flag */
556     SERVER_START_REQ( set_user_object_info )
557     {
558         req->handle    = handle;
559         req->flags     = SET_USER_OBJECT_FLAGS;
560         req->obj_flags = obj_flags->dwFlags;
561         ret = !wine_server_call_err( req );
562     }
563     SERVER_END_REQ;
564     return ret;
565 }
566
567
568 /***********************************************************************
569  *              GetUserObjectSecurity   (USER32.@)
570  */
571 BOOL WINAPI GetUserObjectSecurity( HANDLE handle, PSECURITY_INFORMATION info,
572                                    PSECURITY_DESCRIPTOR sid, DWORD len, LPDWORD needed )
573 {
574     FIXME( "(%p %p %p len=%ld %p),stub!\n", handle, info, sid, len, needed );
575     return TRUE;
576 }
577
578 /***********************************************************************
579  *              SetUserObjectSecurity   (USER32.@)
580  */
581 BOOL WINAPI SetUserObjectSecurity( HANDLE handle, PSECURITY_INFORMATION info,
582                                    PSECURITY_DESCRIPTOR sid )
583 {
584     FIXME( "(%p,%p,%p),stub!\n", handle, info, sid );
585     return TRUE;
586 }