/*++

Copyright (c) 1990  Microsoft Corporation

Module Name:

    raisexcp.c

Abstract:

    This module implements the internal kernel code to continue execution
    and raise a exception.

Author:

    David N. Cutler (davec) 8-Aug-1990

Environment:

    Kernel mode only.

Revision History:

--*/

#include "ki.h"

NTSTATUS
KiContinue (
    IN PCONTEXT ContextRecord,
    IN PKEXCEPTION_FRAME ExceptionFrame,
    IN PKTRAP_FRAME TrapFrame
    )

/*++

Routine Description:

    This function is called to copy the specified context frame to the
    specified exception and trap frames for the continue system service.

Arguments:

    ContextRecord - Supplies a pointer to a context record.

    ExceptionFrame - Supplies a pointer to an exception frame.

    TrapFrame - Supplies a pointer to a trap frame.

Return Value:

    STATUS_ACCESS_VIOLATION is returned if the context record is not readable
        from user mode.

    STATUS_DATATYPE_MISALIGNMENT is returned if the context record is not
        properly aligned.

    STATUS_SUCCESS is returned if the context frame is copied successfully
        to the specified exception and trap frames.

--*/

{
    KIRQL OldIrql;
    BOOLEAN IrqlChanged = FALSE;

    //
    // Synchronize with other context operations.
    //

    if (KeGetCurrentIrql() < APC_LEVEL) {

        //
        // To support try-except and ExRaiseStatus in device driver code we
        // need to check if we are already at raised level.
        //

        IrqlChanged = TRUE;
        KeRaiseIrql(APC_LEVEL, &OldIrql);
    }

    //
    // Move information from the context record to the exception
    // and trap frames.
    //

    KeContextToKframes(TrapFrame,
                       ContextRecord,
                       ContextRecord->ContextFlags);

    if (IrqlChanged) {
        KeLowerIrql (OldIrql);
    }

    return STATUS_SUCCESS;
}

NTSTATUS
KiRaiseException (
    IN PEXCEPTION_RECORD ExceptionRecord,
    IN PCONTEXT ContextRecord,
    IN PKEXCEPTION_FRAME ExceptionFrame,
    IN PKTRAP_FRAME TrapFrame,
    IN BOOLEAN FirstChance
    )

/*++

Routine Description:

    This function is called to raise an exception. The exception can be
    raised as a first or second chance exception.

Arguments:

    ExceptionRecord - Supplies a pointer to an exception record.

    ContextRecord - Supplies a pointer to a context record.

    ExceptionFrame - Supplies a pointer to an exception frame.

    TrapFrame - Supplies a pointer to a trap frame.

    FirstChance - Supplies a boolean value that specifies whether this is
        the first (TRUE) or second (FALSE) chance for the exception.

Return Value:

    STATUS_ACCESS_VIOLATION is returned if either the exception or the context
        record is not readable from user mode.

    STATUS_DATATYPE_MISALIGNMENT is returned if the exception record or the
        context record are not properly aligned.

    STATUS_INVALID_PARAMETER is returned if the number of exception parameters
        is greater than the maximum allowable number of exception parameters.

    STATUS_SUCCESS is returned if the exception is dispatched and handled.

--*/

{

    //
    // Move information from the context record to the exception and
    // trap frames.
    //

    KeContextToKframes(TrapFrame,
                       ContextRecord,
                       ContextRecord->ContextFlags);

    //
    // Make sure the reserved bit is clear in the exception code and
    // perform exception dispatching.
    //
    // N.B. The reserved bit is used to differentiate internally gerarated
    //      codes from codes generated by application programs.
    //

    ExceptionRecord->ExceptionCode &= 0xefffffff;
    KiDispatchException(ExceptionRecord,
                        ExceptionFrame,
                        TrapFrame,
                        FirstChance);

    return STATUS_SUCCESS;
}
