274 lines
6.4 KiB
C
274 lines
6.4 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.
|
|||
|
|
|||
|
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);
|
|||
|
}
|