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
++;
62 /* Assume Full context */
63 TContext
.ContextFlags
= CONTEXT_FULL
;
66 if (PreviousMode
== UserMode
)
68 /* Add Debugger Registers if this is User Mode */
69 TContext
.ContextFlags
= TContext
.ContextFlags
| CONTEXT_DEBUGGER
;
72 /* Convert the Trapframe into a Context */
73 KeTrapFrameToContext(Tf
, &TContext
);
75 /* Use local stack context */
79 /* Break into Debugger */
80 Action
= KdpEnterDebuggerException(ExceptionRecord
,
87 /* If the debugger said continue, then continue */
88 if (Action
== kdContinue
) return;
90 /* If the Debugger couldn't handle it... */
91 if (Action
!= kdDoNotHandleException
)
93 /* See what kind of Exception this is */
94 if (PreviousMode
== UserMode
)
96 /* User mode exception, search the frames if we have to */
101 char temp_space
[12 + sizeof(EXCEPTION_RECORD
) + sizeof(CONTEXT
)]; /* FIXME: HACKHACK */
102 PULONG pNewUserStack
= (PULONG
)(Tf
->Esp
- (12 + sizeof(EXCEPTION_RECORD
) + sizeof(CONTEXT
)));
103 NTSTATUS StatusOfCopy
;
105 /* Enter Debugger if available */
106 Action
= KdpEnterDebuggerException(ExceptionRecord
,
113 /* Exit if we're continuing */
114 if (Action
== kdContinue
) return;
116 /* FIXME: Forward exception to user mode debugger */
118 /* FIXME: Check user mode stack for enough space */
120 /* Let usermode try and handle the exception. Setup Stack */
121 Stack
= (PULONG
)temp_space
;
122 CDest
= 3 + (ROUND_UP(sizeof(EXCEPTION_RECORD
), 4) / 4);
125 /* Pointer to EXCEPTION_RECORD structure */
126 Stack
[1] = (ULONG
)&pNewUserStack
[3];
127 /* Pointer to CONTEXT structure */
128 Stack
[2] = (ULONG
)&pNewUserStack
[CDest
];
129 memcpy(&Stack
[3], ExceptionRecord
, sizeof(EXCEPTION_RECORD
));
130 memcpy(&Stack
[CDest
], Context
, sizeof(CONTEXT
));
133 StatusOfCopy
= MmCopyToCaller(pNewUserStack
,
135 (12 + sizeof(EXCEPTION_RECORD
) + sizeof(CONTEXT
)));
137 /* Check for success */
138 if (NT_SUCCESS(StatusOfCopy
))
140 /* Set new Stack Pointer */
141 Tf
->Esp
= (ULONG
)pNewUserStack
;
146 * Now it really hit the ventilation device. Sorry,
147 * can do nothing but kill the sucker.
149 ZwTerminateThread(NtCurrentThread(), ExceptionRecord
->ExceptionCode
);
150 DPRINT1("User-mode stack was invalid. Terminating target thread\n");
152 /* Set EIP to the User-mode Dispathcer */
153 Tf
->Eip
= (ULONG
)LdrpGetSystemDllExceptionDispatcher();
157 /* FIXME: Forward the exception to the debugger */
159 /* FIXME: Forward the exception to the process exception port */
161 /* Enter KDB if available */
162 Action
= KdpEnterDebuggerException(ExceptionRecord
,
169 /* Exit if we're continuing */
170 if (Action
== kdContinue
) return;
172 /* Terminate the offending thread */
173 DPRINT1("Unhandled UserMode exception, terminating thread\n");
174 ZwTerminateThread(NtCurrentThread(), ExceptionRecord
->ExceptionCode
);
178 /* This is Kernel Mode */
180 /* Enter KDB if available */
181 Action
= KdpEnterDebuggerException(ExceptionRecord
,
188 /* Exit if we're continuing */
189 if (Action
== kdContinue
) return;
191 /* Dispatch the Exception */
192 Value
= RtlpDispatchException (ExceptionRecord
, Context
);
193 DPRINT("RtlpDispatchException() returned with 0x%X\n", Value
);
195 /* If RtlpDispatchException() did not handle the exception then bugcheck */
196 if (Value
!= ExceptionContinueExecution
||
197 0 != (ExceptionRecord
->ExceptionFlags
& EXCEPTION_NONCONTINUABLE
))
199 DPRINT("ExceptionRecord->ExceptionAddress = 0x%p\n", ExceptionRecord
->ExceptionAddress
);
201 /* Enter KDB if available */
202 Action
= KdpEnterDebuggerException(ExceptionRecord
,
209 /* Exit if we're continuing */
210 if (Action
== kdContinue
) return;
212 KEBUGCHECKWITHTF(KMODE_EXCEPTION_NOT_HANDLED
,
213 ExceptionRecord
->ExceptionCode
,
214 (ULONG
)ExceptionRecord
->ExceptionAddress
,
215 ExceptionRecord
->ExceptionInformation
[0],
216 ExceptionRecord
->ExceptionInformation
[1],