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