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