ReactOS  r76032
except.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS Kernel
3  * LICENSE: BSD - See COPYING.ARM in the top level directory
4  * FILE: ntoskrnl/ke/except.c
5  * PURPOSE: Platform independent exception handling
6  * PROGRAMMERS: ReactOS Portable Systems Group
7  * Alex Ionescu (alex.ionescu@reactos.org)
8  */
9 
10 /* INCLUDES ******************************************************************/
11 
12 #include <ntoskrnl.h>
13 #define NDEBUG
14 #include <debug.h>
15 
16 /* FUNCTIONS *****************************************************************/
17 
18 VOID
19 NTAPI
21  IN PKEXCEPTION_FRAME ExceptionFrame,
22  IN PKTRAP_FRAME TrapFrame)
23 {
24  CONTEXT LocalContext;
25 
26  /* We'll have to make a copy and probe it */
27  ProbeForRead(Context, sizeof(CONTEXT), sizeof(ULONG));
28  RtlCopyMemory(&LocalContext, Context, sizeof(CONTEXT));
29  Context = &LocalContext;
30 
31  /* Convert the context into Exception/Trap Frames */
32  KeContextToTrapFrame(&LocalContext,
33  ExceptionFrame,
34  TrapFrame,
35  LocalContext.ContextFlags,
36  UserMode);
37 }
38 
40 NTAPI
42  IN PKEXCEPTION_FRAME ExceptionFrame,
43  IN PKTRAP_FRAME TrapFrame)
44 {
48 
49  /* Raise to APC_LEVEL, only if needed */
50  if (KeGetCurrentIrql() < APC_LEVEL) KeRaiseIrql(APC_LEVEL, &OldIrql);
51 
52  /* Set up SEH to validate the context */
53  _SEH2_TRY
54  {
55  /* Check the previous mode */
56  if (PreviousMode != KernelMode)
57  {
58  /* Validate from user-mode */
60  ExceptionFrame,
61  TrapFrame);
62  }
63  else
64  {
65  /* Convert the context into Exception/Trap Frames */
66  KeContextToTrapFrame(Context,
67  ExceptionFrame,
68  TrapFrame,
69  Context->ContextFlags,
70  KernelMode);
71  }
72  }
74  {
75  /* Save the exception code */
76  Status = _SEH2_GetExceptionCode();
77  }
78  _SEH2_END;
79 
80  /* Lower the IRQL if needed */
81  if (OldIrql < APC_LEVEL) KeLowerIrql(OldIrql);
82 
83  /* Return status */
84  return Status;
85 }
86 
88 NTAPI
91  IN PKEXCEPTION_FRAME ExceptionFrame,
92  IN PKTRAP_FRAME TrapFrame,
93  IN BOOLEAN SearchFrames)
94 {
96  CONTEXT LocalContext;
97  EXCEPTION_RECORD LocalExceptionRecord;
98  ULONG ParameterCount, Size;
99 
100  /* Check if we need to probe */
101  if (PreviousMode != KernelMode)
102  {
103  /* Set up SEH */
104  _SEH2_TRY
105  {
106  /* Probe the context */
107  ProbeForRead(Context, sizeof(CONTEXT), sizeof(ULONG));
108 
109  /* Probe the Exception Record */
110  ProbeForRead(ExceptionRecord,
111  FIELD_OFFSET(EXCEPTION_RECORD, NumberParameters) +
112  sizeof(ULONG),
113  sizeof(ULONG));
114 
115  /* Validate the maximum parameters */
116  if ((ParameterCount = ExceptionRecord->NumberParameters) >
118  {
119  /* Too large */
121  }
122 
123  /* Probe the entire parameters now*/
124  Size = (sizeof(EXCEPTION_RECORD) -
125  ((EXCEPTION_MAXIMUM_PARAMETERS - ParameterCount) * sizeof(ULONG)));
126  ProbeForRead(ExceptionRecord, Size, sizeof(ULONG));
127 
128  /* Now make copies in the stack */
129  RtlCopyMemory(&LocalContext, Context, sizeof(CONTEXT));
130  RtlCopyMemory(&LocalExceptionRecord, ExceptionRecord, Size);
131  Context = &LocalContext;
132  ExceptionRecord = &LocalExceptionRecord;
133 
134  /* Update the parameter count */
135  ExceptionRecord->NumberParameters = ParameterCount;
136  }
138  {
139  /* Don't fail silently */
140  DPRINT1("KiRaiseException: Failed to Probe\n");
141  DbgBreakPoint();
142 
143  /* Return the exception code */
145  }
146  _SEH2_END;
147  }
148 
149  /* Convert the context record */
150  KeContextToTrapFrame(Context,
151  ExceptionFrame,
152  TrapFrame,
153  Context->ContextFlags,
154  PreviousMode);
155 
156  /* Dispatch the exception */
157  ExceptionRecord->ExceptionCode &= ~KI_EXCEPTION_INTERNAL;
158  KiDispatchException(ExceptionRecord,
159  ExceptionFrame,
160  TrapFrame,
161  PreviousMode,
162  SearchFrames);
163 
164  /* We are done */
165  return STATUS_SUCCESS;
166 }
167 
168 /* SYSTEM CALLS ***************************************************************/
169 
170 NTSTATUS
171 NTAPI
174  IN BOOLEAN FirstChance)
175 {
178  PKTRAP_FRAME TrapFrame;
179 
180  /* Get trap frame and link previous one*/
181  Thread = KeGetCurrentThread();
182  TrapFrame = Thread->TrapFrame;
183  Thread->TrapFrame = KiGetLinkedTrapFrame(TrapFrame);
184 
185  /* Set exception list */
186 #ifdef _M_IX86
187  KeGetPcr()->NtTib.ExceptionList = TrapFrame->ExceptionList;
188 #endif
189 
190  /* Raise the exception */
191  Status = KiRaiseException(ExceptionRecord,
192  Context,
193  NULL,
194  TrapFrame,
195  FirstChance);
196  if (NT_SUCCESS(Status))
197  {
198  /* It was handled, so exit restoring all state */
199  KiServiceExit2(TrapFrame);
200  }
201  else
202  {
203  /* Exit with error */
204  KiServiceExit(TrapFrame, Status);
205  }
206 
207  /* We don't actually make it here */
208  return Status;
209 }
210 
211 NTSTATUS
212 NTAPI
214  IN BOOLEAN TestAlert)
215 {
218  PKTRAP_FRAME TrapFrame;
219 
220  /* Get trap frame and link previous one*/
221  Thread = KeGetCurrentThread();
222  TrapFrame = Thread->TrapFrame;
223  Thread->TrapFrame = KiGetLinkedTrapFrame(TrapFrame);
224 
225  /* Continue from this point on */
226  Status = KiContinue(Context, NULL, TrapFrame);
227  if (NT_SUCCESS(Status))
228  {
229  /* Check if alert was requested */
230  if (TestAlert) KeTestAlertThread(Thread->PreviousMode);
231 
232  /* Exit to new trap frame */
233  KiServiceExit2(TrapFrame);
234  }
235  else
236  {
237  /* Exit with an error */
238  KiServiceExit(TrapFrame, Status);
239  }
240 
241  /* We don't actually make it here */
242  return Status;
243 }
244 
245 /* EOF */
VOID NTAPI KeContextToTrapFrame(PCONTEXT Context, PKEXCEPTION_FRAME ExeptionFrame, PKTRAP_FRAME TrapFrame, ULONG ContextFlags, KPROCESSOR_MODE PreviousMode)
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
#define IN
Definition: typedefs.h:38
NTSTATUS NTAPI KiContinue(IN PCONTEXT Context, IN PKEXCEPTION_FRAME ExceptionFrame, IN PKTRAP_FRAME TrapFrame)
Definition: except.c:41
#define KeRaiseIrql(irql, oldIrql)
Definition: env_spec_w32.h:597
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
return STATUS_SUCCESS
Definition: btrfs.c:2664
#define KeGetPreviousMode()
Definition: ketypes.h:1081
#define EXCEPTION_MAXIMUM_PARAMETERS
Definition: compat.h:194
PKTRAP_FRAME TrapFrame
Definition: ketypes.h:1181
void DbgBreakPoint()
Definition: mach.c:558
#define KeGetPcr()
Definition: ke.h:25
UCHAR KIRQL
Definition: env_spec_w32.h:591
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
NTSTATUS NTAPI NtContinue(IN PCONTEXT Context, IN BOOLEAN TestAlert)
Definition: except.c:213
#define _SEH2_END
Definition: pseh2_64.h:7
struct _EXCEPTION_RECORD EXCEPTION_RECORD
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
smooth NULL
Definition: ftsmooth.c:557
NTSTATUS NTAPI NtRaiseException(IN PEXCEPTION_RECORD ExceptionRecord, IN PCONTEXT Context, IN BOOLEAN FirstChance)
Definition: except.c:172
UCHAR PreviousMode
Definition: ketypes.h:1216
ULONG ContextFlags
Definition: compat.h:331
UINTN Size
Definition: acefiex.h:555
DECLSPEC_NORETURN VOID FASTCALL KiServiceExit(IN PKTRAP_FRAME TrapFrame, IN NTSTATUS Status)
Definition: traphdlr.c:150
VOID NTAPI KiContinuePreviousModeUser(IN PCONTEXT Context, IN PKEXCEPTION_FRAME ExceptionFrame, IN PKTRAP_FRAME TrapFrame)
Definition: except.c:20
unsigned char BOOLEAN
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
#define _SEH2_YIELD(STMT_)
Definition: pseh2_64.h:8
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:24
#define KI_EXCEPTION_INTERNAL
Definition: ketypes.h:176
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
struct _EXCEPTION_REGISTRATION_RECORD FAR * ExceptionList
Definition: ketypes.h:258
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
NTSTATUS NTAPI KiRaiseException(IN PEXCEPTION_RECORD ExceptionRecord, IN PCONTEXT Context, IN PKEXCEPTION_FRAME ExceptionFrame, IN PKTRAP_FRAME TrapFrame, IN BOOLEAN SearchFrames)
Definition: except.c:89
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
Status
Definition: gdiplustypes.h:24
LONG NTSTATUS
Definition: DriverTester.h:11
#define KiGetLinkedTrapFrame(x)
Definition: ke.h:109
#define _SEH2_TRY
Definition: pseh2_64.h:5
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
#define KiServiceExit2
Definition: ke.h:5
#define DPRINT1
Definition: precomp.h:8
BOOLEAN NTAPI KeTestAlertThread(IN KPROCESSOR_MODE AlertMode)
Definition: thrdobj.c:731
VOID NTAPI KiDispatchException(IN PEXCEPTION_RECORD ExceptionRecord, IN PKEXCEPTION_FRAME ExceptionFrame, IN PKTRAP_FRAME TrapFrame, IN KPROCESSOR_MODE PreviousMode, IN BOOLEAN FirstChance)
Definition: except.c:237
unsigned int ULONG
Definition: retypes.h:1
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
DWORD NumberParameters
Definition: compat.h:200
#define KeGetCurrentThread
Definition: hal.h:44
#define APC_LEVEL
Definition: env_spec_w32.h:695