Author: ion
Date: Wed Aug 30 20:58:12 2006
New Revision: 23802
URL: 
http://svn.reactos.org/svn/reactos?rev=23802&view=rev
Log:
- Some fixes to KiDispatchException: Add support for forwarding exception back to
user-mode, protect against V86 or invalid-stack faults, handle stack overflow exception
while handling usermode exception (Thanks KJK for the SEH_FILTER help). Decrement EIP by
one when hitting an INT3, to get the correct address.
- Remove two associated kernel fun entries.
Modified:
    trunk/reactos/ntoskrnl/KrnlFun.c
    trunk/reactos/ntoskrnl/dbgk/debug.c
    trunk/reactos/ntoskrnl/include/internal/dbgk.h
    trunk/reactos/ntoskrnl/include/internal/ke.h
    trunk/reactos/ntoskrnl/ke/i386/exp.c
Modified: trunk/reactos/ntoskrnl/KrnlFun.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/KrnlFun.c?rev=238…
==============================================================================
--- trunk/reactos/ntoskrnl/KrnlFun.c (original)
+++ trunk/reactos/ntoskrnl/KrnlFun.c Wed Aug 30 20:58:12 2006
@@ -25,9 +25,7 @@
 //  - Use Object Type Mutex/Lock.
 //
 // Ke:
-//  - Add PSEH handler when an exception occurs in an exception (KiCopyExceptionRecord).
 //  - Get rid of KiRosPrintAddress and use KiDumpParameterImages instead.
-//  - Forward exceptions to user-mode debugger.
 //  - Sanitize some context fields during conversions.
 //  - Implement stack fault and segment fault handlers.
 //  - Implement kernel-mode GPF handler, possibly fixing below:
Modified: trunk/reactos/ntoskrnl/dbgk/debug.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/dbgk/debug.c?rev=…
==============================================================================
--- trunk/reactos/ntoskrnl/dbgk/debug.c (original)
+++ trunk/reactos/ntoskrnl/dbgk/debug.c Wed Aug 30 20:58:12 2006
@@ -24,6 +24,17 @@
 {
     /* FIXME: Implement */
 }
+
+BOOLEAN
+NTAPI
+DbgkForwardException(IN PEXCEPTION_RECORD ExceptionRecord,
+                     IN BOOLEAN DebugPort,
+                     IN BOOLEAN SecondChance)
+{
+    /* FIXME: Implement */
+    return FALSE;
+}
+
 NTSTATUS
 NTAPI
Modified: trunk/reactos/ntoskrnl/include/internal/dbgk.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/dbgk.h (original)
+++ trunk/reactos/ntoskrnl/include/internal/dbgk.h Wed Aug 30 20:58:12 2006
@@ -20,6 +20,14 @@
     IN PEPROCESS Parent
 );
+BOOLEAN
+NTAPI
+DbgkForwardException(
+    IN PEXCEPTION_RECORD ExceptionRecord,
+    IN BOOLEAN DebugPort,
+    IN BOOLEAN SecondChance
+);
+
 extern POBJECT_TYPE DbgkDebugObjectType;
 #endif
Modified: trunk/reactos/ntoskrnl/include/internal/ke.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/ke.h (original)
+++ trunk/reactos/ntoskrnl/include/internal/ke.h Wed Aug 30 20:58:12 2006
@@ -691,13 +691,6 @@
     ULONG FrameCount
 );
-ULONG
-STDCALL
-KeRosGetStackFrames(
-    PULONG Frames,
-    ULONG FrameCount
-);
-
 VOID
 NTAPI
 KiSetSystemTime(PLARGE_INTEGER NewSystemTime);
Modified: trunk/reactos/ntoskrnl/ke/i386/exp.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/exp.c?rev…
==============================================================================
--- trunk/reactos/ntoskrnl/ke/i386/exp.c (original)
+++ trunk/reactos/ntoskrnl/ke/i386/exp.c Wed Aug 30 20:58:12 2006
@@ -15,6 +15,22 @@
 #include <debug.h>
 /* FUNCTIONS *****************************************************************/
+
+_SEH_DEFINE_LOCALS(KiCopyInfo)
+{
+    volatile EXCEPTION_RECORD SehExceptRecord;
+};
+
+_SEH_FILTER(KiCopyInformation)
+{
+    _SEH_ACCESS_LOCALS(KiCopyInfo);
+
+    /* Copy the exception records and return to the handler */
+    RtlMoveMemory((PVOID)&_SEH_VAR(SehExceptRecord),
+                  _SEH_GetExceptionPointers()->ExceptionRecord,
+                  sizeof(EXCEPTION_RECORD));
+    return EXCEPTION_EXECUTE_HANDLER;
+}
 VOID
 INIT_FUNCTION
@@ -588,7 +604,8 @@
     KD_CONTINUE_TYPE Action;
     ULONG_PTR Stack, NewStack;
     ULONG Size;
-    BOOLEAN UserDispatch = FALSE;
+    EXCEPTION_RECORD LocalExceptRecord;
+    _SEH_DECLARE_LOCALS(KiCopyInfo);
     /* Increase number of Exception Dispatches */
     KeGetCurrentPrcb()->KeExceptionDispatchCount++;
@@ -596,16 +613,32 @@
     /* Set the context flags */
     Context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
-    /* Check if User Mode */
-    if (PreviousMode == UserMode)
+    /* Check if User Mode or if the debugger isenabled */
+    if ((PreviousMode == UserMode) || (KdDebuggerEnabled))
     {
         /* Add the FPU Flag */
         Context.ContextFlags |= CONTEXT_FLOATING_POINT;
-        if (KeI386FxsrPresent) Context.ContextFlags |= CONTEXT_EXTENDED_REGISTERS;
+
+        /* Check for NPX Support */
+        if (KeI386FxsrPresent)
+        {
+            /* Save those too */
+            Context.ContextFlags |= CONTEXT_EXTENDED_REGISTERS;
+        }
     }
     /* Get a Context */
     KeTrapFrameToContext(TrapFrame, ExceptionFrame, &Context);
+
+    /* Fix up EIP */
+    if (ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT)
+    {
+        /* Decrement EIP by one */
+        Context.Eip--;
+    }
+
+    ASSERT(!((PreviousMode == KernelMode) &&
+             (Context.EFlags & EFLAGS_V86_MASK)));
     /* Handle kernel-mode first, it's simpler */
     if (PreviousMode == KernelMode)
@@ -625,11 +658,7 @@
             if (Action == kdContinue) goto Handled;
             /* If the Debugger couldn't handle it, dispatch the exception */
-            if (RtlDispatchException(ExceptionRecord, &Context))
-            {
-                /* It was handled by an exception handler, continue */
-                goto Handled;
-            }
+            if (RtlDispatchException(ExceptionRecord, &Context)) goto Handled;
         }
         /* This is a second-chance exception, only for the debugger */
@@ -644,12 +673,11 @@
         if (Action == kdContinue) goto Handled;
         /* Third strike; you're out */
-        KEBUGCHECKWITHTF(KMODE_EXCEPTION_NOT_HANDLED,
-                         ExceptionRecord->ExceptionCode,
-                         (ULONG_PTR)ExceptionRecord->ExceptionAddress,
-                         ExceptionRecord->ExceptionInformation[0],
-                         ExceptionRecord->ExceptionInformation[1],
-                         TrapFrame);
+        KeBugCheckEx(KMODE_EXCEPTION_NOT_HANDLED,
+                     ExceptionRecord->ExceptionCode,
+                     (ULONG_PTR)ExceptionRecord->ExceptionAddress,
+                     ExceptionRecord->ExceptionInformation[0],
+                     ExceptionRecord->ExceptionInformation[1]);
     }
     else
     {
@@ -668,27 +696,39 @@
             if (Action == kdContinue) goto Handled;
             /* FIXME: Forward exception to user mode debugger */
+            if (DbgkForwardException(ExceptionRecord, TRUE, FALSE)) goto Exit;
             /* Set up the user-stack */
+DispatchToUser:
             _SEH_TRY
             {
+                /* Make sure we have a valid SS and that this isn't V86 mode */
+                if ((TrapFrame->HardwareSegSs != (KGDT_R3_DATA | RPL_MASK)) ||
+                    (TrapFrame->EFlags & EFLAGS_V86_MASK))
+                {
+                    /* Raise an exception instead */
+                    LocalExceptRecord.ExceptionCode = STATUS_ACCESS_VIOLATION;
+                    LocalExceptRecord.ExceptionFlags = 0;
+                    LocalExceptRecord.NumberParameters = 0;
+                    RtlRaiseException(&LocalExceptRecord);
+                }
+
                 /* Align context size and get stack pointer */
                 Size = (sizeof(CONTEXT) + 3) & ~3;
                 Stack = (Context.Esp & ~3) - Size;
-                DPRINT("Stack: %lx\n", Stack);
                 /* Probe stack and copy Context */
                 ProbeForWrite((PVOID)Stack, Size, sizeof(ULONG));
                 RtlCopyMemory((PVOID)Stack, &Context, sizeof(CONTEXT));
                 /* Align exception record size and get stack pointer */
-                Size = (sizeof(EXCEPTION_RECORD) -
-                        (EXCEPTION_MAXIMUM_PARAMETERS -
ExceptionRecord->NumberParameters) *
-                        sizeof(ULONG) + 3) & ~3;
+                Size = (sizeof(EXCEPTION_RECORD) -
+                       (EXCEPTION_MAXIMUM_PARAMETERS -
+                        ExceptionRecord->NumberParameters) *
+                       sizeof(ULONG) + 3) & ~3;
                 NewStack = Stack - Size;
-                DPRINT("NewStack: %lx\n", NewStack);
-
-                /* Probe stack and copy exception record. Don't forget to add the two
params */
+
+                /* Probe stack and copy exception record */
                 ProbeForWrite((PVOID)(NewStack - 2 * sizeof(ULONG_PTR)),
                               Size +  2 * sizeof(ULONG_PTR),
                               sizeof(ULONG));
@@ -699,34 +739,59 @@
                 *(PULONG_PTR)(NewStack - 2 * sizeof(ULONG_PTR)) = NewStack;
                 /* Set new Stack Pointer */
+                KiSsToTrapFrame(TrapFrame, KGDT_R3_DATA);
                 KiEspToTrapFrame(TrapFrame, NewStack - 2 * sizeof(ULONG_PTR));
+
+                /* Force correct segments */
+                TrapFrame->SegCs = KGDT_R3_CODE | RPL_MASK;
+                TrapFrame->SegDs = KGDT_R3_DATA | RPL_MASK;
+                TrapFrame->SegEs = KGDT_R3_DATA | RPL_MASK;
+                TrapFrame->SegFs = KGDT_R3_TEB | RPL_MASK;
+                TrapFrame->SegGs = 0;
                 /* Set EIP to the User-mode Dispathcer */
                 TrapFrame->Eip = (ULONG)KeUserExceptionDispatcher;
-                UserDispatch = TRUE;
                 _SEH_LEAVE;
             }
-            _SEH_HANDLE
-            {
-                /* Do second-chance */
+            _SEH_EXCEPT(KiCopyInformation)
+            {
+                /* Check if we got a stack overflow and raise that instead */
+                if (_SEH_VAR(SehExceptRecord).ExceptionCode ==
+                    STATUS_STACK_OVERFLOW)
+                {
+                    /* Copy the exception address and record */
+                    _SEH_VAR(SehExceptRecord).ExceptionAddress =
+                        ExceptionRecord->ExceptionAddress;
+                    RtlMoveMemory(ExceptionRecord,
+                                  (PVOID)&_SEH_VAR(SehExceptRecord),
+                                  sizeof(EXCEPTION_RECORD));
+
+                    /* Do the exception again */
+                    goto DispatchToUser;
+                }
             }
             _SEH_END;
         }
-        /* If we dispatch to user, return now */
-        if (UserDispatch) return;
-
-        /* FIXME: Forward the exception to the debugger for 2nd chance */
-
-        /* 3rd strike, kill the thread */
-        DPRINT1("Unhandled UserMode exception, terminating thread\n");
-        ZwTerminateThread(NtCurrentThread(), ExceptionRecord->ExceptionCode);
-        KEBUGCHECKWITHTF(KMODE_EXCEPTION_NOT_HANDLED,
-                         ExceptionRecord->ExceptionCode,
-                         (ULONG_PTR)ExceptionRecord->ExceptionAddress,
-                         ExceptionRecord->ExceptionInformation[0],
-                         ExceptionRecord->ExceptionInformation[1],
-                         TrapFrame);
+        /* Try second chance */
+        if (DbgkForwardException(ExceptionRecord, TRUE, FALSE))
+        {
+            /* Handled, get out */
+            goto Exit;
+        }
+        else if (DbgkForwardException(ExceptionRecord, FALSE, TRUE))
+        {
+            /* Handled, get out */
+            goto Exit;
+        }
+
+        /* 3rd strike, kill the process */
+        ZwTerminateProcess(NtCurrentProcess(), ExceptionRecord->ExceptionCode);
+        KeBugCheckEx(KMODE_EXCEPTION_NOT_HANDLED,
+                     ExceptionRecord->ExceptionCode,
+                     (ULONG_PTR)ExceptionRecord->ExceptionAddress,
+                     ExceptionRecord->ExceptionInformation[0],
+                     ExceptionRecord->ExceptionInformation[1]);
     }
 Handled:
@@ -736,6 +801,7 @@
                          TrapFrame,
                          Context.ContextFlags,
                          PreviousMode);
+Exit:
     return;
 }