Fix misplaced STDCALL
[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.48 2004/08/21 21:19:06 tamlin 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 <ntoskrnl.h>
31 #define NDEBUG
32 #include <internal/debug.h>
33
34 /* FUNCTIONS ****************************************************************/
35
36 ULONG
37 RtlpDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,
38 IN PCONTEXT Context);
39
40 VOID
41 KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
42 PCONTEXT Context,
43 PKTRAP_FRAME Tf,
44 KPROCESSOR_MODE PreviousMode,
45 BOOLEAN SearchFrames)
46 {
47 EXCEPTION_DISPOSITION Value;
48 CONTEXT TContext;
49 KD_CONTINUE_TYPE Action = kdContinue;
50
51 DPRINT("KiDispatchException() called\n");
52
53 /* PCR->KeExceptionDispatchCount++; */
54
55 if (Context == NULL)
56 {
57 TContext.ContextFlags = CONTEXT_FULL;
58 if (PreviousMode == UserMode)
59 {
60 TContext.ContextFlags = TContext.ContextFlags | CONTEXT_DEBUGGER;
61 }
62
63 KeTrapFrameToContext(Tf, &TContext);
64
65 Context = &TContext;
66 }
67
68 #if 0
69 if (ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT)
70 {
71 Context->Eip--;
72 }
73 #endif
74
75 if (KdDebuggerEnabled && KdDebugState & KD_DEBUG_GDB)
76 {
77 Action = KdEnterDebuggerException (ExceptionRecord, Context, Tf);
78 }
79 #ifdef KDBG
80 else if (KdDebuggerEnabled && KdDebugState & KD_DEBUG_KDB)
81 {
82 Action = KdbEnterDebuggerException (ExceptionRecord, Context, Tf);
83 if (Action == kdContinue)
84 {
85 return;
86 }
87 }
88 #endif /* KDBG */
89 if (Action != kdHandleException)
90 {
91 if (PreviousMode == UserMode)
92 {
93 if (SearchFrames)
94 {
95 PULONG Stack;
96 ULONG CDest;
97 char temp_space[12 + sizeof(EXCEPTION_RECORD) + sizeof(CONTEXT)]; // FIXME: HACKHACK
98 PULONG pNewUserStack = (PULONG)(Tf->Esp - (12 + sizeof(EXCEPTION_RECORD) + sizeof(CONTEXT)));
99 NTSTATUS StatusOfCopy;
100
101 /* FIXME: Forward exception to user mode debugger */
102
103 /* FIXME: Check user mode stack for enough space */
104
105 /*
106 * Let usermode try and handle the exception
107 */
108 Stack = (PULONG)temp_space;
109 CDest = 3 + (ROUND_UP(sizeof(EXCEPTION_RECORD), 4) / 4);
110 /* Return address */
111 Stack[0] = 0;
112 /* Pointer to EXCEPTION_RECORD structure */
113 Stack[1] = (ULONG)&pNewUserStack[3];
114 /* Pointer to CONTEXT structure */
115 Stack[2] = (ULONG)&pNewUserStack[CDest];
116 memcpy(&Stack[3], ExceptionRecord, sizeof(EXCEPTION_RECORD));
117 memcpy(&Stack[CDest], Context, sizeof(CONTEXT));
118
119 StatusOfCopy = MmCopyToCaller(pNewUserStack,
120 temp_space,
121 (12 + sizeof(EXCEPTION_RECORD) + sizeof(CONTEXT)));
122 if (NT_SUCCESS(StatusOfCopy))
123 {
124 Tf->Esp = (ULONG)pNewUserStack;
125 }
126 else
127 {
128 // Now it really hit the ventilation device. Sorry,
129 // can do nothing but kill the sucker.
130 ZwTerminateThread(NtCurrentThread(), ExceptionRecord->ExceptionCode);
131 DPRINT1("User-mode stack was invalid. Terminating target thread\nn");
132 }
133 Tf->Eip = (ULONG)LdrpGetSystemDllExceptionDispatcher();
134 return;
135 }
136
137 /* FIXME: Forward the exception to the debugger */
138
139 /* FIXME: Forward the exception to the process exception port */
140
141 /* Terminate the offending thread */
142 DPRINT1("Unhandled UserMode exception, terminating thread\n");
143 ZwTerminateThread(NtCurrentThread(), ExceptionRecord->ExceptionCode);
144
145 /* If that fails then bugcheck */
146 DPRINT1("Could not terminate thread\n");
147 KEBUGCHECK(KMODE_EXCEPTION_NOT_HANDLED);
148 }
149 else
150 {
151 /* PreviousMode == KernelMode */
152 Value = RtlpDispatchException (ExceptionRecord, Context);
153
154 DPRINT("RtlpDispatchException() returned with 0x%X\n", Value);
155 /*
156 * If RtlpDispatchException() does not handle the exception then
157 * bugcheck
158 */
159 if (Value != ExceptionContinueExecution ||
160 0 != (ExceptionRecord->ExceptionFlags & EXCEPTION_NONCONTINUABLE))
161 {
162 DPRINT("ExceptionRecord->ExceptionAddress = 0x%x\n",
163 ExceptionRecord->ExceptionAddress );
164 KEBUGCHECKWITHTF(KMODE_EXCEPTION_NOT_HANDLED, 0, 0, 0, 0, Tf);
165 }
166 }
167 }
168 else
169 {
170 KeContextToTrapFrame (Context, KeGetCurrentThread()->TrapFrame);
171 }
172 }
173
174 /*
175 * @implemented
176 */
177 VOID STDCALL
178 ExRaiseAccessViolation (VOID)
179 {
180 ExRaiseStatus (STATUS_ACCESS_VIOLATION);
181 }
182
183 /*
184 * @implemented
185 */
186 VOID STDCALL
187 ExRaiseDatatypeMisalignment (VOID)
188 {
189 ExRaiseStatus (STATUS_DATATYPE_MISALIGNMENT);
190 }
191
192 /*
193 * @implemented
194 */
195 VOID STDCALL
196 ExRaiseStatus (IN NTSTATUS Status)
197 {
198 EXCEPTION_RECORD ExceptionRecord;
199
200 DPRINT("ExRaiseStatus(%x)\n", Status);
201
202 ExceptionRecord.ExceptionRecord = NULL;
203 ExceptionRecord.NumberParameters = 0;
204 ExceptionRecord.ExceptionCode = Status;
205 ExceptionRecord.ExceptionFlags = 0;
206
207 RtlRaiseException(&ExceptionRecord);
208 }
209
210
211 /*
212 * @unimplemented
213 */
214 VOID
215 STDCALL
216 ExRaiseException (
217 PEXCEPTION_RECORD pExcptRec
218 )
219 {
220 UNIMPLEMENTED;
221 }
222 /*
223 * @unimplemented
224 */
225 VOID
226 STDCALL
227 ExRaiseHardError (
228 IN NTSTATUS ErrorStatus,
229 IN ULONG NumberOfParameters,
230 IN PUNICODE_STRING UnicodeStringParameterMask OPTIONAL,
231 IN PVOID *Parameters,
232 IN HARDERROR_RESPONSE_OPTION ResponseOption,
233 OUT PHARDERROR_RESPONSE Response
234 )
235 {
236 UNIMPLEMENTED;
237 }
238
239
240 /*
241 * @unimplemented
242 */
243 BOOLEAN
244 STDCALL
245 ExSystemExceptionFilter()
246 {
247 UNIMPLEMENTED;
248 return FALSE;
249 }
250
251 /*
252 * @unimplemented
253 */
254 BOOLEAN
255 STDCALL
256 KeDeregisterBugCheckReasonCallback(
257 IN PKBUGCHECK_REASON_CALLBACK_RECORD CallbackRecord
258 )
259 {
260 UNIMPLEMENTED;
261 return FALSE;
262 }
263
264 /*
265 * @unimplemented
266 */
267 ULONG
268 STDCALL
269 KeGetRecommendedSharedDataAlignment(
270 VOID
271 )
272 {
273 UNIMPLEMENTED;
274 return 0;
275 }
276
277 /*
278 * @unimplemented
279 */
280 BOOLEAN
281 STDCALL
282 KeRegisterBugCheckReasonCallback(
283 IN PKBUGCHECK_REASON_CALLBACK_RECORD CallbackRecord,
284 IN PKBUGCHECK_REASON_CALLBACK_ROUTINE CallbackRoutine,
285 IN KBUGCHECK_CALLBACK_REASON Reason,
286 IN PUCHAR Component
287 )
288 {
289 UNIMPLEMENTED;
290 return FALSE;
291 }
292
293 /* EOF */