mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +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
|
@ -567,9 +567,9 @@ KiDeliverApc(KPROCESSOR_MODE DeliveryMode,
|
||||||
Apc = CONTAINING_RECORD(ApcListEntry, KAPC, ApcListEntry);
|
Apc = CONTAINING_RECORD(ApcListEntry, KAPC, ApcListEntry);
|
||||||
|
|
||||||
/* Save Parameters so that it's safe to free the Object in Kernel Routine*/
|
/* Save Parameters so that it's safe to free the Object in Kernel Routine*/
|
||||||
NormalRoutine = Apc->NormalRoutine;
|
NormalRoutine = Apc->NormalRoutine;
|
||||||
KernelRoutine = Apc->KernelRoutine;
|
KernelRoutine = Apc->KernelRoutine;
|
||||||
NormalContext = Apc->NormalContext;
|
NormalContext = Apc->NormalContext;
|
||||||
SystemArgument1 = Apc->SystemArgument1;
|
SystemArgument1 = Apc->SystemArgument1;
|
||||||
SystemArgument2 = Apc->SystemArgument2;
|
SystemArgument2 = Apc->SystemArgument2;
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -586,10 +586,10 @@ KiDeliverApc(KPROCESSOR_MODE DeliveryMode,
|
||||||
/* Call the Special APC */
|
/* Call the Special APC */
|
||||||
DPRINT("Delivering a Special APC: %x\n", Apc);
|
DPRINT("Delivering a Special APC: %x\n", Apc);
|
||||||
KernelRoutine(Apc,
|
KernelRoutine(Apc,
|
||||||
&NormalRoutine,
|
&NormalRoutine,
|
||||||
&NormalContext,
|
&NormalContext,
|
||||||
&SystemArgument1,
|
&SystemArgument1,
|
||||||
&SystemArgument2);
|
&SystemArgument2);
|
||||||
|
|
||||||
/* Raise IRQL and Lock again */
|
/* Raise IRQL and Lock again */
|
||||||
KeAcquireSpinLock(&Thread->ApcQueueLock, &OldIrql);
|
KeAcquireSpinLock(&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);
|
||||||
|
@ -621,10 +621,10 @@ KiDeliverApc(KPROCESSOR_MODE DeliveryMode,
|
||||||
/* Call the Kernel APC */
|
/* Call the Kernel APC */
|
||||||
DPRINT("Delivering a Normal APC: %x\n", Apc);
|
DPRINT("Delivering a Normal APC: %x\n", Apc);
|
||||||
KernelRoutine(Apc,
|
KernelRoutine(Apc,
|
||||||
&NormalRoutine,
|
&NormalRoutine,
|
||||||
&NormalContext,
|
&NormalContext,
|
||||||
&SystemArgument1,
|
&SystemArgument1,
|
||||||
&SystemArgument2);
|
&SystemArgument2);
|
||||||
|
|
||||||
/* If There still is a Normal Routine, then we need to call this at PASSIVE_LEVEL */
|
/* If There still is a Normal Routine, then we need to call this at PASSIVE_LEVEL */
|
||||||
if (NormalRoutine != NULL) {
|
if (NormalRoutine != NULL) {
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -657,23 +657,23 @@ KiDeliverApc(KPROCESSOR_MODE DeliveryMode,
|
||||||
Apc = CONTAINING_RECORD(ApcListEntry, KAPC, ApcListEntry);
|
Apc = CONTAINING_RECORD(ApcListEntry, KAPC, ApcListEntry);
|
||||||
|
|
||||||
/* Save Parameters so that it's safe to free the Object in Kernel Routine*/
|
/* Save Parameters so that it's safe to free the Object in Kernel Routine*/
|
||||||
NormalRoutine = Apc->NormalRoutine;
|
NormalRoutine = Apc->NormalRoutine;
|
||||||
KernelRoutine = Apc->KernelRoutine;
|
KernelRoutine = Apc->KernelRoutine;
|
||||||
NormalContext = Apc->NormalContext;
|
NormalContext = Apc->NormalContext;
|
||||||
SystemArgument1 = Apc->SystemArgument1;
|
SystemArgument1 = Apc->SystemArgument1;
|
||||||
SystemArgument2 = Apc->SystemArgument2;
|
SystemArgument2 = Apc->SystemArgument2;
|
||||||
|
|
||||||
/* 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,
|
||||||
&NormalContext,
|
&NormalContext,
|
||||||
&SystemArgument1,
|
&SystemArgument1,
|
||||||
&SystemArgument2);
|
&SystemArgument2);
|
||||||
|
|
||||||
if (NormalRoutine == NULL) {
|
if (NormalRoutine == NULL) {
|
||||||
|
|
||||||
|
@ -685,11 +685,11 @@ KiDeliverApc(KPROCESSOR_MODE DeliveryMode,
|
||||||
/* Set up the Trap Frame and prepare for Execution in NTDLL.DLL */
|
/* Set up the Trap Frame and prepare for Execution in NTDLL.DLL */
|
||||||
DPRINT("Delivering a User APC: %x\n", Apc);
|
DPRINT("Delivering a User APC: %x\n", Apc);
|
||||||
KiInitializeUserApc(Reserved,
|
KiInitializeUserApc(Reserved,
|
||||||
TrapFrame,
|
TrapFrame,
|
||||||
NormalRoutine,
|
NormalRoutine,
|
||||||
NormalContext,
|
NormalContext,
|
||||||
SystemArgument1,
|
SystemArgument1,
|
||||||
SystemArgument2);
|
SystemArgument2);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -346,18 +346,23 @@ 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);
|
||||||
|
|
||||||
/* Terminate the Thread */
|
/* Terminate the Thread */
|
||||||
PspExitThread(ExitStatus);
|
PspExitThread(ExitStatus);
|
||||||
|
|
||||||
/* 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);
|
DPRINT1("PspExitNormalApc called: 0x%x (proc: 0x%x)\n",
|
||||||
|
PsGetCurrentThread(), PsGetCurrentProcess());
|
||||||
|
|
||||||
/* we should never reach this point! */
|
/* This should never happen */
|
||||||
KEBUGCHECK(0);
|
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…
Reference in a new issue