- Call KeBugCheckWithTf for not handled kernel mode exceptions in KiDispatchException.
[reactos.git] / reactos / ntoskrnl / ke / catch.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 2000 ReactOS Team
4 *
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.
9 *
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.
14 *
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.
18 */
19 /* $Id: catch.c,v 1.31 2003/04/24 16:55:08 hbirr Exp $
20 *
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)
26 */
27
28 /* INCLUDES *****************************************************************/
29
30 #include <ddk/ntddk.h>
31 #include <reactos/bugcodes.h>
32 #include <roscfg.h>
33 #include <internal/ke.h>
34 #include <internal/ldr.h>
35 #include <internal/ps.h>
36 #include <internal/kd.h>
37
38 #define NDEBUG
39 #include <internal/debug.h>
40
41 /* FUNCTIONS ****************************************************************/
42
43 ULONG
44 RtlpDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,
45 IN PCONTEXT Context);
46
47 VOID
48 KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
49 PCONTEXT Context,
50 PKTRAP_FRAME Tf,
51 KPROCESSOR_MODE PreviousMode,
52 BOOLEAN SearchFrames)
53 {
54 EXCEPTION_DISPOSITION Value;
55 CONTEXT TContext;
56 KD_CONTINUE_TYPE Action = kdContinue;
57
58 DPRINT("KiDispatchException() called\n");
59
60 /* PCR->KeExceptionDispatchCount++; */
61
62 if (Context == NULL)
63 {
64 TContext.ContextFlags = CONTEXT_FULL;
65 if (PreviousMode == UserMode)
66 {
67 TContext.ContextFlags = TContext.ContextFlags | CONTEXT_DEBUGGER;
68 }
69
70 KeTrapFrameToContext(Tf, &TContext);
71
72 Context = &TContext;
73 }
74
75 #if 0
76 if (ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT)
77 {
78 Context->Eip--;
79 }
80 #endif
81
82 if (KdDebuggerEnabled && KdDebugState & KD_DEBUG_GDB)
83 {
84 Action = KdEnterDebuggerException (ExceptionRecord, Context, Tf);
85 }
86 #ifdef KDBG
87 else if (KdDebuggerEnabled && KdDebugState & KD_DEBUG_KDB)
88 {
89 Action = KdbEnterDebuggerException (ExceptionRecord, Context, Tf);
90 }
91 #endif /* KDBG */
92 if (Action != kdHandleException)
93 {
94 if (PreviousMode == UserMode)
95 {
96 if (SearchFrames)
97 {
98 PULONG Stack;
99 ULONG CDest;
100
101 /* FIXME: Forward exception to user mode debugger */
102
103 /* FIXME: Check user mode stack for enough space */
104
105 /*
106 * Let usermode try and handle the exception
107 */
108 Tf->Esp = Tf->Esp -
109 (12 + sizeof(EXCEPTION_RECORD) + sizeof(CONTEXT));
110 Stack = (PULONG)Tf->Esp;
111 CDest = 3 + (ROUND_UP(sizeof(EXCEPTION_RECORD), 4) / 4);
112 /* Return address */
113 Stack[0] = 0;
114 /* Pointer to EXCEPTION_RECORD structure */
115 Stack[1] = (ULONG)&Stack[3];
116 /* Pointer to CONTEXT structure */
117 Stack[2] = (ULONG)&Stack[CDest];
118 memcpy(&Stack[3], ExceptionRecord, sizeof(EXCEPTION_RECORD));
119 memcpy(&Stack[CDest], Context, sizeof(CONTEXT));
120
121 Tf->Eip = (ULONG)LdrpGetSystemDllExceptionDispatcher();
122 return;
123 }
124
125 /* FIXME: Forward the exception to the debugger */
126
127 /* FIXME: Forward the exception to the process exception port */
128
129 /* Terminate the offending thread */
130 DPRINT1("Unhandled UserMode exception, terminating thread\n");
131 ZwTerminateThread(NtCurrentThread(), ExceptionRecord->ExceptionCode);
132
133 /* If that fails then bugcheck */
134 DPRINT1("Could not terminate thread\n");
135 KeBugCheck(KMODE_EXCEPTION_NOT_HANDLED);
136 }
137 else
138 {
139 /* PreviousMode == KernelMode */
140 Value = RtlpDispatchException (ExceptionRecord, Context);
141
142 DPRINT("RtlpDispatchException() returned with 0x%X\n", Value);
143 /*
144 * If RtlpDispatchException() does not handle the exception then
145 * bugcheck
146 */
147 if (Value != ExceptionContinueExecution ||
148 0 != (ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE))
149 {
150 KeBugCheckWithTf(KMODE_EXCEPTION_NOT_HANDLED, 0, 0, 0, 0, Tf);
151 }
152 }
153 }
154 else
155 {
156 KeContextToTrapFrame (Context, KeGetCurrentThread()->TrapFrame);
157 }
158 }
159
160 VOID STDCALL
161 ExRaiseAccessViolation (VOID)
162 {
163 ExRaiseStatus (STATUS_ACCESS_VIOLATION);
164 }
165
166 VOID STDCALL
167 ExRaiseDatatypeMisalignment (VOID)
168 {
169 ExRaiseStatus (STATUS_DATATYPE_MISALIGNMENT);
170 }
171
172 VOID STDCALL
173 ExRaiseStatus (IN NTSTATUS Status)
174 {
175 EXCEPTION_RECORD ExceptionRecord;
176
177 DPRINT("ExRaiseStatus(%x)\n", Status);
178
179 ExceptionRecord.ExceptionRecord = NULL;
180 ExceptionRecord.NumberParameters = 0;
181 ExceptionRecord.ExceptionCode = Status;
182 ExceptionRecord.ExceptionFlags = 0;
183
184 RtlRaiseException(&ExceptionRecord);
185 }
186
187
188 NTSTATUS STDCALL
189 NtRaiseException (IN PEXCEPTION_RECORD ExceptionRecord,
190 IN PCONTEXT Context,
191 IN BOOLEAN SearchFrames)
192 {
193 KiDispatchException(ExceptionRecord,
194 Context,
195 PsGetCurrentThread()->Tcb.TrapFrame,
196 ExGetPreviousMode(),
197 SearchFrames);
198 return(STATUS_SUCCESS);
199 }
200
201
202 VOID STDCALL
203 RtlRaiseException(PEXCEPTION_RECORD ExceptionRecord)
204 {
205 ZwRaiseException(ExceptionRecord, NULL, TRUE);
206 }
207
208 /* EOF */