1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS Win32k subsystem 4 * PURPOSE: Miscellaneous User functions 5 * FILE: win32ss/user/ntuser/misc.c 6 * PROGRAMER: Ge van Geldorp (ge@gse.nl) 7 */ 8 9 #include <win32k.h> 10 DBG_DEFAULT_CHANNEL(UserMisc); 11 12 13 /* 14 * NOTE: _scwprintf() is NOT exported by ntoskrnl.exe, 15 * only _vscwprintf() is, so we need to implement it here. 16 * Code comes from sdk/lib/crt/printf/_scwprintf.c . 17 * See also win32ss/user/winsrv/usersrv/harderror.c . 18 */ 19 int 20 __cdecl 21 _scwprintf( 22 const wchar_t *format, 23 ...) 24 { 25 int len; 26 va_list args; 27 28 va_start(args, format); 29 len = _vscwprintf(format, args); 30 va_end(args); 31 32 return len; 33 } 34 35 36 /* 37 * Test the Thread to verify and validate it. Hard to the core tests are required. 38 * Win: PtiFromThreadId 39 */ 40 PTHREADINFO 41 FASTCALL 42 IntTID2PTI(HANDLE id) 43 { 44 NTSTATUS Status; 45 PETHREAD Thread; 46 PTHREADINFO pti; 47 Status = PsLookupThreadByThreadId(id, &Thread); 48 if (!NT_SUCCESS(Status)) 49 { 50 return NULL; 51 } 52 if (PsIsThreadTerminating(Thread)) 53 { 54 ObDereferenceObject(Thread); 55 return NULL; 56 } 57 pti = PsGetThreadWin32Thread(Thread); 58 if (!pti) 59 { 60 ObDereferenceObject(Thread); 61 return NULL; 62 } 63 // Validate and verify! 64 _SEH2_TRY 65 { 66 if (pti->TIF_flags & TIF_INCLEANUP) pti = NULL; 67 if (pti && !(pti->TIF_flags & TIF_GUITHREADINITIALIZED)) pti = NULL; 68 if (PsGetThreadId(Thread) != id) pti = NULL; 69 } 70 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 71 { 72 pti = NULL; 73 } 74 _SEH2_END 75 ObDereferenceObject(Thread); 76 return pti; 77 } 78 79 /** 80 * @see https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-2000-server/cc976564%28v=technet.10%29 81 */ 82 DWORD 83 FASTCALL 84 UserGetLanguageToggle( 85 _In_ PCWSTR pszType, 86 _In_ DWORD dwDefaultValue) 87 { 88 NTSTATUS Status; 89 DWORD dwValue = dwDefaultValue; 90 WCHAR szBuff[4]; 91 92 Status = RegReadUserSetting(L"Keyboard Layout\\Toggle", pszType, REG_SZ, szBuff, sizeof(szBuff)); 93 if (NT_SUCCESS(Status)) 94 { 95 szBuff[RTL_NUMBER_OF(szBuff) - 1] = UNICODE_NULL; 96 dwValue = _wtoi(szBuff); 97 } 98 99 TRACE("%ls: %lu\n", pszType, dwValue); 100 return dwValue; 101 } 102 103 USHORT 104 FASTCALL 105 UserGetLanguageID(VOID) 106 { 107 HANDLE KeyHandle; 108 OBJECT_ATTRIBUTES ObAttr; 109 // http://support.microsoft.com/kb/324097 110 ULONG Ret = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT); 111 PKEY_VALUE_PARTIAL_INFORMATION pKeyInfo; 112 ULONG Size = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + MAX_PATH*sizeof(WCHAR); 113 UNICODE_STRING Language; 114 115 RtlInitUnicodeString( &Language, 116 L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Nls\\Language"); 117 118 InitializeObjectAttributes( &ObAttr, 119 &Language, 120 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 121 NULL, 122 NULL); 123 124 if ( NT_SUCCESS(ZwOpenKey(&KeyHandle, KEY_READ, &ObAttr))) 125 { 126 pKeyInfo = ExAllocatePoolWithTag(PagedPool, Size, TAG_STRING); 127 if ( pKeyInfo ) 128 { 129 RtlInitUnicodeString(&Language, L"Default"); 130 131 if ( NT_SUCCESS(ZwQueryValueKey( KeyHandle, 132 &Language, 133 KeyValuePartialInformation, 134 pKeyInfo, 135 Size, 136 &Size)) ) 137 { 138 RtlInitUnicodeString(&Language, (PWSTR)pKeyInfo->Data); 139 if (!NT_SUCCESS(RtlUnicodeStringToInteger(&Language, 16, &Ret))) 140 { 141 Ret = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT); 142 } 143 } 144 ExFreePoolWithTag(pKeyInfo, TAG_STRING); 145 } 146 ZwClose(KeyHandle); 147 } 148 TRACE("Language ID = %x\n",Ret); 149 return (USHORT) Ret; 150 } 151 152 HBRUSH 153 FASTCALL 154 GetControlColor( 155 PWND pwndParent, 156 PWND pwnd, 157 HDC hdc, 158 UINT CtlMsg) 159 { 160 HBRUSH hBrush; 161 162 if (!pwndParent) pwndParent = pwnd; 163 164 if ( pwndParent->head.pti->ppi != PsGetCurrentProcessWin32Process()) 165 { 166 return (HBRUSH)IntDefWindowProc( pwndParent, CtlMsg, (WPARAM)hdc, (LPARAM)UserHMGetHandle(pwnd), FALSE); 167 } 168 169 hBrush = (HBRUSH)co_IntSendMessage( UserHMGetHandle(pwndParent), CtlMsg, (WPARAM)hdc, (LPARAM)UserHMGetHandle(pwnd)); 170 171 if (!hBrush || !GreIsHandleValid(hBrush)) 172 { 173 hBrush = (HBRUSH)IntDefWindowProc( pwndParent, CtlMsg, (WPARAM)hdc, (LPARAM)UserHMGetHandle(pwnd), FALSE); 174 } 175 return hBrush; 176 } 177 178 HBRUSH 179 FASTCALL 180 GetControlBrush( 181 PWND pwnd, 182 HDC hdc, 183 UINT ctlType) 184 { 185 PWND pwndParent = IntGetParent(pwnd); 186 return GetControlColor( pwndParent, pwnd, hdc, ctlType); 187 } 188 189 HBRUSH 190 APIENTRY 191 NtUserGetControlBrush( 192 HWND hwnd, 193 HDC hdc, 194 UINT ctlType) 195 { 196 PWND pwnd; 197 HBRUSH hBrush = NULL; 198 199 UserEnterExclusive(); 200 if ( (pwnd = UserGetWindowObject(hwnd)) && 201 ((ctlType - WM_CTLCOLORMSGBOX) < CTLCOLOR_MAX) && 202 hdc ) 203 { 204 hBrush = GetControlBrush(pwnd, hdc, ctlType); 205 } 206 UserLeave(); 207 return hBrush; 208 } 209 210 /* 211 * Called from PaintRect, works almost like wine PaintRect16 but returns hBrush. 212 */ 213 HBRUSH 214 APIENTRY 215 NtUserGetControlColor( 216 HWND hwndParent, 217 HWND hwnd, 218 HDC hdc, 219 UINT CtlMsg) // Wine PaintRect: WM_CTLCOLORMSGBOX + hbrush 220 { 221 PWND pwnd, pwndParent = NULL; 222 HBRUSH hBrush = NULL; 223 224 UserEnterExclusive(); 225 if ( (pwnd = UserGetWindowObject(hwnd)) && 226 ((CtlMsg - WM_CTLCOLORMSGBOX) < CTLCOLOR_MAX) && 227 hdc ) 228 { 229 if (hwndParent) pwndParent = UserGetWindowObject(hwndParent); 230 hBrush = GetControlColor( pwndParent, pwnd, hdc, CtlMsg); 231 } 232 UserLeave(); 233 return hBrush; 234 } 235 236 /* 237 * @unimplemented 238 */ 239 DWORD_PTR APIENTRY 240 NtUserGetThreadState( 241 DWORD Routine) 242 { 243 DWORD_PTR ret = 0; 244 PTHREADINFO pti; 245 246 TRACE("Enter NtUserGetThreadState\n"); 247 if (Routine != THREADSTATE_GETTHREADINFO) 248 { 249 UserEnterShared(); 250 } 251 else 252 { 253 UserEnterExclusive(); 254 } 255 256 pti = PsGetCurrentThreadWin32Thread(); 257 258 switch (Routine) 259 { 260 case THREADSTATE_GETTHREADINFO: 261 ret = TRUE; 262 break; 263 case THREADSTATE_FOCUSWINDOW: 264 ret = (DWORD_PTR)IntGetThreadFocusWindow(); 265 break; 266 case THREADSTATE_CAPTUREWINDOW: 267 /* FIXME: Should use UserEnterShared */ 268 ret = (DWORD_PTR)IntGetCapture(); 269 break; 270 case THREADSTATE_PROGMANWINDOW: /* FIXME: Delete this HACK */ 271 ret = (DWORD_PTR)GetW32ThreadInfo()->pDeskInfo->hProgmanWindow; 272 break; 273 case THREADSTATE_TASKMANWINDOW: /* FIXME: Delete this HACK */ 274 ret = (DWORD_PTR)GetW32ThreadInfo()->pDeskInfo->hTaskManWindow; 275 break; 276 case THREADSTATE_ACTIVEWINDOW: 277 ret = (DWORD_PTR)UserGetActiveWindow(); 278 break; 279 case THREADSTATE_INSENDMESSAGE: 280 { 281 PUSER_SENT_MESSAGE Message = 282 ((PTHREADINFO)PsGetCurrentThreadWin32Thread())->pusmCurrent; 283 TRACE("THREADSTATE_INSENDMESSAGE\n"); 284 285 ret = ISMEX_NOSEND; 286 if (Message) 287 { 288 if (Message->ptiSender) 289 ret = ISMEX_SEND; 290 else 291 { 292 if (Message->CompletionCallback) 293 ret = ISMEX_CALLBACK; 294 else 295 ret = ISMEX_NOTIFY; 296 } 297 /* If ReplyMessage */ 298 if (Message->QS_Flags & QS_SMRESULT) ret |= ISMEX_REPLIED; 299 } 300 301 break; 302 } 303 case THREADSTATE_GETMESSAGETIME: 304 ret = ((PTHREADINFO)PsGetCurrentThreadWin32Thread())->timeLast; 305 break; 306 307 case THREADSTATE_UPTIMELASTREAD: 308 pti->pcti->timeLastRead = EngGetTickCount32(); 309 break; 310 311 case THREADSTATE_GETINPUTSTATE: 312 ret = LOWORD(IntGetQueueStatus(QS_POSTMESSAGE|QS_TIMER|QS_PAINT|QS_SENDMESSAGE|QS_INPUT)) & (QS_KEY | QS_MOUSEBUTTON); 313 break; 314 315 case THREADSTATE_FOREGROUNDTHREAD: 316 ret = (gpqForeground == GetW32ThreadInfo()->MessageQueue); 317 break; 318 case THREADSTATE_GETCURSOR: 319 ret = (DWORD_PTR) (GetW32ThreadInfo()->MessageQueue->CursorObject ? 320 UserHMGetHandle(GetW32ThreadInfo()->MessageQueue->CursorObject) : 0); 321 break; 322 case THREADSTATE_GETMESSAGEEXTRAINFO: 323 ret = (DWORD_PTR)MsqGetMessageExtraInfo(); 324 break; 325 case THREADSTATE_DEFAULTIMEWINDOW: 326 if (pti->spwndDefaultIme) 327 ret = (ULONG_PTR)UserHMGetHandle(pti->spwndDefaultIme); 328 break; 329 case THREADSTATE_DEFAULTINPUTCONTEXT: 330 if (pti->spDefaultImc) 331 ret = (ULONG_PTR)UserHMGetHandle(pti->spDefaultImc); 332 break; 333 case THREADSTATE_CHANGEBITS: 334 ret = pti->pcti->fsChangeBits; 335 break; 336 case THREADSTATE_IMECOMPATFLAGS: 337 ret = pti->ppi->dwImeCompatFlags; 338 break; 339 case THREADSTATE_OLDKEYBOARDLAYOUT: 340 ret = (ULONG_PTR)pti->hklPrev; 341 break; 342 case THREADSTATE_ISWINLOGON: 343 case THREADSTATE_ISWINLOGON2: 344 ret = (gpidLogon == PsGetCurrentProcessId()); 345 break; 346 case THREADSTATE_CHECKCONIME: 347 ret = (IntTID2PTI(UlongToHandle(pti->rpdesk->dwConsoleThreadId)) == pti); 348 break; 349 } 350 351 TRACE("Leave NtUserGetThreadState, ret=%lu\n", ret); 352 UserLeave(); 353 354 return ret; 355 } 356 357 DWORD 358 APIENTRY 359 NtUserSetThreadState( 360 DWORD Set, 361 DWORD Flags) 362 { 363 PTHREADINFO pti; 364 DWORD Ret = 0; 365 // Test the only flags user can change. 366 if (Set & ~(QF_FF10STATUS|QF_DIALOGACTIVE|QF_TABSWITCHING|QF_FMENUSTATUS|QF_FMENUSTATUSBREAK)) return 0; 367 if (Flags & ~(QF_FF10STATUS|QF_DIALOGACTIVE|QF_TABSWITCHING|QF_FMENUSTATUS|QF_FMENUSTATUSBREAK)) return 0; 368 UserEnterExclusive(); 369 pti = PsGetCurrentThreadWin32Thread(); 370 if (pti->MessageQueue) 371 { 372 Ret = pti->MessageQueue->QF_flags; // Get the queue flags. 373 if (Set) 374 pti->MessageQueue->QF_flags |= (Set&Flags); // Set the queue flags. 375 else 376 { 377 if (Flags) pti->MessageQueue->QF_flags &= ~Flags; // Clr the queue flags. 378 } 379 } 380 UserLeave(); 381 return Ret; 382 } 383 384 UINT 385 APIENTRY 386 NtUserGetDoubleClickTime(VOID) 387 { 388 UINT Result; 389 390 TRACE("Enter NtUserGetDoubleClickTime\n"); 391 UserEnterShared(); 392 393 // FIXME: Check if this works on non-interactive winsta 394 Result = gspv.iDblClickTime; 395 396 TRACE("Leave NtUserGetDoubleClickTime, ret=%u\n", Result); 397 UserLeave(); 398 return Result; 399 } 400 401 BOOL 402 APIENTRY 403 NtUserGetGUIThreadInfo( 404 DWORD idThread, /* If NULL use foreground thread */ 405 LPGUITHREADINFO lpgui) 406 { 407 NTSTATUS Status; 408 PTHRDCARETINFO CaretInfo; 409 GUITHREADINFO SafeGui; 410 PDESKTOP Desktop; 411 PUSER_MESSAGE_QUEUE MsgQueue; 412 PTHREADINFO W32Thread, pti; 413 414 DECLARE_RETURN(BOOLEAN); 415 416 TRACE("Enter NtUserGetGUIThreadInfo\n"); 417 UserEnterShared(); 418 419 Status = MmCopyFromCaller(&SafeGui, lpgui, sizeof(DWORD)); 420 if(!NT_SUCCESS(Status)) 421 { 422 SetLastNtError(Status); 423 RETURN( FALSE); 424 } 425 426 if(SafeGui.cbSize != sizeof(GUITHREADINFO)) 427 { 428 EngSetLastError(ERROR_INVALID_PARAMETER); 429 RETURN( FALSE); 430 } 431 432 if (idThread) 433 { 434 pti = PsGetCurrentThreadWin32Thread(); 435 436 // Validate Tread ID 437 W32Thread = IntTID2PTI((HANDLE)(DWORD_PTR)idThread); 438 439 if ( !W32Thread ) 440 { 441 EngSetLastError(ERROR_ACCESS_DENIED); 442 RETURN( FALSE); 443 } 444 445 Desktop = W32Thread->rpdesk; 446 447 // Check Desktop and it must be the same as current. 448 if ( !Desktop || Desktop != pti->rpdesk ) 449 { 450 EngSetLastError(ERROR_ACCESS_DENIED); 451 RETURN( FALSE); 452 } 453 454 if ( W32Thread->MessageQueue ) 455 MsgQueue = W32Thread->MessageQueue; 456 else 457 { 458 MsgQueue = Desktop->ActiveMessageQueue; 459 } 460 } 461 else 462 { /* Get the foreground thread */ 463 /* FIXME: Handle NULL queue properly? */ 464 MsgQueue = IntGetFocusMessageQueue(); 465 if(!MsgQueue) 466 { 467 EngSetLastError(ERROR_ACCESS_DENIED); 468 RETURN( FALSE); 469 } 470 } 471 472 CaretInfo = &MsgQueue->CaretInfo; 473 474 SafeGui.flags = (CaretInfo->Visible ? GUI_CARETBLINKING : 0); 475 /* 476 if (W32Thread->pMenuState->pGlobalPopupMenu) 477 { 478 SafeGui.flags |= GUI_INMENUMODE; 479 480 if (W32Thread->pMenuState->pGlobalPopupMenu->spwndNotify) 481 SafeGui.hwndMenuOwner = UserHMGetHandle(W32Thread->pMenuState->pGlobalPopupMenu->spwndNotify); 482 483 if (W32Thread->pMenuState->pGlobalPopupMenu->fHasMenuBar) 484 { 485 if (W32Thread->pMenuState->pGlobalPopupMenu->fIsSysMenu) 486 { 487 SafeGui.flags |= GUI_SYSTEMMENUMODE; 488 } 489 } 490 else 491 { 492 SafeGui.flags |= GUI_POPUPMENUMODE; 493 } 494 } 495 */ 496 SafeGui.hwndMenuOwner = MsgQueue->MenuOwner; 497 498 if (MsgQueue->MenuOwner) 499 SafeGui.flags |= GUI_INMENUMODE | MsgQueue->MenuState; 500 501 if (MsgQueue->MoveSize) 502 SafeGui.flags |= GUI_INMOVESIZE; 503 504 /* FIXME: Add flag GUI_16BITTASK */ 505 506 SafeGui.hwndActive = MsgQueue->spwndActive ? UserHMGetHandle(MsgQueue->spwndActive) : 0; 507 SafeGui.hwndFocus = MsgQueue->spwndFocus ? UserHMGetHandle(MsgQueue->spwndFocus) : 0; 508 SafeGui.hwndCapture = MsgQueue->spwndCapture ? UserHMGetHandle(MsgQueue->spwndCapture) : 0; 509 SafeGui.hwndMoveSize = MsgQueue->MoveSize; 510 SafeGui.hwndCaret = CaretInfo->hWnd; 511 512 SafeGui.rcCaret.left = CaretInfo->Pos.x; 513 SafeGui.rcCaret.top = CaretInfo->Pos.y; 514 SafeGui.rcCaret.right = SafeGui.rcCaret.left + CaretInfo->Size.cx; 515 SafeGui.rcCaret.bottom = SafeGui.rcCaret.top + CaretInfo->Size.cy; 516 517 Status = MmCopyToCaller(lpgui, &SafeGui, sizeof(GUITHREADINFO)); 518 if(!NT_SUCCESS(Status)) 519 { 520 SetLastNtError(Status); 521 RETURN( FALSE); 522 } 523 524 RETURN( TRUE); 525 526 CLEANUP: 527 TRACE("Leave NtUserGetGUIThreadInfo, ret=%u\n",_ret_); 528 UserLeave(); 529 END_CLEANUP; 530 } 531 532 533 DWORD 534 APIENTRY 535 NtUserGetGuiResources( 536 HANDLE hProcess, 537 DWORD uiFlags) 538 { 539 PEPROCESS Process; 540 PPROCESSINFO W32Process; 541 NTSTATUS Status; 542 DWORD Ret = 0; 543 DECLARE_RETURN(DWORD); 544 545 TRACE("Enter NtUserGetGuiResources\n"); 546 UserEnterShared(); 547 548 Status = ObReferenceObjectByHandle(hProcess, 549 PROCESS_QUERY_INFORMATION, 550 *PsProcessType, 551 ExGetPreviousMode(), 552 (PVOID*)&Process, 553 NULL); 554 555 if(!NT_SUCCESS(Status)) 556 { 557 SetLastNtError(Status); 558 RETURN( 0); 559 } 560 561 W32Process = (PPROCESSINFO)Process->Win32Process; 562 if(!W32Process) 563 { 564 ObDereferenceObject(Process); 565 EngSetLastError(ERROR_INVALID_PARAMETER); 566 RETURN( 0); 567 } 568 569 switch(uiFlags) 570 { 571 case GR_GDIOBJECTS: 572 { 573 Ret = (DWORD)W32Process->GDIHandleCount; 574 break; 575 } 576 case GR_USEROBJECTS: 577 { 578 Ret = (DWORD)W32Process->UserHandleCount; 579 break; 580 } 581 default: 582 { 583 EngSetLastError(ERROR_INVALID_PARAMETER); 584 break; 585 } 586 } 587 588 ObDereferenceObject(Process); 589 590 RETURN( Ret); 591 592 CLEANUP: 593 TRACE("Leave NtUserGetGuiResources, ret=%lu\n",_ret_); 594 UserLeave(); 595 END_CLEANUP; 596 } 597 598 VOID FASTCALL 599 IntSetWindowState(PWND pWnd, UINT Flag) 600 { 601 UINT bit; 602 if (gptiCurrent->ppi != pWnd->head.pti->ppi) return; 603 bit = 1 << LOWORD(Flag); 604 TRACE("SWS %x\n",bit); 605 switch(HIWORD(Flag)) 606 { 607 case 0: 608 pWnd->state |= bit; 609 break; 610 case 1: 611 pWnd->state2 |= bit; 612 break; 613 case 2: 614 pWnd->ExStyle2 |= bit; 615 break; 616 } 617 } 618 619 VOID FASTCALL 620 IntClearWindowState(PWND pWnd, UINT Flag) 621 { 622 UINT bit; 623 if (gptiCurrent->ppi != pWnd->head.pti->ppi) return; 624 bit = 1 << LOWORD(Flag); 625 TRACE("CWS %x\n",bit); 626 switch(HIWORD(Flag)) 627 { 628 case 0: 629 pWnd->state &= ~bit; 630 break; 631 case 1: 632 pWnd->state2 &= ~bit; 633 break; 634 case 2: 635 pWnd->ExStyle2 &= ~bit; 636 break; 637 } 638 } 639 640 NTSTATUS FASTCALL 641 IntSafeCopyUnicodeString(PUNICODE_STRING Dest, 642 PUNICODE_STRING Source) 643 { 644 NTSTATUS Status; 645 PWSTR Src; 646 647 Status = MmCopyFromCaller(Dest, Source, sizeof(UNICODE_STRING)); 648 if(!NT_SUCCESS(Status)) 649 { 650 return Status; 651 } 652 653 if(Dest->Length > 0x4000) 654 { 655 return STATUS_UNSUCCESSFUL; 656 } 657 658 Src = Dest->Buffer; 659 Dest->Buffer = NULL; 660 Dest->MaximumLength = Dest->Length; 661 662 if(Dest->Length > 0 && Src) 663 { 664 Dest->Buffer = ExAllocatePoolWithTag(PagedPool, Dest->MaximumLength, TAG_STRING); 665 if(!Dest->Buffer) 666 { 667 return STATUS_NO_MEMORY; 668 } 669 670 Status = MmCopyFromCaller(Dest->Buffer, Src, Dest->Length); 671 if(!NT_SUCCESS(Status)) 672 { 673 ExFreePoolWithTag(Dest->Buffer, TAG_STRING); 674 Dest->Buffer = NULL; 675 return Status; 676 } 677 678 679 return STATUS_SUCCESS; 680 } 681 682 /* String is empty */ 683 return STATUS_SUCCESS; 684 } 685 686 NTSTATUS FASTCALL 687 IntSafeCopyUnicodeStringTerminateNULL(PUNICODE_STRING Dest, 688 PUNICODE_STRING Source) 689 { 690 NTSTATUS Status; 691 PWSTR Src; 692 693 Status = MmCopyFromCaller(Dest, Source, sizeof(UNICODE_STRING)); 694 if(!NT_SUCCESS(Status)) 695 { 696 return Status; 697 } 698 699 if(Dest->Length > 0x4000) 700 { 701 return STATUS_UNSUCCESSFUL; 702 } 703 704 Src = Dest->Buffer; 705 Dest->Buffer = NULL; 706 Dest->MaximumLength = 0; 707 708 if(Dest->Length > 0 && Src) 709 { 710 Dest->MaximumLength = Dest->Length + sizeof(WCHAR); 711 Dest->Buffer = ExAllocatePoolWithTag(PagedPool, Dest->MaximumLength, TAG_STRING); 712 if(!Dest->Buffer) 713 { 714 return STATUS_NO_MEMORY; 715 } 716 717 Status = MmCopyFromCaller(Dest->Buffer, Src, Dest->Length); 718 if(!NT_SUCCESS(Status)) 719 { 720 ExFreePoolWithTag(Dest->Buffer, TAG_STRING); 721 Dest->Buffer = NULL; 722 return Status; 723 } 724 725 /* Make sure the string is null-terminated */ 726 Src = (PWSTR)((PBYTE)Dest->Buffer + Dest->Length); 727 *Src = L'\0'; 728 729 return STATUS_SUCCESS; 730 } 731 732 /* String is empty */ 733 return STATUS_SUCCESS; 734 } 735 736 void UserDbgAssertThreadInfo(BOOL showCaller) 737 { 738 PTEB Teb; 739 PPROCESSINFO ppi; 740 PCLIENTINFO pci; 741 PTHREADINFO pti; 742 743 ppi = PsGetCurrentProcessWin32Process(); 744 pti = PsGetCurrentThreadWin32Thread(); 745 Teb = NtCurrentTeb(); 746 pci = GetWin32ClientInfo(); 747 748 ASSERT(Teb); 749 ASSERT(pti); 750 ASSERT(pti->ppi == ppi); 751 ASSERT(pti->pClientInfo == pci); 752 ASSERT(Teb->Win32ThreadInfo == pti); 753 ASSERT(pci->ppi == ppi); 754 ASSERT(pci->fsHooks == pti->fsHooks); 755 ASSERT(pci->ulClientDelta == DesktopHeapGetUserDelta()); 756 if (pti->pcti && pci->pDeskInfo) 757 ASSERT(pci->pClientThreadInfo == (PVOID)((ULONG_PTR)pti->pcti - pci->ulClientDelta)); 758 if (pti->KeyboardLayout) 759 ASSERT(pci->hKL == pti->KeyboardLayout->hkl); 760 if(pti->rpdesk != NULL) 761 ASSERT(pti->pDeskInfo == pti->rpdesk->pDeskInfo); 762 763 /*too bad we still get this assertion*/ 764 765 // Why? Not all flags are passed to the user and doing so could crash the system........ 766 767 /* ASSERT(pci->dwTIFlags == pti->TIF_flags); */ 768 /* if(pci->dwTIFlags != pti->TIF_flags) 769 { 770 ERR("pci->dwTIFlags(0x%x) doesn't match pti->TIF_flags(0x%x)\n", pci->dwTIFlags, pti->TIF_flags); 771 if(showCaller) 772 { 773 DbgPrint("Caller:\n"); 774 KeRosDumpStackFrames(NULL, 10); 775 } 776 pci->dwTIFlags = pti->TIF_flags; 777 } 778 */ 779 } 780 781 void 782 NTAPI 783 UserDbgPreServiceHook(ULONG ulSyscallId, PULONG_PTR pulArguments) 784 { 785 UserDbgAssertThreadInfo(FALSE); 786 } 787 788 ULONG_PTR 789 NTAPI 790 UserDbgPostServiceHook(ULONG ulSyscallId, ULONG_PTR ulResult) 791 { 792 /* Make sure that the first syscall is NtUserInitialize */ 793 /* too bad this fails */ 794 // ASSERT(gpepCSRSS); 795 796 UserDbgAssertThreadInfo(TRUE); 797 798 return ulResult; 799 } 800 801 802 PPROCESSINFO 803 GetW32ProcessInfo(VOID) 804 { 805 return (PPROCESSINFO)PsGetCurrentProcessWin32Process(); 806 } 807 808 PTHREADINFO 809 GetW32ThreadInfo(VOID) 810 { 811 UserDbgAssertThreadInfo(TRUE); 812 return (PTHREADINFO)PsGetCurrentThreadWin32Thread(); 813 } 814 815 816 NTSTATUS 817 GetProcessLuid( 818 IN PETHREAD Thread OPTIONAL, 819 IN PEPROCESS Process OPTIONAL, 820 OUT PLUID Luid) 821 { 822 NTSTATUS Status; 823 PACCESS_TOKEN Token = NULL; 824 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel; 825 BOOLEAN CopyOnOpen, EffectiveOnly; 826 827 if (Thread && Process) 828 return STATUS_INVALID_PARAMETER; 829 830 /* If nothing has been specified, use the current thread */ 831 if (!Thread && !Process) 832 Thread = PsGetCurrentThread(); 833 834 if (Thread) 835 { 836 /* Use a thread token */ 837 ASSERT(!Process); 838 Token = PsReferenceImpersonationToken(Thread, 839 &CopyOnOpen, 840 &EffectiveOnly, 841 &ImpersonationLevel); 842 843 /* If we don't have a thread token, use a process token */ 844 if (!Token) 845 Process = PsGetThreadProcess(Thread); 846 } 847 if (!Token && Process) 848 { 849 /* Use a process token */ 850 Token = PsReferencePrimaryToken(Process); 851 852 /* If we don't have a token, fail */ 853 if (!Token) 854 return STATUS_NO_TOKEN; 855 } 856 ASSERT(Token); 857 858 /* Query the LUID */ 859 Status = SeQueryAuthenticationIdToken(Token, Luid); 860 861 /* Get rid of the token and return */ 862 ObDereferenceObject(Token); 863 return Status; 864 } 865 866 /* EOF */ 867