- Add a comment and debug print
[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 /* Don't fail silently */
141 DPRINT1("KiRaiseException: Failed to Probe\n"),
142 DbgBreakPoint();
143
144 /* Return the exception code */
145 _SEH2_YIELD(return _SEH2_GetExceptionCode());
146 }
147 _SEH2_END;
148 }
149
150 /* Convert the context record */
151 KeContextToTrapFrame(Context,
152 ExceptionFrame,
153 TrapFrame,
154 Context->ContextFlags,
155 PreviousMode);
156
157 /* Dispatch the exception */
158 ExceptionRecord->ExceptionCode &= ~KI_EXCEPTION_INTERNAL;
159 KiDispatchException(ExceptionRecord,
160 ExceptionFrame,
161 TrapFrame,
162 PreviousMode,
163 SearchFrames);
164
165 /* Return the status */
166 return Status;
167 }
168
169 /* EOF */