3 * Copyright (C) 2000 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 * PROJECT: ReactOS kernel
22 * FILE: ntoskrnl/ke/catch.c
23 * PURPOSE: Exception handling
24 * PROGRAMMER: David Welch (welch@mcmail.com)
25 * Casper S. Hornstrup (chorns@users.sourceforge.net)
28 /* INCLUDES *****************************************************************/
30 #include <ddk/ntddk.h>
32 #include <reactos/bugcodes.h>
33 #endif /* LIBCAPTIVE */
35 #include <internal/ke.h>
36 #include <internal/ldr.h>
37 #include <internal/ps.h>
38 #include <internal/kd.h>
41 #include <internal/debug.h>
43 /* FUNCTIONS ****************************************************************/
46 RtlpDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,
50 KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
53 KPROCESSOR_MODE PreviousMode,
56 EXCEPTION_DISPOSITION Value;
59 #endif /* LIBCAPTIVE */
60 KD_CONTINUE_TYPE Action = kdContinue;
62 DPRINT("KiDispatchException() called\n");
64 /* PCR->KeExceptionDispatchCount++; */
69 TContext.ContextFlags = CONTEXT_FULL;
70 if (PreviousMode == UserMode)
72 TContext.ContextFlags = TContext.ContextFlags | CONTEXT_DEBUGGER;
75 KeTrapFrameToContext(Tf, &TContext);
79 #endif /* LIBCAPTIVE */
82 if (ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT)
89 if (KdDebuggerEnabled && KdDebugState & KD_DEBUG_GDB)
91 Action = KdEnterDebuggerException (ExceptionRecord, Context, Tf);
94 else if (KdDebuggerEnabled && KdDebugState & KD_DEBUG_KDB)
96 Action = KdbEnterDebuggerException (ExceptionRecord, Context, Tf);
99 #endif /* LIBCAPTIVE */
100 if (Action != kdHandleException)
102 if (PreviousMode == UserMode)
106 #else /* !LIBCAPTIVE */
112 /* FIXME: Forward exception to user mode debugger */
114 /* FIXME: Check user mode stack for enough space */
117 * Let usermode try and handle the exception
120 (12 + sizeof(EXCEPTION_RECORD) + sizeof(CONTEXT));
121 Stack = (PULONG)Tf->Esp;
122 CDest = 3 + (ROUND_UP(sizeof(EXCEPTION_RECORD), 4) / 4);
125 /* Pointer to EXCEPTION_RECORD structure */
126 Stack[1] = (ULONG)&Stack[3];
127 /* Pointer to CONTEXT structure */
128 Stack[2] = (ULONG)&Stack[CDest];
129 memcpy(&Stack[3], ExceptionRecord, sizeof(EXCEPTION_RECORD));
130 memcpy(&Stack[CDest], Context, sizeof(CONTEXT));
132 Tf->Eip = (ULONG)LdrpGetSystemDllExceptionDispatcher();
136 /* FIXME: Forward the exception to the debugger */
138 /* FIXME: Forward the exception to the process exception port */
140 /* Terminate the offending thread */
141 DPRINT1("Unhandled UserMode exception, terminating thread\n");
142 ZwTerminateThread(NtCurrentThread(), ExceptionRecord->ExceptionCode);
144 /* If that fails then bugcheck */
145 DPRINT1("Could not terminate thread\n");
146 KEBUGCHECK(KMODE_EXCEPTION_NOT_HANDLED);
147 #endif /* LIBCAPTIVE */
151 /* PreviousMode == KernelMode */
152 Value = RtlpDispatchException (ExceptionRecord, Context);
154 DPRINT("RtlpDispatchException() returned with 0x%X\n", Value);
156 * If RtlpDispatchException() does not handle the exception then
159 if (Value != ExceptionContinueExecution ||
160 0 != (ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE))
162 DbgPrint("ExceptionRecord->ExceptionAddress = 0x%x\n",
163 ExceptionRecord->ExceptionAddress );
165 KEBUGCHECKWITHTF(KMODE_EXCEPTION_NOT_HANDLED, 0, 0, 0, 0, Tf);
166 #else /* !LIBCAPTIVE */
168 #endif /* LIBCAPTIVE */
175 KeContextToTrapFrame (Context, KeGetCurrentThread()->TrapFrame);
176 #else /* !LIBCAPTIVE */
178 #endif /* LIBCAPTIVE */
188 ExRaiseAccessViolation (VOID)
190 ExRaiseStatus (STATUS_ACCESS_VIOLATION);
197 ExRaiseDatatypeMisalignment (VOID)
199 ExRaiseStatus (STATUS_DATATYPE_MISALIGNMENT);
202 #endif /* LIBCAPTIVE */
208 ExRaiseStatus (IN NTSTATUS Status)
210 EXCEPTION_RECORD ExceptionRecord;
212 DPRINT("ExRaiseStatus(%x)\n", Status);
214 ExceptionRecord.ExceptionRecord = NULL;
215 ExceptionRecord.NumberParameters = 0;
216 ExceptionRecord.ExceptionCode = Status;
217 ExceptionRecord.ExceptionFlags = 0;
219 RtlRaiseException(&ExceptionRecord);
223 NtRaiseException (IN PEXCEPTION_RECORD ExceptionRecord,
225 IN BOOLEAN SearchFrames)
227 KiDispatchException(ExceptionRecord,
229 PsGetCurrentThread()->Tcb.TrapFrame,
232 #else /* !LIBCAPTIVE */
234 #endif /* LIBCAPTIVE */
236 return(STATUS_SUCCESS);
244 RtlRaiseException(PEXCEPTION_RECORD ExceptionRecord)
247 ZwRaiseException(ExceptionRecord, NULL, TRUE);
248 #else /* !LIBCAPTIVE */
249 CONTEXT *LocalContext;
251 /* Do not use local variable to benefit from ElectricFence boundary checks */
252 LocalContext=ExAllocatePool(PagedPool,sizeof(LocalContext->ContextFlags));
253 LocalContext->ContextFlags=0;
255 NtRaiseException(ExceptionRecord, LocalContext, TRUE);
257 ExFreePool(LocalContext);
258 #endif /* LIBCAPTIVE */