/*
- * COPYRIGHT: See COPYING in the top level directory
+ * 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.27 2002/12/11 04:39:20 robd 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)
*/
/* INCLUDES *****************************************************************/
-#include <windows.h>
#include <ddk/ntddk.h>
+#include <roscfg.h>
+#include <internal/ke.h>
+#include <internal/ldr.h>
+#include <internal/ps.h>
+#include <internal/kd.h>
+#define NDEBUG
#include <internal/debug.h>
/* FUNCTIONS ****************************************************************/
-VOID ExRaiseStatus(NTSTATUS Status)
+ULONG
+RtlpDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PCONTEXT Context);
+
+VOID
+KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
+ PCONTEXT Context,
+ PKTRAP_FRAME Tf,
+ KPROCESSOR_MODE PreviousMode,
+ BOOLEAN SearchFrames)
{
- DbgPrint("ExRaiseStatus(%x)\n",Status);
- for(;;);
+ EXCEPTION_DISPOSITION Value;
+ CONTEXT TContext;
+
+ 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 (PreviousMode == UserMode)
+ {
+ if (SearchFrames)
+ {
+ PULONG Stack;
+ ULONG CDest;
+
+ /* FIXME: Give the kernel debugger a chance */
+
+ /* 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 */
+ ZwTerminateThread(NtCurrentThread(), ExceptionRecord->ExceptionCode);
+
+ /* If that fails then bugcheck */
+ DbgPrint("Could not terminate thread\n");
+ KeBugCheck(KMODE_EXCEPTION_NOT_HANDLED);
+ }
+ else
+ {
+ KD_CONTINUE_TYPE Action = kdContinue;
+
+ /* PreviousMode == KernelMode */
+
+ 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)
+ {
+ Value = RtlpDispatchException (ExceptionRecord, Context);
+
+ DPRINT("RtlpDispatchException() returned with 0x%X\n", Value);
+ /*
+ * If RtlpDispatchException() does not handle the exception then
+ * bugcheck
+ */
+ if (Value != ExceptionContinueExecution)
+ {
+ KeBugCheck (KMODE_EXCEPTION_NOT_HANDLED);
+ }
+ }
+ else
+ {
+ KeContextToTrapFrame (Context, KeGetCurrentThread()->TrapFrame);
+ }
+ }
}
+VOID STDCALL
+ExRaiseAccessViolation (VOID)
+{
+ ExRaiseStatus (STATUS_ACCESS_VIOLATION);
+}
+
+VOID STDCALL
+ExRaiseDatatypeMisalignment (VOID)
+{
+ ExRaiseStatus (STATUS_DATATYPE_MISALIGNMENT);
+}
+
+VOID STDCALL
+ExRaiseStatus (IN NTSTATUS Status)
+{
+ EXCEPTION_RECORD ExceptionRecord;
+
+ DPRINT("ExRaiseStatus(%x)\n", Status);
+
+ ExceptionRecord.ExceptionRecord = NULL;
+ ExceptionRecord.NumberParameters = 0;
+ ExceptionRecord.ExceptionCode = Status;
+ ExceptionRecord.ExceptionFlags = 0;
-NTSTATUS
-STDCALL
-NtRaiseException (
- IN PEXCEPTION_RECORD ExceptionRecord,
- IN PCONTEXT Context,
- IN BOOL IsDebugger OPTIONAL
- )
+ RtlRaiseException(&ExceptionRecord);
+}
+
+
+NTSTATUS STDCALL
+NtRaiseException (IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PCONTEXT Context,
+ IN BOOLEAN SearchFrames)
+{
+ KiDispatchException(ExceptionRecord,
+ Context,
+ PsGetCurrentThread()->Tcb.TrapFrame,
+ ExGetPreviousMode(),
+ SearchFrames);
+ return(STATUS_SUCCESS);
+}
+
+
+VOID STDCALL
+RtlRaiseException(PEXCEPTION_RECORD ExceptionRecord)
{
- UNIMPLEMENTED;
+ ZwRaiseException(ExceptionRecord, NULL, TRUE);
}
+
+/* EOF */