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
7 * PROGRAMMER: David Welch (welch@mcmail.com)
10 * Updated 09/08/2003 by Skywing (skywing@valhallalegends.com)
11 * to suppport thread-eventpairs.
14 /* INCLUDES *****************************************************************/
16 #include <ddk/ntddk.h>
17 #include <internal/ps.h>
18 #include <internal/ex.h>
19 #include <internal/safe.h>
21 #include <internal/debug.h>
23 /* FUNCTIONS *****************************************************************/
26 NtSetInformationThread(HANDLE ThreadHandle,
27 THREADINFOCLASS ThreadInformationClass,
28 PVOID ThreadInformation,
29 ULONG ThreadInformationLength)
34 Status = ObReferenceObjectByHandle(ThreadHandle,
35 THREAD_SET_INFORMATION,
40 if (!NT_SUCCESS(Status))
45 switch (ThreadInformationClass)
47 case ThreadBasicInformation:
48 /* Can only be queried */
49 Status = STATUS_INVALID_INFO_CLASS;
53 /* Can only be queried */
54 Status = STATUS_INVALID_INFO_CLASS;
61 if (ThreadInformationLength != sizeof(KPRIORITY))
63 Status = STATUS_INFO_LENGTH_MISMATCH;
66 Priority = *(KPRIORITY*)ThreadInformation;
67 if (Priority < LOW_PRIORITY || Priority >= MAXIMUM_PRIORITY)
69 Status = STATUS_INVALID_PARAMETER;
72 KeSetPriorityThread(&Thread->Tcb, Priority);
73 Status = STATUS_SUCCESS;
77 case ThreadBasePriority:
78 if (ThreadInformationLength != sizeof(ULONG))
80 Status = STATUS_INFO_LENGTH_MISMATCH;
83 Status = MmCopyFromCaller(&(Thread->Tcb.BasePriority),
88 case ThreadAffinityMask:
89 Thread->Tcb.UserAffinity = *((PULONG)ThreadInformation);
92 case ThreadImpersonationToken:
96 if (ThreadInformationLength != sizeof(HANDLE))
98 Status = STATUS_INFO_LENGTH_MISMATCH;
101 TokenHandle = *((PHANDLE)ThreadInformation);
102 Status = PsAssignImpersonationToken(Thread, TokenHandle);
106 case ThreadDescriptorTableEntry:
107 /* Can only be queried */
108 Status = STATUS_INVALID_INFO_CLASS;
111 case ThreadEventPair:
113 PKEVENT_PAIR EventPair;
115 if (ThreadInformationLength != sizeof(HANDLE))
117 Status = STATUS_INFO_LENGTH_MISMATCH;
121 if (ExGetPreviousMode() == UserMode) /* FIXME: Validate this for all infoclasses and system services */
123 DPRINT("NtSetInformationThread:ThreadEventPair: Checking user pointer %08x...\n", ThreadInformation);
124 ProbeForRead(ThreadInformation, sizeof(HANDLE), sizeof(HANDLE)); /* FIXME: This entire function should be
125 * wrapped in an SEH frame... return (NTSTATUS)GetExceptionCode() on exception */
128 Status = ObReferenceObjectByHandle(*(PHANDLE)ThreadInformation,
130 ExEventPairObjectType,
135 if (!NT_SUCCESS(Status))
140 ExpSwapThreadEventPair(Thread, EventPair); /* Note that the extra reference is kept intentionally */
141 Status = STATUS_SUCCESS;
145 case ThreadQuerySetWin32StartAddress:
146 if (ThreadInformationLength != sizeof(ULONG))
148 Status = STATUS_INFO_LENGTH_MISMATCH;
151 Thread->u2.Win32StartAddress = (PVOID)*((PULONG)ThreadInformation);
152 Status = STATUS_SUCCESS;
155 case ThreadZeroTlsCell:
157 Status = STATUS_NOT_IMPLEMENTED;
161 case ThreadPerformanceCount:
162 /* Can only be queried */
163 Status = STATUS_INVALID_INFO_CLASS;
166 case ThreadAmILastThread:
167 /* Can only be queried */
168 Status = STATUS_INVALID_INFO_CLASS;
171 case ThreadIdealProcessor:
172 Status = STATUS_NOT_IMPLEMENTED;
175 case ThreadPriorityBoost:
176 Status = STATUS_NOT_IMPLEMENTED;
179 case ThreadSetTlsArrayAddress:
180 Status = STATUS_NOT_IMPLEMENTED;
183 case ThreadIsIoPending:
184 /* Can only be queried */
185 Status = STATUS_INVALID_INFO_CLASS;
188 case ThreadHideFromDebugger:
189 Status = STATUS_NOT_IMPLEMENTED;
193 Status = STATUS_UNSUCCESSFUL;
195 ObDereferenceObject(Thread);
201 NtQueryInformationThread (IN HANDLE ThreadHandle,
202 IN THREADINFOCLASS ThreadInformationClass,
203 OUT PVOID ThreadInformation,
204 IN ULONG ThreadInformationLength,
205 OUT PULONG ReturnLength)
210 Status = ObReferenceObjectByHandle(ThreadHandle,
211 THREAD_QUERY_INFORMATION,
216 if (!NT_SUCCESS(Status))
221 switch (ThreadInformationClass)
223 case ThreadBasicInformation:
225 PTHREAD_BASIC_INFORMATION TBI;
227 TBI = (PTHREAD_BASIC_INFORMATION)ThreadInformation;
229 if (ThreadInformationLength != sizeof(THREAD_BASIC_INFORMATION))
231 Status = STATUS_INFO_LENGTH_MISMATCH;
235 TBI->ExitStatus = Thread->ExitStatus;
236 TBI->TebBaseAddress = Thread->Tcb.Teb;
237 TBI->ClientId = Thread->Cid;
238 TBI->AffinityMask = Thread->Tcb.Affinity;
239 TBI->Priority = Thread->Tcb.Priority;
240 TBI->BasePriority = Thread->Tcb.BasePriority;
241 Status = STATUS_SUCCESS;
246 Status = STATUS_NOT_IMPLEMENTED;
250 /* Can be set only */
251 Status = STATUS_INVALID_INFO_CLASS;
254 case ThreadBasePriority:
255 /* Can be set only */
256 Status = STATUS_INVALID_INFO_CLASS;
259 case ThreadAffinityMask:
260 /* Can be set only */
261 Status = STATUS_INVALID_INFO_CLASS;
264 case ThreadImpersonationToken:
265 /* Can be set only */
266 Status = STATUS_INVALID_INFO_CLASS;
269 case ThreadDescriptorTableEntry:
270 /* Nebbett says nothing about this */
271 Status = STATUS_NOT_IMPLEMENTED;
274 case ThreadEnableAlignmentFaultFixup:
275 /* Can be set only */
276 Status = STATUS_INVALID_INFO_CLASS;
279 case ThreadEventPair:
280 /* Can be set only */
281 Status = STATUS_INVALID_INFO_CLASS;
284 case ThreadQuerySetWin32StartAddress:
285 if (ThreadInformationLength != sizeof(PVOID))
287 Status = STATUS_INFO_LENGTH_MISMATCH;
290 *((PVOID*)ThreadInformation) = Thread->u2.Win32StartAddress;
291 Status = STATUS_SUCCESS;
294 case ThreadZeroTlsCell:
295 /* Can only be set */
296 Status = STATUS_INVALID_INFO_CLASS;
299 case ThreadPerformanceCount:
300 /* Nebbett says this class is always zero */
301 if (ThreadInformationLength != sizeof(LARGE_INTEGER))
303 Status = STATUS_INFO_LENGTH_MISMATCH;
306 ((PLARGE_INTEGER)ThreadInformation)->QuadPart = 0;
307 Status = STATUS_SUCCESS;
310 case ThreadAmILastThread:
312 if (ThreadInformationLength != sizeof(BOOLEAN))
314 Status = STATUS_INFO_LENGTH_MISMATCH;
317 if (Thread->ThreadsProcess->ThreadListHead.Flink->Flink ==
318 &Thread->ThreadsProcess->ThreadListHead)
320 *((PBOOLEAN)ThreadInformation) = TRUE;
324 *((PBOOLEAN)ThreadInformation) = FALSE;
326 Status = STATUS_SUCCESS;
330 case ThreadIdealProcessor:
331 /* Can only be set */
332 Status = STATUS_INFO_LENGTH_MISMATCH;
335 case ThreadPriorityBoost:
336 Status = STATUS_NOT_IMPLEMENTED;
339 case ThreadSetTlsArrayAddress:
340 /* Can only be set */
341 Status = STATUS_INVALID_INFO_CLASS;
344 case ThreadIsIoPending:
345 Status = STATUS_NOT_IMPLEMENTED;
348 case ThreadHideFromDebugger:
349 /* Can only be set */
350 Status = STATUS_INVALID_INFO_CLASS;
354 Status = STATUS_INVALID_INFO_CLASS;
356 ObDereferenceObject(Thread);
360 VOID KeSetPreviousMode(ULONG Mode)
362 PsGetCurrentThread()->Tcb.PreviousMode = Mode;
369 KeGetPreviousMode (VOID)
371 return (ULONG)PsGetCurrentThread()->Tcb.PreviousMode;
378 ExGetPreviousMode (VOID)
380 return (ULONG)PsGetCurrentThread()->Tcb.PreviousMode;