1 /* 2 * PROJECT: ReactOS Kernel 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: ntoskrnl/ps/query.c 5 * PURPOSE: Process Manager: Thread/Process Query/Set Information 6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 7 * Thomas Weidenmueller (w3seek@reactos.org) 8 * Eric Kohl 9 */ 10 11 /* INCLUDES ******************************************************************/ 12 13 #include <ntoskrnl.h> 14 #define NDEBUG 15 #include <debug.h> 16 17 /* Debugging Level */ 18 ULONG PspTraceLevel = 0; 19 20 /* PRIVATE FUNCTIONS *********************************************************/ 21 22 NTSTATUS 23 NTAPI 24 PsReferenceProcessFilePointer(IN PEPROCESS Process, 25 OUT PFILE_OBJECT *FileObject) 26 { 27 PSECTION Section; 28 PAGED_CODE(); 29 30 /* Lock the process */ 31 if (!ExAcquireRundownProtection(&Process->RundownProtect)) 32 { 33 return STATUS_PROCESS_IS_TERMINATING; 34 } 35 36 /* Get the section */ 37 Section = Process->SectionObject; 38 if (Section) 39 { 40 /* Get the file object and reference it */ 41 *FileObject = MmGetFileObjectForSection((PVOID)Section); 42 ObReferenceObject(*FileObject); 43 } 44 45 /* Release the protection */ 46 ExReleaseRundownProtection(&Process->RundownProtect); 47 48 /* Return status */ 49 return Section ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL; 50 } 51 52 /* PUBLIC FUNCTIONS **********************************************************/ 53 54 /* 55 * @implemented 56 */ 57 NTSTATUS 58 NTAPI 59 NtQueryInformationProcess( 60 _In_ HANDLE ProcessHandle, 61 _In_ PROCESSINFOCLASS ProcessInformationClass, 62 _Out_ PVOID ProcessInformation, 63 _In_ ULONG ProcessInformationLength, 64 _Out_opt_ PULONG ReturnLength) 65 { 66 PEPROCESS Process; 67 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 68 NTSTATUS Status; 69 ULONG Length = 0; 70 HANDLE DebugPort = 0; 71 PPROCESS_BASIC_INFORMATION ProcessBasicInfo = 72 (PPROCESS_BASIC_INFORMATION)ProcessInformation; 73 PKERNEL_USER_TIMES ProcessTime = (PKERNEL_USER_TIMES)ProcessInformation; 74 ULONG UserTime, KernelTime; 75 PPROCESS_PRIORITY_CLASS PsPriorityClass = (PPROCESS_PRIORITY_CLASS)ProcessInformation; 76 ULONG HandleCount; 77 PPROCESS_SESSION_INFORMATION SessionInfo = 78 (PPROCESS_SESSION_INFORMATION)ProcessInformation; 79 PVM_COUNTERS VmCounters = (PVM_COUNTERS)ProcessInformation; 80 PIO_COUNTERS IoCounters = (PIO_COUNTERS)ProcessInformation; 81 PQUOTA_LIMITS QuotaLimits = (PQUOTA_LIMITS)ProcessInformation; 82 PUNICODE_STRING ImageName; 83 ULONG Cookie, ExecuteOptions = 0; 84 ULONG_PTR Wow64 = 0; 85 PROCESS_VALUES ProcessValues; 86 ULONG Flags; 87 PAGED_CODE(); 88 89 /* Verify Information Class validity */ 90 Status = DefaultQueryInfoBufferCheck(ProcessInformationClass, 91 PsProcessInfoClass, 92 RTL_NUMBER_OF(PsProcessInfoClass), 93 ProcessInformation, 94 ProcessInformationLength, 95 ReturnLength, 96 NULL, 97 PreviousMode, 98 FALSE); 99 if (!NT_SUCCESS(Status)) 100 { 101 DPRINT1("NtQueryInformationProcess(): Information verification class failed! (Status -> 0x%lx, ProcessInformationClass -> %lx)\n", Status, ProcessInformationClass); 102 return Status; 103 } 104 105 if (((ProcessInformationClass == ProcessCookie) || 106 (ProcessInformationClass == ProcessImageInformation)) && 107 (ProcessHandle != NtCurrentProcess())) 108 { 109 /* 110 * Retrieving the process cookie is only allowed for the calling process 111 * itself! XP only allows NtCurrentProcess() as process handles even if 112 * a real handle actually represents the current process. 113 */ 114 return STATUS_INVALID_PARAMETER; 115 } 116 117 /* Check the information class */ 118 switch (ProcessInformationClass) 119 { 120 /* Basic process information */ 121 case ProcessBasicInformation: 122 123 if (ProcessInformationLength != sizeof(PROCESS_BASIC_INFORMATION)) 124 { 125 Status = STATUS_INFO_LENGTH_MISMATCH; 126 break; 127 } 128 129 /* Set return length */ 130 Length = sizeof(PROCESS_BASIC_INFORMATION); 131 132 /* Reference the process */ 133 Status = ObReferenceObjectByHandle(ProcessHandle, 134 PROCESS_QUERY_INFORMATION, 135 PsProcessType, 136 PreviousMode, 137 (PVOID*)&Process, 138 NULL); 139 if (!NT_SUCCESS(Status)) break; 140 141 /* Protect writes with SEH */ 142 _SEH2_TRY 143 { 144 /* Write all the information from the EPROCESS/KPROCESS */ 145 ProcessBasicInfo->ExitStatus = Process->ExitStatus; 146 ProcessBasicInfo->PebBaseAddress = Process->Peb; 147 ProcessBasicInfo->AffinityMask = Process->Pcb.Affinity; 148 ProcessBasicInfo->UniqueProcessId = (ULONG_PTR)Process-> 149 UniqueProcessId; 150 ProcessBasicInfo->InheritedFromUniqueProcessId = 151 (ULONG_PTR)Process->InheritedFromUniqueProcessId; 152 ProcessBasicInfo->BasePriority = Process->Pcb.BasePriority; 153 154 } 155 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 156 { 157 /* Get exception code */ 158 Status = _SEH2_GetExceptionCode(); 159 } 160 _SEH2_END; 161 162 /* Dereference the process */ 163 ObDereferenceObject(Process); 164 break; 165 166 /* Process quota limits */ 167 case ProcessQuotaLimits: 168 169 if (ProcessInformationLength != sizeof(QUOTA_LIMITS)) 170 { 171 Status = STATUS_INFO_LENGTH_MISMATCH; 172 break; 173 } 174 175 Length = sizeof(QUOTA_LIMITS); 176 177 /* Reference the process */ 178 Status = ObReferenceObjectByHandle(ProcessHandle, 179 PROCESS_QUERY_INFORMATION, 180 PsProcessType, 181 PreviousMode, 182 (PVOID*)&Process, 183 NULL); 184 if (!NT_SUCCESS(Status)) break; 185 186 /* Indicate success */ 187 Status = STATUS_SUCCESS; 188 189 _SEH2_TRY 190 { 191 /* Set max/min working set sizes */ 192 QuotaLimits->MaximumWorkingSetSize = 193 Process->Vm.MaximumWorkingSetSize << PAGE_SHIFT; 194 QuotaLimits->MinimumWorkingSetSize = 195 Process->Vm.MinimumWorkingSetSize << PAGE_SHIFT; 196 197 /* Set default time limits */ 198 QuotaLimits->TimeLimit.LowPart = MAXULONG; 199 QuotaLimits->TimeLimit.HighPart = MAXULONG; 200 201 /* Is quota block a default one? */ 202 if (Process->QuotaBlock == &PspDefaultQuotaBlock) 203 { 204 /* Set default pools and pagefile limits */ 205 QuotaLimits->PagedPoolLimit = (SIZE_T)-1; 206 QuotaLimits->NonPagedPoolLimit = (SIZE_T)-1; 207 QuotaLimits->PagefileLimit = (SIZE_T)-1; 208 } 209 else 210 { 211 /* Get limits from non-default quota block */ 212 QuotaLimits->PagedPoolLimit = 213 Process->QuotaBlock->QuotaEntry[PsPagedPool].Limit; 214 QuotaLimits->NonPagedPoolLimit = 215 Process->QuotaBlock->QuotaEntry[PsNonPagedPool].Limit; 216 QuotaLimits->PagefileLimit = 217 Process->QuotaBlock->QuotaEntry[PsPageFile].Limit; 218 } 219 } 220 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 221 { 222 /* Get exception code */ 223 Status = _SEH2_GetExceptionCode(); 224 } 225 _SEH2_END; 226 227 /* Dereference the process */ 228 ObDereferenceObject(Process); 229 break; 230 231 case ProcessIoCounters: 232 233 if (ProcessInformationLength != sizeof(IO_COUNTERS)) 234 { 235 Status = STATUS_INFO_LENGTH_MISMATCH; 236 break; 237 } 238 239 Length = sizeof(IO_COUNTERS); 240 241 /* Reference the process */ 242 Status = ObReferenceObjectByHandle(ProcessHandle, 243 PROCESS_QUERY_INFORMATION, 244 PsProcessType, 245 PreviousMode, 246 (PVOID*)&Process, 247 NULL); 248 if (!NT_SUCCESS(Status)) break; 249 250 /* Query IO counters from the process */ 251 KeQueryValuesProcess(&Process->Pcb, &ProcessValues); 252 253 _SEH2_TRY 254 { 255 RtlCopyMemory(IoCounters, &ProcessValues.IoInfo, sizeof(IO_COUNTERS)); 256 } 257 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 258 { 259 /* Ignore exception */ 260 } 261 _SEH2_END; 262 263 /* Set status to success in any case */ 264 Status = STATUS_SUCCESS; 265 266 /* Dereference the process */ 267 ObDereferenceObject(Process); 268 break; 269 270 /* Timing */ 271 case ProcessTimes: 272 273 /* Set the return length */ 274 if (ProcessInformationLength != sizeof(KERNEL_USER_TIMES)) 275 { 276 Status = STATUS_INFO_LENGTH_MISMATCH; 277 break; 278 } 279 280 Length = sizeof(KERNEL_USER_TIMES); 281 282 /* Reference the process */ 283 Status = ObReferenceObjectByHandle(ProcessHandle, 284 PROCESS_QUERY_INFORMATION, 285 PsProcessType, 286 PreviousMode, 287 (PVOID*)&Process, 288 NULL); 289 if (!NT_SUCCESS(Status)) break; 290 291 /* Protect writes with SEH */ 292 _SEH2_TRY 293 { 294 /* Copy time information from EPROCESS/KPROCESS */ 295 KernelTime = KeQueryRuntimeProcess(&Process->Pcb, &UserTime); 296 ProcessTime->CreateTime = Process->CreateTime; 297 ProcessTime->UserTime.QuadPart = (LONGLONG)UserTime * KeMaximumIncrement; 298 ProcessTime->KernelTime.QuadPart = (LONGLONG)KernelTime * KeMaximumIncrement; 299 ProcessTime->ExitTime = Process->ExitTime; 300 } 301 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 302 { 303 /* Get exception code */ 304 Status = _SEH2_GetExceptionCode(); 305 } 306 _SEH2_END; 307 308 /* Dereference the process */ 309 ObDereferenceObject(Process); 310 break; 311 312 /* Process Debug Port */ 313 case ProcessDebugPort: 314 315 if (ProcessInformationLength != sizeof(HANDLE)) 316 { 317 Status = STATUS_INFO_LENGTH_MISMATCH; 318 break; 319 } 320 321 /* Set return length */ 322 Length = sizeof(HANDLE); 323 324 /* Reference the process */ 325 Status = ObReferenceObjectByHandle(ProcessHandle, 326 PROCESS_QUERY_INFORMATION, 327 PsProcessType, 328 PreviousMode, 329 (PVOID*)&Process, 330 NULL); 331 if (!NT_SUCCESS(Status)) break; 332 333 /* Protect write with SEH */ 334 _SEH2_TRY 335 { 336 /* Return whether or not we have a debug port */ 337 *(PHANDLE)ProcessInformation = (Process->DebugPort ? 338 (HANDLE)-1 : NULL); 339 } 340 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 341 { 342 /* Get exception code */ 343 Status = _SEH2_GetExceptionCode(); 344 } 345 _SEH2_END; 346 347 /* Dereference the process */ 348 ObDereferenceObject(Process); 349 break; 350 351 case ProcessHandleCount: 352 353 if (ProcessInformationLength != sizeof(ULONG)) 354 { 355 Status = STATUS_INFO_LENGTH_MISMATCH; 356 break; 357 } 358 359 /* Set the return length*/ 360 Length = sizeof(ULONG); 361 362 /* Reference the process */ 363 Status = ObReferenceObjectByHandle(ProcessHandle, 364 PROCESS_QUERY_INFORMATION, 365 PsProcessType, 366 PreviousMode, 367 (PVOID*)&Process, 368 NULL); 369 if (!NT_SUCCESS(Status)) break; 370 371 /* Count the number of handles this process has */ 372 HandleCount = ObGetProcessHandleCount(Process); 373 374 /* Protect write in SEH */ 375 _SEH2_TRY 376 { 377 /* Return the count of handles */ 378 *(PULONG)ProcessInformation = HandleCount; 379 } 380 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 381 { 382 /* Get the exception code */ 383 Status = _SEH2_GetExceptionCode(); 384 } 385 _SEH2_END; 386 387 /* Dereference the process */ 388 ObDereferenceObject(Process); 389 break; 390 391 /* Session ID for the process */ 392 case ProcessSessionInformation: 393 394 if (ProcessInformationLength != sizeof(PROCESS_SESSION_INFORMATION)) 395 { 396 Status = STATUS_INFO_LENGTH_MISMATCH; 397 break; 398 } 399 400 /* Set the return length*/ 401 Length = sizeof(PROCESS_SESSION_INFORMATION); 402 403 /* Reference the process */ 404 Status = ObReferenceObjectByHandle(ProcessHandle, 405 PROCESS_QUERY_INFORMATION, 406 PsProcessType, 407 PreviousMode, 408 (PVOID*)&Process, 409 NULL); 410 if (!NT_SUCCESS(Status)) break; 411 412 /* Enter SEH for write safety */ 413 _SEH2_TRY 414 { 415 /* Write back the Session ID */ 416 SessionInfo->SessionId = PsGetProcessSessionId(Process); 417 } 418 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 419 { 420 /* Get the exception code */ 421 Status = _SEH2_GetExceptionCode(); 422 } 423 _SEH2_END; 424 425 /* Dereference the process */ 426 ObDereferenceObject(Process); 427 break; 428 429 /* Virtual Memory Statistics */ 430 case ProcessVmCounters: 431 432 /* Validate the input length */ 433 if ((ProcessInformationLength != sizeof(VM_COUNTERS)) && 434 (ProcessInformationLength != sizeof(VM_COUNTERS_EX))) 435 { 436 Status = STATUS_INFO_LENGTH_MISMATCH; 437 break; 438 } 439 440 /* Reference the process */ 441 Status = ObReferenceObjectByHandle(ProcessHandle, 442 PROCESS_QUERY_INFORMATION, 443 PsProcessType, 444 PreviousMode, 445 (PVOID*)&Process, 446 NULL); 447 if (!NT_SUCCESS(Status)) break; 448 449 /* Enter SEH for write safety */ 450 _SEH2_TRY 451 { 452 /* Return data from EPROCESS */ 453 VmCounters->PeakVirtualSize = Process->PeakVirtualSize; 454 VmCounters->VirtualSize = Process->VirtualSize; 455 VmCounters->PageFaultCount = Process->Vm.PageFaultCount; 456 VmCounters->PeakWorkingSetSize = Process->Vm.PeakWorkingSetSize; 457 VmCounters->WorkingSetSize = Process->Vm.WorkingSetSize; 458 VmCounters->QuotaPeakPagedPoolUsage = Process->QuotaPeak[PsPagedPool]; 459 VmCounters->QuotaPagedPoolUsage = Process->QuotaUsage[PsPagedPool]; 460 VmCounters->QuotaPeakNonPagedPoolUsage = Process->QuotaPeak[PsNonPagedPool]; 461 VmCounters->QuotaNonPagedPoolUsage = Process->QuotaUsage[PsNonPagedPool]; 462 VmCounters->PagefileUsage = Process->QuotaUsage[PsPageFile] << PAGE_SHIFT; 463 VmCounters->PeakPagefileUsage = Process->QuotaPeak[PsPageFile] << PAGE_SHIFT; 464 //VmCounters->PrivateUsage = Process->CommitCharge << PAGE_SHIFT; 465 // 466 467 /* Set the return length */ 468 Length = ProcessInformationLength; 469 } 470 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 471 { 472 /* Get the exception code */ 473 Status = _SEH2_GetExceptionCode(); 474 } 475 _SEH2_END; 476 477 /* Dereference the process */ 478 ObDereferenceObject(Process); 479 break; 480 481 /* Hard Error Processing Mode */ 482 case ProcessDefaultHardErrorMode: 483 484 if (ProcessInformationLength != sizeof(ULONG)) 485 { 486 Status = STATUS_INFO_LENGTH_MISMATCH; 487 break; 488 } 489 490 /* Set the return length*/ 491 Length = sizeof(ULONG); 492 493 /* Reference the process */ 494 Status = ObReferenceObjectByHandle(ProcessHandle, 495 PROCESS_QUERY_INFORMATION, 496 PsProcessType, 497 PreviousMode, 498 (PVOID*)&Process, 499 NULL); 500 if (!NT_SUCCESS(Status)) break; 501 502 /* Enter SEH for writing back data */ 503 _SEH2_TRY 504 { 505 /* Write the current processing mode */ 506 *(PULONG)ProcessInformation = Process-> 507 DefaultHardErrorProcessing; 508 } 509 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 510 { 511 /* Get the exception code */ 512 Status = _SEH2_GetExceptionCode(); 513 } 514 _SEH2_END; 515 516 /* Dereference the process */ 517 ObDereferenceObject(Process); 518 break; 519 520 /* Priority Boosting status */ 521 case ProcessPriorityBoost: 522 523 if (ProcessInformationLength != sizeof(ULONG)) 524 { 525 Status = STATUS_INFO_LENGTH_MISMATCH; 526 break; 527 } 528 529 /* Set the return length */ 530 Length = sizeof(ULONG); 531 532 /* Reference the process */ 533 Status = ObReferenceObjectByHandle(ProcessHandle, 534 PROCESS_QUERY_INFORMATION, 535 PsProcessType, 536 PreviousMode, 537 (PVOID*)&Process, 538 NULL); 539 if (!NT_SUCCESS(Status)) break; 540 541 /* Enter SEH for writing back data */ 542 _SEH2_TRY 543 { 544 /* Return boost status */ 545 *(PULONG)ProcessInformation = Process->Pcb.DisableBoost ? 546 TRUE : FALSE; 547 } 548 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 549 { 550 /* Get the exception code */ 551 Status = _SEH2_GetExceptionCode(); 552 } 553 _SEH2_END; 554 555 /* Dereference the process */ 556 ObDereferenceObject(Process); 557 break; 558 559 /* DOS Device Map */ 560 case ProcessDeviceMap: 561 562 if (ProcessInformationLength == sizeof(PROCESS_DEVICEMAP_INFORMATION_EX)) 563 { 564 /* Protect read in SEH */ 565 _SEH2_TRY 566 { 567 PPROCESS_DEVICEMAP_INFORMATION_EX DeviceMapEx = ProcessInformation; 568 569 Flags = DeviceMapEx->Flags; 570 } 571 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 572 { 573 /* Get the exception code */ 574 Status = _SEH2_GetExceptionCode(); 575 _SEH2_YIELD(break); 576 } 577 _SEH2_END; 578 579 /* Only one flag is supported and it needs LUID mappings */ 580 if ((Flags & ~PROCESS_LUID_DOSDEVICES_ONLY) != 0 || 581 !ObIsLUIDDeviceMapsEnabled()) 582 { 583 Status = STATUS_INVALID_PARAMETER; 584 break; 585 } 586 } 587 else 588 { 589 /* This has to be the size of the Query union field for x64 compatibility! */ 590 if (ProcessInformationLength != RTL_FIELD_SIZE(PROCESS_DEVICEMAP_INFORMATION, Query)) 591 { 592 Status = STATUS_INFO_LENGTH_MISMATCH; 593 break; 594 } 595 596 /* No flags for standard call */ 597 Flags = 0; 598 } 599 600 /* Set the return length */ 601 Length = ProcessInformationLength; 602 603 /* Reference the process */ 604 Status = ObReferenceObjectByHandle(ProcessHandle, 605 PROCESS_QUERY_INFORMATION, 606 PsProcessType, 607 PreviousMode, 608 (PVOID*)&Process, 609 NULL); 610 if (!NT_SUCCESS(Status)) break; 611 612 /* Query the device map information */ 613 Status = ObQueryDeviceMapInformation(Process, 614 ProcessInformation, 615 Flags); 616 617 /* Dereference the process */ 618 ObDereferenceObject(Process); 619 break; 620 621 /* Priority class */ 622 case ProcessPriorityClass: 623 624 if (ProcessInformationLength != sizeof(PROCESS_PRIORITY_CLASS)) 625 { 626 Status = STATUS_INFO_LENGTH_MISMATCH; 627 break; 628 } 629 630 /* Set the return length*/ 631 Length = sizeof(PROCESS_PRIORITY_CLASS); 632 633 /* Reference the process */ 634 Status = ObReferenceObjectByHandle(ProcessHandle, 635 PROCESS_QUERY_INFORMATION, 636 PsProcessType, 637 PreviousMode, 638 (PVOID*)&Process, 639 NULL); 640 if (!NT_SUCCESS(Status)) break; 641 642 /* Enter SEH for writing back data */ 643 _SEH2_TRY 644 { 645 /* Return current priority class */ 646 PsPriorityClass->PriorityClass = Process->PriorityClass; 647 PsPriorityClass->Foreground = FALSE; 648 } 649 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 650 { 651 /* Get the exception code */ 652 Status = _SEH2_GetExceptionCode(); 653 } 654 _SEH2_END; 655 656 /* Dereference the process */ 657 ObDereferenceObject(Process); 658 break; 659 660 case ProcessImageFileName: 661 662 /* Reference the process */ 663 Status = ObReferenceObjectByHandle(ProcessHandle, 664 PROCESS_QUERY_INFORMATION, 665 PsProcessType, 666 PreviousMode, 667 (PVOID*)&Process, 668 NULL); 669 if (!NT_SUCCESS(Status)) break; 670 671 /* Get the image path */ 672 Status = SeLocateProcessImageName(Process, &ImageName); 673 if (NT_SUCCESS(Status)) 674 { 675 /* Set return length */ 676 Length = ImageName->MaximumLength + 677 sizeof(OBJECT_NAME_INFORMATION); 678 679 /* Make sure it's large enough */ 680 if (Length <= ProcessInformationLength) 681 { 682 /* Enter SEH to protect write */ 683 _SEH2_TRY 684 { 685 /* Copy it */ 686 RtlCopyMemory(ProcessInformation, 687 ImageName, 688 Length); 689 690 /* Update pointer */ 691 ((PUNICODE_STRING)ProcessInformation)->Buffer = 692 (PWSTR)((PUNICODE_STRING)ProcessInformation + 1); 693 } 694 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 695 { 696 /* Get the exception code */ 697 Status = _SEH2_GetExceptionCode(); 698 } 699 _SEH2_END; 700 } 701 else 702 { 703 /* Buffer too small */ 704 Status = STATUS_INFO_LENGTH_MISMATCH; 705 } 706 707 /* Free the image path */ 708 ExFreePoolWithTag(ImageName, TAG_SEPA); 709 } 710 /* Dereference the process */ 711 ObDereferenceObject(Process); 712 break; 713 714 case ProcessDebugFlags: 715 716 if (ProcessInformationLength != sizeof(ULONG)) 717 { 718 Status = STATUS_INFO_LENGTH_MISMATCH; 719 break; 720 } 721 722 /* Set the return length*/ 723 Length = sizeof(ULONG); 724 725 /* Reference the process */ 726 Status = ObReferenceObjectByHandle(ProcessHandle, 727 PROCESS_QUERY_INFORMATION, 728 PsProcessType, 729 PreviousMode, 730 (PVOID*)&Process, 731 NULL); 732 if (!NT_SUCCESS(Status)) break; 733 734 /* Enter SEH for writing back data */ 735 _SEH2_TRY 736 { 737 /* Return the debug flag state */ 738 *(PULONG)ProcessInformation = Process->NoDebugInherit ? 0 : 1; 739 } 740 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 741 { 742 /* Get the exception code */ 743 Status = _SEH2_GetExceptionCode(); 744 } 745 _SEH2_END; 746 747 /* Dereference the process */ 748 ObDereferenceObject(Process); 749 break; 750 751 case ProcessBreakOnTermination: 752 753 if (ProcessInformationLength != sizeof(ULONG)) 754 { 755 Status = STATUS_INFO_LENGTH_MISMATCH; 756 break; 757 } 758 759 /* Set the return length */ 760 Length = sizeof(ULONG); 761 762 /* Reference the process */ 763 Status = ObReferenceObjectByHandle(ProcessHandle, 764 PROCESS_QUERY_INFORMATION, 765 PsProcessType, 766 PreviousMode, 767 (PVOID*)&Process, 768 NULL); 769 if (!NT_SUCCESS(Status)) break; 770 771 /* Enter SEH for writing back data */ 772 _SEH2_TRY 773 { 774 /* Return the BreakOnTermination state */ 775 *(PULONG)ProcessInformation = Process->BreakOnTermination; 776 } 777 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 778 { 779 /* Get the exception code */ 780 Status = _SEH2_GetExceptionCode(); 781 } 782 _SEH2_END; 783 784 /* Dereference the process */ 785 ObDereferenceObject(Process); 786 break; 787 788 /* Per-process security cookie */ 789 case ProcessCookie: 790 791 if (ProcessInformationLength != sizeof(ULONG)) 792 { 793 /* Length size wrong, bail out */ 794 Status = STATUS_INFO_LENGTH_MISMATCH; 795 break; 796 } 797 798 /* Get the current process and cookie */ 799 Process = PsGetCurrentProcess(); 800 Cookie = Process->Cookie; 801 if (!Cookie) 802 { 803 LARGE_INTEGER SystemTime; 804 ULONG NewCookie; 805 PKPRCB Prcb; 806 807 /* Generate a new cookie */ 808 KeQuerySystemTime(&SystemTime); 809 Prcb = KeGetCurrentPrcb(); 810 NewCookie = Prcb->KeSystemCalls ^ Prcb->InterruptTime ^ 811 SystemTime.u.LowPart ^ SystemTime.u.HighPart; 812 813 /* Set the new cookie or return the current one */ 814 Cookie = InterlockedCompareExchange((LONG*)&Process->Cookie, 815 NewCookie, 816 Cookie); 817 if (!Cookie) Cookie = NewCookie; 818 819 /* Set return length */ 820 Length = sizeof(ULONG); 821 } 822 823 /* Indicate success */ 824 Status = STATUS_SUCCESS; 825 826 /* Enter SEH to protect write */ 827 _SEH2_TRY 828 { 829 /* Write back the cookie */ 830 *(PULONG)ProcessInformation = Cookie; 831 } 832 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 833 { 834 /* Get the exception code */ 835 Status = _SEH2_GetExceptionCode(); 836 } 837 _SEH2_END; 838 break; 839 840 case ProcessImageInformation: 841 842 if (ProcessInformationLength != sizeof(SECTION_IMAGE_INFORMATION)) 843 { 844 /* Break out */ 845 Status = STATUS_INFO_LENGTH_MISMATCH; 846 break; 847 } 848 849 /* Set the length required and validate it */ 850 Length = sizeof(SECTION_IMAGE_INFORMATION); 851 852 /* Enter SEH to protect write */ 853 _SEH2_TRY 854 { 855 MmGetImageInformation((PSECTION_IMAGE_INFORMATION)ProcessInformation); 856 } 857 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 858 { 859 /* Get the exception code */ 860 Status = _SEH2_GetExceptionCode(); 861 } 862 _SEH2_END; 863 864 /* Indicate success */ 865 Status = STATUS_SUCCESS; 866 break; 867 868 case ProcessDebugObjectHandle: 869 870 if (ProcessInformationLength != sizeof(HANDLE)) 871 { 872 Status = STATUS_INFO_LENGTH_MISMATCH; 873 break; 874 } 875 876 /* Set the return length */ 877 Length = sizeof(HANDLE); 878 879 /* Reference the process */ 880 Status = ObReferenceObjectByHandle(ProcessHandle, 881 PROCESS_QUERY_INFORMATION, 882 PsProcessType, 883 PreviousMode, 884 (PVOID*)&Process, 885 NULL); 886 if (!NT_SUCCESS(Status)) break; 887 888 /* Get the debug port */ 889 Status = DbgkOpenProcessDebugPort(Process, PreviousMode, &DebugPort); 890 891 /* Let go of the process */ 892 ObDereferenceObject(Process); 893 894 /* Protect write in SEH */ 895 _SEH2_TRY 896 { 897 /* Return debug port's handle */ 898 *(PHANDLE)ProcessInformation = DebugPort; 899 } 900 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 901 { 902 /* Get the exception code */ 903 Status = _SEH2_GetExceptionCode(); 904 } 905 _SEH2_END; 906 break; 907 908 case ProcessHandleTracing: 909 DPRINT1("Handle tracing Not implemented: %lx\n", ProcessInformationClass); 910 Status = STATUS_NOT_IMPLEMENTED; 911 break; 912 913 case ProcessLUIDDeviceMapsEnabled: 914 915 if (ProcessInformationLength != sizeof(ULONG)) 916 { 917 Status = STATUS_INFO_LENGTH_MISMATCH; 918 break; 919 } 920 921 /* Set the return length */ 922 Length = sizeof(ULONG); 923 924 /* Indicate success */ 925 Status = STATUS_SUCCESS; 926 927 /* Protect write in SEH */ 928 _SEH2_TRY 929 { 930 /* Query Ob */ 931 *(PULONG)ProcessInformation = ObIsLUIDDeviceMapsEnabled(); 932 } 933 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 934 { 935 /* Get the exception code */ 936 Status = _SEH2_GetExceptionCode(); 937 } 938 _SEH2_END; 939 break; 940 941 case ProcessWx86Information: 942 943 if (ProcessInformationLength != sizeof(ULONG)) 944 { 945 Status = STATUS_INFO_LENGTH_MISMATCH; 946 break; 947 } 948 949 /* Set the return length */ 950 Length = sizeof(ULONG); 951 952 /* Reference the process */ 953 Status = ObReferenceObjectByHandle(ProcessHandle, 954 PROCESS_QUERY_INFORMATION, 955 PsProcessType, 956 PreviousMode, 957 (PVOID*)&Process, 958 NULL); 959 if (!NT_SUCCESS(Status)) break; 960 961 /* Protect write in SEH */ 962 _SEH2_TRY 963 { 964 /* Return if the flag is set */ 965 *(PULONG)ProcessInformation = (ULONG)Process->VdmAllowed; 966 } 967 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 968 { 969 /* Get the exception code */ 970 Status = _SEH2_GetExceptionCode(); 971 } 972 _SEH2_END; 973 974 /* Dereference the process */ 975 ObDereferenceObject(Process); 976 break; 977 978 case ProcessWow64Information: 979 980 if (ProcessInformationLength != sizeof(ULONG_PTR)) 981 { 982 Status = STATUS_INFO_LENGTH_MISMATCH; 983 break; 984 } 985 986 /* Set return length */ 987 Length = sizeof(ULONG_PTR); 988 989 /* Reference the process */ 990 Status = ObReferenceObjectByHandle(ProcessHandle, 991 PROCESS_QUERY_INFORMATION, 992 PsProcessType, 993 PreviousMode, 994 (PVOID*)&Process, 995 NULL); 996 if (!NT_SUCCESS(Status)) break; 997 998 /* Make sure the process isn't dying */ 999 if (ExAcquireRundownProtection(&Process->RundownProtect)) 1000 { 1001 /* Get the WOW64 process structure */ 1002 #ifdef _WIN64 1003 Wow64 = (ULONG_PTR)Process->Wow64Process; 1004 #else 1005 Wow64 = 0; 1006 #endif 1007 /* Release the lock */ 1008 ExReleaseRundownProtection(&Process->RundownProtect); 1009 } 1010 1011 /* Protect write with SEH */ 1012 _SEH2_TRY 1013 { 1014 /* Return whether or not we have a debug port */ 1015 *(PULONG_PTR)ProcessInformation = Wow64; 1016 } 1017 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1018 { 1019 /* Get exception code */ 1020 Status = _SEH2_GetExceptionCode(); 1021 } 1022 _SEH2_END; 1023 1024 /* Dereference the process */ 1025 ObDereferenceObject(Process); 1026 break; 1027 1028 case ProcessExecuteFlags: 1029 1030 if (ProcessInformationLength != sizeof(ULONG)) 1031 { 1032 Status = STATUS_INFO_LENGTH_MISMATCH; 1033 break; 1034 } 1035 1036 /* Set return length */ 1037 Length = sizeof(ULONG); 1038 1039 if (ProcessHandle != NtCurrentProcess()) 1040 { 1041 return STATUS_INVALID_PARAMETER; 1042 } 1043 1044 /* Get the options */ 1045 Status = MmGetExecuteOptions(&ExecuteOptions); 1046 if (NT_SUCCESS(Status)) 1047 { 1048 /* Protect write with SEH */ 1049 _SEH2_TRY 1050 { 1051 /* Return them */ 1052 *(PULONG)ProcessInformation = ExecuteOptions; 1053 } 1054 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1055 { 1056 /* Get exception code */ 1057 Status = _SEH2_GetExceptionCode(); 1058 } 1059 _SEH2_END; 1060 } 1061 break; 1062 1063 case ProcessLdtInformation: 1064 DPRINT1("VDM/16-bit not implemented: %lx\n", ProcessInformationClass); 1065 Status = STATUS_NOT_IMPLEMENTED; 1066 break; 1067 1068 case ProcessWorkingSetWatch: 1069 DPRINT1("WS Watch Not implemented: %lx\n", ProcessInformationClass); 1070 Status = STATUS_NOT_IMPLEMENTED; 1071 break; 1072 1073 case ProcessPooledUsageAndLimits: 1074 DPRINT1("Pool limits Not implemented: %lx\n", ProcessInformationClass); 1075 Status = STATUS_NOT_IMPLEMENTED; 1076 break; 1077 1078 /* Not supported by Server 2003 */ 1079 default: 1080 DPRINT1("Unsupported info class: %lx\n", ProcessInformationClass); 1081 Status = STATUS_INVALID_INFO_CLASS; 1082 } 1083 1084 /* Protect write with SEH */ 1085 _SEH2_TRY 1086 { 1087 /* Check if caller wanted return length */ 1088 if ((ReturnLength) && (Length)) *ReturnLength = Length; 1089 } 1090 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1091 { 1092 /* Get exception code */ 1093 Status = _SEH2_GetExceptionCode(); 1094 } 1095 _SEH2_END; 1096 1097 return Status; 1098 } 1099 1100 /* 1101 * @implemented 1102 */ 1103 NTSTATUS 1104 NTAPI 1105 NtSetInformationProcess(IN HANDLE ProcessHandle, 1106 IN PROCESSINFOCLASS ProcessInformationClass, 1107 IN PVOID ProcessInformation, 1108 IN ULONG ProcessInformationLength) 1109 { 1110 PEPROCESS Process; 1111 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 1112 ACCESS_MASK Access; 1113 NTSTATUS Status; 1114 HANDLE PortHandle = NULL; 1115 HANDLE TokenHandle = NULL; 1116 HANDLE DirectoryHandle = NULL; 1117 PROCESS_SESSION_INFORMATION SessionInfo = {0}; 1118 PROCESS_PRIORITY_CLASS PriorityClass = {0}; 1119 PROCESS_FOREGROUND_BACKGROUND Foreground = {0}; 1120 PVOID ExceptionPort; 1121 ULONG Break; 1122 KAFFINITY ValidAffinity, Affinity = 0; 1123 KPRIORITY BasePriority = 0; 1124 UCHAR MemoryPriority = 0; 1125 BOOLEAN DisableBoost = 0; 1126 ULONG DefaultHardErrorMode = 0; 1127 ULONG DebugFlags = 0, EnableFixup = 0, Boost = 0; 1128 ULONG NoExecute = 0, VdmPower = 0; 1129 BOOLEAN HasPrivilege; 1130 PLIST_ENTRY Next; 1131 PETHREAD Thread; 1132 PAGED_CODE(); 1133 1134 /* Verify Information Class validity */ 1135 Status = DefaultSetInfoBufferCheck(ProcessInformationClass, 1136 PsProcessInfoClass, 1137 RTL_NUMBER_OF(PsProcessInfoClass), 1138 ProcessInformation, 1139 ProcessInformationLength, 1140 PreviousMode); 1141 if (!NT_SUCCESS(Status)) 1142 { 1143 DPRINT1("NtSetInformationProcess(): Information verification class failed! (Status -> 0x%lx, ProcessInformationClass -> %lx)\n", Status, ProcessInformationClass); 1144 return Status; 1145 } 1146 1147 /* Check what class this is */ 1148 Access = PROCESS_SET_INFORMATION; 1149 if (ProcessInformationClass == ProcessSessionInformation) 1150 { 1151 /* Setting the Session ID needs a special mask */ 1152 Access |= PROCESS_SET_SESSIONID; 1153 } 1154 else if (ProcessInformationClass == ProcessExceptionPort) 1155 { 1156 /* Setting the exception port needs a special mask */ 1157 Access |= PROCESS_SUSPEND_RESUME; 1158 } 1159 1160 /* Reference the process */ 1161 Status = ObReferenceObjectByHandle(ProcessHandle, 1162 Access, 1163 PsProcessType, 1164 PreviousMode, 1165 (PVOID*)&Process, 1166 NULL); 1167 if (!NT_SUCCESS(Status)) return Status; 1168 1169 /* Check what kind of information class this is */ 1170 switch (ProcessInformationClass) 1171 { 1172 case ProcessWx86Information: 1173 1174 /* Check buffer length */ 1175 if (ProcessInformationLength != sizeof(ULONG)) 1176 { 1177 Status = STATUS_INFO_LENGTH_MISMATCH; 1178 break; 1179 } 1180 1181 /* Use SEH for capture */ 1182 _SEH2_TRY 1183 { 1184 /* Capture the boolean */ 1185 VdmPower = *(PULONG)ProcessInformation; 1186 } 1187 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1188 { 1189 /* Get the exception code */ 1190 Status = _SEH2_GetExceptionCode(); 1191 _SEH2_YIELD(break); 1192 } 1193 _SEH2_END; 1194 1195 /* Getting VDM powers requires the SeTcbPrivilege */ 1196 if (!SeSinglePrivilegeCheck(SeTcbPrivilege, PreviousMode)) 1197 { 1198 /* We don't hold the privilege, bail out */ 1199 Status = STATUS_PRIVILEGE_NOT_HELD; 1200 DPRINT1("Need TCB privilege\n"); 1201 break; 1202 } 1203 1204 /* Set or clear the flag */ 1205 if (VdmPower) 1206 { 1207 PspSetProcessFlag(Process, PSF_VDM_ALLOWED_BIT); 1208 } 1209 else 1210 { 1211 PspClearProcessFlag(Process, PSF_VDM_ALLOWED_BIT); 1212 } 1213 break; 1214 1215 /* Error/Exception Port */ 1216 case ProcessExceptionPort: 1217 1218 /* Check buffer length */ 1219 if (ProcessInformationLength != sizeof(HANDLE)) 1220 { 1221 Status = STATUS_INFO_LENGTH_MISMATCH; 1222 break; 1223 } 1224 1225 /* Use SEH for capture */ 1226 _SEH2_TRY 1227 { 1228 /* Capture the handle */ 1229 PortHandle = *(PHANDLE)ProcessInformation; 1230 } 1231 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1232 { 1233 /* Get the exception code */ 1234 Status = _SEH2_GetExceptionCode(); 1235 _SEH2_YIELD(break); 1236 } 1237 _SEH2_END; 1238 1239 /* Setting the error port requires the SeTcbPrivilege */ 1240 if (!SeSinglePrivilegeCheck(SeTcbPrivilege, PreviousMode)) 1241 { 1242 /* We don't hold the privilege, bail out */ 1243 Status = STATUS_PRIVILEGE_NOT_HELD; 1244 break; 1245 } 1246 1247 /* Get the LPC Port */ 1248 Status = ObReferenceObjectByHandle(PortHandle, 1249 0, 1250 LpcPortObjectType, 1251 PreviousMode, 1252 (PVOID)&ExceptionPort, 1253 NULL); 1254 if (!NT_SUCCESS(Status)) break; 1255 1256 /* Change the pointer */ 1257 if (InterlockedCompareExchangePointer(&Process->ExceptionPort, 1258 ExceptionPort, 1259 NULL)) 1260 { 1261 /* We already had one, fail */ 1262 ObDereferenceObject(ExceptionPort); 1263 Status = STATUS_PORT_ALREADY_SET; 1264 } 1265 break; 1266 1267 /* Security Token */ 1268 case ProcessAccessToken: 1269 1270 /* Check buffer length */ 1271 if (ProcessInformationLength != sizeof(PROCESS_ACCESS_TOKEN)) 1272 { 1273 Status = STATUS_INFO_LENGTH_MISMATCH; 1274 break; 1275 } 1276 1277 /* Use SEH for capture */ 1278 _SEH2_TRY 1279 { 1280 /* Save the token handle */ 1281 TokenHandle = ((PPROCESS_ACCESS_TOKEN)ProcessInformation)-> 1282 Token; 1283 } 1284 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1285 { 1286 /* Get the exception code */ 1287 Status = _SEH2_GetExceptionCode(); 1288 _SEH2_YIELD(break); 1289 } 1290 _SEH2_END; 1291 1292 /* Assign the actual token */ 1293 Status = PspSetPrimaryToken(Process, TokenHandle, NULL); 1294 break; 1295 1296 /* Hard error processing */ 1297 case ProcessDefaultHardErrorMode: 1298 1299 /* Check buffer length */ 1300 if (ProcessInformationLength != sizeof(ULONG)) 1301 { 1302 Status = STATUS_INFO_LENGTH_MISMATCH; 1303 break; 1304 } 1305 1306 /* Enter SEH for direct buffer read */ 1307 _SEH2_TRY 1308 { 1309 DefaultHardErrorMode = *(PULONG)ProcessInformation; 1310 } 1311 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1312 { 1313 /* Get exception code */ 1314 Status = _SEH2_GetExceptionCode(); 1315 _SEH2_YIELD(break); 1316 } 1317 _SEH2_END; 1318 1319 /* Set the mode */ 1320 Process->DefaultHardErrorProcessing = DefaultHardErrorMode; 1321 1322 /* Call Ke for the update */ 1323 if (DefaultHardErrorMode & SEM_NOALIGNMENTFAULTEXCEPT) 1324 { 1325 KeSetAutoAlignmentProcess(&Process->Pcb, TRUE); 1326 } 1327 else 1328 { 1329 KeSetAutoAlignmentProcess(&Process->Pcb, FALSE); 1330 } 1331 Status = STATUS_SUCCESS; 1332 break; 1333 1334 /* Session ID */ 1335 case ProcessSessionInformation: 1336 1337 /* Check buffer length */ 1338 if (ProcessInformationLength != sizeof(PROCESS_SESSION_INFORMATION)) 1339 { 1340 Status = STATUS_INFO_LENGTH_MISMATCH; 1341 break; 1342 } 1343 1344 /* Enter SEH for capture */ 1345 _SEH2_TRY 1346 { 1347 /* Capture the caller's buffer */ 1348 SessionInfo = *(PPROCESS_SESSION_INFORMATION)ProcessInformation; 1349 } 1350 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1351 { 1352 /* Get the exception code */ 1353 Status = _SEH2_GetExceptionCode(); 1354 _SEH2_YIELD(break); 1355 } 1356 _SEH2_END; 1357 1358 /* Setting the session id requires the SeTcbPrivilege */ 1359 if (!SeSinglePrivilegeCheck(SeTcbPrivilege, PreviousMode)) 1360 { 1361 /* We don't hold the privilege, bail out */ 1362 Status = STATUS_PRIVILEGE_NOT_HELD; 1363 break; 1364 } 1365 1366 #if 0 // OLD AND DEPRECATED CODE!!!! 1367 1368 /* FIXME - update the session id for the process token */ 1369 //Status = PsLockProcess(Process, FALSE); 1370 if (!NT_SUCCESS(Status)) break; 1371 1372 /* Write the session ID in the EPROCESS */ 1373 Process->Session = UlongToPtr(SessionInfo.SessionId); // HACK!!! 1374 1375 /* Check if the process also has a PEB */ 1376 if (Process->Peb) 1377 { 1378 /* 1379 * Attach to the process to make sure we're in the right 1380 * context to access the PEB structure 1381 */ 1382 KeAttachProcess(&Process->Pcb); 1383 1384 /* Enter SEH for write to user-mode PEB */ 1385 _SEH2_TRY 1386 { 1387 /* Write the session ID */ 1388 Process->Peb->SessionId = SessionInfo.SessionId; 1389 } 1390 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1391 { 1392 /* Get exception code */ 1393 Status = _SEH2_GetExceptionCode(); 1394 } 1395 _SEH2_END; 1396 1397 /* Detach from the process */ 1398 KeDetachProcess(); 1399 } 1400 1401 /* Unlock the process */ 1402 //PsUnlockProcess(Process); 1403 1404 #endif 1405 1406 /* 1407 * Since we cannot change the session ID of the given 1408 * process anymore because it is set once and for all 1409 * at process creation time and because it is stored 1410 * inside the Process->Session structure managed by MM, 1411 * we fake changing it: we just return success if the 1412 * user-defined value is the same as the session ID of 1413 * the process, and otherwise we fail. 1414 */ 1415 if (SessionInfo.SessionId == PsGetProcessSessionId(Process)) 1416 { 1417 Status = STATUS_SUCCESS; 1418 } 1419 else 1420 { 1421 Status = STATUS_ACCESS_DENIED; 1422 } 1423 1424 break; 1425 1426 case ProcessPriorityClass: 1427 1428 /* Check buffer length */ 1429 if (ProcessInformationLength != sizeof(PROCESS_PRIORITY_CLASS)) 1430 { 1431 Status = STATUS_INFO_LENGTH_MISMATCH; 1432 break; 1433 } 1434 1435 /* Enter SEH for capture */ 1436 _SEH2_TRY 1437 { 1438 /* Capture the caller's buffer */ 1439 PriorityClass = *(PPROCESS_PRIORITY_CLASS)ProcessInformation; 1440 } 1441 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1442 { 1443 /* Return the exception code */ 1444 Status = _SEH2_GetExceptionCode(); 1445 _SEH2_YIELD(break); 1446 } 1447 _SEH2_END; 1448 1449 /* Check for invalid PriorityClass value */ 1450 if (PriorityClass.PriorityClass > PROCESS_PRIORITY_CLASS_ABOVE_NORMAL) 1451 { 1452 Status = STATUS_INVALID_PARAMETER; 1453 break; 1454 } 1455 1456 if ((PriorityClass.PriorityClass != Process->PriorityClass) && 1457 (PriorityClass.PriorityClass == PROCESS_PRIORITY_CLASS_REALTIME)) 1458 { 1459 /* Check the privilege */ 1460 HasPrivilege = SeCheckPrivilegedObject(SeIncreaseBasePriorityPrivilege, 1461 ProcessHandle, 1462 PROCESS_SET_INFORMATION, 1463 PreviousMode); 1464 if (!HasPrivilege) 1465 { 1466 ObDereferenceObject(Process); 1467 DPRINT1("Privilege to change priority to realtime lacking\n"); 1468 return STATUS_PRIVILEGE_NOT_HELD; 1469 } 1470 } 1471 1472 /* Check if we have a job */ 1473 if (Process->Job) 1474 { 1475 DPRINT1("Jobs not yet supported\n"); 1476 } 1477 1478 /* Set process priority class */ 1479 Process->PriorityClass = PriorityClass.PriorityClass; 1480 1481 /* Set process priority mode (foreground or background) */ 1482 PsSetProcessPriorityByClass(Process, 1483 PriorityClass.Foreground ? 1484 PsProcessPriorityForeground : 1485 PsProcessPriorityBackground); 1486 Status = STATUS_SUCCESS; 1487 break; 1488 1489 case ProcessForegroundInformation: 1490 1491 /* Check buffer length */ 1492 if (ProcessInformationLength != sizeof(PROCESS_FOREGROUND_BACKGROUND)) 1493 { 1494 Status = STATUS_INFO_LENGTH_MISMATCH; 1495 break; 1496 } 1497 1498 /* Enter SEH for capture */ 1499 _SEH2_TRY 1500 { 1501 /* Capture the caller's buffer */ 1502 Foreground = *(PPROCESS_FOREGROUND_BACKGROUND)ProcessInformation; 1503 } 1504 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1505 { 1506 /* Return the exception code */ 1507 Status = _SEH2_GetExceptionCode(); 1508 _SEH2_YIELD(break); 1509 } 1510 _SEH2_END; 1511 1512 /* Set process priority mode (foreground or background) */ 1513 PsSetProcessPriorityByClass(Process, 1514 Foreground.Foreground ? 1515 PsProcessPriorityForeground : 1516 PsProcessPriorityBackground); 1517 Status = STATUS_SUCCESS; 1518 break; 1519 1520 case ProcessBasePriority: 1521 1522 /* Validate input length */ 1523 if (ProcessInformationLength != sizeof(KPRIORITY)) 1524 { 1525 Status = STATUS_INFO_LENGTH_MISMATCH; 1526 break; 1527 } 1528 1529 /* Enter SEH for direct buffer read */ 1530 _SEH2_TRY 1531 { 1532 BasePriority = *(KPRIORITY*)ProcessInformation; 1533 } 1534 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1535 { 1536 /* Get exception code */ 1537 Break = 0; 1538 Status = _SEH2_GetExceptionCode(); 1539 _SEH2_YIELD(break); 1540 } 1541 _SEH2_END; 1542 1543 /* Extract the memory priority out of there */ 1544 if (BasePriority & 0x80000000) 1545 { 1546 MemoryPriority = MEMORY_PRIORITY_FOREGROUND; 1547 BasePriority &= ~0x80000000; 1548 } 1549 else 1550 { 1551 MemoryPriority = MEMORY_PRIORITY_BACKGROUND; 1552 } 1553 1554 /* Validate the number */ 1555 if ((BasePriority > HIGH_PRIORITY) || (BasePriority <= LOW_PRIORITY)) 1556 { 1557 ObDereferenceObject(Process); 1558 return STATUS_INVALID_PARAMETER; 1559 } 1560 1561 /* Check if the new base is higher */ 1562 if (BasePriority > Process->Pcb.BasePriority) 1563 { 1564 HasPrivilege = SeCheckPrivilegedObject(SeIncreaseBasePriorityPrivilege, 1565 ProcessHandle, 1566 PROCESS_SET_INFORMATION, 1567 PreviousMode); 1568 if (!HasPrivilege) 1569 { 1570 ObDereferenceObject(Process); 1571 DPRINT1("Privilege to change priority from %lx to %lx lacking\n", BasePriority, Process->Pcb.BasePriority); 1572 return STATUS_PRIVILEGE_NOT_HELD; 1573 } 1574 } 1575 1576 /* Call Ke */ 1577 KeSetPriorityAndQuantumProcess(&Process->Pcb, BasePriority, 0); 1578 1579 /* Now set the memory priority */ 1580 MmSetMemoryPriorityProcess(Process, MemoryPriority); 1581 Status = STATUS_SUCCESS; 1582 break; 1583 1584 case ProcessRaisePriority: 1585 1586 /* Validate input length */ 1587 if (ProcessInformationLength != sizeof(ULONG)) 1588 { 1589 Status = STATUS_INFO_LENGTH_MISMATCH; 1590 break; 1591 } 1592 1593 /* Enter SEH for direct buffer read */ 1594 _SEH2_TRY 1595 { 1596 Boost = *(PULONG)ProcessInformation; 1597 } 1598 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1599 { 1600 /* Get exception code */ 1601 Break = 0; 1602 Status = _SEH2_GetExceptionCode(); 1603 _SEH2_YIELD(break); 1604 } 1605 _SEH2_END; 1606 1607 /* Make sure the process isn't dying */ 1608 if (ExAcquireRundownProtection(&Process->RundownProtect)) 1609 { 1610 /* Lock it */ 1611 KeEnterCriticalRegion(); 1612 ExAcquirePushLockShared(&Process->ProcessLock); 1613 1614 /* Loop the threads */ 1615 for (Next = Process->ThreadListHead.Flink; 1616 Next != &Process->ThreadListHead; 1617 Next = Next->Flink) 1618 { 1619 /* Call Ke for the thread */ 1620 Thread = CONTAINING_RECORD(Next, ETHREAD, ThreadListEntry); 1621 KeBoostPriorityThread(&Thread->Tcb, Boost); 1622 } 1623 1624 /* Release the lock and rundown */ 1625 ExReleasePushLockShared(&Process->ProcessLock); 1626 KeLeaveCriticalRegion(); 1627 ExReleaseRundownProtection(&Process->RundownProtect); 1628 1629 /* Set success code */ 1630 Status = STATUS_SUCCESS; 1631 } 1632 else 1633 { 1634 /* Avoid race conditions */ 1635 Status = STATUS_PROCESS_IS_TERMINATING; 1636 } 1637 break; 1638 1639 case ProcessBreakOnTermination: 1640 1641 /* Check buffer length */ 1642 if (ProcessInformationLength != sizeof(ULONG)) 1643 { 1644 Status = STATUS_INFO_LENGTH_MISMATCH; 1645 break; 1646 } 1647 1648 /* Enter SEH for direct buffer read */ 1649 _SEH2_TRY 1650 { 1651 Break = *(PULONG)ProcessInformation; 1652 } 1653 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1654 { 1655 /* Get exception code */ 1656 Break = 0; 1657 Status = _SEH2_GetExceptionCode(); 1658 _SEH2_YIELD(break); 1659 } 1660 _SEH2_END; 1661 1662 /* Setting 'break on termination' requires the SeDebugPrivilege */ 1663 if (!SeSinglePrivilegeCheck(SeDebugPrivilege, PreviousMode)) 1664 { 1665 /* We don't hold the privilege, bail out */ 1666 Status = STATUS_PRIVILEGE_NOT_HELD; 1667 break; 1668 } 1669 1670 /* Set or clear the flag */ 1671 if (Break) 1672 { 1673 PspSetProcessFlag(Process, PSF_BREAK_ON_TERMINATION_BIT); 1674 } 1675 else 1676 { 1677 PspClearProcessFlag(Process, PSF_BREAK_ON_TERMINATION_BIT); 1678 } 1679 1680 break; 1681 1682 case ProcessAffinityMask: 1683 1684 /* Check buffer length */ 1685 if (ProcessInformationLength != sizeof(KAFFINITY)) 1686 { 1687 Status = STATUS_INFO_LENGTH_MISMATCH; 1688 break; 1689 } 1690 1691 /* Enter SEH for direct buffer read */ 1692 _SEH2_TRY 1693 { 1694 Affinity = *(PKAFFINITY)ProcessInformation; 1695 } 1696 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1697 { 1698 /* Get exception code */ 1699 Break = 0; 1700 Status = _SEH2_GetExceptionCode(); 1701 _SEH2_YIELD(break); 1702 } 1703 _SEH2_END; 1704 1705 /* Make sure it's valid for the CPUs present */ 1706 ValidAffinity = Affinity & KeActiveProcessors; 1707 if (!Affinity || (ValidAffinity != Affinity)) 1708 { 1709 Status = STATUS_INVALID_PARAMETER; 1710 break; 1711 } 1712 1713 /* Check if it's within job affinity limits */ 1714 if (Process->Job) 1715 { 1716 /* Not yet implemented */ 1717 UNIMPLEMENTED; 1718 Status = STATUS_NOT_IMPLEMENTED; 1719 break; 1720 } 1721 1722 /* Make sure the process isn't dying */ 1723 if (ExAcquireRundownProtection(&Process->RundownProtect)) 1724 { 1725 /* Lock it */ 1726 KeEnterCriticalRegion(); 1727 ExAcquirePushLockShared(&Process->ProcessLock); 1728 1729 /* Call Ke to do the work */ 1730 KeSetAffinityProcess(&Process->Pcb, ValidAffinity); 1731 1732 /* Release the lock and rundown */ 1733 ExReleasePushLockShared(&Process->ProcessLock); 1734 KeLeaveCriticalRegion(); 1735 ExReleaseRundownProtection(&Process->RundownProtect); 1736 1737 /* Set success code */ 1738 Status = STATUS_SUCCESS; 1739 } 1740 else 1741 { 1742 /* Avoid race conditions */ 1743 Status = STATUS_PROCESS_IS_TERMINATING; 1744 } 1745 break; 1746 1747 /* Priority Boosting status */ 1748 case ProcessPriorityBoost: 1749 1750 /* Validate input length */ 1751 if (ProcessInformationLength != sizeof(ULONG)) 1752 { 1753 Status = STATUS_INFO_LENGTH_MISMATCH; 1754 break; 1755 } 1756 1757 /* Enter SEH for direct buffer read */ 1758 _SEH2_TRY 1759 { 1760 DisableBoost = *(PBOOLEAN)ProcessInformation; 1761 } 1762 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1763 { 1764 /* Get exception code */ 1765 Break = 0; 1766 Status = _SEH2_GetExceptionCode(); 1767 _SEH2_YIELD(break); 1768 } 1769 _SEH2_END; 1770 1771 /* Make sure the process isn't dying */ 1772 if (ExAcquireRundownProtection(&Process->RundownProtect)) 1773 { 1774 /* Lock it */ 1775 KeEnterCriticalRegion(); 1776 ExAcquirePushLockShared(&Process->ProcessLock); 1777 1778 /* Call Ke to do the work */ 1779 KeSetDisableBoostProcess(&Process->Pcb, DisableBoost); 1780 1781 /* Loop the threads too */ 1782 for (Next = Process->ThreadListHead.Flink; 1783 Next != &Process->ThreadListHead; 1784 Next = Next->Flink) 1785 { 1786 /* Call Ke for the thread */ 1787 Thread = CONTAINING_RECORD(Next, ETHREAD, ThreadListEntry); 1788 KeSetDisableBoostThread(&Thread->Tcb, DisableBoost); 1789 } 1790 1791 /* Release the lock and rundown */ 1792 ExReleasePushLockShared(&Process->ProcessLock); 1793 KeLeaveCriticalRegion(); 1794 ExReleaseRundownProtection(&Process->RundownProtect); 1795 1796 /* Set success code */ 1797 Status = STATUS_SUCCESS; 1798 } 1799 else 1800 { 1801 /* Avoid race conditions */ 1802 Status = STATUS_PROCESS_IS_TERMINATING; 1803 } 1804 break; 1805 1806 case ProcessDebugFlags: 1807 1808 /* Check buffer length */ 1809 if (ProcessInformationLength != sizeof(ULONG)) 1810 { 1811 Status = STATUS_INFO_LENGTH_MISMATCH; 1812 break; 1813 } 1814 1815 /* Enter SEH for direct buffer read */ 1816 _SEH2_TRY 1817 { 1818 DebugFlags = *(PULONG)ProcessInformation; 1819 } 1820 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1821 { 1822 /* Get exception code */ 1823 Status = _SEH2_GetExceptionCode(); 1824 _SEH2_YIELD(break); 1825 } 1826 _SEH2_END; 1827 1828 /* Set the mode */ 1829 if (DebugFlags & ~1) 1830 { 1831 Status = STATUS_INVALID_PARAMETER; 1832 } 1833 else 1834 { 1835 if (DebugFlags & 1) 1836 { 1837 PspClearProcessFlag(Process, PSF_NO_DEBUG_INHERIT_BIT); 1838 } 1839 else 1840 { 1841 PspSetProcessFlag(Process, PSF_NO_DEBUG_INHERIT_BIT); 1842 } 1843 } 1844 1845 /* Done */ 1846 Status = STATUS_SUCCESS; 1847 break; 1848 1849 case ProcessEnableAlignmentFaultFixup: 1850 1851 /* Check buffer length */ 1852 if (ProcessInformationLength != sizeof(BOOLEAN)) 1853 { 1854 Status = STATUS_INFO_LENGTH_MISMATCH; 1855 break; 1856 } 1857 1858 /* Enter SEH for direct buffer read */ 1859 _SEH2_TRY 1860 { 1861 EnableFixup = *(PULONG)ProcessInformation; 1862 } 1863 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1864 { 1865 /* Get exception code */ 1866 Status = _SEH2_GetExceptionCode(); 1867 _SEH2_YIELD(break); 1868 } 1869 _SEH2_END; 1870 1871 /* Set the mode */ 1872 if (EnableFixup) 1873 { 1874 Process->DefaultHardErrorProcessing |= SEM_NOALIGNMENTFAULTEXCEPT; 1875 } 1876 else 1877 { 1878 Process->DefaultHardErrorProcessing &= ~SEM_NOALIGNMENTFAULTEXCEPT; 1879 } 1880 1881 /* Call Ke for the update */ 1882 KeSetAutoAlignmentProcess(&Process->Pcb, FALSE); 1883 Status = STATUS_SUCCESS; 1884 break; 1885 1886 case ProcessUserModeIOPL: 1887 1888 /* Only TCB can do this */ 1889 if (!SeSinglePrivilegeCheck(SeTcbPrivilege, PreviousMode)) 1890 { 1891 /* We don't hold the privilege, bail out */ 1892 DPRINT1("Need TCB to set IOPL\n"); 1893 Status = STATUS_PRIVILEGE_NOT_HELD; 1894 break; 1895 } 1896 1897 /* Only supported on x86 */ 1898 #if defined (_X86_) 1899 Ke386SetIOPL(); 1900 #elif defined(_M_AMD64) 1901 /* On x64 this function isn't implemented. 1902 On Windows 2003 it returns success. 1903 On Vista+ it returns STATUS_NOT_IMPLEMENTED. */ 1904 if ((ExGetPreviousMode() != KernelMode) && 1905 (RtlRosGetAppcompatVersion() > _WIN32_WINNT_WS03)) 1906 { 1907 Status = STATUS_NOT_IMPLEMENTED; 1908 } 1909 #else 1910 Status = STATUS_NOT_IMPLEMENTED; 1911 #endif 1912 /* Done */ 1913 break; 1914 1915 case ProcessExecuteFlags: 1916 1917 /* Check buffer length */ 1918 if (ProcessInformationLength != sizeof(ULONG)) 1919 { 1920 Status = STATUS_INFO_LENGTH_MISMATCH; 1921 break; 1922 } 1923 1924 if (ProcessHandle != NtCurrentProcess()) 1925 { 1926 Status = STATUS_INVALID_PARAMETER; 1927 break; 1928 } 1929 1930 /* Enter SEH for direct buffer read */ 1931 _SEH2_TRY 1932 { 1933 NoExecute = *(PULONG)ProcessInformation; 1934 } 1935 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1936 { 1937 /* Get exception code */ 1938 Status = _SEH2_GetExceptionCode(); 1939 _SEH2_YIELD(break); 1940 } 1941 _SEH2_END; 1942 1943 /* Call Mm for the update */ 1944 Status = MmSetExecuteOptions(NoExecute); 1945 break; 1946 1947 case ProcessDeviceMap: 1948 1949 /* Check buffer length */ 1950 if (ProcessInformationLength != sizeof(HANDLE)) 1951 { 1952 Status = STATUS_INFO_LENGTH_MISMATCH; 1953 break; 1954 } 1955 1956 /* Use SEH for capture */ 1957 _SEH2_TRY 1958 { 1959 /* Capture the handle */ 1960 DirectoryHandle = *(PHANDLE)ProcessInformation; 1961 } 1962 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 1963 { 1964 /* Get the exception code */ 1965 Status = _SEH2_GetExceptionCode(); 1966 _SEH2_YIELD(break); 1967 } 1968 _SEH2_END; 1969 1970 /* Call Ob to set the device map */ 1971 Status = ObSetDeviceMap(Process, DirectoryHandle); 1972 break; 1973 1974 1975 /* We currently don't implement any of these */ 1976 case ProcessLdtInformation: 1977 case ProcessLdtSize: 1978 case ProcessIoPortHandlers: 1979 DPRINT1("VDM/16-bit Request not implemented: %lx\n", ProcessInformationClass); 1980 Status = STATUS_NOT_IMPLEMENTED; 1981 break; 1982 1983 case ProcessQuotaLimits: 1984 1985 Status = PspSetQuotaLimits(Process, 1986 1, 1987 ProcessInformation, 1988 ProcessInformationLength, 1989 PreviousMode); 1990 break; 1991 1992 case ProcessWorkingSetWatch: 1993 DPRINT1("WS watch not implemented\n"); 1994 Status = STATUS_NOT_IMPLEMENTED; 1995 break; 1996 1997 case ProcessHandleTracing: 1998 DPRINT1("Handle tracing not implemented\n"); 1999 Status = STATUS_NOT_IMPLEMENTED; 2000 break; 2001 2002 /* Anything else is invalid */ 2003 default: 2004 DPRINT1("Invalid Server 2003 Info Class: %lx\n", ProcessInformationClass); 2005 Status = STATUS_INVALID_INFO_CLASS; 2006 } 2007 2008 /* Dereference and return status */ 2009 ObDereferenceObject(Process); 2010 return Status; 2011 } 2012 2013 /* 2014 * @implemented 2015 */ 2016 NTSTATUS 2017 NTAPI 2018 NtSetInformationThread(IN HANDLE ThreadHandle, 2019 IN THREADINFOCLASS ThreadInformationClass, 2020 IN PVOID ThreadInformation, 2021 IN ULONG ThreadInformationLength) 2022 { 2023 PETHREAD Thread; 2024 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 2025 NTSTATUS Status; 2026 HANDLE TokenHandle = NULL; 2027 KPRIORITY Priority = 0; 2028 KAFFINITY Affinity = 0, CombinedAffinity; 2029 PVOID Address = NULL; 2030 PEPROCESS Process; 2031 ULONG_PTR DisableBoost = 0; 2032 ULONG_PTR IdealProcessor = 0; 2033 ULONG_PTR Break = 0; 2034 PTEB Teb; 2035 ULONG_PTR TlsIndex = 0; 2036 PVOID *ExpansionSlots; 2037 PETHREAD ProcThread; 2038 BOOLEAN HasPrivilege; 2039 PAGED_CODE(); 2040 2041 /* Verify Information Class validity */ 2042 Status = DefaultSetInfoBufferCheck(ThreadInformationClass, 2043 PsThreadInfoClass, 2044 RTL_NUMBER_OF(PsThreadInfoClass), 2045 ThreadInformation, 2046 ThreadInformationLength, 2047 PreviousMode); 2048 if (!NT_SUCCESS(Status)) 2049 { 2050 DPRINT1("NtSetInformationThread(): Information verification class failed! (Status -> 0x%lx, ThreadInformationClass -> %lx)\n", Status, ThreadInformationClass); 2051 return Status; 2052 } 2053 2054 /* Check what kind of information class this is */ 2055 switch (ThreadInformationClass) 2056 { 2057 /* Thread priority */ 2058 case ThreadPriority: 2059 2060 /* Check buffer length */ 2061 if (ThreadInformationLength != sizeof(KPRIORITY)) 2062 { 2063 Status = STATUS_INFO_LENGTH_MISMATCH; 2064 break; 2065 } 2066 2067 /* Use SEH for capture */ 2068 _SEH2_TRY 2069 { 2070 /* Get the priority */ 2071 Priority = *(PLONG)ThreadInformation; 2072 } 2073 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 2074 { 2075 /* Get the exception code */ 2076 Status = _SEH2_GetExceptionCode(); 2077 _SEH2_YIELD(break); 2078 } 2079 _SEH2_END; 2080 2081 /* Validate it */ 2082 if ((Priority > HIGH_PRIORITY) || 2083 (Priority <= LOW_PRIORITY)) 2084 { 2085 /* Fail */ 2086 Status = STATUS_INVALID_PARAMETER; 2087 break; 2088 } 2089 2090 /* Check for the required privilege */ 2091 if (Priority >= LOW_REALTIME_PRIORITY) 2092 { 2093 HasPrivilege = SeCheckPrivilegedObject(SeIncreaseBasePriorityPrivilege, 2094 ThreadHandle, 2095 THREAD_SET_INFORMATION, 2096 PreviousMode); 2097 if (!HasPrivilege) 2098 { 2099 DPRINT1("Privilege to change priority to %lx lacking\n", Priority); 2100 return STATUS_PRIVILEGE_NOT_HELD; 2101 } 2102 } 2103 2104 /* Reference the thread */ 2105 Status = ObReferenceObjectByHandle(ThreadHandle, 2106 THREAD_SET_INFORMATION, 2107 PsThreadType, 2108 PreviousMode, 2109 (PVOID*)&Thread, 2110 NULL); 2111 if (!NT_SUCCESS(Status)) 2112 break; 2113 2114 /* Set the priority */ 2115 KeSetPriorityThread(&Thread->Tcb, Priority); 2116 2117 /* Dereference the thread */ 2118 ObDereferenceObject(Thread); 2119 break; 2120 2121 case ThreadBasePriority: 2122 2123 /* Check buffer length */ 2124 if (ThreadInformationLength != sizeof(LONG)) 2125 { 2126 Status = STATUS_INFO_LENGTH_MISMATCH; 2127 break; 2128 } 2129 2130 /* Use SEH for capture */ 2131 _SEH2_TRY 2132 { 2133 /* Get the priority */ 2134 Priority = *(PLONG)ThreadInformation; 2135 } 2136 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 2137 { 2138 /* Get the exception code */ 2139 Status = _SEH2_GetExceptionCode(); 2140 _SEH2_YIELD(break); 2141 } 2142 _SEH2_END; 2143 2144 /* Validate it */ 2145 if ((Priority > THREAD_BASE_PRIORITY_MAX) || 2146 (Priority < THREAD_BASE_PRIORITY_MIN)) 2147 { 2148 /* These ones are OK */ 2149 if ((Priority != THREAD_BASE_PRIORITY_LOWRT + 1) && 2150 (Priority != THREAD_BASE_PRIORITY_IDLE - 1)) 2151 { 2152 /* Check if the process is real time */ 2153 if (PsGetCurrentProcess()->PriorityClass != 2154 PROCESS_PRIORITY_CLASS_REALTIME) 2155 { 2156 /* It isn't, fail */ 2157 Status = STATUS_INVALID_PARAMETER; 2158 break; 2159 } 2160 } 2161 } 2162 2163 /* Reference the thread */ 2164 Status = ObReferenceObjectByHandle(ThreadHandle, 2165 THREAD_SET_INFORMATION, 2166 PsThreadType, 2167 PreviousMode, 2168 (PVOID*)&Thread, 2169 NULL); 2170 if (!NT_SUCCESS(Status)) 2171 break; 2172 2173 /* Set the base priority */ 2174 KeSetBasePriorityThread(&Thread->Tcb, Priority); 2175 2176 /* Dereference the thread */ 2177 ObDereferenceObject(Thread); 2178 break; 2179 2180 case ThreadAffinityMask: 2181 2182 /* Check buffer length */ 2183 if (ThreadInformationLength != sizeof(ULONG_PTR)) 2184 { 2185 Status = STATUS_INFO_LENGTH_MISMATCH; 2186 break; 2187 } 2188 2189 /* Use SEH for capture */ 2190 _SEH2_TRY 2191 { 2192 /* Get the priority */ 2193 Affinity = *(PULONG_PTR)ThreadInformation; 2194 } 2195 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 2196 { 2197 /* Get the exception code */ 2198 Status = _SEH2_GetExceptionCode(); 2199 _SEH2_YIELD(break); 2200 } 2201 _SEH2_END; 2202 2203 /* Validate it */ 2204 if (!Affinity) 2205 { 2206 /* Fail */ 2207 Status = STATUS_INVALID_PARAMETER; 2208 break; 2209 } 2210 2211 /* Reference the thread */ 2212 Status = ObReferenceObjectByHandle(ThreadHandle, 2213 THREAD_SET_INFORMATION, 2214 PsThreadType, 2215 PreviousMode, 2216 (PVOID*)&Thread, 2217 NULL); 2218 if (!NT_SUCCESS(Status)) 2219 break; 2220 2221 /* Get the process */ 2222 Process = Thread->ThreadsProcess; 2223 2224 /* Try to acquire rundown */ 2225 if (ExAcquireRundownProtection(&Process->RundownProtect)) 2226 { 2227 /* Lock it */ 2228 KeEnterCriticalRegion(); 2229 ExAcquirePushLockShared(&Process->ProcessLock); 2230 2231 /* Combine masks */ 2232 CombinedAffinity = Affinity & Process->Pcb.Affinity; 2233 if (CombinedAffinity != Affinity) 2234 { 2235 /* Fail */ 2236 Status = STATUS_INVALID_PARAMETER; 2237 } 2238 else 2239 { 2240 /* Set the affinity */ 2241 KeSetAffinityThread(&Thread->Tcb, CombinedAffinity); 2242 } 2243 2244 /* Release the lock and rundown */ 2245 ExReleasePushLockShared(&Process->ProcessLock); 2246 KeLeaveCriticalRegion(); 2247 ExReleaseRundownProtection(&Process->RundownProtect); 2248 } 2249 else 2250 { 2251 /* Too late */ 2252 Status = STATUS_PROCESS_IS_TERMINATING; 2253 } 2254 2255 /* Dereference the thread */ 2256 ObDereferenceObject(Thread); 2257 break; 2258 2259 case ThreadImpersonationToken: 2260 2261 /* Check buffer length */ 2262 if (ThreadInformationLength != sizeof(HANDLE)) 2263 { 2264 Status = STATUS_INFO_LENGTH_MISMATCH; 2265 break; 2266 } 2267 2268 /* Use SEH for capture */ 2269 _SEH2_TRY 2270 { 2271 /* Save the token handle */ 2272 TokenHandle = *(PHANDLE)ThreadInformation; 2273 } 2274 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 2275 { 2276 /* Get the exception code */ 2277 Status = _SEH2_GetExceptionCode(); 2278 _SEH2_YIELD(break); 2279 } 2280 _SEH2_END; 2281 2282 /* Reference the thread */ 2283 Status = ObReferenceObjectByHandle(ThreadHandle, 2284 THREAD_SET_THREAD_TOKEN, 2285 PsThreadType, 2286 PreviousMode, 2287 (PVOID*)&Thread, 2288 NULL); 2289 if (!NT_SUCCESS(Status)) 2290 break; 2291 2292 /* Assign the actual token */ 2293 Status = PsAssignImpersonationToken(Thread, TokenHandle); 2294 2295 /* Dereference the thread */ 2296 ObDereferenceObject(Thread); 2297 break; 2298 2299 case ThreadQuerySetWin32StartAddress: 2300 2301 /* Check buffer length */ 2302 if (ThreadInformationLength != sizeof(ULONG_PTR)) 2303 { 2304 Status = STATUS_INFO_LENGTH_MISMATCH; 2305 break; 2306 } 2307 2308 /* Use SEH for capture */ 2309 _SEH2_TRY 2310 { 2311 /* Get the priority */ 2312 Address = *(PVOID*)ThreadInformation; 2313 } 2314 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 2315 { 2316 /* Get the exception code */ 2317 Status = _SEH2_GetExceptionCode(); 2318 _SEH2_YIELD(break); 2319 } 2320 _SEH2_END; 2321 2322 /* Reference the thread */ 2323 Status = ObReferenceObjectByHandle(ThreadHandle, 2324 THREAD_SET_INFORMATION, 2325 PsThreadType, 2326 PreviousMode, 2327 (PVOID*)&Thread, 2328 NULL); 2329 if (!NT_SUCCESS(Status)) 2330 break; 2331 2332 /* Set the address */ 2333 Thread->Win32StartAddress = Address; 2334 2335 /* Dereference the thread */ 2336 ObDereferenceObject(Thread); 2337 break; 2338 2339 case ThreadIdealProcessor: 2340 2341 /* Check buffer length */ 2342 if (ThreadInformationLength != sizeof(ULONG_PTR)) 2343 { 2344 Status = STATUS_INFO_LENGTH_MISMATCH; 2345 break; 2346 } 2347 2348 /* Use SEH for capture */ 2349 _SEH2_TRY 2350 { 2351 /* Get the priority */ 2352 IdealProcessor = *(PULONG_PTR)ThreadInformation; 2353 } 2354 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 2355 { 2356 /* Get the exception code */ 2357 Status = _SEH2_GetExceptionCode(); 2358 _SEH2_YIELD(break); 2359 } 2360 _SEH2_END; 2361 2362 /* Validate it */ 2363 if (IdealProcessor > MAXIMUM_PROCESSORS) 2364 { 2365 /* Fail */ 2366 Status = STATUS_INVALID_PARAMETER; 2367 break; 2368 } 2369 2370 /* Reference the thread */ 2371 Status = ObReferenceObjectByHandle(ThreadHandle, 2372 THREAD_SET_INFORMATION, 2373 PsThreadType, 2374 PreviousMode, 2375 (PVOID*)&Thread, 2376 NULL); 2377 if (!NT_SUCCESS(Status)) 2378 break; 2379 2380 /* Set the ideal */ 2381 Status = KeSetIdealProcessorThread(&Thread->Tcb, 2382 (CCHAR)IdealProcessor); 2383 2384 /* Get the TEB and protect the thread */ 2385 Teb = Thread->Tcb.Teb; 2386 if ((Teb) && (ExAcquireRundownProtection(&Thread->RundownProtect))) 2387 { 2388 /* Save the ideal processor */ 2389 Teb->IdealProcessor = Thread->Tcb.IdealProcessor; 2390 2391 /* Release rundown protection */ 2392 ExReleaseRundownProtection(&Thread->RundownProtect); 2393 } 2394 2395 /* Dereference the thread */ 2396 ObDereferenceObject(Thread); 2397 break; 2398 2399 case ThreadPriorityBoost: 2400 2401 /* Check buffer length */ 2402 if (ThreadInformationLength != sizeof(ULONG_PTR)) 2403 { 2404 Status = STATUS_INFO_LENGTH_MISMATCH; 2405 break; 2406 } 2407 2408 /* Use SEH for capture */ 2409 _SEH2_TRY 2410 { 2411 /* Get the priority */ 2412 DisableBoost = *(PULONG_PTR)ThreadInformation; 2413 } 2414 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 2415 { 2416 /* Get the exception code */ 2417 Status = _SEH2_GetExceptionCode(); 2418 _SEH2_YIELD(break); 2419 } 2420 _SEH2_END; 2421 2422 /* Reference the thread */ 2423 Status = ObReferenceObjectByHandle(ThreadHandle, 2424 THREAD_SET_INFORMATION, 2425 PsThreadType, 2426 PreviousMode, 2427 (PVOID*)&Thread, 2428 NULL); 2429 if (!NT_SUCCESS(Status)) 2430 break; 2431 2432 /* Call the kernel */ 2433 KeSetDisableBoostThread(&Thread->Tcb, (BOOLEAN)DisableBoost); 2434 2435 /* Dereference the thread */ 2436 ObDereferenceObject(Thread); 2437 break; 2438 2439 case ThreadZeroTlsCell: 2440 2441 /* Check buffer length */ 2442 if (ThreadInformationLength != sizeof(ULONG)) 2443 { 2444 Status = STATUS_INFO_LENGTH_MISMATCH; 2445 break; 2446 } 2447 2448 /* Use SEH for capture */ 2449 _SEH2_TRY 2450 { 2451 /* Get the priority */ 2452 TlsIndex = *(PULONG)ThreadInformation; 2453 } 2454 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 2455 { 2456 /* Get the exception code */ 2457 Status = _SEH2_GetExceptionCode(); 2458 _SEH2_YIELD(break); 2459 } 2460 _SEH2_END; 2461 2462 /* Reference the thread */ 2463 Status = ObReferenceObjectByHandle(ThreadHandle, 2464 THREAD_SET_INFORMATION, 2465 PsThreadType, 2466 PreviousMode, 2467 (PVOID*)&Thread, 2468 NULL); 2469 if (!NT_SUCCESS(Status)) 2470 break; 2471 2472 /* This is only valid for the current thread */ 2473 if (Thread != PsGetCurrentThread()) 2474 { 2475 /* Fail */ 2476 Status = STATUS_INVALID_PARAMETER; 2477 ObDereferenceObject(Thread); 2478 break; 2479 } 2480 2481 /* Get the process */ 2482 Process = Thread->ThreadsProcess; 2483 2484 /* Loop the threads */ 2485 ProcThread = PsGetNextProcessThread(Process, NULL); 2486 while (ProcThread) 2487 { 2488 /* Acquire rundown */ 2489 if (ExAcquireRundownProtection(&ProcThread->RundownProtect)) 2490 { 2491 /* Get the TEB */ 2492 Teb = ProcThread->Tcb.Teb; 2493 if (Teb) 2494 { 2495 /* Check if we're in the expansion range */ 2496 if (TlsIndex > TLS_MINIMUM_AVAILABLE - 1) 2497 { 2498 if (TlsIndex < (TLS_MINIMUM_AVAILABLE + 2499 TLS_EXPANSION_SLOTS) - 1) 2500 { 2501 /* Check if we have expansion slots */ 2502 ExpansionSlots = Teb->TlsExpansionSlots; 2503 if (ExpansionSlots) 2504 { 2505 /* Clear the index */ 2506 ExpansionSlots[TlsIndex - TLS_MINIMUM_AVAILABLE] = 0; 2507 } 2508 } 2509 } 2510 else 2511 { 2512 /* Clear the index */ 2513 Teb->TlsSlots[TlsIndex] = NULL; 2514 } 2515 } 2516 2517 /* Release rundown */ 2518 ExReleaseRundownProtection(&ProcThread->RundownProtect); 2519 } 2520 2521 /* Go to the next thread */ 2522 ProcThread = PsGetNextProcessThread(Process, ProcThread); 2523 } 2524 2525 /* Dereference the thread */ 2526 ObDereferenceObject(Thread); 2527 break; 2528 2529 case ThreadBreakOnTermination: 2530 2531 /* Check buffer length */ 2532 if (ThreadInformationLength != sizeof(ULONG)) 2533 { 2534 Status = STATUS_INFO_LENGTH_MISMATCH; 2535 break; 2536 } 2537 2538 /* Enter SEH for direct buffer read */ 2539 _SEH2_TRY 2540 { 2541 Break = *(PULONG)ThreadInformation; 2542 } 2543 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 2544 { 2545 /* Get exception code */ 2546 Break = 0; 2547 Status = _SEH2_GetExceptionCode(); 2548 _SEH2_YIELD(break); 2549 } 2550 _SEH2_END; 2551 2552 /* Setting 'break on termination' requires the SeDebugPrivilege */ 2553 if (!SeSinglePrivilegeCheck(SeDebugPrivilege, PreviousMode)) 2554 { 2555 /* We don't hold the privilege, bail out */ 2556 Status = STATUS_PRIVILEGE_NOT_HELD; 2557 break; 2558 } 2559 2560 /* Reference the thread */ 2561 Status = ObReferenceObjectByHandle(ThreadHandle, 2562 THREAD_SET_INFORMATION, 2563 PsThreadType, 2564 PreviousMode, 2565 (PVOID*)&Thread, 2566 NULL); 2567 if (!NT_SUCCESS(Status)) 2568 break; 2569 2570 /* Set or clear the flag */ 2571 if (Break) 2572 { 2573 PspSetCrossThreadFlag(Thread, CT_BREAK_ON_TERMINATION_BIT); 2574 } 2575 else 2576 { 2577 PspClearCrossThreadFlag(Thread, CT_BREAK_ON_TERMINATION_BIT); 2578 } 2579 2580 /* Dereference the thread */ 2581 ObDereferenceObject(Thread); 2582 break; 2583 2584 case ThreadHideFromDebugger: 2585 2586 /* Check buffer length */ 2587 if (ThreadInformationLength != 0) 2588 { 2589 Status = STATUS_INFO_LENGTH_MISMATCH; 2590 break; 2591 } 2592 2593 /* Reference the thread */ 2594 Status = ObReferenceObjectByHandle(ThreadHandle, 2595 THREAD_SET_INFORMATION, 2596 PsThreadType, 2597 PreviousMode, 2598 (PVOID*)&Thread, 2599 NULL); 2600 if (!NT_SUCCESS(Status)) 2601 break; 2602 2603 /* Set the flag */ 2604 PspSetCrossThreadFlag(Thread, CT_HIDE_FROM_DEBUGGER_BIT); 2605 2606 /* Dereference the thread */ 2607 ObDereferenceObject(Thread); 2608 break; 2609 2610 default: 2611 /* We don't implement it yet */ 2612 DPRINT1("Not implemented: %d\n", ThreadInformationClass); 2613 Status = STATUS_NOT_IMPLEMENTED; 2614 } 2615 2616 return Status; 2617 } 2618 2619 /* 2620 * @implemented 2621 */ 2622 NTSTATUS 2623 NTAPI 2624 NtQueryInformationThread(IN HANDLE ThreadHandle, 2625 IN THREADINFOCLASS ThreadInformationClass, 2626 OUT PVOID ThreadInformation, 2627 IN ULONG ThreadInformationLength, 2628 OUT PULONG ReturnLength OPTIONAL) 2629 { 2630 PETHREAD Thread; 2631 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); 2632 NTSTATUS Status; 2633 ULONG Access; 2634 ULONG Length = 0; 2635 PTHREAD_BASIC_INFORMATION ThreadBasicInfo = 2636 (PTHREAD_BASIC_INFORMATION)ThreadInformation; 2637 PKERNEL_USER_TIMES ThreadTime = (PKERNEL_USER_TIMES)ThreadInformation; 2638 KIRQL OldIrql; 2639 ULONG ThreadTerminated; 2640 PAGED_CODE(); 2641 2642 /* Verify Information Class validity */ 2643 Status = DefaultQueryInfoBufferCheck(ThreadInformationClass, 2644 PsThreadInfoClass, 2645 RTL_NUMBER_OF(PsThreadInfoClass), 2646 ThreadInformation, 2647 ThreadInformationLength, 2648 ReturnLength, 2649 NULL, 2650 PreviousMode, 2651 FALSE); 2652 if (!NT_SUCCESS(Status)) 2653 { 2654 DPRINT1("NtQueryInformationThread(): Information verification class failed! (Status -> 0x%lx , ThreadInformationClass -> %lx)\n", Status, ThreadInformationClass); 2655 return Status; 2656 } 2657 2658 /* Check what class this is */ 2659 Access = THREAD_QUERY_INFORMATION; 2660 2661 /* Check what kind of information class this is */ 2662 switch (ThreadInformationClass) 2663 { 2664 /* Basic thread information */ 2665 case ThreadBasicInformation: 2666 2667 /* Set return length */ 2668 Length = sizeof(THREAD_BASIC_INFORMATION); 2669 2670 if (ThreadInformationLength != Length) 2671 { 2672 Status = STATUS_INFO_LENGTH_MISMATCH; 2673 break; 2674 } 2675 2676 /* Reference the process */ 2677 Status = ObReferenceObjectByHandle(ThreadHandle, 2678 Access, 2679 PsThreadType, 2680 PreviousMode, 2681 (PVOID*)&Thread, 2682 NULL); 2683 if (!NT_SUCCESS(Status)) 2684 break; 2685 2686 /* Protect writes with SEH */ 2687 _SEH2_TRY 2688 { 2689 /* Write all the information from the ETHREAD/KTHREAD */ 2690 ThreadBasicInfo->ExitStatus = Thread->ExitStatus; 2691 ThreadBasicInfo->TebBaseAddress = (PVOID)Thread->Tcb.Teb; 2692 ThreadBasicInfo->ClientId = Thread->Cid; 2693 ThreadBasicInfo->AffinityMask = Thread->Tcb.Affinity; 2694 ThreadBasicInfo->Priority = Thread->Tcb.Priority; 2695 ThreadBasicInfo->BasePriority = KeQueryBasePriorityThread(&Thread->Tcb); 2696 } 2697 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 2698 { 2699 /* Get exception code */ 2700 Status = _SEH2_GetExceptionCode(); 2701 } 2702 _SEH2_END; 2703 2704 /* Dereference the thread */ 2705 ObDereferenceObject(Thread); 2706 break; 2707 2708 /* Thread time information */ 2709 case ThreadTimes: 2710 2711 /* Set the return length */ 2712 Length = sizeof(KERNEL_USER_TIMES); 2713 2714 if (ThreadInformationLength != Length) 2715 { 2716 Status = STATUS_INFO_LENGTH_MISMATCH; 2717 break; 2718 } 2719 2720 /* Reference the process */ 2721 Status = ObReferenceObjectByHandle(ThreadHandle, 2722 Access, 2723 PsThreadType, 2724 PreviousMode, 2725 (PVOID*)&Thread, 2726 NULL); 2727 if (!NT_SUCCESS(Status)) 2728 break; 2729 2730 /* Protect writes with SEH */ 2731 _SEH2_TRY 2732 { 2733 /* Copy time information from ETHREAD/KTHREAD */ 2734 ThreadTime->KernelTime.QuadPart = Thread->Tcb.KernelTime * KeMaximumIncrement; 2735 ThreadTime->UserTime.QuadPart = Thread->Tcb.UserTime * KeMaximumIncrement; 2736 ThreadTime->CreateTime = Thread->CreateTime; 2737 2738 /* Exit time is in a union and only valid on actual exit! */ 2739 if (KeReadStateThread(&Thread->Tcb)) 2740 { 2741 ThreadTime->ExitTime = Thread->ExitTime; 2742 } 2743 else 2744 { 2745 ThreadTime->ExitTime.QuadPart = 0; 2746 } 2747 } 2748 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 2749 { 2750 /* Get exception code */ 2751 Status = _SEH2_GetExceptionCode(); 2752 } 2753 _SEH2_END; 2754 2755 /* Dereference the thread */ 2756 ObDereferenceObject(Thread); 2757 break; 2758 2759 case ThreadQuerySetWin32StartAddress: 2760 2761 /* Set the return length*/ 2762 Length = sizeof(PVOID); 2763 2764 if (ThreadInformationLength != Length) 2765 { 2766 Status = STATUS_INFO_LENGTH_MISMATCH; 2767 break; 2768 } 2769 2770 /* Reference the process */ 2771 Status = ObReferenceObjectByHandle(ThreadHandle, 2772 Access, 2773 PsThreadType, 2774 PreviousMode, 2775 (PVOID*)&Thread, 2776 NULL); 2777 if (!NT_SUCCESS(Status)) 2778 break; 2779 2780 /* Protect write with SEH */ 2781 _SEH2_TRY 2782 { 2783 /* Return the Win32 Start Address */ 2784 *(PVOID*)ThreadInformation = Thread->Win32StartAddress; 2785 } 2786 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 2787 { 2788 /* Get exception code */ 2789 Status = _SEH2_GetExceptionCode(); 2790 } 2791 _SEH2_END; 2792 2793 /* Dereference the thread */ 2794 ObDereferenceObject(Thread); 2795 break; 2796 2797 case ThreadPerformanceCount: 2798 2799 /* Set the return length*/ 2800 Length = sizeof(LARGE_INTEGER); 2801 2802 if (ThreadInformationLength != Length) 2803 { 2804 Status = STATUS_INFO_LENGTH_MISMATCH; 2805 break; 2806 } 2807 2808 /* Reference the process */ 2809 Status = ObReferenceObjectByHandle(ThreadHandle, 2810 Access, 2811 PsThreadType, 2812 PreviousMode, 2813 (PVOID*)&Thread, 2814 NULL); 2815 if (!NT_SUCCESS(Status)) 2816 break; 2817 2818 /* Protect write with SEH */ 2819 _SEH2_TRY 2820 { 2821 /* FIXME */ 2822 (*(PLARGE_INTEGER)ThreadInformation).QuadPart = 0; 2823 } 2824 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 2825 { 2826 /* Get exception code */ 2827 Status = _SEH2_GetExceptionCode(); 2828 } 2829 _SEH2_END; 2830 2831 /* Dereference the thread */ 2832 ObDereferenceObject(Thread); 2833 break; 2834 2835 case ThreadAmILastThread: 2836 2837 /* Set the return length*/ 2838 Length = sizeof(ULONG); 2839 2840 if (ThreadInformationLength != Length) 2841 { 2842 Status = STATUS_INFO_LENGTH_MISMATCH; 2843 break; 2844 } 2845 2846 /* Reference the process */ 2847 Status = ObReferenceObjectByHandle(ThreadHandle, 2848 Access, 2849 PsThreadType, 2850 PreviousMode, 2851 (PVOID*)&Thread, 2852 NULL); 2853 if (!NT_SUCCESS(Status)) 2854 break; 2855 2856 /* Protect write with SEH */ 2857 _SEH2_TRY 2858 { 2859 /* Return whether or not we are the last thread */ 2860 *(PULONG)ThreadInformation = ((Thread->ThreadsProcess-> 2861 ThreadListHead.Flink->Flink == 2862 &Thread->ThreadsProcess-> 2863 ThreadListHead) ? 2864 TRUE : FALSE); 2865 } 2866 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 2867 { 2868 /* Get exception code */ 2869 Status = _SEH2_GetExceptionCode(); 2870 } 2871 _SEH2_END; 2872 2873 /* Dereference the thread */ 2874 ObDereferenceObject(Thread); 2875 break; 2876 2877 case ThreadIsIoPending: 2878 2879 /* Set the return length*/ 2880 Length = sizeof(ULONG); 2881 2882 if (ThreadInformationLength != Length) 2883 { 2884 Status = STATUS_INFO_LENGTH_MISMATCH; 2885 break; 2886 } 2887 2888 /* Reference the process */ 2889 Status = ObReferenceObjectByHandle(ThreadHandle, 2890 Access, 2891 PsThreadType, 2892 PreviousMode, 2893 (PVOID*)&Thread, 2894 NULL); 2895 if (!NT_SUCCESS(Status)) 2896 break; 2897 2898 /* Raise the IRQL to protect the IRP list */ 2899 KeRaiseIrql(APC_LEVEL, &OldIrql); 2900 2901 /* Protect write with SEH */ 2902 _SEH2_TRY 2903 { 2904 /* Check if the IRP list is empty or not */ 2905 *(PULONG)ThreadInformation = !IsListEmpty(&Thread->IrpList); 2906 } 2907 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 2908 { 2909 /* Get exception code */ 2910 Status = _SEH2_GetExceptionCode(); 2911 } 2912 _SEH2_END; 2913 2914 /* Lower IRQL back */ 2915 KeLowerIrql(OldIrql); 2916 2917 /* Dereference the thread */ 2918 ObDereferenceObject(Thread); 2919 break; 2920 2921 /* LDT and GDT information */ 2922 case ThreadDescriptorTableEntry: 2923 2924 #if defined(_X86_) 2925 /* Reference the process */ 2926 Status = ObReferenceObjectByHandle(ThreadHandle, 2927 Access, 2928 PsThreadType, 2929 PreviousMode, 2930 (PVOID*)&Thread, 2931 NULL); 2932 if (!NT_SUCCESS(Status)) 2933 break; 2934 2935 /* Call the worker routine */ 2936 Status = PspQueryDescriptorThread(Thread, 2937 ThreadInformation, 2938 ThreadInformationLength, 2939 ReturnLength); 2940 2941 /* Dereference the thread */ 2942 ObDereferenceObject(Thread); 2943 #else 2944 /* Only implemented on x86 */ 2945 Status = STATUS_NOT_IMPLEMENTED; 2946 #endif 2947 break; 2948 2949 case ThreadPriorityBoost: 2950 2951 /* Set the return length*/ 2952 Length = sizeof(ULONG); 2953 2954 if (ThreadInformationLength != Length) 2955 { 2956 Status = STATUS_INFO_LENGTH_MISMATCH; 2957 break; 2958 } 2959 2960 /* Reference the process */ 2961 Status = ObReferenceObjectByHandle(ThreadHandle, 2962 Access, 2963 PsThreadType, 2964 PreviousMode, 2965 (PVOID*)&Thread, 2966 NULL); 2967 if (!NT_SUCCESS(Status)) 2968 break; 2969 2970 _SEH2_TRY 2971 { 2972 *(PULONG)ThreadInformation = Thread->Tcb.DisableBoost ? 1 : 0; 2973 } 2974 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 2975 { 2976 Status = _SEH2_GetExceptionCode(); 2977 } 2978 _SEH2_END; 2979 2980 /* Dereference the thread */ 2981 ObDereferenceObject(Thread); 2982 break; 2983 2984 case ThreadIsTerminated: 2985 2986 /* Set the return length*/ 2987 Length = sizeof(ThreadTerminated); 2988 2989 if (ThreadInformationLength != Length) 2990 { 2991 Status = STATUS_INFO_LENGTH_MISMATCH; 2992 break; 2993 } 2994 2995 /* Reference the process */ 2996 Status = ObReferenceObjectByHandle(ThreadHandle, 2997 Access, 2998 PsThreadType, 2999 PreviousMode, 3000 (PVOID*)&Thread, 3001 NULL); 3002 if (!NT_SUCCESS(Status)) 3003 break; 3004 3005 ThreadTerminated = PsIsThreadTerminating(Thread); 3006 3007 _SEH2_TRY 3008 { 3009 *(PULONG)ThreadInformation = ThreadTerminated ? 1 : 0; 3010 } 3011 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 3012 { 3013 Status = _SEH2_GetExceptionCode(); 3014 } 3015 _SEH2_END; 3016 3017 /* Dereference the thread */ 3018 ObDereferenceObject(Thread); 3019 break; 3020 3021 /* Anything else */ 3022 default: 3023 3024 /* Not yet implemented */ 3025 DPRINT1("Not implemented: %lx\n", ThreadInformationClass); 3026 Status = STATUS_NOT_IMPLEMENTED; 3027 } 3028 3029 /* Protect write with SEH */ 3030 _SEH2_TRY 3031 { 3032 /* Check if caller wanted return length */ 3033 if (ReturnLength) *ReturnLength = Length; 3034 } 3035 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 3036 { 3037 /* Get exception code */ 3038 Status = _SEH2_GetExceptionCode(); 3039 } 3040 _SEH2_END; 3041 3042 return Status; 3043 } 3044 3045 /* EOF */ 3046