(Hopefully) fix (parts of) terribly broken NtSet/GetContextThread
functions ;-)
If we have a test for this anywhere, it must be reaaally broken!
Thanks to Alex and KJK for helping!
Modified: trunk/reactos/ntoskrnl/ps/debug.c
_____
Modified: trunk/reactos/ntoskrnl/ps/debug.c
--- trunk/reactos/ntoskrnl/ps/debug.c 2005-11-02 23:57:38 UTC (rev
18963)
+++ trunk/reactos/ntoskrnl/ps/debug.c 2005-11-03 00:09:19 UTC (rev
18964)
@@ -23,6 +23,7 @@
KEVENT Event;
CONTEXT Context;
KPROCESSOR_MODE Mode;
+ NTSTATUS Status;
} GET_SET_CTX_CONTEXT, *PGET_SET_CTX_CONTEXT;
@@ -44,9 +45,11 @@
PKEVENT Event;
PCONTEXT Context;
KPROCESSOR_MODE Mode;
- PETHREAD Thread;
PKTRAP_FRAME TrapFrame;
+ TrapFrame =
(PKTRAP_FRAME)((ULONG_PTR)KeGetCurrentThread()->InitialStack -
+ sizeof (FX_SAVE_AREA) -
sizeof (KTRAP_FRAME));
+
/* Get the Context Structure */
GetSetContext = CONTAINING_RECORD(Apc, GET_SET_CTX_CONTEXT, Apc);
Context = &GetSetContext->Context;
@@ -54,20 +57,21 @@
Mode = GetSetContext->Mode;
Thread = SystemArgument2;
- /* Get trap frame */
- TrapFrame = (PKTRAP_FRAME)((ULONG_PTR)Thread->Tcb.InitialStack -
- sizeof(KTRAP_FRAME) -
sizeof(FX_SAVE_AREA));
-
- /* Check if it's a set or get */
- if (SystemArgument1)
+ if (TrapFrame->Cs == KERNEL_CS && Mode != KernelMode)
{
- /* Get the Context */
- KeTrapFrameToContext(TrapFrame, NULL, Context);
+ GetSetContext->Status = STATUS_ACCESS_DENIED;
}
else
{
- /* Set the Context */
- KeContextToTrapFrame(Context, NULL, TrapFrame, Mode);
+ /* Check if it's a set or get */
+ if (*SystemArgument1) {
+ /* Get the Context */
+ KeTrapFrameToContext(TrapFrame, NULL, Context);
+ } else {
+ /* Set the Context */
+ KeContextToTrapFrame(Context, NULL, TrapFrame, Mode);
+ }
+ GetSetContext->Status = STATUS_SUCCESS;
}
/* Notify the Native API that we are done */
@@ -77,7 +81,7 @@
NTSTATUS
STDCALL
NtGetContextThread(IN HANDLE ThreadHandle,
- OUT PCONTEXT ThreadContext)
+ IN OUT PCONTEXT ThreadContext)
{
PETHREAD Thread;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
@@ -94,6 +98,8 @@
ProbeForWrite(ThreadContext,
sizeof(CONTEXT),
sizeof(ULONG));
+ GetSetContext.Context = *ThreadContext;
+
} _SEH_HANDLE {
Status = _SEH_GetExceptionCode();
@@ -159,6 +165,8 @@
KernelMode,
FALSE,
NULL);
+ if (NT_SUCCESS(Status))
+ Status = GetSetContext.Status;
}
}
@@ -167,7 +175,6 @@
/* Check for success and return the Context */
if(NT_SUCCESS(Status)) {
-
_SEH_TRY {
*ThreadContext = GetSetContext.Context;
@@ -231,13 +238,17 @@
if(Thread == PsGetCurrentThread()) {
/*
- * I don't know if trying to get your own context makes
much
+ * I don't know if trying to set your own context makes
much
* sense but we can handle it more efficently.
*/
- KeContextToTrapFrame(&GetSetContext.Context, NULL,
Thread->Tcb.TrapFrame, PreviousMode);
+ KeContextToTrapFrame(ThreadContext, NULL,
Thread->Tcb.TrapFrame, PreviousMode);
} else {
+ /* Copy context into GetSetContext if not already done */
+ if(PreviousMode == KernelMode)
+ GetSetContext.Context = *ThreadContext;
+
/* Use an APC... Initialize the Event */
KeInitializeEvent(&GetSetContext.Event,
NotificationEvent,
@@ -258,8 +269,8 @@
/* Queue it as a Get APC */
if (!KeInsertQueueApc(&GetSetContext.Apc,
+ (PVOID)0,
NULL,
- NULL,
IO_NO_INCREMENT)) {
Status = STATUS_THREAD_IS_TERMINATING;
@@ -272,6 +283,8 @@
KernelMode,
FALSE,
NULL);
+ if (NT_SUCCESS(Status))
+ Status = GetSetContext.Status;
}
}