+FSCTL_DISMOUNT_VOLUME define
[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 #ifndef LIBCAPTIVE
32 #include <reactos/bugcodes.h>
33 #endif /* LIBCAPTIVE */
34 #include <roscfg.h>
35 #include <internal/ke.h>
36 #include <internal/ldr.h>
37 #include <internal/ps.h>
38 #include <internal/kd.h>
39
40 #define NDEBUG
41 #include <internal/debug.h>
42
43 /* FUNCTIONS ****************************************************************/
44
45 ULONG
46 RtlpDispatchException(IN PEXCEPTION_RECORD  ExceptionRecord,
47         IN PCONTEXT  Context);
48
49 VOID 
50 KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
51                     PCONTEXT Context,
52                     PKTRAP_FRAME Tf,
53                     KPROCESSOR_MODE PreviousMode,
54                     BOOLEAN SearchFrames)
55 {
56   EXCEPTION_DISPOSITION Value;
57 #ifndef LIBCAPTIVE
58   CONTEXT TContext;
59 #endif /* LIBCAPTIVE */
60   KD_CONTINUE_TYPE Action = kdContinue;
61
62   DPRINT("KiDispatchException() called\n");
63
64   /* PCR->KeExceptionDispatchCount++; */
65
66 #ifndef LIBCAPTIVE
67   if (Context == NULL)
68     {
69       TContext.ContextFlags = CONTEXT_FULL;
70       if (PreviousMode == UserMode)
71         {
72           TContext.ContextFlags = TContext.ContextFlags | CONTEXT_DEBUGGER;
73         }
74   
75       KeTrapFrameToContext(Tf, &TContext);
76
77       Context = &TContext;
78     }
79 #endif /* LIBCAPTIVE */
80
81 #if 0
82   if (ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) 
83     {
84       Context->Eip--;
85     }
86 #endif
87       
88 #ifndef LIBCAPTIVE
89   if (KdDebuggerEnabled && KdDebugState & KD_DEBUG_GDB)
90     {
91       Action = KdEnterDebuggerException (ExceptionRecord, Context, Tf);
92     }
93 #ifdef KDBG
94   else if (KdDebuggerEnabled && KdDebugState & KD_DEBUG_KDB)
95     {
96       Action = KdbEnterDebuggerException (ExceptionRecord, Context, Tf);
97     }
98 #endif /* KDBG */
99 #endif /* LIBCAPTIVE */
100   if (Action != kdHandleException)
101     {
102       if (PreviousMode == UserMode)
103         {
104 #ifdef LIBCAPTIVE
105           KeBugCheck (0);             
106 #else /* !LIBCAPTIVE */
107           if (SearchFrames)
108             {
109               PULONG Stack;
110               ULONG CDest;
111
112               /* FIXME: Forward exception to user mode debugger */
113
114               /* FIXME: Check user mode stack for enough space */
115           
116               /*
117                * Let usermode try and handle the exception
118                */
119               Tf->Esp = Tf->Esp - 
120                 (12 + sizeof(EXCEPTION_RECORD) + sizeof(CONTEXT));
121               Stack = (PULONG)Tf->Esp;
122               CDest = 3 + (ROUND_UP(sizeof(EXCEPTION_RECORD), 4) / 4);
123               /* Return address */
124               Stack[0] = 0;    
125               /* Pointer to EXCEPTION_RECORD structure */
126               Stack[1] = (ULONG)&Stack[3];   
127               /* Pointer to CONTEXT structure */
128               Stack[2] = (ULONG)&Stack[CDest];     
129               memcpy(&Stack[3], ExceptionRecord, sizeof(EXCEPTION_RECORD));
130               memcpy(&Stack[CDest], Context, sizeof(CONTEXT));
131
132               Tf->Eip = (ULONG)LdrpGetSystemDllExceptionDispatcher();
133               return;
134             }
135       
136           /* FIXME: Forward the exception to the debugger */
137
138           /* FIXME: Forward the exception to the process exception port */
139
140           /* Terminate the offending thread */
141           DPRINT1("Unhandled UserMode exception, terminating thread\n");
142           ZwTerminateThread(NtCurrentThread(), ExceptionRecord->ExceptionCode);
143
144           /* If that fails then bugcheck */
145           DPRINT1("Could not terminate thread\n");
146           KeBugCheck(KMODE_EXCEPTION_NOT_HANDLED);
147 #endif /* LIBCAPTIVE */
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 #ifndef LIBCAPTIVE
163               KeBugCheckWithTf(KMODE_EXCEPTION_NOT_HANDLED, 0, 0, 0, 0, Tf);          
164 #else /* !LIBCAPTIVE */
165               KeBugCheck (0);         
166 #endif /* LIBCAPTIVE */
167             }
168         }
169     }
170   else
171     {
172 #ifndef LIBCAPTIVE
173       KeContextToTrapFrame (Context, KeGetCurrentThread()->TrapFrame);
174 #else /* !LIBCAPTIVE */
175       KeBugCheck(0);
176 #endif /* LIBCAPTIVE */
177     }
178 }
179
180 #ifndef LIBCAPTIVE
181
182 VOID STDCALL
183 ExRaiseAccessViolation (VOID)
184 {
185   ExRaiseStatus (STATUS_ACCESS_VIOLATION);
186 }
187
188 VOID STDCALL
189 ExRaiseDatatypeMisalignment (VOID)
190 {
191   ExRaiseStatus (STATUS_DATATYPE_MISALIGNMENT);
192 }
193
194 VOID STDCALL
195 ExRaiseStatus (IN NTSTATUS Status)
196 {
197   EXCEPTION_RECORD ExceptionRecord;
198
199   DPRINT("ExRaiseStatus(%x)\n", Status);
200
201   ExceptionRecord.ExceptionRecord = NULL;
202   ExceptionRecord.NumberParameters = 0;
203   ExceptionRecord.ExceptionCode = Status;
204   ExceptionRecord.ExceptionFlags = 0;
205
206   RtlRaiseException(&ExceptionRecord);
207 }
208
209 #endif /* LIBCAPTIVE */
210
211 NTSTATUS STDCALL
212 NtRaiseException (IN PEXCEPTION_RECORD ExceptionRecord,
213                   IN PCONTEXT Context,
214                   IN BOOLEAN SearchFrames)
215 {
216   KiDispatchException(ExceptionRecord,
217                       Context,
218                       PsGetCurrentThread()->Tcb.TrapFrame,
219 #ifndef LIBCAPTIVE
220                       ExGetPreviousMode(),
221 #else /* !LIBCAPTIVE */
222                       KernelMode,
223 #endif /* LIBCAPTIVE */
224                       SearchFrames);
225   return(STATUS_SUCCESS);
226 }
227
228
229 VOID STDCALL
230 RtlRaiseException(PEXCEPTION_RECORD ExceptionRecord)
231 {
232 #ifndef LIBCAPTIVE
233   ZwRaiseException(ExceptionRecord, NULL, TRUE);
234 #else /* !LIBCAPTIVE */
235 CONTEXT *LocalContext;
236
237   /* Do not use local variable to benefit from ElectricFence boundary checks */
238   LocalContext=ExAllocatePool(PagedPool,sizeof(LocalContext->ContextFlags));
239   LocalContext->ContextFlags=0;
240
241   NtRaiseException(ExceptionRecord, LocalContext, TRUE);
242
243   ExFreePool(LocalContext);
244 #endif /* LIBCAPTIVE */
245 }
246
247 /* EOF */