3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ps/tinfo.c
6 * PURPOSE: Getting/setting thread information
8 * PROGRAMMERS: David Welch (welch@mcmail.com)
9 * Skywing (skywing@valhallalegends.com)
12 /* INCLUDES *****************************************************************/
15 #include <internal/debug.h>
17 /* GLOBALS *****************************************************************/
21 * Remove the Implemented value if all functions are implemented.
28 } QueryInformationData
[MaxThreadInfoClass
+ 1] =
30 {TRUE
, sizeof(THREAD_BASIC_INFORMATION
)}, // ThreadBasicInformation
31 {TRUE
, sizeof(KERNEL_USER_TIMES
)}, // ThreadTimes
32 {TRUE
, 0}, // ThreadPriority
33 {TRUE
, 0}, // ThreadBasePriority
34 {TRUE
, 0}, // ThreadAffinityMask
35 {TRUE
, 0}, // ThreadImpersonationToken
36 {FALSE
, 0}, // ThreadDescriptorTableEntry
37 {TRUE
, 0}, // ThreadEnableAlignmentFaultFixup
38 {TRUE
, 0}, // ThreadEventPair
39 {TRUE
, sizeof(PVOID
)}, // ThreadQuerySetWin32StartAddress
40 {TRUE
, 0}, // ThreadZeroTlsCell
41 {TRUE
, sizeof(LARGE_INTEGER
)}, // ThreadPerformanceCount
42 {TRUE
, sizeof(BOOLEAN
)}, // ThreadAmILastThread
43 {TRUE
, 0}, // ThreadIdealProcessor
44 {FALSE
, 0}, // ThreadPriorityBoost
45 {TRUE
, 0}, // ThreadSetTlsArrayAddress
46 {FALSE
, 0}, // ThreadIsIoPending
47 {TRUE
, 0} // ThreadHideFromDebugger
54 } SetInformationData
[MaxThreadInfoClass
+ 1] =
56 {TRUE
, 0}, // ThreadBasicInformation
57 {TRUE
, 0}, // ThreadTimes
58 {TRUE
, sizeof(KPRIORITY
)}, // ThreadPriority
59 {TRUE
, sizeof(LONG
)}, // ThreadBasePriority
60 {TRUE
, sizeof(KAFFINITY
)}, // ThreadAffinityMask
61 {TRUE
, sizeof(HANDLE
)}, // ThreadImpersonationToken
62 {TRUE
, 0}, // ThreadDescriptorTableEntry
63 {FALSE
, 0}, // ThreadEnableAlignmentFaultFixup
64 #ifdef _ENABLE_THRDEVTPAIR
65 {TRUE
, sizeof(HANDLE
)}, // ThreadEventPair
67 {FALSE
, 0}, // ThreadEventPair
69 {TRUE
, sizeof(PVOID
)}, // ThreadQuerySetWin32StartAddress
70 {FALSE
, 0}, // ThreadZeroTlsCell
71 {TRUE
, 0}, // ThreadPerformanceCount
72 {TRUE
, 0}, // ThreadAmILastThread
73 {FALSE
, 0}, // ThreadIdealProcessor
74 {FALSE
, 0}, // ThreadPriorityBoost
75 {FALSE
, 0}, // ThreadSetTlsArrayAddress
76 {TRUE
, 0}, // ThreadIsIoPending
77 {FALSE
, 0} // ThreadHideFromDebugger
80 /* FUNCTIONS *****************************************************************/
86 NtSetInformationThread (IN HANDLE ThreadHandle
,
87 IN THREADINFOCLASS ThreadInformationClass
,
88 IN PVOID ThreadInformation
,
89 IN ULONG ThreadInformationLength
)
102 if (ThreadInformationClass
<= MaxThreadInfoClass
&&
103 !SetInformationData
[ThreadInformationClass
].Implemented
)
105 return STATUS_NOT_IMPLEMENTED
;
107 if (ThreadInformationClass
> MaxThreadInfoClass
||
108 SetInformationData
[ThreadInformationClass
].Size
== 0)
110 return STATUS_INVALID_INFO_CLASS
;
112 if (ThreadInformationLength
!= SetInformationData
[ThreadInformationClass
].Size
)
114 return STATUS_INFO_LENGTH_MISMATCH
;
117 Status
= ObReferenceObjectByHandle (ThreadHandle
,
118 THREAD_SET_INFORMATION
,
120 ExGetPreviousMode (),
123 if (!NT_SUCCESS(Status
))
128 Status
= MmCopyFromCaller(&u
.Priority
,
130 SetInformationData
[ThreadInformationClass
].Size
);
131 if (NT_SUCCESS(Status
))
133 switch (ThreadInformationClass
)
136 if (u
.Priority
< LOW_PRIORITY
|| u
.Priority
>= MAXIMUM_PRIORITY
)
138 Status
= STATUS_INVALID_PARAMETER
;
141 KeSetPriorityThread(&Thread
->Tcb
, u
.Priority
);
144 case ThreadBasePriority
:
145 KeSetBasePriorityThread (&Thread
->Tcb
, u
.Increment
);
148 case ThreadAffinityMask
:
149 Status
= KeSetAffinityThread(&Thread
->Tcb
, u
.Affinity
);
152 case ThreadImpersonationToken
:
153 Status
= PsAssignImpersonationToken (Thread
, u
.Handle
);
156 #ifdef _ENABLE_THRDEVTPAIR
157 case ThreadEventPair
:
159 PKEVENT_PAIR EventPair
;
161 Status
= ObReferenceObjectByHandle(u
.Handle
,
163 ExEventPairObjectType
,
167 if (NT_SUCCESS(Status
))
169 ExpSwapThreadEventPair(Thread
, EventPair
); /* Note that the extra reference is kept intentionally */
173 #endif /* _ENABLE_THRDEVTPAIR */
175 case ThreadQuerySetWin32StartAddress
:
176 Thread
->Win32StartAddress
= u
.Address
;
180 /* Shoult never occure if the data table is correct */
184 ObDereferenceObject (Thread
);
193 NtQueryInformationThread (IN HANDLE ThreadHandle
,
194 IN THREADINFOCLASS ThreadInformationClass
,
195 OUT PVOID ThreadInformation
,
196 IN ULONG ThreadInformationLength
,
197 OUT PULONG ReturnLength OPTIONAL
)
203 THREAD_BASIC_INFORMATION TBI
;
204 KERNEL_USER_TIMES TTI
;
210 if (ThreadInformationClass
<= MaxThreadInfoClass
&&
211 !QueryInformationData
[ThreadInformationClass
].Implemented
)
213 return STATUS_NOT_IMPLEMENTED
;
215 if (ThreadInformationClass
> MaxThreadInfoClass
||
216 QueryInformationData
[ThreadInformationClass
].Size
== 0)
218 return STATUS_INVALID_INFO_CLASS
;
220 if (ThreadInformationLength
!= QueryInformationData
[ThreadInformationClass
].Size
)
222 return STATUS_INFO_LENGTH_MISMATCH
;
225 Status
= ObReferenceObjectByHandle(ThreadHandle
,
226 THREAD_QUERY_INFORMATION
,
231 if (!NT_SUCCESS(Status
))
236 switch (ThreadInformationClass
)
238 case ThreadBasicInformation
:
239 /* A test on W2K agains ntdll shows NtQueryInformationThread return STATUS_PENDING
240 * as ExitStatus for current/running thread, while KETHREAD's ExitStatus is
241 * 0. So do the conversion here:
243 u
.TBI
.ExitStatus
= (Thread
->ExitStatus
== 0) ? STATUS_PENDING
: Thread
->ExitStatus
;
244 u
.TBI
.TebBaseAddress
= Thread
->Tcb
.Teb
;
245 u
.TBI
.ClientId
= Thread
->Cid
;
246 u
.TBI
.AffinityMask
= Thread
->Tcb
.Affinity
;
247 u
.TBI
.Priority
= Thread
->Tcb
.Priority
;
248 u
.TBI
.BasePriority
= Thread
->Tcb
.BasePriority
;
252 u
.TTI
.KernelTime
.QuadPart
= Thread
->Tcb
.KernelTime
* 100000LL;
253 u
.TTI
.UserTime
.QuadPart
= Thread
->Tcb
.UserTime
* 100000LL;
254 u
.TTI
.CreateTime
= Thread
->CreateTime
;
256 u
.TTI
.ExitTime
= Thread
->ExitTime
;
259 case ThreadQuerySetWin32StartAddress
:
260 u
.Address
= Thread
->Win32StartAddress
;
263 case ThreadPerformanceCount
:
264 /* Nebbett says this class is always zero */
265 u
.Count
.QuadPart
= 0;
268 case ThreadAmILastThread
:
269 if (Thread
->ThreadsProcess
->ThreadListHead
.Flink
->Flink
==
270 &Thread
->ThreadsProcess
->ThreadListHead
)
280 /* Shoult never occure if the data table is correct */
283 if (QueryInformationData
[ThreadInformationClass
].Size
)
285 Status
= MmCopyToCaller(ThreadInformation
,
287 QueryInformationData
[ThreadInformationClass
].Size
);
292 static ULONG Null
= 0;
293 Status2
= MmCopyToCaller(ReturnLength
,
294 NT_SUCCESS(Status
) ? &QueryInformationData
[ThreadInformationClass
].Size
: &Null
,
296 if (NT_SUCCESS(Status
))
302 ObDereferenceObject(Thread
);
308 KeSetPreviousMode (ULONG Mode
)
310 PsGetCurrentThread()->Tcb
.PreviousMode
= (UCHAR
)Mode
;
317 KPROCESSOR_MODE STDCALL
318 KeGetPreviousMode (VOID
)
320 return (ULONG
)PsGetCurrentThread()->Tcb
.PreviousMode
;
327 KPROCESSOR_MODE STDCALL
328 ExGetPreviousMode (VOID
)
330 return (KPROCESSOR_MODE
)PsGetCurrentThread()->Tcb
.PreviousMode
;