Used HasTerminated as bitmap for flags to make difference between calling PsTerminateCurrentThread and delivering an apc which calls PsTerminateCurrentThread.
Modified: trunk/reactos/ntoskrnl/ps/kill.c

Modified: trunk/reactos/ntoskrnl/ps/kill.c
--- trunk/reactos/ntoskrnl/ps/kill.c	2005-02-23 18:40:51 UTC (rev 13727)
+++ trunk/reactos/ntoskrnl/ps/kill.c	2005-02-23 18:43:25 UTC (rev 13728)
@@ -23,6 +23,9 @@
 
 LIST_ENTRY ThreadsToReapHead;
 
+#define TERMINATE_PROC	0x1
+#define TERMINATE_APC	0x2
+
 /* FUNCTIONS *****************************************************************/
 
 VOID
@@ -110,9 +113,21 @@
    SIZE_T Length = PAGE_SIZE;
    PVOID TebBlock;
 
+   DPRINT("PsTerminateCurrentThread(ExitStatus %x)\n", ExitStatus);
+
+   CurrentThread = PsGetCurrentThread();
+
+   oldIrql = KeAcquireDispatcherDatabaseLock();
+   if (CurrentThread->HasTerminated & TERMINATE_PROC)
+   {
+      KeReleaseDispatcherDatabaseLock(oldIrql);
+      return;
+   }
+   CurrentThread->HasTerminated |= TERMINATE_PROC;
+   KeReleaseDispatcherDatabaseLock(oldIrql);
+
    KeLowerIrql(PASSIVE_LEVEL);
 
-   CurrentThread = PsGetCurrentThread();
    CurrentProcess = CurrentThread->ThreadsProcess;
 
    /* Can't terminate a thread if it attached another process */
@@ -130,7 +145,6 @@
 
    DPRINT("terminating %x\n",CurrentThread);
 
-   CurrentThread->HasTerminated = TRUE;
    CurrentThread->ExitStatus = ExitStatus;
    KeQuerySystemTime((PLARGE_INTEGER)&CurrentThread->ExitTime);
 
@@ -238,13 +252,7 @@
 			     PVOID SystemArgument1,
 			     PVOID SystemArgument2)
 {
-  PETHREAD EThread = PsGetCurrentThread();
-  if (EThread->HasTerminated)
-  {
-     /* Someone else has already called PsTerminateCurrentThread */
-     return;
-  }
-  PsTerminateCurrentThread(PsGetCurrentThread()->ExitStatus);
+  PsTerminateCurrentThread((NTSTATUS)SystemArgument1);
 }
 
 VOID
@@ -262,14 +270,13 @@
 	 Thread, ExitStatus);
 
   OldIrql = KeAcquireDispatcherDatabaseLock();
-  if (Thread->HasTerminated)
+  if (Thread->HasTerminated & TERMINATE_APC)
   {
      KeReleaseDispatcherDatabaseLock (OldIrql);
      return;
   }
-  Thread->HasTerminated = TRUE;
+  Thread->HasTerminated |= TERMINATE_APC;
   KeReleaseDispatcherDatabaseLock (OldIrql);
-  Thread->ExitStatus = ExitStatus;
   Apc = ExAllocatePoolWithTag(NonPagedPool, sizeof(KAPC), TAG_TERMINATE_APC);
   KeInitializeApc(Apc,
 		  &Thread->Tcb,
@@ -280,8 +287,8 @@
 		  KernelMode,
 		  NULL);
   KeInsertQueueApc(Apc,
+		   (PVOID)ExitStatus,
 		   NULL,
-		   NULL,
 		   IO_NO_INCREMENT);
 
   OldIrql = KeAcquireDispatcherDatabaseLock();