PureBasic Forum
https://www.purebasic.fr/english/

[Windows XP+] Try .. Catch .. EndTry - Error Handling
https://www.purebasic.fr/english/viewtopic.php?f=12&t=49903
Page 1 of 2

Author:  Danilo [ Tue May 08, 2012 8:43 pm ]
Post subject:  [Windows XP+] Try .. Catch .. EndTry - Error Handling

Simple Macros for catching program exceptions and continue the program.

Requires Windows XP or newer, 32bit and 64bit PureBasic.

Code:
;---[ 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 ;)")

The variable "CurrentExceptionInfo" contains the exception informations.

Author:  dige [ Wed May 09, 2012 9:34 am ]
Post subject:  Re: [Windows XP+] Try .. Catch .. EndTry - Error Handling

Thank you Danilo. It it the same mechanism like the POSL TryCatch Lib?

Author:  Danilo [ Wed May 09, 2012 9:41 am ]
Post subject:  Re: [Windows XP+] Try .. Catch .. EndTry - Error Handling

dige wrote:
Thank you Danilo. It it the same mechanism like the POSL TryCatch Lib?

I don't know. Wasn't aware there was already a Try..Catch somewhere.

Author:  Little John [ Wed May 09, 2012 3:23 pm ]
Post subject:  Re: [Windows XP+] Try .. Catch .. EndTry - Error Handling

Great! Thank you, Danilo.

Regards, Little John

Author:  skywalk [ Wed May 09, 2012 3:54 pm ]
Post subject:  Re: [Windows XP+] Try .. Catch .. EndTry - Error Handling

Very cool Danilo, can't wait to "Try" this. :wink:

Author:  Kiffi [ Wed May 09, 2012 4:14 pm ]
Post subject:  Re: [Windows XP+] Try .. Catch .. EndTry - Error Handling

Thanks Danilo!

Works under 32 Bit. But under 64 Bit:

Image

Did i missed something?

Greetings ... Kiffi

Author:  ts-soft [ Wed May 09, 2012 4:52 pm ]
Post subject:  Re: [Windows XP+] Try .. Catch .. EndTry - Error Handling

Kiffi wrote:
Did i missed something?

Greetings ... Kiffi

I think, you have enabled the Debugger :wink:

Author:  Danilo [ Wed May 09, 2012 5:35 pm ]
Post subject:  Re: [Windows XP+] Try .. Catch .. EndTry - Error Handling

Kiffi wrote:
Thanks Danilo!

Works under 32 Bit. But under 64 Bit:

Image

Did i missed something?

Greetings ... Kiffi

I wondered about this too. I made a small mistake: First argument of AddVectoredExceptionHandler()
has to be nonzero to become the first handler. I changed it in the code above, thanks.

Author:  Kiffi [ Wed May 09, 2012 7:16 pm ]
Post subject:  Re: [Windows XP+] Try .. Catch .. EndTry - Error Handling

@Danilo: Works perfect! Thanks a lot! Image

Greetings ... Kiffi

Author:  RichAlgeni [ Fri May 11, 2012 3:28 am ]
Post subject:  Re: [Windows XP+] Try .. Catch .. EndTry - Error Handling

Would this replace OnErrorCall()?

Coming from a background that had no Try-Catch, could you give me a quick heads up to someone would utilize this? Would it be useful in using functions over a network, where it's possible for the network connection to be dropped, and this procedure might gracefully handle that situation?

Thanks!

Author:  dige [ Sat May 12, 2012 1:45 pm ]
Post subject:  Re: [Windows XP+] Try .. Catch .. EndTry - Error Handling

@Danilo: Duno why, but using try / catch for CatchImage and LoadImage, makes the program unstable...
I use the OnError Lib too. May be there are now some side effects?

Author:  TeraByte [ Fri May 25, 2012 8:56 pm ]
Post subject:  Re: [Windows XP+] Try .. Catch .. EndTry - Error Handling

Thank you Danilo for your excellent code! :D

Author:  Little John [ Fri May 25, 2012 9:11 pm ]
Post subject:  Re: [Windows XP+] Try .. Catch .. EndTry - Error Handling

Danilo wrote:
Simple Macros for catching program exceptions and continue the program.

Requires Windows XP or newer

Danilo, what happens if I use this code in a compiled EXE program, and someone runs that program on Windows 2000? OK, your code will probably not catch exceptions then ... but can it cause any problems on Windows 2000?

Regards, LIttle John

Author:  ts-soft [ Fri May 25, 2012 9:32 pm ]
Post subject:  Re: [Windows XP+] Try .. Catch .. EndTry - Error Handling

@Little John
If imported functions not available, so your exe will not start!

I think, dynamic load of functions should help.

Author:  Danilo [ Sat May 26, 2012 6:27 am ]
Post subject:  Re: [Windows XP+] Try .. Catch .. EndTry - Error Handling

Little John wrote:
Danilo, what happens if I use this code in a compiled EXE program, and someone runs that program on Windows 2000? OK, your code will probably not catch exceptions then ... but can it cause any problems on Windows 2000?

Regards, LIttle John

As ts-soft said, the exe will not start because the functions imports are not found in kernel32.lib

If you change the 2 out-commented lines, it should work with Win95+, but only with 32bit PureBasic.
First 64bit Windows was WindowsXP, right?

So for 32bit only and Win95+ use this version:
Code:
;---[ Try Catch EndTry ]----------------------------------------------------
;
; Structured Exception Handling for Win95+, PureBasic/Windows 32bit only
;
; by Danilo, May 2012
;
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
        CompilerError "This version of Try/Catch does not support 64bit PureBasic"
    CompilerEndIf

    SetUnhandledExceptionFilter_( ExceptionHandlerList()\oldHandler )

    DeleteElement( ExceptionHandlerList() )
    ProcedureReturn $ffffffff

EndProcedure

Procedure AddExceptionHandler(*catch,StackPointer.i)
    If AddElement( ExceptionHandlerList() )
        ExceptionHandlerList()\oldHandler   = SetUnhandledExceptionFilter_(@UnhandledExceptionFilter()) ; Win95+ 32bit
        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 ;)")


dige wrote:
I use the OnError Lib too. May be there are now some side effects?

Yes, I think the OnError Lib uses the same functions internally.

Page 1 of 2 All times are UTC + 1 hour
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/