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");
143 /* Return the exception code */
144 _SEH2_YIELD(return _SEH2_GetExceptionCode());
149 /* Convert the context record */
150 KeContextToTrapFrame(Context
,
153 Context
->ContextFlags
,
156 /* Dispatch the exception */
157 ExceptionRecord
->ExceptionCode
&= ~KI_EXCEPTION_INTERNAL
;
158 KiDispatchException(ExceptionRecord
,
165 return STATUS_SUCCESS
;
168 /* SYSTEM CALLS ***************************************************************/
172 NtRaiseException(IN PEXCEPTION_RECORD ExceptionRecord
,
174 IN BOOLEAN FirstChance
)
178 PKTRAP_FRAME TrapFrame
;
180 /* Get trap frame and link previous one*/
181 Thread
= KeGetCurrentThread();
182 TrapFrame
= Thread
->TrapFrame
;
183 Thread
->TrapFrame
= KiGetLinkedTrapFrame(TrapFrame
);
185 /* Set exception list */
187 KeGetPcr()->NtTib
.ExceptionList
= TrapFrame
->ExceptionList
;
190 /* Raise the exception */
191 Status
= KiRaiseException(ExceptionRecord
,
196 if (NT_SUCCESS(Status
))
198 /* It was handled, so exit restoring all state */
199 KiServiceExit2(TrapFrame
);
203 /* Exit with error */
204 KiServiceExit(TrapFrame
, Status
);
207 /* We don't actually make it here */
213 NtContinue(IN PCONTEXT Context
,
214 IN BOOLEAN TestAlert
)
218 PKTRAP_FRAME TrapFrame
;
220 /* Get trap frame and link previous one*/
221 Thread
= KeGetCurrentThread();
222 TrapFrame
= Thread
->TrapFrame
;
223 Thread
->TrapFrame
= KiGetLinkedTrapFrame(TrapFrame
);
225 /* Continue from this point on */
226 Status
= KiContinue(Context
, NULL
, TrapFrame
);
227 if (NT_SUCCESS(Status
))
229 /* Check if alert was requested */
230 if (TestAlert
) KeTestAlertThread(Thread
->PreviousMode
);
232 /* Exit to new trap frame */
233 KiServiceExit2(TrapFrame
);
237 /* Exit with an error */
238 KiServiceExit(TrapFrame
, Status
);
241 /* We don't actually make it here */