|
|
/*++
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.
Return Value:
None.
--*/
{
#ifdef DBGxx
DbgPrint("ExRaiseStatus(ExceptionCode = %lx)\n", ExceptionCode); #endif
ExpRaiseStatus(ExceptionCode); return; }
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.
Return Value:
None.
--*/
{
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); }
|