ab348755f5ac40f7084926c0b2befbd3a16fc52c
[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 <internal/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 _SEH_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 _SEH_HANDLE
73 {
74 /* Save the exception code */
75 Status = _SEH_GetExceptionCode();
76 }
77 _SEH_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 /* Set up SEH */
101 _SEH_TRY
102 {
103 /* Check the previous mode */
104 if (PreviousMode != KernelMode)
105 {
106 #if 0
107 /* Probe the context */
108 ProbeForRead(Context, sizeof(CONTEXT), sizeof(ULONG));
109
110 /* Probe the Exception Record */
111 ProbeForRead(ExceptionRecord,
112 FIELD_OFFSET(EXCEPTION_RECORD, NumberParameters) +
113 sizeof(ULONG),
114 sizeof(ULONG));
115 #endif
116 /* Validate the maximum parameters */
117 if ((ParameterCount = ExceptionRecord->NumberParameters) >
118 EXCEPTION_MAXIMUM_PARAMETERS)
119 {
120 /* Too large */
121 Status = STATUS_INVALID_PARAMETER;
122 _SEH_LEAVE;
123 }
124
125 /* Probe the entire parameters now*/
126 Size = (sizeof(EXCEPTION_RECORD) -
127 ((EXCEPTION_MAXIMUM_PARAMETERS - ParameterCount) * sizeof(ULONG)));
128 ProbeForRead(ExceptionRecord, Size, sizeof(ULONG));
129
130 /* Now make copies in the stack */
131 RtlCopyMemory(&LocalContext, Context, sizeof(CONTEXT));
132 RtlCopyMemory(&LocalExceptionRecord, ExceptionRecord, Size);
133 Context = &LocalContext;
134 ExceptionRecord = &LocalExceptionRecord;
135
136 /* Update the parameter count */
137 ExceptionRecord->NumberParameters = ParameterCount;
138 }
139 }
140 _SEH_HANDLE
141 {
142 /* Get the exception code */
143 Status = _SEH_GetExceptionCode();
144 }
145 _SEH_END;
146
147 /* Make sure we didn't crash in SEH */
148 if (NT_SUCCESS(Status))
149 {
150 /* Convert the context record */
151 KeContextToTrapFrame(Context,
152 ExceptionFrame,
153 TrapFrame,
154 Context->ContextFlags,
155 PreviousMode);
156
157 /* Dispatch the exception */
158 KiDispatchException(ExceptionRecord,
159 ExceptionFrame,
160 TrapFrame,
161 PreviousMode,
162 SearchFrames);
163 }
164
165 /* Return the status */
166 return Status;
167 }
168
169 /* EOF */