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 ******************************************************************/
17 /* Include Information Class Tables */
18 #include "internal/ps_i.h"
21 ULONG PspTraceLevel
= 0;
23 /* PRIVATE FUNCTIONS *********************************************************/
27 PsReferenceProcessFilePointer(IN PEPROCESS Process
,
28 OUT PFILE_OBJECT
*FileObject
)
33 /* Lock the process */
34 ExAcquireRundownProtection(&Process
->RundownProtect
);
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();
69 PPROCESS_BASIC_INFORMATION ProcessBasicInfo
=
70 (PPROCESS_BASIC_INFORMATION
)ProcessInformation
;
71 PKERNEL_USER_TIMES ProcessTime
= (PKERNEL_USER_TIMES
)ProcessInformation
;
72 PPROCESS_PRIORITY_CLASS PsPriorityClass
= (PPROCESS_PRIORITY_CLASS
)ProcessInformation
;
74 PPROCESS_SESSION_INFORMATION SessionInfo
=
75 (PPROCESS_SESSION_INFORMATION
)ProcessInformation
;
76 PVM_COUNTERS VmCounters
= (PVM_COUNTERS
)ProcessInformation
;
77 PIO_COUNTERS IoCounters
= (PIO_COUNTERS
)ProcessInformation
;
78 PQUOTA_LIMITS QuotaLimits
= (PQUOTA_LIMITS
)ProcessInformation
;
79 PROCESS_DEVICEMAP_INFORMATION DeviceMap
;
80 PUNICODE_STRING ImageName
;
84 /* Check for user-mode caller */
85 if (PreviousMode
!= KernelMode
)
87 /* Prepare to probe parameters */
90 /* Probe the buffer */
91 ProbeForWrite(ProcessInformation
,
92 ProcessInformationLength
,
95 /* Probe the return length if required */
96 if (ReturnLength
) ProbeForWriteUlong(ReturnLength
);
98 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
100 /* Return the exception code */
101 _SEH2_YIELD(return _SEH2_GetExceptionCode());
106 if((ProcessInformationClass
== ProcessCookie
) &&
107 (ProcessHandle
!= NtCurrentProcess()))
110 * Retreiving the process cookie is only allowed for the calling process
111 * itself! XP only allowes NtCurrentProcess() as process handles even if
112 * a real handle actually represents the current process.
114 return STATUS_INVALID_PARAMETER
;
117 /* Check the information class */
118 switch (ProcessInformationClass
)
120 /* Basic process information */
121 case ProcessBasicInformation
:
123 /* Set return length */
124 Length
= sizeof(PROCESS_BASIC_INFORMATION
);
126 if (ProcessInformationLength
!= Length
)
128 Status
= STATUS_INFO_LENGTH_MISMATCH
;
132 /* Reference the process */
133 Status
= ObReferenceObjectByHandle(ProcessHandle
,
134 PROCESS_QUERY_INFORMATION
,
139 if (!NT_SUCCESS(Status
)) break;
141 /* Protect writes with SEH */
144 /* Write all the information from the EPROCESS/KPROCESS */
145 ProcessBasicInfo
->ExitStatus
= Process
->ExitStatus
;
146 ProcessBasicInfo
->PebBaseAddress
= Process
->Peb
;
147 ProcessBasicInfo
->AffinityMask
= Process
->Pcb
.Affinity
;
148 ProcessBasicInfo
->UniqueProcessId
= (ULONG_PTR
)Process
->
150 ProcessBasicInfo
->InheritedFromUniqueProcessId
=
151 (ULONG
)Process
->InheritedFromUniqueProcessId
;
152 ProcessBasicInfo
->BasePriority
= Process
->Pcb
.BasePriority
;
155 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
157 /* Get exception code */
158 Status
= _SEH2_GetExceptionCode();
162 /* Dereference the process */
163 ObDereferenceObject(Process
);
166 /* Process quota limits */
167 case ProcessQuotaLimits
:
169 Length
= sizeof(QUOTA_LIMITS
);
170 if (ProcessInformationLength
!= Length
)
172 Status
= STATUS_INFO_LENGTH_MISMATCH
;
176 /* Reference the process */
177 Status
= ObReferenceObjectByHandle(ProcessHandle
,
178 PROCESS_QUERY_INFORMATION
,
183 if (!NT_SUCCESS(Status
)) break;
185 /* Indicate success */
186 Status
= STATUS_SUCCESS
;
190 /* Set max/min working set sizes */
191 QuotaLimits
->MaximumWorkingSetSize
=
192 Process
->Vm
.MaximumWorkingSetSize
<< PAGE_SHIFT
;
193 QuotaLimits
->MinimumWorkingSetSize
=
194 Process
->Vm
.MinimumWorkingSetSize
<< PAGE_SHIFT
;
196 /* Set default time limits */
197 QuotaLimits
->TimeLimit
.LowPart
= MAXULONG
;
198 QuotaLimits
->TimeLimit
.HighPart
= MAXULONG
;
200 /* Is quota block a default one? */
201 if (Process
->QuotaBlock
== &PspDefaultQuotaBlock
)
203 /* Set default pools and pagefile limits */
204 QuotaLimits
->PagedPoolLimit
= (SIZE_T
)-1;
205 QuotaLimits
->NonPagedPoolLimit
= (SIZE_T
)-1;
206 QuotaLimits
->PagefileLimit
= (SIZE_T
)-1;
210 /* Get limits from non-default quota block */
211 QuotaLimits
->PagedPoolLimit
=
212 Process
->QuotaBlock
->QuotaEntry
[PagedPool
].Limit
;
213 QuotaLimits
->NonPagedPoolLimit
=
214 Process
->QuotaBlock
->QuotaEntry
[NonPagedPool
].Limit
;
215 QuotaLimits
->PagefileLimit
=
216 Process
->QuotaBlock
->QuotaEntry
[2].Limit
;
219 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
221 /* Get exception code */
222 Status
= _SEH2_GetExceptionCode();
226 /* Dereference the process */
227 ObDereferenceObject(Process
);
230 case ProcessIoCounters
:
232 Length
= sizeof(IO_COUNTERS
);
233 if (ProcessInformationLength
!= Length
)
235 Status
= STATUS_INFO_LENGTH_MISMATCH
;
239 /* Reference the process */
240 Status
= ObReferenceObjectByHandle(ProcessHandle
,
241 PROCESS_QUERY_INFORMATION
,
246 if (!NT_SUCCESS(Status
)) break;
250 IoCounters
->ReadOperationCount
= Process
->ReadOperationCount
.QuadPart
;
251 IoCounters
->ReadTransferCount
= Process
->ReadTransferCount
.QuadPart
;
252 IoCounters
->WriteOperationCount
= Process
->WriteOperationCount
.QuadPart
;
253 IoCounters
->WriteTransferCount
= Process
->WriteTransferCount
.QuadPart
;
254 IoCounters
->OtherOperationCount
= Process
->OtherOperationCount
.QuadPart
;
255 IoCounters
->OtherTransferCount
= Process
->OtherTransferCount
.QuadPart
;
257 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
259 /* Ignore exception */
263 /* Set status to success in any case */
264 Status
= STATUS_SUCCESS
;
266 /* Dereference the process */
267 ObDereferenceObject(Process
);
273 /* Set the return length */
274 Length
= sizeof(KERNEL_USER_TIMES
);
276 if (ProcessInformationLength
!= Length
)
278 Status
= STATUS_INFO_LENGTH_MISMATCH
;
282 /* Reference the process */
283 Status
= ObReferenceObjectByHandle(ProcessHandle
,
284 PROCESS_QUERY_INFORMATION
,
289 if (!NT_SUCCESS(Status
)) break;
291 /* Protect writes with SEH */
294 /* Copy time information from EPROCESS/KPROCESS */
295 ProcessTime
->CreateTime
= Process
->CreateTime
;
296 ProcessTime
->UserTime
.QuadPart
= Process
->Pcb
.UserTime
*
298 ProcessTime
->KernelTime
.QuadPart
= Process
->Pcb
.KernelTime
*
300 ProcessTime
->ExitTime
= Process
->ExitTime
;
302 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
304 /* Get exception code */
305 Status
= _SEH2_GetExceptionCode();
309 /* Dereference the process */
310 ObDereferenceObject(Process
);
313 /* Process Debug Port */
314 case ProcessDebugPort
:
316 /* Set return length */
317 Length
= sizeof(HANDLE
);
319 if (ProcessInformationLength
!= Length
)
321 Status
= STATUS_INFO_LENGTH_MISMATCH
;
325 /* Reference the process */
326 Status
= ObReferenceObjectByHandle(ProcessHandle
,
327 PROCESS_QUERY_INFORMATION
,
332 if (!NT_SUCCESS(Status
)) break;
334 /* Protect write with SEH */
337 /* Return whether or not we have a debug port */
338 *(PHANDLE
)ProcessInformation
= (Process
->DebugPort
?
341 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
343 /* Get exception code */
344 Status
= _SEH2_GetExceptionCode();
348 /* Dereference the process */
349 ObDereferenceObject(Process
);
352 /* LDT, WS and VDM Information: not implemented */
353 case ProcessLdtInformation
:
354 case ProcessWorkingSetWatch
:
355 case ProcessWx86Information
:
357 /* Reference the process */
358 Status
= ObReferenceObjectByHandle(ProcessHandle
,
359 PROCESS_QUERY_INFORMATION
,
364 if (!NT_SUCCESS(Status
)) break;
366 DPRINT1("Not implemented: %lx\n", ProcessInformationClass
);
368 /* Dereference the process */
369 ObDereferenceObject(Process
);
370 Status
= STATUS_NOT_IMPLEMENTED
;
373 case ProcessHandleCount
:
375 /* Set the return length*/
376 Length
= sizeof(ULONG
);
378 if (ProcessInformationLength
!= Length
)
380 Status
= STATUS_INFO_LENGTH_MISMATCH
;
384 /* Reference the process */
385 Status
= ObReferenceObjectByHandle(ProcessHandle
,
386 PROCESS_QUERY_INFORMATION
,
391 if (!NT_SUCCESS(Status
)) break;
393 /* Count the number of handles this process has */
394 HandleCount
= ObGetProcessHandleCount(Process
);
396 /* Protect write in SEH */
399 /* Return the count of handles */
400 *(PULONG
)ProcessInformation
= HandleCount
;
402 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
404 /* Get the exception code */
405 Status
= _SEH2_GetExceptionCode();
409 /* Dereference the process */
410 ObDereferenceObject(Process
);
413 /* Session ID for the process */
414 case ProcessSessionInformation
:
416 /* Set the return length*/
417 Length
= sizeof(PROCESS_SESSION_INFORMATION
);
419 if (ProcessInformationLength
!= Length
)
421 Status
= STATUS_INFO_LENGTH_MISMATCH
;
425 /* Reference the process */
426 Status
= ObReferenceObjectByHandle(ProcessHandle
,
427 PROCESS_QUERY_INFORMATION
,
432 if (!NT_SUCCESS(Status
)) break;
434 /* Enter SEH for write safety */
437 /* Write back the Session ID */
438 SessionInfo
->SessionId
= Process
->Session
;
440 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
442 /* Get the exception code */
443 Status
= _SEH2_GetExceptionCode();
447 /* Dereference the process */
448 ObDereferenceObject(Process
);
451 /* WOW64: Not implemented */
452 case ProcessWow64Information
:
454 /* Set the return length */
455 Length
= sizeof(ULONG_PTR
);
457 if (ProcessInformationLength
!= Length
)
459 Status
= STATUS_INFO_LENGTH_MISMATCH
;
463 /* Reference the process */
464 Status
= ObReferenceObjectByHandle(ProcessHandle
,
465 PROCESS_QUERY_INFORMATION
,
470 if (!NT_SUCCESS(Status
)) break;
472 /* Protect write in SEH */
476 DPRINT1("Not implemented: ProcessWow64Information\n");
477 Status
= STATUS_NOT_IMPLEMENTED
;
479 /* Wow64 not present */
480 *(PULONG_PTR
)ProcessInformation
= 0;
483 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
485 /* Get the exception code */
486 Status
= _SEH2_GetExceptionCode();
490 /* Dereference the process */
491 ObDereferenceObject(Process
);
494 /* Virtual Memory Statistics */
495 case ProcessVmCounters
:
497 /* Set the return length */
498 Length
= sizeof(VM_COUNTERS
);
500 if (ProcessInformationLength
!= Length
)
502 Status
= STATUS_INFO_LENGTH_MISMATCH
;
506 /* Reference the process */
507 Status
= ObReferenceObjectByHandle(ProcessHandle
,
508 PROCESS_QUERY_INFORMATION
,
513 if (!NT_SUCCESS(Status
)) break;
515 /* Enter SEH for write safety */
518 /* Return data from EPROCESS */
519 VmCounters
->PeakVirtualSize
= Process
->PeakVirtualSize
;
520 VmCounters
->VirtualSize
= Process
->VirtualSize
;
521 VmCounters
->PageFaultCount
= Process
->Vm
.PageFaultCount
;
522 VmCounters
->PeakWorkingSetSize
= Process
->Vm
.PeakWorkingSetSize
;
523 VmCounters
->WorkingSetSize
= Process
->Vm
.WorkingSetSize
;
524 VmCounters
->QuotaPeakPagedPoolUsage
= Process
->QuotaPeak
[0];
525 VmCounters
->QuotaPagedPoolUsage
= Process
->QuotaUsage
[0];
526 VmCounters
->QuotaPeakNonPagedPoolUsage
= Process
->QuotaPeak
[1];
527 VmCounters
->QuotaNonPagedPoolUsage
= Process
->QuotaUsage
[1];
528 VmCounters
->PagefileUsage
= Process
->QuotaUsage
[2];
529 VmCounters
->PeakPagefileUsage
= Process
->QuotaPeak
[2];
532 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
534 /* Get the exception code */
535 Status
= _SEH2_GetExceptionCode();
539 /* Dereference the process */
540 ObDereferenceObject(Process
);
543 /* Hard Error Processing Mode */
544 case ProcessDefaultHardErrorMode
:
546 /* Set the return length*/
547 Length
= sizeof(ULONG
);
549 if (ProcessInformationLength
!= Length
)
551 Status
= STATUS_INFO_LENGTH_MISMATCH
;
555 /* Reference the process */
556 Status
= ObReferenceObjectByHandle(ProcessHandle
,
557 PROCESS_QUERY_INFORMATION
,
562 if (!NT_SUCCESS(Status
)) break;
564 /* Enter SEH for writing back data */
567 /* Write the current processing mode */
568 *(PULONG
)ProcessInformation
= Process
->
569 DefaultHardErrorProcessing
;
571 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
573 /* Get the exception code */
574 Status
= _SEH2_GetExceptionCode();
578 /* Dereference the process */
579 ObDereferenceObject(Process
);
582 /* Priority Boosting status */
583 case ProcessPriorityBoost
:
585 /* Set the return length*/
586 Length
= sizeof(ULONG
);
588 if (ProcessInformationLength
!= Length
)
590 Status
= STATUS_INFO_LENGTH_MISMATCH
;
594 /* Reference the process */
595 Status
= ObReferenceObjectByHandle(ProcessHandle
,
596 PROCESS_QUERY_INFORMATION
,
601 if (!NT_SUCCESS(Status
)) break;
603 /* Enter SEH for writing back data */
606 /* Return boost status */
607 *(PULONG
)ProcessInformation
= Process
->Pcb
.DisableBoost
?
610 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
612 /* Get the exception code */
613 Status
= _SEH2_GetExceptionCode();
617 /* Dereference the process */
618 ObDereferenceObject(Process
);
622 case ProcessDeviceMap
:
624 /* Set the return length*/
625 Length
= sizeof(PROCESS_DEVICEMAP_INFORMATION
);
627 if (ProcessInformationLength
!= Length
)
629 Status
= STATUS_INFO_LENGTH_MISMATCH
;
633 /* Reference the process */
634 Status
= ObReferenceObjectByHandle(ProcessHandle
,
635 PROCESS_QUERY_INFORMATION
,
640 if (!NT_SUCCESS(Status
)) break;
642 /* Query the device map information */
643 ObQueryDeviceMapInformation(Process
, &DeviceMap
);
645 /* Enter SEH for writing back data */
648 *(PPROCESS_DEVICEMAP_INFORMATION
)ProcessInformation
= DeviceMap
;
650 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
652 /* Get the exception code */
653 Status
= _SEH2_GetExceptionCode();
657 /* Dereference the process */
658 ObDereferenceObject(Process
);
662 case ProcessPriorityClass
:
664 /* Set the return length*/
665 Length
= sizeof(PROCESS_PRIORITY_CLASS
);
667 if (ProcessInformationLength
!= Length
)
669 Status
= STATUS_INFO_LENGTH_MISMATCH
;
673 /* Reference the process */
674 Status
= ObReferenceObjectByHandle(ProcessHandle
,
675 PROCESS_QUERY_INFORMATION
,
680 if (!NT_SUCCESS(Status
)) break;
682 /* Enter SEH for writing back data */
685 /* Return current priority class */
686 PsPriorityClass
->PriorityClass
= Process
->PriorityClass
;
687 PsPriorityClass
->Foreground
= FALSE
;
689 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
691 /* Get the exception code */
692 Status
= _SEH2_GetExceptionCode();
696 /* Dereference the process */
697 ObDereferenceObject(Process
);
700 case ProcessImageFileName
:
702 /* Reference the process */
703 Status
= ObReferenceObjectByHandle(ProcessHandle
,
704 PROCESS_QUERY_INFORMATION
,
709 if (!NT_SUCCESS(Status
)) break;
711 /* Get the image path */
712 Status
= SeLocateProcessImageName(Process
, &ImageName
);
713 if (NT_SUCCESS(Status
))
715 /* Set return length */
716 Length
= ImageName
->MaximumLength
+
717 sizeof(OBJECT_NAME_INFORMATION
);
719 /* Make sure it's large enough */
720 if (Length
<= ProcessInformationLength
)
722 /* Enter SEH to protect write */
726 RtlCopyMemory(ProcessInformation
,
731 ((PUNICODE_STRING
)ProcessInformation
)->Buffer
=
732 (PWSTR
)((PUNICODE_STRING
)ProcessInformation
+ 1);
734 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
736 /* Get the exception code */
737 Status
= _SEH2_GetExceptionCode();
743 /* Buffer too small */
744 Status
= STATUS_INFO_LENGTH_MISMATCH
;
747 /* Free the image path */
748 ExFreePool(ImageName
);
750 /* Dereference the process */
751 ObDereferenceObject(Process
);
754 case ProcessBreakOnTermination
:
756 /* Set the return length*/
757 Length
= sizeof(ULONG
);
758 if (ProcessInformationLength
!= Length
)
760 Status
= STATUS_INFO_LENGTH_MISMATCH
;
764 /* Reference the process */
765 Status
= ObReferenceObjectByHandle(ProcessHandle
,
766 PROCESS_QUERY_INFORMATION
,
771 if (!NT_SUCCESS(Status
)) break;
773 /* Enter SEH for writing back data */
776 /* Return the BreakOnTermination state */
777 *(PULONG
)ProcessInformation
= Process
->BreakOnTermination
;
779 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
781 /* Get the exception code */
782 Status
= _SEH2_GetExceptionCode();
786 /* Dereference the process */
787 ObDereferenceObject(Process
);
790 /* Per-process security cookie */
793 /* Get the current process and cookie */
794 Process
= PsGetCurrentProcess();
795 Cookie
= Process
->Cookie
;
798 LARGE_INTEGER SystemTime
;
802 /* Generate a new cookie */
803 KeQuerySystemTime(&SystemTime
);
804 Prcb
= KeGetCurrentPrcb();
805 NewCookie
= Prcb
->KeSystemCalls
^ Prcb
->InterruptTime
^
806 SystemTime
.u
.LowPart
^ SystemTime
.u
.HighPart
;
808 /* Set the new cookie or return the current one */
809 Cookie
= InterlockedCompareExchange((LONG
*)&Process
->Cookie
,
812 if (!Cookie
) Cookie
= NewCookie
;
814 /* Set return length */
815 Length
= sizeof(ULONG
);
818 /* Indicate success */
819 Status
= STATUS_SUCCESS
;
821 /* Enter SEH to protect write */
824 /* Write back the cookie */
825 *(PULONG
)ProcessInformation
= Cookie
;
827 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
829 /* Get the exception code */
830 Status
= _SEH2_GetExceptionCode();
835 /* Not yet implemented, or unknown */
836 case ProcessBasePriority
:
837 case ProcessRaisePriority
:
838 case ProcessExceptionPort
:
839 case ProcessAccessToken
:
841 case ProcessIoPortHandlers
:
842 case ProcessUserModeIOPL
:
843 case ProcessEnableAlignmentFaultFixup
:
844 case ProcessAffinityMask
:
845 case ProcessForegroundInformation
:
847 DPRINT1("Unsupported or unimplemented: %lx\n", ProcessInformationClass
);
848 Status
= STATUS_INVALID_INFO_CLASS
;
851 /* Protect write with SEH */
854 /* Check if caller wanted return length */
855 if (ReturnLength
) *ReturnLength
= Length
;
857 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
859 /* Get exception code */
860 Status
= _SEH2_GetExceptionCode();
872 NtSetInformationProcess(IN HANDLE ProcessHandle
,
873 IN PROCESSINFOCLASS ProcessInformationClass
,
874 IN PVOID ProcessInformation
,
875 IN ULONG ProcessInformationLength
)
878 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
881 HANDLE PortHandle
= NULL
;
882 HANDLE TokenHandle
= NULL
;
883 PROCESS_SESSION_INFORMATION SessionInfo
= {0};
884 PROCESS_PRIORITY_CLASS PriorityClass
= {0};
889 /* Verify Information Class validity */
891 Status
= DefaultSetInfoBufferCheck(ProcessInformationClass
,
893 RTL_NUMBER_OF(PsProcessInfoClass
),
895 ProcessInformationLength
,
897 if (!NT_SUCCESS(Status
)) return Status
;
900 /* Check what class this is */
901 Access
= PROCESS_SET_INFORMATION
;
902 if (ProcessInformationClass
== ProcessSessionInformation
)
904 /* Setting the Session ID needs a special mask */
905 Access
|= PROCESS_SET_SESSIONID
;
907 else if (ProcessInformationClass
== ProcessExceptionPort
)
909 /* Setting the exception port needs a special mask */
910 Access
|= PROCESS_SUSPEND_RESUME
;
913 /* Reference the process */
914 Status
= ObReferenceObjectByHandle(ProcessHandle
,
920 if (!NT_SUCCESS(Status
)) return Status
;
922 /* Check what kind of information class this is */
923 switch (ProcessInformationClass
)
925 /* Error/Exception Port */
926 case ProcessExceptionPort
:
928 /* Check buffer length */
929 if (ProcessInformationLength
!= sizeof(HANDLE
))
931 Status
= STATUS_INFO_LENGTH_MISMATCH
;
935 /* Use SEH for capture */
938 /* Capture the handle */
939 PortHandle
= *(PHANDLE
)ProcessInformation
;
941 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
943 /* Get the exception code */
944 Status
= _SEH2_GetExceptionCode();
949 /* Get the LPC Port */
950 Status
= ObReferenceObjectByHandle(PortHandle
,
954 (PVOID
)&ExceptionPort
,
956 if (!NT_SUCCESS(Status
)) break;
958 /* Change the pointer */
959 if (InterlockedCompareExchangePointer(&Process
->ExceptionPort
,
963 /* We already had one, fail */
964 ObDereferenceObject(ExceptionPort
);
965 Status
= STATUS_PORT_ALREADY_SET
;
970 case ProcessAccessToken
:
972 /* Check buffer length */
973 if (ProcessInformationLength
!= sizeof(PROCESS_ACCESS_TOKEN
))
975 Status
= STATUS_INFO_LENGTH_MISMATCH
;
979 /* Use SEH for capture */
982 /* Save the token handle */
983 TokenHandle
= ((PPROCESS_ACCESS_TOKEN
)ProcessInformation
)->
986 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
988 /* Get the exception code */
989 Status
= _SEH2_GetExceptionCode();
994 /* Assign the actual token */
995 Status
= PspSetPrimaryToken(Process
, TokenHandle
, NULL
);
998 /* Hard error processing */
999 case ProcessDefaultHardErrorMode
:
1001 /* Check buffer length */
1002 if (ProcessInformationLength
!= sizeof(ULONG
))
1004 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1008 /* Enter SEH for direct buffer read */
1011 /* Update the current mode abd return the previous one */
1012 InterlockedExchange((LONG
*)&Process
->DefaultHardErrorProcessing
,
1013 *(PLONG
)ProcessInformation
);
1015 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1017 /* Get exception code */
1018 Status
= _SEH2_GetExceptionCode();
1024 case ProcessSessionInformation
:
1026 /* Check buffer length */
1027 if (ProcessInformationLength
!= sizeof(PROCESS_SESSION_INFORMATION
))
1029 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1033 /* Enter SEH for capture */
1036 /* Capture the caller's buffer */
1037 SessionInfo
= *(PPROCESS_SESSION_INFORMATION
)ProcessInformation
;
1039 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1041 /* Get the exception code */
1042 Status
= _SEH2_GetExceptionCode();
1047 /* Setting the session id requires the SeTcbPrivilege */
1048 if (!SeSinglePrivilegeCheck(SeTcbPrivilege
, PreviousMode
))
1050 /* Can't set the session ID, bail out. */
1051 Status
= STATUS_PRIVILEGE_NOT_HELD
;
1055 /* FIXME - update the session id for the process token */
1056 //Status = PsLockProcess(Process, FALSE);
1057 if (!NT_SUCCESS(Status
)) break;
1059 /* Write the session ID in the EPROCESS */
1060 Process
->Session
= SessionInfo
.SessionId
;
1062 /* Check if the process also has a PEB */
1066 * Attach to the process to make sure we're in the right
1067 * context to access the PEB structure
1069 KeAttachProcess(&Process
->Pcb
);
1071 /* Enter SEH for write to user-mode PEB */
1074 /* Write the session ID */
1075 Process
->Peb
->SessionId
= SessionInfo
.SessionId
;
1077 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1079 /* Get exception code */
1080 Status
= _SEH2_GetExceptionCode();
1084 /* Detach from the process */
1088 /* Unlock the process */
1089 //PsUnlockProcess(Process);
1092 case ProcessPriorityClass
:
1094 /* Check buffer length */
1095 if (ProcessInformationLength
!= sizeof(PROCESS_PRIORITY_CLASS
))
1097 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1101 /* Enter SEH for capture */
1104 /* Capture the caller's buffer */
1105 PriorityClass
= *(PPROCESS_PRIORITY_CLASS
)ProcessInformation
;
1107 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1109 /* Return the exception code */
1110 Status
= _SEH2_GetExceptionCode();
1115 /* Check for invalid PriorityClass value */
1116 if (PriorityClass
.PriorityClass
> PROCESS_PRIORITY_CLASS_ABOVE_NORMAL
)
1118 Status
= STATUS_INVALID_PARAMETER
;
1122 /* TODO: Check privileges */
1124 /* Check if we have a job */
1127 DPRINT1("Jobs not yet supported\n");
1130 /* Set process priority class */
1131 Process
->PriorityClass
= PriorityClass
.PriorityClass
;
1133 /* Set process priority mode (foreground or background) */
1134 PsSetProcessPriorityByClass(Process
,
1135 !PriorityClass
.Foreground
? PsProcessPriorityBackground
:
1136 PsProcessPriorityForeground
);
1138 Status
= STATUS_SUCCESS
;
1141 case ProcessQuotaLimits
:
1143 /* Check buffer length */
1144 if (ProcessInformationLength
!= sizeof(QUOTA_LIMITS
))
1146 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1150 DPRINT1("Not implemented: ProcessQuotaLimits\n");
1151 Status
= STATUS_NOT_IMPLEMENTED
;
1154 case ProcessBasePriority
:
1156 /* Check buffer length */
1157 if (ProcessInformationLength
!= sizeof(KPRIORITY
))
1159 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1163 DPRINT1("Not implemented: ProcessBasePriority\n");
1164 Status
= STATUS_NOT_IMPLEMENTED
;
1167 case ProcessRaisePriority
:
1169 /* Check buffer length */
1170 if (ProcessInformationLength
!= sizeof(ULONG
))
1172 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1176 DPRINT1("Not implemented: ProcessRaisePriority\n");
1177 Status
= STATUS_NOT_IMPLEMENTED
;
1180 case ProcessWx86Information
:
1182 /* Check buffer length */
1183 if (ProcessInformationLength
!= sizeof(HANDLE
))
1185 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1189 DPRINT1("Not implemented: ProcessWx86Information\n");
1190 Status
= STATUS_NOT_IMPLEMENTED
;
1193 case ProcessDebugPort
:
1195 /* Check buffer length */
1196 if (ProcessInformationLength
!= sizeof(HANDLE
))
1198 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1202 DPRINT1("Not implemented: ProcessDebugPort\n");
1203 Status
= STATUS_NOT_IMPLEMENTED
;
1206 case ProcessBreakOnTermination
:
1208 /* Check buffer length */
1209 if (ProcessInformationLength
!= sizeof(ULONG
))
1211 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1215 /* Enter SEH for direct buffer read */
1218 Break
= *(PULONG
)ProcessInformation
;
1220 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1222 /* Get exception code */
1224 Status
= _SEH2_GetExceptionCode();
1229 /* Setting 'break on termination' requires the SeDebugPrivilege */
1230 if (!SeSinglePrivilegeCheck(SeDebugPrivilege
, PreviousMode
))
1232 Status
= STATUS_PRIVILEGE_NOT_HELD
;
1236 /* Set or clear the flag */
1239 PspSetProcessFlag(Process
, PSF_BREAK_ON_TERMINATION_BIT
);
1243 PspClearProcessFlag(Process
, PSF_BREAK_ON_TERMINATION_BIT
);
1248 /* We currently don't implement any of these */
1249 case ProcessLdtInformation
:
1250 case ProcessLdtSize
:
1251 case ProcessIoPortHandlers
:
1252 case ProcessWorkingSetWatch
:
1253 case ProcessUserModeIOPL
:
1254 case ProcessEnableAlignmentFaultFixup
:
1255 case ProcessAffinityMask
:
1256 DPRINT1("Not implemented: %lx\n", ProcessInformationClass
);
1257 Status
= STATUS_NOT_IMPLEMENTED
;
1260 /* Supposedly these are invalid...!? verify! */
1261 case ProcessBasicInformation
:
1262 case ProcessIoCounters
:
1264 case ProcessPooledUsageAndLimits
:
1265 case ProcessHandleCount
:
1266 case ProcessWow64Information
:
1268 DPRINT1("Unsupported or unimplemented: %lx\n", ProcessInformationClass
);
1269 Status
= STATUS_INVALID_INFO_CLASS
;
1272 /* Dereference and return status */
1273 ObDereferenceObject(Process
);
1282 NtSetInformationThread(IN HANDLE ThreadHandle
,
1283 IN THREADINFOCLASS ThreadInformationClass
,
1284 IN PVOID ThreadInformation
,
1285 IN ULONG ThreadInformationLength
)
1289 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1291 HANDLE TokenHandle
= NULL
;
1292 KPRIORITY Priority
= 0;
1293 KAFFINITY Affinity
= 0, CombinedAffinity
;
1294 PVOID Address
= NULL
;
1296 ULONG DisableBoost
= 0;
1297 ULONG IdealProcessor
= 0;
1300 PVOID
*ExpansionSlots
;
1301 PETHREAD ProcThread
;
1304 /* Verify Information Class validity */
1306 Status
= DefaultSetInfoBufferCheck(ThreadInformationClass
,
1308 RTL_NUMBER_OF(PsThreadInfoClass
),
1310 ThreadInformationLength
,
1312 if (!NT_SUCCESS(Status
)) return Status
;
1315 /* Check what class this is */
1316 Access
= THREAD_SET_INFORMATION
;
1317 if (ThreadInformationClass
== ThreadImpersonationToken
)
1319 /* Setting the impersonation token needs a special mask */
1320 Access
= THREAD_SET_THREAD_TOKEN
;
1323 /* Reference the thread */
1324 Status
= ObReferenceObjectByHandle(ThreadHandle
,
1330 if (!NT_SUCCESS(Status
)) return Status
;
1332 /* Check what kind of information class this is */
1333 switch (ThreadInformationClass
)
1335 /* Thread priority */
1336 case ThreadPriority
:
1338 /* Check buffer length */
1339 if (ThreadInformationLength
!= sizeof(KPRIORITY
))
1341 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1345 /* Use SEH for capture */
1348 /* Get the priority */
1349 Priority
= *(PLONG
)ThreadInformation
;
1351 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1353 /* Get the exception code */
1354 Status
= _SEH2_GetExceptionCode();
1360 if ((Priority
> HIGH_PRIORITY
) ||
1361 (Priority
<= LOW_PRIORITY
))
1364 Status
= STATUS_INVALID_PARAMETER
;
1368 /* Set the priority */
1369 KeSetPriorityThread(&Thread
->Tcb
, Priority
);
1372 case ThreadBasePriority
:
1374 /* Check buffer length */
1375 if (ThreadInformationLength
!= sizeof(LONG
))
1377 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1381 /* Use SEH for capture */
1384 /* Get the priority */
1385 Priority
= *(PLONG
)ThreadInformation
;
1387 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1389 /* Get the exception code */
1390 Status
= _SEH2_GetExceptionCode();
1396 if ((Priority
> THREAD_BASE_PRIORITY_MAX
) ||
1397 (Priority
< THREAD_BASE_PRIORITY_MIN
))
1399 /* These ones are OK */
1400 if ((Priority
!= THREAD_BASE_PRIORITY_LOWRT
+ 1) &&
1401 (Priority
!= THREAD_BASE_PRIORITY_IDLE
- 1))
1403 /* Check if the process is real time */
1404 if (PsGetCurrentProcess()->PriorityClass
!=
1405 PROCESS_PRIORITY_CLASS_REALTIME
)
1407 /* It isn't, fail */
1408 Status
= STATUS_INVALID_PARAMETER
;
1414 /* Set the base priority */
1415 KeSetBasePriorityThread(&Thread
->Tcb
, Priority
);
1418 case ThreadAffinityMask
:
1420 /* Check buffer length */
1421 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
1423 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1427 /* Use SEH for capture */
1430 /* Get the priority */
1431 Affinity
= *(PULONG_PTR
)ThreadInformation
;
1433 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1435 /* Get the exception code */
1436 Status
= _SEH2_GetExceptionCode();
1444 Status
= STATUS_INVALID_PARAMETER
;
1448 /* Get the process */
1449 Process
= Thread
->ThreadsProcess
;
1451 /* Try to acquire rundown */
1452 if (ExAcquireRundownProtection(&Process
->RundownProtect
))
1455 KeEnterCriticalRegion();
1456 ExAcquirePushLockShared(&Process
->ProcessLock
);
1459 CombinedAffinity
= Affinity
& Process
->Pcb
.Affinity
;
1460 if (CombinedAffinity
!= Affinity
)
1463 Status
= STATUS_INVALID_PARAMETER
;
1467 /* Set the affinity */
1468 KeSetAffinityThread(&Thread
->Tcb
, CombinedAffinity
);
1471 /* Release the lock and rundown */
1472 ExReleasePushLockShared(&Process
->ProcessLock
);
1473 KeLeaveCriticalRegion();
1474 ExReleaseRundownProtection(&Process
->RundownProtect
);
1479 Status
= STATUS_PROCESS_IS_TERMINATING
;
1485 case ThreadImpersonationToken
:
1487 /* Check buffer length */
1488 if (ThreadInformationLength
!= sizeof(HANDLE
))
1490 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1494 /* Use SEH for capture */
1497 /* Save the token handle */
1498 TokenHandle
= *(PHANDLE
)ThreadInformation
;
1500 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1502 /* Get the exception code */
1503 Status
= _SEH2_GetExceptionCode();
1508 /* Assign the actual token */
1509 Status
= PsAssignImpersonationToken(Thread
, TokenHandle
);
1512 case ThreadQuerySetWin32StartAddress
:
1514 /* Check buffer length */
1515 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
1517 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1521 /* Use SEH for capture */
1524 /* Get the priority */
1525 Address
= *(PVOID
*)ThreadInformation
;
1527 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1529 /* Get the exception code */
1530 Status
= _SEH2_GetExceptionCode();
1535 /* Set the address */
1536 Thread
->Win32StartAddress
= Address
;
1539 case ThreadIdealProcessor
:
1541 /* Check buffer length */
1542 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
1544 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1548 /* Use SEH for capture */
1551 /* Get the priority */
1552 IdealProcessor
= *(PULONG_PTR
)ThreadInformation
;
1554 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1556 /* Get the exception code */
1557 Status
= _SEH2_GetExceptionCode();
1563 if (IdealProcessor
> MAXIMUM_PROCESSORS
)
1566 Status
= STATUS_INVALID_PARAMETER
;
1571 Status
= KeSetIdealProcessorThread(&Thread
->Tcb
,
1572 (CCHAR
)IdealProcessor
);
1574 /* Get the TEB and protect the thread */
1575 Teb
= Thread
->Tcb
.Teb
;
1576 if ((Teb
) && (ExAcquireRundownProtection(&Thread
->RundownProtect
)))
1578 /* Save the ideal processor */
1579 Teb
->IdealProcessor
= Thread
->Tcb
.IdealProcessor
;
1581 /* Release rundown protection */
1582 ExReleaseRundownProtection(&Thread
->RundownProtect
);
1587 case ThreadPriorityBoost
:
1589 /* Check buffer length */
1590 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
1592 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1596 /* Use SEH for capture */
1599 /* Get the priority */
1600 DisableBoost
= *(PULONG_PTR
)ThreadInformation
;
1602 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1604 /* Get the exception code */
1605 Status
= _SEH2_GetExceptionCode();
1610 /* Call the kernel */
1611 KeSetDisableBoostThread(&Thread
->Tcb
, (BOOLEAN
)DisableBoost
);
1614 case ThreadZeroTlsCell
:
1616 /* Check buffer length */
1617 if (ThreadInformationLength
!= sizeof(ULONG_PTR
))
1619 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1623 /* Use SEH for capture */
1626 /* Get the priority */
1627 TlsIndex
= *(PULONG_PTR
)ThreadInformation
;
1629 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1631 /* Get the exception code */
1632 Status
= _SEH2_GetExceptionCode();
1637 /* This is only valid for the current thread */
1638 if (Thread
!= PsGetCurrentThread())
1641 Status
= STATUS_INVALID_PARAMETER
;
1645 /* Get the process */
1646 Process
= Thread
->ThreadsProcess
;
1648 /* Loop the threads */
1649 ProcThread
= PsGetNextProcessThread(Process
, NULL
);
1652 /* Acquire rundown */
1653 if (ExAcquireRundownProtection(&ProcThread
->RundownProtect
))
1656 Teb
= ProcThread
->Tcb
.Teb
;
1659 /* Check if we're in the expansion range */
1660 if (TlsIndex
> TLS_MINIMUM_AVAILABLE
- 1)
1662 if (TlsIndex
< (TLS_MINIMUM_AVAILABLE
+
1663 TLS_EXPANSION_SLOTS
) - 1)
1665 /* Check if we have expansion slots */
1666 ExpansionSlots
= Teb
->TlsExpansionSlots
;
1669 /* Clear the index */
1670 ExpansionSlots
[TlsIndex
- TLS_MINIMUM_AVAILABLE
] = 0;
1676 /* Clear the index */
1677 Teb
->TlsSlots
[TlsIndex
] = NULL
;
1681 /* Release rundown */
1682 ExReleaseRundownProtection(&ProcThread
->RundownProtect
);
1685 /* Go to the next thread */
1686 ProcThread
= PsGetNextProcessThread(Process
, ProcThread
);
1693 /* We don't implement it yet */
1694 DPRINT1("Not implemented: %lx\n", ThreadInformationClass
);
1695 Status
= STATUS_NOT_IMPLEMENTED
;
1698 /* Dereference and return status */
1699 ObDereferenceObject(Thread
);
1708 NtQueryInformationThread(IN HANDLE ThreadHandle
,
1709 IN THREADINFOCLASS ThreadInformationClass
,
1710 OUT PVOID ThreadInformation
,
1711 IN ULONG ThreadInformationLength
,
1712 OUT PULONG ReturnLength OPTIONAL
)
1715 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1719 PTHREAD_BASIC_INFORMATION ThreadBasicInfo
=
1720 (PTHREAD_BASIC_INFORMATION
)ThreadInformation
;
1721 PKERNEL_USER_TIMES ThreadTime
= (PKERNEL_USER_TIMES
)ThreadInformation
;
1725 /* Check if we were called from user mode */
1726 if (PreviousMode
!= KernelMode
)
1731 /* Probe the buffer */
1732 ProbeForWrite(ThreadInformation
,
1733 ThreadInformationLength
,
1736 /* Probe the return length if required */
1737 if (ReturnLength
) ProbeForWriteUlong(ReturnLength
);
1739 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1741 /* Return the exception code */
1742 _SEH2_YIELD(return _SEH2_GetExceptionCode());
1747 /* Check what class this is */
1748 Access
= THREAD_QUERY_INFORMATION
;
1750 /* Reference the process */
1751 Status
= ObReferenceObjectByHandle(ThreadHandle
,
1757 if (!NT_SUCCESS(Status
)) return Status
;
1759 /* Check what kind of information class this is */
1760 switch (ThreadInformationClass
)
1762 /* Basic thread information */
1763 case ThreadBasicInformation
:
1765 /* Set return length */
1766 Length
= sizeof(THREAD_BASIC_INFORMATION
);
1768 if (ThreadInformationLength
!= Length
)
1770 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1773 /* Protect writes with SEH */
1776 /* Write all the information from the ETHREAD/KTHREAD */
1777 ThreadBasicInfo
->ExitStatus
= Thread
->ExitStatus
;
1778 ThreadBasicInfo
->TebBaseAddress
= (PVOID
)Thread
->Tcb
.Teb
;
1779 ThreadBasicInfo
->ClientId
= Thread
->Cid
;
1780 ThreadBasicInfo
->AffinityMask
= Thread
->Tcb
.Affinity
;
1781 ThreadBasicInfo
->Priority
= Thread
->Tcb
.Priority
;
1782 ThreadBasicInfo
->BasePriority
= KeQueryBasePriorityThread(&Thread
->Tcb
);
1784 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1786 /* Get exception code */
1787 Status
= _SEH2_GetExceptionCode();
1792 /* Thread time information */
1795 /* Set the return length */
1796 Length
= sizeof(KERNEL_USER_TIMES
);
1798 if (ThreadInformationLength
!= Length
)
1800 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1803 /* Protect writes with SEH */
1806 /* Copy time information from ETHREAD/KTHREAD */
1807 ThreadTime
->KernelTime
.QuadPart
= Thread
->Tcb
.KernelTime
*
1809 ThreadTime
->UserTime
.QuadPart
= Thread
->Tcb
.UserTime
*
1811 ThreadTime
->CreateTime
= Thread
->CreateTime
;
1812 ThreadTime
->ExitTime
= Thread
->ExitTime
;
1814 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1816 /* Get exception code */
1817 Status
= _SEH2_GetExceptionCode();
1822 case ThreadQuerySetWin32StartAddress
:
1824 /* Set the return length*/
1825 Length
= sizeof(PVOID
);
1827 if (ThreadInformationLength
!= Length
)
1829 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1832 /* Protect write with SEH */
1835 /* Return the Win32 Start Address */
1836 *(PVOID
*)ThreadInformation
= Thread
->Win32StartAddress
;
1838 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1840 /* Get exception code */
1841 Status
= _SEH2_GetExceptionCode();
1846 case ThreadPerformanceCount
:
1848 /* Set the return length*/
1849 Length
= sizeof(LARGE_INTEGER
);
1851 if (ThreadInformationLength
!= Length
)
1853 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1856 /* Protect write with SEH */
1860 (*(PLARGE_INTEGER
)ThreadInformation
).QuadPart
= 0;
1862 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1864 /* Get exception code */
1865 Status
= _SEH2_GetExceptionCode();
1870 case ThreadAmILastThread
:
1872 /* Set the return length*/
1873 Length
= sizeof(ULONG
);
1875 if (ThreadInformationLength
!= Length
)
1877 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1880 /* Protect write with SEH */
1883 /* Return whether or not we are the last thread */
1884 *(PULONG
)ThreadInformation
= ((Thread
->ThreadsProcess
->
1885 ThreadListHead
.Flink
->Flink
==
1886 &Thread
->ThreadsProcess
->
1890 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1892 /* Get exception code */
1893 Status
= _SEH2_GetExceptionCode();
1898 case ThreadIsIoPending
:
1900 /* Set the return length*/
1901 Length
= sizeof(ULONG
);
1903 if (ThreadInformationLength
!= Length
)
1905 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1908 /* Raise the IRQL to protect the IRP list */
1909 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
1911 /* Protect write with SEH */
1914 /* Check if the IRP list is empty or not */
1915 *(PULONG
)ThreadInformation
= !IsListEmpty(&Thread
->IrpList
);
1917 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1919 /* Get exception code */
1920 Status
= _SEH2_GetExceptionCode();
1924 /* Lower IRQL back */
1925 KeLowerIrql(OldIrql
);
1928 /* LDT and GDT information */
1929 case ThreadDescriptorTableEntry
:
1932 /* Call the worker routine */
1933 Status
= PspQueryDescriptorThread(Thread
,
1935 ThreadInformationLength
,
1938 /* Only implemented on x86 */
1939 Status
= STATUS_NOT_IMPLEMENTED
;
1943 case ThreadPriorityBoost
:
1945 /* Set the return length*/
1946 Length
= sizeof(ULONG
);
1948 if (ThreadInformationLength
!= Length
)
1950 Status
= STATUS_INFO_LENGTH_MISMATCH
;
1956 *(PULONG
)ThreadInformation
= Thread
->Tcb
.DisableBoost
? 1 : 0;
1958 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1960 Status
= _SEH2_GetExceptionCode();
1968 /* Not yet implemented */
1969 DPRINT1("Not implemented: %lx\n", ThreadInformationClass
);
1970 Status
= STATUS_NOT_IMPLEMENTED
;
1973 /* Protect write with SEH */
1976 /* Check if caller wanted return length */
1977 if (ReturnLength
) *ReturnLength
= Length
;
1979 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1981 /* Get exception code */
1982 Status
= _SEH2_GetExceptionCode();
1986 /* Dereference the thread, and return */
1987 ObDereferenceObject(Thread
);