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 BOOL Ret = FALSE; 414 415 TRACE("Enter NtUserGetGUIThreadInfo\n"); 416 UserEnterShared(); 417 418 Status = MmCopyFromCaller(&SafeGui, lpgui, sizeof(DWORD)); 419 if(!NT_SUCCESS(Status)) 420 { 421 SetLastNtError(Status); 422 goto Exit; // Return FALSE 423 } 424 425 if(SafeGui.cbSize != sizeof(GUITHREADINFO)) 426 { 427 EngSetLastError(ERROR_INVALID_PARAMETER); 428 goto Exit; // Return FALSE 429 } 430 431 if (idThread) 432 { 433 pti = PsGetCurrentThreadWin32Thread(); 434 435 // Validate Tread ID 436 W32Thread = IntTID2PTI((HANDLE)(DWORD_PTR)idThread); 437 438 if ( !W32Thread ) 439 { 440 EngSetLastError(ERROR_ACCESS_DENIED); 441 goto Exit; // Return FALSE 442 } 443 444 Desktop = W32Thread->rpdesk; 445 446 // Check Desktop and it must be the same as current. 447 if ( !Desktop || Desktop != pti->rpdesk ) 448 { 449 EngSetLastError(ERROR_ACCESS_DENIED); 450 goto Exit; // Return FALSE 451 } 452 453 if ( W32Thread->MessageQueue ) 454 MsgQueue = W32Thread->MessageQueue; 455 else 456 { 457 MsgQueue = Desktop->ActiveMessageQueue; 458 } 459 } 460 else 461 { /* Get the foreground thread */ 462 /* FIXME: Handle NULL queue properly? */ 463 MsgQueue = IntGetFocusMessageQueue(); 464 if(!MsgQueue) 465 { 466 EngSetLastError(ERROR_ACCESS_DENIED); 467 goto Exit; // Return FALSE 468 } 469 } 470 471 CaretInfo = &MsgQueue->CaretInfo; 472 473 SafeGui.flags = (CaretInfo->Visible ? GUI_CARETBLINKING : 0); 474 /* 475 if (W32Thread->pMenuState->pGlobalPopupMenu) 476 { 477 SafeGui.flags |= GUI_INMENUMODE; 478 479 if (W32Thread->pMenuState->pGlobalPopupMenu->spwndNotify) 480 SafeGui.hwndMenuOwner = UserHMGetHandle(W32Thread->pMenuState->pGlobalPopupMenu->spwndNotify); 481 482 if (W32Thread->pMenuState->pGlobalPopupMenu->fHasMenuBar) 483 { 484 if (W32Thread->pMenuState->pGlobalPopupMenu->fIsSysMenu) 485 { 486 SafeGui.flags |= GUI_SYSTEMMENUMODE; 487 } 488 } 489 else 490 { 491 SafeGui.flags |= GUI_POPUPMENUMODE; 492 } 493 } 494 */ 495 SafeGui.hwndMenuOwner = MsgQueue->MenuOwner; 496 497 if (MsgQueue->MenuOwner) 498 SafeGui.flags |= GUI_INMENUMODE | MsgQueue->MenuState; 499 500 if (MsgQueue->MoveSize) 501 SafeGui.flags |= GUI_INMOVESIZE; 502 503 /* FIXME: Add flag GUI_16BITTASK */ 504 505 SafeGui.hwndActive = MsgQueue->spwndActive ? UserHMGetHandle(MsgQueue->spwndActive) : 0; 506 SafeGui.hwndFocus = MsgQueue->spwndFocus ? UserHMGetHandle(MsgQueue->spwndFocus) : 0; 507 SafeGui.hwndCapture = MsgQueue->spwndCapture ? UserHMGetHandle(MsgQueue->spwndCapture) : 0; 508 SafeGui.hwndMoveSize = MsgQueue->MoveSize; 509 SafeGui.hwndCaret = CaretInfo->hWnd; 510 511 SafeGui.rcCaret.left = CaretInfo->Pos.x; 512 SafeGui.rcCaret.top = CaretInfo->Pos.y; 513 SafeGui.rcCaret.right = SafeGui.rcCaret.left + CaretInfo->Size.cx; 514 SafeGui.rcCaret.bottom = SafeGui.rcCaret.top + CaretInfo->Size.cy; 515 516 Status = MmCopyToCaller(lpgui, &SafeGui, sizeof(GUITHREADINFO)); 517 if(!NT_SUCCESS(Status)) 518 { 519 SetLastNtError(Status); 520 goto Exit; // Return FALSE 521 } 522 523 Ret = TRUE; 524 525 Exit: 526 TRACE("Leave NtUserGetGUIThreadInfo, ret=%i\n", Ret); 527 UserLeave(); 528 return Ret; 529 } 530 531 532 DWORD 533 APIENTRY 534 NtUserGetGuiResources( 535 HANDLE hProcess, 536 DWORD uiFlags) 537 { 538 PEPROCESS Process; 539 PPROCESSINFO W32Process; 540 NTSTATUS Status; 541 DWORD Ret = 0; 542 543 TRACE("Enter NtUserGetGuiResources\n"); 544 UserEnterShared(); 545 546 Status = ObReferenceObjectByHandle(hProcess, 547 PROCESS_QUERY_INFORMATION, 548 *PsProcessType, 549 ExGetPreviousMode(), 550 (PVOID*)&Process, 551 NULL); 552 553 if(!NT_SUCCESS(Status)) 554 { 555 SetLastNtError(Status); 556 goto Exit; // Return 0 557 } 558 559 W32Process = (PPROCESSINFO)Process->Win32Process; 560 if(!W32Process) 561 { 562 ObDereferenceObject(Process); 563 EngSetLastError(ERROR_INVALID_PARAMETER); 564 goto Exit; // Return 0 565 } 566 567 switch(uiFlags) 568 { 569 case GR_GDIOBJECTS: 570 { 571 Ret = (DWORD)W32Process->GDIHandleCount; 572 break; 573 } 574 case GR_USEROBJECTS: 575 { 576 Ret = (DWORD)W32Process->UserHandleCount; 577 break; 578 } 579 default: 580 { 581 EngSetLastError(ERROR_INVALID_PARAMETER); 582 break; 583 } 584 } 585 586 ObDereferenceObject(Process); 587 588 Exit: 589 TRACE("Leave NtUserGetGuiResources, ret=%lu\n", Ret); 590 UserLeave(); 591 return Ret; 592 } 593 594 VOID FASTCALL 595 IntSetWindowState(PWND pWnd, UINT Flag) 596 { 597 UINT bit; 598 if (gptiCurrent->ppi != pWnd->head.pti->ppi) return; 599 bit = 1 << LOWORD(Flag); 600 TRACE("SWS %x\n",bit); 601 switch(HIWORD(Flag)) 602 { 603 case 0: 604 pWnd->state |= bit; 605 break; 606 case 1: 607 pWnd->state2 |= bit; 608 break; 609 case 2: 610 pWnd->ExStyle2 |= bit; 611 break; 612 } 613 } 614 615 VOID FASTCALL 616 IntClearWindowState(PWND pWnd, UINT Flag) 617 { 618 UINT bit; 619 if (gptiCurrent->ppi != pWnd->head.pti->ppi) return; 620 bit = 1 << LOWORD(Flag); 621 TRACE("CWS %x\n",bit); 622 switch(HIWORD(Flag)) 623 { 624 case 0: 625 pWnd->state &= ~bit; 626 break; 627 case 1: 628 pWnd->state2 &= ~bit; 629 break; 630 case 2: 631 pWnd->ExStyle2 &= ~bit; 632 break; 633 } 634 } 635 636 NTSTATUS FASTCALL 637 IntSafeCopyUnicodeString(PUNICODE_STRING Dest, 638 PUNICODE_STRING Source) 639 { 640 NTSTATUS Status; 641 PWSTR Src; 642 643 Status = MmCopyFromCaller(Dest, Source, sizeof(UNICODE_STRING)); 644 if(!NT_SUCCESS(Status)) 645 { 646 return Status; 647 } 648 649 if(Dest->Length > 0x4000) 650 { 651 return STATUS_UNSUCCESSFUL; 652 } 653 654 Src = Dest->Buffer; 655 Dest->Buffer = NULL; 656 Dest->MaximumLength = Dest->Length; 657 658 if(Dest->Length > 0 && Src) 659 { 660 Dest->Buffer = ExAllocatePoolWithTag(PagedPool, Dest->MaximumLength, TAG_STRING); 661 if(!Dest->Buffer) 662 { 663 return STATUS_NO_MEMORY; 664 } 665 666 Status = MmCopyFromCaller(Dest->Buffer, Src, Dest->Length); 667 if(!NT_SUCCESS(Status)) 668 { 669 ExFreePoolWithTag(Dest->Buffer, TAG_STRING); 670 Dest->Buffer = NULL; 671 return Status; 672 } 673 674 675 return STATUS_SUCCESS; 676 } 677 678 /* String is empty */ 679 return STATUS_SUCCESS; 680 } 681 682 NTSTATUS FASTCALL 683 IntSafeCopyUnicodeStringTerminateNULL(PUNICODE_STRING Dest, 684 PUNICODE_STRING Source) 685 { 686 NTSTATUS Status; 687 PWSTR Src; 688 689 Status = MmCopyFromCaller(Dest, Source, sizeof(UNICODE_STRING)); 690 if(!NT_SUCCESS(Status)) 691 { 692 return Status; 693 } 694 695 if(Dest->Length > 0x4000) 696 { 697 return STATUS_UNSUCCESSFUL; 698 } 699 700 Src = Dest->Buffer; 701 Dest->Buffer = NULL; 702 Dest->MaximumLength = 0; 703 704 if(Dest->Length > 0 && Src) 705 { 706 Dest->MaximumLength = Dest->Length + sizeof(WCHAR); 707 Dest->Buffer = ExAllocatePoolWithTag(PagedPool, Dest->MaximumLength, TAG_STRING); 708 if(!Dest->Buffer) 709 { 710 return STATUS_NO_MEMORY; 711 } 712 713 Status = MmCopyFromCaller(Dest->Buffer, Src, Dest->Length); 714 if(!NT_SUCCESS(Status)) 715 { 716 ExFreePoolWithTag(Dest->Buffer, TAG_STRING); 717 Dest->Buffer = NULL; 718 return Status; 719 } 720 721 /* Make sure the string is null-terminated */ 722 Src = (PWSTR)((PBYTE)Dest->Buffer + Dest->Length); 723 *Src = L'\0'; 724 725 return STATUS_SUCCESS; 726 } 727 728 /* String is empty */ 729 return STATUS_SUCCESS; 730 } 731 732 void UserDbgAssertThreadInfo(BOOL showCaller) 733 { 734 PTEB Teb; 735 PPROCESSINFO ppi; 736 PCLIENTINFO pci; 737 PTHREADINFO pti; 738 739 ppi = PsGetCurrentProcessWin32Process(); 740 pti = PsGetCurrentThreadWin32Thread(); 741 Teb = NtCurrentTeb(); 742 pci = GetWin32ClientInfo(); 743 744 ASSERT(Teb); 745 ASSERT(pti); 746 ASSERT(pti->ppi == ppi); 747 ASSERT(pti->pClientInfo == pci); 748 ASSERT(Teb->Win32ThreadInfo == pti); 749 ASSERT(pci->ppi == ppi); 750 ASSERT(pci->fsHooks == pti->fsHooks); 751 ASSERT(pci->ulClientDelta == DesktopHeapGetUserDelta()); 752 if (pti->pcti && pci->pDeskInfo) 753 ASSERT(pci->pClientThreadInfo == (PVOID)((ULONG_PTR)pti->pcti - pci->ulClientDelta)); 754 if (pti->KeyboardLayout) 755 ASSERT(pci->hKL == pti->KeyboardLayout->hkl); 756 if(pti->rpdesk != NULL) 757 ASSERT(pti->pDeskInfo == pti->rpdesk->pDeskInfo); 758 759 /*too bad we still get this assertion*/ 760 761 // Why? Not all flags are passed to the user and doing so could crash the system........ 762 763 /* ASSERT(pci->dwTIFlags == pti->TIF_flags); */ 764 /* if(pci->dwTIFlags != pti->TIF_flags) 765 { 766 ERR("pci->dwTIFlags(0x%x) doesn't match pti->TIF_flags(0x%x)\n", pci->dwTIFlags, pti->TIF_flags); 767 if(showCaller) 768 { 769 DbgPrint("Caller:\n"); 770 KeRosDumpStackFrames(NULL, 10); 771 } 772 pci->dwTIFlags = pti->TIF_flags; 773 } 774 */ 775 } 776 777 void 778 NTAPI 779 UserDbgPreServiceHook(ULONG ulSyscallId, PULONG_PTR pulArguments) 780 { 781 UserDbgAssertThreadInfo(FALSE); 782 } 783 784 ULONG_PTR 785 NTAPI 786 UserDbgPostServiceHook(ULONG ulSyscallId, ULONG_PTR ulResult) 787 { 788 /* Make sure that the first syscall is NtUserInitialize */ 789 /* too bad this fails */ 790 // ASSERT(gpepCSRSS); 791 792 UserDbgAssertThreadInfo(TRUE); 793 794 return ulResult; 795 } 796 797 798 PPROCESSINFO 799 GetW32ProcessInfo(VOID) 800 { 801 return (PPROCESSINFO)PsGetCurrentProcessWin32Process(); 802 } 803 804 PTHREADINFO 805 GetW32ThreadInfo(VOID) 806 { 807 UserDbgAssertThreadInfo(TRUE); 808 return (PTHREADINFO)PsGetCurrentThreadWin32Thread(); 809 } 810 811 812 NTSTATUS 813 GetProcessLuid( 814 IN PETHREAD Thread OPTIONAL, 815 IN PEPROCESS Process OPTIONAL, 816 OUT PLUID Luid) 817 { 818 NTSTATUS Status; 819 PACCESS_TOKEN Token = NULL; 820 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel; 821 BOOLEAN CopyOnOpen, EffectiveOnly; 822 823 if (Thread && Process) 824 return STATUS_INVALID_PARAMETER; 825 826 /* If nothing has been specified, use the current thread */ 827 if (!Thread && !Process) 828 Thread = PsGetCurrentThread(); 829 830 if (Thread) 831 { 832 /* Use a thread token */ 833 ASSERT(!Process); 834 Token = PsReferenceImpersonationToken(Thread, 835 &CopyOnOpen, 836 &EffectiveOnly, 837 &ImpersonationLevel); 838 839 /* If we don't have a thread token, use a process token */ 840 if (!Token) 841 Process = PsGetThreadProcess(Thread); 842 } 843 if (!Token && Process) 844 { 845 /* Use a process token */ 846 Token = PsReferencePrimaryToken(Process); 847 848 /* If we don't have a token, fail */ 849 if (!Token) 850 return STATUS_NO_TOKEN; 851 } 852 ASSERT(Token); 853 854 /* Query the LUID */ 855 Status = SeQueryAuthenticationIdToken(Token, Luid); 856 857 /* Get rid of the token and return */ 858 ObDereferenceObject(Token); 859 return Status; 860 } 861 862 /* EOF */ 863