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