Added process ids.
[reactos.git] / reactos / ntoskrnl / ps / thread.c
index 017ab56..285c7f2 100644 (file)
 #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)
      {
@@ -120,127 +165,192 @@ void PsDispatchThread(void)
      }
    
    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,
@@ -252,6 +362,57 @@ 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,
@@ -278,40 +439,33 @@ 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);
 }
 
@@ -321,6 +475,193 @@ LONG KeSetBasePriorityThread(PKTHREAD Thread, LONG Increment)
 }
 
 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);
+}