- KeInitializeApc(&Apc,
- &Thread->Tcb,
- 0,
- KeGetContextKernelRoutine,
- KeGetContextRundownRoutine,
- NULL,
- KernelMode,
- (PVOID)&KContext);
- KeInsertQueueApc(&Apc,
- (PVOID)&Event,
- (PVOID)&AStatus,
- 0);
- Status = KeWaitForSingleObject(&Event,
- 0,
- UserMode,
- FALSE,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- return(Status);
- }
- if (!NT_SUCCESS(AStatus))
- {
- return(AStatus);
- }
- memcpy(Context, &KContext, sizeof(CONTEXT));
- ObDereferenceObject(Thread);
- return(STATUS_SUCCESS);
- }
+ KeInitializeApc(&Apc,
+ &Thread->Tcb,
+ OriginalApcEnvironment,
+ KeGetContextKernelRoutine,
+ KeGetSetContextRundownRoutine,
+ NULL,
+ KernelMode,
+ (PVOID)&Context);
+ if (!KeInsertQueueApc(&Apc,
+ (PVOID)&Event,
+ (PVOID)&AStatus,
+ IO_NO_INCREMENT))
+ {
+ Status = STATUS_THREAD_IS_TERMINATING;
+ }
+ else
+ {
+ Status = KeWaitForSingleObject(&Event,
+ 0,
+ UserMode,
+ FALSE,
+ NULL);
+ if (NT_SUCCESS(Status) && !NT_SUCCESS(AStatus))
+ {
+ Status = AStatus;
+ }
+ }
+ }
+ if (NT_SUCCESS(Status))
+ {
+ Status = MmCopyToCaller(UnsafeContext, &Context, sizeof(Context));
+ }
+
+ ObDereferenceObject(Thread);
+ return Status;
+}
+
+VOID STDCALL
+KeSetContextKernelRoutine(PKAPC Apc,
+ PKNORMAL_ROUTINE* NormalRoutine,
+ PVOID* NormalContext,
+ PVOID* SystemArgument1,
+ PVOID* SystemArgument2)
+/*
+ * FUNCTION: This routine is called by an APC sent by NtSetContextThread to
+ * set the context of a thread from a buffer.
+ */
+{
+ PKEVENT Event;
+ PCONTEXT Context;
+ PNTSTATUS Status;
+
+ Context = (PCONTEXT)(*NormalContext);
+ Event = (PKEVENT)(*SystemArgument1);
+ Status = (PNTSTATUS)(*SystemArgument2);
+
+ KeContextToTrapFrame(Context, KeGetCurrentThread()->TrapFrame);
+
+ *Status = STATUS_SUCCESS;
+ KeSetEvent(Event, IO_NO_INCREMENT, FALSE);