ReactOS  0.4.14-dev-52-g6116262
winsta.c
Go to the documentation of this file.
1 /*
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
7  */
8 
9 #include <user32.h>
10 
12 
13 /*
14  * @implemented
15  */
16 HWINSTA
17 WINAPI
19  IN LPCSTR lpwinsta OPTIONAL,
21  IN ACCESS_MASK dwDesiredAccess,
23 {
24  HWINSTA hWinSta;
25  UNICODE_STRING WindowStationNameU;
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
53 WINAPI
55  IN LPCWSTR lpwinsta OPTIONAL,
57  IN ACCESS_MASK dwDesiredAccess,
59 {
61  HWINSTA hWinSta;
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");
66  HANDLE hWindowStationsDir;
67 
68  /*
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.
75  */
76  if (lpwinsta && *lpwinsta)
77  {
78  /* Open WindowStations directory */
80  &WindowStationsDir,
82  NULL,
83  NULL);
84 
85  Status = NtOpenDirectoryObject(&hWindowStationsDir,
88  if (!NT_SUCCESS(Status))
89  {
90  ERR("Failed to open WindowStations directory\n");
91  return NULL;
92  }
93 
94  RtlInitUnicodeString(&WindowStationName, lpwinsta);
95  }
96  else
97  {
98  lpwinsta = NULL;
99  hWindowStationsDir = NULL;
100  }
101 
102  /* Create the window station object */
104  lpwinsta ? &WindowStationName : NULL,
106  hWindowStationsDir,
107  NULL);
108 
109  /* Check if the handle should be inheritable */
110  if (lpsa && lpsa->bInheritHandle)
111  {
112  ObjectAttributes.Attributes |= OBJ_INHERIT;
113  }
114 
116  dwDesiredAccess,
117  0, 0, 0, 0, 0);
118 
119  if (hWindowStationsDir)
120  NtClose(hWindowStationsDir);
121 
122  return hWinSta;
123 }
124 
125 /*
126  * Common code for EnumDesktopsA/W and EnumWindowStationsA/W
127  */
128 BOOL
129 FASTCALL
130 EnumNamesW(HWINSTA WindowStation,
132  LPARAM Context,
133  BOOL Desktops)
134 {
135  CHAR Buffer[256];
136  PVOID NameList;
137  PWCHAR Name;
140  ULONG CurrentEntry, EntryCount;
141  BOOL Ret;
142 
143  /* Check parameters */
144  if (WindowStation == NULL && Desktops)
145  {
146  WindowStation = GetProcessWindowStation();
147  }
148 
149  /* Try with fixed-size buffer */
150  Status = NtUserBuildNameList(WindowStation, sizeof(Buffer), Buffer, &RequiredSize);
151  if (NT_SUCCESS(Status))
152  {
153  /* Fixed-size buffer is large enough */
154  NameList = (PWCHAR) Buffer;
155  }
156  else if (Status == STATUS_BUFFER_TOO_SMALL)
157  {
158  /* Allocate a larger buffer */
159  NameList = HeapAlloc(GetProcessHeap(), 0, RequiredSize);
160  if (NameList == NULL)
161  return FALSE;
162 
163  /* Try again */
164  Status = NtUserBuildNameList(WindowStation, RequiredSize, NameList, NULL);
165  if (!NT_SUCCESS(Status))
166  {
167  HeapFree(GetProcessHeap(), 0, NameList);
169  return FALSE;
170  }
171  }
172  else
173  {
174  /* Some unrecognized error occured */
176  return FALSE;
177  }
178 
179  /* Enum the names one by one */
180  EntryCount = *((DWORD *) NameList);
181  Name = (PWCHAR) ((PCHAR) NameList + sizeof(DWORD));
182  Ret = TRUE;
183  for (CurrentEntry = 0; CurrentEntry < EntryCount && Ret; ++CurrentEntry)
184  {
185  Ret = (*EnumFunc)(Name, Context);
186  Name += wcslen(Name) + 1;
187  }
188 
189  /* Cleanup */
190  if (NameList != Buffer)
191  {
192  HeapFree(GetProcessHeap(), 0, NameList);
193  }
194 
195  return Ret;
196 }
197 
198 /* For W->A conversion */
200 {
204 
205 /*
206  * Callback used by Ascii versions. Converts the Unicode name to
207  * Ascii and then calls the user callback
208  */
209 BOOL
210 CALLBACK
212 {
214  CHAR FixedNameA[32];
215  LPSTR NameA;
216  INT Len;
217  BOOL Ret;
218 
219  /*
220  * Determine required size of Ascii string and see
221  * if we can use fixed buffer.
222  */
223  Len = WideCharToMultiByte(CP_ACP, 0, Name, -1, NULL, 0, NULL, NULL);
224  if (Len <= 0)
225  {
226  /* Some strange error occured */
227  return FALSE;
228  }
229  else if (Len <= sizeof(FixedNameA))
230  {
231  /* Fixed-size buffer is large enough */
232  NameA = FixedNameA;
233  }
234  else
235  {
236  /* Allocate a larger buffer */
237  NameA = HeapAlloc(GetProcessHeap(), 0, Len);
238  if (NULL == NameA)
239  {
241  return FALSE;
242  }
243  }
244 
245  /* Do the Unicode ->Ascii conversion */
246  if (0 == WideCharToMultiByte(CP_ACP, 0, Name, -1, NameA, Len, NULL, NULL))
247  {
248  /* Something went wrong, clean up */
249  if (NameA != FixedNameA)
250  {
251  HeapFree(GetProcessHeap(), 0, NameA);
252  }
253  return FALSE;
254  }
255 
256  /* Call user callback */
257  Ret = Context->UserEnumFunc(NameA, Context->UserContext);
258 
259  /* Cleanup */
260  if (NameA != FixedNameA)
261  {
262  HeapFree(GetProcessHeap(), 0, NameA);
263  }
264 
265  return Ret;
266 }
267 
268 /*
269  * Common code for EnumDesktopsA and EnumWindowStationsA
270  */
271 BOOL
272 FASTCALL
273 EnumNamesA(HWINSTA WindowStation,
275  LPARAM Context,
276  BOOL Desktops)
277 {
278  ENUMNAMESASCIICONTEXT PrivateContext;
279 
280  PrivateContext.UserEnumFunc = EnumFunc;
281  PrivateContext.UserContext = Context;
282 
283  return EnumNamesW(WindowStation, EnumNamesCallback, (LPARAM) &PrivateContext, Desktops);
284 }
285 
286 /*
287  * @implemented
288  */
289 BOOL
290 WINAPI
293  IN LPARAM Context)
294 {
295  return EnumNamesA(NULL, EnumFunc, Context, FALSE);
296 }
297 
298 
299 /*
300  * @implemented
301  */
302 BOOL
303 WINAPI
306  IN LPARAM Context)
307 {
308  return EnumNamesW(NULL, EnumFunc, Context, FALSE);
309 }
310 
311 
312 /*
313  * @unimplemented on Win32k side
314  */
315 BOOL
316 WINAPI
318 {
320 }
321 
322 
323 /*
324  * @implemented
325  */
326 HWINSTA
327 WINAPI
329  IN LPCSTR lpszWinSta,
330  IN BOOL fInherit,
331  IN ACCESS_MASK dwDesiredAccess)
332 {
333  HWINSTA hWinSta;
334  UNICODE_STRING WindowStationNameU;
335 
336  if (lpszWinSta)
337  {
338  /* After conversion, the buffer is zero-terminated */
339  RtlCreateUnicodeStringFromAsciiz(&WindowStationNameU, lpszWinSta);
340  }
341  else
342  {
343  RtlInitUnicodeString(&WindowStationNameU, NULL);
344  }
345 
346  hWinSta = OpenWindowStationW(WindowStationNameU.Buffer,
347  fInherit,
348  dwDesiredAccess);
349 
350  /* Free the string if it was allocated */
351  if (lpszWinSta) RtlFreeUnicodeString(&WindowStationNameU);
352 
353  return hWinSta;
354 }
355 
356 
357 /*
358  * @implemented
359  */
360 HWINSTA
361 WINAPI
363  IN LPCWSTR lpszWinSta,
364  IN BOOL fInherit,
365  IN ACCESS_MASK dwDesiredAccess)
366 {
368  HWINSTA hWinSta;
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");
373  HANDLE hWindowStationsDir;
374 
375  /* Open WindowStations directory */
377  &WindowStationsDir,
379  NULL,
380  NULL);
381 
382  Status = NtOpenDirectoryObject(&hWindowStationsDir,
385  if(!NT_SUCCESS(Status))
386  {
387  ERR("Failed to open WindowStations directory\n");
388  return NULL;
389  }
390 
391  /* Open the window station object */
392  RtlInitUnicodeString(&WindowStationName, lpszWinSta);
393 
395  &WindowStationName,
397  hWindowStationsDir,
398  NULL);
399 
400  /* Check if the handle should be inheritable */
401  if (fInherit)
402  {
403  ObjectAttributes.Attributes |= OBJ_INHERIT;
404  }
405 
406  hWinSta = NtUserOpenWindowStation(&ObjectAttributes, dwDesiredAccess);
407 
408  NtClose(hWindowStationsDir);
409 
410  return hWinSta;
411 }
412 
413 
414 /*
415  * @implemented
416  */
417 BOOL
418 WINAPI
420  IN HWINSTA hWindowStation,
421  IN PLUID pluid,
422  IN PSID psid OPTIONAL,
423  IN DWORD size)
424 {
425  BOOL Success;
426 
427  Success = NtUserSetWindowStationUser(hWindowStation, pluid, psid, size);
428  if (Success)
429  {
430  /* Signal log-on/off to WINSRV */
431 
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));
435 
436  Logon(IsLogon);
437  }
438 
439  return Success;
440 }
441 
442 /* EOF */
WINE_DEFAULT_DEBUG_CHANNEL(winsta)
signed char * PCHAR
Definition: retypes.h:7
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
#define IN
Definition: typedefs.h:38
#define TRUE
Definition: types.h:120
NTSTATUS APIENTRY NtUserBuildNameList(HWINSTA hWindowStation, ULONG dwSize, PVOID lpBuffer, PULONG pRequiredSize)
Definition: winsta.c:1901
#define WideCharToMultiByte
Definition: compat.h:101
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
BOOL WINAPI SetWindowStationUser(IN HWINSTA hWindowStation, IN PLUID pluid, IN PSID psid OPTIONAL, IN DWORD size)
Definition: winsta.c:419
BOOL WINAPI EnumWindowStationsW(IN WINSTAENUMPROCW EnumFunc, IN LPARAM Context)
Definition: winsta.c:304
#define DIRECTORY_CREATE_OBJECT
Definition: nt_native.h:1256
HWINSTA WINAPI OpenWindowStationW(IN LPCWSTR lpszWinSta, IN BOOL fInherit, IN ACCESS_MASK dwDesiredAccess)
Definition: winsta.c:362
#define CP_ACP
Definition: compat.h:99
NTSTATUS NTAPI NtOpenDirectoryObject(OUT PHANDLE DirectoryHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes)
Definition: obdir.c:401
char CHAR
Definition: xmlstorage.h:175
HWINSTA APIENTRY NtUserCreateWindowStation(IN POBJECT_ATTRIBUTES ObjectAttributes, IN ACCESS_MASK dwDesiredAccess, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5, DWORD Unknown6)
Definition: winsta.c:695
LONG NTSTATUS
Definition: precomp.h:26
#define CALLBACK
Definition: compat.h:27
HWINSTA APIENTRY NtUserOpenWindowStation(IN POBJECT_ATTRIBUTES ObjectAttributes, IN ACCESS_MASK dwDesiredAccess)
Definition: winsta.c:836
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
DWORD_PTR NTAPI NtUserCallOneParam(DWORD_PTR Param, DWORD Routine)
Definition: simplecall.c:145
NAMEENUMPROCW WINSTAENUMPROCW
Definition: winuser.h:2889
uint16_t * PWCHAR
Definition: typedefs.h:54
char * LPSTR
Definition: xmlstorage.h:182
#define FASTCALL
Definition: nt_native.h:50
LUID LuidNone
Definition: sas.c:46
#define DWORD
Definition: nt_native.h:44
int32_t INT
Definition: typedefs.h:56
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:64
#define OBJ_OPENIF
Definition: winternl.h:229
BOOL(CALLBACK * NAMEENUMPROCW)(LPWSTR, LPARAM)
Definition: winuser.h:2885
BOOL CALLBACK EnumNamesCallback(LPWSTR Name, LPARAM Param)
Definition: winsta.c:211
BOOL(CALLBACK * NAMEENUMPROCA)(LPSTR, LPARAM)
Definition: winuser.h:2884
_In_ HANDLE _In_ DWORD _In_ DWORD _Inout_opt_ LPOVERLAPPED _In_opt_ LPTRANSMIT_FILE_BUFFERS _In_ DWORD dwReserved
Definition: mswsock.h:90
unsigned int BOOL
Definition: ntddk_ex.h:94
#define RtlEqualLuid(Luid1, Luid2)
Definition: rtlfuncs.h:301
struct NameRec_ * Name
Definition: cdprocs.h:464
smooth NULL
Definition: ftsmooth.c:416
LONG_PTR LPARAM
Definition: windef.h:208
NTSYSAPI BOOLEAN NTAPI RtlCreateUnicodeStringFromAsciiz(_Out_ PUNICODE_STRING Destination, _In_ PCSZ Source)
Definition: bufpool.h:45
const char * LPCSTR
Definition: xmlstorage.h:183
_Inout_ PRTL_BUFFER _In_ SIZE_T RequiredSize
struct tagENUMNAMESASCIICONTEXT ENUMNAMESASCIICONTEXT
static BOOL CALLBACK EnumFunc(_In_ HWND hWnd, _In_ PCWSTR lpszString, _In_ HANDLE hData)
Definition: SetProp.c:15
#define DIRECTORY_TRAVERSE
Definition: nt_native.h:1255
_In_ PUNKNOWN pUnknown
Definition: drmk.h:76
BOOL FASTCALL EnumNamesA(HWINSTA WindowStation, NAMEENUMPROCA EnumFunc, LPARAM Context, BOOL Desktops)
Definition: winsta.c:273
GLsizeiptr size
Definition: glext.h:5919
#define GetProcessHeap()
Definition: compat.h:395
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
HWINSTA WINAPI CreateWindowStationA(IN LPCSTR lpwinsta OPTIONAL, IN DWORD dwReserved, IN ACCESS_MASK dwDesiredAccess, IN LPSECURITY_ATTRIBUTES lpsa OPTIONAL)
Definition: winsta.c:18
#define OBJ_INHERIT
Definition: winternl.h:225
#define WINAPI
Definition: msvc.h:8
unsigned long DWORD
Definition: ntddk_ex.h:95
#define Len
Definition: deflate.h:82
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
#define SetLastError(x)
Definition: compat.h:409
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3399
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
BOOL FASTCALL EnumNamesW(HWINSTA WindowStation, NAMEENUMPROCW EnumFunc, LPARAM Context, BOOL Desktops)
Definition: winsta.c:130
static const WCHAR L[]
Definition: oid.c:1250
VOID FASTCALL Logon(BOOL IsLogon)
Definition: logon.c:74
BOOL NTAPI NtUserSetWindowStationUser(IN HWINSTA hWindowStation, IN PLUID pluid, IN PSID psid OPTIONAL, IN DWORD size)
Definition: winsta.c:1959
BOOL WINAPI GetWinStationInfo(PVOID pUnknown)
Definition: winsta.c:317
struct tagENUMNAMESASCIICONTEXT * PENUMNAMESASCIICONTEXT
uint32_t DWORD_PTR
Definition: typedefs.h:63
Status
Definition: gdiplustypes.h:24
NTSYSAPI ULONG WINAPI RtlNtStatusToDosError(NTSTATUS)
#define ERR(fmt,...)
Definition: debug.h:109
HWINSTA WINAPI CreateWindowStationW(IN LPCWSTR lpwinsta OPTIONAL, IN DWORD dwReserved, IN ACCESS_MASK dwDesiredAccess, IN LPSECURITY_ATTRIBUTES lpsa OPTIONAL)
Definition: winsta.c:54
HWINSTA WINAPI GetProcessWindowStation(void)
Definition: ntwrapper.h:124
struct tagContext Context
Definition: acpixf.h:1024
unsigned int ULONG
Definition: retypes.h:1
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
WCHAR * LPWSTR
Definition: xmlstorage.h:184
NAMEENUMPROCA UserEnumFunc
Definition: winsta.c:201
size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define HeapFree(x, y, z)
Definition: compat.h:394
ULONG ACCESS_MASK
Definition: nt_native.h:40
NAMEENUMPROCA WINSTAENUMPROCA
Definition: winuser.h:2888
BOOL WINAPI EnumWindowStationsA(IN WINSTAENUMPROCA EnumFunc, IN LPARAM Context)
Definition: winsta.c:291
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
HWINSTA WINAPI OpenWindowStationA(IN LPCSTR lpszWinSta, IN BOOL fInherit, IN ACCESS_MASK dwDesiredAccess)
Definition: winsta.c:328