KD System Rewrite:
[reactos.git] / reactos / ntoskrnl / ke / catch.c
index 03a369e..ac3a9df 100644 (file)
@@ -1,40 +1,17 @@
 /*
- *  ReactOS kernel
- *  Copyright (C) 2000  ReactOS Team
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-/* $Id: catch.c,v 1.34 2003/07/21 21:53:51 royce Exp $
- *
- * PROJECT:              ReactOS kernel
- * FILE:                 ntoskrnl/ke/catch.c
- * PURPOSE:              Exception handling
- * PROGRAMMER:           David Welch (welch@mcmail.com)
- *                       Casper S. Hornstrup (chorns@users.sourceforge.net)
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS kernel
+ * FILE:            ntoskrnl/ke/catch.c
+ * PURPOSE:         Exception handling
+ * 
+ * PROGRAMMERS:     Anich Gregor
+ *                  David Welch (welch@mcmail.com)
+ *                  Casper S. Hornstrup (chorns@users.sourceforge.net)
  */
 
 /* INCLUDES *****************************************************************/
 
-#include <ddk/ntddk.h>
-#include <reactos/bugcodes.h>
-#include <roscfg.h>
-#include <internal/ke.h>
-#include <internal/ldr.h>
-#include <internal/ps.h>
-#include <internal/kd.h>
-
+#include <ntoskrnl.h>
 #define NDEBUG
 #include <internal/debug.h>
 
 
 ULONG
 RtlpDispatchException(IN PEXCEPTION_RECORD  ExceptionRecord,
-       IN PCONTEXT  Context);
-
-VOID 
-KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
-                   PCONTEXT Context,
-                   PKTRAP_FRAME Tf,
-                   KPROCESSOR_MODE PreviousMode,
-                   BOOLEAN SearchFrames)
-{
-  EXCEPTION_DISPOSITION Value;
-  CONTEXT TContext;
-  KD_CONTINUE_TYPE Action = kdContinue;
-
-  DPRINT("KiDispatchException() called\n");
-
-  /* PCR->KeExceptionDispatchCount++; */
-
-  if (Context == NULL)
-    {
-      TContext.ContextFlags = CONTEXT_FULL;
-      if (PreviousMode == UserMode)
-       {
-         TContext.ContextFlags = TContext.ContextFlags | CONTEXT_DEBUGGER;
-       }
-  
-      KeTrapFrameToContext(Tf, &TContext);
-
-      Context = &TContext;
-    }
-
-#if 0
-  if (ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) 
-    {
-      Context->Eip--;
-    }
-#endif
-      
-  if (KdDebuggerEnabled && KdDebugState & KD_DEBUG_GDB)
-    {
-      Action = KdEnterDebuggerException (ExceptionRecord, Context, Tf);
-    }
-#ifdef KDBG
-  else if (KdDebuggerEnabled && KdDebugState & KD_DEBUG_KDB)
-    {
-      Action = KdbEnterDebuggerException (ExceptionRecord, Context, Tf);
-    }
-#endif /* KDBG */
-  if (Action != kdHandleException)
-    {
-      if (PreviousMode == UserMode)
-       {
-         if (SearchFrames)
-           {
-             PULONG Stack;
-             ULONG CDest;
-
-             /* FIXME: Forward exception to user mode debugger */
-
-             /* FIXME: Check user mode stack for enough space */
-         
-             /*
-              * Let usermode try and handle the exception
-              */
-             Tf->Esp = Tf->Esp - 
-               (12 + sizeof(EXCEPTION_RECORD) + sizeof(CONTEXT));
-             Stack = (PULONG)Tf->Esp;
-             CDest = 3 + (ROUND_UP(sizeof(EXCEPTION_RECORD), 4) / 4);
-             /* Return address */
-             Stack[0] = 0;    
-             /* Pointer to EXCEPTION_RECORD structure */
-             Stack[1] = (ULONG)&Stack[3];   
-             /* Pointer to CONTEXT structure */
-             Stack[2] = (ULONG)&Stack[CDest];     
-             memcpy(&Stack[3], ExceptionRecord, sizeof(EXCEPTION_RECORD));
-             memcpy(&Stack[CDest], Context, sizeof(CONTEXT));
-
-             Tf->Eip = (ULONG)LdrpGetSystemDllExceptionDispatcher();
-             return;
-           }
-      
-         /* FIXME: Forward the exception to the debugger */
-
-         /* FIXME: Forward the exception to the process exception port */
-
-         /* Terminate the offending thread */
-         DPRINT1("Unhandled UserMode exception, terminating thread\n");
-         ZwTerminateThread(NtCurrentThread(), ExceptionRecord->ExceptionCode);
-
-         /* If that fails then bugcheck */
-         DPRINT1("Could not terminate thread\n");
-         KEBUGCHECK(KMODE_EXCEPTION_NOT_HANDLED);
-       }
-      else
-       {
-         /* PreviousMode == KernelMode */
-         Value = RtlpDispatchException (ExceptionRecord, Context);
-         
-         DPRINT("RtlpDispatchException() returned with 0x%X\n", Value);
-         /* 
-          * If RtlpDispatchException() does not handle the exception then 
-          * bugcheck 
-          */
-         if (Value != ExceptionContinueExecution ||
-             0 != (ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE))
-           {
-              KEBUGCHECKWITHTF(KMODE_EXCEPTION_NOT_HANDLED, 0, 0, 0, 0, Tf);         
-           }
-       }
-    }
-  else
-    {
-      KeContextToTrapFrame (Context, KeGetCurrentThread()->TrapFrame);
-    }
-}
+                      IN PCONTEXT  Context);
 
 /*
- * @implemented
+ * @unimplemented
  */
-VOID STDCALL
-ExRaiseAccessViolation (VOID)
+VOID
+STDCALL
+KiCoprocessorError(VOID)
 {
-  ExRaiseStatus (STATUS_ACCESS_VIOLATION);
+    UNIMPLEMENTED;
 }
 
 /*
- * @implemented
+ * @unimplemented
  */
-VOID STDCALL
-ExRaiseDatatypeMisalignment (VOID)
+VOID
+STDCALL
+KiUnexpectedInterrupt(VOID)
 {
-  ExRaiseStatus (STATUS_DATATYPE_MISALIGNMENT);
+    UNIMPLEMENTED;
 }
 
-/*
- * @implemented
- */
-VOID STDCALL
-ExRaiseStatus (IN NTSTATUS Status)
+VOID
+KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
+                    PCONTEXT Context,
+                    PKTRAP_FRAME Tf,
+                    KPROCESSOR_MODE PreviousMode,
+                    BOOLEAN SearchFrames)
 {
-  EXCEPTION_RECORD ExceptionRecord;
-
-  DPRINT("ExRaiseStatus(%x)\n", Status);
+    EXCEPTION_DISPOSITION Value;
+    CONTEXT TContext;
+    KD_CONTINUE_TYPE Action = kdHandleException;
 
-  ExceptionRecord.ExceptionRecord = NULL;
-  ExceptionRecord.NumberParameters = 0;
-  ExceptionRecord.ExceptionCode = Status;
-  ExceptionRecord.ExceptionFlags = 0;
-
-  RtlRaiseException(&ExceptionRecord);
-}
+    DPRINT("KiDispatchException() called\n");
 
+    /* Increase number of Exception Dispatches */
+    KeGetCurrentPrcb()->KeExceptionDispatchCount++;
 
-NTSTATUS STDCALL
-NtRaiseException (IN PEXCEPTION_RECORD ExceptionRecord,
-                 IN PCONTEXT Context,
-                 IN BOOLEAN SearchFrames)
-{
-  KiDispatchException(ExceptionRecord,
-                     Context,
-                     PsGetCurrentThread()->Tcb.TrapFrame,
-                     ExGetPreviousMode(),
-                     SearchFrames);
-  return(STATUS_SUCCESS);
-}
+    if (!Context)    
+    {
+        /* Assume Full context */
+        TContext.ContextFlags = CONTEXT_FULL;
+        
+        /* Check the mode */
+        if (PreviousMode == UserMode) 
+        {
+            /* Add Debugger Registers if this is User Mode */
+            TContext.ContextFlags = TContext.ContextFlags | CONTEXT_DEBUGGER;
+        }
+  
+        /* Convert the Trapframe into a Context */
+        KeTrapFrameToContext(Tf, &TContext);
 
+        /* Use local stack context */
+        Context = &TContext;
+    }
 
-/*
- * @implemented
- */
-VOID STDCALL
-RtlRaiseException(PEXCEPTION_RECORD ExceptionRecord)
-{
-  ZwRaiseException(ExceptionRecord, NULL, TRUE);
+    /* Break into Debugger */
+    Action = KdpEnterDebuggerException(ExceptionRecord, 
+                                       PreviousMode, 
+                                       Context, 
+                                       Tf, 
+                                       TRUE,
+                                       TRUE);
+
+    /* If the debugger said continue, then continue */
+    if (Action == kdContinue) return;
+    
+    /* If the Debugger couldn't handle it... */
+    if (Action != kdDoNotHandleException) 
+    {   
+        /* See what kind of Exception this is */
+        if (PreviousMode == UserMode) 
+        {       
+            /* User mode exception, search the frames if we have to */
+            if (SearchFrames) 
+            {
+                PULONG Stack;
+                ULONG CDest;
+                char temp_space[12 + sizeof(EXCEPTION_RECORD) + sizeof(CONTEXT)]; /* FIXME: HACKHACK */
+                PULONG pNewUserStack = (PULONG)(Tf->Esp - (12 + sizeof(EXCEPTION_RECORD) + sizeof(CONTEXT)));
+                NTSTATUS StatusOfCopy;
+
+                /* Enter Debugger if available */
+                Action = KdpEnterDebuggerException(ExceptionRecord, 
+                                                   PreviousMode,
+                                                   Context, 
+                                                   Tf, 
+                                                   TRUE,
+                                                   FALSE);
+
+                /* Exit if we're continuing */
+                if (Action == kdContinue) return;
+
+                /* FIXME: Forward exception to user mode debugger */
+
+                /* FIXME: Check user mode stack for enough space */
+        
+                /* Let usermode try and handle the exception. Setup Stack */
+                Stack = (PULONG)temp_space;
+                CDest = 3 + (ROUND_UP(sizeof(EXCEPTION_RECORD), 4) / 4);
+                /* Return Address */
+                Stack[0] = 0;
+                /* Pointer to EXCEPTION_RECORD structure */
+                Stack[1] = (ULONG)&pNewUserStack[3];
+                /* Pointer to CONTEXT structure */
+                Stack[2] = (ULONG)&pNewUserStack[CDest];
+                memcpy(&Stack[3], ExceptionRecord, sizeof(EXCEPTION_RECORD));
+                memcpy(&Stack[CDest], Context, sizeof(CONTEXT));
+                
+                /* Copy Stack */
+                StatusOfCopy = MmCopyToCaller(pNewUserStack,
+                                              temp_space,
+                                              (12 + sizeof(EXCEPTION_RECORD) + sizeof(CONTEXT)));
+                
+                /* Check for success */
+                if (NT_SUCCESS(StatusOfCopy)) 
+                {
+                    /* Set new Stack Pointer */
+                    Tf->Esp = (ULONG)pNewUserStack;
+                } 
+                else 
+                { 
+                    /*
+                     * Now it really hit the ventilation device. Sorry,
+                     * can do nothing but kill the sucker.
+                     */
+                    ZwTerminateThread(NtCurrentThread(), ExceptionRecord->ExceptionCode);
+                    DPRINT1("User-mode stack was invalid. Terminating target thread\n");
+                }
+                /* Set EIP to the User-mode Dispathcer */
+                Tf->Eip = (ULONG)LdrpGetSystemDllExceptionDispatcher();
+                return;
+            }
+
+            /* FIXME: Forward the exception to the debugger */
+
+            /* FIXME: Forward the exception to the process exception port */
+
+            /* Enter KDB if available */
+            Action = KdpEnterDebuggerException(ExceptionRecord, 
+                                                PreviousMode,
+                                                Context, 
+                                                Tf, 
+                                                FALSE,
+                                                FALSE);
+
+            /* Exit if we're continuing */
+            if (Action == kdContinue) return;
+
+            /* Terminate the offending thread */
+            DPRINT1("Unhandled UserMode exception, terminating thread\n");
+            ZwTerminateThread(NtCurrentThread(), ExceptionRecord->ExceptionCode);
+        } 
+        else 
+        {
+            /* This is Kernel Mode */            
+
+            /* Enter KDB if available */
+            Action = KdpEnterDebuggerException(ExceptionRecord, 
+                                                PreviousMode,
+                                                Context, 
+                                                Tf, 
+                                                TRUE,
+                                                FALSE);
+
+            /* Exit if we're continuing */
+            if (Action == kdContinue) return;
+
+            /* Dispatch the Exception */
+            Value = RtlpDispatchException (ExceptionRecord, Context);
+            DPRINT("RtlpDispatchException() returned with 0x%X\n", Value);
+        
+            /* If RtlpDispatchException() did not handle the exception then bugcheck */
+            if (Value != ExceptionContinueExecution ||
+                0 != (ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE))    
+            {
+                DPRINT("ExceptionRecord->ExceptionAddress = 0x%x\n", ExceptionRecord->ExceptionAddress);
+
+                /* Enter KDB if available */
+                Action = KdpEnterDebuggerException(ExceptionRecord, 
+                                                   PreviousMode,
+                                                   Context, 
+                                                   Tf, 
+                                                   FALSE,
+                                                   FALSE);
+
+                /* Exit if we're continuing */
+                if (Action == kdContinue) return;
+
+                KEBUGCHECKWITHTF(KMODE_EXCEPTION_NOT_HANDLED, 
+                                 ExceptionRecord->ExceptionCode, 
+                                 (ULONG)ExceptionRecord->ExceptionAddress,
+                                 ExceptionRecord->ExceptionInformation[0],
+                                 ExceptionRecord->ExceptionInformation[1],
+                                 Tf);
+            }
+        }
+    }
 }
 
 /* EOF */