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)
10 /* INCLUDES ******************************************************************/
16 /* FUNCTIONS *****************************************************************/
20 KiContinuePreviousModeUser(IN PCONTEXT Context
,
21 IN PKEXCEPTION_FRAME ExceptionFrame
,
22 IN PKTRAP_FRAME TrapFrame
)
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
;
32 KiSetTrapContext(TrapFrame
, &LocalContext
, UserMode
);
34 /* Convert the context into Exception/Trap Frames */
35 KeContextToTrapFrame(&LocalContext
,
38 LocalContext
.ContextFlags
,
45 KiContinue(IN PCONTEXT Context
,
46 IN PKEXCEPTION_FRAME ExceptionFrame
,
47 IN PKTRAP_FRAME TrapFrame
)
49 NTSTATUS Status
= STATUS_SUCCESS
;
50 KIRQL OldIrql
= APC_LEVEL
;
51 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
53 /* Raise to APC_LEVEL, only if needed */
54 if (KeGetCurrentIrql() < APC_LEVEL
) KeRaiseIrql(APC_LEVEL
, &OldIrql
);
56 /* Set up SEH to validate the context */
59 /* Check the previous mode */
60 if (PreviousMode
!= KernelMode
)
62 /* Validate from user-mode */
63 KiContinuePreviousModeUser(Context
,
70 KiSetTrapContext(TrapFrame
, Context
, KernelMode
);
72 /* Convert the context into Exception/Trap Frames */
73 KeContextToTrapFrame(Context
,
76 Context
->ContextFlags
,
81 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
83 /* Save the exception code */
84 Status
= _SEH2_GetExceptionCode();
88 /* Lower the IRQL if needed */
89 if (OldIrql
< APC_LEVEL
) KeLowerIrql(OldIrql
);
97 KiRaiseException(IN PEXCEPTION_RECORD ExceptionRecord
,
99 IN PKEXCEPTION_FRAME ExceptionFrame
,
100 IN PKTRAP_FRAME TrapFrame
,
101 IN BOOLEAN SearchFrames
)
103 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
104 CONTEXT LocalContext
;
105 EXCEPTION_RECORD LocalExceptionRecord
;
106 ULONG ParameterCount
, Size
;
108 /* Check if we need to probe */
109 if (PreviousMode
!= KernelMode
)
114 /* Probe the context */
115 ProbeForRead(Context
, sizeof(CONTEXT
), sizeof(ULONG
));
117 /* Probe the Exception Record */
118 ProbeForRead(ExceptionRecord
,
119 FIELD_OFFSET(EXCEPTION_RECORD
, NumberParameters
) +
123 /* Validate the maximum parameters */
124 if ((ParameterCount
= ExceptionRecord
->NumberParameters
) >
125 EXCEPTION_MAXIMUM_PARAMETERS
)
128 _SEH2_YIELD(return STATUS_INVALID_PARAMETER
);
131 /* Probe the entire parameters now*/
132 Size
= (sizeof(EXCEPTION_RECORD
) -
133 ((EXCEPTION_MAXIMUM_PARAMETERS
- ParameterCount
) * sizeof(ULONG
)));
134 ProbeForRead(ExceptionRecord
, Size
, sizeof(ULONG
));
136 /* Now make copies in the stack */
137 RtlCopyMemory(&LocalContext
, Context
, sizeof(CONTEXT
));
138 RtlCopyMemory(&LocalExceptionRecord
, ExceptionRecord
, Size
);
139 Context
= &LocalContext
;
140 ExceptionRecord
= &LocalExceptionRecord
;
142 /* Update the parameter count */
143 ExceptionRecord
->NumberParameters
= ParameterCount
;
145 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
147 /* Don't fail silently */
148 DPRINT1("KiRaiseException: Failed to Probe\n");
150 /* Return the exception code */
151 _SEH2_YIELD(return _SEH2_GetExceptionCode());
156 /* Convert the context record */
157 KeContextToTrapFrame(Context
,
160 Context
->ContextFlags
,
163 /* Dispatch the exception */
164 ExceptionRecord
->ExceptionCode
&= ~KI_EXCEPTION_INTERNAL
;
165 KiDispatchException(ExceptionRecord
,
172 return STATUS_SUCCESS
;
175 /* SYSTEM CALLS ***************************************************************/
179 NtRaiseException(IN PEXCEPTION_RECORD ExceptionRecord
,
181 IN BOOLEAN FirstChance
)
185 PKTRAP_FRAME TrapFrame
;
187 /* Get trap frame and link previous one*/
188 Thread
= KeGetCurrentThread();
189 TrapFrame
= Thread
->TrapFrame
;
190 Thread
->TrapFrame
= KiGetLinkedTrapFrame(TrapFrame
);
192 /* Set exception list */
194 KeGetPcr()->NtTib
.ExceptionList
= TrapFrame
->ExceptionList
;
197 /* Raise the exception */
198 Status
= KiRaiseException(ExceptionRecord
,
203 if (NT_SUCCESS(Status
))
205 /* It was handled, so exit restoring all state */
206 KiServiceExit2(TrapFrame
);
210 /* Exit with error */
211 KiServiceExit(TrapFrame
, Status
);
214 /* We don't actually make it here */
220 NtContinue(IN PCONTEXT Context
,
221 IN BOOLEAN TestAlert
)
225 PKTRAP_FRAME TrapFrame
;
227 /* Get trap frame and link previous one*/
228 Thread
= KeGetCurrentThread();
229 TrapFrame
= Thread
->TrapFrame
;
230 Thread
->TrapFrame
= KiGetLinkedTrapFrame(TrapFrame
);
232 /* Continue from this point on */
233 Status
= KiContinue(Context
, NULL
, TrapFrame
);
234 if (NT_SUCCESS(Status
))
236 /* Check if alert was requested */
237 if (TestAlert
) KeTestAlertThread(Thread
->PreviousMode
);
239 /* Exit to new trap frame */
240 KiServiceExit2(TrapFrame
);
244 /* Exit with an error */
245 KiServiceExit(TrapFrame
, Status
);
248 /* We don't actually make it here */