User Tools

Site Tools


prop_lastchancehook.htm
Navigation:  Language Reference > App C - PROP: Runtime Properties > Complete Property List >====== PROP:LastChanceHook ====== Previous pageReturn to chapter overviewNext page

This is a SYSTEM read/write property (returning a LONG) that allows you to specify your own function that will be invoked if an exception has occurred. The hook function allows you to display information about the exception and choose one of the following actions:

·Continue execution of the thread where the exception occurred (unless the exception is fatal).

·Stop the thread (or the entire process if the exception occurred in the main process thread) without invoking the RTL's (runtime library) internal exception handler.

·Invoke the RTL's internal exception handler.

This allows you to catch an exception, and if it is non-fatal you can allow your end users to continue executing your program even when an exception has occurred in one of its threads.

The RTL handler shows information about the exception and asks for one of the following actions:

·Stop the thread where the exception occurred.

·Stop the entire process.

·Invoke the system debugger

·Generate a debug event if the program is already running under the debugger.

The action is dependent on the thread with the exception, whether the program is running under the debugger, etc.

PROP:LastChanceHook also allows the developer to set the exit code (error level) returned by the program to the OS on its termination, without the need to terminate the program immediately as is done when using the HALT statement.

Implementation:

Your function, which you assign to the SYSTEM{PROP:LastChanceHook} property must use the following prototype:

HookProc (*ICWExceptionInfo),LONG

The ICWExceptionInfo Parameter is an interface declared in CWEXCPT.INT, which is found in your LIBSRC folder.

The result returned by the hooked function is evaluated as follows:

·If the result is equal to 0, the RTL executes its own internal exception handler dialog to show information about the exception and subsequently perform the action chosen by the end user.

·If a positive number is returned, the RTL stops the thread (or the entire process if the exception occurred in the main process thread) without invoking the RTL exception handler

·If a negative number is returned, the program will try to continue from the point of the exception. Note, if the exception is fatal, this result is ignored and treated as equal to zero (0).

Example:

PROGRAM
  INCLUDE(’CWEXCPT.INT’),ONCE
  MAP
   Test (LONG,LONG)
   Hook (*ICWExceptionInfo),LONG
   HEX (LONG),STRING,PRIVATE
   MODULE(")
    MessageBox(UNSIGNED, CONST *CSTRING, CONST *CSTRING, UNSIGNED)|
                ,SIGNED,PROC,PASCAL,NAME(’MessageBoxA’)
   END
  END
MB_ICONHAND EQUATE(00000010h)
CODE
  SYSTEM{PROP:LastChanceHook} = ADDRESS(Hook)
  Test (10, 0)  !intentionally causes an exception
  RETURN

In this example the procedure named Hook is assigned as our exception handler. That's the only procedure we are concerned with, the others are just there to help to make the example work by 1) causing an exception and 2) informing the user about the exception.

Next we have:

Hook PROCEDURE(*ICWExceptionInfo info)
S        CSTRING(1024)
Caption  CSTRING(256)
   CODE
 IF info &= NULL
    RETURN 0
 END
 
 Caption = 'Exception ' & HEX (info.ExceptionCode()) & ' at ' & HEX (info.ExceptionAddress())
 S ='Registers' & |
    '<13,10>EAX= ' & HEX (info.Register (i386_Register:Reg32_EAX)) & |
    ' EBX= ' & HEX (info.Register (i386_Register:Reg32_EBX)) & |
    ' ECX= ' & HEX (info.Register (i386_Register:Reg32_ECX)) & |
    ' EDX= ' & HEX (info.Register (i386_Register:Reg32_EDX)) & |
    '<13,10>ESI= ' & HEX (info.Register (i386_Register:Reg32_ESI)) & |
    ' EDI= ' & HEX (info.Register (i386_Register:Reg32_EDI)) & |
    ' ESP= ' & HEX (info.Register (i386_Register:Reg32_ESP)) & |
    ' EBP= ' & HEX (info.Register (i386_Register:Reg32_EBP)) & |
    '<13,10,13,10>Current thread is being terminated '

  MessageBox(0, S, Caption, MB_ICONHAND)
  RETURN 1      !a positive value signals the RTL to kill the thread
 
! *****************************
Test PROCEDURE (LONG a, LONG b)
CODE
  a %= b

! *****************************
HEX PROCEDURE (LONG A)
i       UNSIGNED,AUTO
S       STRING(8),AUTO
DIGITS  STRING(’0123456789ABCDEF’),STATIC
 CODE
    i = SIZE(S)
    LOOP WHILE i <> 0
     S [i] = DIGITS [BAND (A, 0Fh) + 1]
     A = BSHIFT (A, -4)
     i -= 1
    END
    RETURN S

These first two lines of code assign our exception handler function and then call the Test procedure that raises an exception:

    SYSTEM{PROP:LastChanceHook} = ADDRESS (Hook)
    Test (10, 0) ! causes an exception

The exception is trapped and we show the result in an API MessageBox.

Our Hook PROCEDURE(*ICWExceptionInfo info) uses the methods in the interface to show the exception code, its address, and the values of the registers at the time of the exception.

In our example our Hook PROCEDURE executes a RETURN 1 and since we are running on the main thread, then immediately after the MessageBox is displayed and the user presses the OK button the program itself is terminated.

Conceptual Example:

PROGRAM
 INCLUDE('CWEXCPT.INT'),ONCE
 MAP
   MyHandler(*ICWExceptionInfo),LONG
   BadCode()
   MODULE('')
     SLEEP(LONG),PASCAL
   END
 END
badPtr      &LONG
temp        LONG
oldHandler  LONG
continue    BOOL(FALSE)
  CODE
   RESUME(START(BadCode))
   LOOP WHILE NOT continue
     SLEEP(100)
   END
   badPtr &= NULL
   badPtr = 0
   RETURN

BadCode     PROCEDURE()
   CODE
   oldHandler = SYSTEM{PROP:LastChanceHook}        !Read address of oldhandler
   SYSTEM{PROP:LastChanceHook} = ADDRESS(MyHandler)!Call new handler
   badPtr = 0
   RETURN
  
MyHandler   PROCEDURE(*ICWExceptionInfo info)
   CODE
   SYSTEM{PROP:LastChanceHook} = oldHandler
   MESSAGE('Someone did something naughty')
   continue = TRUE
   RETURN 1
prop_lastchancehook.htm.txt · Last modified: 2022/04/14 03:50 by carlbarnes