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