richedit: Correctly initialize the paraformat structure.
[wine] / dlls / user32 / 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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  *              EnumWindowStationsW  (USER32.@)
208  */
209 BOOL WINAPI EnumWindowStationsW( WINSTAENUMPROCW func, LPARAM lparam )
210 {
211     unsigned int index = 0;
212     WCHAR name[MAX_PATH];
213     BOOL ret = TRUE;
214
215     while (ret)
216     {
217         SERVER_START_REQ( enum_winstation )
218         {
219             req->index = index;
220             wine_server_set_reply( req, name, sizeof(name) );
221             ret = !wine_server_call( req );
222             index = reply->next;
223         }
224         SERVER_END_REQ;
225         if (ret) ret = func( name, lparam );
226     }
227     return ret;
228 }
229
230
231 /***********************************************************************
232  *              CreateDesktopA   (USER32.@)
233  */
234 HDESK WINAPI CreateDesktopA( LPCSTR name, LPCSTR device, LPDEVMODEA devmode,
235                              DWORD flags, ACCESS_MASK access, LPSECURITY_ATTRIBUTES sa )
236 {
237     WCHAR buffer[MAX_PATH];
238
239     if (device || devmode)
240     {
241         SetLastError( ERROR_INVALID_PARAMETER );
242         return 0;
243     }
244     if (!name) return CreateDesktopW( NULL, NULL, NULL, flags, access, sa );
245
246     if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
247     {
248         SetLastError( ERROR_FILENAME_EXCED_RANGE );
249         return 0;
250     }
251     return CreateDesktopW( buffer, NULL, NULL, flags, access, sa );
252 }
253
254
255 /***********************************************************************
256  *              CreateDesktopW   (USER32.@)
257  */
258 HDESK WINAPI CreateDesktopW( LPCWSTR name, LPCWSTR device, LPDEVMODEW devmode,
259                              DWORD flags, ACCESS_MASK access, LPSECURITY_ATTRIBUTES sa )
260 {
261     HANDLE ret;
262     DWORD len = name ? strlenW(name) : 0;
263
264     if (device || devmode)
265     {
266         SetLastError( ERROR_INVALID_PARAMETER );
267         return 0;
268     }
269     if (len >= MAX_PATH)
270     {
271         SetLastError( ERROR_FILENAME_EXCED_RANGE );
272         return 0;
273     }
274     SERVER_START_REQ( create_desktop )
275     {
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;
284     }
285     SERVER_END_REQ;
286     return ret;
287 }
288
289
290 /******************************************************************************
291  *              OpenDesktopA   (USER32.@)
292  */
293 HDESK WINAPI OpenDesktopA( LPCSTR name, DWORD flags, BOOL inherit, ACCESS_MASK access )
294 {
295     WCHAR buffer[MAX_PATH];
296
297     if (!name) return OpenDesktopW( NULL, flags, inherit, access );
298
299     if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
300     {
301         SetLastError( ERROR_FILENAME_EXCED_RANGE );
302         return 0;
303     }
304     return OpenDesktopW( buffer, flags, inherit, access );
305 }
306
307
308 /******************************************************************************
309  *              OpenDesktopW   (USER32.@)
310  */
311 HDESK WINAPI OpenDesktopW( LPCWSTR name, DWORD flags, BOOL inherit, ACCESS_MASK access )
312 {
313     HANDLE ret = 0;
314     DWORD len = name ? strlenW(name) : 0;
315     if (len >= MAX_PATH)
316     {
317         SetLastError( ERROR_FILENAME_EXCED_RANGE );
318         return 0;
319     }
320     SERVER_START_REQ( open_desktop )
321     {
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;
327     }
328     SERVER_END_REQ;
329     return ret;
330 }
331
332
333 /***********************************************************************
334  *              CloseDesktop  (USER32.@)
335  */
336 BOOL WINAPI CloseDesktop( HDESK handle )
337 {
338     BOOL ret;
339     SERVER_START_REQ( close_desktop )
340     {
341         req->handle = handle;
342         ret = !wine_server_call_err( req );
343     }
344     SERVER_END_REQ;
345     return ret;
346 }
347
348
349 /******************************************************************************
350  *              GetThreadDesktop   (USER32.@)
351  */
352 HDESK WINAPI GetThreadDesktop( DWORD thread )
353 {
354     HDESK ret = 0;
355
356     SERVER_START_REQ( get_thread_desktop )
357     {
358         req->tid = thread;
359         if (!wine_server_call_err( req )) ret = reply->handle;
360     }
361     SERVER_END_REQ;
362     return ret;
363 }
364
365
366 /******************************************************************************
367  *              SetThreadDesktop   (USER32.@)
368  */
369 BOOL WINAPI SetThreadDesktop( HDESK handle )
370 {
371     BOOL ret;
372
373     SERVER_START_REQ( set_thread_desktop )
374     {
375         req->handle = handle;
376         ret = !wine_server_call_err( req );
377     }
378     SERVER_END_REQ;
379     if (ret) get_user_thread_info()->desktop = 0;  /* reset the desktop window */
380     return ret;
381 }
382
383
384 /******************************************************************************
385  *              EnumDesktopsA   (USER32.@)
386  */
387 BOOL WINAPI EnumDesktopsA( HWINSTA winsta, DESKTOPENUMPROCA func, LPARAM lparam )
388 {
389     struct enum_proc_lparam data;
390     data.func   = func;
391     data.lparam = lparam;
392     return EnumDesktopsW( winsta, enum_names_WtoA, (LPARAM)&data );
393 }
394
395
396 /******************************************************************************
397  *              EnumDesktopsW   (USER32.@)
398  */
399 BOOL WINAPI EnumDesktopsW( HWINSTA winsta, DESKTOPENUMPROCW func, LPARAM lparam )
400 {
401     unsigned int index = 0;
402     WCHAR name[MAX_PATH];
403     BOOL ret = TRUE;
404
405     while (ret)
406     {
407         SERVER_START_REQ( enum_desktop )
408         {
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;
414         }
415         SERVER_END_REQ;
416         if (ret) ret = func( name, lparam );
417     }
418     return ret;
419 }
420
421
422 /******************************************************************************
423  *              OpenInputDesktop   (USER32.@)
424  */
425 HDESK WINAPI OpenInputDesktop( DWORD flags, BOOL inherit, ACCESS_MASK access )
426 {
427     FIXME( "(%x,%i,%x): stub\n", flags, inherit, access );
428     SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
429     return 0;
430 }
431
432
433 /***********************************************************************
434  *              EnumDesktopWindows   (USER32.@)
435  */
436 BOOL WINAPI EnumDesktopWindows( HDESK desktop, WNDENUMPROC func, LPARAM lparam )
437 {
438     FIXME( "(%p,%p,0x%lx): stub!\n", desktop, func, lparam );
439     return TRUE;
440 }
441
442
443 /***********************************************************************
444  *              GetUserObjectInformationA   (USER32.@)
445  */
446 BOOL WINAPI GetUserObjectInformationA( HANDLE handle, INT index, LPVOID info, DWORD len, LPDWORD needed )
447 {
448     /* check for information types returning strings */
449     if (index == UOI_TYPE || index == UOI_NAME)
450     {
451         WCHAR buffer[MAX_PATH];
452         DWORD lenA;
453
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)
458         {
459             SetLastError( ERROR_MORE_DATA );
460             return FALSE;
461         }
462         if (info) WideCharToMultiByte( CP_ACP, 0, buffer, -1, info, len, NULL, NULL );
463         return TRUE;
464     }
465     return GetUserObjectInformationW( handle, index, info, len, needed );
466 }
467
468
469 /***********************************************************************
470  *              GetUserObjectInformationW   (USER32.@)
471  */
472 BOOL WINAPI GetUserObjectInformationW( HANDLE handle, INT index, LPVOID info, DWORD len, LPDWORD needed )
473 {
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;
477
478     switch(index)
479     {
480     case UOI_FLAGS:
481         {
482             USEROBJECTFLAGS *obj_flags = info;
483             if (needed) *needed = sizeof(*obj_flags);
484             if (len < sizeof(*obj_flags))
485             {
486                 SetLastError( ERROR_BUFFER_OVERFLOW );
487                 return FALSE;
488             }
489             SERVER_START_REQ( set_user_object_info )
490             {
491                 req->handle    = handle;
492                 req->flags     = 0;
493                 ret = !wine_server_call_err( req );
494                 if (ret)
495                 {
496                     /* FIXME: inherit flag */
497                     obj_flags->dwFlags = reply->old_obj_flags;
498                 }
499             }
500             SERVER_END_REQ;
501         }
502         return ret;
503
504     case UOI_TYPE:
505         SERVER_START_REQ( set_user_object_info )
506         {
507             req->handle = handle;
508             req->flags  = 0;
509             ret = !wine_server_call_err( req );
510             if (ret)
511             {
512                 size_t size = reply->is_desktop ? sizeof(desktopW) : sizeof(winstationW);
513                 if (needed) *needed = size;
514                 if (len < size)
515                 {
516                     SetLastError( ERROR_MORE_DATA );
517                     ret = FALSE;
518                 }
519                 else memcpy( info, reply->is_desktop ? desktopW : winstationW, size );
520             }
521         }
522         SERVER_END_REQ;
523         return ret;
524
525     case UOI_NAME:
526         {
527             WCHAR buffer[MAX_PATH];
528             SERVER_START_REQ( set_user_object_info )
529             {
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)
535                 {
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)
541                     {
542                         SetLastError( ERROR_MORE_DATA );
543                         ret = FALSE;
544                     }
545                     else memcpy( info, buffer, size );
546                 }
547             }
548             SERVER_END_REQ;
549         }
550         return ret;
551
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;
558     }
559 }
560
561
562 /******************************************************************************
563  *              SetUserObjectInformationA   (USER32.@)
564  */
565 BOOL WINAPI SetUserObjectInformationA( HANDLE handle, INT index, LPVOID info, DWORD len )
566 {
567     return SetUserObjectInformationW( handle, index, info, len );
568 }
569
570
571 /******************************************************************************
572  *              SetUserObjectInformationW   (USER32.@)
573  */
574 BOOL WINAPI SetUserObjectInformationW( HANDLE handle, INT index, LPVOID info, DWORD len )
575 {
576     BOOL ret;
577     const USEROBJECTFLAGS *obj_flags = info;
578
579     if (index != UOI_FLAGS || !info || len < sizeof(*obj_flags))
580     {
581         SetLastError( ERROR_INVALID_PARAMETER );
582         return FALSE;
583     }
584     /* FIXME: inherit flag */
585     SERVER_START_REQ( set_user_object_info )
586     {
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 );
591     }
592     SERVER_END_REQ;
593     return ret;
594 }
595
596
597 /***********************************************************************
598  *              GetUserObjectSecurity   (USER32.@)
599  */
600 BOOL WINAPI GetUserObjectSecurity( HANDLE handle, PSECURITY_INFORMATION info,
601                                    PSECURITY_DESCRIPTOR sid, DWORD len, LPDWORD needed )
602 {
603     FIXME( "(%p %p %p len=%d %p),stub!\n", handle, info, sid, len, needed );
604     return TRUE;
605 }
606
607 /***********************************************************************
608  *              SetUserObjectSecurity   (USER32.@)
609  */
610 BOOL WINAPI SetUserObjectSecurity( HANDLE handle, PSECURITY_INFORMATION info,
611                                    PSECURITY_DESCRIPTOR sid )
612 {
613     FIXME( "(%p,%p,%p),stub!\n", handle, info, sid );
614     return TRUE;
615 }