[USER32] Add wine/debug.h to the PCH and remove an unneeded wine/unicode.h inclusion.
[reactos.git] / win32ss / user / user32 / misc / winsta.c
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 */