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