Fixed bug in NtFreeVirtualMemory reported by Philip Susi

Added all thread information classes
Began work on fixing suspend/resume

svn path=/trunk/; revision=1554
This commit is contained in:
David Welch 2001-01-21 14:54:30 +00:00
parent 3f694e507f
commit 10f230ae0a
9 changed files with 371 additions and 282 deletions

View file

@ -55,7 +55,9 @@ extern ULONG IMPORTED NtBuildNumber;
#define ProcessImageFileName 22 #define ProcessImageFileName 22
#define MaxProcessInfoClass 23 #define MaxProcessInfoClass 23
// thread query / set information class /*
* thread query / set information class
*/
#define ThreadBasicInformation 0 #define ThreadBasicInformation 0
#define ThreadTimes 1 #define ThreadTimes 1
#define ThreadPriority 2 #define ThreadPriority 2
@ -71,7 +73,10 @@ extern ULONG IMPORTED NtBuildNumber;
#define ThreadAmILastThread 12 #define ThreadAmILastThread 12
#define ThreadIdealProcessor 13 #define ThreadIdealProcessor 13
#define ThreadPriorityBoost 14 #define ThreadPriorityBoost 14
#define MaxThreadInfoClass 15 #define ThreadSetTlsArrayAddress 15
#define ThreadIsIoPending 16
#define ThreadHideFromDebugger 17
#define MaxThreadInfoClass 17
// object handle information // object handle information
@ -862,11 +867,12 @@ typedef KERNEL_USER_TIMES *PKERNEL_USER_TIMES;
typedef struct _THREAD_BASIC_INFORMATION typedef struct _THREAD_BASIC_INFORMATION
{ {
NTSTATUS ExitStatus; NTSTATUS ExitStatus;
PVOID TebBaseAddress; PVOID TebBaseAddress;
KAFFINITY AffinityMask; CLIENT_ID ClientId;
KPRIORITY BasePriority; KAFFINITY AffinityMask;
ULONG UniqueThreadId; KPRIORITY Priority;
KPRIORITY BasePriority;
} THREAD_BASIC_INFORMATION, *PTHREAD_BASIC_INFORMATION; } THREAD_BASIC_INFORMATION, *PTHREAD_BASIC_INFORMATION;
// object information // object information

View file

@ -396,15 +396,8 @@ PACCESS_TOKEN PsReferenceEffectiveToken(PETHREAD Thread,
NTSTATUS PsOpenTokenOfProcess(HANDLE ProcessHandle, NTSTATUS PsOpenTokenOfProcess(HANDLE ProcessHandle,
PACCESS_TOKEN* Token); PACCESS_TOKEN* Token);
ULONG PsFreezeThread(PETHREAD Thread, NTSTATUS PsSuspendThread(PETHREAD Thread, PULONG PreviousCount);
PNTSTATUS WaitStatus, NTSTATUS PsResumeThread(PETHREAD Thread, PULONG PreviousCount);
UCHAR Alertable,
ULONG WaitMode);
ULONG PsUnfreezeThread(PETHREAD Thread,
PNTSTATUS WaitStatus);
ULONG PsSuspendThread(PETHREAD Thread);
ULONG PsResumeThread(PETHREAD Thread);
#define THREAD_STATE_INVALID (0) #define THREAD_STATE_INVALID (0)

View file

@ -77,7 +77,7 @@ KeInitializeThread(PKPROCESS Process, PKTHREAD Thread, BOOLEAN First)
Thread->Teb = NULL; Thread->Teb = NULL;
Thread->TlsArray = NULL; Thread->TlsArray = NULL;
Thread->DebugActive = 0; Thread->DebugActive = 0;
Thread->State = THREAD_STATE_SUSPENDED; Thread->State = THREAD_STATE_BLOCKED;
Thread->Alerted[0] = 0; Thread->Alerted[0] = 0;
Thread->Alerted[1] = 0; Thread->Alerted[1] = 0;
Thread->Iopl = 0; Thread->Iopl = 0;
@ -146,7 +146,7 @@ KeInitializeThread(PKPROCESS Process, PKTHREAD Thread, BOOLEAN First)
Thread->ThreadListEntry.Flink = NULL; Thread->ThreadListEntry.Flink = NULL;
Thread->ThreadListEntry.Blink = NULL; Thread->ThreadListEntry.Blink = NULL;
Thread->FreezeCount = 0; Thread->FreezeCount = 0;
Thread->SuspendCount = 1; Thread->SuspendCount = 0;
/* /*
* Initialize ReactOS specific members * Initialize ReactOS specific members

View file

@ -1,4 +1,4 @@
/* $Id: virtual.c,v 1.36 2001/01/08 02:14:06 dwelch Exp $ /* $Id: virtual.c,v 1.37 2001/01/21 14:54:29 dwelch Exp $
* *
* COPYRIGHT: See COPYING in the top directory * COPYRIGHT: See COPYING in the top directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -995,16 +995,18 @@ NtFreeVirtualMemory(IN HANDLE ProcessHandle,
for (i=0; i<=(MemoryArea->Length/PAGESIZE); i++) for (i=0; i<=(MemoryArea->Length/PAGESIZE); i++)
{ {
LARGE_INTEGER PhysicalAddr; ULONG PhysicalAddr;
PhysicalAddr = MmGetPhysicalAddress(MemoryArea->BaseAddress + PhysicalAddr =
(i*PAGESIZE)); MmGetPhysicalAddressForProcess(Process,
if (PhysicalAddr.u.LowPart != 0) MemoryArea->BaseAddress +
(i*PAGESIZE));
if (PhysicalAddr != 0)
{ {
MmRemovePageFromWorkingSet(AddressSpace->Process, MmRemovePageFromWorkingSet(AddressSpace->Process,
MemoryArea->BaseAddress + MemoryArea->BaseAddress +
(i*PAGESIZE)); (i*PAGESIZE));
MmDereferencePage((PVOID)(ULONG)(PhysicalAddr.u.LowPart)); MmDereferencePage((PVOID)(ULONG)(PhysicalAddr));
} }
} }

View file

@ -1,4 +1,4 @@
/* $Id: create.c,v 1.28 2001/01/19 15:09:01 dwelch Exp $ /* $Id: create.c,v 1.29 2001/01/21 14:54:29 dwelch Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -512,14 +512,15 @@ static NTSTATUS PsCreateTeb (HANDLE ProcessHandle,
} }
NTSTATUS STDCALL NtCreateThread (PHANDLE ThreadHandle, NTSTATUS STDCALL
ACCESS_MASK DesiredAccess, NtCreateThread (PHANDLE ThreadHandle,
POBJECT_ATTRIBUTES ObjectAttributes, ACCESS_MASK DesiredAccess,
HANDLE ProcessHandle, POBJECT_ATTRIBUTES ObjectAttributes,
PCLIENT_ID Client, HANDLE ProcessHandle,
PCONTEXT ThreadContext, PCLIENT_ID Client,
PINITIAL_TEB InitialTeb, PCONTEXT ThreadContext,
BOOLEAN CreateSuspended) PINITIAL_TEB InitialTeb,
BOOLEAN CreateSuspended)
{ {
PETHREAD Thread; PETHREAD Thread;
PNT_TEB TebBase; PNT_TEB TebBase;
@ -601,23 +602,24 @@ NTSTATUS STDCALL NtCreateThread (PHANDLE ThreadHandle,
if (!CreateSuspended) if (!CreateSuspended)
{ {
DPRINT("Not creating suspended\n"); DPRINT("Not creating suspended\n");
PsResumeThread(Thread); PsUnblockThread(Thread, NULL);
}
else
{
KeBugCheck(0);
} }
DPRINT("Thread %x\n", Thread);
DPRINT("ObGetReferenceCount(Thread) %d ObGetHandleCount(Thread) %x\n",
ObGetReferenceCount(Thread), ObGetHandleCount(Thread));
DPRINT("Finished PsCreateThread()\n");
return(STATUS_SUCCESS); return(STATUS_SUCCESS);
} }
NTSTATUS STDCALL PsCreateSystemThread(PHANDLE ThreadHandle, NTSTATUS STDCALL
ACCESS_MASK DesiredAccess, PsCreateSystemThread(PHANDLE ThreadHandle,
POBJECT_ATTRIBUTES ObjectAttributes, ACCESS_MASK DesiredAccess,
HANDLE ProcessHandle, POBJECT_ATTRIBUTES ObjectAttributes,
PCLIENT_ID ClientId, HANDLE ProcessHandle,
PKSTART_ROUTINE StartRoutine, PCLIENT_ID ClientId,
PVOID StartContext) PKSTART_ROUTINE StartRoutine,
PVOID StartContext)
/* /*
* FUNCTION: Creates a thread which executes in kernel mode * FUNCTION: Creates a thread which executes in kernel mode
* ARGUMENTS: * ARGUMENTS:
@ -660,7 +662,7 @@ NTSTATUS STDCALL PsCreateSystemThread(PHANDLE ThreadHandle,
*ClientId=Thread->Cid; *ClientId=Thread->Cid;
} }
PsResumeThread(Thread); PsUnblockThread(Thread, NULL);
return(STATUS_SUCCESS); return(STATUS_SUCCESS);
} }

View file

@ -1,4 +1,4 @@
/* $Id: process.c,v 1.54 2000/10/22 16:36:53 ekohl Exp $ /* $Id: process.c,v 1.55 2001/01/21 14:54:29 dwelch Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -315,14 +315,15 @@ PEPROCESS STDCALL IoGetCurrentProcess(VOID)
return(PsGetCurrentProcess()); return(PsGetCurrentProcess());
} }
NTSTATUS STDCALL NtCreateProcess (OUT PHANDLE ProcessHandle, NTSTATUS STDCALL
IN ACCESS_MASK DesiredAccess, NtCreateProcess (OUT PHANDLE ProcessHandle,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN ACCESS_MASK DesiredAccess,
IN HANDLE ParentProcessHandle, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN BOOLEAN InheritObjectTable, IN HANDLE ParentProcessHandle,
IN HANDLE SectionHandle OPTIONAL, IN BOOLEAN InheritObjectTable,
IN HANDLE DebugPortHandle OPTIONAL, IN HANDLE SectionHandle OPTIONAL,
IN HANDLE ExceptionPortHandle OPTIONAL) IN HANDLE DebugPortHandle OPTIONAL,
IN HANDLE ExceptionPortHandle OPTIONAL)
/* /*
* FUNCTION: Creates a process. * FUNCTION: Creates a process.
* ARGUMENTS: * ARGUMENTS:

View file

@ -1,4 +1,4 @@
/* $Id: suspend.c,v 1.1 2001/01/19 15:09:01 dwelch Exp $ /* $Id: suspend.c,v 1.2 2001/01/21 14:54:30 dwelch Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -19,36 +19,12 @@
#define NDEBUG #define NDEBUG
#include <internal/debug.h> #include <internal/debug.h>
/* GLOBALS *******************************************************************/ /* NOTES **********************************************************************
*
extern KSPIN_LOCK PiThreadListLock; */
VOID PsInsertIntoThreadList(KPRIORITY Priority, PETHREAD Thread);
/* FUNCTIONS *****************************************************************/ /* FUNCTIONS *****************************************************************/
#if 1
ULONG PsResumeThread(PETHREAD Thread)
{
KIRQL oldIrql;
ULONG SuspendCount;
KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
if (Thread->Tcb.SuspendCount > 0)
{
Thread->Tcb.SuspendCount--;
SuspendCount = Thread->Tcb.SuspendCount;
Thread->Tcb.State = THREAD_STATE_RUNNABLE;
PsInsertIntoThreadList(Thread->Tcb.Priority, Thread);
}
KeReleaseSpinLock(&PiThreadListLock, oldIrql);
return SuspendCount;
}
#endif
#if 0
VOID VOID
PiSuspendThreadRundownRoutine(PKAPC Apc) PiSuspendThreadRundownRoutine(PKAPC Apc)
{ {
@ -62,8 +38,7 @@ PiSuspendThreadKernelRoutine(PKAPC Apc,
PVOID* SystemArgument1, PVOID* SystemArgument1,
PVOID* SystemArguemnt2) PVOID* SystemArguemnt2)
{ {
InterlockedIncrement(&PsGetCurrentThread()->Tcb.SuspendThread); KeWaitForSingleObject(&PsGetCurrentThread()->Tcb.SuspendSemaphore,
KeWaitForSingleObject((PVOID)&PsGetCurrentThread()->SuspendSemaphore,
0, 0,
UserMode, UserMode,
TRUE, TRUE,
@ -72,21 +47,45 @@ PiSuspendThreadKernelRoutine(PKAPC Apc,
} }
NTSTATUS NTSTATUS
PsSuspendThread(PETHREAD Thread, PULONG SuspendCount) PsResumeThread(PETHREAD Thread, PULONG SuspendCount)
{
KeReleaseSemaphore(&Thread->Tcb.SuspendSemaphore, IO_NO_INCREMENT, 1, FALSE);
return(STATUS_SUCCESS);
}
NTSTATUS
PsSuspendThread(PETHREAD Thread, PULONG PreviousSuspendCount)
{ {
PKAPC Apc; PKAPC Apc;
NTSTATUS Status;
/*
* If we are suspending ourselves then we can cut out the work in
* sending an APC
*/
if (Thread == PsGetCurrentThread())
{
Status = KeWaitForSingleObject(&Thread->Tcb.SuspendSemaphore,
0,
UserMode,
FALSE,
NULL);
if (!NT_SUCCESS(Status))
{
return(Status);
}
return(Status);
}
Apc = ExAllocatePool(NonPagedPool, sizeof(KAPC)); Apc = ExAllocatePool(NonPagedPool, sizeof(KAPC));
if (Apc == NULL) if (Apc == NULL)
{ {
return(STATUS_NO_MORE_MEMORY); return(STATUS_NO_MEMORY);
} }
*SuspendCount = Thread->Tcb.SuspendCount;
KeInitializeApc(Apc, KeInitializeApc(Apc,
&Thread->Tcb, &Thread->Tcb,
NULL, 0,
PiSuspendThreadKernelRoutine, PiSuspendThreadKernelRoutine,
PiSuspendThreadRundownRoutine, PiSuspendThreadRundownRoutine,
NULL, NULL,
@ -98,33 +97,89 @@ PsSuspendThread(PETHREAD Thread, PULONG SuspendCount)
0); 0);
return(STATUS_SUCCESS); return(STATUS_SUCCESS);
} }
#endif
#if 1 NTSTATUS STDCALL
ULONG NtResumeThread (IN HANDLE ThreadHandle,
PsSuspendThread(PETHREAD Thread) IN PULONG SuspendCount)
/*
* FUNCTION: Decrements a thread's resume count
* ARGUMENTS:
* ThreadHandle = Handle to the thread that should be resumed
* ResumeCount = The resulting resume count.
* RETURNS: Status
*/
{ {
KIRQL oldIrql; PETHREAD Thread;
ULONG PreviousSuspendCount; NTSTATUS Status;
ULONG Count;
KeAcquireSpinLock(&PiThreadListLock, &oldIrql); Status = ObReferenceObjectByHandle(ThreadHandle,
THREAD_SUSPEND_RESUME,
PreviousSuspendCount = Thread->Tcb.SuspendCount; PsThreadType,
if (Thread->Tcb.SuspendCount < MAXIMUM_SUSPEND_COUNT) UserMode,
(PVOID*)&Thread,
NULL);
if (!NT_SUCCESS(Status))
{ {
Thread->Tcb.SuspendCount++; return(Status);
} }
if (PsGetCurrentThread() == Thread) Status = PsResumeThread(Thread, &Count);
if (SuspendCount != NULL)
{ {
DbgPrint("Cannot suspend self\n"); *SuspendCount = Count;
KeBugCheck(0);
} }
Thread->Tcb.State = THREAD_STATE_SUSPENDED; ObDereferenceObject((PVOID)Thread);
KeReleaseSpinLock(&PiThreadListLock, oldIrql); return STATUS_SUCCESS;
return PreviousSuspendCount;
} }
#endif
NTSTATUS STDCALL
NtSuspendThread (IN HANDLE ThreadHandle,
IN PULONG PreviousSuspendCount)
/*
* FUNCTION: Increments a thread's suspend count
* ARGUMENTS:
* ThreadHandle = Handle to the thread that should be resumed
* PreviousSuspendCount = The resulting/previous suspend count.
* REMARK:
* A thread will be suspended if its suspend count is greater than 0.
* This procedure maps to the win32 SuspendThread function. (
* documentation about the the suspend count can be found here aswell )
* The suspend count is not increased if it is greater than
* MAXIMUM_SUSPEND_COUNT.
* RETURNS: Status
*/
{
PETHREAD Thread;
NTSTATUS Status;
ULONG Count;
Status = ObReferenceObjectByHandle(ThreadHandle,
THREAD_SUSPEND_RESUME,
PsThreadType,
UserMode,
(PVOID*)&Thread,
NULL);
if (!NT_SUCCESS(Status))
{
return(Status);
}
Status = PsSuspendThread(Thread, &Count);
if (PreviousSuspendCount != NULL)
{
*PreviousSuspendCount = Count;
}
ObDereferenceObject((PVOID)Thread);
return STATUS_SUCCESS;
}

View file

@ -1,4 +1,4 @@
/* $Id: thread.c,v 1.66 2001/01/19 15:09:01 dwelch Exp $ /* $Id: thread.c,v 1.67 2001/01/21 14:54:30 dwelch Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -386,91 +386,6 @@ NtOpenThread(OUT PHANDLE ThreadHandle,
UNIMPLEMENTED; UNIMPLEMENTED;
} }
NTSTATUS STDCALL
NtResumeThread (IN HANDLE ThreadHandle,
IN PULONG SuspendCount)
/*
* FUNCTION: Decrements a thread's resume count
* ARGUMENTS:
* ThreadHandle = Handle to the thread that should be resumed
* ResumeCount = The resulting resume count.
* REMARK:
* A thread is resumed if its suspend count is 0. This procedure maps to
* the win32 ResumeThread function. ( documentation about the the suspend
* count can be found here aswell )
* RETURNS: Status
*/
{
PETHREAD Thread;
NTSTATUS Status;
ULONG Count;
Status = ObReferenceObjectByHandle(ThreadHandle,
THREAD_SUSPEND_RESUME,
PsThreadType,
UserMode,
(PVOID*)&Thread,
NULL);
if (!NT_SUCCESS(Status))
{
return(Status);
}
Count = PsResumeThread(Thread);
if (SuspendCount != NULL)
{
*SuspendCount = Count;
}
ObDereferenceObject((PVOID)Thread);
return STATUS_SUCCESS;
}
NTSTATUS STDCALL
NtSuspendThread (IN HANDLE ThreadHandle,
IN PULONG PreviousSuspendCount)
/*
* FUNCTION: Increments a thread's suspend count
* ARGUMENTS:
* ThreadHandle = Handle to the thread that should be resumed
* PreviousSuspendCount = The resulting/previous suspend count.
* REMARK:
* A thread will be suspended if its suspend count is greater than 0.
* This procedure maps to the win32 SuspendThread function. (
* documentation about the the suspend count can be found here aswell )
* The suspend count is not increased if it is greater than
* MAXIMUM_SUSPEND_COUNT.
* RETURNS: Status
*/
{
PETHREAD Thread;
NTSTATUS Status;
ULONG Count;
Status = ObReferenceObjectByHandle(ThreadHandle,
THREAD_SUSPEND_RESUME,
PsThreadType,
UserMode,
(PVOID*)&Thread,
NULL);
if (!NT_SUCCESS(Status))
{
return(Status);
}
Count = PsSuspendThread(Thread);
if (PreviousSuspendCount != NULL)
{
*PreviousSuspendCount = Count;
}
ObDereferenceObject((PVOID)Thread);
return STATUS_SUCCESS;
}
NTSTATUS STDCALL NTSTATUS STDCALL
NtCallbackReturn (PVOID Result, NtCallbackReturn (PVOID Result,
ULONG ResultLength, ULONG ResultLength,

View file

@ -17,14 +17,14 @@
/* FUNCTIONS *****************************************************************/ /* FUNCTIONS *****************************************************************/
NTSTATUS STDCALL NtSetInformationThread(HANDLE ThreadHandle, NTSTATUS STDCALL
THREADINFOCLASS ThreadInformationClass, NtSetInformationThread(HANDLE ThreadHandle,
PVOID ThreadInformation, THREADINFOCLASS ThreadInformationClass,
ULONG ThreadInformationLength) PVOID ThreadInformation,
ULONG ThreadInformationLength)
{ {
PETHREAD Thread; PETHREAD Thread;
NTSTATUS Status; NTSTATUS Status;
PTHREAD_BASIC_INFORMATION ThreadBasicInformationP;
Status = ObReferenceObjectByHandle(ThreadHandle, Status = ObReferenceObjectByHandle(ThreadHandle,
THREAD_SET_INFORMATION, THREAD_SET_INFORMATION,
@ -40,72 +40,110 @@ NTSTATUS STDCALL NtSetInformationThread(HANDLE ThreadHandle,
switch (ThreadInformationClass) switch (ThreadInformationClass)
{ {
case ThreadBasicInformation: case ThreadBasicInformation:
ThreadBasicInformationP = /* Can only be queried */
(PTHREAD_BASIC_INFORMATION) ThreadInformation; Status = STATUS_INVALID_INFO_CLASS;
ThreadBasicInformationP->ExitStatus =
Thread->ExitStatus;
ThreadBasicInformationP->TebBaseAddress =
Thread->Tcb.Teb;
ThreadBasicInformationP->AffinityMask =
Thread->Tcb.Affinity;
ThreadBasicInformationP->BasePriority =
Thread->Tcb.BasePriority;
ThreadBasicInformationP->UniqueThreadId =
(ULONG) Thread->Cid.UniqueThread;
Status = STATUS_SUCCESS;
break; break;
case ThreadTimes: case ThreadTimes:
/* Can only be queried */
Status = STATUS_INVALID_INFO_CLASS;
break; break;
case ThreadPriority: case ThreadPriority:
{ {
KPRIORITY Priority; KPRIORITY Priority;
Priority = *(KPRIORITY*)ThreadInformation; if (ThreadInformationLength != sizeof(KPRIORITY))
if (Priority < LOW_PRIORITY || Priority >= MAXIMUM_PRIORITY) {
{ Status = STATUS_INFO_LENGTH_MISMATCH;
Status = STATUS_INVALID_PARAMETER; break;
break; }
} Priority = *(KPRIORITY*)ThreadInformation;
KeSetPriorityThread(&Thread->Tcb, Priority); if (Priority < LOW_PRIORITY || Priority >= MAXIMUM_PRIORITY)
Status = STATUS_SUCCESS; {
break; Status = STATUS_INVALID_PARAMETER;
break;
}
KeSetPriorityThread(&Thread->Tcb, Priority);
Status = STATUS_SUCCESS;
break;
} }
case ThreadBasePriority: case ThreadBasePriority:
Status = STATUS_NOT_IMPLEMENTED;
break; break;
case ThreadAffinityMask: case ThreadAffinityMask:
Status = STATUS_NOT_IMPLEMENTED;
break; break;
case ThreadImpersonationToken: case ThreadImpersonationToken:
Status = PsAssignImpersonationToken(Thread, {
*((PHANDLE)ThreadInformation)); HANDLE TokenHandle;
break;
if (ThreadInformationLength != sizeof(HANDLE))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
TokenHandle = *((PHANDLE)ThreadInformation);
Status = PsAssignImpersonationToken(Thread, TokenHandle);
break;
}
case ThreadDescriptorTableEntry: case ThreadDescriptorTableEntry:
UNIMPLEMENTED; /* Can only be queried */
Status = STATUS_INVALID_INFO_CLASS;
break; break;
case ThreadEventPair: case ThreadEventPair:
UNIMPLEMENTED; Status = STATUS_NOT_IMPLEMENTED;
break; break;
case ThreadQuerySetWin32StartAddress: case ThreadQuerySetWin32StartAddress:
if (ThreadInformationLength != sizeof(ULONG))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
Thread->u2.Win32StartAddress = (PVOID)*((PULONG)ThreadInformation);
Status = STATUS_SUCCESS;
break; break;
case ThreadZeroTlsCell: case ThreadZeroTlsCell:
Status = STATUS_NOT_IMPLEMENTED;
break; break;
case ThreadPerformanceCount: case ThreadPerformanceCount:
/* Can only be queried */
Status = STATUS_INVALID_INFO_CLASS;
break; break;
case ThreadAmILastThread: case ThreadAmILastThread:
/* Can only be queried */
Status = STATUS_INVALID_INFO_CLASS;
break; break;
case ThreadPriorityBoost: case ThreadIdealProcessor:
break; Status = STATUS_NOT_IMPLEMENTED;
break;
case ThreadPriorityBoost:
Status = STATUS_NOT_IMPLEMENTED;
break;
case ThreadSetTlsArrayAddress:
Status = STATUS_NOT_IMPLEMENTED;
break;
case ThreadIsIoPending:
/* Can only be queried */
Status = STATUS_INVALID_INFO_CLASS;
break;
case ThreadHideFromDebugger:
Status = STATUS_NOT_IMPLEMENTED;
break;
default: default:
Status = STATUS_UNSUCCESSFUL; Status = STATUS_UNSUCCESSFUL;
@ -116,12 +154,11 @@ NTSTATUS STDCALL NtSetInformationThread(HANDLE ThreadHandle,
NTSTATUS STDCALL NTSTATUS STDCALL
NtQueryInformationThread ( NtQueryInformationThread (IN HANDLE ThreadHandle,
IN HANDLE ThreadHandle, IN THREADINFOCLASS ThreadInformationClass,
IN THREADINFOCLASS ThreadInformationClass, OUT PVOID ThreadInformation,
OUT PVOID ThreadInformation, IN ULONG ThreadInformationLength,
IN ULONG ThreadInformationLength, OUT PULONG ReturnLength)
OUT PULONG ReturnLength)
{ {
PETHREAD Thread; PETHREAD Thread;
NTSTATUS Status; NTSTATUS Status;
@ -139,60 +176,141 @@ NtQueryInformationThread (
switch (ThreadInformationClass) switch (ThreadInformationClass)
{ {
case ThreadBasicInformation: case ThreadBasicInformation:
break; {
PTHREAD_BASIC_INFORMATION TBI;
case ThreadTimes: TBI = (PTHREAD_BASIC_INFORMATION)ThreadInformation;
break;
case ThreadPriority: if (ThreadInformationLength != sizeof(THREAD_BASIC_INFORMATION))
break; {
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
case ThreadBasePriority: TBI->ExitStatus = Thread->ExitStatus;
break; TBI->TebBaseAddress = Thread->Tcb.Teb;
TBI->ClientId = Thread->Cid;
TBI->AffinityMask = Thread->Tcb.Affinity;
TBI->Priority = Thread->Tcb.Priority;
TBI->BasePriority = Thread->Tcb.BasePriority;
Status = STATUS_SUCCESS;
break;
}
case ThreadAffinityMask: case ThreadTimes:
break; Status = STATUS_NOT_IMPLEMENTED;
break;
case ThreadImpersonationToken: case ThreadPriority:
break; /* Can be set only */
Status = STATUS_INVALID_INFO_CLASS;
break;
case ThreadDescriptorTableEntry: case ThreadBasePriority:
UNIMPLEMENTED; /* Can be set only */
break; Status = STATUS_INVALID_INFO_CLASS;
break;
case ThreadEventPair: case ThreadAffinityMask:
UNIMPLEMENTED; /* Can be set only */
break; Status = STATUS_INVALID_INFO_CLASS;
break;
case ThreadQuerySetWin32StartAddress: case ThreadImpersonationToken:
break; /* Can be set only */
Status = STATUS_INVALID_INFO_CLASS;
break;
case ThreadZeroTlsCell: case ThreadDescriptorTableEntry:
break; /* Nebbett says nothing about this */
Status = STATUS_NOT_IMPLEMENTED;
break;
case ThreadPerformanceCount: case ThreadEnableAlignmentFaultFixup:
break; /* Can be set only */
Status = STATUS_INVALID_INFO_CLASS;
break;
case ThreadAmILastThread: case ThreadEventPair:
{ /* Can be set only */
BOOLEAN *LastThread; Status = STATUS_INVALID_INFO_CLASS;
PLIST_ENTRY Entry; break;
LastThread = (PBOOLEAN) ThreadInformation; case ThreadQuerySetWin32StartAddress:
Entry = &(Thread->ThreadsProcess->ThreadListHead); if (ThreadInformationLength != sizeof(PVOID))
*LastThread = (Entry->Flink->Flink == Entry)?TRUE:FALSE; {
} Status = STATUS_INFO_LENGTH_MISMATCH;
break; break;
}
*((PVOID*)ThreadInformation) = Thread->u2.Win32StartAddress;
Status = STATUS_SUCCESS;
break;
case ThreadPriorityBoost: case ThreadZeroTlsCell:
break; /* Can only be set */
Status = STATUS_INVALID_INFO_CLASS;
break;
case ThreadPerformanceCount:
/* Nebbett says this class is always zero */
if (ThreadInformationLength != sizeof(LARGE_INTEGER))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
((PLARGE_INTEGER)ThreadInformation)->QuadPart = 0;
Status = STATUS_SUCCESS;
break;
case ThreadAmILastThread:
{
if (ThreadInformationLength != sizeof(BOOLEAN))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
}
if (Thread->ThreadsProcess->ThreadListHead.Flink->Flink ==
&Thread->ThreadsProcess->ThreadListHead)
{
*((PBOOLEAN)ThreadInformation) = TRUE;
}
else
{
*((PBOOLEAN)ThreadInformation) = FALSE;
}
Status = STATUS_SUCCESS;
break;
}
case ThreadIdealProcessor:
/* Can only be set */
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
case ThreadPriorityBoost:
Status = STATUS_NOT_IMPLEMENTED;
break;
case ThreadSetTlsArrayAddress:
/* Can only be set */
Status = STATUS_INVALID_INFO_CLASS;
break;
case ThreadIsIoPending:
Status = STATUS_NOT_IMPLEMENTED;
break;
case ThreadHideFromDebugger:
/* Can only be set */
Status = STATUS_INVALID_INFO_CLASS;
break;
default: default:
Status = STATUS_UNSUCCESSFUL; Status = STATUS_INVALID_INFO_CLASS;
} }
ObDereferenceObject(Thread); ObDereferenceObject(Thread);
return Status; return(Status);
} }
VOID KeSetPreviousMode(ULONG Mode) VOID KeSetPreviousMode(ULONG Mode)
@ -203,15 +321,12 @@ VOID KeSetPreviousMode(ULONG Mode)
ULONG STDCALL ULONG STDCALL
KeGetPreviousMode (VOID) KeGetPreviousMode (VOID)
{ {
/* CurrentThread is in ntoskrnl/ps/thread.c */
return (ULONG)PsGetCurrentThread()->Tcb.PreviousMode; return (ULONG)PsGetCurrentThread()->Tcb.PreviousMode;
} }
ULONG STDCALL ULONG STDCALL
ExGetPreviousMode (VOID) ExGetPreviousMode (VOID)
{ {
/* CurrentThread is in ntoskrnl/ps/thread.c */
return (ULONG)PsGetCurrentThread()->Tcb.PreviousMode; return (ULONG)PsGetCurrentThread()->Tcb.PreviousMode;
} }