Major refactoring of the exception handling code + misc fixes:
[reactos.git] / reactos / ntoskrnl / ke / exception.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel
4 * FILE: ntoskrnl/ke/exception.c
5 * PURPOSE: Platform independent exception handling
6 * PROGRAMMER: Alex Ionescu (alex@relsoft.net)
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 RtlMoveMemory(&LocalContext, Context, sizeof(CONTEXT));
28 Context = &LocalContext;
29
30 /* Convert the context into Exception/Trap Frames */
31 KeContextToTrapFrame(&LocalContext, ExceptionFrame, TrapFrame);
32 }
33
34 NTSTATUS
35 NTAPI
36 KiContinue(IN PCONTEXT Context,
37 IN PKEXCEPTION_FRAME ExceptionFrame,
38 IN PKTRAP_FRAME TrapFrame)
39 {
40 NTSTATUS Status = STATUS_SUCCESS;
41 KIRQL OldIrql = APC_LEVEL;
42 KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
43
44 /* Raise to APC_LEVEL, only if needed */
45 if (KeGetCurrentIrql() < APC_LEVEL)
46 {
47 /* Raise to APC_LEVEL */
48 KeRaiseIrql(APC_LEVEL, &OldIrql);
49 }
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, ExceptionFrame, TrapFrame);
66 }
67 }
68 _SEH_HANDLE
69 {
70 Status = _SEH_GetExceptionCode();
71 }
72 _SEH_END;
73
74 /* Lower the IRQL if needed */
75 if (OldIrql < APC_LEVEL) KeLowerIrql(OldIrql);
76
77 /* Return status */
78 return Status;
79 }
80
81 NTSTATUS
82 NTAPI
83 KiRaiseException(PEXCEPTION_RECORD ExceptionRecord,
84 PCONTEXT Context,
85 PKEXCEPTION_FRAME ExceptionFrame,
86 PKTRAP_FRAME TrapFrame,
87 BOOLEAN SearchFrames)
88 {
89 KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
90 CONTEXT LocalContext;
91 EXCEPTION_RECORD LocalExceptionRecord;
92 ULONG ParameterCount, Size;
93 NTSTATUS Status = STATUS_SUCCESS;
94 DPRINT1("KiRaiseException\n");
95
96 /* Set up SEH */
97 _SEH_TRY
98 {
99 /* Check the previous mode */
100 if (PreviousMode != KernelMode)
101 {
102 /* Probe the context */
103 ProbeForRead(Context, sizeof(CONTEXT), sizeof(ULONG));
104
105 /* Probe the Exception Record */
106 ProbeForRead(ExceptionRecord,
107 FIELD_OFFSET(EXCEPTION_RECORD, NumberParameters) +
108 sizeof(ULONG),
109 sizeof(ULONG));
110
111 /* Validate the maximum parameters */
112 if ((ParameterCount = ExceptionRecord->NumberParameters) >
113 EXCEPTION_MAXIMUM_PARAMETERS)
114 {
115 /* Too large */
116 return STATUS_INVALID_PARAMETER;
117 }
118
119 /* Probe the entire parameters now*/
120 Size = (sizeof(EXCEPTION_RECORD) -
121 ((EXCEPTION_MAXIMUM_PARAMETERS - ParameterCount) * sizeof(ULONG)));
122 ProbeForRead(ExceptionRecord, Size, sizeof(ULONG));
123
124 /* Now make copies in the stack */
125 RtlMoveMemory(&LocalContext, Context, sizeof(CONTEXT));
126 RtlMoveMemory(&LocalExceptionRecord, ExceptionRecord, Size);
127 Context = &LocalContext;
128 ExceptionRecord = &LocalExceptionRecord;
129
130 /* Update the parameter count */
131 ExceptionRecord->NumberParameters = ParameterCount;
132 }
133 }
134 _SEH_HANDLE
135 {
136 Status = _SEH_GetExceptionCode();
137 }
138 _SEH_END;
139
140 if (NT_SUCCESS(Status))
141 {
142 /* Convert the context record */
143 KeContextToTrapFrame(Context, ExceptionFrame, TrapFrame);
144
145 /* Dispatch the exception */
146 KiDispatchException(ExceptionRecord,
147 ExceptionFrame,
148 TrapFrame,
149 PreviousMode,
150 SearchFrames);
151 }
152
153 /* Return the status */
154 return Status;
155 }
156
157 /* EOF */