- Fix nasty APC delivery bug (in case a Kernel-Mode Special APC still returned with a Normal Routine, the Normal Routine was called with incorrect values (Special Routines take PVOID* arguments, while Normal Routines do not!))

- Remove APC from list before setting it to non-inserted.
 - Do proper thread termination piggybacking; terminate threads in user-mode as Hartmut correctly fixed.

svn path=/trunk/; revision=16635
This commit is contained in:
Alex Ionescu 2005-07-18 19:50:23 +00:00
parent 269fab698e
commit ce7fb8c1b9
2 changed files with 81 additions and 44 deletions

View file

@ -577,8 +577,8 @@ KiDeliverApc(KPROCESSOR_MODE DeliveryMode,
if (NormalRoutine == NULL) {
/* Remove the APC from the list */
Apc->Inserted = FALSE;
RemoveEntryList(ApcListEntry);
Apc->Inserted = FALSE;
/* Go back to APC_LEVEL */
KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
@ -612,8 +612,8 @@ KiDeliverApc(KPROCESSOR_MODE DeliveryMode,
}
/* Dequeue the APC */
RemoveEntryList(ApcListEntry);
Apc->Inserted = FALSE;
RemoveEntryList(ApcListEntry);
/* Go back to APC_LEVEL */
KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
@ -635,7 +635,7 @@ KiDeliverApc(KPROCESSOR_MODE DeliveryMode,
/* Call and Raise IRQ back to APC_LEVEL */
DPRINT("Calling the Normal Routine for a Normal APC: %x\n", Apc);
NormalRoutine(&NormalContext, &SystemArgument1, &SystemArgument2);
NormalRoutine(NormalContext, SystemArgument1, SystemArgument2);
KeRaiseIrql(APC_LEVEL, &OldIrql);
}
@ -666,8 +666,8 @@ KiDeliverApc(KPROCESSOR_MODE DeliveryMode,
/* Remove the APC from Queue, restore IRQL and call the APC */
RemoveEntryList(ApcListEntry);
Apc->Inserted = FALSE;
KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
DPRINT("Calling the Kernel Routine for for a User APC: %x\n", Apc);
KernelRoutine(Apc,
&NormalRoutine,

View file

@ -346,9 +346,13 @@ PsExitSpecialApc(PKAPC Apc,
PVOID* SystemArgument1,
PVOID* SystemArguemnt2)
{
NTSTATUS ExitStatus = (NTSTATUS)Apc->NormalContext;
DPRINT1("PsExitSpecialApc called: 0x%x (proc: 0x%x)\n",
PsGetCurrentThread(), PsGetCurrentProcess());
DPRINT("PsExitSpecialApc called: 0x%x (proc: 0x%x)\n", PsGetCurrentThread(), PsGetCurrentProcess());
/* Don't do anything unless we are in User-Mode */
if (Apc->SystemArgument2)
{
NTSTATUS ExitStatus = (NTSTATUS)Apc->NormalContext;
/* Free the APC */
ExFreePool(Apc);
@ -359,6 +363,7 @@ PsExitSpecialApc(PKAPC Apc,
/* we should never reach this point! */
KEBUGCHECK(0);
}
}
VOID
STDCALL
@ -366,14 +371,46 @@ PspExitNormalApc(PVOID NormalContext,
PVOID SystemArgument1,
PVOID SystemArgument2)
{
/* Not fully supported yet... must work out some issues that
* I don't understand yet -- Alex
*/
DPRINT1("APC2\n");
PspExitThread((NTSTATUS)NormalContext);
PKAPC Apc = (PKAPC)SystemArgument1;
PETHREAD Thread = PsGetCurrentThread();
NTSTATUS ExitStatus;
/* we should never reach this point! */
KEBUGCHECK(0);
DPRINT1("PspExitNormalApc called: 0x%x (proc: 0x%x)\n",
PsGetCurrentThread(), PsGetCurrentProcess());
/* This should never happen */
ASSERT(!SystemArgument2);
/* If this is a system thread, we can safely kill it from Kernel-Mode */
if (PsIsSystemThread(Thread))
{
/* Get the Exit Status */
DPRINT1("Killing System Thread\n");
ExitStatus = (NTSTATUS)Apc->NormalContext;
/* Free the APC */
ExFreePool(Apc);
/* Exit the Thread */
PspExitThread(ExitStatus);
}
/* If we're here, this is not a System Thread, so kill it from User-Mode */
DPRINT1("Initializing User-Mode APC\n");
KeInitializeApc(Apc,
&Thread->Tcb,
OriginalApcEnvironment,
PsExitSpecialApc,
NULL,
PspExitNormalApc,
UserMode,
NormalContext);
/* Now insert the APC with the User-Mode Flag */
KeInsertQueueApc(Apc, Apc, (PVOID)UserMode, 2);
/* Forcefully resume the thread */
KeForceResumeThread(&Thread->Tcb);
}
/*
@ -402,14 +439,14 @@ PspTerminateThreadByPointer(PETHREAD Thread,
/* Allocate the APC */
Apc = ExAllocatePoolWithTag(NonPagedPool, sizeof(KAPC), TAG_TERMINATE_APC);
/* Initialize a User Mode APC to Kill the Thread */
/* Initialize a Kernel Mode APC to Kill the Thread */
KeInitializeApc(Apc,
&Thread->Tcb,
OriginalApcEnvironment,
PsExitSpecialApc,
NULL,
PspExitNormalApc,
UserMode,
KernelMode,
(PVOID)ExitStatus);
/* Insert it into the APC Queue */