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