* Sync up to trunk head (r65426).
[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: lib/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 /*
125 * Check parameters
126 */
127 if (NULL == WindowStation && Desktops)
128 {
129 WindowStation = GetProcessWindowStation();
130 }
131
132 /*
133 * Try with fixed-size buffer
134 */
135 Status = NtUserBuildNameList(WindowStation, sizeof(Buffer), Buffer, &RequiredSize);
136 if (NT_SUCCESS(Status))
137 {
138 /* Fixed-size buffer is large enough */
139 NameList = (PWCHAR) Buffer;
140 }
141 else if (Status == STATUS_BUFFER_TOO_SMALL)
142 {
143 /* Allocate a larger buffer */
144 NameList = HeapAlloc(GetProcessHeap(), 0, RequiredSize);
145 if (NULL == NameList)
146 {
147 return FALSE;
148 }
149 /* Try again */
150 Status = NtUserBuildNameList(WindowStation, RequiredSize, NameList, NULL);
151 if (! NT_SUCCESS(Status))
152 {
153 HeapFree(GetProcessHeap(), 0, NameList);
154 SetLastError(RtlNtStatusToDosError(Status));
155 return FALSE;
156 }
157 }
158 else
159 {
160 /* Some unrecognized error occured */
161 SetLastError(RtlNtStatusToDosError(Status));
162 return FALSE;
163 }
164
165 /*
166 * Enum the names one by one
167 */
168 EntryCount = *((DWORD *) NameList);
169 Name = (PWCHAR) ((PCHAR) NameList + sizeof(DWORD));
170 Ret = TRUE;
171 for (CurrentEntry = 0; CurrentEntry < EntryCount && Ret; ++CurrentEntry)
172 {
173 Ret = (*EnumFunc)(Name, Context);
174 Name += wcslen(Name) + 1;
175 }
176
177 /*
178 * Cleanup
179 */
180 if (NameList != Buffer)
181 {
182 HeapFree(GetProcessHeap(), 0, NameList);
183 }
184
185 return Ret;
186 }
187
188
189 /* For W->A conversion */
190 typedef struct tagENUMNAMESASCIICONTEXT
191 {
192 NAMEENUMPROCA UserEnumFunc;
193 LPARAM UserContext;
194 } ENUMNAMESASCIICONTEXT, *PENUMNAMESASCIICONTEXT;
195
196 /*
197 * Callback used by Ascii versions. Converts the Unicode name to
198 * Ascii and then calls the user callback
199 */
200 BOOL CALLBACK
201 EnumNamesCallback(LPWSTR Name, LPARAM Param)
202 {
203 PENUMNAMESASCIICONTEXT Context = (PENUMNAMESASCIICONTEXT) Param;
204 char FixedNameA[32];
205 LPSTR NameA;
206 int Len;
207 BOOL Ret;
208
209 /*
210 * Determine required size of Ascii string and see if we can use
211 * fixed buffer
212 */
213 Len = WideCharToMultiByte(CP_ACP, 0, Name, -1, NULL, 0, NULL, NULL);
214 if (Len <= 0)
215 {
216 /* Some strange error occured */
217 return FALSE;
218 }
219 else if (Len <= sizeof(FixedNameA))
220 {
221 /* Fixed-size buffer is large enough */
222 NameA = FixedNameA;
223 }
224 else
225 {
226 /* Allocate a larger buffer */
227 NameA = HeapAlloc(GetProcessHeap(), 0, Len);
228 if (NULL == NameA)
229 {
230 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
231 return FALSE;
232 }
233 }
234
235 /*
236 * Do the Unicode ->Ascii conversion
237 */
238 if (0 == WideCharToMultiByte(CP_ACP, 0, Name, -1, NameA, Len, NULL, NULL))
239 {
240 /* Something went wrong, clean up */
241 if (NameA != FixedNameA)
242 {
243 HeapFree(GetProcessHeap(), 0, NameA);
244 }
245 return FALSE;
246 }
247
248 /*
249 * Call user callback
250 */
251 Ret = Context->UserEnumFunc(NameA, Context->UserContext);
252
253 /*
254 * Clean up
255 */
256 if (NameA != FixedNameA)
257 {
258 HeapFree(GetProcessHeap(), 0, NameA);
259 }
260
261 return Ret;
262 }
263
264 /*
265 * Common code for EnumDesktopsA and EnumWindowStationsA
266 */
267 BOOL FASTCALL
268 EnumNamesA(HWINSTA WindowStation,
269 NAMEENUMPROCA EnumFunc,
270 LPARAM Context,
271 BOOL Desktops)
272 {
273 ENUMNAMESASCIICONTEXT PrivateContext;
274
275 PrivateContext.UserEnumFunc = EnumFunc;
276 PrivateContext.UserContext = Context;
277
278 return EnumNamesW(WindowStation, EnumNamesCallback, (LPARAM) &PrivateContext, Desktops);
279 }
280
281 /*
282 * @implemented
283 */
284 BOOL WINAPI
285 EnumWindowStationsA(WINSTAENUMPROCA EnumFunc,
286 LPARAM Context)
287 {
288 return EnumNamesA(NULL, EnumFunc, Context, FALSE);
289 }
290
291
292 /*
293 * @implemented
294 */
295 BOOL WINAPI
296 EnumWindowStationsW(WINSTAENUMPROCW EnumFunc,
297 LPARAM Context)
298 {
299 return EnumNamesW(NULL, EnumFunc, Context, FALSE);
300 }
301
302
303 /*
304 * @implemented
305 */
306 HWINSTA WINAPI
307 OpenWindowStationA(LPCSTR lpszWinSta,
308 BOOL fInherit,
309 ACCESS_MASK dwDesiredAccess)
310 {
311 UNICODE_STRING WindowStationNameU;
312 HWINSTA hWinSta;
313
314 if (lpszWinSta)
315 {
316 /* After conversion, the buffer is zero-terminated */
317 RtlCreateUnicodeStringFromAsciiz(&WindowStationNameU, lpszWinSta);
318 }
319 else
320 {
321 RtlInitUnicodeString(&WindowStationNameU, NULL);
322 }
323
324 hWinSta = OpenWindowStationW(WindowStationNameU.Buffer,
325 fInherit,
326 dwDesiredAccess);
327
328 /* Free the string, if it was allocated */
329 if (lpszWinSta) RtlFreeUnicodeString(&WindowStationNameU);
330
331 return hWinSta;
332 }
333
334
335 /*
336 * @implemented
337 */
338 HWINSTA WINAPI
339 OpenWindowStationW(LPCWSTR lpszWinSta,
340 BOOL fInherit,
341 ACCESS_MASK dwDesiredAccess)
342 {
343 UNICODE_STRING WindowStationName;
344 UNICODE_STRING WindowStationsDir = RTL_CONSTANT_STRING(L"\\Windows\\WindowStations");
345 OBJECT_ATTRIBUTES ObjectAttributes;
346 HANDLE hWindowStationsDir;
347 NTSTATUS Status;
348 HWINSTA hwinsta;
349
350 /* Open WindowStations directory */
351 InitializeObjectAttributes(&ObjectAttributes,
352 &WindowStationsDir,
353 OBJ_CASE_INSENSITIVE,
354 0,
355 0);
356
357 Status = NtOpenDirectoryObject(&hWindowStationsDir,
358 DIRECTORY_TRAVERSE,
359 &ObjectAttributes);
360 if(!NT_SUCCESS(Status))
361 {
362 ERR("Failed to open WindowStations directory\n");
363 return NULL;
364 }
365
366 /* Open the window station object */
367 RtlInitUnicodeString(&WindowStationName, lpszWinSta);
368
369 InitializeObjectAttributes(&ObjectAttributes,
370 &WindowStationName,
371 OBJ_CASE_INSENSITIVE,
372 hWindowStationsDir,
373 0);
374
375 if( fInherit )
376 {
377 ObjectAttributes.Attributes |= OBJ_INHERIT;
378 }
379
380 hwinsta = NtUserOpenWindowStation(&ObjectAttributes, dwDesiredAccess);
381
382 NtClose(hWindowStationsDir);
383
384 return hwinsta;
385 }
386
387
388 /*
389 * @unimplemented
390 */
391 DWORD
392 WINAPI
393 SetWindowStationUser(
394 DWORD Unknown1,
395 DWORD Unknown2,
396 DWORD Unknown3,
397 DWORD Unknown4
398 )
399 {
400 return NtUserSetWindowStationUser(Unknown1, Unknown2, Unknown3, Unknown4);
401 }
402
403 /* EOF */
404