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
11 WINE_DEFAULT_DEBUG_CHANNEL(winsta
);
19 IN LPCSTR lpwinsta OPTIONAL
,
21 IN ACCESS_MASK dwDesiredAccess
,
22 IN LPSECURITY_ATTRIBUTES lpsa OPTIONAL
)
25 UNICODE_STRING WindowStationNameU
;
29 /* After conversion, the buffer is zero-terminated */
30 RtlCreateUnicodeStringFromAsciiz(&WindowStationNameU
, lpwinsta
);
34 RtlInitUnicodeString(&WindowStationNameU
, NULL
);
37 hWinSta
= CreateWindowStationW(WindowStationNameU
.Buffer
,
42 /* Free the string if it was allocated */
43 if (lpwinsta
) RtlFreeUnicodeString(&WindowStationNameU
);
55 IN LPCWSTR lpwinsta OPTIONAL
,
57 IN ACCESS_MASK dwDesiredAccess
,
58 IN LPSECURITY_ATTRIBUTES lpsa OPTIONAL
)
62 UNICODE_STRING WindowStationName
;
63 // FIXME: We should cache a per-session directory (see ntuser\winsta.c!UserCreateWinstaDirectory).
64 UNICODE_STRING WindowStationsDir
= RTL_CONSTANT_STRING(L
"\\Windows\\WindowStations");
65 OBJECT_ATTRIBUTES ObjectAttributes
;
66 HANDLE hWindowStationsDir
;
69 * If provided, the window station name is always relative to the
70 * current user session's WindowStations directory.
71 * Otherwise (the window station name is NULL or an empty string),
72 * pass both an empty string and no WindowStations directory handle
73 * to win32k, so that it will create a window station whose name
74 * is based on the logon session identifier for the calling process.
76 if (lpwinsta
&& *lpwinsta
)
78 /* Open WindowStations directory */
79 InitializeObjectAttributes(&ObjectAttributes
,
85 Status
= NtOpenDirectoryObject(&hWindowStationsDir
,
86 DIRECTORY_CREATE_OBJECT
,
88 if (!NT_SUCCESS(Status
))
90 ERR("Failed to open WindowStations directory\n");
94 RtlInitUnicodeString(&WindowStationName
, lpwinsta
);
99 hWindowStationsDir
= NULL
;
102 /* Create the window station object */
103 InitializeObjectAttributes(&ObjectAttributes
,
104 lpwinsta
? &WindowStationName
: NULL
,
105 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
,
109 /* Check if the handle should be inheritable */
110 if (lpsa
&& lpsa
->bInheritHandle
)
112 ObjectAttributes
.Attributes
|= OBJ_INHERIT
;
115 hWinSta
= NtUserCreateWindowStation(&ObjectAttributes
,
119 if (hWindowStationsDir
)
120 NtClose(hWindowStationsDir
);
126 * Common code for EnumDesktopsA/W and EnumWindowStationsA/W
130 EnumNamesW(HWINSTA WindowStation
,
131 NAMEENUMPROCW EnumFunc
,
140 ULONG CurrentEntry
, EntryCount
;
143 /* Check parameters */
144 if (WindowStation
== NULL
&& Desktops
)
146 WindowStation
= GetProcessWindowStation();
149 /* Try with fixed-size buffer */
150 Status
= NtUserBuildNameList(WindowStation
, sizeof(Buffer
), Buffer
, &RequiredSize
);
151 if (NT_SUCCESS(Status
))
153 /* Fixed-size buffer is large enough */
154 NameList
= (PWCHAR
) Buffer
;
156 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
158 /* Allocate a larger buffer */
159 NameList
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
);
160 if (NameList
== NULL
)
164 Status
= NtUserBuildNameList(WindowStation
, RequiredSize
, NameList
, NULL
);
165 if (!NT_SUCCESS(Status
))
167 HeapFree(GetProcessHeap(), 0, NameList
);
168 SetLastError(RtlNtStatusToDosError(Status
));
174 /* Some unrecognized error occured */
175 SetLastError(RtlNtStatusToDosError(Status
));
179 /* Enum the names one by one */
180 EntryCount
= *((DWORD
*) NameList
);
181 Name
= (PWCHAR
) ((PCHAR
) NameList
+ sizeof(DWORD
));
183 for (CurrentEntry
= 0; CurrentEntry
< EntryCount
&& Ret
; ++CurrentEntry
)
185 Ret
= (*EnumFunc
)(Name
, Context
);
186 Name
+= wcslen(Name
) + 1;
190 if (NameList
!= Buffer
)
192 HeapFree(GetProcessHeap(), 0, NameList
);
198 /* For W->A conversion */
199 typedef struct tagENUMNAMESASCIICONTEXT
201 NAMEENUMPROCA UserEnumFunc
;
203 } ENUMNAMESASCIICONTEXT
, *PENUMNAMESASCIICONTEXT
;
206 * Callback used by Ascii versions. Converts the Unicode name to
207 * Ascii and then calls the user callback
211 EnumNamesCallback(LPWSTR Name
, LPARAM Param
)
213 PENUMNAMESASCIICONTEXT Context
= (PENUMNAMESASCIICONTEXT
) Param
;
220 * Determine required size of Ascii string and see
221 * if we can use fixed buffer.
223 Len
= WideCharToMultiByte(CP_ACP
, 0, Name
, -1, NULL
, 0, NULL
, NULL
);
226 /* Some strange error occured */
229 else if (Len
<= sizeof(FixedNameA
))
231 /* Fixed-size buffer is large enough */
236 /* Allocate a larger buffer */
237 NameA
= HeapAlloc(GetProcessHeap(), 0, Len
);
240 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
245 /* Do the Unicode ->Ascii conversion */
246 if (0 == WideCharToMultiByte(CP_ACP
, 0, Name
, -1, NameA
, Len
, NULL
, NULL
))
248 /* Something went wrong, clean up */
249 if (NameA
!= FixedNameA
)
251 HeapFree(GetProcessHeap(), 0, NameA
);
256 /* Call user callback */
257 Ret
= Context
->UserEnumFunc(NameA
, Context
->UserContext
);
260 if (NameA
!= FixedNameA
)
262 HeapFree(GetProcessHeap(), 0, NameA
);
269 * Common code for EnumDesktopsA and EnumWindowStationsA
273 EnumNamesA(HWINSTA WindowStation
,
274 NAMEENUMPROCA EnumFunc
,
278 ENUMNAMESASCIICONTEXT PrivateContext
;
280 PrivateContext
.UserEnumFunc
= EnumFunc
;
281 PrivateContext
.UserContext
= Context
;
283 return EnumNamesW(WindowStation
, EnumNamesCallback
, (LPARAM
) &PrivateContext
, Desktops
);
292 IN WINSTAENUMPROCA EnumFunc
,
295 return EnumNamesA(NULL
, EnumFunc
, Context
, FALSE
);
305 IN WINSTAENUMPROCW EnumFunc
,
308 return EnumNamesW(NULL
, EnumFunc
, Context
, FALSE
);
313 * @unimplemented on Win32k side
317 GetWinStationInfo(PVOID pUnknown
)
319 return (BOOL
)NtUserCallOneParam((DWORD_PTR
)pUnknown
, ONEPARAM_ROUTINE_GETWINSTAINFO
);
329 IN LPCSTR lpszWinSta
,
331 IN ACCESS_MASK dwDesiredAccess
)
334 UNICODE_STRING WindowStationNameU
;
338 /* After conversion, the buffer is zero-terminated */
339 RtlCreateUnicodeStringFromAsciiz(&WindowStationNameU
, lpszWinSta
);
343 RtlInitUnicodeString(&WindowStationNameU
, NULL
);
346 hWinSta
= OpenWindowStationW(WindowStationNameU
.Buffer
,
350 /* Free the string if it was allocated */
351 if (lpszWinSta
) RtlFreeUnicodeString(&WindowStationNameU
);
363 IN LPCWSTR lpszWinSta
,
365 IN ACCESS_MASK dwDesiredAccess
)
369 UNICODE_STRING WindowStationName
;
370 // FIXME: We should cache a per-session directory (see ntuser\winsta.c!UserCreateWinstaDirectory).
371 UNICODE_STRING WindowStationsDir
= RTL_CONSTANT_STRING(L
"\\Windows\\WindowStations");
372 OBJECT_ATTRIBUTES ObjectAttributes
;
373 HANDLE hWindowStationsDir
;
375 /* Open WindowStations directory */
376 InitializeObjectAttributes(&ObjectAttributes
,
378 OBJ_CASE_INSENSITIVE
,
382 Status
= NtOpenDirectoryObject(&hWindowStationsDir
,
385 if(!NT_SUCCESS(Status
))
387 ERR("Failed to open WindowStations directory\n");
391 /* Open the window station object */
392 RtlInitUnicodeString(&WindowStationName
, lpszWinSta
);
394 InitializeObjectAttributes(&ObjectAttributes
,
396 OBJ_CASE_INSENSITIVE
,
400 /* Check if the handle should be inheritable */
403 ObjectAttributes
.Attributes
|= OBJ_INHERIT
;
406 hWinSta
= NtUserOpenWindowStation(&ObjectAttributes
, dwDesiredAccess
);
408 NtClose(hWindowStationsDir
);
419 SetWindowStationUser(
420 IN HWINSTA hWindowStation
,
422 IN PSID psid OPTIONAL
,
427 Success
= NtUserSetWindowStationUser(hWindowStation
, pluid
, psid
, size
);
430 /* Signal log-on/off to WINSRV */
432 /* User is logging on if *pluid != LuidNone, otherwise it is a log-off */
433 LUID LuidNone
= {0, 0};
434 BOOL IsLogon
= (pluid
&& !RtlEqualLuid(pluid
, &LuidNone
));