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)
11 /* INCLUDES ******************************************************************/
18 ULONG PspTraceLevel
= 0;
20 /* PRIVATE FUNCTIONS *********************************************************/
24 PsReferenceProcessFilePointer(IN PEPROCESS Process
,
25 OUT PFILE_OBJECT
*FileObject
)
30 /* Lock the process */
31 if (!ExAcquireRundownProtection(&Process
->RundownProtect
))
33 return STATUS_PROCESS_IS_TERMINATING
;
37 Section
= Process
->SectionObject
;
40 /* Get the file object and reference it */
41 *FileObject
= MmGetFileObjectForSection((PVOID
)Section
);
42 ObReferenceObject(*FileObject
);
45 /* Release the protection */
46 ExReleaseRundownProtection(&Process
->RundownProtect
);
49 return Section
? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
;
52 /* PUBLIC FUNCTIONS **********************************************************/
59 NtQueryInformationProcess(IN HANDLE ProcessHandle
,
60 IN PROCESSINFOCLASS ProcessInformationClass
,
61 OUT PVOID ProcessInformation
,
62 IN ULONG ProcessInformationLength
,
63 OUT PULONG ReturnLength OPTIONAL
)
66 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
70 PPROCESS_BASIC_INFORMATION ProcessBasicInfo
=
71 (PPROCESS_BASIC_INFORMATION
)ProcessInformation
;
72 PKERNEL_USER_TIMES ProcessTime
= (PKERNEL_USER_TIMES
)ProcessInformation
;
73 ULONG UserTime
, KernelTime
;
74 PPROCESS_PRIORITY_CLASS PsPriorityClass
= (PPROCESS_PRIORITY_CLASS
)ProcessInformation
;
76 PPROCESS_SESSION_INFORMATION SessionInfo
=
77 (PPROCESS_SESSION_INFORMATION
)ProcessInformation
;
78 PVM_COUNTERS VmCounters
= (PVM_COUNTERS
)ProcessInformation
;
79 PIO_COUNTERS IoCounters
= (PIO_COUNTERS
)ProcessInformation
;
80 PQUOTA_LIMITS QuotaLimits
= (PQUOTA_LIMITS
)ProcessInformation
;
81 PUNICODE_STRING ImageName
;
82 ULONG Cookie
, ExecuteOptions
= 0;
84 PROCESS_VALUES ProcessValues
;
88 /* Check for user-mode caller */
89 if (PreviousMode
!= KernelMode
)
91 /* Prepare to probe parameters */
94 /* Probe the buffer */
95 ProbeForRead(ProcessInformation
,
96 ProcessInformationLength
,
99 /* Probe the return length if required */
100 if (ReturnLength
) ProbeForWriteUlong(ReturnLength
);
102 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
104 /* Return the exception code */
105 _SEH2_YIELD(return _SEH2_GetExceptionCode());
110 if (((ProcessInformationClass
== ProcessCookie
) ||
111 (ProcessInformationClass
== ProcessImageInformation
)) &&
112 (ProcessHandle
!= NtCurrentProcess()))
115 * Retrieving the process cookie is only allowed for the calling process
116 * itself! XP only allows NtCurrentProcess() as process handles even if
117 * a real handle actually represents the current process.
119 return STATUS_INVALID_PARAMETER
;
122 /* Check the information class */
123 switch (ProcessInformationClass
)
125 /* Basic process information */
126 case ProcessBasicInformation
:
128 if (ProcessInformationLength
!= sizeof(PROCESS_BASIC_INFORMATION
))
130 Status
= STATUS_INFO_LENGTH_MISMATCH
;
134 /* Set return length */
135 Length
= sizeof(PROCESS_BASIC_INFORMATION
);
137 /* Reference the process */
138 Status
= ObReferenceObjectByHandle(ProcessHandle
,
139 PROCESS_QUERY_INFORMATION
,
144 if (!NT_SUCCESS(Status
)) break;
146 /* Protect writes with SEH */
149 /* Write all the information from the EPROCESS/KPROCESS */
150 ProcessBasicInfo
->ExitStatus
= Process
->ExitStatus
;
151 ProcessBasicInfo
->PebBaseAddress
= Process
->Peb
;
152 ProcessBasicInfo
->AffinityMask
= Process
->Pcb
.Affinity
;
153 ProcessBasicInfo
->UniqueProcessId
= (ULONG_PTR
)Process
->
155 ProcessBasicInfo
->InheritedFromUniqueProcessId
=
156 (ULONG_PTR
)Process
->InheritedFromUniqueProcessId
;
157 ProcessBasicInfo
->BasePriority
= Process
->Pcb
.BasePriority
;
160 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
162 /* Get exception code */
163 Status
= _SEH2_GetExceptionCode();
167 /* Dereference the process */
168 ObDereferenceObject(Process
);
171 /* Process quota limits */
172 case ProcessQuotaLimits
:
174 if (ProcessInformationLength
!= sizeof(QUOTA_LIMITS
))
176 Status
= STATUS_INFO_LENGTH_MISMATCH
;
180 Length
= sizeof(QUOTA_LIMITS
);
182 /* Reference the process */
183 Status
= ObReferenceObjectByHandle(ProcessHandle
,
184 PROCESS_QUERY_INFORMATION
,
189 if (!NT_SUCCESS(Status
)) break;
191 /* Indicate success */
192 Status
= STATUS_SUCCESS
;
196 /* Set max/min working set sizes */
197 QuotaLimits
->MaximumWorkingSetSize
=
198 Process
->Vm
.MaximumWorkingSetSize
<< PAGE_SHIFT
;
199 QuotaLimits
->MinimumWorkingSetSize
=
200 Process
->Vm
.MinimumWorkingSetSize
<< PAGE_SHIFT
;
202 /* Set default time limits */
203 QuotaLimits
->TimeLimit
.LowPart
= MAXULONG
;
204 QuotaLimits
->TimeLimit
.HighPart
= MAXULONG
;
206 /* Is quota block a default one? */
207 if (Process
->QuotaBlock
== &PspDefaultQuotaBlock
)
209 /* Set default pools and pagefile limits */
210 QuotaLimits
->PagedPoolLimit
= (SIZE_T
)-1;
211 QuotaLimits
->NonPagedPoolLimit
= (SIZE_T
)-1;
212 QuotaLimits
->PagefileLimit
= (SIZE_T
)-1;
216 /* Get limits from non-default quota block */
217 QuotaLimits
->PagedPoolLimit
=
218 Process
->QuotaBlock
->QuotaEntry
[PagedPool
].Limit
;
219 QuotaLimits
->NonPagedPoolLimit
=
220 Process
->QuotaBlock
->QuotaEntry
[NonPagedPool
].Limit
;
221 QuotaLimits
->PagefileLimit
=
222 Process
->QuotaBlock
->QuotaEntry
[2].Limit
;
225 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
227 /* Get exception code */
228 Status
= _SEH2_GetExceptionCode();
232 /* Dereference the process */
233 ObDereferenceObject(Process
);
236 case ProcessIoCounters
:
238 if (ProcessInformationLength
!= sizeof(IO_COUNTERS
))
240 Status
= STATUS_INFO_LENGTH_MISMATCH
;
244 Length
= sizeof(IO_COUNTERS
);
246 /* Reference the process */
247 Status
= ObReferenceObjectByHandle(ProcessHandle
,
248 PROCESS_QUERY_INFORMATION
,
253 if (!NT_SUCCESS(Status
)) break;
255 /* Query IO counters from the process */
256 KeQueryValuesProcess(&Process
->Pcb
, &ProcessValues
);
260 RtlCopyMemory(IoCounters
, &ProcessValues
.IoInfo
, sizeof(IO_COUNTERS
));
262 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
264 /* Ignore exception */
268 /* Set status to success in any case */
269 Status
= STATUS_SUCCESS
;
271 /* Dereference the process */
272 ObDereferenceObject(Process
);
278 /* Set the return length */
279 if (ProcessInformationLength
!= sizeof(KERNEL_USER_TIMES
))
281 Status
= STATUS_INFO_LENGTH_MISMATCH
;
285 Length
= sizeof(KERNEL_USER_TIMES
);
287 /* Reference the process */
288 Status
= ObReferenceObjectByHandle(ProcessHandle
,
289 PROCESS_QUERY_INFORMATION
,
294 if (!NT_SUCCESS(Status
)) break;
296 /* Protect writes with SEH */
299 /* Copy time information from EPROCESS/KPROCESS */
300 KernelTime
= KeQueryRuntimeProcess(&Process
->Pcb
, &UserTime
);
301 ProcessTime
->CreateTime
= Process
->CreateTime
;
302 ProcessTime
->UserTime
.QuadPart
= (LONGLONG
)UserTime
* KeMaximumIncrement
;
303 ProcessTime
->KernelTime
.QuadPart
= (LONGLONG
)KernelTime
* KeMaximumIncrement
;
304 ProcessTime
->ExitTime
= Process
->ExitTime
;
306 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
308 /* Get exception code */
309 Status
= _SEH2_GetExceptionCode();
313 /* Dereference the process */
314 ObDereferenceObject(Process
);
317 /* Process Debug Port */
318 case ProcessDebugPort
:
320 if (ProcessInformationLength
!= sizeof(HANDLE
))
322 Status
= STATUS_INFO_LENGTH_MISMATCH
;
326 /* Set return length */
327 Length
= sizeof(HANDLE
);
329 /* Reference the process */
330 Status
= ObReferenceObjectByHandle(ProcessHandle
,
331 PROCESS_QUERY_INFORMATION
,
336 if (!NT_SUCCESS(Status
)) break;
338 /* Protect write with SEH */
341 /* Return whether or not we have a debug port */
342 *(PHANDLE
)ProcessInformation
= (Process
->DebugPort
?
345 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
347 /* Get exception code */
348 Status
= _SEH2_GetExceptionCode();
352 /* Dereference the process */
353 ObDereferenceObject(Process
);
356 case ProcessHandleCount
:
358 if (ProcessInformationLength
!= sizeof(ULONG
))
360 Status
= STATUS_INFO_LENGTH_MISMATCH
;
364 /* Set the return length*/
365 Length
= sizeof(ULONG
);
367 /* Reference the process */
368 Status
= ObReferenceObjectByHandle(ProcessHandle
,
369 PROCESS_QUERY_INFORMATION
,
374 if (!NT_SUCCESS(Status
)) break;
376 /* Count the number of handles this process has */
377 HandleCount
= ObGetProcessHandleCount(Process
);
379 /* Protect write in SEH */
382 /* Return the count of handles */
383 *(PULONG
)ProcessInformation
= HandleCount
;
385 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
387 /* Get the exception code */
388 Status
= _SEH2_GetExceptionCode();
392 /* Dereference the process */
393 ObDereferenceObject(Process
);
396 /* Session ID for the process */
397 case ProcessSessionInformation
:
399 if (ProcessInformationLength
!= sizeof(PROCESS_SESSION_INFORMATION
))
401 Status
= STATUS_INFO_LENGTH_MISMATCH
;
405 /* Set the return length*/
406 Length
= sizeof(PROCESS_SESSION_INFORMATION
);
408 /* Reference the process */
409 Status
= ObReferenceObjectByHandle(ProcessHandle
,
410 PROCESS_QUERY_INFORMATION
,
415 if (!NT_SUCCESS(Status
)) break;
417 /* Enter SEH for write safety */
420 /* Write back the Session ID */
421 SessionInfo
->SessionId
= PsGetProcessSessionId(Process
);
423 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
425 /* Get the exception code */
426 Status
= _SEH2_GetExceptionCode();
430 /* Dereference the process */
431 ObDereferenceObject(Process
);
434 /* Virtual Memory Statistics */
435 case ProcessVmCounters
:
437 /* Validate the input length */
438 if ((ProcessInformationLength
!= sizeof(VM_COUNTERS
)) &&
439 (ProcessInformationLength
!= sizeof(VM_COUNTERS_EX
)))
441 Status
= STATUS_INFO_LENGTH_MISMATCH
;
445 /* Reference the process */
446 Status
= ObReferenceObjectByHandle(ProcessHandle
,
447 PROCESS_QUERY_INFORMATION
,
452 if (!NT_SUCCESS(Status
)) break;
454 /* Enter SEH for write safety */
457 /* Return data from EPROCESS */
458 VmCounters
->PeakVirtualSize
= Process
->PeakVirtualSize
;
459 VmCounters
->VirtualSize
= Process
->VirtualSize
;
460 VmCounters
->PageFaultCount
= Process
->Vm
.PageFaultCount
;
461 VmCounters
->PeakWorkingSetSize
= Process
->Vm
.PeakWorkingSetSize
;
462 VmCounters
->WorkingSetSize
= Process
->Vm
.WorkingSetSize
;
463 VmCounters
->QuotaPeakPagedPoolUsage
= Process
->QuotaPeak
[0];
464 VmCounters
->QuotaPagedPoolUsage
= Process
->QuotaUsage
[0];
465 VmCounters
->QuotaPeakNonPagedPoolUsage
= Process
->QuotaPeak
[1];
466 VmCounters
->QuotaNonPagedPoolUsage
= Process
->QuotaUsage
[1];
467 VmCounters
->PagefileUsage
= Process
->QuotaUsage
[2] << PAGE_SHIFT
;
468 VmCounters
->PeakPagefileUsage
= Process
->QuotaPeak
[2] << PAGE_SHIFT
;
469 //VmCounters->PrivateUsage = Process->CommitCharge << PAGE_SHIFT;
472 /* Set the return length */
473 Length
= ProcessInformationLength
;
475 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
477 /* Get the exception code */
478 Status
= _SEH2_GetExceptionCode();
482 /* Dereference the process */
483 ObDereferenceObject(Process
);
486 /* Hard Error Processing Mode */
487 case ProcessDefaultHardErrorMode
:
489 if (ProcessInformationLength
!= sizeof(ULONG
))
491 Status
= STATUS_INFO_LENGTH_MISMATCH
;
495 /* Set the return length*/
496 Length
= sizeof(ULONG
);
498 /* Reference the process */
499 Status
= ObReferenceObjectByHandle(ProcessHandle
,
500 PROCESS_QUERY_INFORMATION
,
505 if (!NT_SUCCESS(Status
)) break;
507 /* Enter SEH for writing back data */
510 /* Write the current processing mode */
511 *(PULONG
)ProcessInformation
= Process
->
512 DefaultHardErrorProcessing
;
514 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
516 /* Get the exception code */
517 Status
= _SEH2_GetExceptionCode();
521 /* Dereference the process */
522 ObDereferenceObject(Process
);
525 /* Priority Boosting status */
526 case ProcessPriorityBoost
:
528 if (ProcessInformationLength
!= sizeof(ULONG
))
530 Status
= STATUS_INFO_LENGTH_MISMATCH
;
534 /* Set the return length */
535 Length
= sizeof(ULONG
);
537 /* Reference the process */
538 Status
= ObReferenceObjectByHandle(ProcessHandle
,
539 PROCESS_QUERY_INFORMATION
,
544 if (!NT_SUCCESS(Status
)) break;
546 /* Enter SEH for writing back data */
549 /* Return boost status */
550 *(PULONG
)ProcessInformation
= Process
->Pcb
.DisableBoost
?
553 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
555 /* Get the exception code */
556 Status
= _SEH2_GetExceptionCode();
560 /* Dereference the process */
561 ObDereferenceObject(Process
);
565 case ProcessDeviceMap
:
567 if (ProcessInformationLength
< sizeof(PROCESS_DEVICEMAP_INFORMATION
))
569 Status
= STATUS_INFO_LENGTH_MISMATCH
;
573 if (ProcessInformationLength
== sizeof(PROCESS_DEVICEMAP_INFORMATION_EX
))
575 /* Protect read in SEH */
578 PPROCESS_DEVICEMAP_INFORMATION_EX DeviceMapEx
= ProcessInformation
;
580 Flags
= DeviceMapEx
->Flags
;
582 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
584 /* Get the exception code */
585 Status
= _SEH2_GetExceptionCode();
589 if (!NT_SUCCESS(Status
))
594 /* Only one flag is supported and it needs LUID mappings */
595 if ((Flags
& ~PROCESS_LUID_DOSDEVICES_ONLY
) != 0 ||
596 !ObIsLUIDDeviceMapsEnabled())
598 Status
= STATUS_INVALID_PARAMETER
;
604 if (ProcessInformationLength
!= sizeof(PROCESS_DEVICEMAP_INFORMATION
))
606 Status
= STATUS_INFO_LENGTH_MISMATCH
;
610 /* No flags for standard call */
614 /* Set the return length */
615 Length
= ProcessInformationLength
;
617 /* Reference the process */
618 Status
= ObReferenceObjectByHandle(ProcessHandle
,
619 PROCESS_QUERY_INFORMATION
,
624 if (!NT_SUCCESS(Status
)) break;
626 /* Query the device map information */
627 Status
= ObQueryDeviceMapInformation(Process
,
631 /* Dereference the process */
632 ObDereferenceObject(Process
);
636 case ProcessPriorityClass
:
638 if (ProcessInformationLength
!= sizeof(PROCESS_PRIORITY_CLASS
))
640 Status
= STATUS_INFO_LENGTH_MISMATCH
;
644 /* Set the return length*/
645 Length
= sizeof(PROCESS_PRIORITY_CLASS
);
647 /* Reference the process */
648 Status
= ObReferenceObjectByHandle(ProcessHandle
,
649 PROCESS_QUERY_INFORMATION
,
654 if (!NT_SUCCESS(Status
)) break;
656 /* Enter SEH for writing back data */
659 /* Return current priority class */
660 PsPriorityClass
->PriorityClass
= Process
->PriorityClass
;
661 PsPriorityClass
->Foreground
= FALSE
;
663 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
665 /* Get the exception code */
666 Status
= _SEH2_GetExceptionCode();
670 /* Dereference the process */
671 ObDereferenceObject(Process
);
674 case ProcessImageFileName
:
676 /* Reference the process */
677 Status
= ObReferenceObjectByHandle(ProcessHandle
,
678 PROCESS_QUERY_INFORMATION
,
683 if (!NT_SUCCESS(Status
)) break;
685 /* Get the image path */
686 Status
= SeLocateProcessImageName(Process
, &ImageName
);
687 if (NT_SUCCESS(Status
))
689 /* Set return length */
690 Length
= ImageName
->MaximumLength
+
691 sizeof(OBJECT_NAME_INFORMATION
);
693 /* Make sure it's large enough */
694 if (Length
<= ProcessInformationLength
)
696 /* Enter SEH to protect write */
700 RtlCopyMemory(ProcessInformation
,
705 ((PUNICODE_STRING
)ProcessInformation
)->Buffer
=
706 (PWSTR
)((PUNICODE_STRING
)ProcessInformation
+ 1);
708 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
710 /* Get the exception code */
711 Status
= _SEH2_GetExceptionCode();
717 /* Buffer too small */
718 Status
= STATUS_INFO_LENGTH_MISMATCH
;
721 /* Free the image path */
722 ExFreePoolWithTag(ImageName
, TAG_SEPA
);
724 /* Dereference the process */
725 ObDereferenceObject(Process
);
728 case ProcessDebugFlags
:
730 if (ProcessInformationLength
!= sizeof(ULONG
))
732 Status
= STATUS_INFO_LENGTH_MISMATCH
;
736 /* Set the return length*/
737 Length
= sizeof(ULONG
);
739 /* Reference the process */
740 Status
= ObReferenceObjectByHandle(ProcessHandle
,
741 PROCESS_QUERY_INFORMATION
,
746 if (!NT_SUCCESS(Status
)) break;
748 /* Enter SEH for writing back data */
751 /* Return the debug flag state */
752 *(PULONG
)ProcessInformation
= Process
->NoDebugInherit
? 0 : 1;
754 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
756 /* Get the exception code */
757 Status
= _SEH2_GetExceptionCode();
761 /* Dereference the process */
762 ObDereferenceObject(Process
);
765 case ProcessBreakOnTermination
:
767 if (ProcessInformationLength
!= sizeof(ULONG
))
769 Status
= STATUS_INFO_LENGTH_MISMATCH
;
773 /* Set the return length */
774 Length
= sizeof(ULONG
);
776 /* Reference the process */
777 Status
= ObReferenceObjectByHandle(ProcessHandle
,
778 PROCESS_QUERY_INFORMATION
,
783 if (!NT_SUCCESS(Status
)) break;
785 /* Enter SEH for writing back data */
788 /* Return the BreakOnTermination state */
789 *(PULONG
)ProcessInformation
= Process
->BreakOnTermination
;
791 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
793 /* Get the exception code */
794 Status
= _SEH2_GetExceptionCode();
798 /* Dereference the process */
799 ObDereferenceObject(Process
);
802 /* Per-process security cookie */
805 /* Get the current process and cookie */
806 Process
= PsGetCurrentProcess();
807 Cookie
= Process
->Cookie
;
810 LARGE_INTEGER SystemTime
;
814 /* Generate a new cookie */
815 KeQuerySystemTime(&SystemTime
);
816 Prcb
= KeGetCurrentPrcb();
817 NewCookie
= Prcb
->KeSystemCalls
^ Prcb
->InterruptTime
^
818 SystemTime
.u
.LowPart
^ SystemTime
.u
.HighPart
;
820 /* Set the new cookie or return the current one */
821 Cookie
= InterlockedCompareExchange((LONG
*)&Process
->Cookie
,
824 if (!Cookie
) Cookie
= NewCookie
;
826 /* Set return length */
827 Length
= sizeof(ULONG
);
830 /* Indicate success */
831 Status
= STATUS_SUCCESS
;
833 /* Enter SEH to protect write */
836 /* Write back the cookie */
837 *(PULONG
)ProcessInformation
= Cookie
;
839 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
841 /* Get the exception code */
842 Status
= _SEH2_GetExceptionCode();
847 case ProcessImageInformation
:
849 if (ProcessInformationLength
!= sizeof(SECTION_IMAGE_INFORMATION
))
852 Status
= STATUS_INFO_LENGTH_MISMATCH
;
856 /* Set the length required and validate it */
857 Length
= sizeof(SECTION_IMAGE_INFORMATION
);
859 /* Enter SEH to protect write */
862 MmGetImageInformation((PSECTION_IMAGE_INFORMATION
)ProcessInformation
);
864 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
866 /* Get the exception code */
867 Status
= _SEH2_GetExceptionCode();
871 /* Indicate success */
872 Status
= STATUS_SUCCESS
;
875 case ProcessDebugObjectHandle
:
877 if (ProcessInformationLength
!= sizeof(HANDLE
))
879 Status
= STATUS_INFO_LENGTH_MISMATCH
;
883 /* Set the return length */
884 Length
= sizeof(HANDLE
);
886 /* Reference the process */
887 Status
= ObReferenceObjectByHandle(ProcessHandle
,
888 PROCESS_QUERY_INFORMATION
,
893 if (!NT_SUCCESS(Status
)) break;
895 /* Get the debug port */
896 Status
= DbgkOpenProcessDebugPort(Process
, PreviousMode
, &DebugPort
);
898 /* Let go of the process */
899 ObDereferenceObject(Process
);
901 /* Protect write in SEH */
904 /* Return debug port's handle */
905 *(PHANDLE
)ProcessInformation
= DebugPort
;
907 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
909 /* Get the exception code */
910 Status
= _SEH2_GetExceptionCode();
915 case ProcessHandleTracing
:
916 DPRINT1("Handle tracing Not implemented: %lx\n", ProcessInformationClass
);
917 Status
= STATUS_NOT_IMPLEMENTED
;
920 case ProcessLUIDDeviceMapsEnabled
:
922 if (ProcessInformationLength
!= sizeof(ULONG
))
924 Status
= STATUS_INFO_LENGTH_MISMATCH
;
928 /* Set the return length */
929 Length
= sizeof(ULONG
);
931 /* Indicate success */
932 Status
= STATUS_SUCCESS
;
934 /* Protect write in SEH */
938 *(PULONG
)ProcessInformation
= ObIsLUIDDeviceMapsEnabled();
940 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
942 /* Get the exception code */
943 Status
= _SEH2_GetExceptionCode();
948 case ProcessWx86Information
:
950 if (ProcessInformationLength
!= sizeof(ULONG
))
952 Status
= STATUS_INFO_LENGTH_MISMATCH
;
956 /* Set the return length */
957 Length
= sizeof(ULONG
);
959 /* Reference the process */
960 Status
= ObReferenceObjectByHandle(ProcessHandle
,
961 PROCESS_QUERY_INFORMATION
,
966 if (!NT_SUCCESS(Status
)) break;
968 /* Protect write in SEH */
971 /* Return if the flag is set */
972 *(PULONG
)ProcessInformation
= (ULONG
)Process
->VdmAllowed
;
974 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
976 /* Get the exception code */
977 Status
= _SEH2_GetExceptionCode();
981 /* Dereference the process */
982 ObDereferenceObject(Process
);
985 case ProcessWow64Information
:
987 if (ProcessInformationLength
!= sizeof(ULONG_PTR
))
989 Status
= STATUS_INFO_LENGTH_MISMATCH
;
993 /* Set return length */
994 Length
= sizeof(ULONG_PTR
);
996 /* Reference the process */
997 Status
= ObReferenceObjectByHandle(ProcessHandle
,
998 PROCESS_QUERY_INFORMATION
,
1003 if (!NT_SUCCESS(Status
)) break;
1005 /* Make sure the process isn't dying */
1006 if (ExAcquireRundownProtection(&Process
->RundownProtect
))
1008 /* Get the WOW64 process structure */
1010 Wow64
= (ULONG_PTR
)Process
->Wow64Process
;
1014 /* Release the lock */
1015 ExReleaseRundownProtection(&Process
->RundownProtect
);
1018 /* Protect write with SEH */
1021 /* Return whether or not we have a debug port */
1022 *(PULONG_PTR
)ProcessInformation
= Wow64
;
1024 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1026 /* Get exception code */
1027 Status
= _SEH2_GetExceptionCode();
1031 /* Dereference the process */
1032 ObDereferenceObject(Process
);
1035 case ProcessExecuteFlags
:
1037 if (ProcessInformationLength
!= sizeof(ULONG
))
1039 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1043 /* Set return length */
1044 Length
= sizeof(ULONG
);
1046 if (ProcessHandle
!= NtCurrentProcess())
1048 return STATUS_INVALID_PARAMETER
;
1051 /* Get the options */
1052 Status
= MmGetExecuteOptions(&ExecuteOptions
);
1053 if (NT_SUCCESS(Status
))
1055 /* Protect write with SEH */
1059 *(PULONG
)ProcessInformation
= ExecuteOptions
;
1061 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1063 /* Get exception code */
1064 Status
= _SEH2_GetExceptionCode();
1070 case ProcessLdtInformation
:
1071 DPRINT1("VDM/16-bit not implemented: %lx\n", ProcessInformationClass
);
1072 Status
= STATUS_NOT_IMPLEMENTED
;
1075 case ProcessWorkingSetWatch
:
1076 DPRINT1("WS Watch Not implemented: %lx\n", ProcessInformationClass
);
1077 Status
= STATUS_NOT_IMPLEMENTED
;
1080 case ProcessPooledUsageAndLimits
:
1081 DPRINT1("Pool limits Not implemented: %lx\n", ProcessInformationClass
);
1082 Status
= STATUS_NOT_IMPLEMENTED
;
1085 /* Not supported by Server 2003 */
1087 DPRINT1("Unsupported info class: %lx\n", ProcessInformationClass
);
1088 Status
= STATUS_INVALID_INFO_CLASS
;
1091 /* Protect write with SEH */
1094 /* Check if caller wanted return length */
1095 if ((ReturnLength
) && (Length
)) *ReturnLength
= Length
;
1097 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1099 /* Get exception code */
1100 Status
= _SEH2_GetExceptionCode();
1112 NtSetInformationProcess(IN HANDLE ProcessHandle
,
1113 IN PROCESSINFOCLASS ProcessInformationClass
,
1114 IN PVOID ProcessInformation
,
1115 IN ULONG ProcessInformationLength
)
1118 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1121 HANDLE PortHandle
= NULL
;
1122 HANDLE TokenHandle
= NULL
;
1123 HANDLE DirectoryHandle
= NULL
;
1124 PROCESS_SESSION_INFORMATION SessionInfo
= {0};
1125 PROCESS_PRIORITY_CLASS PriorityClass
= {0};
1126 PROCESS_FOREGROUND_BACKGROUND Foreground
= {0};
1127 PVOID ExceptionPort
;
1129 KAFFINITY ValidAffinity
, Affinity
= 0;
1130 KPRIORITY BasePriority
= 0;
1131 UCHAR MemoryPriority
= 0;
1132 BOOLEAN DisableBoost
= 0;
1133 ULONG DefaultHardErrorMode
= 0;
1134 ULONG DebugFlags
= 0, EnableFixup
= 0, Boost
= 0;
1135 ULONG NoExecute
= 0, VdmPower
= 0;
1136 BOOLEAN HasPrivilege
;
1141 /* Verify Information Class validity */
1143 Status
= DefaultSetInfoBufferCheck(ProcessInformationClass
,
1145 RTL_NUMBER_OF(PsProcessInfoClass
),
1147 ProcessInformationLength
,
1149 if (!NT_SUCCESS(Status
)) return Status
;
1152 /* Check what class this is */
1153 Access
= PROCESS_SET_INFORMATION
;
1154 if (ProcessInformationClass
== ProcessSessionInformation
)
1156 /* Setting the Session ID needs a special mask */
1157 Access
|= PROCESS_SET_SESSIONID
;
1159 else if (ProcessInformationClass
== ProcessExceptionPort
)
1161 /* Setting the exception port needs a special mask */
1162 Access
|= PROCESS_SUSPEND_RESUME
;
1165 /* Reference the process */
1166 Status
= ObReferenceObjectByHandle(ProcessHandle
,
1172 if (!NT_SUCCESS(Status
)) return Status
;
1174 /* Check what kind of information class this is */
1175 switch (ProcessInformationClass
)
1177 case ProcessWx86Information
:
1179 /* Check buffer length */
1180 if (ProcessInformationLength
!= sizeof(HANDLE
))
1182 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1186 /* Use SEH for capture */
1189 /* Capture the boolean */
1190 VdmPower
= *(PULONG
)ProcessInformation
;
1192 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1194 /* Get the exception code */
1195 Status
= _SEH2_GetExceptionCode();
1200 /* Getting VDM powers requires the SeTcbPrivilege */
1201 if (!SeSinglePrivilegeCheck(SeTcbPrivilege
, PreviousMode
))
1203 /* We don't hold the privilege, bail out */
1204 Status
= STATUS_PRIVILEGE_NOT_HELD
;
1205 DPRINT1("Need TCB privilege\n");
1209 /* Set or clear the flag */
1212 PspSetProcessFlag(Process
, PSF_VDM_ALLOWED_BIT
);
1216 PspClearProcessFlag(Process
, PSF_VDM_ALLOWED_BIT
);
1220 /* Error/Exception Port */
1221 case ProcessExceptionPort
:
1223 /* Check buffer length */
1224 if (ProcessInformationLength
!= sizeof(HANDLE
))
1226 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1230 /* Use SEH for capture */
1233 /* Capture the handle */
1234 PortHandle
= *(PHANDLE
)ProcessInformation
;
1236 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1238 /* Get the exception code */
1239 Status
= _SEH2_GetExceptionCode();
1244 /* Setting the error port requires the SeTcbPrivilege */
1245 if (!SeSinglePrivilegeCheck(SeTcbPrivilege
, PreviousMode
))
1247 /* We don't hold the privilege, bail out */
1248 Status
= STATUS_PRIVILEGE_NOT_HELD
;
1252 /* Get the LPC Port */
1253 Status
= ObReferenceObjectByHandle(PortHandle
,
1257 (PVOID
)&ExceptionPort
,
1259 if (!NT_SUCCESS(Status
)) break;
1261 /* Change the pointer */
1262 if (InterlockedCompareExchangePointer(&Process
->ExceptionPort
,
1266 /* We already had one, fail */
1267 ObDereferenceObject(ExceptionPort
);
1268 Status
= STATUS_PORT_ALREADY_SET
;
1272 /* Security Token */
1273 case ProcessAccessToken
:
1275 /* Check buffer length */
1276 if (ProcessInformationLength
!= sizeof(PROCESS_ACCESS_TOKEN
))
1278 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1282 /* Use SEH for capture */
1285 /* Save the token handle */
1286 TokenHandle
= ((PPROCESS_ACCESS_TOKEN
)ProcessInformation
)->
1289 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1291 /* Get the exception code */
1292 Status
= _SEH2_GetExceptionCode();
1297 /* Assign the actual token */
1298 Status
= PspSetPrimaryToken(Process
, TokenHandle
, NULL
);
1301 /* Hard error processing */
1302 case ProcessDefaultHardErrorMode
:
1304 /* Check buffer length */
1305 if (ProcessInformationLength
!= sizeof(ULONG
))
1307 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1311 /* Enter SEH for direct buffer read */
1314 DefaultHardErrorMode
= *(PULONG
)ProcessInformation
;
1316 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1318 /* Get exception code */
1319 Status
= _SEH2_GetExceptionCode();
1325 Process
->DefaultHardErrorProcessing
= DefaultHardErrorMode
;
1327 /* Call Ke for the update */
1328 if (DefaultHardErrorMode
& SEM_NOALIGNMENTFAULTEXCEPT
)
1330 KeSetAutoAlignmentProcess(&Process
->Pcb
, TRUE
);
1334 KeSetAutoAlignmentProcess(&Process
->Pcb
, FALSE
);
1336 Status
= STATUS_SUCCESS
;
1340 case ProcessSessionInformation
:
1342 /* Check buffer length */
1343 if (ProcessInformationLength
!= sizeof(PROCESS_SESSION_INFORMATION
))
1345 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1349 /* Enter SEH for capture */
1352 /* Capture the caller's buffer */
1353 SessionInfo
= *(PPROCESS_SESSION_INFORMATION
)ProcessInformation
;
1355 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1357 /* Get the exception code */
1358 Status
= _SEH2_GetExceptionCode();
1363 /* Setting the session id requires the SeTcbPrivilege */
1364 if (!SeSinglePrivilegeCheck(SeTcbPrivilege
, PreviousMode
))
1366 /* We don't hold the privilege, bail out */
1367 Status
= STATUS_PRIVILEGE_NOT_HELD
;
1371 #if 0 // OLD AND DEPRECATED CODE!!!!
1373 /* FIXME - update the session id for the process token */
1374 //Status = PsLockProcess(Process, FALSE);
1375 if (!NT_SUCCESS(Status
)) break;
1377 /* Write the session ID in the EPROCESS */
1378 Process
->Session
= UlongToPtr(SessionInfo
.SessionId
); // HACK!!!
1380 /* Check if the process also has a PEB */
1384 * Attach to the process to make sure we're in the right
1385 * context to access the PEB structure
1387 KeAttachProcess(&Process
->Pcb
);
1389 /* Enter SEH for write to user-mode PEB */
1392 /* Write the session ID */
1393 Process
->Peb
->SessionId
= SessionInfo
.SessionId
;
1395 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1397 /* Get exception code */
1398 Status
= _SEH2_GetExceptionCode();
1402 /* Detach from the process */
1406 /* Unlock the process */
1407 //PsUnlockProcess(Process);
1412 * Since we cannot change the session ID of the given
1413 * process anymore because it is set once and for all
1414 * at process creation time and because it is stored
1415 * inside the Process->Session structure managed by MM,
1416 * we fake changing it: we just return success if the
1417 * user-defined value is the same as the session ID of
1418 * the process, and otherwise we fail.
1420 if (SessionInfo
.SessionId
== PsGetProcessSessionId(Process
))
1422 Status
= STATUS_SUCCESS
;
1426 Status
= STATUS_ACCESS_DENIED
;
1431 case ProcessPriorityClass
:
1433 /* Check buffer length */
1434 if (ProcessInformationLength
!= sizeof(PROCESS_PRIORITY_CLASS
))
1436 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1440 /* Enter SEH for capture */
1443 /* Capture the caller's buffer */
1444 PriorityClass
= *(PPROCESS_PRIORITY_CLASS
)ProcessInformation
;
1446 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1448 /* Return the exception code */
1449 Status
= _SEH2_GetExceptionCode();
1454 /* Check for invalid PriorityClass value */
1455 if (PriorityClass
.PriorityClass
> PROCESS_PRIORITY_CLASS_ABOVE_NORMAL
)
1457 Status
= STATUS_INVALID_PARAMETER
;
1461 if ((PriorityClass
.PriorityClass
!= Process
->PriorityClass
) &&
1462 (PriorityClass
.PriorityClass
== PROCESS_PRIORITY_CLASS_REALTIME
))
1464 /* Check the privilege */
1465 HasPrivilege
= SeCheckPrivilegedObject(SeIncreaseBasePriorityPrivilege
,
1467 PROCESS_SET_INFORMATION
,
1471 ObDereferenceObject(Process
);
1472 DPRINT1("Privilege to change priority to realtime lacking\n");
1473 return STATUS_PRIVILEGE_NOT_HELD
;
1477 /* Check if we have a job */
1480 DPRINT1("Jobs not yet supported\n");
1483 /* Set process priority class */
1484 Process
->PriorityClass
= PriorityClass
.PriorityClass
;
1486 /* Set process priority mode (foreground or background) */
1487 PsSetProcessPriorityByClass(Process
,
1488 PriorityClass
.Foreground
?
1489 PsProcessPriorityForeground
:
1490 PsProcessPriorityBackground
);
1491 Status
= STATUS_SUCCESS
;
1494 case ProcessForegroundInformation
:
1496 /* Check buffer length */
1497 if (ProcessInformationLength
!= sizeof(PROCESS_FOREGROUND_BACKGROUND
))
1499 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1503 /* Enter SEH for capture */
1506 /* Capture the caller's buffer */
1507 Foreground
= *(PPROCESS_FOREGROUND_BACKGROUND
)ProcessInformation
;
1509 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1511 /* Return the exception code */
1512 Status
= _SEH2_GetExceptionCode();
1517 /* Set process priority mode (foreground or background) */
1518 PsSetProcessPriorityByClass(Process
,
1519 Foreground
.Foreground
?
1520 PsProcessPriorityForeground
:
1521 PsProcessPriorityBackground
);
1522 Status
= STATUS_SUCCESS
;
1525 case ProcessBasePriority
:
1527 /* Validate input length */
1528 if (ProcessInformationLength
!= sizeof(KPRIORITY
))
1530 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1534 /* Enter SEH for direct buffer read */
1537 BasePriority
= *(KPRIORITY
*)ProcessInformation
;
1539 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1541 /* Get exception code */
1543 Status
= _SEH2_GetExceptionCode();
1548 /* Extract the memory priority out of there */
1549 if (BasePriority
& 0x80000000)
1551 MemoryPriority
= MEMORY_PRIORITY_FOREGROUND
;
1552 BasePriority
&= ~0x80000000;
1556 MemoryPriority
= MEMORY_PRIORITY_BACKGROUND
;
1559 /* Validate the number */
1560 if ((BasePriority
> HIGH_PRIORITY
) || (BasePriority
<= LOW_PRIORITY
))
1562 ObDereferenceObject(Process
);
1563 return STATUS_INVALID_PARAMETER
;
1566 /* Check if the new base is higher */
1567 if (BasePriority
> Process
->Pcb
.BasePriority
)
1569 HasPrivilege
= SeCheckPrivilegedObject(SeIncreaseBasePriorityPrivilege
,
1571 PROCESS_SET_INFORMATION
,
1575 ObDereferenceObject(Process
);
1576 DPRINT1("Privilege to change priority from %lx to %lx lacking\n", BasePriority
, Process
->Pcb
.BasePriority
);
1577 return STATUS_PRIVILEGE_NOT_HELD
;
1582 KeSetPriorityAndQuantumProcess(&Process
->Pcb
, BasePriority
, 0);
1584 /* Now set the memory priority */
1585 MmSetMemoryPriorityProcess(Process
, MemoryPriority
);
1586 Status
= STATUS_SUCCESS
;
1589 case ProcessRaisePriority
:
1591 /* Validate input length */
1592 if (ProcessInformationLength
!= sizeof(ULONG
))
1594 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1598 /* Enter SEH for direct buffer read */
1601 Boost
= *(PULONG
)ProcessInformation
;
1603 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1605 /* Get exception code */
1607 Status
= _SEH2_GetExceptionCode();
1612 /* Make sure the process isn't dying */
1613 if (ExAcquireRundownProtection(&Process
->RundownProtect
))
1616 KeEnterCriticalRegion();
1617 ExAcquirePushLockShared(&Process
->ProcessLock
);
1619 /* Loop the threads */
1620 for (Next
= Process
->ThreadListHead
.Flink
;
1621 Next
!= &Process
->ThreadListHead
;
1624 /* Call Ke for the thread */
1625 Thread
= CONTAINING_RECORD(Next
, ETHREAD
, ThreadListEntry
);
1626 KeBoostPriorityThread(&Thread
->Tcb
, Boost
);
1629 /* Release the lock and rundown */
1630 ExReleasePushLockShared(&Process
->ProcessLock
);
1631 KeLeaveCriticalRegion();
1632 ExReleaseRundownProtection(&Process
->RundownProtect
);
1634 /* Set success code */
1635 Status
= STATUS_SUCCESS
;
1639 /* Avoid race conditions */
1640 Status
= STATUS_PROCESS_IS_TERMINATING
;
1644 case ProcessBreakOnTermination
:
1646 /* Check buffer length */
1647 if (ProcessInformationLength
!= sizeof(ULONG
))
1649 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1653 /* Enter SEH for direct buffer read */
1656 Break
= *(PULONG
)ProcessInformation
;
1658 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1660 /* Get exception code */
1662 Status
= _SEH2_GetExceptionCode();
1667 /* Setting 'break on termination' requires the SeDebugPrivilege */
1668 if (!SeSinglePrivilegeCheck(SeDebugPrivilege
, PreviousMode
))
1670 /* We don't hold the privilege, bail out */
1671 Status
= STATUS_PRIVILEGE_NOT_HELD
;
1675 /* Set or clear the flag */
1678 PspSetProcessFlag(Process
, PSF_BREAK_ON_TERMINATION_BIT
);
1682 PspClearProcessFlag(Process
, PSF_BREAK_ON_TERMINATION_BIT
);
1687 case ProcessAffinityMask
:
1689 /* Check buffer length */
1690 if (ProcessInformationLength
!= sizeof(KAFFINITY
))
1692 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1696 /* Enter SEH for direct buffer read */
1699 Affinity
= *(PKAFFINITY
)ProcessInformation
;
1701 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1703 /* Get exception code */
1705 Status
= _SEH2_GetExceptionCode();
1710 /* Make sure it's valid for the CPUs present */
1711 ValidAffinity
= Affinity
& KeActiveProcessors
;
1712 if (!Affinity
|| (ValidAffinity
!= Affinity
))
1714 Status
= STATUS_INVALID_PARAMETER
;
1718 /* Check if it's within job affinity limits */
1721 /* Not yet implemented */
1723 Status
= STATUS_NOT_IMPLEMENTED
;
1727 /* Make sure the process isn't dying */
1728 if (ExAcquireRundownProtection(&Process
->RundownProtect
))
1731 KeEnterCriticalRegion();
1732 ExAcquirePushLockShared(&Process
->ProcessLock
);
1734 /* Call Ke to do the work */
1735 KeSetAffinityProcess(&Process
->Pcb
, ValidAffinity
);
1737 /* Release the lock and rundown */
1738 ExReleasePushLockShared(&Process
->ProcessLock
);
1739 KeLeaveCriticalRegion();
1740 ExReleaseRundownProtection(&Process
->RundownProtect
);
1742 /* Set success code */
1743 Status
= STATUS_SUCCESS
;
1747 /* Avoid race conditions */
1748 Status
= STATUS_PROCESS_IS_TERMINATING
;
1752 /* Priority Boosting status */
1753 case ProcessPriorityBoost
:
1755 /* Validate input length */
1756 if (ProcessInformationLength
!= sizeof(ULONG
))
1758 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1762 /* Enter SEH for direct buffer read */
1765 DisableBoost
= *(PBOOLEAN
)ProcessInformation
;
1767 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1769 /* Get exception code */
1771 Status
= _SEH2_GetExceptionCode();
1776 /* Make sure the process isn't dying */
1777 if (ExAcquireRundownProtection(&Process
->RundownProtect
))
1780 KeEnterCriticalRegion();
1781 ExAcquirePushLockShared(&Process
->ProcessLock
);
1783 /* Call Ke to do the work */
1784 KeSetDisableBoostProcess(&Process
->Pcb
, DisableBoost
);
1786 /* Loop the threads too */
1787 for (Next
= Process
->ThreadListHead
.Flink
;
1788 Next
!= &Process
->ThreadListHead
;
1791 /* Call Ke for the thread */
1792 Thread
= CONTAINING_RECORD(Next
, ETHREAD
, ThreadListEntry
);
1793 KeSetDisableBoostThread(&Thread
->Tcb
, DisableBoost
);
1796 /* Release the lock and rundown */
1797 ExReleasePushLockShared(&Process
->ProcessLock
);
1798 KeLeaveCriticalRegion();
1799 ExReleaseRundownProtection(&Process
->RundownProtect
);
1801 /* Set success code */
1802 Status
= STATUS_SUCCESS
;
1806 /* Avoid race conditions */
1807 Status
= STATUS_PROCESS_IS_TERMINATING
;
1811 case ProcessDebugFlags
:
1813 /* Check buffer length */
1814 if (ProcessInformationLength
!= sizeof(ULONG
))
1816 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1820 /* Enter SEH for direct buffer read */
1823 DebugFlags
= *(PULONG
)ProcessInformation
;
1825 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1827 /* Get exception code */
1828 Status
= _SEH2_GetExceptionCode();
1834 if (DebugFlags
& ~1)
1836 Status
= STATUS_INVALID_PARAMETER
;
1842 PspClearProcessFlag(Process
, PSF_NO_DEBUG_INHERIT_BIT
);
1846 PspSetProcessFlag(Process
, PSF_NO_DEBUG_INHERIT_BIT
);
1851 Status
= STATUS_SUCCESS
;
1854 case ProcessEnableAlignmentFaultFixup
:
1856 /* Check buffer length */
1857 if (ProcessInformationLength
!= sizeof(ULONG
))
1859 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1863 /* Enter SEH for direct buffer read */
1866 EnableFixup
= *(PULONG
)ProcessInformation
;
1868 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1870 /* Get exception code */
1871 Status
= _SEH2_GetExceptionCode();
1879 Process
->DefaultHardErrorProcessing
|= SEM_NOALIGNMENTFAULTEXCEPT
;
1883 Process
->DefaultHardErrorProcessing
&= ~SEM_NOALIGNMENTFAULTEXCEPT
;
1886 /* Call Ke for the update */
1887 KeSetAutoAlignmentProcess(&Process
->Pcb
, FALSE
);
1888 Status
= STATUS_SUCCESS
;
1891 case ProcessUserModeIOPL
:
1893 /* Only TCB can do this */
1894 if (!SeSinglePrivilegeCheck(SeTcbPrivilege
, PreviousMode
))
1896 /* We don't hold the privilege, bail out */
1897 DPRINT1("Need TCB to set IOPL\n");
1898 Status
= STATUS_PRIVILEGE_NOT_HELD
;
1902 /* Only supported on x86 */
1906 Status
= STATUS_NOT_IMPLEMENTED
;
1911 case ProcessExecuteFlags
:
1913 /* Check buffer length */
1914 if (ProcessInformationLength
!= sizeof(ULONG
))
1916 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1920 if (ProcessHandle
!= NtCurrentProcess())
1922 Status
= STATUS_INVALID_PARAMETER
;
1926 /* Enter SEH for direct buffer read */
1929 NoExecute
= *(PULONG
)ProcessInformation
;
1931 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1933 /* Get exception code */
1934 Status
= _SEH2_GetExceptionCode();
1939 /* Call Mm for the update */
1940 Status
= MmSetExecuteOptions(NoExecute
);
1943 case ProcessDeviceMap
:
1945 /* Check buffer length */
1946 if (ProcessInformationLength
!= sizeof(HANDLE
))
1948 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1952 /* Use SEH for capture */
1955 /* Capture the handle */
1956 DirectoryHandle
= *(PHANDLE
)ProcessInformation
;
1958 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1960 /* Get the exception code */
1961 Status
= _SEH2_GetExceptionCode();
1966 /* Call Ob to set the device map */
1967 Status
= ObSetDeviceMap(Process
, DirectoryHandle
);
1971 /* We currently don't implement any of these */
1972 case ProcessLdtInformation
:
1973 case ProcessLdtSize
:
1974 case ProcessIoPortHandlers
:
1975 DPRINT1("VDM/16-bit Request not implemented: %lx\n", ProcessInformationClass
);
1976 Status
= STATUS_NOT_IMPLEMENTED
;
1979 case ProcessQuotaLimits
:
1981 Status
= PspSetQuotaLimits(Process
,
1984 ProcessInformationLength
,
1988 case ProcessWorkingSetWatch
:
1989 DPRINT1("WS watch not implemented\n");
1990 Status
= STATUS_NOT_IMPLEMENTED
;
1993 case ProcessHandleTracing
:
1994 DPRINT1("Handle tracing not implemented\n");
1995 Status
= STATUS_NOT_IMPLEMENTED
;
1998 /* Anything else is invalid */
2000 DPRINT1("Invalid Server 2003 Info Class: %lx\n", ProcessInformationClass
);
2001 Status
= STATUS_INVALID_INFO_CLASS
;
2004 /* Dereference and return status */
2005 ObDereferenceObject(Process
);
2014 NtSetInformationThread(IN HANDLE ThreadHandle
,
2015 IN THREADINFOCLASS ThreadInformationClass
,
2016 IN PVOID ThreadInformation
,
2017 IN ULONG ThreadInformationLength
)
2021 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2023 HANDLE TokenHandle
= NULL
;
2024 KPRIORITY Priority
= 0;
2025 KAFFINITY Affinity
= 0, CombinedAffinity
;
2026 PVOID Address
= NULL
;
2028 ULONG_PTR DisableBoost
= 0;
2029 ULONG_PTR IdealProcessor
= 0;
2030 ULONG_PTR Break
= 0;
2032 ULONG_PTR TlsIndex
= 0;
2033 PVOID
*ExpansionSlots
;
2034 PETHREAD ProcThread
;
2037 /* Verify Information Class validity */
2039 Status
= DefaultSetInfoBufferCheck(ThreadInformationClass
,
2041 RTL_NUMBER_OF(PsThreadInfoClass
),
2043 ThreadInformationLength
,
2045 if (!NT_SUCCESS(Status
)) return Status
;
2048 /* Check what class this is */
2049 Access
= THREAD_SET_INFORMATION
;
2050 if (ThreadInformationClass
== ThreadImpersonationToken
)
2052 /* Setting the impersonation token needs a special mask */
2053 Access
= THREAD_SET_THREAD_TOKEN
;
2056 /* Reference the thread */
2057 Status
= ObReferenceObjectByHandle(ThreadHandle
,
2063 if (!NT_SUCCESS(Status
)) return Status
;
2065 /* Check what kind of information class this is */
2066 switch (ThreadInformationClass
)
2068 /* Thread priority */
2069 case ThreadPriority
:
2071 /* Check buffer length */
2072 if (ThreadInformationLength
!= sizeof(KPRIORITY
))
2074 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2078 /* Use SEH for capture */
2081 /* Get the priority */
2082 Priority
= *(PLONG
)ThreadInformation
;
2084 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2086 /* Get the exception code */
2087 Status
= _SEH2_GetExceptionCode();
2093 if ((Priority
> HIGH_PRIORITY
) ||
2094 (Priority
<= LOW_PRIORITY
))
2097 Status
= STATUS_INVALID_PARAMETER
;
2101 /* Set the priority */
2102 KeSetPriorityThread(&Thread
->Tcb
, Priority
);
2105 case ThreadBasePriority
:
2107 /* Check buffer length */
2108 if (ThreadInformationLength
!= sizeof(LONG
))
2110 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2114 /* Use SEH for capture */
2117 /* Get the priority */
2118 Priority
= *(PLONG
)ThreadInformation
;
2120 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2122 /* Get the exception code */
2123 Status
= _SEH2_GetExceptionCode();
2129 if ((Priority
> THREAD_BASE_PRIORITY_MAX
) ||
2130 (Priority
< THREAD_BASE_PRIORITY_MIN
))
2132 /* These ones are OK */
2133 if ((Priority
!= THREAD_BASE_PRIORITY_LOWRT
+ 1) &&
2134 (Priority
!= THREAD_BASE_PRIORITY_IDLE
- 1))
2136 /* Check if the process is real time */
2137 if (PsGetCurrentProcess()->PriorityClass
!=
2138 PROCESS_PRIORITY_CLASS_REALTIME
)
2140 /* It isn't, fail */
2141 Status
= STATUS_INVALID_PARAMETER
;
2147 /* Set the base priority */
2148 KeSetBasePriorityThread(&Thread
->Tcb
, Priority
);
2151 case ThreadAffinityMask
:
2153 /* Check buffer length */
2154 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
2156 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2160 /* Use SEH for capture */
2163 /* Get the priority */
2164 Affinity
= *(PULONG_PTR
)ThreadInformation
;
2166 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2168 /* Get the exception code */
2169 Status
= _SEH2_GetExceptionCode();
2178 Status
= STATUS_INVALID_PARAMETER
;
2182 /* Get the process */
2183 Process
= Thread
->ThreadsProcess
;
2185 /* Try to acquire rundown */
2186 if (ExAcquireRundownProtection(&Process
->RundownProtect
))
2189 KeEnterCriticalRegion();
2190 ExAcquirePushLockShared(&Process
->ProcessLock
);
2193 CombinedAffinity
= Affinity
& Process
->Pcb
.Affinity
;
2194 if (CombinedAffinity
!= Affinity
)
2197 Status
= STATUS_INVALID_PARAMETER
;
2201 /* Set the affinity */
2202 KeSetAffinityThread(&Thread
->Tcb
, CombinedAffinity
);
2205 /* Release the lock and rundown */
2206 ExReleasePushLockShared(&Process
->ProcessLock
);
2207 KeLeaveCriticalRegion();
2208 ExReleaseRundownProtection(&Process
->RundownProtect
);
2213 Status
= STATUS_PROCESS_IS_TERMINATING
;
2219 case ThreadImpersonationToken
:
2221 /* Check buffer length */
2222 if (ThreadInformationLength
!= sizeof(HANDLE
))
2224 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2228 /* Use SEH for capture */
2231 /* Save the token handle */
2232 TokenHandle
= *(PHANDLE
)ThreadInformation
;
2234 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2236 /* Get the exception code */
2237 Status
= _SEH2_GetExceptionCode();
2242 /* Assign the actual token */
2243 Status
= PsAssignImpersonationToken(Thread
, TokenHandle
);
2246 case ThreadQuerySetWin32StartAddress
:
2248 /* Check buffer length */
2249 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
2251 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2255 /* Use SEH for capture */
2258 /* Get the priority */
2259 Address
= *(PVOID
*)ThreadInformation
;
2261 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2263 /* Get the exception code */
2264 Status
= _SEH2_GetExceptionCode();
2269 /* Set the address */
2270 Thread
->Win32StartAddress
= Address
;
2273 case ThreadIdealProcessor
:
2275 /* Check buffer length */
2276 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
2278 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2282 /* Use SEH for capture */
2285 /* Get the priority */
2286 IdealProcessor
= *(PULONG_PTR
)ThreadInformation
;
2288 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2290 /* Get the exception code */
2291 Status
= _SEH2_GetExceptionCode();
2297 if (IdealProcessor
> MAXIMUM_PROCESSORS
)
2300 Status
= STATUS_INVALID_PARAMETER
;
2305 Status
= KeSetIdealProcessorThread(&Thread
->Tcb
,
2306 (CCHAR
)IdealProcessor
);
2308 /* Get the TEB and protect the thread */
2309 Teb
= Thread
->Tcb
.Teb
;
2310 if ((Teb
) && (ExAcquireRundownProtection(&Thread
->RundownProtect
)))
2312 /* Save the ideal processor */
2313 Teb
->IdealProcessor
= Thread
->Tcb
.IdealProcessor
;
2315 /* Release rundown protection */
2316 ExReleaseRundownProtection(&Thread
->RundownProtect
);
2321 case ThreadPriorityBoost
:
2323 /* Check buffer length */
2324 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
2326 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2330 /* Use SEH for capture */
2333 /* Get the priority */
2334 DisableBoost
= *(PULONG_PTR
)ThreadInformation
;
2336 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2338 /* Get the exception code */
2339 Status
= _SEH2_GetExceptionCode();
2344 /* Call the kernel */
2345 KeSetDisableBoostThread(&Thread
->Tcb
, (BOOLEAN
)DisableBoost
);
2348 case ThreadZeroTlsCell
:
2350 /* Check buffer length */
2351 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
2353 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2357 /* Use SEH for capture */
2360 /* Get the priority */
2361 TlsIndex
= *(PULONG_PTR
)ThreadInformation
;
2363 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2365 /* Get the exception code */
2366 Status
= _SEH2_GetExceptionCode();
2371 /* This is only valid for the current thread */
2372 if (Thread
!= PsGetCurrentThread())
2375 Status
= STATUS_INVALID_PARAMETER
;
2379 /* Get the process */
2380 Process
= Thread
->ThreadsProcess
;
2382 /* Loop the threads */
2383 ProcThread
= PsGetNextProcessThread(Process
, NULL
);
2386 /* Acquire rundown */
2387 if (ExAcquireRundownProtection(&ProcThread
->RundownProtect
))
2390 Teb
= ProcThread
->Tcb
.Teb
;
2393 /* Check if we're in the expansion range */
2394 if (TlsIndex
> TLS_MINIMUM_AVAILABLE
- 1)
2396 if (TlsIndex
< (TLS_MINIMUM_AVAILABLE
+
2397 TLS_EXPANSION_SLOTS
) - 1)
2399 /* Check if we have expansion slots */
2400 ExpansionSlots
= Teb
->TlsExpansionSlots
;
2403 /* Clear the index */
2404 ExpansionSlots
[TlsIndex
- TLS_MINIMUM_AVAILABLE
] = 0;
2410 /* Clear the index */
2411 Teb
->TlsSlots
[TlsIndex
] = NULL
;
2415 /* Release rundown */
2416 ExReleaseRundownProtection(&ProcThread
->RundownProtect
);
2419 /* Go to the next thread */
2420 ProcThread
= PsGetNextProcessThread(Process
, ProcThread
);
2426 case ThreadBreakOnTermination
:
2428 /* Check buffer length */
2429 if (ThreadInformationLength
!= sizeof(ULONG
))
2431 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2435 /* Enter SEH for direct buffer read */
2438 Break
= *(PULONG
)ThreadInformation
;
2440 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2442 /* Get exception code */
2444 Status
= _SEH2_GetExceptionCode();
2449 /* Setting 'break on termination' requires the SeDebugPrivilege */
2450 if (!SeSinglePrivilegeCheck(SeDebugPrivilege
, PreviousMode
))
2452 /* We don't hold the privilege, bail out */
2453 Status
= STATUS_PRIVILEGE_NOT_HELD
;
2457 /* Set or clear the flag */
2460 PspSetCrossThreadFlag(Thread
, CT_BREAK_ON_TERMINATION_BIT
);
2464 PspClearCrossThreadFlag(Thread
, CT_BREAK_ON_TERMINATION_BIT
);
2468 case ThreadHideFromDebugger
:
2470 /* Check buffer length */
2471 if (ThreadInformationLength
!= 0)
2473 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2478 PspSetCrossThreadFlag(Thread
, CT_HIDE_FROM_DEBUGGER_BIT
);
2482 /* We don't implement it yet */
2483 DPRINT1("Not implemented: %d\n", ThreadInformationClass
);
2484 Status
= STATUS_NOT_IMPLEMENTED
;
2487 /* Dereference and return status */
2488 ObDereferenceObject(Thread
);
2497 NtQueryInformationThread(IN HANDLE ThreadHandle
,
2498 IN THREADINFOCLASS ThreadInformationClass
,
2499 OUT PVOID ThreadInformation
,
2500 IN ULONG ThreadInformationLength
,
2501 OUT PULONG ReturnLength OPTIONAL
)
2504 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
2508 PTHREAD_BASIC_INFORMATION ThreadBasicInfo
=
2509 (PTHREAD_BASIC_INFORMATION
)ThreadInformation
;
2510 PKERNEL_USER_TIMES ThreadTime
= (PKERNEL_USER_TIMES
)ThreadInformation
;
2512 ULONG ThreadTerminated
;
2515 /* Check if we were called from user mode */
2516 if (PreviousMode
!= KernelMode
)
2521 /* Probe the buffer */
2522 ProbeForWrite(ThreadInformation
,
2523 ThreadInformationLength
,
2526 /* Probe the return length if required */
2527 if (ReturnLength
) ProbeForWriteUlong(ReturnLength
);
2529 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2531 /* Return the exception code */
2532 _SEH2_YIELD(return _SEH2_GetExceptionCode());
2537 /* Check what class this is */
2538 Access
= THREAD_QUERY_INFORMATION
;
2540 /* Reference the process */
2541 Status
= ObReferenceObjectByHandle(ThreadHandle
,
2547 if (!NT_SUCCESS(Status
)) return Status
;
2549 /* Check what kind of information class this is */
2550 switch (ThreadInformationClass
)
2552 /* Basic thread information */
2553 case ThreadBasicInformation
:
2555 /* Set return length */
2556 Length
= sizeof(THREAD_BASIC_INFORMATION
);
2558 if (ThreadInformationLength
!= Length
)
2560 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2563 /* Protect writes with SEH */
2566 /* Write all the information from the ETHREAD/KTHREAD */
2567 ThreadBasicInfo
->ExitStatus
= Thread
->ExitStatus
;
2568 ThreadBasicInfo
->TebBaseAddress
= (PVOID
)Thread
->Tcb
.Teb
;
2569 ThreadBasicInfo
->ClientId
= Thread
->Cid
;
2570 ThreadBasicInfo
->AffinityMask
= Thread
->Tcb
.Affinity
;
2571 ThreadBasicInfo
->Priority
= Thread
->Tcb
.Priority
;
2572 ThreadBasicInfo
->BasePriority
= KeQueryBasePriorityThread(&Thread
->Tcb
);
2574 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2576 /* Get exception code */
2577 Status
= _SEH2_GetExceptionCode();
2582 /* Thread time information */
2585 /* Set the return length */
2586 Length
= sizeof(KERNEL_USER_TIMES
);
2588 if (ThreadInformationLength
!= Length
)
2590 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2593 /* Protect writes with SEH */
2596 /* Copy time information from ETHREAD/KTHREAD */
2597 ThreadTime
->KernelTime
.QuadPart
= Thread
->Tcb
.KernelTime
* KeMaximumIncrement
;
2598 ThreadTime
->UserTime
.QuadPart
= Thread
->Tcb
.UserTime
* KeMaximumIncrement
;
2599 ThreadTime
->CreateTime
= Thread
->CreateTime
;
2601 /* Exit time is in a union and only valid on actual exit! */
2602 if (KeReadStateThread(&Thread
->Tcb
))
2604 ThreadTime
->ExitTime
= Thread
->ExitTime
;
2608 ThreadTime
->ExitTime
.QuadPart
= 0;
2611 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2613 /* Get exception code */
2614 Status
= _SEH2_GetExceptionCode();
2619 case ThreadQuerySetWin32StartAddress
:
2621 /* Set the return length*/
2622 Length
= sizeof(PVOID
);
2624 if (ThreadInformationLength
!= Length
)
2626 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2629 /* Protect write with SEH */
2632 /* Return the Win32 Start Address */
2633 *(PVOID
*)ThreadInformation
= Thread
->Win32StartAddress
;
2635 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2637 /* Get exception code */
2638 Status
= _SEH2_GetExceptionCode();
2643 case ThreadPerformanceCount
:
2645 /* Set the return length*/
2646 Length
= sizeof(LARGE_INTEGER
);
2648 if (ThreadInformationLength
!= Length
)
2650 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2653 /* Protect write with SEH */
2657 (*(PLARGE_INTEGER
)ThreadInformation
).QuadPart
= 0;
2659 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2661 /* Get exception code */
2662 Status
= _SEH2_GetExceptionCode();
2667 case ThreadAmILastThread
:
2669 /* Set the return length*/
2670 Length
= sizeof(ULONG
);
2672 if (ThreadInformationLength
!= Length
)
2674 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2677 /* Protect write with SEH */
2680 /* Return whether or not we are the last thread */
2681 *(PULONG
)ThreadInformation
= ((Thread
->ThreadsProcess
->
2682 ThreadListHead
.Flink
->Flink
==
2683 &Thread
->ThreadsProcess
->
2687 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2689 /* Get exception code */
2690 Status
= _SEH2_GetExceptionCode();
2695 case ThreadIsIoPending
:
2697 /* Set the return length*/
2698 Length
= sizeof(ULONG
);
2700 if (ThreadInformationLength
!= Length
)
2702 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2705 /* Raise the IRQL to protect the IRP list */
2706 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
2708 /* Protect write with SEH */
2711 /* Check if the IRP list is empty or not */
2712 *(PULONG
)ThreadInformation
= !IsListEmpty(&Thread
->IrpList
);
2714 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2716 /* Get exception code */
2717 Status
= _SEH2_GetExceptionCode();
2721 /* Lower IRQL back */
2722 KeLowerIrql(OldIrql
);
2725 /* LDT and GDT information */
2726 case ThreadDescriptorTableEntry
:
2729 /* Call the worker routine */
2730 Status
= PspQueryDescriptorThread(Thread
,
2732 ThreadInformationLength
,
2735 /* Only implemented on x86 */
2736 Status
= STATUS_NOT_IMPLEMENTED
;
2740 case ThreadPriorityBoost
:
2742 /* Set the return length*/
2743 Length
= sizeof(ULONG
);
2745 if (ThreadInformationLength
!= Length
)
2747 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2753 *(PULONG
)ThreadInformation
= Thread
->Tcb
.DisableBoost
? 1 : 0;
2755 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2757 Status
= _SEH2_GetExceptionCode();
2762 case ThreadIsTerminated
:
2764 /* Set the return length*/
2765 Length
= sizeof(ThreadTerminated
);
2767 if (ThreadInformationLength
!= Length
)
2769 Status
= STATUS_INFO_LENGTH_MISMATCH
;
2773 ThreadTerminated
= PsIsThreadTerminating(Thread
);
2777 *(PULONG
)ThreadInformation
= ThreadTerminated
? 1 : 0;
2779 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2781 Status
= _SEH2_GetExceptionCode();
2790 /* Not yet implemented */
2791 DPRINT1("Not implemented: %lx\n", ThreadInformationClass
);
2792 Status
= STATUS_NOT_IMPLEMENTED
;
2795 /* Protect write with SEH */
2798 /* Check if caller wanted return length */
2799 if (ReturnLength
) *ReturnLength
= Length
;
2801 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
2803 /* Get exception code */
2804 Status
= _SEH2_GetExceptionCode();
2808 /* Dereference the thread, and return */
2809 ObDereferenceObject(Thread
);