--- trunk/reactos/ntoskrnl/ex/error.c 2005-12-29 18:03:24 UTC (rev 20428)
+++ trunk/reactos/ntoskrnl/ex/error.c 2005-12-29 18:28:05 UTC (rev 20429)
@@ -1,10 +1,9 @@
/*
* COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS kernel
+ * PROJECT: ReactOS Kernel
* FILE: ntoskrnl/ex/error.c
* PURPOSE: Error Functions and Status/Exception Dispatching/Raising
- *
- * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) - Created File
+ * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
*/
/* INCLUDES *****************************************************************/
@@ -13,6 +12,8 @@
#define NDEBUG
#include <internal/debug.h>
+#define TAG_ERR TAG('E', 'r', 'r', ' ')
+
/* GLOBALS ****************************************************************/
BOOLEAN ExReadyForErrors = FALSE;
@@ -21,11 +22,23 @@
/* FUNCTIONS ****************************************************************/
+VOID
+NTAPI
+ExpRaiseHardError(IN NTSTATUS ErrorStatus,
+ IN ULONG NumberOfParameters,
+ IN ULONG UnicodeStringParameterMask,
+ IN PULONG_PTR Parameters,
+ IN ULONG ValidResponseOptions,
+ OUT PULONG Response)
+{
+ UNIMPLEMENTED;
+}
+
/*
* @implemented
*/
VOID
-STDCALL
+NTAPI
ExRaiseAccessViolation(VOID)
{
/* Raise the Right Status */
@@ -36,7 +49,7 @@
* @implemented
*/
VOID
-STDCALL
+NTAPI
ExRaiseDatatypeMisalignment (VOID)
{
/* Raise the Right Status */
@@ -47,17 +60,18 @@
* @implemented
*/
LONG
-STDCALL
+NTAPI
ExSystemExceptionFilter(VOID)
{
- return KeGetPreviousMode() != KernelMode ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH;
+ return KeGetPreviousMode() != KernelMode ?
+ EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH;
}
/*
* @unimplemented
*/
VOID
-STDCALL
+NTAPI
ExRaiseHardError(IN NTSTATUS ErrorStatus,
IN ULONG NumberOfParameters,
IN ULONG UnicodeStringParameterMask,
@@ -65,11 +79,19 @@
IN ULONG ValidResponseOptions,
OUT PULONG Response)
{
- UNIMPLEMENTED;
+ /* FIXME: Capture to user-mode! */
+
+ /* Now call the worker function */
+ ExpRaiseHardError(ErrorStatus,
+ NumberOfParameters,
+ UnicodeStringParameterMask,
+ Parameters,
+ ValidResponseOptions,
+ Response);
}
NTSTATUS
-STDCALL
+NTAPI
NtRaiseHardError(IN NTSTATUS ErrorStatus,
IN ULONG NumberOfParameters,
IN ULONG UnicodeStringParameterMask,
@@ -77,37 +99,184 @@
IN ULONG ValidResponseOptions,
OUT PULONG Response)
{
+ NTSTATUS Status;
+ PULONG_PTR SafeParams = NULL;
+ ULONG SafeResponse;
+ UNICODE_STRING SafeString;
+ ULONG i;
+ ULONG ParamSize;
+ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
DPRINT1("Hard error %x\n", ErrorStatus);
- /* Call the Executive Function (WE SHOULD PUT SEH HERE/CAPTURE!) */
- ExRaiseHardError(ErrorStatus,
- NumberOfParameters,
- UnicodeStringParameterMask,
- Parameters,
- ValidResponseOptions,
- Response);
+ /* Validate parameter count */
+ if (NumberOfParameters > MAXIMUM_HARDERROR_PARAMETERS)
+ {
+ /* Fail */
+ DPRINT1("Invalid parameters\n");
+ return STATUS_INVALID_PARAMETER_2;
+ }
- /* Return Success */
- return STATUS_SUCCESS;
+ /* Make sure we have some at least */
+ if ((Parameters) && !(NumberOfParameters))
+ {
+ /* Fail */
+ DPRINT1("Invalid parameters\n");
+ return STATUS_INVALID_PARAMETER_2;
+ }
+
+ /* Check if we were called from user-mode */
+ if (PreviousMode != KernelMode)
+ {
+ /* First validate the responses */
+ switch (ValidResponseOptions)
+ {
+ /* Check all valid cases */
+ case OptionAbortRetryIgnore:
+ case OptionOk:
+ case OptionOkCancel:
+ case OptionRetryCancel:
+ case OptionYesNo:
+ case OptionYesNoCancel:
+ case OptionShutdownSystem:
+ break;
+
+ /* Anything else is invalid */
+ default:
+ return STATUS_INVALID_PARAMETER_4;
+ }
+
+ /* Enter SEH Block */
+ _SEH_TRY
+ {
+ /* Validate the response pointer */
+ ProbeForWriteUlong(Response);
+
+ /* Check if we have parameters */
+ if (Parameters)
+ {
+ /* Validate the parameter pointers */
+ ParamSize = sizeof(ULONG_PTR) * NumberOfParameters;
+ ProbeForRead(Parameters, ParamSize, sizeof(ULONG_PTR));
+
+ /* Allocate a safe buffer */
+ SafeParams = ExAllocatePoolWithTag(PagedPool,
+ ParamSize,
+ TAG_ERR);
+
+ /* Copy them */
+ RtlMoveMemory(SafeParams, Parameters, ParamSize);
+
+ /* Nowo check if there's strings in it */
+ if (UnicodeStringParameterMask)
+ {
+ /* Loop every string */
+ for (i = 0; i < NumberOfParameters; i++)
+ {
+ /* Check if this parameter is a string */
+ if (UnicodeStringParameterMask & (1 << i))
+ {
+ /* Probe the structure */
+ ProbeForRead((PVOID)SafeParams[i],
+ sizeof(UNICODE_STRING),
+ sizeof(ULONG_PTR));
+
+ /* Capture it */
+ RtlMoveMemory(&SafeString,
+ (PVOID)SafeParams[i],
+ sizeof(UNICODE_STRING));
+
+ /* Probe the buffer */
+ ProbeForRead(SafeString.Buffer,
+ SafeString.MaximumLength,
+ sizeof(UCHAR));
+ }
+ }
+ }
+ }
+ }
+ _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
+ {
+ /* Free captured buffer */
+ if (SafeParams) ExFreePool(SafeParams);
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+
+ /* If we failed to capture/probe, bail out */
+ if (!NT_SUCCESS(Status)) return Status;
+
+ /* Call the system function directly, because we probed */
+ ExpRaiseHardError(ErrorStatus,
+ NumberOfParameters,
+ UnicodeStringParameterMask,
+ SafeParams,
+ ValidResponseOptions,
+ &SafeResponse);
+ }
+ else
+ {
+ /* Reuse variable */
+ SafeParams = Parameters;
+
+ /*
+ * Call the Executive Function. It will probe and copy pointers to
+ * user-mode
+ */
+ ExRaiseHardError(ErrorStatus,
+ NumberOfParameters,
+ UnicodeStringParameterMask,
+ SafeParams,
+ ValidResponseOptions,
+ &SafeResponse);
+ }
+
+ /* Check if we were called in user-mode */
+ if (PreviousMode != KernelMode)
+ {
+ /* That means we have a buffer to free */
+ if (SafeParams) ExFreePool(SafeParams);
+
+ /* Enter SEH Block for return */
+ _SEH_TRY
+ {
+ /* Return the response */
+ *Response = SafeResponse;
+ }
+ _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END;
+ }
+ else
+ {
+ /* Return the response */
+ *Response = SafeResponse;
+ }
+
+ /* Return status */
+ return Status;
}
NTSTATUS
-STDCALL
+NTAPI
NtSetDefaultHardErrorPort(IN HANDLE PortHandle)
{
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status = STATUS_UNSUCCESSFUL;
/* Check if we have the Privilege */
- if(!SeSinglePrivilegeCheck(SeTcbPrivilege, PreviousMode)) {
-
- DPRINT1("NtSetDefaultHardErrorPort: Caller requires the SeTcbPrivilege privilege!\n");
+ if(!SeSinglePrivilegeCheck(SeTcbPrivilege, PreviousMode))
+ {
+ DPRINT1("NtSetDefaultHardErrorPort: Caller requires "
+ "the SeTcbPrivilege privilege!\n");
return STATUS_PRIVILEGE_NOT_HELD;
}
/* Only called once during bootup, make sure we weren't called yet */
- if(!ExReadyForErrors) {
-
+ if(!ExReadyForErrors)
+ {
+ /* Reference the port */
Status = ObReferenceObjectByHandle(PortHandle,
0,
LpcPortObjectType,
@@ -116,14 +285,15 @@
NULL);
/* Check for Success */
- if(NT_SUCCESS(Status)) {
-
+ if(NT_SUCCESS(Status))
+ {
/* Save the data */
ExpDefaultErrorPortProcess = PsGetCurrentProcess();
ExReadyForErrors = TRUE;
}
}
+ /* Return status to caller */
return Status;
}