Added ObGetObjectHandleCount().
[reactos.git] / reactos / ntoskrnl / ps / create.c
index 609ccd0..14dc422 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: create.c,v 1.29 2001/01/21 14:54:29 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 <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>
@@ -40,6 +40,12 @@ 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 ***************************************************************/
 
 NTSTATUS STDCALL
@@ -54,7 +60,7 @@ PsAssignImpersonationToken(PETHREAD Thread,
      {
        Status = ObReferenceObjectByHandle(TokenHandle,
                                           0,
-                                          SeTokenType,
+                                          SepTokenObjectType,
                                           UserMode,
                                           (PVOID*)&Token,
                                           NULL);
@@ -82,17 +88,21 @@ PsAssignImpersonationToken(PETHREAD Thread,
    return(STATUS_SUCCESS);
 }
 
-VOID STDCALL 
-PsRevertToSelf(PETHREAD Thread)
+VOID STDCALL
+PsRevertToSelf(VOID)
 {
+   PETHREAD Thread;
+
+   Thread = PsGetCurrentThread();
+
    if (Thread->ActiveImpersonationInfo != 0)
      {
-       Thread->ActiveImpersonationInfo = 0;
        ObDereferenceObject(Thread->ImpersonationInfo->Token);
+       Thread->ActiveImpersonationInfo = 0;
      }
 }
 
-VOID STDCALL 
+VOID STDCALL
 PsImpersonateClient(PETHREAD Thread,
                    PACCESS_TOKEN Token,
                    UCHAR b,
@@ -123,12 +133,12 @@ PsImpersonateClient(PETHREAD Thread,
    Thread->ImpersonationInfo->Token = Token;
    ObReferenceObjectByPointer(Token,
                              0,
-                             SeTokenType,
+                             SepTokenObjectType,
                              KernelMode);
    Thread->ActiveImpersonationInfo = 1;
 }
 
-PACCESS_TOKEN 
+PACCESS_TOKEN
 PsReferenceEffectiveToken(PETHREAD Thread,
                          PTOKEN_TYPE TokenType,
                          PUCHAR b,
@@ -154,16 +164,15 @@ PsReferenceEffectiveToken(PETHREAD Thread,
    return(Token);
 }
 
-NTSTATUS STDCALL 
-NtImpersonateThread (IN HANDLE ThreadHandle,
-                    IN HANDLE ThreadToImpersonateHandle,
-                    IN PSECURITY_QUALITY_OF_SERVICE    
-                    SecurityQualityOfService)
+NTSTATUS STDCALL
+NtImpersonateThread(IN HANDLE ThreadHandle,
+                   IN HANDLE ThreadToImpersonateHandle,
+                   IN PSECURITY_QUALITY_OF_SERVICE SecurityQualityOfService)
 {
    PETHREAD Thread;
    PETHREAD ThreadToImpersonate;
    NTSTATUS Status;
-   SE_SOME_STRUCT2 b;
+   SECURITY_CLIENT_CONTEXT ClientContext;
    
    Status = ObReferenceObjectByHandle(ThreadHandle,
                                      0,
@@ -191,7 +200,7 @@ NtImpersonateThread (IN HANDLE ThreadHandle,
    Status = SeCreateClientSecurity(ThreadToImpersonate,
                                   SecurityQualityOfService,
                                   0,
-                                  &b);
+                                  &ClientContext);
    if (!NT_SUCCESS(Status))
      {
        ObDereferenceObject(Thread);
@@ -199,15 +208,15 @@ NtImpersonateThread (IN HANDLE ThreadHandle,
        return(Status);
      }
    
-   SeImpersonateClient(&b, Thread);
-   if (b.Token != NULL)
+   SeImpersonateClient(&ClientContext, Thread);
+   if (ClientContext.Token != NULL)
      {
-       ObDereferenceObject(b.Token);
+       ObDereferenceObject(ClientContext.Token);
      }
    return(STATUS_SUCCESS);
 }
 
-NTSTATUS STDCALL 
+NTSTATUS STDCALL
 NtOpenThreadToken(IN   HANDLE          ThreadHandle,  
                  IN    ACCESS_MASK     DesiredAccess,  
                  IN    BOOLEAN         OpenAsSelf,     
@@ -250,16 +259,16 @@ PsReferenceImpersonationToken(PETHREAD Thread,
    *Unknown1 = Thread->ImpersonationInfo->Unknown1;
    *Unknown2 = Thread->ImpersonationInfo->Unknown2;
    ObReferenceObjectByPointer(Thread->ImpersonationInfo->Token,
-                             GENERIC_ALL,
-                             SeTokenType,
+                             TOKEN_ALL_ACCESS,
+                             SepTokenObjectType,
                              KernelMode);
    return(Thread->ImpersonationInfo->Token);
 }
 
-VOID 
-PiTimeoutThread(struct _KDPC *dpc, 
-               PVOID Context, 
-               PVOID arg1, 
+VOID STDCALL
+PiTimeoutThread(struct _KDPC *dpc,
+               PVOID Context,
+               PVOID arg1,
                PVOID arg2)
 {
    // wake up the thread, and tell it it timed out
@@ -270,7 +279,7 @@ PiTimeoutThread(struct _KDPC *dpc,
    KeRemoveAllWaitsThread((PETHREAD)Context, Status);
 }
 
-VOID 
+VOID
 PiBeforeBeginThread(CONTEXT c)
 {
    DPRINT("PiBeforeBeginThread(Eip %x)\n", c.Eip);
@@ -292,44 +301,61 @@ PsBeginThread(PKSTART_ROUTINE StartRoutine, PVOID StartContext)
 }
 #endif
 
-VOID PiDeleteThread(PVOID ObjectBody)
+VOID STDCALL
+PiDeleteThread(PVOID ObjectBody)
 {
-   KIRQL oldIrql;
-   
-   DPRINT("PiDeleteThread(ObjectBody %x)\n",ObjectBody);
-   
-   KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
-   DPRINT("Process %x(%d)\n", ((PETHREAD)ObjectBody)->ThreadsProcess,
-          ObGetReferenceCount(((PETHREAD)ObjectBody)->ThreadsProcess));
-   ObDereferenceObject(((PETHREAD)ObjectBody)->ThreadsProcess);
-   ((PETHREAD)ObjectBody)->ThreadsProcess = NULL;
-   PiNrThreads--;
-   RemoveEntryList(&((PETHREAD)ObjectBody)->Tcb.ThreadListEntry);
-   HalReleaseTask((PETHREAD)ObjectBody);
-   KeReleaseSpinLock(&PiThreadListLock, oldIrql);
-   DPRINT("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,
-                           BOOLEAN First)
+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
@@ -361,10 +387,16 @@ 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++;
@@ -383,7 +415,7 @@ NTSTATUS PsInitializeThread(HANDLE ProcessHandle,
                                              &PiNextThreadUniqueId);
    Thread->Cid.UniqueProcess = (HANDLE)Thread->ThreadsProcess->UniqueProcessId;
    Thread->DeadThread = 0;
-   Thread->Win32ThreadData = 0;
+   Thread->Win32Thread = 0;
    DPRINT("Thread->Cid.UniqueThread %d\n",Thread->Cid.UniqueThread);
    
    *ThreadPtr = Thread;
@@ -394,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;
@@ -410,7 +450,7 @@ static NTSTATUS PsCreateTeb (HANDLE ProcessHandle,
    ULONG RegionSize;
    ULONG TebSize;
    PVOID TebBase;
-   NT_TEB Teb;
+   TEB Teb;
    ULONG ResultLength;
 
    TebBase = (PVOID)0x7FFDE000;
@@ -426,7 +466,7 @@ static NTSTATUS PsCreateTeb (HANDLE ProcessHandle,
                                      &ResultLength);
        if (!NT_SUCCESS(Status))
          {
-            DbgPrint("NtQueryVirtualMemory (Status %x)\n", Status);
+            CPRINT("NtQueryVirtualMemory (Status %x)\n", Status);
             KeBugCheck(0);
          }
        /* FIXME: Race between this and the above check */
@@ -437,7 +477,7 @@ static NTSTATUS PsCreateTeb (HANDLE ProcessHandle,
                                              &TebBase,
                                              0,
                                              &TebSize,
-                                             MEM_COMMIT,
+                                             MEM_RESERVE | MEM_COMMIT,
                                              PAGE_READWRITE);
             if (NT_SUCCESS(Status))
               {
@@ -463,28 +503,21 @@ static NTSTATUS PsCreateTeb (HANDLE ProcessHandle,
      {
         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.StackReserve = InitialTeb->StackReserve;
+        Teb.DeallocationStack = InitialTeb->StackAllocate;
      }
 
-
    /* more initialization */
    Teb.Cid.UniqueThread = Thread->Cid.UniqueThread;
    Teb.Cid.UniqueProcess = Thread->Cid.UniqueProcess;
+   Teb.CurrentLocale = PsDefaultThreadLocaleId;
    
-   DPRINT("sizeof(NT_TEB) %x\n", sizeof(NT_TEB));
+   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))
@@ -503,7 +536,7 @@ static NTSTATUS PsCreateTeb (HANDLE ProcessHandle,
 
    if (TebPtr != NULL)
      {
-        *TebPtr = (PNT_TEB)TebBase;
+        *TebPtr = (PTEB)TebBase;
      }
 
    DPRINT("TEB allocated at %p\n", TebBase);
@@ -512,7 +545,7 @@ static NTSTATUS PsCreateTeb (HANDLE ProcessHandle,
 }
 
 
-NTSTATUS STDCALL 
+NTSTATUS STDCALL
 NtCreateThread (PHANDLE                ThreadHandle,
                ACCESS_MASK             DesiredAccess,
                POBJECT_ATTRIBUTES      ObjectAttributes,
@@ -523,48 +556,39 @@ NtCreateThread (PHANDLE           ThreadHandle,
                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, FALSE);
+   Status = PsInitializeThread(ProcessHandle,
+                              &Thread,
+                              ThreadHandle,
+                              DesiredAccess,
+                              ObjectAttributes,
+                              FALSE);
    if (!NT_SUCCESS(Status))
      {
        return(Status);
      }
-
-#if 0
-   Status = NtWriteVirtualMemory(ProcessHandle,
-                                (PVOID)(((ULONG)ThreadContext->Esp) - 8),
-                                &ThreadContext->Eip,
-                                sizeof(ULONG),
-                                &Length);
-   if (!NT_SUCCESS(Status))
-     {
-       DPRINT1("NtWriteVirtualMemory failed\n");
-       KeBugCheck(0);
-     }
-   ThreadContext->Eip = LdrpGetSystemDllEntryPoint;
-#endif   
    
-   Status = Ke386InitThreadWithContext(&Thread->Tcb, 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;
 
@@ -573,32 +597,16 @@ NtCreateThread (PHANDLE           ThreadHandle,
    if (Client != NULL)
      {
        *Client=Thread->Cid;
-     }  
+     }
    
    /*
     * Maybe send a message to the process's debugger
     */
-#if 0
-   if (ParentProcess->DebugPort != NULL)
-     {
-       LPC_DBG_MESSAGE Message;
-       PEPROCESS Process;
-       
-       
-       Message.Header.MessageSize = sizeof(LPC_DBG_MESSAGE);
-       Message.Header.DataSize = sizeof(LPC_DBG_MESSAGE) -
-         sizeof(LPC_MESSAGE_HEADER);
-       Message.EventCode = DBG_EVENT_CREATE_THREAD;
-       Message.Data.CreateThread.StartAddress =
-         ;
-       Message.Data.CreateProcess.Base = ImageBase;
-       Message.Data.CreateProcess.EntryPoint = NULL; //
-       
-       Status = LpcSendDebugMessagePort(ParentProcess->DebugPort,
-                                        &Message);
-     }
-#endif
+   DbgkCreateThread((PVOID)ThreadContext->Eip);
    
+   /*
+    * Start the thread running
+    */
    if (!CreateSuspended)
      {
        DPRINT("Not creating suspended\n");
@@ -612,7 +620,7 @@ NtCreateThread (PHANDLE             ThreadHandle,
 }
 
 
-NTSTATUS STDCALL 
+NTSTATUS STDCALL
 PsCreateSystemThread(PHANDLE ThreadHandle,
                     ACCESS_MASK DesiredAccess,
                     POBJECT_ATTRIBUTES ObjectAttributes,
@@ -643,15 +651,21 @@ PsCreateSystemThread(PHANDLE ThreadHandle,
    DPRINT("PsCreateSystemThread(ThreadHandle %x, ProcessHandle %x)\n",
            ThreadHandle,ProcessHandle);
    
-   Status = PsInitializeThread(ProcessHandle,&Thread,ThreadHandle,
-                              DesiredAccess,ObjectAttributes, FALSE);
+   Status = PsInitializeThread(ProcessHandle,
+                              &Thread,
+                              ThreadHandle,
+                              DesiredAccess,
+                              ObjectAttributes,
+                              FALSE);
    if (!NT_SUCCESS(Status))
      {
        return(Status);
      }
    
    Thread->StartAddress=StartRoutine;
-   Status = Ke386InitThread(&Thread->Tcb, StartRoutine, StartContext);
+   Status = Ke386InitThread(&Thread->Tcb,
+                           StartRoutine,
+                           StartContext);
    if (!NT_SUCCESS(Status))
      {
        return(Status);
@@ -660,11 +674,24 @@ PsCreateSystemThread(PHANDLE ThreadHandle,
    if (ClientId!=NULL)
      {
        *ClientId=Thread->Cid;
-     }  
+     }
 
    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 */