[NTOS:KE] Remove unnecessary breakpoint in KiRaiseException. CORE-15640
[reactos.git] / ntoskrnl / ke / except.c
1 /*
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)
8 */
9
10 /* INCLUDES ******************************************************************/
11
12 #include <ntoskrnl.h>
13 #define NDEBUG
14 #include <debug.h>
15
16 /* FUNCTIONS *****************************************************************/
17
18 VOID
19 NTAPI
20 KiContinuePreviousModeUser(IN PCONTEXT Context,
21 IN PKEXCEPTION_FRAME ExceptionFrame,
22 IN PKTRAP_FRAME TrapFrame)
23 {
24 CONTEXT LocalContext;
25
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;
30
31 /* Convert the context into Exception/Trap Frames */
32 KeContextToTrapFrame(&LocalContext,
33 ExceptionFrame,
34 TrapFrame,
35 LocalContext.ContextFlags,
36 UserMode);
37 }
38
39 NTSTATUS
40 NTAPI
41 KiContinue(IN PCONTEXT Context,
42 IN PKEXCEPTION_FRAME ExceptionFrame,
43 IN PKTRAP_FRAME TrapFrame)
44 {
45 NTSTATUS Status = STATUS_SUCCESS;
46 KIRQL OldIrql = APC_LEVEL;
47 KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
48
49 /* Raise to APC_LEVEL, only if needed */
50 if (KeGetCurrentIrql() < APC_LEVEL) KeRaiseIrql(APC_LEVEL, &OldIrql);
51
52 /* Set up SEH to validate the context */
53 _SEH2_TRY
54 {
55 /* Check the previous mode */
56 if (PreviousMode != KernelMode)
57 {
58 /* Validate from user-mode */
59 KiContinuePreviousModeUser(Context,
60 ExceptionFrame,
61 TrapFrame);
62 }
63 else
64 {
65 /* Convert the context into Exception/Trap Frames */
66 KeContextToTrapFrame(Context,
67 ExceptionFrame,
68 TrapFrame,
69 Context->ContextFlags,
70 KernelMode);
71 }
72 }
73 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
74 {
75 /* Save the exception code */
76 Status = _SEH2_GetExceptionCode();
77 }
78 _SEH2_END;
79
80 /* Lower the IRQL if needed */
81 if (OldIrql < APC_LEVEL) KeLowerIrql(OldIrql);
82
83 /* Return status */
84 return Status;
85 }
86
87 NTSTATUS
88 NTAPI
89 KiRaiseException(IN PEXCEPTION_RECORD ExceptionRecord,
90 IN PCONTEXT Context,
91 IN PKEXCEPTION_FRAME ExceptionFrame,
92 IN PKTRAP_FRAME TrapFrame,
93 IN BOOLEAN SearchFrames)
94 {
95 KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
96 CONTEXT LocalContext;
97 EXCEPTION_RECORD LocalExceptionRecord;
98 ULONG ParameterCount, Size;
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 _SEH2_YIELD(return STATUS_INVALID_PARAMETER);
121 }
122
123 /* Probe the entire parameters now*/
124 Size = (sizeof(EXCEPTION_RECORD) -
125 ((EXCEPTION_MAXIMUM_PARAMETERS - ParameterCount) * sizeof(ULONG)));
126 ProbeForRead(ExceptionRecord, Size, sizeof(ULONG));
127
128 /* Now make copies in the stack */
129 RtlCopyMemory(&LocalContext, Context, sizeof(CONTEXT));
130 RtlCopyMemory(&LocalExceptionRecord, ExceptionRecord, Size);
131 Context = &LocalContext;
132 ExceptionRecord = &LocalExceptionRecord;
133
134 /* Update the parameter count */
135 ExceptionRecord->NumberParameters = ParameterCount;
136 }
137 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
138 {
139 /* Don't fail silently */
140 DPRINT1("KiRaiseException: Failed to Probe\n");
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 /* We are done */
164 return STATUS_SUCCESS;
165 }
166
167 /* SYSTEM CALLS ***************************************************************/
168
169 NTSTATUS
170 NTAPI
171 NtRaiseException(IN PEXCEPTION_RECORD ExceptionRecord,
172 IN PCONTEXT Context,
173 IN BOOLEAN FirstChance)
174 {
175 NTSTATUS Status;
176 PKTHREAD Thread;
177 PKTRAP_FRAME TrapFrame;
178
179 /* Get trap frame and link previous one*/
180 Thread = KeGetCurrentThread();
181 TrapFrame = Thread->TrapFrame;
182 Thread->TrapFrame = KiGetLinkedTrapFrame(TrapFrame);
183
184 /* Set exception list */
185 #ifdef _M_IX86
186 KeGetPcr()->NtTib.ExceptionList = TrapFrame->ExceptionList;
187 #endif
188
189 /* Raise the exception */
190 Status = KiRaiseException(ExceptionRecord,
191 Context,
192 NULL,
193 TrapFrame,
194 FirstChance);
195 if (NT_SUCCESS(Status))
196 {
197 /* It was handled, so exit restoring all state */
198 KiServiceExit2(TrapFrame);
199 }
200 else
201 {
202 /* Exit with error */
203 KiServiceExit(TrapFrame, Status);
204 }
205
206 /* We don't actually make it here */
207 return Status;
208 }
209
210 NTSTATUS
211 NTAPI
212 NtContinue(IN PCONTEXT Context,
213 IN BOOLEAN TestAlert)
214 {
215 PKTHREAD Thread;
216 NTSTATUS Status;
217 PKTRAP_FRAME TrapFrame;
218
219 /* Get trap frame and link previous one*/
220 Thread = KeGetCurrentThread();
221 TrapFrame = Thread->TrapFrame;
222 Thread->TrapFrame = KiGetLinkedTrapFrame(TrapFrame);
223
224 /* Continue from this point on */
225 Status = KiContinue(Context, NULL, TrapFrame);
226 if (NT_SUCCESS(Status))
227 {
228 /* Check if alert was requested */
229 if (TestAlert) KeTestAlertThread(Thread->PreviousMode);
230
231 /* Exit to new trap frame */
232 KiServiceExit2(TrapFrame);
233 }
234 else
235 {
236 /* Exit with an error */
237 KiServiceExit(TrapFrame, Status);
238 }
239
240 /* We don't actually make it here */
241 return Status;
242 }
243
244 /* EOF */