#include <windows.h>
#include <ddk/ntddk.h>
#include <internal/ke.h>
-#include <internal/objmgr.h>
+#include <internal/ob.h>
+#include <string.h>
#include <internal/string.h>
#include <internal/hal.h>
-#include <internal/psmgr.h>
+#include <internal/ps.h>
+#include <internal/ob.h>
#define NDEBUG
#include <internal/debug.h>
/* GLOBALS ******************************************************************/
-OBJECT_TYPE ThreadObjectType = {{NULL,0,0},
- 0,
- 0,
- ULONG_MAX,
- ULONG_MAX,
- sizeof(ETHREAD),
- 0,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- };
-
-#define NR_THREAD_PRIORITY_LEVELS (32)
+POBJECT_TYPE PsThreadType = NULL;
-static KSPIN_LOCK ThreadListLock = {0,};
+#define NR_THREAD_PRIORITY_LEVELS (31)
+#define THREAD_PRIORITY_MAX (15)
-/*
- * PURPOSE: List of all threads currently active
- */
-static LIST_ENTRY ThreadListHead = {NULL,NULL};
+static KSPIN_LOCK ThreadListLock = {0,};
/*
* PURPOSE: List of threads associated with each priority level
*/
static LIST_ENTRY PriorityListHead[NR_THREAD_PRIORITY_LEVELS]={{NULL,NULL},};
static BOOLEAN DoneInitYet = FALSE;
+ULONG PiNrThreads = 0;
+ULONG PiNrRunnableThreads = 0;
static PETHREAD CurrentThread = NULL;
-static ULONG NextThreadUniqueId = 0;
+static ULONG NextUniqueThreadId = 0;
/* FUNCTIONS ***************************************************************/
-NTSTATUS ZwSetInformationThread(HANDLE ThreadHandle,
- THREADINFOCLASS ThreadInformationClass,
- PVOID ThreadInformation,
- ULONG ThreadInformationLength)
+PKTHREAD KeGetCurrentThread(VOID)
{
- UNIMPLEMENTED;
+ return(&(CurrentThread->Tcb));
}
-PKTHREAD KeGetCurrentThread(VOID)
+PETHREAD PsGetCurrentThread(VOID)
{
- return((PKTHREAD)CurrentThread);
+ return(CurrentThread);
}
-PETHREAD PsGetCurrentThread(VOID)
+VOID PiTerminateProcessThreads(PEPROCESS Process, NTSTATUS ExitStatus)
{
- return((PETHREAD)KeGetCurrentThread());
+ KIRQL oldlvl;
+ PLIST_ENTRY current_entry;
+ PETHREAD current;
+ ULONG i;
+
+ KeAcquireSpinLock(&ThreadListLock, &oldlvl);
+
+ for (i=0; i<NR_THREAD_PRIORITY_LEVELS; i++)
+ {
+ current_entry = PriorityListHead[i].Flink;
+ while (current_entry != &PriorityListHead[i])
+ {
+ current = CONTAINING_RECORD(current_entry,ETHREAD,Tcb.Entry);
+ if (current->ThreadsProcess == Process &&
+ current != PsGetCurrentThread())
+ {
+ PsTerminateOtherThread(current, ExitStatus);
+ }
+ current_entry = current_entry->Flink;
+ }
+ }
+
+ KeReleaseSpinLock(&ThreadListLock, oldlvl);
}
-#if CAN_WE_DARE_TO_TRY_THIS
-void PsDispatchThread(void)
+static VOID PsInsertIntoThreadList(KPRIORITY Priority, PETHREAD Thread)
{
- int i;
+ KIRQL oldlvl;
- for (i=0; i<NR_THREAD_PRIORITY_LEVELS; i++)
+ DPRINT("PsInsertIntoThreadList(Priority %x, Thread %x)\n",Priority,
+ Thread);
+
+ KeAcquireSpinLock(&ThreadListLock,&oldlvl);
+ InsertTailList(&PriorityListHead[THREAD_PRIORITY_MAX+Priority],
+ &Thread->Tcb.Entry);
+ KeReleaseSpinLock(&ThreadListLock,oldlvl);
+}
+
+VOID PsBeginThread(PKSTART_ROUTINE StartRoutine, PVOID StartContext)
+{
+ NTSTATUS Ret;
+
+ KeReleaseSpinLock(&ThreadListLock,PASSIVE_LEVEL);
+ Ret = StartRoutine(StartContext);
+ PsTerminateSystemThread(Ret);
+ KeBugCheck(0);
+}
+
+static PETHREAD PsScanThreadList(KPRIORITY Priority)
+{
+ PLIST_ENTRY current_entry;
+ PETHREAD current;
+ PETHREAD oldest = NULL;
+ ULONG oldest_time = 0;
+
+// DPRINT("PsScanThreadList(Priority %d)\n",Priority);
+
+ current_entry = PriorityListHead[THREAD_PRIORITY_MAX+Priority].Flink;
+ while (current_entry != &PriorityListHead[THREAD_PRIORITY_MAX+Priority])
{
- if (PsDispatchSpecificPriorityThread(i))
+ current = CONTAINING_RECORD(current_entry,ETHREAD,Tcb.Entry);
+
+ if (current->Tcb.ThreadState == THREAD_STATE_TERMINATED &&
+ current != CurrentThread)
{
- return;
+ PsReleaseThread(current);
}
+
+ if (current->Tcb.ThreadState == THREAD_STATE_RUNNABLE)
+ {
+ if (oldest == NULL || oldest_time > current->Tcb.LastTick)
+ {
+ oldest = current;
+ oldest_time = current->Tcb.LastTick;
+ }
+ }
+ current_entry = current_entry->Flink;
}
+// DPRINT("PsScanThreadList() = %x\n",oldest);
+ return(oldest);
}
-#endif
-void PsDispatchThread(void)
-/*
- * FUNCTION: Chooses a thread, possibly the current one if it is runnable
- * and dispatches it
- */
+VOID PsDispatchThread(VOID)
{
+ KPRIORITY CurrentPriority;
+ PETHREAD Candidate;
KIRQL irql;
- PLIST_ENTRY current_entry;
- PKTHREAD current;
+ LARGE_INTEGER TickCount;
+
+ KeAcquireSpinLock(&ThreadListLock,&irql);
if (!DoneInitYet)
{
}
DPRINT("PsDispatchThread() Current %x\n",CurrentThread);
-
- /*
- * Bump overselves up to a higher IRQ level during this
- */
- KeAcquireSpinLock(&ThreadListLock,&irql);
-
- /*
- * If this was an involuntary reschedule then the current thread will still
- * be eligible to run later
- */
+
if (CurrentThread->Tcb.ThreadState==THREAD_STATE_RUNNING)
{
CurrentThread->Tcb.ThreadState=THREAD_STATE_RUNNABLE;
}
- /*
- * Simple round robin algorithm, iterate through and dispatch the first
- * runnable thread
- */
- current = CONTAINING_RECORD(ThreadListHead.Flink,KTHREAD,Entry);
- current_entry = ThreadListHead.Flink;
-
- while (current_entry!=(&ThreadListHead))
+ for (CurrentPriority=THREAD_PRIORITY_TIME_CRITICAL;
+ CurrentPriority>=THREAD_PRIORITY_IDLE;
+ CurrentPriority--)
{
- DPRINT("Scanning %x ",current);
- DPRINT("State %x Runnable %x\n",current->ThreadState,
- THREAD_STATE_RUNNABLE);
- if (current->ThreadState == THREAD_STATE_RUNNABLE &&
- current != (PKTHREAD)CurrentThread)
- {
- DPRINT("Scheduling this one %x\n",current);
- CurrentThread = current;
+ Candidate = PsScanThreadList(CurrentPriority);
+ if (Candidate == CurrentThread)
+ {
+ DPRINT("Scheduling current thread\n");
+ KeQueryTickCount(&TickCount);
+ CurrentThread->Tcb.LastTick = TickCount.LowPart;
CurrentThread->Tcb.ThreadState = THREAD_STATE_RUNNING;
KeReleaseSpinLock(&ThreadListLock,irql);
- HalTaskSwitch(current);
return;
}
- current_entry = current->Entry.Flink;
- current = CONTAINING_RECORD(current_entry,KTHREAD,Entry);
- }
-
- /*
- * If there are no other threads then continue with the current one if
- * possible
- */
- if (CurrentThread->Tcb.ThreadState == THREAD_STATE_RUNNABLE)
- {
- return;
+ if (Candidate != NULL)
+ {
+ DPRINT("Scheduling %x\n",Candidate);
+
+ Candidate->Tcb.ThreadState = THREAD_STATE_RUNNING;
+
+ KeQueryTickCount(&TickCount);
+ CurrentThread->Tcb.LastTick = TickCount.LowPart;
+
+ CurrentThread = Candidate;
+
+ HalTaskSwitch(&CurrentThread->Tcb);
+ KeReleaseSpinLock(&ThreadListLock,irql);
+ return;
+ }
}
-
- /*
- * Disaster
- */
- printk("Out of threads at %s:%d\n",__FILE__,__LINE__);
- for(;;);
+ DbgPrint("CRITICAL: No threads are runnable\n");
+ KeBugCheck(0);
}
-void PsInitThreadManagment(void)
-/*
- * FUNCTION: Initialize thread managment
- */
+NTSTATUS PsInitializeThread(HANDLE ProcessHandle,
+ PETHREAD* ThreadPtr,
+ PHANDLE ThreadHandle,
+ ACCESS_MASK DesiredAccess,
+ POBJECT_ATTRIBUTES ThreadAttributes)
{
- PETHREAD first_thread;
+ PETHREAD Thread;
+ NTSTATUS Status;
- InitializeListHead(&ThreadListHead);
- KeInitializeSpinLock(&ThreadListLock);
+ PiNrThreads++;
- ObRegisterType(OBJTYP_THREAD,&ThreadObjectType);
+ Thread = ObCreateObject(ThreadHandle,
+ DesiredAccess,
+ ThreadAttributes,
+ PsThreadType);
+ DPRINT("Thread = %x\n",Thread);
+ Thread->Tcb.LastTick = 0;
+ Thread->Tcb.ThreadState=THREAD_STATE_SUSPENDED;
+ Thread->Tcb.BasePriority=THREAD_PRIORITY_NORMAL;
+ Thread->Tcb.CurrentPriority=THREAD_PRIORITY_NORMAL;
+ Thread->Tcb.ApcList=ExAllocatePool(NonPagedPool,sizeof(LIST_ENTRY));
+ Thread->Tcb.SuspendCount = 1;
+ if (ProcessHandle != NULL)
+ {
+ Status = ObReferenceObjectByHandle(ProcessHandle,
+ PROCESS_CREATE_THREAD,
+ PsProcessType,
+ UserMode,
+ (PVOID*)&Thread->ThreadsProcess,
+ NULL);
+ if (Status != STATUS_SUCCESS)
+ {
+ DPRINT("Failed at %s:%d\n",__FILE__,__LINE__);
+ return(Status);
+ }
+ }
+ else
+ {
+ Thread->ThreadsProcess = SystemProcess;
+ ObReferenceObjectByPointer(Thread->ThreadsProcess,
+ PROCESS_CREATE_THREAD,
+ PsProcessType,
+ UserMode);
+ }
+ ObReferenceObjectByPointer(Thread->ThreadsProcess,
+ PROCESS_CREATE_THREAD,
+ PsProcessType,
+ UserMode);
+ InitializeListHead(Thread->Tcb.ApcList);
+ InitializeListHead(&(Thread->IrpList));
+ Thread->Cid.UniqueThread = (HANDLE)InterlockedIncrement(
+ &NextUniqueThreadId);
+ Thread->Cid.UniqueProcess = (HANDLE)Thread->ThreadsProcess->UniqueProcessId;
+ DbgPrint("Thread->Cid.UniqueThread %d\nThread->Cid.UniqueProcess %d\n",
+ Thread->Cid.UniqueThread, Thread->Cid.UniqueThread);
+ ObReferenceObjectByPointer(Thread,
+ THREAD_ALL_ACCESS,
+ PsThreadType,
+ UserMode);
+ PsInsertIntoThreadList(Thread->Tcb.CurrentPriority,Thread);
- first_thread = ExAllocatePool(NonPagedPool,sizeof(ETHREAD));
- first_thread->Tcb.ThreadState = THREAD_STATE_RUNNING;
- HalInitFirstTask((PKTHREAD)first_thread);
- ExInterlockedInsertHeadList(&ThreadListHead,&first_thread->Tcb.Entry,
- &ThreadListLock);
- CurrentThread = first_thread;
+ *ThreadPtr = Thread;
- DoneInitYet = TRUE;
+ ObDereferenceObject(Thread->ThreadsProcess);
+ return(STATUS_SUCCESS);
}
-NTSTATUS PsWakeThread(PETHREAD Thread)
+VOID PsResumeThread(PETHREAD Thread)
{
- Thread->Tcb.ThreadState = THREAD_STATE_RUNNABLE;
- return(STATUS_SUCCESS);
+ DPRINT("PsResumeThread(Thread %x)\n",Thread);
+ Thread->Tcb.SuspendCount--;
+ if (Thread->Tcb.SuspendCount <= 0 &&
+ Thread->Tcb.ThreadState != THREAD_STATE_RUNNING)
+ {
+ DPRINT("Setting thread to runnable\n");
+ Thread->Tcb.ThreadState = THREAD_STATE_RUNNABLE;
+ }
+ DPRINT("Finished PsResumeThread()\n");
}
-NTSTATUS PsSuspendThread(VOID)
-/*
- * FUNCTION: Suspend the current thread
- */
+VOID PsSuspendThread(PETHREAD Thread)
{
- KIRQL oldlvl;
-
- DPRINT("suspending %x\n",CurrentThread);
-
- /*
- * NOTE: When we return from PsDispatchThread the spinlock will be
- * released
- */
- CurrentThread->Tcb.ThreadState = THREAD_STATE_SUSPENDED;
- PsDispatchThread();
- return(STATUS_SUCCESS);
+ DPRINT("PsSuspendThread(Thread %x)\n",Thread);
+ Thread->Tcb.SuspendCount++;
+ if (Thread->Tcb.SuspendCount > 0)
+ {
+ Thread->Tcb.ThreadState = THREAD_STATE_SUSPENDED;
+ if (Thread == CurrentThread)
+ {
+ PsDispatchThread();
+ }
+ }
}
+VOID PiDeleteThread(PVOID ObjectBody)
+{
+ DbgPrint("PiDeleteThread(ObjectBody %x)\n",ObjectBody);
+}
-
-NTSTATUS PsTerminateSystemThread(NTSTATUS ExitStatus)
+VOID PsInitThreadManagment(VOID)
/*
- * FUNCTION: Terminates the current thread
- * ARGUMENTS:
- * ExitStatus = Status to pass to the creater
- * RETURNS: Doesn't
+ * FUNCTION: Initialize thread managment
*/
{
- KIRQL oldlvl;
+ PETHREAD FirstThread;
+ ULONG i;
+ ANSI_STRING AnsiString;
+ HANDLE FirstThreadHandle;
- DPRINT("terminating %x\n",CurrentThread);
- KeRaiseIrql(DISPATCH_LEVEL,&oldlvl);
- CurrentThread->Tcb.ThreadState = THREAD_STATE_TERMINATED;
- RemoveEntryList(&CurrentThread->Tcb.Entry);
- PsDispatchThread();
- for(;;);
+ KeInitializeSpinLock(&ThreadListLock);
+ for (i=0; i<NR_THREAD_PRIORITY_LEVELS; i++)
+ {
+ InitializeListHead(&PriorityListHead[i]);
+ }
+
+ PsThreadType = ExAllocatePool(NonPagedPool,sizeof(OBJECT_TYPE));
+
+ RtlInitAnsiString(&AnsiString,"Thread");
+ RtlAnsiStringToUnicodeString(&PsThreadType->TypeName,&AnsiString,TRUE);
+
+ PsThreadType->TotalObjects = 0;
+ PsThreadType->TotalHandles = 0;
+ PsThreadType->MaxObjects = 0;
+ PsThreadType->MaxHandles = 0;
+ PsThreadType->PagedPoolCharge = 0;
+ PsThreadType->NonpagedPoolCharge = sizeof(ETHREAD);
+ PsThreadType->Dump = NULL;
+ PsThreadType->Open = NULL;
+ PsThreadType->Close = NULL;
+ PsThreadType->Delete = PiDeleteThread;
+ PsThreadType->Parse = NULL;
+ PsThreadType->Security = NULL;
+ PsThreadType->QueryName = NULL;
+ PsThreadType->OkayToClose = NULL;
+
+ PsInitializeThread(NULL,&FirstThread,&FirstThreadHandle,
+ THREAD_ALL_ACCESS,NULL);
+ HalInitFirstTask(FirstThread);
+ FirstThread->Tcb.ThreadState = THREAD_STATE_RUNNING;
+ FirstThread->Tcb.SuspendCount = 0;
+
+ DPRINT("FirstThread %x\n",FirstThread);
+
+ CurrentThread = FirstThread;
+
+ DoneInitYet = TRUE;
}
NTSTATUS NtCreateThread(PHANDLE ThreadHandle,
PINITIAL_TEB InitialTeb,
BOOLEAN CreateSuspended)
{
+ return(ZwCreateThread(ThreadHandle,
+ DesiredAccess,
+ ObjectAttributes,
+ ProcessHandle,
+ Client,
+ ThreadContext,
+ InitialTeb,
+ CreateSuspended));
+}
+
+NTSTATUS ZwCreateThread(PHANDLE ThreadHandle,
+ ACCESS_MASK DesiredAccess,
+ POBJECT_ATTRIBUTES ObjectAttributes,
+ HANDLE ProcessHandle,
+ PCLIENT_ID Client,
+ PCONTEXT ThreadContext,
+ PINITIAL_TEB InitialTeb,
+ BOOLEAN CreateSuspended)
+{
+ PETHREAD Thread;
+ NTSTATUS Status;
+
+ DPRINT("ZwCreateThread(ThreadHandle %x, PCONTEXT %x)\n",
+ ThreadHandle,ThreadContext);
+
+ Status = PsInitializeThread(ProcessHandle,&Thread,ThreadHandle,
+ DesiredAccess,ObjectAttributes);
+ if (!NT_SUCCESS(Status))
+ {
+ return(Status);
+ }
+
+ Status = HalInitTaskWithContext(Thread,ThreadContext);
+ if (!NT_SUCCESS(Status))
+ {
+ return(Status);
+ }
+ Thread->StartAddress=NULL;
+
+ if (Client!=NULL)
+ {
+ *Client=Thread->Cid;
+ }
+
+ if (!CreateSuspended)
+ {
+ DPRINT("Not creating suspended\n");
+ PsResumeThread(Thread);
+ }
+ DPRINT("Finished PsCreateThread()\n");
+ return(STATUS_SUCCESS);
}
NTSTATUS PsCreateSystemThread(PHANDLE ThreadHandle,
* RETURNS: Success or failure status
*/
{
- PETHREAD thread;
- ULONG ThreadId;
- ULONG ProcessId;
-
- thread = ObGenericCreateObject(ThreadHandle,0,NULL,OBJTYP_THREAD);
- DPRINT("Allocating thread %x\n",thread);
-
- thread->Tcb.ThreadState=THREAD_STATE_RUNNABLE;
- thread->Tcb.BasePriority=0;
- thread->Tcb.CurrentPriority=0;
- thread->Tcb.ApcList=ExAllocatePool(NonPagedPool,sizeof(LIST_ENTRY));
- InitializeListHead(thread->Tcb.ApcList);
- HalInitTask(&(thread->Tcb),StartRoutine,StartContext);
- InitializeListHead(&(thread->IrpList));
- thread->Cid.UniqueThread=NextThreadUniqueId++;
-// thread->Cid.ThreadId=InterlockedIncrement(&NextThreadUniqueId);
- if (ClientId!=NULL)
+ PETHREAD Thread;
+ NTSTATUS Status;
+
+ DPRINT("PsCreateSystemThread(ThreadHandle %x, ProcessHandle %x)\n",
+ ThreadHandle,ProcessHandle);
+
+ Status = PsInitializeThread(ProcessHandle,&Thread,ThreadHandle,
+ DesiredAccess,ObjectAttributes);
+ if (!NT_SUCCESS(Status))
{
- *ClientId=thread->Cid;
+ return(Status);
}
- if (ProcessHandle!=NULL)
- {
- thread->ThreadsProcess=ObGetObjectByHandle(ProcessHandle);
- }
- else
+ Thread->StartAddress=StartRoutine;
+ Status = HalInitTask(Thread,StartRoutine,StartContext);
+ if (!NT_SUCCESS(Status))
{
- thread->ThreadsProcess=&SystemProcess;
+ return(Status);
}
- thread->StartAddress=StartRoutine;
-
+
+ if (ClientId!=NULL)
+ {
+ *ClientId=Thread->Cid;
+ }
+
+ PsResumeThread(Thread);
- ExInterlockedInsertHeadList(&ThreadListHead,&thread->Tcb.Entry,
- &ThreadListLock);
return(STATUS_SUCCESS);
}
}
KPRIORITY KeSetPriorityThread(PKTHREAD Thread, KPRIORITY Priority)
+{
+ KPRIORITY OldPriority;
+ OldPriority = Thread->CurrentPriority;
+ Thread->CurrentPriority = Priority;
+
+ RemoveEntryList(&Thread->Entry);
+ PsInsertIntoThreadList(Thread->CurrentPriority,
+ CONTAINING_RECORD(Thread,ETHREAD,Tcb));
+
+ return(OldPriority);
+}
+
+NTSTATUS STDCALL NtAlertResumeThread(IN HANDLE ThreadHandle,
+ OUT PULONG SuspendCount)
+{
+ return(ZwAlertResumeThread(ThreadHandle,SuspendCount));
+}
+
+NTSTATUS STDCALL ZwAlertResumeThread(IN HANDLE ThreadHandle,
+ OUT PULONG SuspendCount)
+{
+ UNIMPLEMENTED;
+}
+
+NTSTATUS STDCALL NtAlertThread(IN HANDLE ThreadHandle)
+{
+ return(ZwAlertThread(ThreadHandle));
+}
+
+NTSTATUS STDCALL ZwAlertThread(IN HANDLE ThreadHandle)
{
UNIMPLEMENTED;
}
+
+NTSTATUS STDCALL NtGetContextThread(IN HANDLE ThreadHandle,
+ OUT PCONTEXT Context)
+{
+ return(ZwGetContextThread(ThreadHandle,Context));
+}
+
+NTSTATUS STDCALL ZwGetContextThread(IN HANDLE ThreadHandle,
+ OUT PCONTEXT Context)
+{
+ UNIMPLEMENTED;
+}
+
+NTSTATUS STDCALL NtOpenThread(OUT PHANDLE ThreadHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes,
+ IN PCLIENT_ID ClientId)
+{
+ return(ZwOpenThread(ThreadHandle,
+ DesiredAccess,
+ ObjectAttributes,
+ ClientId));
+}
+
+NTSTATUS STDCALL ZwOpenThread(OUT PHANDLE ThreadHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes,
+ IN PCLIENT_ID ClientId)
+{
+ UNIMPLEMENTED;
+}
+
+NTSTATUS STDCALL NtResumeThread(IN HANDLE ThreadHandle,
+ IN PULONG SuspendCount)
+{
+ return(ZwResumeThread(ThreadHandle,SuspendCount));
+}
+
+NTSTATUS STDCALL ZwResumeThread(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;
+
+ Status = ObReferenceObjectByHandle(ThreadHandle,
+ THREAD_SUSPEND_RESUME,
+ PsThreadType,
+ UserMode,
+ (PVOID*)&Thread,
+ NULL);
+ if (Status != STATUS_SUCCESS)
+ {
+ return(Status);
+ }
+
+ (*SuspendCount) = InterlockedDecrement(&Thread->Tcb.SuspendCount);
+ if (Thread->Tcb.SuspendCount <= 0)
+ {
+ Thread->Tcb.ThreadState = THREAD_STATE_RUNNABLE;
+ }
+
+ ObDereferenceObject(Thread);
+ return(STATUS_SUCCESS);
+}
+
+NTSTATUS STDCALL NtSetContextThread(IN HANDLE ThreadHandle,
+ IN PCONTEXT Context)
+{
+ return(ZwSetContextThread(ThreadHandle,Context));
+}
+
+NTSTATUS STDCALL ZwSetContextThread(IN HANDLE ThreadHandle,
+ IN PCONTEXT Context)
+{
+ UNIMPLEMENTED;
+}
+
+NTSTATUS STDCALL NtSuspendThread(IN HANDLE ThreadHandle,
+ IN PULONG PreviousSuspendCount)
+{
+ return(ZwSuspendThread(ThreadHandle,PreviousSuspendCount));
+}
+
+NTSTATUS STDCALL ZwSuspendThread(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;
+
+ Status = ObReferenceObjectByHandle(ThreadHandle,
+ THREAD_SUSPEND_RESUME,
+ PsThreadType,
+ UserMode,
+ (PVOID*)&Thread,
+ NULL);
+ if (Status != STATUS_SUCCESS)
+ {
+ return(Status);
+ }
+
+ (*PreviousSuspendCount) = InterlockedIncrement(&Thread->Tcb.SuspendCount);
+ if (Thread->Tcb.SuspendCount > 0)
+ {
+ Thread->Tcb.ThreadState = THREAD_STATE_SUSPENDED;
+ if (Thread == PsGetCurrentThread())
+ {
+ PsDispatchThread();
+ }
+ }
+
+ ObDereferenceObject(Thread);
+ return(STATUS_SUCCESS);
+}
+
+NTSTATUS STDCALL NtContinue(IN PCONTEXT Context, IN CINT IrqLevel)
+{
+ return(ZwContinue(Context,IrqLevel));
+}
+
+NTSTATUS STDCALL ZwContinue(IN PCONTEXT Context, IN CINT IrqLevel)
+{
+ UNIMPLEMENTED;
+}
+
+NTSTATUS STDCALL NtYieldExecution(VOID)
+{
+ return(ZwYieldExecution());
+}
+
+NTSTATUS STDCALL ZwYieldExecution(VOID)
+{
+ PsDispatchThread();
+ return(STATUS_SUCCESS);
+}