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--;
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);
/*
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
return(TRUE);
}
+/*
+ * @implemented
+ */
VOID STDCALL
KiDeliverApc(ULONG Unknown1,
ULONG Unknown2,
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++;
KeAcquireSpinLock(&PiApcLock, &oldlvl);
Thread->Tcb.ApcState.KernelApcInProgress--;
+ current_entry = Thread->Tcb.ApcState.ApcListHead[0].Flink;
}
else
{
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:
* 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);
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],
Apc->NormalRoutine == NULL)
{
KeReleaseSpinLock(&PiApcLock, oldlvl);
- return;
+ return TRUE;
}
/*
Apc->NormalRoutine == NULL)
{
KeRemoveAllWaitsThread(CONTAINING_RECORD(TargetThread, ETHREAD, Tcb),
- STATUS_KERNEL_APC);
+ STATUS_KERNEL_APC, TRUE);
}
/*
PETHREAD Thread;
Thread = CONTAINING_RECORD(TargetThread, ETHREAD, Tcb);
- KeRemoveAllWaitsThread(Thread, STATUS_USER_APC);
+ KeRemoveAllWaitsThread(Thread, STATUS_USER_APC, TRUE);
}
}
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
{
KIRQL oldIrql;
PKTHREAD TargetThread;
-
- KeAcquireSpinLockAtDpcLevel(&PiApcLock);
+
KeRaiseIrql(HIGH_LEVEL, &oldIrql);
+ KeAcquireSpinLockAtDpcLevel(&PiApcLock);
if (Apc->Inserted == FALSE)
{
KeReleaseSpinLock(&PiApcLock, oldIrql);
}
+/*
+ * @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
* 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));
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
{
KeInitializeApc(Apc,
&Thread->Tcb,
- 0,
+ OriginalApcEnvironment,
NtQueueApcKernelRoutine,
NtQueueApcRundownRoutine,
ApcRoutine,
KeInsertQueueApc(Apc,
SystemArgument1,
SystemArgument2,
- UserMode);
+ IO_NO_INCREMENT);
ObDereferenceObject(Thread);
return(STATUS_SUCCESS);