(Hopefully) fix (parts of) terribly broken NtSet/GetContextThread functions ;-)
authorGregor Anich <blight@blight.eu.org>
Thu, 3 Nov 2005 00:09:19 +0000 (00:09 +0000)
committerGregor Anich <blight@blight.eu.org>
Thu, 3 Nov 2005 00:09:19 +0000 (00:09 +0000)
If we have a test for this anywhere, it must be reaaally broken!
Thanks to Alex and KJK for helping!

svn path=/trunk/; revision=18964

reactos/ntoskrnl/ps/debug.c

index 82dcf7d..4c7b26e 100644 (file)
@@ -23,6 +23,7 @@ typedef struct _GET_SET_CTX_CONTEXT {
     KEVENT Event;
     CONTEXT Context;
     KPROCESSOR_MODE Mode;
+    NTSTATUS Status;
 } GET_SET_CTX_CONTEXT, *PGET_SET_CTX_CONTEXT;
 
 
@@ -44,9 +45,11 @@ PspGetOrSetContextKernelRoutine(PKAPC Apc,
     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 @@ PspGetOrSetContextKernelRoutine(PKAPC Apc,
     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 @@ PspGetOrSetContextKernelRoutine(PKAPC Apc,
 NTSTATUS
 STDCALL
 NtGetContextThread(IN HANDLE ThreadHandle,
-                   OUT PCONTEXT ThreadContext)
+                   IN OUT PCONTEXT ThreadContext)
 {
     PETHREAD Thread;
     KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
@@ -94,6 +98,8 @@ NtGetContextThread(IN HANDLE ThreadHandle,
             ProbeForWrite(ThreadContext,
                           sizeof(CONTEXT),
                           sizeof(ULONG));
+            GetSetContext.Context = *ThreadContext;
+
         } _SEH_HANDLE {
 
             Status = _SEH_GetExceptionCode();
@@ -159,6 +165,8 @@ NtGetContextThread(IN HANDLE ThreadHandle,
                                                KernelMode,
                                                FALSE,
                                                NULL);
+                if (NT_SUCCESS(Status))
+                    Status = GetSetContext.Status;
             }
         }
 
@@ -167,7 +175,6 @@ NtGetContextThread(IN HANDLE ThreadHandle,
 
         /* Check for success and return the Context */
         if(NT_SUCCESS(Status)) {
-
             _SEH_TRY {
 
                 *ThreadContext = GetSetContext.Context;
@@ -231,13 +238,17 @@ NtSetContextThread(IN HANDLE ThreadHandle,
         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,7 +269,7 @@ NtSetContextThread(IN HANDLE ThreadHandle,
 
             /* Queue it as a Get APC */
             if (!KeInsertQueueApc(&GetSetContext.Apc,
-                                  NULL,
+                                  (PVOID)0,
                                   NULL,
                                   IO_NO_INCREMENT)) {
 
@@ -272,6 +283,8 @@ NtSetContextThread(IN HANDLE ThreadHandle,
                                                KernelMode,
                                                FALSE,
                                                NULL);
+                if (NT_SUCCESS(Status))
+                    Status = GetSetContext.Status;
             }
         }