mirror of
https://github.com/reactos/reactos.git
synced 2025-06-26 15:19:43 +00:00
- 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:
parent
269fab698e
commit
ce7fb8c1b9
2 changed files with 81 additions and 44 deletions
|
@ -577,8 +577,8 @@ KiDeliverApc(KPROCESSOR_MODE DeliveryMode,
|
||||||
if (NormalRoutine == NULL) {
|
if (NormalRoutine == NULL) {
|
||||||
|
|
||||||
/* Remove the APC from the list */
|
/* Remove the APC from the list */
|
||||||
Apc->Inserted = FALSE;
|
|
||||||
RemoveEntryList(ApcListEntry);
|
RemoveEntryList(ApcListEntry);
|
||||||
|
Apc->Inserted = FALSE;
|
||||||
|
|
||||||
/* Go back to APC_LEVEL */
|
/* Go back to APC_LEVEL */
|
||||||
KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
|
KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
|
||||||
|
@ -612,8 +612,8 @@ KiDeliverApc(KPROCESSOR_MODE DeliveryMode,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Dequeue the APC */
|
/* Dequeue the APC */
|
||||||
RemoveEntryList(ApcListEntry);
|
|
||||||
Apc->Inserted = FALSE;
|
Apc->Inserted = FALSE;
|
||||||
|
RemoveEntryList(ApcListEntry);
|
||||||
|
|
||||||
/* Go back to APC_LEVEL */
|
/* Go back to APC_LEVEL */
|
||||||
KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
|
KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
|
||||||
|
@ -635,7 +635,7 @@ KiDeliverApc(KPROCESSOR_MODE DeliveryMode,
|
||||||
|
|
||||||
/* Call and Raise IRQ back to APC_LEVEL */
|
/* Call and Raise IRQ back to APC_LEVEL */
|
||||||
DPRINT("Calling the Normal Routine for a Normal APC: %x\n", Apc);
|
DPRINT("Calling the Normal Routine for a Normal APC: %x\n", Apc);
|
||||||
NormalRoutine(&NormalContext, &SystemArgument1, &SystemArgument2);
|
NormalRoutine(NormalContext, SystemArgument1, SystemArgument2);
|
||||||
KeRaiseIrql(APC_LEVEL, &OldIrql);
|
KeRaiseIrql(APC_LEVEL, &OldIrql);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -666,8 +666,8 @@ KiDeliverApc(KPROCESSOR_MODE DeliveryMode,
|
||||||
/* Remove the APC from Queue, restore IRQL and call the APC */
|
/* Remove the APC from Queue, restore IRQL and call the APC */
|
||||||
RemoveEntryList(ApcListEntry);
|
RemoveEntryList(ApcListEntry);
|
||||||
Apc->Inserted = FALSE;
|
Apc->Inserted = FALSE;
|
||||||
|
|
||||||
KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
|
KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
|
||||||
|
|
||||||
DPRINT("Calling the Kernel Routine for for a User APC: %x\n", Apc);
|
DPRINT("Calling the Kernel Routine for for a User APC: %x\n", Apc);
|
||||||
KernelRoutine(Apc,
|
KernelRoutine(Apc,
|
||||||
&NormalRoutine,
|
&NormalRoutine,
|
||||||
|
|
|
@ -346,9 +346,13 @@ PsExitSpecialApc(PKAPC Apc,
|
||||||
PVOID* SystemArgument1,
|
PVOID* SystemArgument1,
|
||||||
PVOID* SystemArguemnt2)
|
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 */
|
/* Free the APC */
|
||||||
ExFreePool(Apc);
|
ExFreePool(Apc);
|
||||||
|
@ -358,6 +362,7 @@ PsExitSpecialApc(PKAPC Apc,
|
||||||
|
|
||||||
/* we should never reach this point! */
|
/* we should never reach this point! */
|
||||||
KEBUGCHECK(0);
|
KEBUGCHECK(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
|
@ -366,14 +371,46 @@ PspExitNormalApc(PVOID NormalContext,
|
||||||
PVOID SystemArgument1,
|
PVOID SystemArgument1,
|
||||||
PVOID SystemArgument2)
|
PVOID SystemArgument2)
|
||||||
{
|
{
|
||||||
/* Not fully supported yet... must work out some issues that
|
PKAPC Apc = (PKAPC)SystemArgument1;
|
||||||
* I don't understand yet -- Alex
|
PETHREAD Thread = PsGetCurrentThread();
|
||||||
*/
|
NTSTATUS ExitStatus;
|
||||||
DPRINT1("APC2\n");
|
|
||||||
PspExitThread((NTSTATUS)NormalContext);
|
|
||||||
|
|
||||||
/* we should never reach this point! */
|
DPRINT1("PspExitNormalApc called: 0x%x (proc: 0x%x)\n",
|
||||||
KEBUGCHECK(0);
|
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 */
|
/* Allocate the APC */
|
||||||
Apc = ExAllocatePoolWithTag(NonPagedPool, sizeof(KAPC), TAG_TERMINATE_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,
|
KeInitializeApc(Apc,
|
||||||
&Thread->Tcb,
|
&Thread->Tcb,
|
||||||
OriginalApcEnvironment,
|
OriginalApcEnvironment,
|
||||||
PsExitSpecialApc,
|
PsExitSpecialApc,
|
||||||
NULL,
|
NULL,
|
||||||
PspExitNormalApc,
|
PspExitNormalApc,
|
||||||
UserMode,
|
KernelMode,
|
||||||
(PVOID)ExitStatus);
|
(PVOID)ExitStatus);
|
||||||
|
|
||||||
/* Insert it into the APC Queue */
|
/* Insert it into the APC Queue */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue