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