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
;
31 /* Convert the context into Exception/Trap Frames */
32 KeContextToTrapFrame(&LocalContext
,
35 LocalContext
.ContextFlags
,
41 KiContinue(IN PCONTEXT Context
,
42 IN PKEXCEPTION_FRAME ExceptionFrame
,
43 IN PKTRAP_FRAME TrapFrame
)
45 NTSTATUS Status
= STATUS_SUCCESS
;
46 KIRQL OldIrql
= APC_LEVEL
;
47 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
49 /* Raise to APC_LEVEL, only if needed */
50 if (KeGetCurrentIrql() < APC_LEVEL
) KeRaiseIrql(APC_LEVEL
, &OldIrql
);
52 /* Set up SEH to validate the context */
55 /* Check the previous mode */
56 if (PreviousMode
!= KernelMode
)
58 /* Validate from user-mode */
59 KiContinuePreviousModeUser(Context
,
65 /* Convert the context into Exception/Trap Frames */
66 KeContextToTrapFrame(Context
,
69 Context
->ContextFlags
,
73 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
75 /* Save the exception code */
76 Status
= _SEH2_GetExceptionCode();
80 /* Lower the IRQL if needed */
81 if (OldIrql
< APC_LEVEL
) KeLowerIrql(OldIrql
);
89 KiRaiseException(IN PEXCEPTION_RECORD ExceptionRecord
,
91 IN PKEXCEPTION_FRAME ExceptionFrame
,
92 IN PKTRAP_FRAME TrapFrame
,
93 IN BOOLEAN SearchFrames
)
95 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
97 EXCEPTION_RECORD LocalExceptionRecord
;
98 ULONG ParameterCount
, Size
;
100 /* Check if we need to probe */
101 if (PreviousMode
!= KernelMode
)
106 /* Probe the context */
107 ProbeForRead(Context
, sizeof(CONTEXT
), sizeof(ULONG
));
109 /* Probe the Exception Record */
110 ProbeForRead(ExceptionRecord
,
111 FIELD_OFFSET(EXCEPTION_RECORD
, NumberParameters
) +
115 /* Validate the maximum parameters */
116 if ((ParameterCount
= ExceptionRecord
->NumberParameters
) >
117 EXCEPTION_MAXIMUM_PARAMETERS
)
120 _SEH2_YIELD(return STATUS_INVALID_PARAMETER
);
123 /* Probe the entire parameters now*/
124 Size
= (sizeof(EXCEPTION_RECORD
) -
125 ((EXCEPTION_MAXIMUM_PARAMETERS
- ParameterCount
) * sizeof(ULONG
)));
126 ProbeForRead(ExceptionRecord
, Size
, sizeof(ULONG
));
128 /* Now make copies in the stack */
129 RtlCopyMemory(&LocalContext
, Context
, sizeof(CONTEXT
));
130 RtlCopyMemory(&LocalExceptionRecord
, ExceptionRecord
, Size
);
131 Context
= &LocalContext
;
132 ExceptionRecord
= &LocalExceptionRecord
;
134 /* Update the parameter count */
135 ExceptionRecord
->NumberParameters
= ParameterCount
;
137 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
139 /* Don't fail silently */
140 DPRINT1("KiRaiseException: Failed to Probe\n");
142 /* Return the exception code */
143 _SEH2_YIELD(return _SEH2_GetExceptionCode());
148 /* Convert the context record */
149 KeContextToTrapFrame(Context
,
152 Context
->ContextFlags
,
155 /* Dispatch the exception */
156 ExceptionRecord
->ExceptionCode
&= ~KI_EXCEPTION_INTERNAL
;
157 KiDispatchException(ExceptionRecord
,
164 return STATUS_SUCCESS
;
167 /* SYSTEM CALLS ***************************************************************/
171 NtRaiseException(IN PEXCEPTION_RECORD ExceptionRecord
,
173 IN BOOLEAN FirstChance
)
177 PKTRAP_FRAME TrapFrame
;
179 /* Get trap frame and link previous one*/
180 Thread
= KeGetCurrentThread();
181 TrapFrame
= Thread
->TrapFrame
;
182 Thread
->TrapFrame
= KiGetLinkedTrapFrame(TrapFrame
);
184 /* Set exception list */
186 KeGetPcr()->NtTib
.ExceptionList
= TrapFrame
->ExceptionList
;
189 /* Raise the exception */
190 Status
= KiRaiseException(ExceptionRecord
,
195 if (NT_SUCCESS(Status
))
197 /* It was handled, so exit restoring all state */
198 KiServiceExit2(TrapFrame
);
202 /* Exit with error */
203 KiServiceExit(TrapFrame
, Status
);
206 /* We don't actually make it here */
212 NtContinue(IN PCONTEXT Context
,
213 IN BOOLEAN TestAlert
)
217 PKTRAP_FRAME TrapFrame
;
219 /* Get trap frame and link previous one*/
220 Thread
= KeGetCurrentThread();
221 TrapFrame
= Thread
->TrapFrame
;
222 Thread
->TrapFrame
= KiGetLinkedTrapFrame(TrapFrame
);
224 /* Continue from this point on */
225 Status
= KiContinue(Context
, NULL
, TrapFrame
);
226 if (NT_SUCCESS(Status
))
228 /* Check if alert was requested */
229 if (TestAlert
) KeTestAlertThread(Thread
->PreviousMode
);
231 /* Exit to new trap frame */
232 KiServiceExit2(TrapFrame
);
236 /* Exit with an error */
237 KiServiceExit(TrapFrame
, Status
);
240 /* We don't actually make it here */