;
; HANDLER.ASM
;
; ExceptionHandler function used as the callback for the GP Fault Handler.
;
; Copyright(c) Microsoft Corp. 1992 All Rights Reserved
;

    .xlist
    ?PLM=1
    ?WIN=1
    include cmacros.inc
    include toolhelp.inc
    include fault.inc
    .list


createSeg HANDLER_TEXT, HANDLER_TEXT, BYTE, PUBLIC, CODE
sBegin    HANDLER_TEXT
assumes   CS,HANDLER_TEXT
assumes   DS,_DATA


;
; ExceptionHandler
;
; Purpose:
;  Exception handling function called from ToolHelp when it detects
;  an exception.  If the error was caused by our application AND we
;  want to trap it, then we use Throw to return control to the function
;  that faulted at a point BEFORE the erroneous code.  If we do not
;  want the fault, then we just pass it to the next interrupt handler.
;
;  If the fault was caused by our application, we use Throw to return to
;  whatever function caused it.  Otherwise we just let the fault pass.
;
; Parameters:
;  None; however, the stack contains values of interest.  We use AX to
;  simply set the DS register properly.
;
;     |           .           |
;     |           .           |
;     |           .           |
;     |-----------------------|
;     |   SS (fault)          |  SP + 12h
;     |-----------------------|
;     |   SP (fault)          |  SP + 10h
;     |-----------------------|
;     |   Flags (fault)       |  SP + 0Eh
;     |-----------------------|
;     |   CS (fault)          |  SP + 0Ch
;     |-----------------------|
;     |   IP (fault)          |  SP + 0Ah
;     |-----------------------|
;     |   handle (internal)   |  SP + 08h
;     |-----------------------|
;     |   interrupt number    |  SP + 06h
;     |-----------------------|
;     |   AX (NOT the DS)     |  SP + 04h
;     |-----------------------|
;     |   CS (toolhelp.dll)   |  SP + 02h
;     |-----------------------|
;     |   IP (toolhelp.dll)   |  SP + 00h
;     +-----------------------+
;
;  Note that the interrupt number may have the high bit set to
;  indicate a low-stack fault (above and beyond a normal Int 12 stack)
;  fault.  We trap this condition if we're trapping a stack fault or a
;  GP fault.
;


cProc   ExceptionHandler, <PUBLIC,FAR>

cBegin  nogen

        mov     ds,ax               ;Make sure we can reference our data.

        mov     ax,bp
        mov     bp,sp
        mov     bx,[bp+06]
        mov     bp,ax

        ;
        ; Cycle through the possible faults we are looking for.
        ; If BX contains that fault, then we use Throw to return
        ; the error to the application.  Otherwise we pass the
        ; fault down the chain.
        ;
        ; First, the high bit might be set in the interrupt meaning
        ; that we have a low-stack fault.  Since we do not handle
        ; these, we exit this handler.
        ;

        test    bx,08000h           ;Check high bit
        jnz     EHExit              ;Leave it it's set--we can't handle it.

        mov     ax,_wException      ;Get the exceptions we want to trap.
        or      ax,ax               ;Do we want any?
        jz      EHExit


EHDivideByZero:
        ;
        ; Check for divide by zero.
        ;

        test    ax,EXCEPTION_DIVIDEBYZERO
        jz      EHGPFault
        or      bx,bx
        jz      EHThrow


EHGPFault:
        ;
        ; Check for a GP fault.
        ;

        test    ax,EXCEPTION_GPFAULT
        jz      EHExit
        cmp     bx,13
        je      EHThrow


EHThrow:
        ccall   Throw,<_pcbEx, 1>  ;Return the exception to the faulting
                                    ;function.

EHExit:
        retf


EHRestart:
        ;
        ; This code illustrates what we need to do if we wanted to
        ; clean up the problem and restart the instruction that faulted.
        ; This exception handler does not use this code.
        ;

        add     sp,10                   ;Clear the return data on the stack.
        iret                            ;Return to the faulting instruction.


EHTerminate:
        ;
        ; This code illustrates what we need to do if we wanted to
        ; terminate the applciation on this exception.  This exception
        ; handler does not use this code.
        ;

        add     sp,10                   ;Clear the return data on the stack.

        ;
        ; With TerminateApp you have the choice to display the standard
        ; UAE box or not.  This sample does since it otherwise would give
        ; no indication of the problem.
        ;
        cCall   TerminateApp, <0, UAE_BOX>

cEnd    nogen

sEnd    HANDLER_TEXT

        END
