fd4ba952eda5207d3f882c83e5990b9987249b3d
[reactos.git] / reactos / ntoskrnl / ke / except.c
1 /*
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)
7 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include <ntoskrnl.h>
12 #define NDEBUG
13 #include <debug.h>
14
15 /* FUNCTIONS *****************************************************************/
16
17 VOID
18 NTAPI
19 KiContinuePreviousModeUser(IN PCONTEXT Context,
20 IN PKEXCEPTION_FRAME ExceptionFrame,
21 IN PKTRAP_FRAME TrapFrame)
22 {
23 CONTEXT LocalContext;
24
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;
29
30 /* Convert the context into Exception/Trap Frames */
31 KeContextToTrapFrame(&LocalContext,
32 ExceptionFrame,
33 TrapFrame,
34 LocalContext.ContextFlags,
35 UserMode);
36 }
37
38 NTSTATUS
39 NTAPI
40 KiContinue(IN PCONTEXT Context,
41 IN PKEXCEPTION_FRAME ExceptionFrame,
42 IN PKTRAP_FRAME TrapFrame)
43 {
44 NTSTATUS Status = STATUS_SUCCESS;
45 KIRQL OldIrql = APC_LEVEL;
46 KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
47
48 /* Raise to APC_LEVEL, only if needed */
49 if (KeGetCurrentIrql() < APC_LEVEL) KeRaiseIrql(APC_LEVEL, &OldIrql);
50
51 /* Set up SEH to validate the context */
52 _SEH2_TRY
53 {
54 /* Check the previous mode */
55 if (PreviousMode != KernelMode)
56 {
57 /* Validate from user-mode */
58 KiContinuePreviousModeUser(Context,
59 ExceptionFrame,
60 TrapFrame);
61 }
62 else
63 {
64 /* Convert the context into Exception/Trap Frames */
65 KeContextToTrapFrame(Context,
66 ExceptionFrame,
67 TrapFrame,
68 Context->ContextFlags,
69 KernelMode);
70 }
71 }
72 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
73 {
74 /* Save the exception code */
75 Status = _SEH2_GetExceptionCode();
76 }
77 _SEH2_END;
78
79 /* Lower the IRQL if needed */
80 if (OldIrql < APC_LEVEL) KeLowerIrql(OldIrql);
81
82 /* Return status */
83 return Status;
84 }
85
86 NTSTATUS
87 NTAPI
88 KiRaiseException(IN PEXCEPTION_RECORD ExceptionRecord,
89 IN PCONTEXT Context,
90 IN PKEXCEPTION_FRAME ExceptionFrame,
91 IN PKTRAP_FRAME TrapFrame,
92 IN BOOLEAN SearchFrames)
93 {
94 KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
95 CONTEXT LocalContext;
96 EXCEPTION_RECORD LocalExceptionRecord;
97 ULONG ParameterCount, Size;
98 NTSTATUS Status = STATUS_SUCCESS;
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) >
117 EXCEPTION_MAXIMUM_PARAMETERS)
118 {
119 /* Too large */
120 Status = STATUS_INVALID_PARAMETER;
121 _SEH2_LEAVE;
122 }
123
124 /* Probe the entire parameters now*/
125 Size = (sizeof(EXCEPTION_RECORD) -
126 ((EXCEPTION_MAXIMUM_PARAMETERS - ParameterCount) * sizeof(ULONG)));
127 ProbeForRead(ExceptionRecord, Size, sizeof(ULONG));
128
129 /* Now make copies in the stack */
130 RtlCopyMemory(&LocalContext, Context, sizeof(CONTEXT));
131 RtlCopyMemory(&LocalExceptionRecord, ExceptionRecord, Size);
132 Context = &LocalContext;
133 ExceptionRecord = &LocalExceptionRecord;
134
135 /* Update the parameter count */
136 ExceptionRecord->NumberParameters = ParameterCount;
137 }
138 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
139 {
140 DbgBreakPoint();
141
142 /* Return the exception code */
143 _SEH2_YIELD(return _SEH2_GetExceptionCode());
144 }
145 _SEH2_END;
146 }
147
148 /* Convert the context record */
149 KeContextToTrapFrame(Context,
150 ExceptionFrame,
151 TrapFrame,
152 Context->ContextFlags,
153 PreviousMode);
154
155 /* Dispatch the exception */
156 ExceptionRecord->ExceptionCode &= ~KI_EXCEPTION_INTERNAL;
157 KiDispatchException(ExceptionRecord,
158 ExceptionFrame,
159 TrapFrame,
160 PreviousMode,
161 SearchFrames);
162
163 /* Return the status */
164 return Status;
165 }
166
167 /* EOF */