include '%lib%/freshlib.inc'

@BinaryType GUI

include '%lib%/freshlib.asm'

start:
        InitializeAll

; First level of exception handling
beginTry

  ; Second level of exception handling
  beginTry

        xor     esi, esi
        mov     eax, [esi]        ; exception
        invoke  MessageBoxA, NULL, eax, NULL, MB_ICONINFORMATION or MB_OK

    onException

        ; Get the exception number
        mov     eax, [ptrExceptionRecord]
        mov     eax, [eax+EXCEPTION_RECORD.ExceptionCode]

        ; This is simply creating of the message for message box.
        ; Strictly preserve esi, edi, ebx and ebp registers
        push    ebx
        stdcall NumToStr, eax, ntsUnsigned or ntsHex
        mov     ebx, eax
        stdcall StrInsert, ebx, msgException, 0
        stdcall StrCat, ebx, msgSecond
        stdcall StrPtr, ebx
        invoke  MessageBoxA, NULL, eax, NULL, MB_ICONINFORMATION or MB_YESNO
        stdcall StrDel, ebx
        pop     ebx

        ; How to proceed? Yes means the exception will be passed to the
        ; previous exception handler - i.e. the first one.
        cmp     eax, IDYES
        jne     @f

    Next

@@:

    Ignore

  endTry

  invoke  MessageBoxA, NULL, msgAfterSecond, NULL, MB_ICONINFORMATION or MB_OK

onException

        invoke  MessageBoxA, NULL, msgFirst, NULL, MB_ICONINFORMATION or MB_YESNO
        cmp     eax, IDYES
        je      .patchesi

        Ignore

        ; Change esi register to have valid value after retry.
  .patchesi:
        mov     eax, [ptrExceptionContext]
        mov     [eax+CONTEXT.regEsi], ptrRecovered
        Retry

endTry

        FinalizeAll
        invoke  MessageBoxA, NULL, msgBeforeEnd, NULL, MB_ICONINFORMATION or MB_OK
        invoke  ExitProcess, 0

msgBeforeEnd db 'Just before termination.', 0
msgRecovered db 'Recovered. ESI have proper value now.', 0
msgSecond    db ' Second level exception handler. Do you want to pass exception to the first level handler?', 0
msgFirst     db 'First level exception handler. Do you want to fix the value of the esi register?', 0
msgAfterSecond db 'Code, after second level exception handler.', 0
msgException db 'Exception No. $', 0
ptrRecovered dd msgRecovered

