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