2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/ke/catch.c
5 * PURPOSE: Exception handling
7 * PROGRAMMERS: Anich Gregor
8 * David Welch (welch@mcmail.com)
9 * Casper S. Hornstrup (chorns@users.sourceforge.net)
12 /* INCLUDES *****************************************************************/
16 #include <internal/debug.h>
18 /* FUNCTIONS ****************************************************************/
21 RtlpDispatchException(IN PEXCEPTION_RECORD ExceptionRecord
,
29 KiCoprocessorError(VOID
)
39 KiUnexpectedInterrupt(VOID
)
45 KiDispatchException(PEXCEPTION_RECORD ExceptionRecord
,
48 KPROCESSOR_MODE PreviousMode
,
51 EXCEPTION_DISPOSITION Value
;
53 KD_CONTINUE_TYPE Action
= kdHandleException
;
55 DPRINT("KiDispatchException() called\n");
57 /* Increase number of Exception Dispatches */
58 KeGetCurrentPrcb()->KeExceptionDispatchCount
++;
63 /* Assume Full context */
64 TContext
.ContextFlags
= CONTEXT_FULL
;
67 if (PreviousMode
== UserMode
)
70 /* Add Debugger Registers if this is User Mode */
71 TContext
.ContextFlags
= TContext
.ContextFlags
| CONTEXT_DEBUGGER
;
74 /* Convert the Trapframe into a Context */
75 KeTrapFrameToContext(Tf
, &TContext
);
77 /* Use local stack context */
81 #if 0 /* FIXME: Isn't this right? With a break after? */
82 if (ExceptionRecord
->ExceptionCode
== STATUS_BREAKPOINT
)
88 /* Check if a Debugger is enabled */
89 if (KdDebuggerEnabled
&& KdDebugState
& KD_DEBUG_GDB
)
93 Action
= KdEnterDebuggerException (ExceptionRecord
, Context
, Tf
);
96 /* If the debugger said continue, then continue */
97 if (Action
== kdContinue
) return;
99 /* If the Debugger couldn't handle it... */
100 if (Action
!= kdDoNotHandleException
)
103 /* See what kind of Exception this is */
104 if (PreviousMode
== UserMode
)
107 /* User mode exception, search the frames if we have to */
113 char temp_space
[12 + sizeof(EXCEPTION_RECORD
) + sizeof(CONTEXT
)]; /* FIXME: HACKHACK */
114 PULONG pNewUserStack
= (PULONG
)(Tf
->Esp
- (12 + sizeof(EXCEPTION_RECORD
) + sizeof(CONTEXT
)));
115 NTSTATUS StatusOfCopy
;
118 /* Enter KDB if available */
119 Action
= KdbEnterDebuggerException(ExceptionRecord
,
125 /* Exit if we're continuing */
126 if (Action
== kdContinue
) return;
129 /* FIXME: Forward exception to user mode debugger */
131 /* FIXME: Check user mode stack for enough space */
133 /* Let usermode try and handle the exception. Setup Stack */
134 Stack
= (PULONG
)temp_space
;
135 CDest
= 3 + (ROUND_UP(sizeof(EXCEPTION_RECORD
), 4) / 4);
138 /* Pointer to EXCEPTION_RECORD structure */
139 Stack
[1] = (ULONG
)&pNewUserStack
[3];
140 /* Pointer to CONTEXT structure */
141 Stack
[2] = (ULONG
)&pNewUserStack
[CDest
];
142 memcpy(&Stack
[3], ExceptionRecord
, sizeof(EXCEPTION_RECORD
));
143 memcpy(&Stack
[CDest
], Context
, sizeof(CONTEXT
));
146 StatusOfCopy
= MmCopyToCaller(pNewUserStack
,
148 (12 + sizeof(EXCEPTION_RECORD
) + sizeof(CONTEXT
)));
150 /* Check for success */
151 if (NT_SUCCESS(StatusOfCopy
))
154 /* Set new Stack Pointer */
155 Tf
->Esp
= (ULONG
)pNewUserStack
;
162 * Now it really hit the ventilation device. Sorry,
163 * can do nothing but kill the sucker.
165 ZwTerminateThread(NtCurrentThread(), ExceptionRecord
->ExceptionCode
);
166 DPRINT1("User-mode stack was invalid. Terminating target thread\n");
169 /* Set EIP to the User-mode Dispathcer */
170 Tf
->Eip
= (ULONG
)LdrpGetSystemDllExceptionDispatcher();
174 /* FIXME: Forward the exception to the debugger */
176 /* FIXME: Forward the exception to the process exception port */
179 /* Enter KDB if available */
180 Action
= KdbEnterDebuggerException(ExceptionRecord
,
186 /* Exit if we're continuing */
187 if (Action
== kdContinue
) return;
190 /* Terminate the offending thread */
191 DPRINT1("Unhandled UserMode exception, terminating thread\n");
192 ZwTerminateThread(NtCurrentThread(), ExceptionRecord
->ExceptionCode
);
198 /* This is Kernel Mode */
200 /* Enter KDB if available */
201 Action
= KdbEnterDebuggerException(ExceptionRecord
,
207 /* Exit if we're continuing */
208 if (Action
== kdContinue
) return;
211 /* Dispatch the Exception */
212 Value
= RtlpDispatchException (ExceptionRecord
, Context
);
213 DPRINT("RtlpDispatchException() returned with 0x%X\n", Value
);
215 /* If RtlpDispatchException() did not handle the exception then bugcheck */
216 if (Value
!= ExceptionContinueExecution
||
217 0 != (ExceptionRecord
->ExceptionFlags
& EXCEPTION_NONCONTINUABLE
))
220 DPRINT("ExceptionRecord->ExceptionAddress = 0x%x\n", ExceptionRecord
->ExceptionAddress
);
222 /* Enter KDB if available */
223 Action
= KdbEnterDebuggerException(ExceptionRecord
,
229 /* Exit if we're continuing */
230 if (Action
== kdContinue
) return;
232 KEBUGCHECKWITHTF(KMODE_EXCEPTION_NOT_HANDLED
,
233 ExceptionRecord
->ExceptionCode
,
234 (ULONG
)ExceptionRecord
->ExceptionAddress
,
235 ExceptionRecord
->ExceptionInformation
[0],
236 ExceptionRecord
->ExceptionInformation
[1],