Windows2000/private/ntos/ex/alpha/raisests.c
2020-09-30 17:12:32 +02:00

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);
}