Standardize comment headers. Patch by Trevor McCort
[reactos.git] / reactos / ntoskrnl / ke / catch.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ke/catch.c
6 * PURPOSE: Exception handling
7 *
8 * PROGRAMMERS: David Welch (welch@mcmail.com)
9 * Casper S. Hornstrup (chorns@users.sourceforge.net)
10 */
11
12 /* INCLUDES *****************************************************************/
13
14 #include <ntoskrnl.h>
15 #define NDEBUG
16 #include <internal/debug.h>
17
18 /* FUNCTIONS ****************************************************************/
19
20 ULONG
21 RtlpDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,
22 IN PCONTEXT Context);
23
24 VOID
25 KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
26 PCONTEXT Context,
27 PKTRAP_FRAME Tf,
28 KPROCESSOR_MODE PreviousMode,
29 BOOLEAN SearchFrames)
30 {
31 EXCEPTION_DISPOSITION Value;
32 CONTEXT TContext;
33 KD_CONTINUE_TYPE Action = kdHandleException;
34
35 DPRINT("KiDispatchException() called\n");
36
37
38 /* PCR->KeExceptionDispatchCount++; */
39
40 if (Context == NULL)
41 {
42 TContext.ContextFlags = CONTEXT_FULL;
43 if (PreviousMode == UserMode)
44 {
45 TContext.ContextFlags = TContext.ContextFlags | CONTEXT_DEBUGGER;
46 }
47
48 KeTrapFrameToContext(Tf, &TContext);
49
50 Context = &TContext;
51 }
52
53 #if 0
54 if (ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT)
55 {
56 Context->Eip--;
57 }
58 #endif
59
60 if (KdDebuggerEnabled && KdDebugState & KD_DEBUG_GDB)
61 {
62 Action = KdEnterDebuggerException (ExceptionRecord, Context, Tf);
63 }
64
65 if (Action == kdContinue)
66 {
67 return;
68 }
69
70 if (Action != kdDoNotHandleException)
71 {
72 if (PreviousMode == UserMode)
73 {
74 if (SearchFrames)
75 {
76 PULONG Stack;
77 ULONG CDest;
78 char temp_space[12 + sizeof(EXCEPTION_RECORD) + sizeof(CONTEXT)]; /* FIXME: HACKHACK */
79 PULONG pNewUserStack = (PULONG)(Tf->Esp - (12 + sizeof(EXCEPTION_RECORD) + sizeof(CONTEXT)));
80 NTSTATUS StatusOfCopy;
81
82 #ifdef KDBG
83 Action = KdbEnterDebuggerException (ExceptionRecord, PreviousMode,
84 Context, Tf, FALSE);
85 if (Action == kdContinue)
86 {
87 return;
88 }
89 #endif
90
91 /* FIXME: Forward exception to user mode debugger */
92
93 /* FIXME: Check user mode stack for enough space */
94
95 /*
96 * Let usermode try and handle the exception
97 */
98 Stack = (PULONG)temp_space;
99 CDest = 3 + (ROUND_UP(sizeof(EXCEPTION_RECORD), 4) / 4);
100 /* Return address */
101 Stack[0] = 0;
102 /* Pointer to EXCEPTION_RECORD structure */
103 Stack[1] = (ULONG)&pNewUserStack[3];
104 /* Pointer to CONTEXT structure */
105 Stack[2] = (ULONG)&pNewUserStack[CDest];
106 memcpy(&Stack[3], ExceptionRecord, sizeof(EXCEPTION_RECORD));
107 memcpy(&Stack[CDest], Context, sizeof(CONTEXT));
108
109 StatusOfCopy = MmCopyToCaller(pNewUserStack,
110 temp_space,
111 (12 + sizeof(EXCEPTION_RECORD) + sizeof(CONTEXT)));
112 if (NT_SUCCESS(StatusOfCopy))
113 {
114 Tf->Esp = (ULONG)pNewUserStack;
115 }
116 else
117 {
118 /* Now it really hit the ventilation device. Sorry,
119 * can do nothing but kill the sucker.
120 */
121 ZwTerminateThread(NtCurrentThread(), ExceptionRecord->ExceptionCode);
122 DPRINT1("User-mode stack was invalid. Terminating target thread\n");
123 }
124 Tf->Eip = (ULONG)LdrpGetSystemDllExceptionDispatcher();
125 return;
126 }
127
128 /* FIXME: Forward the exception to the debugger */
129
130 /* FIXME: Forward the exception to the process exception port */
131
132 #ifdef KDBG
133 Action = KdbEnterDebuggerException (ExceptionRecord, PreviousMode,
134 Context, Tf, TRUE);
135 if (Action == kdContinue)
136 {
137 return;
138 }
139 #endif
140
141 /* Terminate the offending thread */
142 DPRINT1("Unhandled UserMode exception, terminating thread\n");
143 ZwTerminateThread(NtCurrentThread(), ExceptionRecord->ExceptionCode);
144 }
145 else
146 {
147 /* PreviousMode == KernelMode */
148 #ifdef KDBG
149 Action = KdbEnterDebuggerException (ExceptionRecord, PreviousMode,
150 Context, Tf, FALSE);
151 if (Action == kdContinue)
152 {
153 return;
154 }
155 #endif
156
157 Value = RtlpDispatchException (ExceptionRecord, Context);
158
159 DPRINT("RtlpDispatchException() returned with 0x%X\n", Value);
160 /*
161 * If RtlpDispatchException() does not handle the exception then
162 * bugcheck
163 */
164 if (Value != ExceptionContinueExecution ||
165 0 != (ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE))
166 {
167 DPRINT("ExceptionRecord->ExceptionAddress = 0x%x\n",
168 ExceptionRecord->ExceptionAddress );
169 #ifdef KDBG
170 Action = KdbEnterDebuggerException (ExceptionRecord, PreviousMode,
171 Context, Tf, TRUE);
172 if (Action == kdContinue)
173 {
174 return;
175 }
176 #endif
177 KEBUGCHECKWITHTF(KMODE_EXCEPTION_NOT_HANDLED, 0, 0, 0, 0, Tf);
178 }
179 }
180 }
181 }
182
183 /*
184 * @implemented
185 */
186 VOID STDCALL
187 ExRaiseAccessViolation (VOID)
188 {
189 ExRaiseStatus (STATUS_ACCESS_VIOLATION);
190 }
191
192 /*
193 * @implemented
194 */
195 VOID STDCALL
196 ExRaiseDatatypeMisalignment (VOID)
197 {
198 ExRaiseStatus (STATUS_DATATYPE_MISALIGNMENT);
199 }
200
201 /*
202 * @implemented
203 */
204 VOID STDCALL
205 ExRaiseStatus (IN NTSTATUS Status)
206 {
207 EXCEPTION_RECORD ExceptionRecord;
208
209 DPRINT("ExRaiseStatus(%x)\n", Status);
210
211 ExceptionRecord.ExceptionRecord = NULL;
212 ExceptionRecord.NumberParameters = 0;
213 ExceptionRecord.ExceptionCode = Status;
214 ExceptionRecord.ExceptionFlags = 0;
215
216 RtlRaiseException(&ExceptionRecord);
217 }
218
219
220
221 /*
222 * @implemented
223 */
224 VOID
225 STDCALL
226 ExRaiseException (
227 PEXCEPTION_RECORD ExceptionRecord
228 )
229 {
230 RtlRaiseException(ExceptionRecord);
231 }
232
233 /*
234 * @implemented
235 */
236 BOOLEAN
237 STDCALL
238 ExSystemExceptionFilter(VOID)
239 {
240 return KeGetPreviousMode() != KernelMode ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH;
241 }
242
243 /*
244 * @unimplemented
245 */
246 VOID
247 STDCALL
248 ExRaiseHardError (
249 IN NTSTATUS ErrorStatus,
250 IN ULONG NumberOfParameters,
251 IN PUNICODE_STRING UnicodeStringParameterMask OPTIONAL,
252 IN PVOID *Parameters,
253 IN HARDERROR_RESPONSE_OPTION ResponseOption,
254 OUT PHARDERROR_RESPONSE Response
255 )
256 {
257 UNIMPLEMENTED;
258 }
259
260 /*
261 * @unimplemented
262 */
263 BOOLEAN
264 STDCALL
265 KeDeregisterBugCheckReasonCallback(
266 IN PKBUGCHECK_REASON_CALLBACK_RECORD CallbackRecord
267 )
268 {
269 UNIMPLEMENTED;
270 return FALSE;
271 }
272
273 /*
274 * @unimplemented
275 */
276 ULONG
277 STDCALL
278 KeGetRecommendedSharedDataAlignment(
279 VOID
280 )
281 {
282 UNIMPLEMENTED;
283 return 0;
284 }
285
286 /*
287 * @unimplemented
288 */
289 BOOLEAN
290 STDCALL
291 KeRegisterBugCheckReasonCallback(
292 IN PKBUGCHECK_REASON_CALLBACK_RECORD CallbackRecord,
293 IN PKBUGCHECK_REASON_CALLBACK_ROUTINE CallbackRoutine,
294 IN KBUGCHECK_CALLBACK_REASON Reason,
295 IN PUCHAR Component
296 )
297 {
298 UNIMPLEMENTED;
299 return FALSE;
300 }
301
302 /* EOF */