- Formatting fixes
[reactos.git] / reactos / ntoskrnl / ex / error.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel
4 * FILE: ntoskrnl/ex/error.c
5 * PURPOSE: Error Functions and Status/Exception Dispatching/Raising
6 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
7 */
8
9 /* INCLUDES *****************************************************************/
10
11 #include <ntoskrnl.h>
12 #define NDEBUG
13 #include <internal/debug.h>
14
15 #define TAG_ERR TAG('E', 'r', 'r', ' ')
16
17 /* GLOBALS ****************************************************************/
18
19 BOOLEAN ExReadyForErrors = FALSE;
20 PEPORT ExpDefaultErrorPort = NULL;
21 PEPROCESS ExpDefaultErrorPortProcess = NULL;
22
23 /* FUNCTIONS ****************************************************************/
24
25 VOID
26 NTAPI
27 ExpRaiseHardError(IN NTSTATUS ErrorStatus,
28 IN ULONG NumberOfParameters,
29 IN ULONG UnicodeStringParameterMask,
30 IN PULONG_PTR Parameters,
31 IN ULONG ValidResponseOptions,
32 OUT PULONG Response)
33 {
34 UNIMPLEMENTED;
35 }
36
37 /*
38 * @implemented
39 */
40 VOID
41 NTAPI
42 ExRaiseAccessViolation(VOID)
43 {
44 /* Raise the Right Status */
45 RtlRaiseStatus(STATUS_ACCESS_VIOLATION);
46 }
47
48 /*
49 * @implemented
50 */
51 VOID
52 NTAPI
53 ExRaiseDatatypeMisalignment (VOID)
54 {
55 /* Raise the Right Status */
56 RtlRaiseStatus(STATUS_DATATYPE_MISALIGNMENT);
57 }
58
59 /*
60 * @implemented
61 */
62 LONG
63 NTAPI
64 ExSystemExceptionFilter(VOID)
65 {
66 return KeGetPreviousMode() != KernelMode ?
67 EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH;
68 }
69
70 /*
71 * @unimplemented
72 */
73 VOID
74 NTAPI
75 ExRaiseHardError(IN NTSTATUS ErrorStatus,
76 IN ULONG NumberOfParameters,
77 IN ULONG UnicodeStringParameterMask,
78 IN PULONG_PTR Parameters,
79 IN ULONG ValidResponseOptions,
80 OUT PULONG Response)
81 {
82 /* FIXME: Capture to user-mode! */
83
84 /* Now call the worker function */
85 ExpRaiseHardError(ErrorStatus,
86 NumberOfParameters,
87 UnicodeStringParameterMask,
88 Parameters,
89 ValidResponseOptions,
90 Response);
91 }
92
93 NTSTATUS
94 NTAPI
95 NtRaiseHardError(IN NTSTATUS ErrorStatus,
96 IN ULONG NumberOfParameters,
97 IN ULONG UnicodeStringParameterMask,
98 IN PULONG_PTR Parameters,
99 IN ULONG ValidResponseOptions,
100 OUT PULONG Response)
101 {
102 NTSTATUS Status;
103 PULONG_PTR SafeParams = NULL;
104 ULONG SafeResponse;
105 UNICODE_STRING SafeString;
106 ULONG i;
107 ULONG ParamSize;
108 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
109 DPRINT1("Hard error %x\n", ErrorStatus);
110
111 /* Validate parameter count */
112 if (NumberOfParameters > MAXIMUM_HARDERROR_PARAMETERS)
113 {
114 /* Fail */
115 DPRINT1("Invalid parameters\n");
116 return STATUS_INVALID_PARAMETER_2;
117 }
118
119 /* Make sure we have some at least */
120 if ((Parameters) && !(NumberOfParameters))
121 {
122 /* Fail */
123 DPRINT1("Invalid parameters\n");
124 return STATUS_INVALID_PARAMETER_2;
125 }
126
127 /* Check if we were called from user-mode */
128 if (PreviousMode != KernelMode)
129 {
130 /* First validate the responses */
131 switch (ValidResponseOptions)
132 {
133 /* Check all valid cases */
134 case OptionAbortRetryIgnore:
135 case OptionOk:
136 case OptionOkCancel:
137 case OptionRetryCancel:
138 case OptionYesNo:
139 case OptionYesNoCancel:
140 case OptionShutdownSystem:
141 break;
142
143 /* Anything else is invalid */
144 default:
145 return STATUS_INVALID_PARAMETER_4;
146 }
147
148 /* Enter SEH Block */
149 _SEH_TRY
150 {
151 /* Validate the response pointer */
152 ProbeForWriteUlong(Response);
153
154 /* Check if we have parameters */
155 if (Parameters)
156 {
157 /* Validate the parameter pointers */
158 ParamSize = sizeof(ULONG_PTR) * NumberOfParameters;
159 ProbeForRead(Parameters, ParamSize, sizeof(ULONG_PTR));
160
161 /* Allocate a safe buffer */
162 SafeParams = ExAllocatePoolWithTag(PagedPool,
163 ParamSize,
164 TAG_ERR);
165
166 /* Copy them */
167 RtlMoveMemory(SafeParams, Parameters, ParamSize);
168
169 /* Nowo check if there's strings in it */
170 if (UnicodeStringParameterMask)
171 {
172 /* Loop every string */
173 for (i = 0; i < NumberOfParameters; i++)
174 {
175 /* Check if this parameter is a string */
176 if (UnicodeStringParameterMask & (1 << i))
177 {
178 /* Probe the structure */
179 ProbeForRead((PVOID)SafeParams[i],
180 sizeof(UNICODE_STRING),
181 sizeof(ULONG_PTR));
182
183 /* Capture it */
184 RtlMoveMemory(&SafeString,
185 (PVOID)SafeParams[i],
186 sizeof(UNICODE_STRING));
187
188 /* Probe the buffer */
189 ProbeForRead(SafeString.Buffer,
190 SafeString.MaximumLength,
191 sizeof(UCHAR));
192 }
193 }
194 }
195 }
196 }
197 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
198 {
199 /* Free captured buffer */
200 if (SafeParams) ExFreePool(SafeParams);
201 Status = _SEH_GetExceptionCode();
202 }
203 _SEH_END;
204
205 /* If we failed to capture/probe, bail out */
206 if (!NT_SUCCESS(Status)) return Status;
207
208 /* Call the system function directly, because we probed */
209 ExpRaiseHardError(ErrorStatus,
210 NumberOfParameters,
211 UnicodeStringParameterMask,
212 SafeParams,
213 ValidResponseOptions,
214 &SafeResponse);
215 }
216 else
217 {
218 /* Reuse variable */
219 SafeParams = Parameters;
220
221 /*
222 * Call the Executive Function. It will probe and copy pointers to
223 * user-mode
224 */
225 ExRaiseHardError(ErrorStatus,
226 NumberOfParameters,
227 UnicodeStringParameterMask,
228 SafeParams,
229 ValidResponseOptions,
230 &SafeResponse);
231 }
232
233 /* Check if we were called in user-mode */
234 if (PreviousMode != KernelMode)
235 {
236 /* That means we have a buffer to free */
237 if (SafeParams) ExFreePool(SafeParams);
238
239 /* Enter SEH Block for return */
240 _SEH_TRY
241 {
242 /* Return the response */
243 *Response = SafeResponse;
244 }
245 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
246 {
247 Status = _SEH_GetExceptionCode();
248 }
249 _SEH_END;
250 }
251 else
252 {
253 /* Return the response */
254 *Response = SafeResponse;
255 }
256
257 /* Return status */
258 return Status;
259 }
260
261 NTSTATUS
262 NTAPI
263 NtSetDefaultHardErrorPort(IN HANDLE PortHandle)
264 {
265 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
266 NTSTATUS Status = STATUS_UNSUCCESSFUL;
267
268 /* Check if we have the Privilege */
269 if(!SeSinglePrivilegeCheck(SeTcbPrivilege, PreviousMode))
270 {
271 DPRINT1("NtSetDefaultHardErrorPort: Caller requires "
272 "the SeTcbPrivilege privilege!\n");
273 return STATUS_PRIVILEGE_NOT_HELD;
274 }
275
276 /* Only called once during bootup, make sure we weren't called yet */
277 if(!ExReadyForErrors)
278 {
279 /* Reference the port */
280 Status = ObReferenceObjectByHandle(PortHandle,
281 0,
282 LpcPortObjectType,
283 PreviousMode,
284 (PVOID*)&ExpDefaultErrorPort,
285 NULL);
286
287 /* Check for Success */
288 if(NT_SUCCESS(Status))
289 {
290 /* Save the data */
291 ExpDefaultErrorPortProcess = PsGetCurrentProcess();
292 ExReadyForErrors = TRUE;
293 }
294 }
295
296 /* Return status to caller */
297 return Status;
298 }
299
300 VOID
301 __cdecl
302 _purecall(VOID)
303 {
304 /* Not supported in Kernel Mode */
305 RtlRaiseStatus(STATUS_NOT_IMPLEMENTED);
306 }
307
308 /* EOF */