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