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
!= KernelMode
)
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
!= KernelMode
)
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 Status
= STATUS_SUCCESS
;
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
));
135 ProbeForWrite(pNewUserStack
,
136 12 + sizeof(EXCEPTION_RECORD
) + sizeof(CONTEXT
),
138 RtlCopyMemory(pNewUserStack
,
140 12 + sizeof(EXCEPTION_RECORD
) + sizeof(CONTEXT
));
144 Status
= _SEH_GetExceptionCode();
148 /* Check for success */
149 if (NT_SUCCESS(Status
))
151 /* Set new Stack Pointer */
152 Tf
->Esp
= (ULONG
)pNewUserStack
;
157 * Now it really hit the ventilation device. Sorry,
158 * can do nothing but kill the sucker.
160 ZwTerminateThread(NtCurrentThread(), ExceptionRecord
->ExceptionCode
);
161 DPRINT1("User-mode stack was invalid. Terminating target thread\n");
163 /* Set EIP to the User-mode Dispathcer */
164 Tf
->Eip
= (ULONG
)KeUserExceptionDispatcher
;
168 /* FIXME: Forward the exception to the debugger */
170 /* FIXME: Forward the exception to the process exception port */
172 /* Enter KDB if available */
173 Action
= KdpEnterDebuggerException(ExceptionRecord
,
180 /* Exit if we're continuing */
181 if (Action
== kdContinue
) return;
183 /* Terminate the offending thread */
184 DPRINT1("Unhandled UserMode exception, terminating thread\n");
185 ZwTerminateThread(NtCurrentThread(), ExceptionRecord
->ExceptionCode
);
189 /* This is Kernel Mode */
191 /* Enter KDB if available */
192 Action
= KdpEnterDebuggerException(ExceptionRecord
,
199 /* Exit if we're continuing */
200 if (Action
== kdContinue
) return;
202 /* Dispatch the Exception */
203 Value
= RtlpDispatchException (ExceptionRecord
, Context
);
204 DPRINT("RtlpDispatchException() returned with 0x%X\n", Value
);
206 /* If RtlpDispatchException() did not handle the exception then bugcheck */
207 if (Value
!= ExceptionContinueExecution
||
208 0 != (ExceptionRecord
->ExceptionFlags
& EXCEPTION_NONCONTINUABLE
))
210 DPRINT("ExceptionRecord->ExceptionAddress = 0x%p\n", ExceptionRecord
->ExceptionAddress
);
212 /* Enter KDB if available */
213 Action
= KdpEnterDebuggerException(ExceptionRecord
,
220 /* Exit if we're continuing */
221 if (Action
== kdContinue
) return;
223 KEBUGCHECKWITHTF(KMODE_EXCEPTION_NOT_HANDLED
,
224 ExceptionRecord
->ExceptionCode
,
225 (ULONG
)ExceptionRecord
->ExceptionAddress
,
226 ExceptionRecord
->ExceptionInformation
[0],
227 ExceptionRecord
->ExceptionInformation
[1],