*** empty log message ***
[reactos.git] / reactos / ntoskrnl / ps / kill.c
index 2b00b9b..72736c6 100644 (file)
@@ -1,4 +1,5 @@
-/*
+/* $Id: kill.c,v 1.46 2001/07/28 07:57:24 ea Exp $
+ *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
  * FILE:            ntoskrnl/ps/kill.c
@@ -16,6 +17,7 @@
 #include <internal/mm.h>
 #include <internal/ob.h>
 #include <internal/port.h>
+#include <internal/pool.h>
 
 #define NDEBUG
 #include <internal/debug.h>
@@ -30,9 +32,12 @@ extern KSPIN_LOCK PiApcLock;
 
 VOID PsTerminateCurrentThread(NTSTATUS ExitStatus);
 
+#define TAG_TERMINATE_APC   TAG('T', 'A', 'P', 'C')
+
 /* FUNCTIONS *****************************************************************/
 
-VOID PiTerminateProcessThreads(PEPROCESS Process, NTSTATUS ExitStatus)
+VOID 
+PiTerminateProcessThreads(PEPROCESS Process, NTSTATUS ExitStatus)
 {
    KIRQL oldlvl;
    PLIST_ENTRY current_entry;
@@ -46,19 +51,30 @@ VOID PiTerminateProcessThreads(PEPROCESS Process, NTSTATUS ExitStatus)
    current_entry = Process->ThreadListHead.Flink;
    while (current_entry != &Process->ThreadListHead)
      {
-       current = CONTAINING_RECORD(current_entry,ETHREAD,Tcb.ProcessThreadListEntry);
-       if (current != PsGetCurrentThread())
+       current = CONTAINING_RECORD(current_entry, ETHREAD,
+                                   Tcb.ProcessThreadListEntry);
+       if (current != PsGetCurrentThread() &&
+           current->DeadThread == 0)
          {
-            DPRINT("Terminating %x, current thread: %x, thread's process: %x\n", current, PsGetCurrentThread(), current->ThreadsProcess );
+            DPRINT("Terminating %x, current thread: %x, "
+                   "thread's process: %x\n", current, PsGetCurrentThread(), 
+                   current->ThreadsProcess);
+            KeReleaseSpinLock(&PiThreadListLock, oldlvl);
             PsTerminateOtherThread(current, ExitStatus);
+            KeAcquireSpinLock(&PiThreadListLock, &oldlvl);
+            current_entry = Process->ThreadListHead.Flink;
+         }
+       else
+         {
+            current_entry = current_entry->Flink;
          }
-       current_entry = current_entry->Flink;
      }
    KeReleaseSpinLock(&PiThreadListLock, oldlvl);
    DPRINT("Finished PiTerminateProcessThreads()\n");
 }
 
-VOID PsReapThreads(VOID)
+VOID 
+PsReapThreads(VOID)
 {
    PLIST_ENTRY current_entry;
    PETHREAD current;
@@ -118,6 +134,7 @@ VOID PsTerminateCurrentThread(NTSTATUS ExitStatus)
    KeAcquireSpinLock(&PiThreadListLock, &oldIrql);
    
    CurrentThread->ExitStatus = ExitStatus;
+   KeCancelTimer(&KeGetCurrentThread()->Timer);
    KeAcquireDispatcherDatabaseLock(FALSE);
    CurrentThread->Tcb.DispatcherHeader.SignalState = TRUE;
    KeDispatcherObjectWake(&CurrentThread->Tcb.DispatcherHeader);
@@ -127,43 +144,79 @@ VOID PsTerminateCurrentThread(NTSTATUS ExitStatus)
    KeBugCheck(0);
 }
 
-VOID PsTerminateOtherThread(PETHREAD Thread, NTSTATUS ExitStatus)
+VOID
+PiTerminateThreadRundownRoutine(PKAPC Apc)
+{
+  ExFreePool(Apc);
+}
+
+VOID
+PiTerminateThreadKernelRoutine(PKAPC Apc,
+                              PKNORMAL_ROUTINE* NormalRoutine,
+                              PVOID* NormalContext,
+                              PVOID* SystemArgument1,
+                              PVOID* SystemArguemnt2)
+{
+  ExFreePool(Apc);
+}
+
+VOID
+PiTerminateThreadNormalRoutine(PVOID NormalContext,
+                            PVOID SystemArgument1,
+                            PVOID SystemArgument2)
+{
+  PsTerminateCurrentThread(PsGetCurrentThread()->ExitStatus);
+}
+
+VOID 
+PsTerminateOtherThread(PETHREAD Thread, NTSTATUS ExitStatus)
 /*
  * FUNCTION: Terminate a thread when calling from another thread's context
+ * NOTES: This function must be called with PiThreadListLock held
  */
 {
-   KIRQL oldIrql;
-   
-   DPRINT("PsTerminateOtherThread(Thread %x, ExitStatus %x)\n",
-         Thread, ExitStatus);
-   
-   KeAcquireSpinLock( &PiThreadListLock, &oldIrql );
-   Thread->DeadThread = 1;
-   Thread->ExitStatus = ExitStatus;
-   if( Thread->Tcb.State == THREAD_STATE_FROZEN && (Thread->Tcb.Alertable || Thread->Tcb.WaitMode == UserMode) )
-     KeRemoveAllWaitsThread( Thread, STATUS_ALERTED );
-   KeReleaseSpinLock( &PiThreadListLock, oldIrql );
+  PKAPC Apc;
+
+  DPRINT("PsTerminateOtherThread(Thread %x, ExitStatus %x)\n",
+        Thread, ExitStatus);
+  
+  Thread->DeadThread = 1;
+  Thread->ExitStatus = ExitStatus;
+  Apc = ExAllocatePoolWithTag(NonPagedPool, sizeof(KAPC), TAG_TERMINATE_APC);
+  KeInitializeApc(Apc,
+                 &Thread->Tcb,
+                 0,
+                 PiTerminateThreadKernelRoutine,
+                 PiTerminateThreadRundownRoutine,
+                 PiTerminateThreadNormalRoutine,
+                 KernelMode,
+                 NULL);
+  KeInsertQueueApc(Apc,
+                  NULL,
+                  NULL,
+                  KernelMode);
 }
 
-NTSTATUS STDCALL PiTerminateProcess(PEPROCESS Process,
-                                   NTSTATUS ExitStatus)
+NTSTATUS STDCALL 
+PiTerminateProcess(PEPROCESS Process, NTSTATUS ExitStatus)
 {
    DPRINT("PiTerminateProcess(Process %x, ExitStatus %x) RC %d HC %d\n",
           Process, ExitStatus, ObGetReferenceCount(Process),
           ObGetHandleCount(Process));
    
-   if (Process->Pcb.ProcessState == PROCESS_STATE_TERMINATED)
+   if (InterlockedExchange((PLONG)&Process->Pcb.State, 
+                          PROCESS_STATE_TERMINATED) == 
+       PROCESS_STATE_TERMINATED)
      {
        return(STATUS_SUCCESS);
      }
-   
+   KeAttachProcess( Process );
    ObCloseAllHandles(Process);
+   KeDetachProcess();
    KeAcquireDispatcherDatabaseLock(FALSE);
-   Process->Pcb.ProcessState = PROCESS_STATE_TERMINATED;
    Process->Pcb.DispatcherHeader.SignalState = TRUE;
    KeDispatcherObjectWake(&Process->Pcb.DispatcherHeader);
    KeReleaseDispatcherDatabaseLock(FALSE);
-   DPRINT("RC %d\n", ObGetReferenceCount(Process));
    return(STATUS_SUCCESS);
 }
 
@@ -183,9 +236,9 @@ NTSTATUS STDCALL NtTerminateProcess(IN      HANDLE          ProcessHandle,
                                       (PVOID*)&Process,
                                      NULL);
    if (!NT_SUCCESS(Status))
-   {
-        return(Status);
-   }
+     {
+       return(Status);
+     }
    
    PiTerminateProcessThreads(Process, ExitStatus);
    if (PsGetCurrentThread()->ThreadsProcess == Process)
@@ -241,7 +294,8 @@ NTSTATUS STDCALL PsTerminateSystemThread(NTSTATUS ExitStatus)
    return(STATUS_SUCCESS);
 }
 
-NTSTATUS STDCALL NtCallTerminatePorts(PETHREAD Thread)
+NTSTATUS STDCALL 
+NtCallTerminatePorts(PETHREAD Thread)
 {
    KIRQL oldIrql;
    PLIST_ENTRY current_entry;
@@ -263,7 +317,8 @@ NTSTATUS STDCALL NtCallTerminatePorts(PETHREAD Thread)
    return(STATUS_SUCCESS);
 }
 
-NTSTATUS STDCALL NtRegisterThreadTerminatePort(HANDLE TerminationPortHandle)
+NTSTATUS STDCALL 
+NtRegisterThreadTerminatePort(HANDLE TerminationPortHandle)
 {
    NTSTATUS Status;
    PEPORT_TERMINATION_REQUEST Request;