6bdda14ed3b4e92c20b30344aafc5155207fde30
[reactos.git] / 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$
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           if (Value != ExceptionContinueExecution)
151             {
152               KeBugCheck (KMODE_EXCEPTION_NOT_HANDLED);       
153             }
154         }
155       else
156         {
157           KeContextToTrapFrame (Context, KeGetCurrentThread()->TrapFrame);
158         }
159     }
160 }
161
162 VOID STDCALL
163 ExRaiseAccessViolation (VOID)
164 {
165   ExRaiseStatus (STATUS_ACCESS_VIOLATION);
166 }
167
168 VOID STDCALL
169 ExRaiseDatatypeMisalignment (VOID)
170 {
171   ExRaiseStatus (STATUS_DATATYPE_MISALIGNMENT);
172 }
173
174 VOID STDCALL
175 ExRaiseStatus (IN NTSTATUS Status)
176 {
177   EXCEPTION_RECORD ExceptionRecord;
178
179   DPRINT("ExRaiseStatus(%x)\n", Status);
180
181   ExceptionRecord.ExceptionRecord = NULL;
182   ExceptionRecord.NumberParameters = 0;
183   ExceptionRecord.ExceptionCode = Status;
184   ExceptionRecord.ExceptionFlags = 0;
185
186   RtlRaiseException(&ExceptionRecord);
187 }
188
189
190 NTSTATUS STDCALL
191 NtRaiseException (IN PEXCEPTION_RECORD ExceptionRecord,
192                   IN PCONTEXT Context,
193                   IN BOOLEAN SearchFrames)
194 {
195   KiDispatchException(ExceptionRecord,
196                       Context,
197                       PsGetCurrentThread()->Tcb.TrapFrame,
198                       ExGetPreviousMode(),
199                       SearchFrames);
200   return(STATUS_SUCCESS);
201 }
202
203
204 VOID STDCALL
205 RtlRaiseException(PEXCEPTION_RECORD ExceptionRecord)
206 {
207   ZwRaiseException(ExceptionRecord, NULL, TRUE);
208 }
209
210 /* EOF */