159 lines
5.7 KiB
C
159 lines
5.7 KiB
C
/*++
|
|
Copyright (c) 1990 Microsoft Corporation
|
|
|
|
Module Name:
|
|
raisests.c
|
|
|
|
Abstract:
|
|
This module implements routines to raise a general exception from kernel mode or a noncontinuable exception from kernel mode.
|
|
|
|
Author:
|
|
David N. Cutler (davec) 18-Oct-1990
|
|
|
|
Environment:
|
|
Any mode.
|
|
|
|
Revision History:
|
|
Thomas Van Baak (tvb) 5-May-1992
|
|
Adapted for Alpha AXP.
|
|
--*/
|
|
|
|
#include "exp.h"
|
|
|
|
|
|
// Define private function prototypes.
|
|
VOID ExpRaiseException (IN PEXCEPTION_RECORD ExceptionRecord);
|
|
VOID ExpRaiseStatus (IN NTSTATUS ExceptionCode);
|
|
|
|
|
|
VOID ExRaiseException (IN PEXCEPTION_RECORD ExceptionRecord)
|
|
/*++
|
|
Routine Description:
|
|
This function raises a software exception by building a context record and calling the exception dispatcher directly.
|
|
|
|
N.B. This routine is a shell routine that simply calls another routine
|
|
to do the real work. The reason this is done is to avoid a problem
|
|
in try/finally scopes where the last statement in the scope is a call to raise an exception.
|
|
|
|
Arguments:
|
|
ExceptionRecord - Supplies a pointer to an exception record.
|
|
Return Value:
|
|
None.
|
|
--*/
|
|
{
|
|
#ifdef DBGtvb
|
|
DbgPrint("ExRaiseException(ExceptionRecord = %lx) Status = %lx\n", ExceptionRecord, ExceptionRecord->ExceptionCode);
|
|
);
|
|
#endif
|
|
ExpRaiseException(ExceptionRecord);
|
|
return;
|
|
}
|
|
|
|
|
|
VOID ExpRaiseException (IN PEXCEPTION_RECORD ExceptionRecord)
|
|
/*++
|
|
Routine Description:
|
|
This function raises a software exception by building a context record and calling the exception dispatcher directly.
|
|
Arguments:
|
|
ExceptionRecord - Supplies a pointer to an exception record.
|
|
Return Value:
|
|
None.
|
|
--*/
|
|
{
|
|
ULONG_PTR ControlPc;
|
|
CONTEXT ContextRecord;
|
|
FRAME_POINTERS EstablisherFrame;
|
|
PRUNTIME_FUNCTION FunctionEntry;
|
|
BOOLEAN InFunction;
|
|
ULONG_PTR NextPc;
|
|
NTSTATUS Status;
|
|
|
|
// Capture the current context, virtually unwind to the caller of this
|
|
// routine, set the fault instruction address to that of the caller, and
|
|
// call the exception dispatcher.
|
|
RtlCaptureContext(&ContextRecord);
|
|
ControlPc = (ULONG_PTR)ContextRecord.IntRa - 4;
|
|
FunctionEntry = RtlLookupFunctionEntry(ControlPc);
|
|
NextPc = RtlVirtualUnwind(ControlPc, FunctionEntry, &ContextRecord, &InFunction, &EstablisherFrame, NULL);
|
|
ContextRecord.Fir = (ULONGLONG)(LONG_PTR)NextPc + 4;
|
|
ExceptionRecord->ExceptionAddress = (PVOID)ContextRecord.Fir;
|
|
|
|
// If the exception is successfully dispatched, then continue execution.
|
|
// Otherwise, give the kernel debugger a chance to handle the exception.
|
|
if (RtlDispatchException(ExceptionRecord, &ContextRecord)) {
|
|
Status = ZwContinue(&ContextRecord, FALSE);
|
|
} else {
|
|
Status = ZwRaiseException(ExceptionRecord, &ContextRecord, FALSE);
|
|
}
|
|
|
|
// Either the attempt to continue execution or the attempt to give
|
|
// the kernel debugger a chance to handle the exception failed. Raise
|
|
// a noncontinuable exception.
|
|
ExRaiseStatus(Status);
|
|
}
|
|
|
|
|
|
VOID ExRaiseStatus (IN NTSTATUS ExceptionCode)
|
|
/*++
|
|
Routine Description:
|
|
This function raises an exception with the specified status value by building an exception record, building a context record, and calling the
|
|
exception dispatcher directly. The exception is marked as noncontinuable with no parameters. There is no return from this function.
|
|
|
|
N.B. This routine is a shell routine that simply calls another routine
|
|
to do the real work. The reason this is done is to avoid a problem
|
|
in try/finally scopes where the last statement in the scope is a call to raise an exception.
|
|
|
|
Arguments:
|
|
ExceptionCode - Supplies the status value to be used as the exception code for the exception that is to be raised.
|
|
--*/
|
|
{
|
|
#ifdef DBGxx
|
|
DbgPrint("ExRaiseStatus(ExceptionCode = %lx)\n", ExceptionCode);
|
|
#endif
|
|
ExpRaiseStatus(ExceptionCode);
|
|
}
|
|
|
|
|
|
VOID ExpRaiseStatus (IN NTSTATUS ExceptionCode)
|
|
/*++
|
|
Routine Description:
|
|
This function raises an exception with the specified status value by building an exception record, building a context record, and calling the
|
|
exception dispatcher directly. The exception is marked as noncontinuable with no parameters. There is no return from this function.
|
|
Arguments:
|
|
ExceptionCode - Supplies the status value to be used as the exception code for the exception that is to be raised.
|
|
--*/
|
|
{
|
|
ULONG_PTR ControlPc;
|
|
CONTEXT ContextRecord;
|
|
FRAME_POINTERS EstablisherFrame;
|
|
EXCEPTION_RECORD ExceptionRecord;
|
|
PRUNTIME_FUNCTION FunctionEntry;
|
|
BOOLEAN InFunction;
|
|
ULONG_PTR NextPc;
|
|
NTSTATUS Status;
|
|
|
|
// Construct an exception record.
|
|
ExceptionRecord.ExceptionCode = ExceptionCode;
|
|
ExceptionRecord.ExceptionRecord = (PEXCEPTION_RECORD)NULL;
|
|
ExceptionRecord.NumberParameters = 0;
|
|
ExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
|
|
|
|
// Capture the current context, virtually unwind to the caller of this
|
|
// routine, set the fault instruction address to that of the caller, and
|
|
// call the exception dispatcher.
|
|
RtlCaptureContext(&ContextRecord);
|
|
ControlPc = (ULONG_PTR)ContextRecord.IntRa - 4;
|
|
FunctionEntry = RtlLookupFunctionEntry(ControlPc);
|
|
NextPc = RtlVirtualUnwind(ControlPc, FunctionEntry, &ContextRecord, &InFunction, &EstablisherFrame, NULL);
|
|
ContextRecord.Fir = (ULONGLONG)(LONG_PTR)NextPc + 4;
|
|
ExceptionRecord.ExceptionAddress = (PVOID)ContextRecord.Fir;
|
|
RtlDispatchException(&ExceptionRecord, &ContextRecord);
|
|
|
|
// An unwind was not initiated during the dispatching of a noncontinuable
|
|
// exception. Give the kernel debugger a chance to handle the exception.
|
|
Status = ZwRaiseException(&ExceptionRecord, &ContextRecord, FALSE);
|
|
|
|
// The attempt to give the kernel debugger a chance to handle the exception
|
|
// failed. Raise another noncontinuable exception.
|
|
ExRaiseStatus(Status);
|
|
} |