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)
9 /* INCLUDES *****************************************************************/
13 #include <internal/debug.h>
15 #define TAG_ERR TAG('E', 'r', 'r', ' ')
17 /* GLOBALS ****************************************************************/
19 BOOLEAN ExReadyForErrors
= FALSE
;
20 PEPORT ExpDefaultErrorPort
= NULL
;
21 PEPROCESS ExpDefaultErrorPortProcess
= NULL
;
23 /* FUNCTIONS ****************************************************************/
27 ExpRaiseHardError(IN NTSTATUS ErrorStatus
,
28 IN ULONG NumberOfParameters
,
29 IN ULONG UnicodeStringParameterMask
,
30 IN PULONG_PTR Parameters
,
31 IN ULONG ValidResponseOptions
,
42 ExRaiseAccessViolation(VOID
)
44 /* Raise the Right Status */
45 RtlRaiseStatus(STATUS_ACCESS_VIOLATION
);
53 ExRaiseDatatypeMisalignment (VOID
)
55 /* Raise the Right Status */
56 RtlRaiseStatus(STATUS_DATATYPE_MISALIGNMENT
);
64 ExSystemExceptionFilter(VOID
)
66 return KeGetPreviousMode() != KernelMode
?
67 EXCEPTION_EXECUTE_HANDLER
: EXCEPTION_CONTINUE_SEARCH
;
75 ExRaiseHardError(IN NTSTATUS ErrorStatus
,
76 IN ULONG NumberOfParameters
,
77 IN ULONG UnicodeStringParameterMask
,
78 IN PULONG_PTR Parameters
,
79 IN ULONG ValidResponseOptions
,
82 /* FIXME: Capture to user-mode! */
84 /* Now call the worker function */
85 ExpRaiseHardError(ErrorStatus
,
87 UnicodeStringParameterMask
,
95 NtRaiseHardError(IN NTSTATUS ErrorStatus
,
96 IN ULONG NumberOfParameters
,
97 IN ULONG UnicodeStringParameterMask
,
98 IN PULONG_PTR Parameters
,
99 IN ULONG ValidResponseOptions
,
102 NTSTATUS Status
= STATUS_SUCCESS
;
103 PULONG_PTR SafeParams
= NULL
;
105 UNICODE_STRING SafeString
;
108 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
109 DPRINT1("Hard error %x\n", ErrorStatus
);
111 /* Validate parameter count */
112 if (NumberOfParameters
> MAXIMUM_HARDERROR_PARAMETERS
)
115 DPRINT1("Invalid parameters\n");
116 return STATUS_INVALID_PARAMETER_2
;
119 /* Make sure we have some at least */
120 if ((Parameters
) && !(NumberOfParameters
))
123 DPRINT1("Invalid parameters\n");
124 return STATUS_INVALID_PARAMETER_2
;
127 /* Check if we were called from user-mode */
128 if (PreviousMode
!= KernelMode
)
130 /* First validate the responses */
131 switch (ValidResponseOptions
)
133 /* Check all valid cases */
134 case OptionAbortRetryIgnore
:
137 case OptionRetryCancel
:
139 case OptionYesNoCancel
:
140 case OptionShutdownSystem
:
143 /* Anything else is invalid */
145 return STATUS_INVALID_PARAMETER_4
;
148 /* Enter SEH Block */
151 /* Validate the response pointer */
152 ProbeForWriteUlong(Response
);
154 /* Check if we have parameters */
157 /* Validate the parameter pointers */
158 ParamSize
= sizeof(ULONG_PTR
) * NumberOfParameters
;
159 ProbeForRead(Parameters
, ParamSize
, sizeof(ULONG_PTR
));
161 /* Allocate a safe buffer */
162 SafeParams
= ExAllocatePoolWithTag(PagedPool
,
167 RtlMoveMemory(SafeParams
, Parameters
, ParamSize
);
169 /* Nowo check if there's strings in it */
170 if (UnicodeStringParameterMask
)
172 /* Loop every string */
173 for (i
= 0; i
< NumberOfParameters
; i
++)
175 /* Check if this parameter is a string */
176 if (UnicodeStringParameterMask
& (1 << i
))
178 /* Probe the structure */
179 ProbeForRead((PVOID
)SafeParams
[i
],
180 sizeof(UNICODE_STRING
),
184 RtlMoveMemory(&SafeString
,
185 (PVOID
)SafeParams
[i
],
186 sizeof(UNICODE_STRING
));
188 /* Probe the buffer */
189 ProbeForRead(SafeString
.Buffer
,
190 SafeString
.MaximumLength
,
197 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
)
199 /* Free captured buffer */
200 if (SafeParams
) ExFreePool(SafeParams
);
201 Status
= _SEH_GetExceptionCode();
205 /* If we failed to capture/probe, bail out */
206 if (!NT_SUCCESS(Status
)) return Status
;
208 /* Call the system function directly, because we probed */
209 ExpRaiseHardError(ErrorStatus
,
211 UnicodeStringParameterMask
,
213 ValidResponseOptions
,
219 SafeParams
= Parameters
;
222 * Call the Executive Function. It will probe and copy pointers to
225 ExRaiseHardError(ErrorStatus
,
227 UnicodeStringParameterMask
,
229 ValidResponseOptions
,
233 /* Check if we were called in user-mode */
234 if (PreviousMode
!= KernelMode
)
236 /* That means we have a buffer to free */
237 if (SafeParams
) ExFreePool(SafeParams
);
239 /* Enter SEH Block for return */
242 /* Return the response */
243 *Response
= SafeResponse
;
245 _SEH_EXCEPT(_SEH_ExSystemExceptionFilter
)
247 Status
= _SEH_GetExceptionCode();
253 /* Return the response */
254 *Response
= SafeResponse
;
263 NtSetDefaultHardErrorPort(IN HANDLE PortHandle
)
265 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
266 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
268 /* Check if we have the Privilege */
269 if(!SeSinglePrivilegeCheck(SeTcbPrivilege
, PreviousMode
))
271 DPRINT1("NtSetDefaultHardErrorPort: Caller requires "
272 "the SeTcbPrivilege privilege!\n");
273 return STATUS_PRIVILEGE_NOT_HELD
;
276 /* Only called once during bootup, make sure we weren't called yet */
277 if(!ExReadyForErrors
)
279 /* Reference the port */
280 Status
= ObReferenceObjectByHandle(PortHandle
,
284 (PVOID
*)&ExpDefaultErrorPort
,
287 /* Check for Success */
288 if(NT_SUCCESS(Status
))
291 ExpDefaultErrorPortProcess
= PsGetCurrentProcess();
292 ExReadyForErrors
= TRUE
;
296 /* Return status to caller */
304 /* Not supported in Kernel Mode */
305 RtlRaiseStatus(STATUS_NOT_IMPLEMENTED
);