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
|
@ -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,
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in a new issue