/*++ Copyright (c) 2000 Microsoft Corporation Module Name: raise.c Abstract: This module implements functions to raise and exception and to raise status. Author: David N. Cutler (davec) 28-Oct-2000 Environment: Any mode. --*/ #include "ntrtlp.h" VOID RtlRaiseException ( IN PEXCEPTION_RECORD ExceptionRecord ) /*++ Routine Description: This function raises a software exception by building a context record and calling the raise exception system service. Arguments: ExceptionRecord - Supplies a pointer to an exception record. Return Value: None. --*/ { CONTEXT ContextRecord; ULONG64 ControlPc; ULONG64 EstablisherFrame; PRUNTIME_FUNCTION FunctionEntry; PVOID HandlerData; ULONG64 ImageBase; NTSTATUS Status = STATUS_INVALID_DISPOSITION; // // Capture the current context, unwind to the caller of this routine, set // the exception address, and call the appropriate exception dispatcher. // RtlCaptureContext(&ContextRecord); ControlPc = ContextRecord.Rip; FunctionEntry = RtlLookupFunctionEntry(ControlPc, &ImageBase, NULL); if (FunctionEntry != NULL) { RtlVirtualUnwind(UNW_FLAG_NHANDLER, ImageBase, ControlPc, FunctionEntry, &ContextRecord, &HandlerData, &EstablisherFrame, NULL); ExceptionRecord->ExceptionAddress = (PVOID)ContextRecord.Rip; #if defined(NTOS_KERNEL_RUNTIME) if (RtlDispatchException(ExceptionRecord, &ContextRecord) != FALSE) { return; } Status = ZwRaiseException(ExceptionRecord, &ContextRecord, FALSE); #else if (ZwQueryPortInformationProcess() == FALSE) { if (RtlDispatchException(ExceptionRecord, &ContextRecord) != FALSE) { return; } Status = ZwRaiseException(ExceptionRecord, &ContextRecord, FALSE); } else { Status = ZwRaiseException(ExceptionRecord, &ContextRecord, TRUE); } #endif } // // There should never be a return from either exception dispatch or the // system service unless there is a problem with the argument list itself. // Raise another exception specifying the status value returned. // RtlRaiseStatus(Status); return; } #pragma warning(push) #pragma warning(disable:4717) // recursive function VOID RtlRaiseStatus ( IN NTSTATUS Status ) /*++ Routine Description: This function raises an exception with the specified status value. The exception is marked as noncontinuable with no parameters. Arguments: Status - Supplies the status value to be used as the exception code for the exception that is to be raised. Return Value: None. --*/ { CONTEXT ContextRecord; EXCEPTION_RECORD ExceptionRecord; // // Capure the current context and construct an exception record. // RtlCaptureContext(&ContextRecord); ExceptionRecord.ExceptionCode = Status; ExceptionRecord.ExceptionRecord = NULL; ExceptionRecord.NumberParameters = 0; ExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE; ExceptionRecord.ExceptionAddress = (PVOID)ContextRecord.Rip; // // Attempt to dispatch the exception. // // N.B. This exception is non-continuable. // #if defined(NTOS_KERNEL_RUNTIME) RtlDispatchException(&ExceptionRecord, &ContextRecord); Status = ZwRaiseException(&ExceptionRecord, &ContextRecord, FALSE); #else if (ZwQueryPortInformationProcess() == FALSE) { RtlDispatchException(&ExceptionRecord, &ContextRecord); Status = ZwRaiseException(&ExceptionRecord, &ContextRecord, FALSE); } else { Status = ZwRaiseException(&ExceptionRecord, &ContextRecord, TRUE); } #endif // // There should never be a return from either exception dispatch or the // system service unless there is a problem with the argument list itself. // Raise another exception specifying the status value returned. // RtlRaiseStatus(Status); return; } #pragma warning(pop)