[Windows XP+] Try .. Catch .. EndTry - Error Handling
Posted: Tue May 08, 2012 8:43 pm
Simple Macros for catching program exceptions and continue the program.
Requires Windows XP or newer, 32bit and 64bit PureBasic.
The variable "CurrentExceptionInfo" contains the exception informations.
Requires Windows XP or newer, 32bit and 64bit PureBasic.
Code: Select all
;---[ Try Catch EndTry ]----------------------------------------------------
;
; Structured Exception Handling for WinXP+, PureBasic/Windows 32bit + 64bit
;
; by Danilo, May 2012
;
Import "kernel32.lib"
AddVectoredExceptionHandler(FirstHandler.l, *VectoredHandler)
RemoveVectoredExceptionHandler(*Handler)
EndImport
Structure ExceptionHandlerStack
catchAddress.i
oldHandler.i
StackPointer.i
EndStructure
Threaded NewList ExceptionHandlerList.ExceptionHandlerStack()
Threaded CurrentExceptionInfo.EXCEPTION_POINTERS
Procedure.l UnhandledExceptionFilter(*ExceptionInfo.EXCEPTION_POINTERS)
CopyStructure(*ExceptionInfo,@CurrentExceptionInfo,EXCEPTION_POINTERS)
CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
*ExceptionInfo\ContextRecord\Eip = ExceptionHandlerList()\catchAddress
*ExceptionInfo\ContextRecord\Esp = ExceptionHandlerList()\StackPointer
CompilerElse
*ExceptionInfo\ContextRecord\Rip = ExceptionHandlerList()\catchAddress
*ExceptionInfo\ContextRecord\Rsp = ExceptionHandlerList()\StackPointer
CompilerEndIf
;SetUnhandledExceptionFilter_( ExceptionHandlerList()\oldHandler )
RemoveVectoredExceptionHandler( ExceptionHandlerList()\oldHandler )
DeleteElement( ExceptionHandlerList() )
ProcedureReturn $ffffffff
EndProcedure
Procedure AddExceptionHandler(*catch,StackPointer.i)
If AddElement( ExceptionHandlerList() )
;ExceptionHandlerList()\oldHandler = SetUnhandledExceptionFilter_(@UnhandledExceptionFilter()) ; Win2000pro+ 32bit
ExceptionHandlerList()\oldHandler = AddVectoredExceptionHandler(1,@UnhandledExceptionFilter()) ; XP+
ExceptionHandlerList()\catchAddress = *catch
ExceptionHandlerList()\StackPointer = StackPointer
EndIf
EndProcedure
Global AddExceptionHandler.i = @AddExceptionHandler()
! macro __try {
! local label1, label2, label3
! handler_label equ label1
! handler_end_label equ label2
! end_try_label equ label3
! }
Macro Try
CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
!__try
! push esp
! push handler_label
! call [v_AddExceptionHandler]
CompilerElse
!__try
! mov qword rdx, rsp
! mov qword rcx, handler_label
! call qword [v_AddExceptionHandler]
CompilerEndIf
EndMacro
Macro Catch
!jmp end_try_label
!handler_label:
EndMacro
Macro EndTry
!end_try_label:
! restore handler_label
! restore end_try_label
! restore handler_end_label
EndMacro
;---------------------------------------------------------------------------
CompilerIf #PB_Compiler_Debugger
;CompilerError "please disable debugger"
DisableDebugger
CompilerEndIf
Procedure a()
Try
Try
a = 0
b = 4/a ; 4/0 = division by zero exception
Catch
MessageRequester("INFO","Catched inner exception")
EndTry
PokeI(0,1234) ; Poke something to address 0
Catch
MessageRequester("INFO","Catched outer exception")
EndTry
EndProcedure
Procedure b()
!push 1234 ; change stack = crash
EndProcedure
a()
Try
b()
Catch
MessageRequester("INFO","Catched stack corruption")
EndTry
MessageRequester("INFO","OK, still alive ;)")