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)
10 /* INCLUDES ******************************************************************/
16 /* Include Information Class Tables */
17 #include "internal/ps_i.h"
20 ULONG PspTraceLevel
= 0;
22 /* PRIVATE FUNCTIONS *********************************************************/
26 PsReferenceProcessFilePointer(IN PEPROCESS Process
,
27 OUT PFILE_OBJECT
*FileObject
)
32 /* Lock the process */
33 ExAcquireRundownProtection(&Process
->RundownProtect
);
36 Section
= Process
->SectionObject
;
39 /* Get the file object and reference it */
40 *FileObject
= MmGetFileObjectForSection((PVOID
)Section
);
41 ObReferenceObject(*FileObject
);
44 /* Release the protection */
45 ExReleaseRundownProtection(&Process
->RundownProtect
);
48 return Section
? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
;
51 /* PUBLIC FUNCTIONS **********************************************************/
58 NtQueryInformationProcess(IN HANDLE ProcessHandle
,
59 IN PROCESSINFOCLASS ProcessInformationClass
,
60 OUT PVOID ProcessInformation
,
61 IN ULONG ProcessInformationLength
,
62 OUT PULONG ReturnLength OPTIONAL
)
65 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
66 NTSTATUS Status
= STATUS_SUCCESS
;
68 PPROCESS_BASIC_INFORMATION ProcessBasicInfo
=
69 (PPROCESS_BASIC_INFORMATION
)ProcessInformation
;
70 PKERNEL_USER_TIMES ProcessTime
= (PKERNEL_USER_TIMES
)ProcessInformation
;
72 PPROCESS_SESSION_INFORMATION SessionInfo
=
73 (PPROCESS_SESSION_INFORMATION
)ProcessInformation
;
74 PVM_COUNTERS VmCounters
= (PVM_COUNTERS
)ProcessInformation
;
75 PROCESS_DEVICEMAP_INFORMATION DeviceMap
;
76 PUNICODE_STRING ImageName
;
80 /* Check validity of Information Class */
82 Status
= DefaultQueryInfoBufferCheck(ProcessInformationClass
,
84 RTL_NUMBER_OF(PsProcessInfoClass
),
86 ProcessInformationLength
,
89 if (!NT_SUCCESS(Status
)) return Status
;
92 /* Check if this isn't the cookie class */
93 if(ProcessInformationClass
!= ProcessCookie
)
95 /* Reference the process */
96 Status
= ObReferenceObjectByHandle(ProcessHandle
,
97 PROCESS_QUERY_INFORMATION
,
102 if (!NT_SUCCESS(Status
)) return Status
;
104 else if(ProcessHandle
!= NtCurrentProcess())
107 * Retreiving the process cookie is only allowed for the calling process
108 * itself! XP only allowes NtCurrentProcess() as process handles even if
109 * a real handle actually represents the current process.
111 return STATUS_INVALID_PARAMETER
;
114 /* Check the information class */
115 switch (ProcessInformationClass
)
117 /* Basic process information */
118 case ProcessBasicInformation
:
120 /* Set return length */
121 Length
= sizeof(PROCESS_BASIC_INFORMATION
);
123 if ( ProcessInformationLength
!= Length
)
125 Status
= STATUS_INFO_LENGTH_MISMATCH
;
128 /* Protect writes with SEH */
131 /* Write all the information from the EPROCESS/KPROCESS */
132 ProcessBasicInfo
->ExitStatus
= Process
->ExitStatus
;
133 ProcessBasicInfo
->PebBaseAddress
= Process
->Peb
;
134 ProcessBasicInfo
->AffinityMask
= Process
->Pcb
.Affinity
;
135 ProcessBasicInfo
->UniqueProcessId
= (ULONG_PTR
)Process
->
137 ProcessBasicInfo
->InheritedFromUniqueProcessId
=
138 (ULONG
)Process
->InheritedFromUniqueProcessId
;
139 ProcessBasicInfo
->BasePriority
= Process
->Pcb
.BasePriority
;
144 /* Get exception code */
145 Status
= _SEH_GetExceptionCode();
150 /* Quote limits and I/O Counters: not implemented */
151 case ProcessQuotaLimits
:
152 case ProcessIoCounters
:
154 Length
= sizeof(IO_COUNTERS
);
155 if ( ProcessInformationLength
!= Length
)
157 Status
= STATUS_INFO_LENGTH_MISMATCH
;
161 Status
= STATUS_NOT_IMPLEMENTED
;
167 /* Set the return length */
168 Length
= sizeof(KERNEL_USER_TIMES
);
170 if ( ProcessInformationLength
!= Length
)
172 Status
= STATUS_INFO_LENGTH_MISMATCH
;
176 /* Protect writes with SEH */
179 /* Copy time information from EPROCESS/KPROCESS */
180 ProcessTime
->CreateTime
= Process
->CreateTime
;
181 ProcessTime
->UserTime
.QuadPart
= Process
->Pcb
.UserTime
*
183 ProcessTime
->KernelTime
.QuadPart
= Process
->Pcb
.KernelTime
*
185 ProcessTime
->ExitTime
= Process
->ExitTime
;
189 /* Get exception code */
190 Status
= _SEH_GetExceptionCode();
195 /* Process Debug Port */
196 case ProcessDebugPort
:
198 /* Protect write with SEH */
201 /* Return whether or not we have a debug port */
202 *(PHANDLE
)ProcessInformation
= (Process
->DebugPort
?
205 /* Set the return length*/
206 Length
= sizeof(HANDLE
);
210 /* Get exception code */
211 Status
= _SEH_GetExceptionCode();
216 /* LDT, WS and VDM Information: not implemented */
217 case ProcessLdtInformation
:
218 case ProcessWorkingSetWatch
:
219 case ProcessWx86Information
:
220 Status
= STATUS_NOT_IMPLEMENTED
;
223 case ProcessHandleCount
:
225 /* Set the return length*/
226 Length
= sizeof(ULONG
);
228 if ( ProcessInformationLength
!= Length
)
230 Status
= STATUS_INFO_LENGTH_MISMATCH
;
234 /* Count the number of handles this process has */
235 HandleCount
= ObpGetHandleCountByHandleTable(Process
->ObjectTable
);
237 /* Protect write in SEH */
240 /* Return the count of handles */
241 *(PULONG
)ProcessInformation
= HandleCount
;
245 /* Get the exception code */
246 Status
= _SEH_GetExceptionCode();
251 /* Session ID for the process */
252 case ProcessSessionInformation
:
254 /* Enter SEH for write safety */
257 /* Write back the Session ID */
258 SessionInfo
->SessionId
= Process
->Session
;
260 /* Set the return length */
261 Length
= sizeof(PROCESS_SESSION_INFORMATION
);
265 /* Get the exception code */
266 Status
= _SEH_GetExceptionCode();
271 /* WOW64: Not implemented */
272 case ProcessWow64Information
:
273 Status
= STATUS_NOT_IMPLEMENTED
;
276 /* Virtual Memory Statistics */
277 case ProcessVmCounters
:
279 /* Set the return length */
280 Length
= sizeof(VM_COUNTERS
);
282 if ( ProcessInformationLength
!= Length
)
284 Status
= STATUS_INFO_LENGTH_MISMATCH
;
288 /* Enter SEH for write safety */
291 /* Return data from EPROCESS */
292 VmCounters
->PeakVirtualSize
= Process
->PeakVirtualSize
;
293 VmCounters
->VirtualSize
= Process
->VirtualSize
;
294 VmCounters
->PageFaultCount
= Process
->Vm
.PageFaultCount
;
295 VmCounters
->PeakWorkingSetSize
= Process
->Vm
.PeakWorkingSetSize
;
296 VmCounters
->WorkingSetSize
= Process
->Vm
.WorkingSetSize
;
297 VmCounters
->QuotaPeakPagedPoolUsage
= Process
->QuotaPeak
[0];
298 VmCounters
->QuotaPagedPoolUsage
= Process
->QuotaUsage
[0];
299 VmCounters
->QuotaPeakNonPagedPoolUsage
= Process
->QuotaPeak
[1];
300 VmCounters
->QuotaNonPagedPoolUsage
= Process
->QuotaUsage
[1];
301 VmCounters
->PagefileUsage
= Process
->QuotaUsage
[2];
302 VmCounters
->PeakPagefileUsage
= Process
->QuotaPeak
[2];
307 /* Get the exception code */
308 Status
= _SEH_GetExceptionCode();
313 /* Hard Error Processing Mode */
314 case ProcessDefaultHardErrorMode
:
316 /* Enter SEH for writing back data */
319 /* Write the current processing mode */
320 *(PULONG
)ProcessInformation
= Process
->
321 DefaultHardErrorProcessing
;
323 /* Set the return length */
324 Length
= sizeof(ULONG
);
328 /* Get the exception code */
329 Status
= _SEH_GetExceptionCode();
334 /* Priority Boosting status */
335 case ProcessPriorityBoost
:
337 /* Enter SEH for writing back data */
340 /* Return boost status */
341 *(PULONG
)ProcessInformation
= Process
->Pcb
.DisableBoost
?
344 /* Set the return length */
345 Length
= sizeof(ULONG
);
349 /* Get the exception code */
350 Status
= _SEH_GetExceptionCode();
356 case ProcessDeviceMap
:
358 /* Query the device map information */
359 ObQueryDeviceMapInformation(Process
, &DeviceMap
);
361 /* Enter SEH for writing back data */
364 *(PPROCESS_DEVICEMAP_INFORMATION
)ProcessInformation
= DeviceMap
;
366 /* Set the return length */
367 Length
= sizeof(PROCESS_DEVICEMAP_INFORMATION
);
371 /* Get the exception code */
372 Status
= _SEH_GetExceptionCode();
378 case ProcessPriorityClass
:
380 /* Enter SEH for writing back data */
383 /* Return current priority class */
384 *(PUSHORT
)ProcessInformation
= Process
->PriorityClass
;
386 /* Set the return length */
387 Length
= sizeof(USHORT
);
391 /* Get the exception code */
392 Status
= _SEH_GetExceptionCode();
397 case ProcessImageFileName
:
399 /* Get the image path */
400 Status
= SeLocateProcessImageName(Process
, &ImageName
);
401 if (NT_SUCCESS(Status
))
403 /* Set return length */
404 Length
= ImageName
->MaximumLength
+
405 sizeof(OBJECT_NAME_INFORMATION
);
407 /* Make sure it's large enough */
408 if (Length
<= ProcessInformationLength
)
410 /* Enter SEH to protect write */
414 RtlCopyMemory(ProcessInformation
,
419 ((PUNICODE_STRING
)ProcessInformation
)->Buffer
=
420 (PWSTR
)((PUNICODE_STRING
)ProcessInformation
+ 1);
424 /* Get the exception code */
425 Status
= _SEH_GetExceptionCode();
432 /* Per-process security cookie */
435 /* Get the current process and cookie */
436 Process
= PsGetCurrentProcess();
437 Cookie
= Process
->Cookie
;
440 LARGE_INTEGER SystemTime
;
444 /* Generate a new cookie */
445 KeQuerySystemTime(&SystemTime
);
446 Prcb
= KeGetCurrentPrcb();
447 NewCookie
= Prcb
->KeSystemCalls
^ Prcb
->InterruptTime
^
448 SystemTime
.u
.LowPart
^ SystemTime
.u
.HighPart
;
450 /* Set the new cookie or return the current one */
451 Cookie
= InterlockedCompareExchange((LONG
*)&Process
->Cookie
,
454 if (!Cookie
) Cookie
= NewCookie
;
456 /* Set return length */
457 Length
= sizeof(ULONG
);
460 /* Enter SEH to protect write */
463 /* Write back the cookie */
464 *(PULONG
)ProcessInformation
= Cookie
;
468 /* Get the exception code */
469 Status
= _SEH_GetExceptionCode();
474 /* Not yet implemented, or unknown */
475 case ProcessBasePriority
:
476 case ProcessRaisePriority
:
477 case ProcessExceptionPort
:
478 case ProcessAccessToken
:
480 case ProcessIoPortHandlers
:
481 case ProcessUserModeIOPL
:
482 case ProcessEnableAlignmentFaultFixup
:
483 case ProcessAffinityMask
:
484 case ProcessForegroundInformation
:
486 Status
= STATUS_INVALID_INFO_CLASS
;
489 /* Protect write with SEH */
492 /* Check if caller wanted return length */
493 if (ReturnLength
) *ReturnLength
= Length
;
497 /* Get exception code */
498 Status
= _SEH_GetExceptionCode();
502 /* If we referenced the process, dereference it */
503 if(ProcessInformationClass
!= ProcessCookie
) ObDereferenceObject(Process
);
512 NtSetInformationProcess(IN HANDLE ProcessHandle
,
513 IN PROCESSINFOCLASS ProcessInformationClass
,
514 IN PVOID ProcessInformation
,
515 IN ULONG ProcessInformationLength
)
518 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
521 HANDLE PortHandle
= NULL
;
522 HANDLE TokenHandle
= NULL
;
523 PROCESS_SESSION_INFORMATION SessionInfo
= {0};
527 /* Verify Information Class validity */
529 Status
= DefaultSetInfoBufferCheck(ProcessInformationClass
,
531 RTL_NUMBER_OF(PsProcessInfoClass
),
533 ProcessInformationLength
,
535 if (!NT_SUCCESS(Status
)) return Status
;
538 /* Check what class this is */
539 Access
= PROCESS_SET_INFORMATION
;
540 if (ProcessInformationClass
== ProcessSessionInformation
)
542 /* Setting the Session ID needs a special mask */
543 Access
|= PROCESS_SET_SESSIONID
;
545 else if (ProcessInformationClass
== ProcessExceptionPort
)
547 /* Setting the exception port needs a special mask */
548 Access
|= PROCESS_SUSPEND_RESUME
;
551 /* Reference the process */
552 Status
= ObReferenceObjectByHandle(ProcessHandle
,
558 if (!NT_SUCCESS(Status
)) return Status
;
560 /* Check what kind of information class this is */
561 switch (ProcessInformationClass
)
563 /* Quotas and priorities: not implemented */
564 case ProcessQuotaLimits
:
565 case ProcessBasePriority
:
566 case ProcessRaisePriority
:
567 Status
= STATUS_NOT_IMPLEMENTED
;
570 /* Error/Exception Port */
571 case ProcessExceptionPort
:
573 /* Use SEH for capture */
576 /* Capture the handle */
577 PortHandle
= *(PHANDLE
)ProcessInformation
;
581 /* Get the exception code */
582 Status
= _SEH_GetExceptionCode();
585 if (!NT_SUCCESS(Status
)) break;
587 /* Get the LPC Port */
588 Status
= ObReferenceObjectByHandle(PortHandle
,
592 (PVOID
)&ExceptionPort
,
594 if (!NT_SUCCESS(Status
)) break;
596 /* Change the pointer */
597 if (InterlockedCompareExchangePointer(&Process
->ExceptionPort
,
601 /* We already had one, fail */
602 ObDereferenceObject(ExceptionPort
);
603 Status
= STATUS_PORT_ALREADY_SET
;
608 case ProcessAccessToken
:
610 /* Use SEH for capture */
613 /* Save the token handle */
614 TokenHandle
= ((PPROCESS_ACCESS_TOKEN
)ProcessInformation
)->
619 /* Get the exception code */
620 Status
= _SEH_GetExceptionCode();
623 if (!NT_SUCCESS(Status
)) break;
625 /* Assign the actual token */
626 Status
= PspSetPrimaryToken(Process
, TokenHandle
, NULL
);
629 /* Hard error processing */
630 case ProcessDefaultHardErrorMode
:
632 /* Enter SEH for direct buffer read */
635 /* Update the current mode abd return the previous one */
636 InterlockedExchange((LONG
*)&Process
->DefaultHardErrorProcessing
,
637 *(PLONG
)ProcessInformation
);
641 /* Get exception code */
642 Status
= _SEH_GetExceptionCode();
648 case ProcessSessionInformation
:
650 /* Enter SEH for capture */
653 /* Capture the caller's buffer */
654 SessionInfo
= *(PPROCESS_SESSION_INFORMATION
)ProcessInformation
;
658 /* Get the exception code */
659 Status
= _SEH_GetExceptionCode();
662 if (!NT_SUCCESS(Status
)) break;
664 /* Setting the session id requires the SeTcbPrivilege */
665 if (!SeSinglePrivilegeCheck(SeTcbPrivilege
, PreviousMode
))
667 /* Can't set the session ID, bail out. */
668 Status
= STATUS_PRIVILEGE_NOT_HELD
;
672 /* FIXME - update the session id for the process token */
673 //Status = PsLockProcess(Process, FALSE);
674 if (!NT_SUCCESS(Status
)) break;
676 /* Write the session ID in the EPROCESS */
677 Process
->Session
= SessionInfo
.SessionId
;
679 /* Check if the process also has a PEB */
683 * Attach to the process to make sure we're in the right
684 * context to access the PEB structure
686 KeAttachProcess(&Process
->Pcb
);
688 /* Enter SEH for write to user-mode PEB */
691 /* Write the session ID */
692 Process
->Peb
->SessionId
= SessionInfo
.SessionId
;
696 /* Get exception code */
697 Status
= _SEH_GetExceptionCode();
701 /* Detach from the process */
705 /* Unlock the process */
706 //PsUnlockProcess(Process);
709 /* Priority class: HACK! */
710 case ProcessPriorityClass
:
713 /* We currently don't implement any of these */
714 case ProcessLdtInformation
:
716 case ProcessIoPortHandlers
:
717 case ProcessWorkingSetWatch
:
718 case ProcessUserModeIOPL
:
719 case ProcessEnableAlignmentFaultFixup
:
720 case ProcessAffinityMask
:
721 Status
= STATUS_NOT_IMPLEMENTED
;
724 /* Supposedly these are invalid...!? verify! */
725 case ProcessBasicInformation
:
726 case ProcessIoCounters
:
728 case ProcessPooledUsageAndLimits
:
729 case ProcessWx86Information
:
730 case ProcessHandleCount
:
731 case ProcessWow64Information
:
732 case ProcessDebugPort
:
734 Status
= STATUS_INVALID_INFO_CLASS
;
737 /* Dereference and return status */
738 ObDereferenceObject(Process
);
747 NtSetInformationThread(IN HANDLE ThreadHandle
,
748 IN THREADINFOCLASS ThreadInformationClass
,
749 IN PVOID ThreadInformation
,
750 IN ULONG ThreadInformationLength
)
754 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
756 HANDLE TokenHandle
= NULL
;
757 KPRIORITY Priority
= 0;
758 KAFFINITY Affinity
= 0, CombinedAffinity
;
759 PVOID Address
= NULL
;
761 ULONG DisableBoost
= 0;
762 ULONG IdealProcessor
= 0;
765 PVOID
*ExpansionSlots
;
769 /* Verify Information Class validity */
771 Status
= DefaultSetInfoBufferCheck(ThreadInformationClass
,
773 RTL_NUMBER_OF(PsThreadInfoClass
),
775 ThreadInformationLength
,
777 if (!NT_SUCCESS(Status
)) return Status
;
780 /* Check what class this is */
781 Access
= THREAD_SET_INFORMATION
;
782 if (ThreadInformationClass
== ThreadImpersonationToken
)
784 /* Setting the impersonation token needs a special mask */
785 Access
= THREAD_SET_THREAD_TOKEN
;
788 /* Reference the process */
789 Status
= ObReferenceObjectByHandle(ThreadHandle
,
795 if (!NT_SUCCESS(Status
)) return Status
;
797 /* Check what kind of information class this is */
798 switch (ThreadInformationClass
)
800 /* Thread priority */
803 /* Use SEH for capture */
806 /* Get the priority */
807 Priority
= *(PLONG
)ThreadInformation
;
811 /* Get the exception code */
812 Status
= _SEH_GetExceptionCode();
815 if (!NT_SUCCESS(Status
)) break;
818 if ((Priority
> HIGH_PRIORITY
) ||
819 (Priority
<= LOW_PRIORITY
))
822 Status
= STATUS_INVALID_PARAMETER
;
826 /* Set the priority */
827 KeSetPriorityThread(&Thread
->Tcb
, Priority
);
830 case ThreadBasePriority
:
832 /* Use SEH for capture */
835 /* Get the priority */
836 Priority
= *(PLONG
)ThreadInformation
;
840 /* Get the exception code */
841 Status
= _SEH_GetExceptionCode();
844 if (!NT_SUCCESS(Status
)) break;
847 if ((Priority
> THREAD_BASE_PRIORITY_MAX
) ||
848 (Priority
< THREAD_BASE_PRIORITY_MIN
))
850 /* These ones are OK */
851 if ((Priority
!= THREAD_BASE_PRIORITY_LOWRT
+ 1) &&
852 (Priority
!= THREAD_BASE_PRIORITY_IDLE
- 1))
854 /* Check if the process is real time */
855 if (PsGetCurrentProcess()->PriorityClass
!=
856 PROCESS_PRIORITY_CLASS_REALTIME
)
859 Status
= STATUS_INVALID_PARAMETER
;
865 /* Set the base priority */
866 KeSetBasePriorityThread(&Thread
->Tcb
, Priority
);
869 case ThreadAffinityMask
:
871 /* Use SEH for capture */
874 /* Get the priority */
875 Affinity
= *(PULONG_PTR
)ThreadInformation
;
879 /* Get the exception code */
880 Status
= _SEH_GetExceptionCode();
883 if (!NT_SUCCESS(Status
)) break;
889 Status
= STATUS_INVALID_PARAMETER
;
893 /* Get the process */
894 Process
= Thread
->ThreadsProcess
;
896 /* Try to acquire rundown */
897 if (ExAcquireRundownProtection(&Process
->RundownProtect
))
900 KeEnterCriticalRegion();
901 ExAcquirePushLockShared(&Process
->ProcessLock
);
904 CombinedAffinity
= Affinity
& Process
->Pcb
.Affinity
;
905 if (CombinedAffinity
!= Affinity
)
908 Status
= STATUS_INVALID_PARAMETER
;
912 /* Set the affinity */
913 KeSetAffinityThread(&Thread
->Tcb
, CombinedAffinity
);
916 /* Release the lock and rundown */
917 ExReleasePushLockShared(&Process
->ProcessLock
);
918 KeLeaveCriticalRegion();
919 ExReleaseRundownProtection(&Process
->RundownProtect
);
924 Status
= STATUS_PROCESS_IS_TERMINATING
;
930 case ThreadImpersonationToken
:
932 /* Use SEH for capture */
935 /* Save the token handle */
936 TokenHandle
= *(PHANDLE
)ThreadInformation
;
940 /* Get the exception code */
941 Status
= _SEH_GetExceptionCode();
944 if (!NT_SUCCESS(Status
)) break;
946 /* Assign the actual token */
947 Status
= PsAssignImpersonationToken(Thread
, TokenHandle
);
950 case ThreadQuerySetWin32StartAddress
:
952 /* Use SEH for capture */
955 /* Get the priority */
956 Address
= *(PVOID
*)ThreadInformation
;
960 /* Get the exception code */
961 Status
= _SEH_GetExceptionCode();
964 if (!NT_SUCCESS(Status
)) break;
966 /* Set the address */
967 Thread
->Win32StartAddress
= Address
;
970 case ThreadIdealProcessor
:
972 /* Use SEH for capture */
975 /* Get the priority */
976 IdealProcessor
= *(PULONG_PTR
)ThreadInformation
;
980 /* Get the exception code */
981 Status
= _SEH_GetExceptionCode();
984 if (!NT_SUCCESS(Status
)) break;
987 if (IdealProcessor
> MAXIMUM_PROCESSORS
)
990 Status
= STATUS_INVALID_PARAMETER
;
995 Status
= KeSetIdealProcessorThread(&Thread
->Tcb
,
996 (CCHAR
)IdealProcessor
);
998 /* Get the TEB and protect the thread */
999 Teb
= Thread
->Tcb
.Teb
;
1000 if ((Teb
) && (ExAcquireRundownProtection(&Thread
->RundownProtect
)))
1002 /* Save the ideal processor */
1003 Teb
->IdealProcessor
= Thread
->Tcb
.IdealProcessor
;
1005 /* Release rundown protection */
1006 ExReleaseRundownProtection(&Thread
->RundownProtect
);
1011 case ThreadPriorityBoost
:
1013 /* Use SEH for capture */
1016 /* Get the priority */
1017 DisableBoost
= *(PULONG_PTR
)ThreadInformation
;
1021 /* Get the exception code */
1022 Status
= _SEH_GetExceptionCode();
1025 if (!NT_SUCCESS(Status
)) break;
1027 /* Call the kernel */
1028 KeSetDisableBoostThread(&Thread
->Tcb
, (BOOLEAN
)DisableBoost
);
1031 case ThreadZeroTlsCell
:
1033 /* Use SEH for capture */
1036 /* Get the priority */
1037 TlsIndex
= *(PULONG_PTR
)ThreadInformation
;
1041 /* Get the exception code */
1042 Status
= _SEH_GetExceptionCode();
1045 if (!NT_SUCCESS(Status
)) break;
1047 /* This is only valid for the current thread */
1048 if (Thread
!= PsGetCurrentThread())
1051 Status
= STATUS_INVALID_PARAMETER
;
1055 /* Get the process */
1056 Process
= Thread
->ThreadsProcess
;
1058 /* Loop the threads */
1059 ProcThread
= PsGetNextProcessThread(Process
, NULL
);
1062 /* Acquire rundown */
1063 if (ExAcquireRundownProtection(&ProcThread
->RundownProtect
))
1066 Teb
= ProcThread
->Tcb
.Teb
;
1069 /* Check if we're in the expansion range */
1070 if (TlsIndex
> TLS_MINIMUM_AVAILABLE
- 1)
1072 if (TlsIndex
< (TLS_MINIMUM_AVAILABLE
+
1073 TLS_EXPANSION_SLOTS
) - 1)
1075 /* Check if we have expansion slots */
1076 ExpansionSlots
= Teb
->TlsExpansionSlots
;
1079 /* Clear the index */
1080 ExpansionSlots
[TlsIndex
- TLS_MINIMUM_AVAILABLE
] = 0;
1086 /* Clear the index */
1087 Teb
->TlsSlots
[TlsIndex
] = NULL
;
1091 /* Release rundown */
1092 ExReleaseRundownProtection(&ProcThread
->RundownProtect
);
1095 /* Go to the next thread */
1096 ProcThread
= PsGetNextProcessThread(Process
, ProcThread
);
1103 /* We don't implement it yet */
1104 DPRINT1("Not implemented: %lx\n", ThreadInformationClass
);
1105 Status
= STATUS_NOT_IMPLEMENTED
;
1108 /* Dereference and return status */
1109 ObDereferenceObject(Thread
);
1118 NtQueryInformationThread(IN HANDLE ThreadHandle
,
1119 IN THREADINFOCLASS ThreadInformationClass
,
1120 OUT PVOID ThreadInformation
,
1121 IN ULONG ThreadInformationLength
,
1122 OUT PULONG ReturnLength OPTIONAL
)
1125 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
1126 NTSTATUS Status
= STATUS_SUCCESS
;
1129 PTHREAD_BASIC_INFORMATION ThreadBasicInfo
=
1130 (PTHREAD_BASIC_INFORMATION
)ThreadInformation
;
1131 PKERNEL_USER_TIMES ThreadTime
= (PKERNEL_USER_TIMES
)ThreadInformation
;
1135 /* Verify Information Class validity */
1137 Status
= DefaultQueryInfoBufferCheck(ThreadInformationClass
,
1139 RTL_NUMBER_OF(PsThreadInfoClass
),
1141 ThreadInformationLength
,
1144 if (!NT_SUCCESS(Status
)) return Status
;
1147 /* Check what class this is */
1148 Access
= THREAD_QUERY_INFORMATION
;
1150 /* Reference the process */
1151 Status
= ObReferenceObjectByHandle(ThreadHandle
,
1157 if (!NT_SUCCESS(Status
)) return Status
;
1159 /* Check what kind of information class this is */
1160 switch (ThreadInformationClass
)
1162 /* Basic thread information */
1163 case ThreadBasicInformation
:
1165 /* Protect writes with SEH */
1168 /* Write all the information from the ETHREAD/KTHREAD */
1169 ThreadBasicInfo
->ExitStatus
= Thread
->ExitStatus
;
1170 ThreadBasicInfo
->TebBaseAddress
= (PVOID
)Thread
->Tcb
.Teb
;
1171 ThreadBasicInfo
->ClientId
= Thread
->Cid
;
1172 ThreadBasicInfo
->AffinityMask
= Thread
->Tcb
.Affinity
;
1173 ThreadBasicInfo
->Priority
= Thread
->Tcb
.Priority
;
1174 ThreadBasicInfo
->BasePriority
= KeQueryBasePriorityThread(&Thread
->Tcb
);
1176 /* Set return length */
1177 Length
= sizeof(THREAD_BASIC_INFORMATION
);
1181 /* Get exception code */
1182 Status
= _SEH_GetExceptionCode();
1187 /* Thread time information */
1190 /* Protect writes with SEH */
1193 /* Copy time information from ETHREAD/KTHREAD */
1194 ThreadTime
->KernelTime
.QuadPart
= Thread
->Tcb
.KernelTime
*
1196 ThreadTime
->UserTime
.QuadPart
= Thread
->Tcb
.UserTime
*
1198 ThreadTime
->CreateTime
= Thread
->CreateTime
;
1199 ThreadTime
->ExitTime
= Thread
->ExitTime
;
1201 /* Set the return length */
1202 Length
= sizeof(KERNEL_USER_TIMES
);
1206 /* Get exception code */
1207 Status
= _SEH_GetExceptionCode();
1212 case ThreadQuerySetWin32StartAddress
:
1214 /* Protect write with SEH */
1217 /* Return the Win32 Start Address */
1218 *(PVOID
*)ThreadInformation
= Thread
->Win32StartAddress
;
1220 /* Set the return length*/
1221 Length
= sizeof(PVOID
);
1225 /* Get exception code */
1226 Status
= _SEH_GetExceptionCode();
1231 case ThreadPerformanceCount
:
1233 /* Protect write with SEH */
1237 (*(PLARGE_INTEGER
)ThreadInformation
).QuadPart
= 0;
1239 /* Set the return length*/
1240 Length
= sizeof(LARGE_INTEGER
);
1244 /* Get exception code */
1245 Status
= _SEH_GetExceptionCode();
1250 case ThreadAmILastThread
:
1252 /* Protect write with SEH */
1255 /* Return whether or not we are the last thread */
1256 *(PULONG
)ThreadInformation
= ((Thread
->ThreadsProcess
->
1257 ThreadListHead
.Flink
->Flink
==
1258 &Thread
->ThreadsProcess
->
1262 /* Set the return length*/
1263 Length
= sizeof(ULONG
);
1267 /* Get exception code */
1268 Status
= _SEH_GetExceptionCode();
1273 case ThreadIsIoPending
:
1275 /* Raise the IRQL to protect the IRP list */
1276 KeRaiseIrql(APC_LEVEL
, &OldIrql
);
1278 /* Protect write with SEH */
1281 /* Check if the IRP list is empty or not */
1282 *(PULONG
)ThreadInformation
= !IsListEmpty(&Thread
->IrpList
);
1284 /* Set the return length*/
1285 Length
= sizeof(ULONG
);
1289 /* Get exception code */
1290 Status
= _SEH_GetExceptionCode();
1294 /* Lower IRQL back */
1295 KeLowerIrql(OldIrql
);
1301 /* Not yet implemented */
1302 DPRINT1("Not implemented: %lx\n", ThreadInformationClass
);
1303 Status
= STATUS_NOT_IMPLEMENTED
;
1306 /* Protect write with SEH */
1309 /* Check if caller wanted return length */
1310 if (ReturnLength
) *ReturnLength
= Length
;
1314 /* Get exception code */
1315 Status
= _SEH_GetExceptionCode();
1319 /* Dereference the thread, and return */
1320 ObDereferenceObject(Thread
);