The code fragment below shows how to set a handler while the calling thread is executing driver code. In the event of an exception, OS/2 calls the handler function, which jumps back to the point of setjmp().

#define INCL_DOS
#include <os2.h>
#include <setjmp.h>

// this exception registration record extends the OS/2-defined one in BSEXCPT.H
// by adding a C jmp_buf at the end
struct _regrec {
  PULONG    pNext;
  PFN       pfnHandler;
  jmp_buf   jmp;
}
typedef struct _regrec REGREC, *PREGREC;

// -------------------------------------------------------------------------
// an exception handler function that jumps back to setjmp()

ULONG _System DriverHandler( PEXCEPTIONREPORTRECORD p1,
                                 PREGREC p2,
                                 PCONTEXTRECORD p3,
                                 PVOID pv )
{
  // handle interesting exceptions
  switch( p1->ExceptionNum ) {
  case XCPT_ACCESS_VIOLATION:
  case XCPT_INTEGER_DIVIDE_BY_ZERO:
  case XCPT_INTEGER_OVERFLOW:
  case XCPT_PROCESS_TERMINATE:
  case XCPT_ASYNC_PROCESS_TERMINATE:
    // setjmp() will return p1->ExceptionNum
    longjmp(p2)->jmp, p1->ExceptionNum );
  }
  // not interested; system should continue search
  return XCPT_CONTINUE_SEARCH;
}

// -------------------------------------------------------------------------
// example of an exported driver function; return TRUE upon success
LONG _System ExportedDriverFunction( PVOID p )
{
  REGREC        regrec;
  ULONG         ulException;
  LONG          lResult;

  regrec.pfnHandler = (PFN)DriverHandler;
  DosSetExceptionHandler( (PEXCEPTIONREGISTRATIONRECORD)&regrec );

  // get thread state; normally rets 0, rets non-zero after longjmp()
  ulException = setjmp( regrec.jmp );

  if( ulException ) {
    // an exception occurred
    // clean up here: release memory, semaphores
    // must check for exiting thread case
    switch( ulException ) {
    case XCPT_PROCESS_TERMINATE:
    case XCPT_ASYNC_PROCESS_TERMINATE:
      // thread is ending or being terminated
      DosUnsetExceptionHandler( (PEXCEPTIONREGISTRATIONRECORD)&regrec );
      DosExit( EXIT_THREAD, 0 );
    }
    WinSetErrorInfo( ... );
    lResult = FALSE;
    goto depart;
  }

  // do the work of the exported function here

  lResult = TRUE;

depart:
  DosUnsetExceptionHandler( (PEXCEPTIONREGISTRATIONRECORD)&regrec );
  return lResult;
}


[Back: The Exception Handler]
[Next: Using Macro Assembler Instructions]