Added ObGetObjectHandleCount().
[reactos.git] / reactos / ntoskrnl / ps / create.c
index 0e2d692..14dc422 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: create.c,v 1.4 1999/12/20 02:14:40 dwelch Exp $
+/* $Id: create.c,v 1.46 2002/03/05 00:20:54 ekohl Exp $
  *
  * COPYRIGHT:              See COPYING in the top level directory
  * PROJECT:                ReactOS kernel
 #include <ddk/ntddk.h>
 #include <internal/ke.h>
 #include <internal/ob.h>
-#include <string.h>
-#include <internal/string.h>
-#include <internal/hal.h>
 #include <internal/ps.h>
-#include <internal/ob.h>
+#include <internal/se.h>
+#include <internal/id.h>
+#include <internal/dbg.h>
 
 #define NDEBUG
 #include <internal/debug.h>
@@ -41,69 +40,322 @@ extern ULONG PiNrThreads;
 
 extern LIST_ENTRY PiThreadListHead;
 
+#define MAX_THREAD_NOTIFY_ROUTINE_COUNT    8
+
+static ULONG PiThreadNotifyRoutineCount = 0;
+static PCREATE_THREAD_NOTIFY_ROUTINE
+PiThreadNotifyRoutine[MAX_THREAD_NOTIFY_ROUTINE_COUNT];
+
 /* FUNCTIONS ***************************************************************/
 
-static VOID PiTimeoutThread( struct _KDPC *dpc, PVOID Context, PVOID arg1, PVOID arg2 )
+NTSTATUS STDCALL
+PsAssignImpersonationToken(PETHREAD Thread,
+                          HANDLE TokenHandle)
+{
+   PACCESS_TOKEN Token;
+   SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
+   NTSTATUS Status;
+   
+   if (TokenHandle != NULL)
+     {
+       Status = ObReferenceObjectByHandle(TokenHandle,
+                                          0,
+                                          SepTokenObjectType,
+                                          UserMode,
+                                          (PVOID*)&Token,
+                                          NULL);
+       if (!NT_SUCCESS(Status))
+         {
+            return(Status);
+         }
+       ImpersonationLevel = Token->ImpersonationLevel;
+     }
+   else
+     {
+       Token = NULL;
+       ImpersonationLevel = 0;
+     }
+   
+   PsImpersonateClient(Thread,
+                      Token,
+                      0,
+                      0,
+                      ImpersonationLevel);
+   if (Token != NULL)
+     {
+       ObDereferenceObject(Token);
+     }
+   return(STATUS_SUCCESS);
+}
+
+VOID STDCALL
+PsRevertToSelf(VOID)
+{
+   PETHREAD Thread;
+
+   Thread = PsGetCurrentThread();
+
+   if (Thread->ActiveImpersonationInfo != 0)
+     {
+       ObDereferenceObject(Thread->ImpersonationInfo->Token);
+       Thread->ActiveImpersonationInfo = 0;
+     }
+}
+
+VOID STDCALL
+PsImpersonateClient(PETHREAD Thread,
+                   PACCESS_TOKEN Token,
+                   UCHAR b,
+                   UCHAR c,
+                   SECURITY_IMPERSONATION_LEVEL Level)
+{
+   if (Token == 0)
+     {
+       if (Thread->ActiveImpersonationInfo != 0)
+         {
+            Thread->ActiveImpersonationInfo = 0;
+            if (Thread->ImpersonationInfo->Token != NULL)
+              {
+                 ObDereferenceObject(Thread->ImpersonationInfo->Token);
+              }
+         }
+       return;
+     }
+   if (Thread->ActiveImpersonationInfo == 0 ||
+       Thread->ImpersonationInfo == NULL)
+     {
+       Thread->ImpersonationInfo = ExAllocatePool(NonPagedPool,
+                                          sizeof(PS_IMPERSONATION_INFO));      
+     }
+   Thread->ImpersonationInfo->Level = Level;
+   Thread->ImpersonationInfo->Unknown2 = c;
+   Thread->ImpersonationInfo->Unknown1 = b;
+   Thread->ImpersonationInfo->Token = Token;
+   ObReferenceObjectByPointer(Token,
+                             0,
+                             SepTokenObjectType,
+                             KernelMode);
+   Thread->ActiveImpersonationInfo = 1;
+}
+
+PACCESS_TOKEN
+PsReferenceEffectiveToken(PETHREAD Thread,
+                         PTOKEN_TYPE TokenType,
+                         PUCHAR b,
+                         PSECURITY_IMPERSONATION_LEVEL Level)
+{
+   PEPROCESS Process;
+   PACCESS_TOKEN Token;
+   
+   if (Thread->ActiveImpersonationInfo == 0)
+     {
+       Process = Thread->ThreadsProcess;
+       *TokenType = TokenPrimary;
+       *b = 0;
+       Token = Process->Token;
+     }
+   else
+     {
+       Token = Thread->ImpersonationInfo->Token;
+       *TokenType = TokenImpersonation;
+       *b = Thread->ImpersonationInfo->Unknown2;
+       *Level = Thread->ImpersonationInfo->Level;      
+     }
+   return(Token);
+}
+
+NTSTATUS STDCALL
+NtImpersonateThread(IN HANDLE ThreadHandle,
+                   IN HANDLE ThreadToImpersonateHandle,
+                   IN PSECURITY_QUALITY_OF_SERVICE SecurityQualityOfService)
+{
+   PETHREAD Thread;
+   PETHREAD ThreadToImpersonate;
+   NTSTATUS Status;
+   SECURITY_CLIENT_CONTEXT ClientContext;
+   
+   Status = ObReferenceObjectByHandle(ThreadHandle,
+                                     0,
+                                     PsThreadType,
+                                     UserMode,
+                                     (PVOID*)&Thread,
+                                     NULL);
+   if (!NT_SUCCESS(Status))
+     {
+       return(Status);
+     }
+   
+   Status = ObReferenceObjectByHandle(ThreadToImpersonateHandle,
+                                     0,
+                                     PsThreadType,
+                                     UserMode,
+                                     (PVOID*)&ThreadToImpersonate,
+                                     NULL);
+   if (!NT_SUCCESS(Status))
+     {
+       ObDereferenceObject(Thread);
+       return(Status);
+     }
+   
+   Status = SeCreateClientSecurity(ThreadToImpersonate,
+                                  SecurityQualityOfService,
+                                  0,
+                                  &ClientContext);
+   if (!NT_SUCCESS(Status))
+     {
+       ObDereferenceObject(Thread);
+       ObDereferenceObject(ThreadToImpersonate);
+       return(Status);
+     }
+   
+   SeImpersonateClient(&ClientContext, Thread);
+   if (ClientContext.Token != NULL)
+     {
+       ObDereferenceObject(ClientContext.Token);
+     }
+   return(STATUS_SUCCESS);
+}
+
+NTSTATUS STDCALL
+NtOpenThreadToken(IN   HANDLE          ThreadHandle,  
+                 IN    ACCESS_MASK     DesiredAccess,  
+                 IN    BOOLEAN         OpenAsSelf,     
+                 OUT   PHANDLE         TokenHandle)
+{
+#if 0
+   PETHREAD Thread;
+   NTSTATUS Status;
+   PACCESS_TOKEN Token;
+   
+   Status = ObReferenceObjectByHandle(ThreadHandle,
+                                     0,
+                                     PsThreadType,
+                                     UserMode,
+                                     (PVOID*)&Thread,
+                                     NULL);
+   if (!NT_SUCCESS(Status))
+     {
+       return(Status);
+     }
+   
+   Token = PsReferencePrimaryToken(Thread->ThreadsProcess);
+   SepCreateImpersonationTokenDacl(Token);
+#endif
+   return(STATUS_UNSUCCESSFUL);
+}
+
+PACCESS_TOKEN STDCALL 
+PsReferenceImpersonationToken(PETHREAD Thread,
+                             PULONG Unknown1,
+                             PULONG Unknown2,
+                             SECURITY_IMPERSONATION_LEVEL* Level)
+{
+   if (Thread->ActiveImpersonationInfo == 0)
+     {
+       return(NULL);
+     }
+   
+   *Level = Thread->ImpersonationInfo->Level;
+   *Unknown1 = Thread->ImpersonationInfo->Unknown1;
+   *Unknown2 = Thread->ImpersonationInfo->Unknown2;
+   ObReferenceObjectByPointer(Thread->ImpersonationInfo->Token,
+                             TOKEN_ALL_ACCESS,
+                             SepTokenObjectType,
+                             KernelMode);
+   return(Thread->ImpersonationInfo->Token);
+}
+
+VOID STDCALL
+PiTimeoutThread(struct _KDPC *dpc,
+               PVOID Context,
+               PVOID arg1,
+               PVOID arg2)
 {
    // wake up the thread, and tell it it timed out
    NTSTATUS Status = STATUS_TIMEOUT;
-   PsUnfreezeThread( (ETHREAD *)Context, &Status );
+   
+   DPRINT("PiTimeoutThread()\n");
+   
+   KeRemoveAllWaitsThread((PETHREAD)Context, Status);
 }
 
-VOID PiBeforeBeginThread(VOID)
+VOID
+PiBeforeBeginThread(CONTEXT c)
 {
-   DPRINT("PiBeforeBeginThread()\n");
+   DPRINT("PiBeforeBeginThread(Eip %x)\n", c.Eip);
    //KeReleaseSpinLock(&PiThreadListLock, PASSIVE_LEVEL);
    KeLowerIrql(PASSIVE_LEVEL);
-   DPRINT("KeGetCurrentIrql() %d\n", KeGetCurrentIrql());
 }
 
-VOID PsBeginThread(PKSTART_ROUTINE StartRoutine, PVOID StartContext)
+#if 0
+VOID 
+PsBeginThread(PKSTART_ROUTINE StartRoutine, PVOID StartContext)
 {
    NTSTATUS Ret;
    
-//   KeReleaseSpinLock(&PiThreadListLock,PASSIVE_LEVEL);
+   //   KeReleaseSpinLock(&PiThreadListLock,PASSIVE_LEVEL);
    KeLowerIrql(PASSIVE_LEVEL);
    Ret = StartRoutine(StartContext);
    PsTerminateSystemThread(Ret);
    KeBugCheck(0);
 }
+#endif
 
-VOID PiDeleteThread(PVOID ObjectBody)
+VOID STDCALL
+PiDeleteThread(PVOID ObjectBody)
 {
-   KIRQL oldIrql;
-   
-   DPRINT1("PiDeleteThread(ObjectBody %x)\n",ObjectBody);
-   
-   KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
-   ObDereferenceObject(((PETHREAD)ObjectBody)->ThreadsProcess);
-   ((PETHREAD)ObjectBody)->ThreadsProcess = NULL;
-   PiNrThreads--;
-   RemoveEntryList(&((PETHREAD)ObjectBody)->Tcb.ThreadListEntry);
-   HalReleaseTask((PETHREAD)ObjectBody);
-   KeReleaseSpinLock(&PiThreadListLock, oldIrql);
-   DPRINT1("PiDeleteThread() finished\n");
+  KIRQL oldIrql;
+  PETHREAD Thread;
+  ULONG i;
+
+  DPRINT("PiDeleteThread(ObjectBody %x)\n",ObjectBody);
+
+  KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
+  Thread = (PETHREAD)ObjectBody;
+
+  for (i = 0; i < PiThreadNotifyRoutineCount; i++)
+    {
+      PiThreadNotifyRoutine[i](Thread->Cid.UniqueProcess,
+                              Thread->Cid.UniqueThread,
+                              FALSE);
+    }
+
+  DPRINT("Process %x(%d)\n",
+        Thread->ThreadsProcess,
+        ObGetObjectPointerCount(Thread->ThreadsProcess));
+  ObDereferenceObject(Thread->ThreadsProcess);
+  Thread->ThreadsProcess = NULL;
+  PiNrThreads--;
+  RemoveEntryList(&Thread->Tcb.ThreadListEntry);
+  KeReleaseThread(Thread);
+  KeReleaseSpinLock(&PiThreadListLock, oldIrql);
+  DPRINT("PiDeleteThread() finished\n");
 }
 
-VOID PiCloseThread(PVOID ObjectBody, ULONG HandleCount)
+VOID STDCALL
+PiCloseThread(PVOID ObjectBody,
+             ULONG HandleCount)
 {
    DPRINT("PiCloseThread(ObjectBody %x)\n", ObjectBody);
-   DPRINT("ObGetReferenceCount(ObjectBody) %d "
-          "ObGetHandleCount(ObjectBody) %d\n",
-          ObGetReferenceCount(ObjectBody),
-          ObGetHandleCount(ObjectBody));
+   DPRINT("ObGetObjectPointerCount(ObjectBody) %d "
+         "ObGetObjectHandleCount(ObjectBody) %d\n",
+         ObGetObjectPointerCount(ObjectBody),
+         ObGetObjectHandleCount(ObjectBody));
 }
 
-NTSTATUS PsInitializeThread(HANDLE                     ProcessHandle, 
-                           PETHREAD            * ThreadPtr,
-                           PHANDLE                     ThreadHandle,
-                           ACCESS_MASK         DesiredAccess,
-                           POBJECT_ATTRIBUTES  ThreadAttributes)
+NTSTATUS
+PsInitializeThread(HANDLE ProcessHandle,
+                  PETHREAD* ThreadPtr,
+                  PHANDLE ThreadHandle,
+                  ACCESS_MASK  DesiredAccess,
+                  POBJECT_ATTRIBUTES ThreadAttributes,
+                  BOOLEAN First)
 {
    PETHREAD Thread;
    NTSTATUS Status;
    KIRQL oldIrql;
    PEPROCESS Process;
+   ULONG i;
    
    /*
     * Reference process
@@ -121,10 +373,11 @@ NTSTATUS PsInitializeThread(HANDLE                        ProcessHandle,
             DPRINT("Failed at %s:%d\n",__FILE__,__LINE__);
             return(Status);
          }
+       DPRINT( "Creating thread in process %x\n", Process );
      }
    else
      {
-       Process = SystemProcess;
+       Process = PsInitialSystemProcess;
        ObReferenceObjectByPointer(Process,
                                   PROCESS_CREATE_THREAD,
                                   PsProcessType,
@@ -134,34 +387,35 @@ NTSTATUS PsInitializeThread(HANDLE                        ProcessHandle,
    /*
     * Create and initialize thread
     */
-   Thread = ObCreateObject(ThreadHandle,
+   Status = ObCreateObject(ThreadHandle,
                           DesiredAccess,
                           ThreadAttributes,
-                          PsThreadType);
+                          PsThreadType,
+                          (PVOID*)&Thread);
+   if (!NT_SUCCESS(Status))
+     {
+       return(Status);
+     }
+
    DPRINT("Thread = %x\n",Thread);
    
    PiNrThreads++;
    
-   Thread->Tcb.State = THREAD_STATE_SUSPENDED;
-   Thread->Tcb.SuspendCount = 0;
-   Thread->Tcb.FreezeCount = 1;
-   InitializeListHead(&Thread->Tcb.ApcState.ApcListHead[0]);
-   InitializeListHead(&Thread->Tcb.ApcState.ApcListHead[1]);
-   Thread->Tcb.KernelApcDisable = 1;
-   Thread->Tcb.WaitIrql = PASSIVE_LEVEL;
+   KeInitializeThread(&Process->Pcb, &Thread->Tcb, First);
    Thread->ThreadsProcess = Process;
-   KeInitializeDpc( &Thread->Tcb.TimerDpc, PiTimeoutThread, Thread );
-   Thread->Tcb.WaitBlockList = NULL;
-   InsertTailList( &Thread->ThreadsProcess->Pcb.ThreadListHead, &Thread->Tcb.ProcessThreadListEntry );
-   KeInitializeDispatcherHeader(&Thread->Tcb.DispatcherHeader,
-                                InternalThreadType,
-                                sizeof(ETHREAD),
-                                FALSE);
-
+   /*
+    * FIXME: What lock protects this?
+    */
+   InsertTailList(&Thread->ThreadsProcess->ThreadListHead, 
+                 &Thread->Tcb.ProcessThreadListEntry);
+   InitializeListHead(&Thread->TerminationPortList);
+   KeInitializeSpinLock(&Thread->ActiveTimerListLock);
    InitializeListHead(&Thread->IrpList);
    Thread->Cid.UniqueThread = (HANDLE)InterlockedIncrement(
                                              &PiNextThreadUniqueId);
    Thread->Cid.UniqueProcess = (HANDLE)Thread->ThreadsProcess->UniqueProcessId;
+   Thread->DeadThread = 0;
+   Thread->Win32Thread = 0;
    DPRINT("Thread->Cid.UniqueThread %d\n",Thread->Cid.UniqueThread);
    
    *ThreadPtr = Thread;
@@ -172,15 +426,23 @@ NTSTATUS PsInitializeThread(HANDLE                        ProcessHandle,
 
    Thread->Tcb.BasePriority = Thread->ThreadsProcess->Pcb.BasePriority;
    Thread->Tcb.Priority = Thread->Tcb.BasePriority;
-   
-   return(STATUS_SUCCESS);
+
+  for (i = 0; i < PiThreadNotifyRoutineCount; i++)
+    {
+      PiThreadNotifyRoutine[i](Thread->Cid.UniqueProcess,
+                              Thread->Cid.UniqueThread,
+                              TRUE);
+    }
+
+  return(STATUS_SUCCESS);
 }
 
 
-static NTSTATUS PsCreateTeb (HANDLE ProcessHandle,
-                            PNT_TEB *TebPtr,
-                            PETHREAD Thread,
-                            PINITIAL_TEB InitialTeb)
+static NTSTATUS
+PsCreateTeb(HANDLE ProcessHandle,
+           PTEB *TebPtr,
+           PETHREAD Thread,
+           PINITIAL_TEB InitialTeb)
 {
    MEMORY_BASIC_INFORMATION Info;
    NTSTATUS Status;
@@ -188,32 +450,43 @@ static NTSTATUS PsCreateTeb (HANDLE ProcessHandle,
    ULONG RegionSize;
    ULONG TebSize;
    PVOID TebBase;
-   NT_TEB Teb;
+   TEB Teb;
+   ULONG ResultLength;
 
    TebBase = (PVOID)0x7FFDE000;
    TebSize = PAGESIZE;
 
    while (TRUE)
      {
-        /* The TEB must reside in user space */
-        Status = NtAllocateVirtualMemory(ProcessHandle,
-                                         &TebBase,
-                                         0,
-                                         &TebSize,
-                                         MEM_COMMIT,
-                                         PAGE_READWRITE);
-        if (NT_SUCCESS(Status))
-          {
-             DPRINT ("TEB allocated at %x\n", TebBase);
-             break;
-          }
-        else
-          {
-             DPRINT ("TEB allocation failed! Status %x\n",Status);
-          }
-
-        TebBase = Info.BaseAddress - TebSize;
-   }
+       Status = NtQueryVirtualMemory(ProcessHandle,
+                                     TebBase,
+                                     MemoryBasicInformation,
+                                     &Info,
+                                     sizeof(Info),
+                                     &ResultLength);
+       if (!NT_SUCCESS(Status))
+         {
+            CPRINT("NtQueryVirtualMemory (Status %x)\n", Status);
+            KeBugCheck(0);
+         }
+       /* FIXME: Race between this and the above check */
+       if (Info.State == MEM_FREE)
+         {
+            /* The TEB must reside in user space */
+            Status = NtAllocateVirtualMemory(ProcessHandle,
+                                             &TebBase,
+                                             0,
+                                             &TebSize,
+                                             MEM_RESERVE | MEM_COMMIT,
+                                             PAGE_READWRITE);
+            if (NT_SUCCESS(Status))
+              {
+                 break;
+              }
+         }
+            
+       TebBase = TebBase - TebSize;
+     }
 
    DPRINT ("TebBase %p TebSize %lu\n", TebBase, TebSize);
 
@@ -223,38 +496,34 @@ static NTSTATUS PsCreateTeb (HANDLE ProcessHandle,
      {
         Teb.Peb = Thread->ThreadsProcess->Peb; /* No PEB yet!! */
      }
-
+   DPRINT("Teb.Peb %x\n", Teb.Peb);
+   
    /* store stack information from InitialTeb */
    if (InitialTeb != NULL)
      {
         Teb.Tib.StackBase = InitialTeb->StackBase;
         Teb.Tib.StackLimit = InitialTeb->StackLimit;
-
-        /*
-         * I don't know if this is really stored in a WNT-TEB,
-         * but it's needed to free the thread stack. (Eric Kohl)
-         */
-        Teb.StackCommit = InitialTeb->StackCommit;
-        Teb.StackCommitMax = InitialTeb->StackCommitMax;
-        Teb.StackReserved = InitialTeb->StackReserved;
+        Teb.DeallocationStack = InitialTeb->StackAllocate;
      }
 
-
    /* more initialization */
    Teb.Cid.UniqueThread = Thread->Cid.UniqueThread;
    Teb.Cid.UniqueProcess = Thread->Cid.UniqueProcess;
-
+   Teb.CurrentLocale = PsDefaultThreadLocaleId;
+   
+   DPRINT("sizeof(TEB) %x\n", sizeof(TEB));
+   
    /* write TEB data into teb page */
    Status = NtWriteVirtualMemory(ProcessHandle,
                                  TebBase,
                                  &Teb,
-                                 sizeof(NT_TEB),
+                                 sizeof(TEB),
                                  &ByteCount);
 
    if (!NT_SUCCESS(Status))
      {
         /* free TEB */
-        DPRINT ("Writing TEB failed!\n");
+        DPRINT1 ("Writing TEB failed!\n");
 
         RegionSize = 0;
         NtFreeVirtualMemory(ProcessHandle,
@@ -265,87 +534,100 @@ static NTSTATUS PsCreateTeb (HANDLE ProcessHandle,
         return Status;
      }
 
-   /* FIXME: fs:[0] = TEB */
-
    if (TebPtr != NULL)
      {
-//        *TebPtr = (PNT_TEB)TebBase;
+        *TebPtr = (PTEB)TebBase;
      }
 
-   DPRINT ("TEB allocated at %p\n", TebBase);
+   DPRINT("TEB allocated at %p\n", TebBase);
 
    return Status;
 }
 
 
-NTSTATUS STDCALL NtCreateThread (PHANDLE                       ThreadHandle,
-                                ACCESS_MASK            DesiredAccess,
-                                POBJECT_ATTRIBUTES     ObjectAttributes,
-                                HANDLE                 ProcessHandle,
-                                PCLIENT_ID             Client,
-                                PCONTEXT               ThreadContext,
-                                PINITIAL_TEB           InitialTeb,
-                                BOOLEAN CreateSuspended)
+NTSTATUS STDCALL
+NtCreateThread (PHANDLE                ThreadHandle,
+               ACCESS_MASK             DesiredAccess,
+               POBJECT_ATTRIBUTES      ObjectAttributes,
+               HANDLE                  ProcessHandle,
+               PCLIENT_ID              Client,
+               PCONTEXT                ThreadContext,
+               PINITIAL_TEB            InitialTeb,
+               BOOLEAN CreateSuspended)
 {
    PETHREAD Thread;
-   PNT_TEB  TebBase;
+   PTEB  TebBase;
    NTSTATUS Status;
    
    DPRINT("NtCreateThread(ThreadHandle %x, PCONTEXT %x)\n",
          ThreadHandle,ThreadContext);
    
-   Status = PsInitializeThread(ProcessHandle,&Thread,ThreadHandle,
-                              DesiredAccess,ObjectAttributes);
+   Status = PsInitializeThread(ProcessHandle,
+                              &Thread,
+                              ThreadHandle,
+                              DesiredAccess,
+                              ObjectAttributes,
+                              FALSE);
    if (!NT_SUCCESS(Status))
      {
        return(Status);
      }
    
-   Status = HalInitTaskWithContext(Thread,ThreadContext);
+   Status = Ke386InitThreadWithContext(&Thread->Tcb,
+                                      ThreadContext);
    if (!NT_SUCCESS(Status))
      {
        return(Status);
      }
-
-   Status = PsCreateTeb (ProcessHandle,
-                         &TebBase,
-                         Thread,
-                         InitialTeb);
+   
+   Status = PsCreateTeb(ProcessHandle,
+                        &TebBase,
+                        Thread,
+                        InitialTeb);
    if (!NT_SUCCESS(Status))
      {
         return(Status);
      }
-
+   
    /* Attention: TebBase is in user memory space */
-//   Thread->Tcb.Teb = TebBase;
+   Thread->Tcb.Teb = TebBase;
 
    Thread->StartAddress=NULL;
 
-   if (Client!=NULL)
+   if (Client != NULL)
      {
        *Client=Thread->Cid;
-     }  
+     }
+   
+   /*
+    * Maybe send a message to the process's debugger
+    */
+   DbgkCreateThread((PVOID)ThreadContext->Eip);
    
+   /*
+    * Start the thread running
+    */
    if (!CreateSuspended)
      {
-        DPRINT("Not creating suspended\n");
-       PsUnfreezeThread(Thread, NULL);
+       DPRINT("Not creating suspended\n");
+       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);
 }
 
 
-NTSTATUS PsCreateSystemThread(PHANDLE ThreadHandle,
-                             ACCESS_MASK DesiredAccess,
-                             POBJECT_ATTRIBUTES ObjectAttributes,
-                             HANDLE ProcessHandle,
-                             PCLIENT_ID ClientId,
-                             PKSTART_ROUTINE StartRoutine,
-                             PVOID StartContext)
+NTSTATUS STDCALL
+PsCreateSystemThread(PHANDLE ThreadHandle,
+                    ACCESS_MASK DesiredAccess,
+                    POBJECT_ATTRIBUTES ObjectAttributes,
+                    HANDLE ProcessHandle,
+                    PCLIENT_ID ClientId,
+                    PKSTART_ROUTINE StartRoutine,
+                    PVOID StartContext)
 /*
  * FUNCTION: Creates a thread which executes in kernel mode
  * ARGUMENTS:
@@ -369,15 +651,21 @@ NTSTATUS PsCreateSystemThread(PHANDLE ThreadHandle,
    DPRINT("PsCreateSystemThread(ThreadHandle %x, ProcessHandle %x)\n",
            ThreadHandle,ProcessHandle);
    
-   Status = PsInitializeThread(ProcessHandle,&Thread,ThreadHandle,
-                              DesiredAccess,ObjectAttributes);
+   Status = PsInitializeThread(ProcessHandle,
+                              &Thread,
+                              ThreadHandle,
+                              DesiredAccess,
+                              ObjectAttributes,
+                              FALSE);
    if (!NT_SUCCESS(Status))
      {
        return(Status);
      }
    
    Thread->StartAddress=StartRoutine;
-   Status = HalInitTask(Thread,StartRoutine,StartContext);
+   Status = Ke386InitThread(&Thread->Tcb,
+                           StartRoutine,
+                           StartContext);
    if (!NT_SUCCESS(Status))
      {
        return(Status);
@@ -386,10 +674,24 @@ NTSTATUS PsCreateSystemThread(PHANDLE ThreadHandle,
    if (ClientId!=NULL)
      {
        *ClientId=Thread->Cid;
-     }  
+     }
 
-   PsUnfreezeThread(Thread, NULL);
+   PsUnblockThread(Thread, NULL);
    
    return(STATUS_SUCCESS);
 }
 
+
+NTSTATUS STDCALL
+PsSetCreateThreadNotifyRoutine(IN PCREATE_THREAD_NOTIFY_ROUTINE NotifyRoutine)
+{
+  if (PiThreadNotifyRoutineCount >= MAX_THREAD_NOTIFY_ROUTINE_COUNT)
+    return(STATUS_INSUFFICIENT_RESOURCES);
+
+  PiThreadNotifyRoutine[PiThreadNotifyRoutineCount] = NotifyRoutine;
+  PiThreadNotifyRoutineCount++;
+
+  return(STATUS_SUCCESS);
+}
+
+/* EOF */