#define NDEBUG
#include <internal/debug.h>
-/* GLOBALS *******************************************************************/
-
-VOID PsTerminateCurrentThread(NTSTATUS ExitStatus);
-
/* FUNCTIONS *****************************************************************/
/*++
}
/*++
- * KeInsertQueueApc
- * @implemented NT4
+ * KiInsertQueueApc
*
- * The KeInsertQueueApc routine queues a APC for execution when the right
+ * The KiInsertQueueApc routine queues a APC for execution when the right
* scheduler environment exists.
*
* Params:
* Apc - Pointer to an initialized control object of type DPC for which the
* caller provides the storage.
*
- * SystemArgument[1,2] - Pointer to a set of two parameters that contain
- * untyped data.
- *
* PriorityBoost - Priority Boost to apply to the Thread.
*
* Returns:
*--*/
BOOLEAN
STDCALL
-KeInsertQueueApc(PKAPC Apc,
- PVOID SystemArgument1,
- PVOID SystemArgument2,
+KiInsertQueueApc(PKAPC Apc,
KPRIORITY PriorityBoost)
-
{
- KIRQL OldIrql;
- PKTHREAD Thread;
+ PKTHREAD Thread = Apc->Thread;
PLIST_ENTRY ApcListEntry;
PKAPC QueuedApc;
-
- ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
- DPRINT("KeInsertQueueApc(Apc %x, SystemArgument1 %x, "
- "SystemArgument2 %x)\n",Apc,SystemArgument1,
- SystemArgument2);
-
- /* Lock the Dispatcher Database */
- OldIrql = KeAcquireDispatcherDatabaseLock();
-
- /* Get the Thread specified in the APC */
- Thread = Apc->Thread;
-
- /* Make sure the thread allows APC Queues.
- * The thread is not apc queueable, for instance, when it's (about to be) terminated.
- */
- if (Thread->ApcQueueable == FALSE) {
- DPRINT("Thread doesn't allow APC Queues\n");
- KeReleaseDispatcherDatabaseLock(OldIrql);
- return FALSE;
- }
- /* Set the System Arguments */
- Apc->SystemArgument1 = SystemArgument1;
- Apc->SystemArgument2 = SystemArgument2;
-
/* Don't do anything if the APC is already inserted */
if (Apc->Inserted) {
- KeReleaseDispatcherDatabaseLock(OldIrql);
return FALSE;
}
DPRINT ("Inserting Normal APC %x into the %x Queue\n", Apc, Apc->ApcMode);
InsertTailList(&Thread->ApcStatePointer[(int)Apc->ApcStateIndex]->ApcListHead[(int)Apc->ApcMode],
- &Apc->ApcListEntry);
+ &Apc->ApcListEntry);
}
/* Confirm Insertion */
DPRINT ("Requesting APC Interrupt for Running Thread \n");
HalRequestSoftwareInterrupt(APC_LEVEL);
- } else if ((Thread->State == THREAD_STATE_BLOCKED) &&
- (Thread->WaitIrql < APC_LEVEL) &&
- (Apc->NormalRoutine == NULL)) {
+ } else if ((Thread->State == THREAD_STATE_BLOCKED) && (Thread->WaitIrql == PASSIVE_LEVEL) &&
+ ((Apc->NormalRoutine == NULL) ||
+ ((!Thread->KernelApcDisable) && (!Thread->ApcState.KernelApcInProgress)))) {
DPRINT("Waking up Thread for Kernel-Mode APC Delivery \n");
KiAbortWaitThread(Thread, STATUS_KERNEL_APC, PriorityBoost);
Thread->ApcState.UserApcPending = TRUE;
KiAbortWaitThread(Thread, STATUS_USER_APC, PriorityBoost);
}
+
+ return TRUE;
+}
+
+/*++
+ * KeInsertQueueApc
+ * @implemented NT4
+ *
+ * The KeInsertQueueApc routine queues a APC for execution when the right
+ * scheduler environment exists.
+ *
+ * Params:
+ * Apc - Pointer to an initialized control object of type DPC for which the
+ * caller provides the storage.
+ *
+ * SystemArgument[1,2] - Pointer to a set of two parameters that contain
+ * untyped data.
+ *
+ * PriorityBoost - Priority Boost to apply to the Thread.
+ *
+ * Returns:
+ * If the APC is already inserted or APC queueing is disabled, FALSE.
+ * Otherwise, TRUE.
+ *
+ * Remarks:
+ * The APC will execute at APC_LEVEL for the KernelRoutine registered, and
+ * at PASSIVE_LEVEL for the NormalRoutine registered.
+ *
+ * Callers of this routine must be running at IRQL = PASSIVE_LEVEL.
+ *
+ *--*/
+BOOLEAN
+STDCALL
+KeInsertQueueApc(PKAPC Apc,
+ PVOID SystemArgument1,
+ PVOID SystemArgument2,
+ KPRIORITY PriorityBoost)
+
+{
+ KIRQL OldIrql;
+ PKTHREAD Thread;
+ BOOLEAN Inserted;
+
+ ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
+ DPRINT("KeInsertQueueApc(Apc %x, SystemArgument1 %x, "
+ "SystemArgument2 %x)\n",Apc,SystemArgument1,
+ SystemArgument2);
+
+ /* Lock the Dispatcher Database */
+ OldIrql = KeAcquireDispatcherDatabaseLock();
+
+ /* Get the Thread specified in the APC */
+ Thread = Apc->Thread;
+
+ /* Make sure the thread allows APC Queues.
+ * The thread is not apc queueable, for instance, when it's (about to be) terminated.
+ */
+ if (Thread->ApcQueueable == FALSE) {
+ DPRINT("Thread doesn't allow APC Queues\n");
+ KeReleaseDispatcherDatabaseLock(OldIrql);
+ return FALSE;
+ }
+
+ /* Set the System Arguments */
+ Apc->SystemArgument1 = SystemArgument1;
+ Apc->SystemArgument2 = SystemArgument2;
+
+ /* Call the Internal Function */
+ Inserted = KiInsertQueueApc(Apc, PriorityBoost);
/* Return Sucess if we are here */
KeReleaseDispatcherDatabaseLock(OldIrql);
- return TRUE;
+ return Inserted;
}
/*++