xref: /reactos/win32ss/user/user32/misc/winsta.c (revision 595b846d)
1 /*
2  * COPYRIGHT:       See COPYING in the top level directory
3  * PROJECT:         ReactOS user32.dll
4  * FILE:            win32ss/user/user32/misc/winsta.c
5  * PURPOSE:         Window stations
6  * PROGRAMMER:      Casper S. Hornstrup (chorns@users.sourceforge.net)
7  * UPDATE HISTORY:
8  *      04-06-2001  CSH  Created
9  */
10 
11 #include <user32.h>
12 
13 WINE_DEFAULT_DEBUG_CHANNEL(winsta);
14 
15 /*
16  * @implemented
17  */
18 HWINSTA WINAPI
19 CreateWindowStationA(LPCSTR lpwinsta,
20                      DWORD dwReserved,
21                      ACCESS_MASK dwDesiredAccess,
22                      LPSECURITY_ATTRIBUTES lpsa)
23 {
24     UNICODE_STRING WindowStationNameU;
25     HWINSTA hWinSta;
26 
27     if (lpwinsta)
28     {
29         /* After conversion, the buffer is zero-terminated */
30         RtlCreateUnicodeStringFromAsciiz(&WindowStationNameU, lpwinsta);
31     }
32     else
33     {
34         RtlInitUnicodeString(&WindowStationNameU, NULL);
35     }
36 
37     hWinSta = CreateWindowStationW(WindowStationNameU.Buffer,
38                                    dwReserved,
39                                    dwDesiredAccess,
40                                    lpsa);
41 
42     /* Free the string, if it was allocated */
43     if (lpwinsta) RtlFreeUnicodeString(&WindowStationNameU);
44 
45     return hWinSta;
46 }
47 
48 
49 /*
50  * @implemented
51  */
52 HWINSTA WINAPI
53 CreateWindowStationW(LPCWSTR lpwinsta,
54                      DWORD dwReserved,
55                      ACCESS_MASK dwDesiredAccess,
56                      LPSECURITY_ATTRIBUTES lpsa)
57 {
58     UNICODE_STRING WindowStationName;
59     UNICODE_STRING WindowStationsDir = RTL_CONSTANT_STRING(L"\\Windows\\WindowStations");
60     OBJECT_ATTRIBUTES ObjectAttributes;
61     HANDLE hWindowStationsDir;
62     NTSTATUS Status;
63     HWINSTA hwinsta;
64 
65     /* Open WindowStations directory */
66     InitializeObjectAttributes(&ObjectAttributes,
67                                &WindowStationsDir,
68                                OBJ_CASE_INSENSITIVE,
69                                0,
70                                0);
71 
72     Status = NtOpenDirectoryObject(&hWindowStationsDir,
73                                    DIRECTORY_CREATE_OBJECT,
74                                    &ObjectAttributes);
75     if(!NT_SUCCESS(Status))
76     {
77         ERR("Failed to open WindowStations directory\n");
78         return NULL;
79     }
80 
81     RtlInitUnicodeString(&WindowStationName, lpwinsta);
82 
83     /* Create the window station object */
84     InitializeObjectAttributes(&ObjectAttributes,
85                                &WindowStationName,
86                                OBJ_CASE_INSENSITIVE,
87                                hWindowStationsDir,
88                                0);
89 
90     /* Check if the handle should be inheritable */
91     if (lpsa && lpsa->bInheritHandle)
92     {
93         ObjectAttributes.Attributes |= OBJ_INHERIT;
94     }
95 
96     hwinsta = NtUserCreateWindowStation(&ObjectAttributes,
97                                         dwDesiredAccess,
98                                         0, 0, 0, 0, 0);
99 
100     NtClose(hWindowStationsDir);
101 
102     return hwinsta;
103 }
104 
105 /*
106  * Common code for EnumDesktopsA/W and EnumWindowStationsA/W
107  */
108 BOOL FASTCALL
109 EnumNamesW(HWINSTA WindowStation,
110            NAMEENUMPROCW EnumFunc,
111            LPARAM Context,
112            BOOL Desktops)
113 {
114     CHAR Buffer[256];
115     PVOID NameList;
116     PWCHAR Name;
117     NTSTATUS Status;
118     ULONG RequiredSize;
119     ULONG CurrentEntry, EntryCount;
120     BOOL Ret;
121 
122     /* Check parameters */
123     if (WindowStation == NULL && Desktops)
124     {
125         WindowStation = GetProcessWindowStation();
126     }
127 
128     /* Try with fixed-size buffer */
129     Status = NtUserBuildNameList(WindowStation, sizeof(Buffer), Buffer, &RequiredSize);
130     if (NT_SUCCESS(Status))
131     {
132         /* Fixed-size buffer is large enough */
133         NameList = (PWCHAR) Buffer;
134     }
135     else if (Status == STATUS_BUFFER_TOO_SMALL)
136     {
137         /* Allocate a larger buffer */
138         NameList = HeapAlloc(GetProcessHeap(), 0, RequiredSize);
139         if (NameList == NULL)
140             return FALSE;
141 
142         /* Try again */
143         Status = NtUserBuildNameList(WindowStation, RequiredSize, NameList, NULL);
144         if (!NT_SUCCESS(Status))
145         {
146             HeapFree(GetProcessHeap(), 0, NameList);
147             SetLastError(RtlNtStatusToDosError(Status));
148             return FALSE;
149         }
150     }
151     else
152     {
153         /* Some unrecognized error occured */
154         SetLastError(RtlNtStatusToDosError(Status));
155         return FALSE;
156     }
157 
158     /* Enum the names one by one */
159     EntryCount = *((DWORD *) NameList);
160     Name = (PWCHAR) ((PCHAR) NameList + sizeof(DWORD));
161     Ret = TRUE;
162     for (CurrentEntry = 0; CurrentEntry < EntryCount && Ret; ++CurrentEntry)
163     {
164         Ret = (*EnumFunc)(Name, Context);
165         Name += wcslen(Name) + 1;
166     }
167 
168     /* Cleanup */
169     if (NameList != Buffer)
170     {
171         HeapFree(GetProcessHeap(), 0, NameList);
172     }
173 
174     return Ret;
175 }
176 
177 
178 /* For W->A conversion */
179 typedef struct tagENUMNAMESASCIICONTEXT
180 {
181     NAMEENUMPROCA UserEnumFunc;
182     LPARAM UserContext;
183 } ENUMNAMESASCIICONTEXT, *PENUMNAMESASCIICONTEXT;
184 
185 /*
186  * Callback used by Ascii versions. Converts the Unicode name to
187  * Ascii and then calls the user callback
188  */
189 BOOL CALLBACK
190 EnumNamesCallback(LPWSTR Name, LPARAM Param)
191 {
192     PENUMNAMESASCIICONTEXT Context = (PENUMNAMESASCIICONTEXT) Param;
193     CHAR FixedNameA[32];
194     LPSTR NameA;
195     INT Len;
196     BOOL Ret;
197 
198     /*
199      * Determine required size of Ascii string and see
200      * if we can use fixed buffer.
201      */
202     Len = WideCharToMultiByte(CP_ACP, 0, Name, -1, NULL, 0, NULL, NULL);
203     if (Len <= 0)
204     {
205         /* Some strange error occured */
206         return FALSE;
207     }
208     else if (Len <= sizeof(FixedNameA))
209     {
210         /* Fixed-size buffer is large enough */
211         NameA = FixedNameA;
212     }
213     else
214     {
215         /* Allocate a larger buffer */
216         NameA = HeapAlloc(GetProcessHeap(), 0, Len);
217         if (NULL == NameA)
218         {
219             SetLastError(ERROR_NOT_ENOUGH_MEMORY);
220             return FALSE;
221         }
222     }
223 
224     /* Do the Unicode ->Ascii conversion */
225     if (0 == WideCharToMultiByte(CP_ACP, 0, Name, -1, NameA, Len, NULL, NULL))
226     {
227         /* Something went wrong, clean up */
228         if (NameA != FixedNameA)
229         {
230             HeapFree(GetProcessHeap(), 0, NameA);
231         }
232         return FALSE;
233     }
234 
235     /* Call user callback */
236     Ret = Context->UserEnumFunc(NameA, Context->UserContext);
237 
238     /* Cleanup */
239     if (NameA != FixedNameA)
240     {
241         HeapFree(GetProcessHeap(), 0, NameA);
242     }
243 
244     return Ret;
245 }
246 
247 /*
248  * Common code for EnumDesktopsA and EnumWindowStationsA
249  */
250 BOOL FASTCALL
251 EnumNamesA(HWINSTA WindowStation,
252            NAMEENUMPROCA EnumFunc,
253            LPARAM Context,
254            BOOL Desktops)
255 {
256     ENUMNAMESASCIICONTEXT PrivateContext;
257 
258     PrivateContext.UserEnumFunc = EnumFunc;
259     PrivateContext.UserContext = Context;
260 
261     return EnumNamesW(WindowStation, EnumNamesCallback, (LPARAM) &PrivateContext, Desktops);
262 }
263 
264 /*
265  * @implemented
266  */
267 BOOL WINAPI
268 EnumWindowStationsA(WINSTAENUMPROCA EnumFunc,
269                     LPARAM Context)
270 {
271     return EnumNamesA(NULL, EnumFunc, Context, FALSE);
272 }
273 
274 
275 /*
276  * @implemented
277  */
278 BOOL WINAPI
279 EnumWindowStationsW(WINSTAENUMPROCW EnumFunc,
280                     LPARAM Context)
281 {
282     return EnumNamesW(NULL, EnumFunc, Context, FALSE);
283 }
284 
285 
286 /*
287  * @unimplemented on Win32k side
288  */
289 BOOL WINAPI
290 GetWinStationInfo(PVOID pUnknown)
291 {
292     return (BOOL)NtUserCallOneParam((DWORD_PTR)pUnknown, ONEPARAM_ROUTINE_GETWINSTAINFO);
293 }
294 
295 
296 /*
297  * @implemented
298  */
299 HWINSTA WINAPI
300 OpenWindowStationA(LPCSTR lpszWinSta,
301                    BOOL fInherit,
302                    ACCESS_MASK dwDesiredAccess)
303 {
304     UNICODE_STRING WindowStationNameU;
305     HWINSTA hWinSta;
306 
307     if (lpszWinSta)
308     {
309         /* After conversion, the buffer is zero-terminated */
310         RtlCreateUnicodeStringFromAsciiz(&WindowStationNameU, lpszWinSta);
311     }
312     else
313     {
314         RtlInitUnicodeString(&WindowStationNameU, NULL);
315     }
316 
317     hWinSta = OpenWindowStationW(WindowStationNameU.Buffer,
318                                  fInherit,
319                                  dwDesiredAccess);
320 
321     /* Free the string, if it was allocated */
322     if (lpszWinSta) RtlFreeUnicodeString(&WindowStationNameU);
323 
324     return hWinSta;
325 }
326 
327 
328 /*
329  * @implemented
330  */
331 HWINSTA WINAPI
332 OpenWindowStationW(LPCWSTR lpszWinSta,
333                    BOOL fInherit,
334                    ACCESS_MASK dwDesiredAccess)
335 {
336     UNICODE_STRING WindowStationName;
337     UNICODE_STRING WindowStationsDir = RTL_CONSTANT_STRING(L"\\Windows\\WindowStations");
338     OBJECT_ATTRIBUTES ObjectAttributes;
339     HANDLE hWindowStationsDir;
340     NTSTATUS Status;
341     HWINSTA hwinsta;
342 
343     /* Open WindowStations directory */
344     InitializeObjectAttributes(&ObjectAttributes,
345                                &WindowStationsDir,
346                                OBJ_CASE_INSENSITIVE,
347                                0,
348                                0);
349 
350     Status = NtOpenDirectoryObject(&hWindowStationsDir,
351                                    DIRECTORY_TRAVERSE,
352                                    &ObjectAttributes);
353     if(!NT_SUCCESS(Status))
354     {
355         ERR("Failed to open WindowStations directory\n");
356         return NULL;
357     }
358 
359     /* Open the window station object */
360     RtlInitUnicodeString(&WindowStationName, lpszWinSta);
361 
362     InitializeObjectAttributes(&ObjectAttributes,
363                                &WindowStationName,
364                                OBJ_CASE_INSENSITIVE,
365                                hWindowStationsDir,
366                                0);
367 
368     if(fInherit)
369     {
370         ObjectAttributes.Attributes |= OBJ_INHERIT;
371     }
372 
373     hwinsta = NtUserOpenWindowStation(&ObjectAttributes, dwDesiredAccess);
374 
375     NtClose(hWindowStationsDir);
376 
377     return hwinsta;
378 }
379 
380 
381 /*
382  * @implemented
383  */
384 BOOL
385 WINAPI
386 SetWindowStationUser(HWINSTA hWindowStation,
387                      PLUID pluid,
388                      PSID psid,
389                      DWORD size)
390 {
391     BOOL Success;
392 
393     Success = NtUserSetWindowStationUser(hWindowStation, pluid, psid, size);
394     if (Success)
395     {
396         /* Signal log-on/off to WINSRV */
397 
398         /* User is logging on if pluid != LuidNone, otherwise it is a log-off */
399         LUID LuidNone = {0, 0};
400         BOOL IsLogon = (pluid && !RtlEqualLuid(pluid, &LuidNone));
401 
402         Logon(IsLogon);
403     }
404 
405     return Success;
406 }
407 
408 /* EOF */
409