3 * Copyright (C) 2000 ReactOS Team
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.
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.
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.
19 /* $Id: catch.c,v 1.56 2004/12/18 19:22:10 blight Exp $
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)
28 /* INCLUDES *****************************************************************/
32 #include <internal/debug.h>
34 /* FUNCTIONS ****************************************************************/
37 RtlpDispatchException(IN PEXCEPTION_RECORD ExceptionRecord
,
41 KiDispatchException(PEXCEPTION_RECORD ExceptionRecord
,
44 KPROCESSOR_MODE PreviousMode
,
47 EXCEPTION_DISPOSITION Value
;
49 KD_CONTINUE_TYPE Action
= kdHandleException
;
51 DPRINT("KiDispatchException() called\n");
53 /* PCR->KeExceptionDispatchCount++; */
57 TContext
.ContextFlags
= CONTEXT_FULL
;
58 if (PreviousMode
== UserMode
)
60 TContext
.ContextFlags
= TContext
.ContextFlags
| CONTEXT_DEBUGGER
;
63 KeTrapFrameToContext(Tf
, &TContext
);
69 if (ExceptionRecord
->ExceptionCode
== STATUS_BREAKPOINT
)
75 if (KdDebuggerEnabled
&& KdDebugState
& KD_DEBUG_GDB
)
77 Action
= KdEnterDebuggerException (ExceptionRecord
, Context
, Tf
);
80 if (Action
== kdContinue
)
85 if (Action
!= kdDoNotHandleException
)
87 if (PreviousMode
== UserMode
)
93 char temp_space
[12 + sizeof(EXCEPTION_RECORD
) + sizeof(CONTEXT
)]; /* FIXME: HACKHACK */
94 PULONG pNewUserStack
= (PULONG
)(Tf
->Esp
- (12 + sizeof(EXCEPTION_RECORD
) + sizeof(CONTEXT
)));
95 NTSTATUS StatusOfCopy
;
98 KdbEnterDebuggerException (ExceptionRecord
, PreviousMode
,
102 /* FIXME: Forward exception to user mode debugger */
104 /* FIXME: Check user mode stack for enough space */
107 * Let usermode try and handle the exception
109 Stack
= (PULONG
)temp_space
;
110 CDest
= 3 + (ROUND_UP(sizeof(EXCEPTION_RECORD
), 4) / 4);
113 /* Pointer to EXCEPTION_RECORD structure */
114 Stack
[1] = (ULONG
)&pNewUserStack
[3];
115 /* Pointer to CONTEXT structure */
116 Stack
[2] = (ULONG
)&pNewUserStack
[CDest
];
117 memcpy(&Stack
[3], ExceptionRecord
, sizeof(EXCEPTION_RECORD
));
118 memcpy(&Stack
[CDest
], Context
, sizeof(CONTEXT
));
120 StatusOfCopy
= MmCopyToCaller(pNewUserStack
,
122 (12 + sizeof(EXCEPTION_RECORD
) + sizeof(CONTEXT
)));
123 if (NT_SUCCESS(StatusOfCopy
))
125 Tf
->Esp
= (ULONG
)pNewUserStack
;
129 /* Now it really hit the ventilation device. Sorry,
130 * can do nothing but kill the sucker.
132 ZwTerminateThread(NtCurrentThread(), ExceptionRecord
->ExceptionCode
);
133 DPRINT1("User-mode stack was invalid. Terminating target thread\n");
135 Tf
->Eip
= (ULONG
)LdrpGetSystemDllExceptionDispatcher();
139 /* FIXME: Forward the exception to the debugger */
141 /* FIXME: Forward the exception to the process exception port */
144 KdbEnterDebuggerException (ExceptionRecord
, PreviousMode
,
148 /* Terminate the offending thread */
149 DPRINT1("Unhandled UserMode exception, terminating thread\n");
150 ZwTerminateThread(NtCurrentThread(), ExceptionRecord
->ExceptionCode
);
154 /* PreviousMode == KernelMode */
156 KdbEnterDebuggerException (ExceptionRecord
, PreviousMode
,
160 Value
= RtlpDispatchException (ExceptionRecord
, Context
);
162 DPRINT("RtlpDispatchException() returned with 0x%X\n", Value
);
164 * If RtlpDispatchException() does not handle the exception then
167 if (Value
!= ExceptionContinueExecution
||
168 0 != (ExceptionRecord
->ExceptionFlags
& EXCEPTION_NONCONTINUABLE
))
170 DPRINT("ExceptionRecord->ExceptionAddress = 0x%x\n",
171 ExceptionRecord
->ExceptionAddress
);
173 Action
= KdbEnterDebuggerException (ExceptionRecord
, PreviousMode
,
175 if (Action
== kdContinue
)
180 KEBUGCHECKWITHTF(KMODE_EXCEPTION_NOT_HANDLED
, 0, 0, 0, 0, Tf
);
190 ExRaiseAccessViolation (VOID
)
192 ExRaiseStatus (STATUS_ACCESS_VIOLATION
);
199 ExRaiseDatatypeMisalignment (VOID
)
201 ExRaiseStatus (STATUS_DATATYPE_MISALIGNMENT
);
208 ExRaiseStatus (IN NTSTATUS Status
)
210 EXCEPTION_RECORD ExceptionRecord
;
212 DPRINT("ExRaiseStatus(%x)\n", Status
);
214 ExceptionRecord
.ExceptionRecord
= NULL
;
215 ExceptionRecord
.NumberParameters
= 0;
216 ExceptionRecord
.ExceptionCode
= Status
;
217 ExceptionRecord
.ExceptionFlags
= 0;
219 RtlRaiseException(&ExceptionRecord
);
230 PEXCEPTION_RECORD ExceptionRecord
233 RtlRaiseException(ExceptionRecord
);
241 ExSystemExceptionFilter(VOID
)
243 return KeGetPreviousMode() != KernelMode
? EXCEPTION_EXECUTE_HANDLER
: EXCEPTION_CONTINUE_SEARCH
;
252 IN NTSTATUS ErrorStatus
,
253 IN ULONG NumberOfParameters
,
254 IN PUNICODE_STRING UnicodeStringParameterMask OPTIONAL
,
255 IN PVOID
*Parameters
,
256 IN HARDERROR_RESPONSE_OPTION ResponseOption
,
257 OUT PHARDERROR_RESPONSE Response
268 KeDeregisterBugCheckReasonCallback(
269 IN PKBUGCHECK_REASON_CALLBACK_RECORD CallbackRecord
281 KeGetRecommendedSharedDataAlignment(
294 KeRegisterBugCheckReasonCallback(
295 IN PKBUGCHECK_REASON_CALLBACK_RECORD CallbackRecord
,
296 IN PKBUGCHECK_REASON_CALLBACK_ROUTINE CallbackRoutine
,
297 IN KBUGCHECK_CALLBACK_REASON Reason
,