1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS Win32k subsystem 4 * PURPOSE: Window stations 5 * FILE: win32ss/user/ntuser/winsta.c 6 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net) 7 * TODO: The process window station is created on 8 * the first USER32/GDI32 call not related 9 * to window station/desktop handling 10 */ 11 12 #include <win32k.h> 13 DBG_DEFAULT_CHANNEL(UserWinsta); 14 15 /* GLOBALS *******************************************************************/ 16 17 /* Currently active window station */ 18 PWINSTATION_OBJECT InputWindowStation = NULL; 19 20 /* Winlogon SAS window */ 21 HWND hwndSAS = NULL; 22 23 /* Full path to WindowStations directory */ 24 UNICODE_STRING gustrWindowStationsDir; 25 26 /* INITIALIZATION FUNCTIONS ****************************************************/ 27 28 INIT_FUNCTION 29 NTSTATUS 30 NTAPI 31 InitWindowStationImpl(VOID) 32 { 33 GENERIC_MAPPING IntWindowStationMapping = { WINSTA_READ, 34 WINSTA_WRITE, 35 WINSTA_EXECUTE, 36 WINSTA_ACCESS_ALL}; 37 38 /* Set Winsta Object Attributes */ 39 ExWindowStationObjectType->TypeInfo.DefaultNonPagedPoolCharge = sizeof(WINSTATION_OBJECT); 40 ExWindowStationObjectType->TypeInfo.GenericMapping = IntWindowStationMapping; 41 ExWindowStationObjectType->TypeInfo.ValidAccessMask = WINSTA_ACCESS_ALL; 42 43 return STATUS_SUCCESS; 44 } 45 46 NTSTATUS 47 NTAPI 48 UserCreateWinstaDirectory(VOID) 49 { 50 PPEB Peb; 51 NTSTATUS Status; 52 WCHAR wstrWindowStationsDir[MAX_PATH]; 53 OBJECT_ATTRIBUTES ObjectAttributes; 54 HANDLE hWinstaDir; 55 56 /* Create the WindowStations directory and cache its path for later use */ 57 Peb = NtCurrentPeb(); 58 if(Peb->SessionId == 0) 59 { 60 if (!RtlCreateUnicodeString(&gustrWindowStationsDir, WINSTA_OBJ_DIR)) 61 { 62 return STATUS_INSUFFICIENT_RESOURCES; 63 } 64 } 65 else 66 { 67 swprintf(wstrWindowStationsDir, 68 L"%ws\\%lu%ws", 69 SESSION_DIR, 70 Peb->SessionId, 71 WINSTA_OBJ_DIR); 72 73 if (!RtlCreateUnicodeString(&gustrWindowStationsDir, wstrWindowStationsDir)) 74 { 75 return STATUS_INSUFFICIENT_RESOURCES; 76 } 77 } 78 79 InitializeObjectAttributes(&ObjectAttributes, 80 &gustrWindowStationsDir, 81 0, 82 NULL, 83 NULL); 84 Status = ZwCreateDirectoryObject(&hWinstaDir, 0, &ObjectAttributes); 85 if (!NT_SUCCESS(Status)) 86 { 87 ERR("Could not create %wZ directory (Status 0x%X)\n", &gustrWindowStationsDir, Status); 88 return Status; 89 } 90 91 TRACE("Created directory %wZ for session %lu\n", &gustrWindowStationsDir, Peb->SessionId); 92 93 return Status; 94 } 95 96 /* OBJECT CALLBACKS **********************************************************/ 97 98 NTSTATUS 99 APIENTRY 100 IntWinStaObjectDelete( 101 _In_ PVOID Parameters) 102 { 103 PWIN32_DELETEMETHOD_PARAMETERS DeleteParameters = Parameters; 104 PWINSTATION_OBJECT WinSta = (PWINSTATION_OBJECT)DeleteParameters->Object; 105 106 TRACE("Deleting window station (0x%p)\n", WinSta); 107 108 WinSta->Flags |= WSS_DYING; 109 110 UserEmptyClipboardData(WinSta); 111 112 RtlDestroyAtomTable(WinSta->AtomTable); 113 114 RtlFreeUnicodeString(&WinSta->Name); 115 116 return STATUS_SUCCESS; 117 } 118 119 NTSTATUS 120 APIENTRY 121 IntWinStaObjectParse( 122 _In_ PVOID Parameters) 123 { 124 PWIN32_PARSEMETHOD_PARAMETERS ParseParameters = Parameters; 125 PUNICODE_STRING RemainingName = ParseParameters->RemainingName; 126 127 /* Assume we don't find anything */ 128 *ParseParameters->Object = NULL; 129 130 /* Check for an empty name */ 131 if (!RemainingName->Length) 132 { 133 /* Make sure this is a window station, can't parse a desktop now */ 134 if (ParseParameters->ObjectType != ExWindowStationObjectType) 135 { 136 /* Fail */ 137 return STATUS_OBJECT_TYPE_MISMATCH; 138 } 139 140 /* Reference the window station and return */ 141 ObReferenceObject(ParseParameters->ParseObject); 142 *ParseParameters->Object = ParseParameters->ParseObject; 143 return STATUS_SUCCESS; 144 } 145 146 /* Check for leading slash */ 147 if (RemainingName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR) 148 { 149 /* Skip it */ 150 RemainingName->Buffer++; 151 RemainingName->Length -= sizeof(WCHAR); 152 RemainingName->MaximumLength -= sizeof(WCHAR); 153 } 154 155 /* Check if there is still a slash */ 156 if (wcschr(RemainingName->Buffer, OBJ_NAME_PATH_SEPARATOR)) 157 { 158 /* In this case, fail */ 159 return STATUS_OBJECT_PATH_INVALID; 160 } 161 162 /* 163 * Check if we are parsing a desktop. 164 */ 165 if (ParseParameters->ObjectType == ExDesktopObjectType) 166 { 167 /* Then call the desktop parse routine */ 168 return IntDesktopObjectParse(ParseParameters->ParseObject, 169 ParseParameters->ObjectType, 170 ParseParameters->AccessState, 171 ParseParameters->AccessMode, 172 ParseParameters->Attributes, 173 ParseParameters->CompleteName, 174 RemainingName, 175 ParseParameters->Context, 176 ParseParameters->SecurityQos, 177 ParseParameters->Object); 178 } 179 180 /* Should hopefully never get here */ 181 return STATUS_OBJECT_TYPE_MISMATCH; 182 } 183 184 NTSTATUS 185 NTAPI 186 IntWinstaOkToClose( 187 _In_ PVOID Parameters) 188 { 189 PWIN32_OKAYTOCLOSEMETHOD_PARAMETERS OkToCloseParameters = Parameters; 190 PPROCESSINFO ppi; 191 192 ppi = PsGetCurrentProcessWin32Process(); 193 194 if(ppi && (OkToCloseParameters->Handle == ppi->hwinsta)) 195 { 196 return STATUS_ACCESS_DENIED; 197 } 198 199 return STATUS_SUCCESS; 200 } 201 202 /* PRIVATE FUNCTIONS **********************************************************/ 203 204 /* 205 * IntValidateWindowStationHandle 206 * 207 * Validates the window station handle. 208 * 209 * Remarks 210 * If the function succeeds, the handle remains referenced. If the 211 * fucntion fails, last error is set. 212 */ 213 214 NTSTATUS FASTCALL 215 IntValidateWindowStationHandle( 216 HWINSTA WindowStation, 217 KPROCESSOR_MODE AccessMode, 218 ACCESS_MASK DesiredAccess, 219 PWINSTATION_OBJECT *Object, 220 POBJECT_HANDLE_INFORMATION pObjectHandleInfo) 221 { 222 NTSTATUS Status; 223 224 if (WindowStation == NULL) 225 { 226 ERR("Invalid window station handle\n"); 227 EngSetLastError(ERROR_INVALID_HANDLE); 228 return STATUS_INVALID_HANDLE; 229 } 230 231 Status = ObReferenceObjectByHandle(WindowStation, 232 DesiredAccess, 233 ExWindowStationObjectType, 234 AccessMode, 235 (PVOID*)Object, 236 pObjectHandleInfo); 237 238 if (!NT_SUCCESS(Status)) 239 SetLastNtError(Status); 240 241 return Status; 242 } 243 244 BOOL FASTCALL 245 co_IntInitializeDesktopGraphics(VOID) 246 { 247 TEXTMETRICW tmw; 248 UNICODE_STRING DriverName = RTL_CONSTANT_STRING(L"DISPLAY"); 249 PDESKTOP pdesk; 250 251 ScreenDeviceContext = IntGdiCreateDC(&DriverName, NULL, NULL, NULL, FALSE); 252 if (NULL == ScreenDeviceContext) 253 { 254 IntDestroyPrimarySurface(); 255 return FALSE; 256 } 257 GreSetDCOwner(ScreenDeviceContext, GDI_OBJ_HMGR_PUBLIC); 258 259 if (! IntCreatePrimarySurface()) 260 { 261 return FALSE; 262 } 263 264 hSystemBM = NtGdiCreateCompatibleDC(ScreenDeviceContext); 265 266 NtGdiSelectFont(hSystemBM, NtGdiGetStockObject(SYSTEM_FONT)); 267 GreSetDCOwner(hSystemBM, GDI_OBJ_HMGR_PUBLIC); 268 269 /* Update the SERVERINFO */ 270 gpsi->aiSysMet[SM_CXSCREEN] = gppdevPrimary->gdiinfo.ulHorzRes; 271 gpsi->aiSysMet[SM_CYSCREEN] = gppdevPrimary->gdiinfo.ulVertRes; 272 gpsi->Planes = NtGdiGetDeviceCaps(ScreenDeviceContext, PLANES); 273 gpsi->BitsPixel = NtGdiGetDeviceCaps(ScreenDeviceContext, BITSPIXEL); 274 gpsi->BitCount = gpsi->Planes * gpsi->BitsPixel; 275 gpsi->dmLogPixels = NtGdiGetDeviceCaps(ScreenDeviceContext, LOGPIXELSY); 276 if (NtGdiGetDeviceCaps(ScreenDeviceContext, RASTERCAPS) & RC_PALETTE) 277 { 278 gpsi->PUSIFlags |= PUSIF_PALETTEDISPLAY; 279 } 280 else 281 gpsi->PUSIFlags &= ~PUSIF_PALETTEDISPLAY; 282 // Font is realized and this dc was previously set to internal DC_ATTR. 283 gpsi->cxSysFontChar = IntGetCharDimensions(hSystemBM, &tmw, (DWORD*)&gpsi->cySysFontChar); 284 gpsi->tmSysFont = tmw; 285 286 /* Put the pointer in the center of the screen */ 287 gpsi->ptCursor.x = gpsi->aiSysMet[SM_CXSCREEN] / 2; 288 gpsi->ptCursor.y = gpsi->aiSysMet[SM_CYSCREEN] / 2; 289 290 /* Attach monitor */ 291 UserAttachMonitor((HDEV)gppdevPrimary); 292 293 /* Setup the cursor */ 294 co_IntLoadDefaultCursors(); 295 296 /* Setup the icons */ 297 co_IntSetWndIcons(); 298 299 /* Setup Menu */ 300 MenuInit(); 301 302 /* Show the desktop */ 303 pdesk = IntGetActiveDesktop(); 304 ASSERT(pdesk); 305 co_IntShowDesktop(pdesk, gpsi->aiSysMet[SM_CXSCREEN], gpsi->aiSysMet[SM_CYSCREEN], TRUE); 306 307 return TRUE; 308 } 309 310 VOID FASTCALL 311 IntEndDesktopGraphics(VOID) 312 { 313 if (NULL != ScreenDeviceContext) 314 { // No need to allocate a new dcattr. 315 GreSetDCOwner(ScreenDeviceContext, GDI_OBJ_HMGR_POWNED); 316 GreDeleteObject(ScreenDeviceContext); 317 ScreenDeviceContext = NULL; 318 } 319 IntHideDesktop(IntGetActiveDesktop()); 320 IntDestroyPrimarySurface(); 321 } 322 323 HDC FASTCALL 324 IntGetScreenDC(VOID) 325 { 326 return ScreenDeviceContext; 327 } 328 329 BOOL FASTCALL 330 CheckWinstaAttributeAccess(ACCESS_MASK DesiredAccess) 331 { 332 PPROCESSINFO ppi = PsGetCurrentProcessWin32Process(); 333 if ( gpidLogon != PsGetCurrentProcessId() ) 334 { 335 if (!(ppi->W32PF_flags & W32PF_IOWINSTA)) 336 { 337 ERR("Requires Interactive Window Station\n"); 338 EngSetLastError(ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION); 339 return FALSE; 340 } 341 if (!RtlAreAllAccessesGranted(ppi->amwinsta, DesiredAccess)) 342 { 343 ERR("Access Denied\n"); 344 EngSetLastError(ERROR_ACCESS_DENIED); 345 return FALSE; 346 } 347 } 348 return TRUE; 349 } 350 351 352 /* PUBLIC FUNCTIONS ***********************************************************/ 353 354 /* 355 * NtUserCreateWindowStation 356 * 357 * Creates a new window station. 358 * 359 * Parameters 360 * lpszWindowStationName 361 * Pointer to a null-terminated string specifying the name of the 362 * window station to be created. Window station names are 363 * case-insensitive and cannot contain backslash characters (\). 364 * Only members of the Administrators group are allowed to specify a 365 * name. 366 * 367 * dwDesiredAccess 368 * Requested type of access 369 * 370 * lpSecurity 371 * Security descriptor 372 * 373 * Unknown3, Unknown4, Unknown5 374 * Unused 375 * 376 * Return Value 377 * If the function succeeds, the return value is a handle to the newly 378 * created window station. If the specified window station already 379 * exists, the function succeeds and returns a handle to the existing 380 * window station. If the function fails, the return value is NULL. 381 * 382 * Todo 383 * Correct the prototype to match the Windows one (with 7 parameters 384 * on Windows XP). 385 * 386 * Status 387 * @implemented 388 */ 389 390 HWINSTA APIENTRY 391 NtUserCreateWindowStation( 392 POBJECT_ATTRIBUTES ObjectAttributes, 393 ACCESS_MASK dwDesiredAccess, 394 DWORD Unknown2, 395 DWORD Unknown3, 396 DWORD Unknown4, 397 DWORD Unknown5, 398 DWORD Unknown6) 399 { 400 UNICODE_STRING WindowStationName; 401 PWINSTATION_OBJECT WindowStationObject; 402 HWINSTA WindowStation; 403 NTSTATUS Status; 404 405 TRACE("NtUserCreateWindowStation called\n"); 406 407 Status = ObOpenObjectByName(ObjectAttributes, 408 ExWindowStationObjectType, 409 UserMode, 410 NULL, 411 dwDesiredAccess, 412 NULL, 413 (PVOID*)&WindowStation); 414 415 if (NT_SUCCESS(Status)) 416 { 417 TRACE("NtUserCreateWindowStation opened window station %wZ\n", ObjectAttributes->ObjectName); 418 return (HWINSTA)WindowStation; 419 } 420 421 /* 422 * No existing window station found, try to create new one 423 */ 424 425 /* Capture window station name */ 426 _SEH2_TRY 427 { 428 ProbeForRead( ObjectAttributes, sizeof(OBJECT_ATTRIBUTES), 1); 429 Status = IntSafeCopyUnicodeStringTerminateNULL(&WindowStationName, ObjectAttributes->ObjectName); 430 } 431 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 432 { 433 Status =_SEH2_GetExceptionCode(); 434 } 435 _SEH2_END 436 437 if (! NT_SUCCESS(Status)) 438 { 439 ERR("Failed reading capturing window station name\n"); 440 SetLastNtError(Status); 441 return NULL; 442 } 443 444 /* Create the window station object */ 445 Status = ObCreateObject(UserMode, 446 ExWindowStationObjectType, 447 ObjectAttributes, 448 UserMode, 449 NULL, 450 sizeof(WINSTATION_OBJECT), 451 0, 452 0, 453 (PVOID*)&WindowStationObject); 454 455 if (!NT_SUCCESS(Status)) 456 { 457 ERR("ObCreateObject failed with %lx for window station %wZ\n", Status, &WindowStationName); 458 ExFreePoolWithTag(WindowStationName.Buffer, TAG_STRING); 459 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES); 460 return 0; 461 } 462 463 /* Initialize the window station */ 464 RtlZeroMemory(WindowStationObject, sizeof(WINSTATION_OBJECT)); 465 466 InitializeListHead(&WindowStationObject->DesktopListHead); 467 WindowStationObject->Name = WindowStationName; 468 WindowStationObject->dwSessionId = NtCurrentPeb()->SessionId; 469 Status = RtlCreateAtomTable(37, &WindowStationObject->AtomTable); 470 if (!NT_SUCCESS(Status)) 471 { 472 ERR("RtlCreateAtomTable failed with %lx for window station %wZ\n", Status, &WindowStationName); 473 ObDereferenceObject(WindowStationObject); 474 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES); 475 return 0; 476 } 477 478 Status = ObInsertObject((PVOID)WindowStationObject, 479 NULL, 480 dwDesiredAccess, 481 0, 482 NULL, 483 (PVOID*)&WindowStation); 484 485 if (!NT_SUCCESS(Status)) 486 { 487 ERR("ObInsertObject failed with %lx for window station\n", Status); 488 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES); 489 return 0; 490 } 491 492 if (InputWindowStation == NULL) 493 { 494 ERR("Initializing input window station\n"); 495 InputWindowStation = WindowStationObject; 496 497 WindowStationObject->Flags &= ~WSS_NOIO; 498 499 InitCursorImpl(); 500 } 501 else 502 { 503 WindowStationObject->Flags |= WSS_NOIO; 504 } 505 506 TRACE("NtUserCreateWindowStation created object %p with name %wZ handle %p\n", 507 WindowStation, &WindowStationObject->Name, WindowStation); 508 return WindowStation; 509 } 510 511 /* 512 * NtUserOpenWindowStation 513 * 514 * Opens an existing window station. 515 * 516 * Parameters 517 * lpszWindowStationName 518 * Name of the existing window station. 519 * 520 * dwDesiredAccess 521 * Requested type of access. 522 * 523 * Return Value 524 * If the function succeeds, the return value is the handle to the 525 * specified window station. If the function fails, the return value 526 * is NULL. 527 * 528 * Remarks 529 * The returned handle can be closed with NtUserCloseWindowStation. 530 * 531 * Status 532 * @implemented 533 */ 534 535 HWINSTA APIENTRY 536 NtUserOpenWindowStation( 537 POBJECT_ATTRIBUTES ObjectAttributes, 538 ACCESS_MASK dwDesiredAccess) 539 { 540 HWINSTA hwinsta; 541 NTSTATUS Status; 542 543 Status = ObOpenObjectByName(ObjectAttributes, 544 ExWindowStationObjectType, 545 UserMode, 546 NULL, 547 dwDesiredAccess, 548 NULL, 549 (PVOID*)&hwinsta); 550 551 if (!NT_SUCCESS(Status)) 552 { 553 ERR("NtUserOpenWindowStation failed\n"); 554 SetLastNtError(Status); 555 return 0; 556 } 557 558 TRACE("Opened window station %wZ with handle %p\n", ObjectAttributes->ObjectName, hwinsta); 559 560 return hwinsta; 561 } 562 563 /* 564 * NtUserCloseWindowStation 565 * 566 * Closes a window station handle. 567 * 568 * Parameters 569 * hWinSta 570 * Handle to the window station. 571 * 572 * Return Value 573 * Status 574 * 575 * Remarks 576 * The window station handle can be created with NtUserCreateWindowStation 577 * or NtUserOpenWindowStation. Attemps to close a handle to the window 578 * station assigned to the calling process will fail. 579 * 580 * Status 581 * @implemented 582 */ 583 584 BOOL 585 APIENTRY 586 NtUserCloseWindowStation( 587 HWINSTA hWinSta) 588 { 589 PWINSTATION_OBJECT Object; 590 NTSTATUS Status; 591 592 TRACE("NtUserCloseWindowStation called (%p)\n", hWinSta); 593 594 if (hWinSta == UserGetProcessWindowStation()) 595 { 596 ERR("Attempted to close process window station\n"); 597 return FALSE; 598 } 599 600 Status = IntValidateWindowStationHandle(hWinSta, 601 UserMode, 602 0, 603 &Object, 604 0); 605 606 if (!NT_SUCCESS(Status)) 607 { 608 ERR("Validation of window station handle (%p) failed\n", hWinSta); 609 return FALSE; 610 } 611 612 ObDereferenceObject(Object); 613 614 TRACE("Closing window station handle (%p)\n", hWinSta); 615 616 Status = ObCloseHandle(hWinSta, UserMode); 617 if (!NT_SUCCESS(Status)) 618 { 619 SetLastNtError(Status); 620 return FALSE; 621 } 622 623 return TRUE; 624 } 625 626 /* 627 * NtUserGetObjectInformation 628 * 629 * The NtUserGetObjectInformation function retrieves information about a 630 * window station or desktop object. 631 * 632 * Parameters 633 * hObj 634 * Handle to the window station or desktop object for which to 635 * return information. This can be a handle of type HDESK or HWINSTA 636 * (for example, a handle returned by NtUserCreateWindowStation, 637 * NtUserOpenWindowStation, NtUserCreateDesktop, or NtUserOpenDesktop). 638 * 639 * nIndex 640 * Specifies the object information to be retrieved. 641 * 642 * pvInfo 643 * Pointer to a buffer to receive the object information. 644 * 645 * nLength 646 * Specifies the size, in bytes, of the buffer pointed to by the 647 * pvInfo parameter. 648 * 649 * lpnLengthNeeded 650 * Pointer to a variable receiving the number of bytes required to 651 * store the requested information. If this variable's value is 652 * greater than the value of the nLength parameter when the function 653 * returns, the function returns FALSE, and none of the information 654 * is copied to the pvInfo buffer. If the value of the variable pointed 655 * to by lpnLengthNeeded is less than or equal to the value of nLength, 656 * the entire information block is copied. 657 * 658 * Return Value 659 * If the function succeeds, the return value is nonzero. If the function 660 * fails, the return value is zero. 661 * 662 * Status 663 * @unimplemented 664 */ 665 666 BOOL APIENTRY 667 NtUserGetObjectInformation( 668 HANDLE hObject, 669 DWORD nIndex, 670 PVOID pvInformation, 671 DWORD nLength, 672 PDWORD nLengthNeeded) 673 { 674 NTSTATUS Status; 675 PWINSTATION_OBJECT WinStaObject = NULL; 676 PDESKTOP DesktopObject = NULL; 677 USEROBJECTFLAGS ObjectFlags; 678 PVOID pvData = NULL; 679 SIZE_T nDataSize = 0; 680 681 _SEH2_TRY 682 { 683 if (nLengthNeeded) 684 ProbeForWrite(nLengthNeeded, sizeof(*nLengthNeeded), 1); 685 ProbeForWrite(pvInformation, nLength, 1); 686 } 687 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 688 { 689 SetLastNtError(_SEH2_GetExceptionCode()); 690 return FALSE; 691 } 692 _SEH2_END; 693 694 /* Try window station */ 695 TRACE("Trying to open window station %p\n", hObject); 696 Status = ObReferenceObjectByHandle(hObject, 697 0, 698 ExWindowStationObjectType, 699 UserMode, 700 (PVOID*)&WinStaObject, 701 NULL); 702 703 if (Status == STATUS_OBJECT_TYPE_MISMATCH) 704 { 705 /* Try desktop */ 706 TRACE("Trying to open desktop %p\n", hObject); 707 WinStaObject = NULL; 708 Status = IntValidateDesktopHandle(hObject, 709 UserMode, 710 0, 711 &DesktopObject); 712 } 713 714 if (!NT_SUCCESS(Status)) 715 { 716 ERR("Failed: 0x%x\n", Status); 717 goto Exit; 718 } 719 720 TRACE("WinSta or Desktop opened!!\n"); 721 722 /* Get data */ 723 switch (nIndex) 724 { 725 case UOI_FLAGS: 726 { 727 /* This is a default implementation that does almost nothing */ 728 ObjectFlags.fInherit = FALSE; 729 ObjectFlags.fReserved = FALSE; 730 ObjectFlags.dwFlags = 0; 731 732 pvData = &ObjectFlags; 733 nDataSize = sizeof(ObjectFlags); 734 Status = STATUS_SUCCESS; 735 ERR("UOI_FLAGS unimplemented!\n"); 736 break; 737 } 738 739 case UOI_NAME: 740 { 741 if (WinStaObject != NULL) 742 { 743 pvData = WinStaObject->Name.Buffer; 744 nDataSize = WinStaObject->Name.Length + sizeof(WCHAR); 745 Status = STATUS_SUCCESS; 746 } 747 else if (DesktopObject != NULL) 748 { 749 pvData = DesktopObject->pDeskInfo->szDesktopName; 750 nDataSize = (wcslen(DesktopObject->pDeskInfo->szDesktopName) + 1) * sizeof(WCHAR); 751 Status = STATUS_SUCCESS; 752 } 753 else 754 { 755 Status = STATUS_INVALID_PARAMETER; 756 } 757 break; 758 } 759 760 case UOI_TYPE: 761 { 762 if (WinStaObject != NULL) 763 { 764 pvData = L"WindowStation"; 765 nDataSize = sizeof(L"WindowStation"); 766 Status = STATUS_SUCCESS; 767 } 768 else if (DesktopObject != NULL) 769 { 770 pvData = L"Desktop"; 771 nDataSize = sizeof(L"Desktop"); 772 Status = STATUS_SUCCESS; 773 } 774 else 775 { 776 Status = STATUS_INVALID_PARAMETER; 777 } 778 break; 779 } 780 781 case UOI_USER_SID: 782 Status = STATUS_NOT_IMPLEMENTED; 783 ERR("UOI_USER_SID unimplemented!\n"); 784 break; 785 786 default: 787 Status = STATUS_INVALID_PARAMETER; 788 break; 789 } 790 791 Exit: 792 if ((Status == STATUS_SUCCESS) && (nLength < nDataSize)) 793 Status = STATUS_BUFFER_TOO_SMALL; 794 795 _SEH2_TRY 796 { 797 if (nLengthNeeded) 798 *nLengthNeeded = nDataSize; 799 800 /* Try to copy data to caller */ 801 if (Status == STATUS_SUCCESS) 802 { 803 TRACE("Trying to copy data to caller (len = %lu, len needed = %lu)\n", nLength, nDataSize); 804 RtlCopyMemory(pvInformation, pvData, nDataSize); 805 } 806 } 807 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 808 { 809 Status = _SEH2_GetExceptionCode(); 810 } 811 _SEH2_END; 812 813 /* Release objects */ 814 if (DesktopObject != NULL) 815 ObDereferenceObject(DesktopObject); 816 if (WinStaObject != NULL) 817 ObDereferenceObject(WinStaObject); 818 819 if (!NT_SUCCESS(Status)) 820 { 821 SetLastNtError(Status); 822 return FALSE; 823 } 824 825 return TRUE; 826 } 827 828 /* 829 * NtUserSetObjectInformation 830 * 831 * The NtUserSetObjectInformation function sets information about a 832 * window station or desktop object. 833 * 834 * Parameters 835 * hObj 836 * Handle to the window station or desktop object for which to set 837 * object information. This value can be a handle of type HDESK or 838 * HWINSTA. 839 * 840 * nIndex 841 * Specifies the object information to be set. 842 * 843 * pvInfo 844 * Pointer to a buffer containing the object information. 845 * 846 * nLength 847 * Specifies the size, in bytes, of the information contained in the 848 * buffer pointed to by pvInfo. 849 * 850 * Return Value 851 * If the function succeeds, the return value is nonzero. If the function 852 * fails the return value is zero. 853 * 854 * Status 855 * @unimplemented 856 */ 857 858 BOOL 859 APIENTRY 860 NtUserSetObjectInformation( 861 HANDLE hObject, 862 DWORD nIndex, 863 PVOID pvInformation, 864 DWORD nLength) 865 { 866 /* FIXME: ZwQueryObject */ 867 /* FIXME: ZwSetInformationObject */ 868 SetLastNtError(STATUS_UNSUCCESSFUL); 869 return FALSE; 870 } 871 872 873 874 875 HWINSTA FASTCALL 876 UserGetProcessWindowStation(VOID) 877 { 878 PPROCESSINFO ppi = PsGetCurrentProcessWin32Process(); 879 880 return ppi->hwinsta; 881 } 882 883 884 /* 885 * NtUserGetProcessWindowStation 886 * 887 * Returns a handle to the current process window station. 888 * 889 * Return Value 890 * If the function succeeds, the return value is handle to the window 891 * station assigned to the current process. If the function fails, the 892 * return value is NULL. 893 * 894 * Status 895 * @implemented 896 */ 897 898 HWINSTA APIENTRY 899 NtUserGetProcessWindowStation(VOID) 900 { 901 return UserGetProcessWindowStation(); 902 } 903 904 BOOL FASTCALL 905 UserSetProcessWindowStation(HWINSTA hWindowStation) 906 { 907 PPROCESSINFO ppi; 908 NTSTATUS Status; 909 HWINSTA hwinstaOld; 910 OBJECT_HANDLE_INFORMATION ObjectHandleInfo; 911 PWINSTATION_OBJECT NewWinSta = NULL, OldWinSta; 912 913 ppi = PsGetCurrentProcessWin32Process(); 914 915 /* Reference the new window station */ 916 if(hWindowStation !=NULL) 917 { 918 Status = IntValidateWindowStationHandle(hWindowStation, 919 UserMode, 920 0, 921 &NewWinSta, 922 &ObjectHandleInfo); 923 if (!NT_SUCCESS(Status)) 924 { 925 TRACE("Validation of window station handle (%p) failed\n", 926 hWindowStation); 927 SetLastNtError(Status); 928 return FALSE; 929 } 930 } 931 932 OldWinSta = ppi->prpwinsta; 933 hwinstaOld = PsGetProcessWin32WindowStation(ppi->peProcess); 934 935 /* Dereference the previous window station */ 936 if(OldWinSta != NULL) 937 { 938 ObDereferenceObject(OldWinSta); 939 } 940 941 /* Check if we have a stale handle (it should happen for console apps) */ 942 if(hwinstaOld != ppi->hwinsta) 943 { 944 ObCloseHandle(hwinstaOld, UserMode); 945 } 946 947 /* 948 * FIXME: Don't allow changing the window station if there are threads that are attached to desktops and own GUI objects. 949 */ 950 951 PsSetProcessWindowStation(ppi->peProcess, hWindowStation); 952 953 ppi->prpwinsta = NewWinSta; 954 ppi->hwinsta = hWindowStation; 955 ppi->amwinsta = hWindowStation != NULL ? ObjectHandleInfo.GrantedAccess : 0; 956 TRACE("WS : Granted Access 0x%08lx\n",ppi->amwinsta); 957 958 if (RtlAreAllAccessesGranted(ppi->amwinsta, WINSTA_READSCREEN)) 959 { 960 ppi->W32PF_flags |= W32PF_READSCREENACCESSGRANTED; 961 } 962 else 963 { 964 ppi->W32PF_flags &= ~W32PF_READSCREENACCESSGRANTED; 965 } 966 967 if (NewWinSta && !(NewWinSta->Flags & WSS_NOIO) ) 968 { 969 ppi->W32PF_flags |= W32PF_IOWINSTA; 970 } 971 else // Might be closed if the handle is null. 972 { 973 ppi->W32PF_flags &= ~W32PF_IOWINSTA; 974 } 975 return TRUE; 976 } 977 978 /* 979 * NtUserSetProcessWindowStation 980 * 981 * Assigns a window station to the current process. 982 * 983 * Parameters 984 * hWinSta 985 * Handle to the window station. 986 * 987 * Return Value 988 * Status 989 * 990 * Status 991 * @implemented 992 */ 993 994 BOOL APIENTRY 995 NtUserSetProcessWindowStation(HWINSTA hWindowStation) 996 { 997 BOOL ret; 998 999 UserEnterExclusive(); 1000 1001 ret = UserSetProcessWindowStation(hWindowStation); 1002 1003 UserLeave(); 1004 1005 return ret; 1006 } 1007 1008 /* 1009 * NtUserLockWindowStation 1010 * 1011 * Locks switching desktops. Only the logon application is allowed to call this function. 1012 * 1013 * Status 1014 * @implemented 1015 */ 1016 1017 BOOL APIENTRY 1018 NtUserLockWindowStation(HWINSTA hWindowStation) 1019 { 1020 PWINSTATION_OBJECT Object; 1021 NTSTATUS Status; 1022 1023 TRACE("About to set process window station with handle (%p)\n", 1024 hWindowStation); 1025 1026 if (gpidLogon != PsGetCurrentProcessId()) 1027 { 1028 ERR("Unauthorized process attempted to lock the window station!\n"); 1029 EngSetLastError(ERROR_ACCESS_DENIED); 1030 return FALSE; 1031 } 1032 1033 Status = IntValidateWindowStationHandle(hWindowStation, 1034 UserMode, 1035 0, 1036 &Object, 1037 0); 1038 if (!NT_SUCCESS(Status)) 1039 { 1040 TRACE("Validation of window station handle (%p) failed\n", 1041 hWindowStation); 1042 SetLastNtError(Status); 1043 return FALSE; 1044 } 1045 1046 Object->Flags |= WSS_LOCKED; 1047 1048 ObDereferenceObject(Object); 1049 return TRUE; 1050 } 1051 1052 /* 1053 * NtUserUnlockWindowStation 1054 * 1055 * Unlocks switching desktops. Only the logon application is allowed to call this function. 1056 * 1057 * Status 1058 * @implemented 1059 */ 1060 1061 BOOL APIENTRY 1062 NtUserUnlockWindowStation(HWINSTA hWindowStation) 1063 { 1064 PWINSTATION_OBJECT Object; 1065 NTSTATUS Status; 1066 BOOL Ret; 1067 1068 TRACE("About to set process window station with handle (%p)\n", 1069 hWindowStation); 1070 1071 if (gpidLogon != PsGetCurrentProcessId()) 1072 { 1073 ERR("Unauthorized process attempted to unlock the window station!\n"); 1074 EngSetLastError(ERROR_ACCESS_DENIED); 1075 return FALSE; 1076 } 1077 1078 Status = IntValidateWindowStationHandle(hWindowStation, 1079 UserMode, 1080 0, 1081 &Object, 1082 0); 1083 if (!NT_SUCCESS(Status)) 1084 { 1085 TRACE("Validation of window station handle (%p) failed\n", 1086 hWindowStation); 1087 SetLastNtError(Status); 1088 return FALSE; 1089 } 1090 1091 Ret = (Object->Flags & WSS_LOCKED) == WSS_LOCKED; 1092 Object->Flags &= ~WSS_LOCKED; 1093 1094 ObDereferenceObject(Object); 1095 return Ret; 1096 } 1097 1098 static NTSTATUS FASTCALL 1099 BuildWindowStationNameList( 1100 ULONG dwSize, 1101 PVOID lpBuffer, 1102 PULONG pRequiredSize) 1103 { 1104 OBJECT_ATTRIBUTES ObjectAttributes; 1105 NTSTATUS Status; 1106 HANDLE DirectoryHandle; 1107 char InitialBuffer[256], *Buffer; 1108 ULONG Context, ReturnLength, BufferSize; 1109 DWORD EntryCount; 1110 POBJECT_DIRECTORY_INFORMATION DirEntry; 1111 WCHAR NullWchar; 1112 1113 /* 1114 * Try to open the directory. 1115 */ 1116 InitializeObjectAttributes(&ObjectAttributes, 1117 &gustrWindowStationsDir, 1118 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 1119 NULL, 1120 NULL); 1121 1122 Status = ZwOpenDirectoryObject(&DirectoryHandle, 1123 DIRECTORY_QUERY, 1124 &ObjectAttributes); 1125 1126 if (!NT_SUCCESS(Status)) 1127 { 1128 return Status; 1129 } 1130 1131 /* First try to query the directory using a fixed-size buffer */ 1132 Context = 0; 1133 Buffer = NULL; 1134 Status = ZwQueryDirectoryObject(DirectoryHandle, 1135 InitialBuffer, 1136 sizeof(InitialBuffer), 1137 FALSE, 1138 TRUE, 1139 &Context, 1140 &ReturnLength); 1141 if (NT_SUCCESS(Status)) 1142 { 1143 if (STATUS_NO_MORE_ENTRIES == ZwQueryDirectoryObject(DirectoryHandle, NULL, 0, FALSE, 1144 FALSE, &Context, NULL)) 1145 { 1146 /* Our fixed-size buffer is large enough */ 1147 Buffer = InitialBuffer; 1148 } 1149 } 1150 1151 if (NULL == Buffer) 1152 { 1153 /* Need a larger buffer, check how large exactly */ 1154 Status = ZwQueryDirectoryObject(DirectoryHandle, NULL, 0, FALSE, TRUE, &Context, 1155 &ReturnLength); 1156 if (!NT_SUCCESS(Status)) 1157 { 1158 ERR("ZwQueryDirectoryObject failed\n"); 1159 ZwClose(DirectoryHandle); 1160 return Status; 1161 } 1162 1163 BufferSize = ReturnLength; 1164 Buffer = ExAllocatePoolWithTag(PagedPool, BufferSize, TAG_WINSTA); 1165 if (NULL == Buffer) 1166 { 1167 ZwClose(DirectoryHandle); 1168 return STATUS_NO_MEMORY; 1169 } 1170 1171 /* We should have a sufficiently large buffer now */ 1172 Context = 0; 1173 Status = ZwQueryDirectoryObject(DirectoryHandle, Buffer, BufferSize, 1174 FALSE, TRUE, &Context, &ReturnLength); 1175 if (! NT_SUCCESS(Status) || 1176 STATUS_NO_MORE_ENTRIES != ZwQueryDirectoryObject(DirectoryHandle, NULL, 0, FALSE, 1177 FALSE, &Context, NULL)) 1178 { 1179 /* Something went wrong, maybe someone added a directory entry? Just give up. */ 1180 ExFreePoolWithTag(Buffer, TAG_WINSTA); 1181 ZwClose(DirectoryHandle); 1182 return NT_SUCCESS(Status) ? STATUS_INTERNAL_ERROR : Status; 1183 } 1184 } 1185 1186 ZwClose(DirectoryHandle); 1187 1188 /* 1189 * Count the required size of buffer. 1190 */ 1191 ReturnLength = sizeof(DWORD); 1192 EntryCount = 0; 1193 for (DirEntry = (POBJECT_DIRECTORY_INFORMATION) Buffer; 1194 0 != DirEntry->Name.Length; 1195 DirEntry++) 1196 { 1197 ReturnLength += DirEntry->Name.Length + sizeof(WCHAR); 1198 EntryCount++; 1199 } 1200 TRACE("Required size: %lu Entry count: %lu\n", ReturnLength, EntryCount); 1201 if (NULL != pRequiredSize) 1202 { 1203 Status = MmCopyToCaller(pRequiredSize, &ReturnLength, sizeof(ULONG)); 1204 if (! NT_SUCCESS(Status)) 1205 { 1206 if (Buffer != InitialBuffer) 1207 { 1208 ExFreePoolWithTag(Buffer, TAG_WINSTA); 1209 } 1210 return STATUS_BUFFER_TOO_SMALL; 1211 } 1212 } 1213 1214 /* 1215 * Check if the supplied buffer is large enough. 1216 */ 1217 if (dwSize < ReturnLength) 1218 { 1219 if (Buffer != InitialBuffer) 1220 { 1221 ExFreePoolWithTag(Buffer, TAG_WINSTA); 1222 } 1223 return STATUS_BUFFER_TOO_SMALL; 1224 } 1225 1226 /* 1227 * Generate the resulting buffer contents. 1228 */ 1229 Status = MmCopyToCaller(lpBuffer, &EntryCount, sizeof(DWORD)); 1230 if (! NT_SUCCESS(Status)) 1231 { 1232 if (Buffer != InitialBuffer) 1233 { 1234 ExFreePoolWithTag(Buffer, TAG_WINSTA); 1235 } 1236 return Status; 1237 } 1238 lpBuffer = (PVOID) ((PCHAR) lpBuffer + sizeof(DWORD)); 1239 1240 NullWchar = L'\0'; 1241 for (DirEntry = (POBJECT_DIRECTORY_INFORMATION) Buffer; 1242 0 != DirEntry->Name.Length; 1243 DirEntry++) 1244 { 1245 Status = MmCopyToCaller(lpBuffer, DirEntry->Name.Buffer, DirEntry->Name.Length); 1246 if (! NT_SUCCESS(Status)) 1247 { 1248 if (Buffer != InitialBuffer) 1249 { 1250 ExFreePoolWithTag(Buffer, TAG_WINSTA); 1251 } 1252 return Status; 1253 } 1254 lpBuffer = (PVOID) ((PCHAR) lpBuffer + DirEntry->Name.Length); 1255 Status = MmCopyToCaller(lpBuffer, &NullWchar, sizeof(WCHAR)); 1256 if (! NT_SUCCESS(Status)) 1257 { 1258 if (Buffer != InitialBuffer) 1259 { 1260 ExFreePoolWithTag(Buffer, TAG_WINSTA); 1261 } 1262 return Status; 1263 } 1264 lpBuffer = (PVOID) ((PCHAR) lpBuffer + sizeof(WCHAR)); 1265 } 1266 1267 /* 1268 * Clean up 1269 */ 1270 if (Buffer != InitialBuffer) 1271 { 1272 ExFreePoolWithTag(Buffer, TAG_WINSTA); 1273 } 1274 1275 return STATUS_SUCCESS; 1276 } 1277 1278 static NTSTATUS FASTCALL 1279 BuildDesktopNameList( 1280 HWINSTA hWindowStation, 1281 ULONG dwSize, 1282 PVOID lpBuffer, 1283 PULONG pRequiredSize) 1284 { 1285 NTSTATUS Status; 1286 PWINSTATION_OBJECT WindowStation; 1287 PLIST_ENTRY DesktopEntry; 1288 PDESKTOP DesktopObject; 1289 DWORD EntryCount; 1290 ULONG ReturnLength; 1291 WCHAR NullWchar; 1292 UNICODE_STRING DesktopName; 1293 1294 Status = IntValidateWindowStationHandle(hWindowStation, 1295 UserMode, 1296 0, 1297 &WindowStation, 1298 0); 1299 if (! NT_SUCCESS(Status)) 1300 { 1301 return Status; 1302 } 1303 1304 /* 1305 * Count the required size of buffer. 1306 */ 1307 ReturnLength = sizeof(DWORD); 1308 EntryCount = 0; 1309 for (DesktopEntry = WindowStation->DesktopListHead.Flink; 1310 DesktopEntry != &WindowStation->DesktopListHead; 1311 DesktopEntry = DesktopEntry->Flink) 1312 { 1313 DesktopObject = CONTAINING_RECORD(DesktopEntry, DESKTOP, ListEntry); 1314 RtlInitUnicodeString(&DesktopName, DesktopObject->pDeskInfo->szDesktopName); 1315 ReturnLength += DesktopName.Length + sizeof(WCHAR); 1316 EntryCount++; 1317 } 1318 TRACE("Required size: %lu Entry count: %lu\n", ReturnLength, EntryCount); 1319 if (NULL != pRequiredSize) 1320 { 1321 Status = MmCopyToCaller(pRequiredSize, &ReturnLength, sizeof(ULONG)); 1322 if (! NT_SUCCESS(Status)) 1323 { 1324 ObDereferenceObject(WindowStation); 1325 return STATUS_BUFFER_TOO_SMALL; 1326 } 1327 } 1328 1329 /* 1330 * Check if the supplied buffer is large enough. 1331 */ 1332 if (dwSize < ReturnLength) 1333 { 1334 ObDereferenceObject(WindowStation); 1335 return STATUS_BUFFER_TOO_SMALL; 1336 } 1337 1338 /* 1339 * Generate the resulting buffer contents. 1340 */ 1341 Status = MmCopyToCaller(lpBuffer, &EntryCount, sizeof(DWORD)); 1342 if (! NT_SUCCESS(Status)) 1343 { 1344 ObDereferenceObject(WindowStation); 1345 return Status; 1346 } 1347 lpBuffer = (PVOID) ((PCHAR) lpBuffer + sizeof(DWORD)); 1348 1349 NullWchar = L'\0'; 1350 for (DesktopEntry = WindowStation->DesktopListHead.Flink; 1351 DesktopEntry != &WindowStation->DesktopListHead; 1352 DesktopEntry = DesktopEntry->Flink) 1353 { 1354 DesktopObject = CONTAINING_RECORD(DesktopEntry, DESKTOP, ListEntry); 1355 RtlInitUnicodeString(&DesktopName, DesktopObject->pDeskInfo->szDesktopName); 1356 Status = MmCopyToCaller(lpBuffer, DesktopName.Buffer, DesktopName.Length); 1357 if (! NT_SUCCESS(Status)) 1358 { 1359 ObDereferenceObject(WindowStation); 1360 return Status; 1361 } 1362 lpBuffer = (PVOID) ((PCHAR)lpBuffer + DesktopName.Length); 1363 Status = MmCopyToCaller(lpBuffer, &NullWchar, sizeof(WCHAR)); 1364 if (! NT_SUCCESS(Status)) 1365 { 1366 ObDereferenceObject(WindowStation); 1367 return Status; 1368 } 1369 lpBuffer = (PVOID) ((PCHAR) lpBuffer + sizeof(WCHAR)); 1370 } 1371 1372 /* 1373 * Clean up and return 1374 */ 1375 ObDereferenceObject(WindowStation); 1376 return STATUS_SUCCESS; 1377 } 1378 1379 /* 1380 * NtUserBuildNameList 1381 * 1382 * Function used for enumeration of desktops or window stations. 1383 * 1384 * Parameters 1385 * hWinSta 1386 * For enumeration of window stations this parameter must be set to 1387 * zero. Otherwise it's handle for window station. 1388 * 1389 * dwSize 1390 * Size of buffer passed by caller. 1391 * 1392 * lpBuffer 1393 * Buffer passed by caller. If the function succeeds, the buffer is 1394 * filled with window station/desktop count (in first DWORD) and 1395 * NULL-terminated window station/desktop names. 1396 * 1397 * pRequiredSize 1398 * If the function succeeds, this is the number of bytes copied. 1399 * Otherwise it's size of buffer needed for function to succeed. 1400 * 1401 * Status 1402 * @implemented 1403 */ 1404 1405 NTSTATUS APIENTRY 1406 NtUserBuildNameList( 1407 HWINSTA hWindowStation, 1408 ULONG dwSize, 1409 PVOID lpBuffer, 1410 PULONG pRequiredSize) 1411 { 1412 /* The WindowStation name list and desktop name list are build in completely 1413 different ways. Call the appropriate function */ 1414 return NULL == hWindowStation ? BuildWindowStationNameList(dwSize, lpBuffer, pRequiredSize) : 1415 BuildDesktopNameList(hWindowStation, dwSize, lpBuffer, pRequiredSize); 1416 } 1417 1418 /* 1419 * @implemented 1420 */ 1421 BOOL APIENTRY 1422 NtUserSetLogonNotifyWindow(HWND hWnd) 1423 { 1424 if (gpidLogon != PsGetCurrentProcessId()) 1425 { 1426 return FALSE; 1427 } 1428 1429 if (!IntIsWindow(hWnd)) 1430 { 1431 return FALSE; 1432 } 1433 1434 hwndSAS = hWnd; 1435 1436 return TRUE; 1437 } 1438 1439 BOOL 1440 APIENTRY 1441 NtUserLockWorkStation(VOID) 1442 { 1443 BOOL ret; 1444 PTHREADINFO pti = PsGetCurrentThreadWin32Thread(); 1445 1446 UserEnterExclusive(); 1447 1448 if (pti->rpdesk == IntGetActiveDesktop()) 1449 { 1450 ret = UserPostMessage(hwndSAS, WM_LOGONNOTIFY, LN_LOCK_WORKSTATION, 0); 1451 } 1452 else 1453 { 1454 ret = FALSE; 1455 } 1456 1457 UserLeave(); 1458 1459 return ret; 1460 } 1461 1462 BOOL APIENTRY 1463 NtUserSetWindowStationUser( 1464 HWINSTA hWindowStation, 1465 PLUID pluid, 1466 PSID psid, 1467 DWORD size) 1468 { 1469 NTSTATUS Status; 1470 PWINSTATION_OBJECT WindowStation = NULL; 1471 BOOL Ret = FALSE; 1472 1473 UserEnterExclusive(); 1474 1475 if (gpidLogon != PsGetCurrentProcessId()) 1476 { 1477 EngSetLastError(ERROR_ACCESS_DENIED); 1478 goto Leave; 1479 } 1480 1481 Status = IntValidateWindowStationHandle(hWindowStation, 1482 UserMode, 1483 0, 1484 &WindowStation, 1485 0); 1486 if (!NT_SUCCESS(Status)) 1487 { 1488 goto Leave; 1489 } 1490 1491 if (WindowStation->psidUser) 1492 { 1493 ExFreePoolWithTag(WindowStation->psidUser, USERTAG_SECURITY); 1494 } 1495 1496 WindowStation->psidUser = ExAllocatePoolWithTag(PagedPool, size, USERTAG_SECURITY); 1497 if (WindowStation->psidUser == NULL) 1498 { 1499 EngSetLastError(ERROR_OUTOFMEMORY); 1500 goto Leave; 1501 } 1502 1503 _SEH2_TRY 1504 { 1505 ProbeForRead( psid, size, 1); 1506 ProbeForRead( pluid, sizeof(LUID), 1); 1507 1508 RtlCopyMemory(WindowStation->psidUser, psid, size); 1509 WindowStation->luidUser = *pluid; 1510 } 1511 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1512 { 1513 Status = _SEH2_GetExceptionCode(); 1514 } 1515 _SEH2_END; 1516 1517 if (!NT_SUCCESS(Status)) 1518 { 1519 ExFreePoolWithTag(WindowStation->psidUser, USERTAG_SECURITY); 1520 WindowStation->psidUser = 0; 1521 goto Leave; 1522 } 1523 1524 Ret = TRUE; 1525 1526 Leave: 1527 if (WindowStation) ObDereferenceObject(WindowStation); 1528 UserLeave(); 1529 return Ret; 1530 } 1531 1532 1533 /* EOF */ 1534