branch update for HEAD-2003091401
[reactos.git] / ntoskrnl / ke / apc.c
index 8a8a633..b490d71 100644 (file)
@@ -91,14 +91,13 @@ KiDeliverNormalApc(VOID)
    KeAcquireSpinLock(&PiApcLock, &oldlvl);
    while(!IsListEmpty(&(Thread->Tcb.ApcState.ApcListHead[0])))
      {
-       current = Thread->Tcb.ApcState.ApcListHead[0].Blink;
+       current = RemoveTailList(&Thread->Tcb.ApcState.ApcListHead[0]);
        Apc = CONTAINING_RECORD(current, KAPC, ApcListEntry);
        if (Apc->NormalRoutine == NULL)
         {
           DbgPrint("Exiting kernel with kernel APCs pending.\n");
-          KeBugCheck(0);
+          KEBUGCHECK(0);
         }
-       (VOID)RemoveTailList(&Thread->Tcb.ApcState.ApcListHead[0]);
        Apc->Inserted = FALSE;
        Thread->Tcb.ApcState.KernelApcInProgress++;
        Thread->Tcb.ApcState.KernelApcPending--;
@@ -166,6 +165,11 @@ KiDeliverUserApc(PKTRAP_FRAME TrapFrame)
        current_entry = RemoveHeadList(&Thread->ApcState.ApcListHead[1]);
        Apc = CONTAINING_RECORD(current_entry, KAPC, ApcListEntry);
        Apc->Inserted = FALSE;
+
+       /*
+       * We've dealt with one pending user-mode APC
+       */
+       Thread->ApcState.UserApcPending--;
        KeReleaseSpinLock(&PiApcLock, oldlvl);       
        
        /*
@@ -210,10 +214,6 @@ KiDeliverUserApc(PKTRAP_FRAME TrapFrame)
        TrapFrame->Eip = (ULONG)LdrpGetSystemDllApcDispatcher();
        TrapFrame->Esp = (ULONG)Esp;     
        
-       /*
-       * We've dealt with one pending user-mode APC
-       */
-       Thread->ApcState.UserApcPending--;
        
        /*
        * Now call for the kernel routine for the APC, which will free
@@ -236,6 +236,9 @@ KiDeliverUserApc(PKTRAP_FRAME TrapFrame)
    return(TRUE);
 }
 
+/*
+ * @implemented
+ */
 VOID STDCALL 
 KiDeliverApc(ULONG Unknown1,
             ULONG Unknown2,
@@ -262,7 +265,6 @@ KiDeliverApc(ULONG Unknown1,
        Apc = CONTAINING_RECORD(current_entry, KAPC, ApcListEntry);
        if (Apc->NormalRoutine == NULL)
         {
-          current_entry = current_entry->Flink;
           Apc->Inserted = FALSE;
           RemoveEntryList(&Apc->ApcListEntry);
           Thread->Tcb.ApcState.KernelApcInProgress++;
@@ -278,6 +280,7 @@ KiDeliverApc(ULONG Unknown1,
           
           KeAcquireSpinLock(&PiApcLock, &oldlvl);
           Thread->Tcb.ApcState.KernelApcInProgress--;
+          current_entry = Thread->Tcb.ApcState.ApcListHead[0].Flink;
         }
        else
         {
@@ -287,11 +290,14 @@ KiDeliverApc(ULONG Unknown1,
    KeReleaseSpinLock(&PiApcLock, oldlvl);
 }
 
-VOID STDCALL
+/*
+ * @implemented
+ */
+BOOLEAN STDCALL
 KeInsertQueueApc (PKAPC        Apc,
                  PVOID SystemArgument1,
                  PVOID SystemArgument2,
-                 UCHAR Mode)
+        KPRIORITY PriorityBoost)
 /*
  * FUNCTION: Queues an APC for execution
  * ARGUMENTS:
@@ -300,12 +306,13 @@ KeInsertQueueApc (PKAPC   Apc,
  *         Mode = TBD
  */
 {
+   //FIXME: return FALSE if APC can't be queued to target thread (thread has ended)
    KIRQL oldlvl;
    PKTHREAD TargetThread;
    
    DPRINT("KeInsertQueueApc(Apc %x, SystemArgument1 %x, "
-         "SystemArgument2 %x, Mode %d)\n",Apc,SystemArgument1,
-         SystemArgument2,Mode);
+         "SystemArgument2 %x)\n",Apc,SystemArgument1,
+         SystemArgument2);
    
    KeAcquireSpinLock(&PiApcLock, &oldlvl);
    
@@ -315,10 +322,18 @@ KeInsertQueueApc (PKAPC   Apc,
    if (Apc->Inserted)
      {
        DbgPrint("KeInsertQueueApc(): multiple APC insertations\n");
-       KeBugCheck(0);
+       KEBUGCHECK(0);
      }
    
    TargetThread = Apc->Thread;
+
+   if (TargetThread->State == THREAD_STATE_TERMINATED_1 ||
+       TargetThread->State == THREAD_STATE_TERMINATED_2)
+     {
+       KeReleaseSpinLock(&PiApcLock, oldlvl);
+       return(FALSE);
+     }
+
    if (Apc->ApcMode == KernelMode)
      {
        InsertTailList(&TargetThread->ApcState.ApcListHead[0], 
@@ -343,7 +358,7 @@ KeInsertQueueApc (PKAPC     Apc,
        Apc->NormalRoutine == NULL)
      {
        KeReleaseSpinLock(&PiApcLock, oldlvl);
-       return;
+       return TRUE;
      }
 
    /*
@@ -358,7 +373,7 @@ KeInsertQueueApc (PKAPC     Apc,
        Apc->NormalRoutine == NULL)
      {
        KeRemoveAllWaitsThread(CONTAINING_RECORD(TargetThread, ETHREAD, Tcb),
-                              STATUS_KERNEL_APC);
+                              STATUS_KERNEL_APC, TRUE);
      }
 
    /*
@@ -375,7 +390,7 @@ KeInsertQueueApc (PKAPC     Apc,
           PETHREAD Thread;
 
           Thread = CONTAINING_RECORD(TargetThread, ETHREAD, Tcb);
-          KeRemoveAllWaitsThread(Thread, STATUS_USER_APC);
+          KeRemoveAllWaitsThread(Thread, STATUS_USER_APC, TRUE);
         }
      }
 
@@ -394,9 +409,10 @@ KeInsertQueueApc (PKAPC    Apc,
        Status = STATUS_USER_APC;
        TargetThread->Alerted[0] = 1;
        KeRemoveAllWaitsThread(CONTAINING_RECORD(TargetThread, ETHREAD, Tcb),
-                              STATUS_USER_APC);
+                              STATUS_USER_APC, TRUE);
      }
    KeReleaseSpinLock(&PiApcLock, oldlvl);
+   return TRUE;
 }
 
 BOOLEAN STDCALL
@@ -412,9 +428,9 @@ KeRemoveQueueApc (PKAPC Apc)
 {
    KIRQL oldIrql;
    PKTHREAD TargetThread;
-   
-   KeAcquireSpinLockAtDpcLevel(&PiApcLock);
+
    KeRaiseIrql(HIGH_LEVEL, &oldIrql);
+   KeAcquireSpinLockAtDpcLevel(&PiApcLock);
    if (Apc->Inserted == FALSE)
      {
        KeReleaseSpinLock(&PiApcLock, oldIrql);
@@ -438,21 +454,25 @@ KeRemoveQueueApc (PKAPC Apc)
 }
 
 
+/*
+ * @implemented
+ */
 VOID STDCALL
-KeInitializeApc(PKAPC                  Apc,
-               PKTHREAD                Thread,
-               UCHAR                   StateIndex,
-               PKKERNEL_ROUTINE        KernelRoutine,
-               PKRUNDOWN_ROUTINE       RundownRoutine,
-               PKNORMAL_ROUTINE        NormalRoutine,
-               UCHAR                   Mode,
-               PVOID                   Context)
+KeInitializeApc(
+  IN PKAPC  Apc,
+       IN PKTHREAD  Thread,
+       IN UCHAR  StateIndex,
+       IN PKKERNEL_ROUTINE  KernelRoutine,
+       IN PKRUNDOWN_ROUTINE  RundownRoutine,
+       IN PKNORMAL_ROUTINE  NormalRoutine,
+       IN UCHAR  Mode,
+       IN PVOID  Context)
 /*
  * FUNCTION: Initialize an APC object
  * ARGUMENTS:
  *       Apc = Pointer to the APC object to initialized
  *       Thread = Thread the APC is to be delivered to
- *       StateIndex = TBD
+ *       StateIndex = KAPC_ENVIRONMENT
  *       KernelRoutine = Routine to be called for a kernel-mode APC
  *       RundownRoutine = Routine to be called if the thread has exited with
  *                        the APC being executed
@@ -461,9 +481,11 @@ KeInitializeApc(PKAPC                      Apc,
  *       Context = Parameter to be passed to the APC routine
  */
 {
-   DPRINT("KeInitializeApc(Apc %x, Thread %x, StateIndex %d, "
+   KAPC_ENVIRONMENT Environment = (KAPC_ENVIRONMENT) StateIndex;
+
+   DPRINT("KeInitializeApc(Apc %x, Thread %x, Environment %d, "
          "KernelRoutine %x, RundownRoutine %x, NormalRoutine %x, Mode %d, "
-         "Context %x)\n",Apc,Thread,StateIndex,KernelRoutine,RundownRoutine,
+         "Context %x)\n",Apc,Thread,Environment,KernelRoutine,RundownRoutine,
          NormalRoutine,Mode,Context);
 
    memset(Apc, 0, sizeof(KAPC));
@@ -475,10 +497,19 @@ KeInitializeApc(PKAPC                     Apc,
    Apc->NormalRoutine = NormalRoutine;
    Apc->NormalContext = Context;
    Apc->Inserted = FALSE;
-   Apc->ApcStateIndex = StateIndex;
+
+   if (Environment == CurrentApcEnvironment)
+   {
+      Apc->ApcStateIndex = Thread->ApcStateIndex;
+   }
+   else
+   {
+      Apc->ApcStateIndex = Environment;   
+   }
+
    if (Apc->NormalRoutine != NULL)
      {
-       Apc->ApcMode = Mode;
+       Apc->ApcMode = (KPROCESSOR_MODE) Mode;
      }
    else
      {
@@ -533,7 +564,7 @@ NtQueueApcThread(HANDLE                     ThreadHandle,
    
    KeInitializeApc(Apc,
                   &Thread->Tcb,
-                  0,
+         OriginalApcEnvironment,
                   NtQueueApcKernelRoutine,
                   NtQueueApcRundownRoutine,
                   ApcRoutine,
@@ -542,7 +573,7 @@ NtQueueApcThread(HANDLE                     ThreadHandle,
    KeInsertQueueApc(Apc,
                    SystemArgument1,
                    SystemArgument2,
-                   UserMode);
+                   IO_NO_INCREMENT);
    
    ObDereferenceObject(Thread);
    return(STATUS_SUCCESS);