(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; } }