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