Switch back to the command prompt when you press the "X" Close button
[reactos.git] / reactos / ntoskrnl / ke / catch.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 2000 ReactOS Team
4 *
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.
9 *
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.
14 *
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.
18 */
19 /* $Id: catch.c,v 1.29 2003/03/06 23:57:02 gvg Exp $
20 *
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)
26 */
27
28 /* INCLUDES *****************************************************************/
29
30 #include <ddk/ntddk.h>
31 #include <reactos/bugcodes.h>
32 #include <roscfg.h>
33 #include <internal/ke.h>
34 #include <internal/ldr.h>
35 #include <internal/ps.h>
36 #include <internal/kd.h>
37
38 #define NDEBUG
39 #include <internal/debug.h>
40
41 /* FUNCTIONS ****************************************************************/
42
43 ULONG
44 RtlpDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,
45 IN PCONTEXT Context);
46
47 VOID
48 KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
49 PCONTEXT Context,
50 PKTRAP_FRAME Tf,
51 KPROCESSOR_MODE PreviousMode,
52 BOOLEAN SearchFrames)
53 {
54 EXCEPTION_DISPOSITION Value;
55 CONTEXT TContext;
56
57 DPRINT("KiDispatchException() called\n");
58
59 /* PCR->KeExceptionDispatchCount++; */
60
61 if (Context == NULL)
62 {
63 TContext.ContextFlags = CONTEXT_FULL;
64 if (PreviousMode == UserMode)
65 {
66 TContext.ContextFlags = TContext.ContextFlags | CONTEXT_DEBUGGER;
67 }
68
69 KeTrapFrameToContext(Tf, &TContext);
70
71 Context = &TContext;
72 }
73
74 #if 0
75 if (ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT)
76 {
77 Context->Eip--;
78 }
79 #endif
80 if (PreviousMode == UserMode)
81 {
82 if (SearchFrames)
83 {
84 PULONG Stack;
85 ULONG CDest;
86
87 /* FIXME: Give the kernel debugger a chance */
88
89 /* FIXME: Forward exception to user mode debugger */
90
91 /* FIXME: Check user mode stack for enough space */
92
93
94 /*
95 * Let usermode try and handle the exception
96 */
97 Tf->Esp = Tf->Esp -
98 (12 + sizeof(EXCEPTION_RECORD) + sizeof(CONTEXT));
99 Stack = (PULONG)Tf->Esp;
100 CDest = 3 + (ROUND_UP(sizeof(EXCEPTION_RECORD), 4) / 4);
101 /* Return address */
102 Stack[0] = 0;
103 /* Pointer to EXCEPTION_RECORD structure */
104 Stack[1] = (ULONG)&Stack[3];
105 /* Pointer to CONTEXT structure */
106 Stack[2] = (ULONG)&Stack[CDest];
107 memcpy(&Stack[3], ExceptionRecord, sizeof(EXCEPTION_RECORD));
108 memcpy(&Stack[CDest], Context, sizeof(CONTEXT));
109
110 Tf->Eip = (ULONG)LdrpGetSystemDllExceptionDispatcher();
111 return;
112 }
113
114 /* FIXME: Forward the exception to the debugger */
115
116 /* FIXME: Forward the exception to the process exception port */
117
118 /* Terminate the offending thread */
119 ZwTerminateThread(NtCurrentThread(), ExceptionRecord->ExceptionCode);
120
121 /* If that fails then bugcheck */
122 DbgPrint("Could not terminate thread\n");
123 KeBugCheck(KMODE_EXCEPTION_NOT_HANDLED);
124 }
125 else
126 {
127 KD_CONTINUE_TYPE Action = kdContinue;
128
129 /* PreviousMode == KernelMode */
130
131 if (KdDebuggerEnabled && KdDebugState & KD_DEBUG_GDB)
132 {
133 Action = KdEnterDebuggerException (ExceptionRecord, Context, Tf);
134 }
135 #ifdef KDBG
136 else if (KdDebuggerEnabled && KdDebugState & KD_DEBUG_KDB)
137 {
138 Action = KdbEnterDebuggerException (ExceptionRecord, Context, Tf);
139 }
140 #endif /* KDBG */
141 if (Action != kdHandleException)
142 {
143 Value = RtlpDispatchException (ExceptionRecord, Context);
144
145 DPRINT("RtlpDispatchException() returned with 0x%X\n", Value);
146 /*
147 * If RtlpDispatchException() does not handle the exception then
148 * bugcheck
149 */
150 #ifdef TODO
151 if (Value != ExceptionContinueExecution)
152 #endif
153 {
154 KeBugCheck (KMODE_EXCEPTION_NOT_HANDLED);
155 }
156 }
157 else
158 {
159 KeContextToTrapFrame (Context, KeGetCurrentThread()->TrapFrame);
160 }
161 }
162 }
163
164 VOID STDCALL
165 ExRaiseAccessViolation (VOID)
166 {
167 ExRaiseStatus (STATUS_ACCESS_VIOLATION);
168 }
169
170 VOID STDCALL
171 ExRaiseDatatypeMisalignment (VOID)
172 {
173 ExRaiseStatus (STATUS_DATATYPE_MISALIGNMENT);
174 }
175
176 VOID STDCALL
177 ExRaiseStatus (IN NTSTATUS Status)
178 {
179 EXCEPTION_RECORD ExceptionRecord;
180
181 DPRINT("ExRaiseStatus(%x)\n", Status);
182
183 ExceptionRecord.ExceptionRecord = NULL;
184 ExceptionRecord.NumberParameters = 0;
185 ExceptionRecord.ExceptionCode = Status;
186 ExceptionRecord.ExceptionFlags = 0;
187
188 RtlRaiseException(&ExceptionRecord);
189 }
190
191
192 NTSTATUS STDCALL
193 NtRaiseException (IN PEXCEPTION_RECORD ExceptionRecord,
194 IN PCONTEXT Context,
195 IN BOOLEAN SearchFrames)
196 {
197 KiDispatchException(ExceptionRecord,
198 Context,
199 PsGetCurrentThread()->Tcb.TrapFrame,
200 ExGetPreviousMode(),
201 SearchFrames);
202 return(STATUS_SUCCESS);
203 }
204
205
206 VOID STDCALL
207 RtlRaiseException(PEXCEPTION_RECORD ExceptionRecord)
208 {
209 ZwRaiseException(ExceptionRecord, NULL, TRUE);
210 }
211
212 /* EOF */