NT4/private/ntos/ex/ppc/raisests.c
2020-09-30 17:12:29 +02:00

269 lines
6.2 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
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:
Tom Wood 23-Aug-1994
Add stack limit parameters to RtlVirtualUnwind.
--*/
#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.
--*/
{
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 ControlPc;
CONTEXT ContextRecord;
ULONG EstablisherFrame;
PRUNTIME_FUNCTION FunctionEntry;
BOOLEAN InFunction;
ULONG 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 = ContextRecord.Lr - 4;
FunctionEntry = RtlLookupFunctionEntry(ControlPc);
NextPc = RtlVirtualUnwind(ControlPc,
FunctionEntry,
&ContextRecord,
&InFunction,
&EstablisherFrame,
NULL,
0,
0xffffffff);
ContextRecord.Iar = NextPc + 4;
ExceptionRecord->ExceptionAddress = (PVOID)ContextRecord.Iar;
//
// 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.
--*/
{
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 ControlPc;
CONTEXT ContextRecord;
ULONG EstablisherFrame;
EXCEPTION_RECORD ExceptionRecord;
PRUNTIME_FUNCTION FunctionEntry;
BOOLEAN InFunction;
ULONG 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 = ContextRecord.Lr - 4;
FunctionEntry = RtlLookupFunctionEntry(ControlPc);
NextPc = RtlVirtualUnwind(ControlPc,
FunctionEntry,
&ContextRecord,
&InFunction,
&EstablisherFrame,
NULL,
0,
0xffffffff);
ContextRecord.Iar = NextPc + 4;
ExceptionRecord.ExceptionAddress = (PVOID)ContextRecord.Iar;
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);
}