Listing 2 Using MFC's TRY/CATCH macros

// Vesely::MFC-TRY/CATCH : listing 2

// replacement for AfxThrow
void AFXAPI CppThrow(CException* pException, BOOL bShared);

class CExceptionMonitor
{
public:
   typedef void(*Callback)( BOOL bStartUnwinding);

private:
   static int m_nCount;
   static Callback m_pfCallback;

   BOOL m_bResumed;

   friend void AFXAPI CppThrow(CException* pException;
      BOOL bShared);      // calls here
   static void OnThrow(); // just before each throw

public:
   CExceptionMonitor() : m_bResumed( FALSE)

   {
      // there must be one auto object inside each handler's block,
      // as done in the macro redefinitions below
      ASSERT( m_nCount > 0);
}

   ~CExceptionMonitor();
   void Resume();
   static BOOL Unwinding() { ASSERT( m_nCount >= 0); return m_nCount; }
   static Callback HookOnThrow( Callback newCallback);
};

#if defined( _DEBUG)
class CDebugException : public CException
// only CATCH_ALL/END_CATCH_ALL get this:
// CATCH( CDebugException, e) => compile error in retail build
{
   DECLARE_DYNAMIC( CDebugException)
public:
   CDebugException();
};

// this intermittently throws the relevant exception
void ThrowPointTest( CRuntimeClass *pE, LPCSTR lpszFileName, int nline);

#define EXCEPTIONS_CAN_BE_THROWN(e) \
   ThrowPointTest( RUNTIME_CLASS( e), THIS_FILE, __LINE__)
#else
#define EXCEPTIONS_CAN_BE_THROWN(e) ((void)0)
#endif // _DEBUG

#under TRY
#define TRY { AFX_EXCEPTION_LINK _afxExceptionLink; \
   try { EXCEPTIONS_CAN_BE_THROWN( CDebugException); {

#undef CATCH
// CATCH can only be the first handler in the list:
// in the (rare) case of a handler list with more than one
// meaningful selective handler, EXCEPTIONS_CAN_BE_THROWN
// needs to be coded explicitely.
#define CATCH(class, e) EXCEPTIONS_CAN_BE_THROWN( class); } \
       } catch (class* e) \
       { ASSERT( e->IsKindOf(RUNTIME_CLASS(class))); \
         ASSERT( _afxExceptionLink.m_pException == e); \
         CExceptionMonitor ExceptionMonitor;

#undef AND_CATCH
#define AND_CATCH(class, e) } catch (class* e) \
       { ASSERT(e->IsKindOf(RUNTIME_CLASS(class))); \
         ASSERT( _afxExceptionLink.m_PException == e); \
         CExceptionMonitor ExceptionMonitor;

#undef END_CATCH
#define END_CATCH } catch (CException* e) \
       { ASSERT(e->IsKindOf(RUNTIME_CLASS(CException))); \
         ASSERT( _afxExceptionLink.m_pException == e); \
         CExceptionMonitor ExceptionMonitor; \
         CppThrow( 0, FALSE); } }

#undef THROW
#define THROW(e) CppThrow( e, FALSE)

#undef THROW_LAST
#define THROW_LAST() CppThrow( 0, FALSE)
// end of listing 2
// End of File