190 lines
4.2 KiB
C
190 lines
4.2 KiB
C
/*++
|
|
|
|
Copyright (c) 2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
raise.c
|
|
|
|
Abstract:
|
|
|
|
This module implements functions to raise and exception and to raise
|
|
status.
|
|
|
|
Author:
|
|
|
|
David N. Cutler (davec) 28-Oct-2000
|
|
|
|
Environment:
|
|
|
|
Any mode.
|
|
|
|
--*/
|
|
|
|
#include "ntrtlp.h"
|
|
|
|
VOID
|
|
RtlRaiseException (
|
|
IN PEXCEPTION_RECORD ExceptionRecord
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function raises a software exception by building a context record
|
|
and calling the raise exception system service.
|
|
|
|
Arguments:
|
|
|
|
ExceptionRecord - Supplies a pointer to an exception record.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
CONTEXT ContextRecord;
|
|
ULONG64 ControlPc;
|
|
ULONG64 EstablisherFrame;
|
|
PRUNTIME_FUNCTION FunctionEntry;
|
|
PVOID HandlerData;
|
|
ULONG64 ImageBase;
|
|
NTSTATUS Status = STATUS_INVALID_DISPOSITION;
|
|
|
|
//
|
|
// Capture the current context, unwind to the caller of this routine, set
|
|
// the exception address, and call the appropriate exception dispatcher.
|
|
//
|
|
|
|
RtlCaptureContext(&ContextRecord);
|
|
ControlPc = ContextRecord.Rip;
|
|
FunctionEntry = RtlLookupFunctionEntry(ControlPc, &ImageBase, NULL);
|
|
if (FunctionEntry != NULL) {
|
|
RtlVirtualUnwind(UNW_FLAG_NHANDLER,
|
|
ImageBase,
|
|
ControlPc,
|
|
FunctionEntry,
|
|
&ContextRecord,
|
|
&HandlerData,
|
|
&EstablisherFrame,
|
|
NULL);
|
|
|
|
ExceptionRecord->ExceptionAddress = (PVOID)ContextRecord.Rip;
|
|
|
|
#if defined(NTOS_KERNEL_RUNTIME)
|
|
|
|
if (RtlDispatchException(ExceptionRecord, &ContextRecord) != FALSE) {
|
|
return;
|
|
|
|
}
|
|
|
|
Status = ZwRaiseException(ExceptionRecord, &ContextRecord, FALSE);
|
|
|
|
#else
|
|
|
|
if (ZwQueryPortInformationProcess() == FALSE) {
|
|
if (RtlDispatchException(ExceptionRecord, &ContextRecord) != FALSE) {
|
|
return;
|
|
}
|
|
|
|
Status = ZwRaiseException(ExceptionRecord, &ContextRecord, FALSE);
|
|
|
|
} else {
|
|
Status = ZwRaiseException(ExceptionRecord, &ContextRecord, TRUE);
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
//
|
|
// There should never be a return from either exception dispatch or the
|
|
// system service unless there is a problem with the argument list itself.
|
|
// Raise another exception specifying the status value returned.
|
|
//
|
|
|
|
RtlRaiseStatus(Status);
|
|
return;
|
|
}
|
|
|
|
#pragma warning(push)
|
|
#pragma warning(disable:4717) // recursive function
|
|
|
|
VOID
|
|
RtlRaiseStatus (
|
|
IN NTSTATUS Status
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function raises an exception with the specified status value. The
|
|
exception is marked as noncontinuable with no parameters.
|
|
|
|
Arguments:
|
|
|
|
Status - Supplies the status value to be used as the exception code
|
|
for the exception that is to be raised.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
CONTEXT ContextRecord;
|
|
EXCEPTION_RECORD ExceptionRecord;
|
|
|
|
//
|
|
// Capure the current context and construct an exception record.
|
|
//
|
|
|
|
RtlCaptureContext(&ContextRecord);
|
|
ExceptionRecord.ExceptionCode = Status;
|
|
ExceptionRecord.ExceptionRecord = NULL;
|
|
ExceptionRecord.NumberParameters = 0;
|
|
ExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
|
|
ExceptionRecord.ExceptionAddress = (PVOID)ContextRecord.Rip;
|
|
|
|
//
|
|
// Attempt to dispatch the exception.
|
|
//
|
|
// N.B. This exception is non-continuable.
|
|
//
|
|
|
|
#if defined(NTOS_KERNEL_RUNTIME)
|
|
|
|
RtlDispatchException(&ExceptionRecord, &ContextRecord);
|
|
Status = ZwRaiseException(&ExceptionRecord, &ContextRecord, FALSE);
|
|
|
|
#else
|
|
|
|
if (ZwQueryPortInformationProcess() == FALSE) {
|
|
RtlDispatchException(&ExceptionRecord, &ContextRecord);
|
|
Status = ZwRaiseException(&ExceptionRecord, &ContextRecord, FALSE);
|
|
|
|
} else {
|
|
Status = ZwRaiseException(&ExceptionRecord, &ContextRecord, TRUE);
|
|
}
|
|
|
|
#endif
|
|
|
|
//
|
|
// There should never be a return from either exception dispatch or the
|
|
// system service unless there is a problem with the argument list itself.
|
|
// Raise another exception specifying the status value returned.
|
|
//
|
|
|
|
RtlRaiseStatus(Status);
|
|
return;
|
|
}
|
|
|
|
#pragma warning(pop)
|