mirror of
https://github.com/reactos/reactos.git
synced 2025-07-31 19:31:45 +00:00
Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers into modules, and delete rossubsys.
This commit is contained in:
parent
b94e2d8ca0
commit
c2c66aff7d
24198 changed files with 0 additions and 37285 deletions
748
ntoskrnl/ex/harderr.c
Normal file
748
ntoskrnl/ex/harderr.c
Normal file
|
@ -0,0 +1,748 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Kernel
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: ntoskrnl/ex/harderr.c
|
||||
* PURPOSE: Error Functions and Status/Exception Dispatching/Raising
|
||||
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
||||
#include <ntoskrnl.h>
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
#define TAG_ERR ' rrE'
|
||||
|
||||
/* GLOBALS ****************************************************************/
|
||||
|
||||
BOOLEAN ExReadyForErrors = FALSE;
|
||||
PVOID ExpDefaultErrorPort = NULL;
|
||||
PEPROCESS ExpDefaultErrorPortProcess = NULL;
|
||||
|
||||
/* FUNCTIONS ****************************************************************/
|
||||
|
||||
/*++
|
||||
* @name ExpSystemErrorHandler
|
||||
*
|
||||
* For now it's a stub
|
||||
*
|
||||
* @param ErrorStatus
|
||||
* FILLME
|
||||
*
|
||||
* @param NumberOfParameters
|
||||
* FILLME
|
||||
*
|
||||
* @param UnicodeStringParameterMask
|
||||
* FILLME
|
||||
*
|
||||
* @param Parameters
|
||||
* FILLME
|
||||
*
|
||||
* @param ValidResponseOptions
|
||||
* FILLME
|
||||
*
|
||||
* @param Response
|
||||
* FILLME
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @remarks None
|
||||
*
|
||||
*--*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ExpSystemErrorHandler(IN NTSTATUS ErrorStatus,
|
||||
IN ULONG NumberOfParameters,
|
||||
IN ULONG UnicodeStringParameterMask,
|
||||
IN PULONG_PTR Parameters,
|
||||
IN BOOLEAN Shutdown)
|
||||
{
|
||||
ULONG_PTR BugCheckParameters[MAXIMUM_HARDERROR_PARAMETERS] = {0, 0, 0, 0};
|
||||
ULONG i;
|
||||
|
||||
/* Sanity check */
|
||||
ASSERT(NumberOfParameters <= MAXIMUM_HARDERROR_PARAMETERS);
|
||||
|
||||
/*
|
||||
* KeBugCheck expects MAXIMUM_HARDERROR_PARAMETERS parameters,
|
||||
* but we might get called with less, so use a local buffer here.
|
||||
*/
|
||||
for (i = 0; i < NumberOfParameters; i++)
|
||||
{
|
||||
/* Copy them over */
|
||||
BugCheckParameters[i] = Parameters[i];
|
||||
}
|
||||
|
||||
/* FIXME: STUB */
|
||||
KeBugCheckEx(FATAL_UNHANDLED_HARD_ERROR,
|
||||
ErrorStatus,
|
||||
(ULONG_PTR)BugCheckParameters,
|
||||
0,
|
||||
0);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/*++
|
||||
* @name ExpRaiseHardError
|
||||
*
|
||||
* For now it's a stub
|
||||
*
|
||||
* @param ErrorStatus
|
||||
* FILLME
|
||||
*
|
||||
* @param NumberOfParameters
|
||||
* FILLME
|
||||
*
|
||||
* @param UnicodeStringParameterMask
|
||||
* FILLME
|
||||
*
|
||||
* @param Parameters
|
||||
* FILLME
|
||||
*
|
||||
* @param ValidResponseOptions
|
||||
* FILLME
|
||||
*
|
||||
* @param Response
|
||||
* FILLME
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @remarks None
|
||||
*
|
||||
*--*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ExpRaiseHardError(IN NTSTATUS ErrorStatus,
|
||||
IN ULONG NumberOfParameters,
|
||||
IN ULONG UnicodeStringParameterMask,
|
||||
IN PULONG_PTR Parameters,
|
||||
IN ULONG ValidResponseOptions,
|
||||
OUT PULONG Response)
|
||||
{
|
||||
PEPROCESS Process = PsGetCurrentProcess();
|
||||
PETHREAD Thread = PsGetCurrentThread();
|
||||
UCHAR Buffer[PORT_MAXIMUM_MESSAGE_LENGTH];
|
||||
PHARDERROR_MSG Message = (PHARDERROR_MSG)Buffer;
|
||||
NTSTATUS Status;
|
||||
HANDLE PortHandle;
|
||||
KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
|
||||
PAGED_CODE();
|
||||
|
||||
/* Check if this error will shutdown the system */
|
||||
if (ValidResponseOptions == OptionShutdownSystem)
|
||||
{
|
||||
/* Check for privilege */
|
||||
if (!SeSinglePrivilegeCheck(SeShutdownPrivilege, PreviousMode))
|
||||
{
|
||||
/* No rights */
|
||||
*Response = ResponseNotHandled;
|
||||
return STATUS_PRIVILEGE_NOT_HELD;
|
||||
}
|
||||
|
||||
/* Don't handle any new hard errors */
|
||||
ExReadyForErrors = FALSE;
|
||||
}
|
||||
|
||||
/* Check if hard errors are not disabled */
|
||||
if (!Thread->HardErrorsAreDisabled)
|
||||
{
|
||||
/* Check if we can't do errors anymore, and this is serious */
|
||||
if (!ExReadyForErrors && NT_ERROR(ErrorStatus))
|
||||
{
|
||||
/* Use the system handler */
|
||||
ExpSystemErrorHandler(ErrorStatus,
|
||||
NumberOfParameters,
|
||||
UnicodeStringParameterMask,
|
||||
Parameters,
|
||||
(PreviousMode != KernelMode) ? TRUE: FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Enable hard error processing if it is enabled for the process
|
||||
* or if the exception status forces it */
|
||||
if ((Process->DefaultHardErrorProcessing & 1) ||
|
||||
(ErrorStatus & HARDERROR_OVERRIDE_ERRORMODE))
|
||||
{
|
||||
/* Check if we have an exception port */
|
||||
if (Process->ExceptionPort)
|
||||
{
|
||||
/* Use the port */
|
||||
PortHandle = Process->ExceptionPort;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Use our default system port */
|
||||
PortHandle = ExpDefaultErrorPort;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Don't process the error */
|
||||
PortHandle = NULL;
|
||||
}
|
||||
|
||||
/* If hard errors are disabled, do nothing */
|
||||
if (Thread->HardErrorsAreDisabled) PortHandle = NULL;
|
||||
|
||||
/* Now check if we have a port */
|
||||
if (PortHandle == NULL)
|
||||
{
|
||||
/* Just return to caller */
|
||||
*Response = ResponseReturnToCaller;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* Check if this is the default process */
|
||||
if (Process == ExpDefaultErrorPortProcess)
|
||||
{
|
||||
/* We can't handle the error, check if this is critical */
|
||||
if (NT_ERROR(ErrorStatus))
|
||||
{
|
||||
/* It is, invoke the system handler */
|
||||
ExpSystemErrorHandler(ErrorStatus,
|
||||
NumberOfParameters,
|
||||
UnicodeStringParameterMask,
|
||||
Parameters,
|
||||
(PreviousMode != KernelMode) ? TRUE: FALSE);
|
||||
|
||||
/* If we survived, return to caller */
|
||||
*Response = ResponseReturnToCaller;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
/* Setup the LPC Message */
|
||||
Message->h.u1.Length = (sizeof(HARDERROR_MSG) << 16) |
|
||||
(sizeof(HARDERROR_MSG) - sizeof(PORT_MESSAGE));
|
||||
Message->h.u2.ZeroInit = 0;
|
||||
Message->h.u2.s2.Type = LPC_ERROR_EVENT;
|
||||
Message->Status = ErrorStatus & ~HARDERROR_OVERRIDE_ERRORMODE;
|
||||
Message->ValidResponseOptions = ValidResponseOptions;
|
||||
Message->UnicodeStringParameterMask = UnicodeStringParameterMask;
|
||||
Message->NumberOfParameters = NumberOfParameters;
|
||||
KeQuerySystemTime(&Message->ErrorTime);
|
||||
|
||||
/* Copy the parameters */
|
||||
if (Parameters) RtlMoveMemory(&Message->Parameters,
|
||||
Parameters,
|
||||
sizeof(ULONG_PTR) * NumberOfParameters);
|
||||
|
||||
/* Send the LPC Message */
|
||||
Status = LpcRequestWaitReplyPort(PortHandle,
|
||||
(PPORT_MESSAGE)Message,
|
||||
(PPORT_MESSAGE)Message);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Check what kind of response we got */
|
||||
if ((Message->Response != ResponseReturnToCaller) &&
|
||||
(Message->Response != ResponseNotHandled) &&
|
||||
(Message->Response != ResponseAbort) &&
|
||||
(Message->Response != ResponseCancel) &&
|
||||
(Message->Response != ResponseIgnore) &&
|
||||
(Message->Response != ResponseNo) &&
|
||||
(Message->Response != ResponseOk) &&
|
||||
(Message->Response != ResponseRetry) &&
|
||||
(Message->Response != ResponseYes) &&
|
||||
(Message->Response != ResponseTryAgain) &&
|
||||
(Message->Response != ResponseContinue))
|
||||
{
|
||||
/* Reset to a default one */
|
||||
Message->Response = ResponseReturnToCaller;
|
||||
}
|
||||
|
||||
/* Set the response */
|
||||
*Response = Message->Response;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set the response */
|
||||
*Response = ResponseReturnToCaller;
|
||||
}
|
||||
|
||||
/* Return status */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*++
|
||||
* @name ExRaiseAccessViolation
|
||||
* @implemented
|
||||
*
|
||||
* The ExRaiseAccessViolation routine can be used with structured exception
|
||||
* handling to throw a driver-determined exception for a memory access
|
||||
* violation that occurs when a driver processes I/O requests.
|
||||
* See: http://msdn.microsoft.com/library/en-us/Kernel_r/hh/Kernel_r/k102_71b4c053-599c-4a6d-8a59-08aae6bdc534.xml.asp?frame=true
|
||||
* http://www.osronline.com/ddkx/kmarch/k102_814i.htm
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @remarks None
|
||||
*
|
||||
*--*/
|
||||
VOID
|
||||
NTAPI
|
||||
ExRaiseAccessViolation(VOID)
|
||||
{
|
||||
/* Raise the Right Status */
|
||||
RtlRaiseStatus(STATUS_ACCESS_VIOLATION);
|
||||
}
|
||||
|
||||
/*++
|
||||
* @name ExRaiseDatatypeMisalignment
|
||||
* @implemented
|
||||
*
|
||||
* ExRaiseDatatypeMisalignment raises an exception with the exception
|
||||
* code set to STATUS_DATATYPE_MISALIGNMENT
|
||||
* See: MSDN / DDK
|
||||
* http://www.osronline.com/ddkx/kmarch/k102_814i.htm
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @remarks None
|
||||
*
|
||||
*--*/
|
||||
VOID
|
||||
NTAPI
|
||||
ExRaiseDatatypeMisalignment(VOID)
|
||||
{
|
||||
/* Raise the Right Status */
|
||||
RtlRaiseStatus(STATUS_DATATYPE_MISALIGNMENT);
|
||||
}
|
||||
|
||||
/*++
|
||||
* @name ExSystemExceptionFilter
|
||||
* @implemented
|
||||
*
|
||||
* TODO: Add description
|
||||
*
|
||||
* @return FILLME
|
||||
*
|
||||
* @remarks None
|
||||
*
|
||||
*--*/
|
||||
LONG
|
||||
NTAPI
|
||||
ExSystemExceptionFilter(VOID)
|
||||
{
|
||||
return KeGetPreviousMode() != KernelMode ?
|
||||
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
|
||||
/*++
|
||||
* @name ExRaiseHardError
|
||||
* @implemented
|
||||
*
|
||||
* See NtRaiseHardError
|
||||
*
|
||||
* @param ErrorStatus
|
||||
* Error Code
|
||||
*
|
||||
* @param NumberOfParameters
|
||||
* Number of optional parameters in Parameters array
|
||||
*
|
||||
* @param UnicodeStringParameterMask
|
||||
* Optional string parameter (can be only one per error code)
|
||||
*
|
||||
* @param Parameters
|
||||
* Array of ULONG parameters for use in error message string
|
||||
*
|
||||
* @param ValidResponseOptions
|
||||
* See HARDERROR_RESPONSE_OPTION for possible values description
|
||||
*
|
||||
* @param Response
|
||||
* Pointer to HARDERROR_RESPONSE enumeration
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @remarks None
|
||||
*
|
||||
*--*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ExRaiseHardError(IN NTSTATUS ErrorStatus,
|
||||
IN ULONG NumberOfParameters,
|
||||
IN ULONG UnicodeStringParameterMask,
|
||||
IN PULONG_PTR Parameters,
|
||||
IN ULONG ValidResponseOptions,
|
||||
OUT PULONG Response)
|
||||
{
|
||||
SIZE_T Size;
|
||||
UNICODE_STRING CapturedParams[MAXIMUM_HARDERROR_PARAMETERS];
|
||||
ULONG i;
|
||||
PVOID UserData = NULL;
|
||||
PHARDERROR_USER_PARAMETERS UserParams;
|
||||
PWSTR BufferBase;
|
||||
ULONG SafeResponse;
|
||||
NTSTATUS Status;
|
||||
PAGED_CODE();
|
||||
|
||||
/* Check if we have parameters */
|
||||
if (Parameters)
|
||||
{
|
||||
/* Check if we have strings */
|
||||
if (UnicodeStringParameterMask)
|
||||
{
|
||||
/* Calculate the required size */
|
||||
Size = FIELD_OFFSET(HARDERROR_USER_PARAMETERS, Buffer[0]);
|
||||
|
||||
/* Loop each parameter */
|
||||
for (i = 0; i < NumberOfParameters; i++)
|
||||
{
|
||||
/* Check if it's part of the mask */
|
||||
if (UnicodeStringParameterMask & (1 << i))
|
||||
{
|
||||
/* Copy it */
|
||||
RtlMoveMemory(&CapturedParams[i],
|
||||
(PVOID)Parameters[i],
|
||||
sizeof(UNICODE_STRING));
|
||||
|
||||
/* Increase the size */
|
||||
Size += CapturedParams[i].MaximumLength;
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate the user data region */
|
||||
Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
|
||||
&UserData,
|
||||
0,
|
||||
&Size,
|
||||
MEM_COMMIT,
|
||||
PAGE_READWRITE);
|
||||
if (!NT_SUCCESS(Status)) return Status;
|
||||
|
||||
/* Set the pointers to our data */
|
||||
UserParams = UserData;
|
||||
BufferBase = UserParams->Buffer;
|
||||
|
||||
/* Loop parameters again */
|
||||
for (i = 0; i < NumberOfParameters; i++)
|
||||
{
|
||||
/* Check if we're in the mask */
|
||||
if (UnicodeStringParameterMask & (1 << i))
|
||||
{
|
||||
/* Update the base */
|
||||
UserParams->Parameters[i] = (ULONG_PTR)&UserParams->Strings[i];
|
||||
|
||||
/* Copy the string buffer */
|
||||
RtlMoveMemory(BufferBase,
|
||||
CapturedParams[i].Buffer,
|
||||
CapturedParams[i].MaximumLength);
|
||||
|
||||
/* Set buffer */
|
||||
CapturedParams[i].Buffer = BufferBase;
|
||||
|
||||
/* Copy the string structure */
|
||||
UserParams->Strings[i] = CapturedParams[i];
|
||||
|
||||
/* Update the pointer */
|
||||
BufferBase += CapturedParams[i].MaximumLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No need to copy any strings */
|
||||
UserParams->Parameters[i] = Parameters[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Just keep the data as is */
|
||||
UserData = Parameters;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now call the worker function */
|
||||
Status = ExpRaiseHardError(ErrorStatus,
|
||||
NumberOfParameters,
|
||||
UnicodeStringParameterMask,
|
||||
UserData,
|
||||
ValidResponseOptions,
|
||||
&SafeResponse);
|
||||
|
||||
/* Check if we had done user-mode allocation */
|
||||
if ((UserData) && (UserData != Parameters))
|
||||
{
|
||||
/* We did! Delete it */
|
||||
Size = 0;
|
||||
ZwFreeVirtualMemory(NtCurrentProcess(),
|
||||
&UserData,
|
||||
&Size,
|
||||
MEM_RELEASE);
|
||||
}
|
||||
|
||||
/* Return status and the response */
|
||||
*Response = SafeResponse;
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*++
|
||||
* @name NtRaiseHardError
|
||||
* @implemented
|
||||
*
|
||||
* This function sends HARDERROR_MSG LPC message to listener
|
||||
* (typically CSRSS.EXE). See NtSetDefaultHardErrorPort for more information
|
||||
* See: http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/Error/NtRaiseHardError.html
|
||||
*
|
||||
* @param ErrorStatus
|
||||
* Error Code
|
||||
*
|
||||
* @param NumberOfParameters
|
||||
* Number of optional parameters in Parameters array
|
||||
*
|
||||
* @param UnicodeStringParameterMask
|
||||
* Optional string parameter (can be only one per error code)
|
||||
*
|
||||
* @param Parameters
|
||||
* Array of ULONG_PTR parameters for use in error message string
|
||||
*
|
||||
* @param ValidResponseOptions
|
||||
* See HARDERROR_RESPONSE_OPTION for possible values description
|
||||
*
|
||||
* @param Response
|
||||
* Pointer to HARDERROR_RESPONSE enumeration
|
||||
*
|
||||
* @return Status
|
||||
*
|
||||
* @remarks NtRaiseHardError is easy way to display message in GUI
|
||||
* without loading Win32 API libraries
|
||||
*
|
||||
*--*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
NtRaiseHardError(IN NTSTATUS ErrorStatus,
|
||||
IN ULONG NumberOfParameters,
|
||||
IN ULONG UnicodeStringParameterMask,
|
||||
IN PULONG_PTR Parameters,
|
||||
IN ULONG ValidResponseOptions,
|
||||
OUT PULONG Response)
|
||||
{
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
PULONG_PTR SafeParams = NULL;
|
||||
ULONG SafeResponse;
|
||||
UNICODE_STRING SafeString;
|
||||
ULONG i;
|
||||
ULONG ParamSize = 0;
|
||||
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
|
||||
|
||||
/* Validate parameter count */
|
||||
if (NumberOfParameters > MAXIMUM_HARDERROR_PARAMETERS)
|
||||
{
|
||||
/* Fail */
|
||||
return STATUS_INVALID_PARAMETER_2;
|
||||
}
|
||||
|
||||
/* Make sure we have some at least */
|
||||
if ((Parameters != NULL) && (NumberOfParameters == 0))
|
||||
{
|
||||
/* Fail */
|
||||
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:
|
||||
case OptionOkNoWait:
|
||||
case OptionCancelTryContinue:
|
||||
break;
|
||||
|
||||
/* Anything else is invalid */
|
||||
default:
|
||||
return STATUS_INVALID_PARAMETER_4;
|
||||
}
|
||||
|
||||
/* Check if we have parameters */
|
||||
if (Parameters)
|
||||
{
|
||||
/* Calculate size of the parameters */
|
||||
ParamSize = sizeof(ULONG_PTR) * NumberOfParameters;
|
||||
|
||||
/* Allocate a safe buffer */
|
||||
SafeParams = ExAllocatePoolWithTag(PagedPool, ParamSize, TAG_ERR);
|
||||
if (!SafeParams)
|
||||
{
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
}
|
||||
|
||||
/* Enter SEH Block */
|
||||
_SEH2_TRY
|
||||
{
|
||||
/* Validate the response pointer */
|
||||
ProbeForWriteUlong(Response);
|
||||
|
||||
/* Check if we have parameters */
|
||||
if (Parameters)
|
||||
{
|
||||
/* Validate the parameter pointers */
|
||||
ProbeForRead(Parameters, ParamSize, sizeof(ULONG_PTR));
|
||||
|
||||
/* Copy them */
|
||||
RtlCopyMemory(SafeParams, Parameters, ParamSize);
|
||||
|
||||
/* Now 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 */
|
||||
RtlCopyMemory(&SafeString,
|
||||
(PVOID)SafeParams[i],
|
||||
sizeof(UNICODE_STRING));
|
||||
|
||||
/* Probe the buffer */
|
||||
ProbeForRead(SafeString.Buffer,
|
||||
SafeString.MaximumLength,
|
||||
sizeof(UCHAR));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
/* Free captured buffer */
|
||||
if (SafeParams) ExFreePoolWithTag(SafeParams, TAG_ERR);
|
||||
|
||||
/* Return the exception code */
|
||||
_SEH2_YIELD(return _SEH2_GetExceptionCode());
|
||||
}
|
||||
_SEH2_END;
|
||||
|
||||
/* 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) ExFreePoolWithTag(SafeParams, TAG_ERR);
|
||||
|
||||
/* Enter SEH Block for return */
|
||||
_SEH2_TRY
|
||||
{
|
||||
/* Return the response */
|
||||
*Response = SafeResponse;
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
/* Get the exception code */
|
||||
Status = _SEH2_GetExceptionCode();
|
||||
}
|
||||
_SEH2_END;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Return the response */
|
||||
*Response = SafeResponse;
|
||||
}
|
||||
|
||||
/* Return status */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*++
|
||||
* @name NtSetDefaultHardErrorPort
|
||||
* @implemented
|
||||
*
|
||||
* NtSetDefaultHardErrorPort is typically called only once. After call,
|
||||
* kernel set BOOLEAN flag named ExReadyForErrors to TRUE, and all other
|
||||
* tries to change default port are broken with STATUS_UNSUCCESSFUL error code
|
||||
* See: http://www.windowsitlibrary.com/Content/356/08/2.html
|
||||
* http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/Error/NtSetDefaultHardErrorPort.html
|
||||
*
|
||||
* @param PortHandle
|
||||
* Handle to named port object
|
||||
*
|
||||
* @return Status
|
||||
*
|
||||
* @remarks Privileges: SE_TCB_PRIVILEGE
|
||||
*
|
||||
*--*/
|
||||
NTSTATUS
|
||||
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");
|
||||
return STATUS_PRIVILEGE_NOT_HELD;
|
||||
}
|
||||
|
||||
/* Only called once during bootup, make sure we weren't called yet */
|
||||
if (!ExReadyForErrors)
|
||||
{
|
||||
/* Reference the port */
|
||||
Status = ObReferenceObjectByHandle(PortHandle,
|
||||
0,
|
||||
LpcPortObjectType,
|
||||
PreviousMode,
|
||||
(PVOID*)&ExpDefaultErrorPort,
|
||||
NULL);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Save the data */
|
||||
ExpDefaultErrorPortProcess = PsGetCurrentProcess();
|
||||
ExReadyForErrors = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return status to caller */
|
||||
return Status;
|
||||
}
|
||||
|
||||
VOID
|
||||
__cdecl
|
||||
_purecall(VOID)
|
||||
{
|
||||
/* Not supported in Kernel Mode */
|
||||
RtlRaiseStatus(STATUS_NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
/* EOF */
|
Loading…
Add table
Add a link
Reference in a new issue