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