2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/ke/except.c
5 * PURPOSE: Platform independent exception handling
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
9 /* INCLUDES ******************************************************************/
13 #include <internal/debug.h>
15 /* FUNCTIONS *****************************************************************/
19 KiContinuePreviousModeUser(IN PCONTEXT Context
,
20 IN PKEXCEPTION_FRAME ExceptionFrame
,
21 IN PKTRAP_FRAME TrapFrame
)
25 /* We'll have to make a copy and probe it */
26 ProbeForRead(Context
, sizeof(CONTEXT
), sizeof(ULONG
));
27 RtlCopyMemory(&LocalContext
, Context
, sizeof(CONTEXT
));
28 Context
= &LocalContext
;
30 /* Convert the context into Exception/Trap Frames */
31 KeContextToTrapFrame(&LocalContext
,
34 LocalContext
.ContextFlags
,
40 KiContinue(IN PCONTEXT Context
,
41 IN PKEXCEPTION_FRAME ExceptionFrame
,
42 IN PKTRAP_FRAME TrapFrame
)
44 NTSTATUS Status
= STATUS_SUCCESS
;
45 KIRQL OldIrql
= APC_LEVEL
;
46 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
48 /* Raise to APC_LEVEL, only if needed */
49 if (KeGetCurrentIrql() < APC_LEVEL
) KeRaiseIrql(APC_LEVEL
, &OldIrql
);
51 /* Set up SEH to validate the context */
54 /* Check the previous mode */
55 if (PreviousMode
!= KernelMode
)
57 /* Validate from user-mode */
58 KiContinuePreviousModeUser(Context
,
64 /* Convert the context into Exception/Trap Frames */
65 KeContextToTrapFrame(Context
,
68 Context
->ContextFlags
,
74 /* Save the exception code */
75 Status
= _SEH_GetExceptionCode();
79 /* Lower the IRQL if needed */
80 if (OldIrql
< APC_LEVEL
) KeLowerIrql(OldIrql
);
88 KiRaiseException(IN PEXCEPTION_RECORD ExceptionRecord
,
90 IN PKEXCEPTION_FRAME ExceptionFrame
,
91 IN PKTRAP_FRAME TrapFrame
,
92 IN BOOLEAN SearchFrames
)
94 KPROCESSOR_MODE PreviousMode
= KeGetPreviousMode();
96 EXCEPTION_RECORD LocalExceptionRecord
;
97 ULONG ParameterCount
, Size
;
98 NTSTATUS Status
= STATUS_SUCCESS
;
103 /* Check the previous mode */
104 if (PreviousMode
!= KernelMode
)
107 /* Probe the context */
108 ProbeForRead(Context
, sizeof(CONTEXT
), sizeof(ULONG
));
110 /* Probe the Exception Record */
111 ProbeForRead(ExceptionRecord
,
112 FIELD_OFFSET(EXCEPTION_RECORD
, NumberParameters
) +
116 /* Validate the maximum parameters */
117 if ((ParameterCount
= ExceptionRecord
->NumberParameters
) >
118 EXCEPTION_MAXIMUM_PARAMETERS
)
121 Status
= STATUS_INVALID_PARAMETER
;
125 /* Probe the entire parameters now*/
126 Size
= (sizeof(EXCEPTION_RECORD
) -
127 ((EXCEPTION_MAXIMUM_PARAMETERS
- ParameterCount
) * sizeof(ULONG
)));
128 ProbeForRead(ExceptionRecord
, Size
, sizeof(ULONG
));
130 /* Now make copies in the stack */
131 RtlCopyMemory(&LocalContext
, Context
, sizeof(CONTEXT
));
132 RtlCopyMemory(&LocalExceptionRecord
, ExceptionRecord
, Size
);
133 Context
= &LocalContext
;
134 ExceptionRecord
= &LocalExceptionRecord
;
136 /* Update the parameter count */
137 ExceptionRecord
->NumberParameters
= ParameterCount
;
142 /* Get the exception code */
143 Status
= _SEH_GetExceptionCode();
147 /* Make sure we didn't crash in SEH */
148 if (NT_SUCCESS(Status
))
150 /* Convert the context record */
151 KeContextToTrapFrame(Context
,
154 Context
->ContextFlags
,
157 /* Dispatch the exception */
158 KiDispatchException(ExceptionRecord
,
165 /* Return the status */