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