summaryrefslogtreecommitdiffstats
path: root/public/sdk/inc/except.hxx
diff options
context:
space:
mode:
Diffstat (limited to 'public/sdk/inc/except.hxx')
-rw-r--r--public/sdk/inc/except.hxx1134
1 files changed, 1134 insertions, 0 deletions
diff --git a/public/sdk/inc/except.hxx b/public/sdk/inc/except.hxx
new file mode 100644
index 000000000..80afa1c46
--- /dev/null
+++ b/public/sdk/inc/except.hxx
@@ -0,0 +1,1134 @@
+//+---------------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1991 - 1992.
+//
+// File: Except.hxx
+//
+// Contents: Macro package for C++ exception support
+//
+// Classes: CException -- The base for all exception classes
+// CExceptionContext -- Per-thread exception context.
+// CUnwindable -- Classes with destructors inherit
+// from this.
+// CTry -- Per/TRY state.
+//
+// Functions: Macros to implement TRY ... CATCH
+// Macros to implement unwind for classes with destructors
+//
+// History: 22-May-91 KyleP Created Interface.
+// 15-Aug-91 SethuR modified THROW,CATCH,AND_CATCH,
+// END_CATCH macros
+// 18-Oct-91 KyleP Win32 try/except implementation
+// 20-Feb-92 KyleP Fixed destruction of classes with
+// virtual methods.
+// 03-Aug-92 KyleP Kernel implementation
+// 13-Nov-92 KyleP Bugfix destruction of heap classes.
+// Added assertion checking.
+// 27-May-93 Mackm Added definitions for un-exceptional
+// operator new.
+// 01-Jun-93 RobBear Added definitions for alloc hooking
+// 30-Sep-93 KyleP DEVL obsolete
+// 14-Dec-93 AlexT Add NOEXCEPTIONS support
+//
+//----------------------------------------------------------------------------
+
+#pragma warning(4:4509) // SEH used in function w/ _trycontext
+
+#ifndef __EXCEPT_HXX_
+#define __EXCEPT_HXX_
+
+#ifdef DISPLAY_INCLUDES
+#pragma message( "#include <" __FILE__ ">..." )
+#endif
+
+#if defined( KERNEL )
+# include <ntstatus.h>
+# include <stddef.h>
+#else // !KERNEL
+# include <memory.h>
+# include <stdlib.h>
+# include <string.h>
+# include <stdio.h>
+#endif
+
+#include <debnot.h>
+
+const int maxExceptionSize = 256;
+#define DEB_BUDDY 0x10000
+#define DEB_UNWIND 0x20000
+
+//
+// If EXCEPT_TEST is defined, then the exception code can be compiled
+// without use the the 'Win4 environment'. This is only to facilitate
+// testing. When EXCEPT_TEST is defined debug messages are printed
+// to stdout instead of the debug terminal.
+//
+
+//
+// REAL CODE -- REAL CODE -- REAL CODE -- REAL CODE
+//
+
+#ifndef EXCEPT_TEST
+//# if !defined( KERNEL )
+//# include <win4p.h>
+//# endif // !KERNEL
+# if (DBG == 1 || OFSDBG == 1)
+
+//
+// VERY UNUSUAL SITUATION:
+// Out xxxDebugOut macros are designed to be inline. This causes
+// a problem in exceptions because the _xxxInfoLevel flag which
+// determines if a message should be printed is not declared in
+// every DLL. So. Instead of calling the macro:
+//
+// DECLARE_DEBUG(ex)
+//
+// I will:
+
+void exInlineDebugOut2(unsigned long fDebugMask, char const *pszfmt, ...);
+
+// and then export this function from OSM.DLL (or whatever DLL
+// exports exception handling.
+//
+
+# define exDebugOut( x ) exInlineDebugOut2 x
+# define exAssert( x ) Win4Assert( x )
+# else // DBG == 0 && OFSDBG == 0
+# define exDebugOut( x )
+# define exAssert( x )
+# endif
+
+//
+// TEST ONLY -- TEST ONLY -- TEST ONLY -- TEST ONLY
+//
+
+#else // EXCEPT_TEST
+ typedef unsigned long ULONG;
+ typedef unsigned char BYTE;
+# define TRUE 1
+# include <assert.h>
+# define exAssert( x ) assert( (x) )
+
+# include <stdarg.h>
+inline void exInlineDebugOut( ULONG,
+ char * msg,
+ ... )
+{
+ va_list arglist;
+
+ va_start(arglist, msg);
+ vfprintf(stderr, msg, arglist);
+}
+
+# define exDebugOut( x ) exInlineDebugOut x
+
+
+# define _PopUpError( p1, p2, p3 ) 0xFFFFFFFF
+# define Win4ExceptionLevel 0xFFFFFFFF
+# define EXCEPT_MESSAGE 0x1
+# define EXCEPT_POPUP 0x0
+# define EXCEPT_BREAK 0x0
+# define DEB_FORCE 0x0
+# define DEB_WARN 0x0
+# define DEB_ERROR 0x0
+# define DEB_ITRACE 0x0
+
+#endif // EXCEPT_TEST
+
+//
+// END TEST -- END TEST -- END TEST -- END TEST
+//
+
+#if defined( WIN32 )
+# if !defined( KERNEL )
+# include <windows.h>
+# endif // !KERNEL
+#else // !WIN32
+# include <setjmp.h>
+#endif // WIN32
+
+class CTry;
+
+typedef void(*PFV)();
+
+extern void terminate();
+extern void unexpected();
+
+extern PFV set_terminate(PFV terminate_fn);
+extern PFV set_unexpected(PFV unexpected_fn);
+
+#if DBG==1 || OFSDBG == 1
+typedef BOOL (* ALLOC_HOOK)(size_t nSize);
+EXPORTDEF ALLOC_HOOK MemSetAllocHook( ALLOC_HOOK pfnAllocHook );
+
+extern EXPORTDEF void WINAPI
+ExceptionReport(
+ unsigned int iLine,
+ char *szFile,
+ char *szMsg);
+#endif // DBG == 1 || OFSDBG == 1
+
+//+---------------------------------------------------------------------------
+//
+// Class: CException
+//
+// Purpose: All exception objects (e.g. objects that are THROW)
+// inherit from CException.
+//
+// Interface: ~CException - Destructor
+// IsKindOf - Class membership query
+//
+// History: 22-May-91 KyleP Created.
+//
+// Notes: This class is a hack, until C7 can provide some support
+// for runtime inheritance detection (e.g. a way to generate
+// a mangled name). When we get this support a new
+// implementation of IsKindOf should be developed. The concept,
+// however, would remain the same: C++ exception objects are
+// instances of an exception class, but they are caught by class.
+//
+// A compiler can implement IsKindOf by throwing a
+// decorated name which uniquely identifies a class and
+// describes its inheritance.
+//
+// Don't do anything too fancy with subclasses of CException.
+// Instances of your subclass are memcpy-ed around. Having
+// a user defined destructor, for example, is probably a bad
+// idea.
+//
+//----------------------------------------------------------------------------
+
+class CException
+{
+public:
+
+ EXPORTDEF CException(long lError);
+ long GetErrorCode() { return _lError;}
+ EXPORTDEF virtual int WINAPI IsKindOf(const char * szClass) const;
+
+protected:
+
+ long _lError;
+};
+
+//+---------------------------------------------------------------------------
+//
+// Class: CExceptionContext
+//
+// Purpose: Per-thread exception state and throw exception methods.
+//
+// Interface: CExceptionContext -- Constructor
+// ~CExceptionContext -- Destructor
+// Push -- Push a new element on the stack of
+// elements-to-be-destroyed.
+// Pop -- Pop an an element off the stack.
+// SetTop -- Set the top of stack to the specified
+// element.
+// GetTop -- Return the top element.
+// Throw -- Throw an exception
+//
+// History: 19-Nov-91 KyleP Fix heap unwind, multiple inheritance
+// 22-May-91 KyleP Created.
+//
+// Notes: There is only 1 CExceptionContext object per thread.
+//
+//----------------------------------------------------------------------------
+
+class CExceptionContext
+{
+public:
+
+ CExceptionContext();
+
+ ~CExceptionContext();
+
+ EXPORTDEF void WINAPI Reserve(void * pthis);
+
+ inline void Pop(void * pthis);
+
+ EXPORTDEF void WINAPI SetTop(void * pthis,
+ ULONG cbElement,
+ void (* pfn)(void *));
+
+ inline int GetTop();
+
+#ifndef WIN32
+
+ void Throw();
+
+#endif /* WIN32 */
+
+ void Unwind( CTry * ptry );
+
+ //
+ // _pTopTry contains the head of a linked list of CTry objects,
+ // each of which corresponds to a TRY clause.
+ //
+
+ CTry * _pTopTry;
+
+ //
+ // _pLastNew records the address of the most recent free
+ // store allocation, _cbLastNew the size.
+ //
+
+ BYTE * _pLastNew;
+ int _cbLastNew;
+ int _fNewReadyForUnwind;
+
+ //
+ // _exception contains a pointer to the current exception,
+ // if any. The character buffer following it is for storing
+ // additional data belonging to subclasses.
+ //
+
+ CException _exception;
+ char buffer[maxExceptionSize];
+
+private:
+
+ //
+ // Each StackElement contains enough information to destroy a
+ // completly constructed object, and the determine whether
+ // objects which have not yet been fully constructed were
+ // allocated on the heap or the stack.
+ //
+
+ class StackElement
+ {
+ public:
+
+ BOOL IsThisEqual( void * pthis ) { return( pthis == _pthis ); }
+ BOOL IsSizeEqual( ULONG cb ) { return( cb == _cbElement ); }
+ BOOL IsOnStack() { return( _cbElement == 0 ); }
+ BOOL IsOnHeap() { return( _cbElement != 0 ); }
+ BOOL IsActive() { return( _pfn != 0 ); }
+
+ void SetOnStack() { _cbElement = 0; }
+ void SetOnHeap( ULONG size ) { _cbElement = size; }
+ void SetThis( void * pthis ) { _pthis = pthis; }
+ void SetDtor( void (* pfn)(void *) ) { _pfn = pfn; }
+
+ void * GetDtor() { return( _pfn ); }
+ void * GetThis() { return( _pthis ); }
+
+ void Destroy() { _pfn( (BYTE *)_pthis ); }
+ void Delete() { delete (BYTE *)_pthis; }
+
+ private:
+
+ void * _pthis; // This for CUnwindable
+ void (* _pfn)(void *); // 'Static destructor'
+ ULONG _cbElement; // 0 == On stack. > 0 = Size of class
+ };
+
+ //
+ // _aStack is the stack of objects-to-be-destroyed in the face
+ // of an exception (stack unwind).
+ //
+
+ StackElement * _aStack;
+
+ //
+ // _StackTop is the index of the first free element on the stack.
+ //
+
+ int _StackTop;
+
+ //
+ // _StackSize is the maximum number of elements which can be
+ // stored on the stack.
+ //
+
+ int _StackSize;
+
+
+ EXPORTDEF void APINOT _Grow();
+
+};
+
+//+---------------------------------------------------------------------------
+//
+// Member: CExceptionContext::Pop, public
+//
+// Synopsis: Pops the top element off the stack of objects to be destroyed.
+//
+// Effects: Pop only has an effect if the top element on the stack
+// is for [pthis].
+//
+// Arguments: [pthis] -- Must correspond to the top of stack if the
+// element is to be popped.
+//
+// History: 22-May-91 KyleP Created.
+//
+//----------------------------------------------------------------------------
+
+inline void CExceptionContext::Pop(void * pthis)
+{
+ //
+ // Remove the top of stack only if it corresponds to pthis.
+ // Thus the element will be removed only if this object was
+ // declared on the stack (as opposed to embedded) and no
+ // exception was encountered.
+ //
+
+ //
+ // You should *always* find what you're looking for. No checking
+ // for runoff. The very bottom element of the stack is a sentinel
+ // for the case of heap objects which have been fully removed from
+ // the stack.
+ //
+
+ exAssert( _StackTop > 0 );
+
+ if ( _aStack[_StackTop-1].IsThisEqual( pthis ) )
+ {
+ //
+ // The following assertion is hit if an unwindable object
+ // is destroyed without END_CONSTRUCTION being called.
+ //
+
+ exAssert( _aStack[_StackTop-1].IsActive() );
+
+ _StackTop--;
+
+#if DBG == 1 || OFSDBG == 1
+ exDebugOut(( DEB_ITRACE, "POP %lx %lx( %lx )\n",
+ _StackTop,
+ _aStack[_StackTop].GetDtor(),
+ _aStack[_StackTop].GetThis() ));
+#endif // DBG || OFSDBG == 1
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CExceptionContext::GetTop, public
+//
+// Returns: The index of the top of the stack of objects to be
+// destroyed. This is the first available element.
+//
+// History: 22-May-91 KyleP Created.
+//
+//----------------------------------------------------------------------------
+
+inline int CExceptionContext::GetTop()
+{
+ return(_StackTop);
+}
+
+EXPORTDEF CExceptionContext& APINOT _ExceptionContext(void);
+
+//----------------------------------------------------------------------------
+//
+// Various operator new implementations
+//
+//----------------------------------------------------------------------------
+
+EXPORTDEF int APINOT LeakCheck ( ULONG* pCount );
+
+#if defined( KERNEL )
+
+//
+// Prototype for extra operator new used in kernel to specify
+// resident vs. swappable heap.
+//
+
+void InitExceptionSystem();
+void* _CRTAPI1 operator new ( size_t size, POOL_TYPE pool );
+
+#if OFSDBG == 1
+# define NEW_POOL( pool, pCounter ) new(pool, pCounter)
+ void* _CRTAPI1 operator new ( size_t size, POOL_TYPE pool, ULONG* pCounter );
+#else
+# define NEW_POOL( pool, pCounter ) new(pool)
+#endif
+
+#endif // KERNEL
+
+//
+// Allocation with trace context
+//
+
+#if OFSDBG == 1 || DBG == 1
+# define NEW( pCounter ) new ( pCounter )
+ void* _CRTAPI1 operator new ( size_t size, ULONG* pCounter );
+#else
+# define NEW( pCounter ) new
+#endif
+
+//
+// Prototype for extra operator new used in routines which do not
+// have an exception handler set up and prefer a null return on
+// failed allocations rather than an exception.
+//
+
+typedef enum _FAIL_BEHAVIOR
+{
+ NullOnFail, // BUGBUG: should be deleted ASAP
+ ExceptOnFail
+} FAIL_BEHAVIOR ;
+
+void* _CRTAPI1 operator new ( size_t size, FAIL_BEHAVIOR FailBehavior );
+
+#define newx new(ExceptOnFail)
+
+//+---------------------------------------------------------------------------
+//
+// Class: CSystemException
+//
+// Purpose: Base class for system (hardware) exceptions which are
+// not handled by a specific exception class
+//
+// Interface:
+//
+// History: 18-Oct-91 KyleP Created.
+//
+//----------------------------------------------------------------------------
+
+class CSystemException : public CException
+{
+public:
+
+ EXPORTDEF CSystemException(ULONG ulExcept);
+
+ virtual int WINAPI IsKindOf(const char * szClass) const;
+
+ ULONG GetSysErrorCode() { return( _ulExcept ); }
+
+private:
+
+ ULONG _ulExcept;
+
+};
+
+//+---------------------------------------------------------------------------
+//
+// Class: CUnwindable, CVirtualUnwindable
+//
+// Purpose: Per-object exception state and registration/unwind methods.
+//
+// Interface: CUnwindable -- Constructor
+// ~CUnwindable -- Destructor
+// _Activate -- Activate object.
+//
+// History: 22-May-91 KyleP Created.
+// 13-Nov-92 KyleP Added virtual version
+//
+// Notes: CVirtualUnwindable should be used if and only if a
+// derived class has some other virtual method.
+//
+//----------------------------------------------------------------------------
+
+class CUnwindable
+{
+public:
+
+ inline CUnwindable();
+
+ inline ~CUnwindable();
+
+ inline void _Activate( ULONG cbElement,
+ void (* pfn)(void *) );
+};
+
+class CVirtualUnwindable
+{
+public:
+
+ inline CVirtualUnwindable();
+
+ virtual ~CVirtualUnwindable();
+
+ inline void _Activate( ULONG cbElement,
+ void (* pfn)(void *) );
+};
+
+//+---------------------------------------------------------------------------
+//
+// Member: CUnwindable::CUnwindable, public
+//
+// Synopsis: Initializes the link field of the object.
+//
+// Effects: Essentially sets up enough state to remember the position
+// of the object which inherits from CUnwindable
+// within the stack of objects-to-be-destroyed.
+//
+// History: 22-May-91 KyleP Created.
+//
+// Notes: This call does not fully link the object into the chain
+// of objects to be destroyed. See _Activate.
+//
+//----------------------------------------------------------------------------
+
+inline CUnwindable::CUnwindable()
+{
+ //
+ // Initialize by allocating a record on the deletion stack.
+ //
+
+ _ExceptionContext().Reserve(this);
+}
+
+inline CVirtualUnwindable::CVirtualUnwindable()
+{
+ //
+ // Initialize by allocating a record on the deletion stack.
+ //
+
+ _ExceptionContext().Reserve(this);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CUnwindable::~CUnwindable, public
+//
+// Synopsis: Removes this object from the stack of objects to be destroyed.
+//
+// Modifies: Per/thread exception context.
+//
+// History: 22-May-91 KyleP Created.
+//
+//----------------------------------------------------------------------------
+
+inline CUnwindable::~CUnwindable()
+{
+ _ExceptionContext().Pop(this);
+}
+
+inline CVirtualUnwindable::~CVirtualUnwindable()
+{
+ _ExceptionContext().Pop(this);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CUnwindable::_Activate, public
+//
+// Synopsis: Fully link object into stack of objects to be destroyed.
+//
+// Effects: After this call, the object which inherits from
+// CUnwindable will be destroyed during unwind.
+//
+// If the object was declared on the heap, then it is
+// removed completely from the stack of objects that will
+// be destroyed during unwind.
+//
+// Arguments: [prealthis] -- This pointer of instance. Will differ
+// from this pointer of CUnwindable
+// if instance has a virtual method.
+// [cbElement] -- Size of the instance being activated. If
+// an element is declared on the heap and
+// [cbElement] is smaller than the allocation
+// then the element won't be deleted.
+//
+// [pfn] -- Pointer to a static destructor. [pfn] takes a
+// this pointer.
+//
+// Modifies: This object is now the top of the stack of objects that
+// will be destroyed (_exceptioncontext is modified).
+//
+// History: 22-May-91 KyleP Created.
+//
+//----------------------------------------------------------------------------
+
+inline void CUnwindable::_Activate(
+ ULONG cbElement,
+ void (* pfn)(void *))
+{
+ _ExceptionContext().SetTop(this, cbElement, pfn);
+}
+
+inline void CVirtualUnwindable::_Activate(
+ ULONG cbElement,
+ void (* pfn)(void *))
+{
+ _ExceptionContext().SetTop(this, cbElement, pfn);
+}
+
+//+---------------------------------------------------------------------------
+//
+// Class: CTry
+//
+// Purpose: Containt per/TRY state.
+//
+// Interface: ~CTry - Destructor
+// TryIt - Setup to run the TRY body.
+//
+// History: 22-May-91 KyleP Created.
+//
+//----------------------------------------------------------------------------
+
+class CTry
+{
+public:
+
+ inline CTry();
+ inline ~CTry();
+
+ //
+ // The following function ***MUST*** be declared inline and
+ // actually be ***IMPLEMENTED*** inline. It calls setjmp;
+ // and if TryIt is a real procedure then we just set the
+ // return for longjmp on a piece of stack that is reclaimed!
+ //
+
+ //inline int TryIt();
+
+#ifndef WIN32
+
+ //
+ // _jb is the setjmp buffer indicating the location that will
+ // be longjmp'ed to when an exception occurs.
+ //
+
+ jmp_buf _jb;
+
+#endif /* WIN32 */
+
+ //
+ // _pPrevTry is a link to the enclosing TRY clause.
+ //
+
+ CTry * _pPrevTry;
+
+ //
+ // _StackTop was the top of the stack of objects-to-be-destroyed
+ // when the TRY clause was entered.
+ //
+
+ int _StackTop;
+};
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTry::~CTry, public
+//
+// Synopsis: Unlinks the TRY ... CATCH from the per/thread list.
+//
+// Modifies: The per/thread list of try clauses in _exceptioncontext.
+//
+// History: 22-May-91 KyleP Created.
+//
+//----------------------------------------------------------------------------
+
+inline CTry::~CTry()
+{
+ exDebugOut(( DEB_ITRACE, "END TRY %lx (%lx)\n", _StackTop, this ));
+
+ //
+ // The destructor for CTry is called only during normal (no
+ // exception) exit from the TRY ... CATCH or when an
+ // exception was successfully caught in this block.
+ // In these cases we want to unlink this CTry.
+ //
+ // Note that we could delete _exceptioncontext._TheException
+ // here, which may be non-null if we caught an exception in
+ // this TRY ... CATCH block. But why bother? That would add
+ // additional code to the normal case. The last exception
+ // can wait to be deleted until the next occurs.
+ //
+
+ _ExceptionContext()._pTopTry = _pPrevTry;
+}
+
+//+---------------------------------------------------------------------------
+//
+// Member: CTry::CTry, public
+//
+// Synopsis: Set up to run the body of a TRY ... CATCH clause.
+//
+// Effects: Links this CTry into the chain of TRY clauses.
+//
+// History: 22-May-91 KyleP Created.
+//
+//----------------------------------------------------------------------------
+
+inline CTry::CTry()
+{
+ CExceptionContext& _exceptioncontext = _ExceptionContext();
+
+ _pPrevTry = _exceptioncontext._pTopTry;
+ _exceptioncontext._pTopTry = this;
+ _StackTop = _exceptioncontext.GetTop();
+
+ exDebugOut(( DEB_ITRACE, "TRY %lx (%lx)\n", _StackTop, this ));
+}
+
+//+---------------------------------------------------------------------------
+//
+// The following macros implement a TRY ... CATCH syntax similar
+// to that in C++. They are used as follows:
+//
+// TRY
+// {
+// // Body of try goes here...
+// }
+// CATCH(exclass, e)
+// {
+// // We get here when an exception of class exclass has
+// // been thrown. The variable e is declared as * exclass.
+// }
+// AND_CATCH(exclass, e)
+// {
+// // Just like CATCH. Any number of AND_CATCH can follow
+// // CATCH. Handlers are tried in order of appearance.
+// }
+// END_CATCH
+//
+// To throw an exception, use the THROW macro -- THROW(exclass). To
+// re-throw the same exception from within a catch clause use
+// RETHROW(). Note that RETHROW() is only valid in a CATCH/AND_CATCH.
+//
+// History: 22-May-91 KyleP Created Interface.
+// 15-Aug-91 SethuR modified THROW,CATCH,AND_CATCH,END_CATCH
+// macros
+// 18-Oct-91 KyleP Win32 try/except implementation
+//
+//----------------------------------------------------------------------------
+
+extern EXPORTDEF void APINOT ThrowDebugException(unsigned int iLine,
+ char * szFile,
+ CException & ecE );
+
+extern EXPORTDEF void APINOT ThrowException(CException & ecE,
+ unsigned dummy);
+
+#if DBG == 1 || OFSDBG == 1// +++++++++++++++++++++++++++++++++++++++++++++++
+# define THROW(e) \
+ { \
+ ThrowDebugException(__LINE__,__FILE__,e); \
+ }
+
+#else // DBG == 0 && OFSDBG == 0 ++++++++++++++++++++++++++++++++++++++++++++
+
+# define THROW(e) \
+ { \
+ ThrowException(e, 1); \
+ }
+
+#endif // DBG == 0 && OFSDBG == 0 ++++++++++++++++++++++++++++++++++++++++++++
+
+
+#ifdef WIN32 // ----------------------------------------------------
+
+#define EXCEPT_VULCAN 0xE0000001
+
+# define CALLEX( x ) \
+ __try \
+ { \
+ x; \
+ } \
+ __except( EXCEPTION_EXECUTE_HANDLER ) \
+ { \
+ THROW( CException( GetExceptionCode() ) ); \
+ }
+
+#if defined( KERNEL )
+# if DBG == 1 || OFSDBG == 1// +++++++++++++++++++++++++++++++++++++++++++++++
+# define RETHROW() \
+ ExceptionReport(__LINE__,__FILE__,"Rethrowing Exception"); \
+ ExRaiseStatus( EXCEPT_VULCAN );
+
+# else // DBG == 0 && OFSDBG == 0 ++++++++++++++++++++++++++++++++++++++++++++
+
+# define RETHROW() \
+ ExRaiseStatus( EXCEPT_VULCAN );
+
+# endif // DBG == 0 && OFSDBG == 0 ++++++++++++++++++++++++++++++++++++++++++++
+
+
+#else // !KERNEL
+# if DBG == 1 || OFSDBG == 1// +++++++++++++++++++++++++++++++++++++++++++++++
+# define RETHROW() \
+ ExceptionReport(__LINE__,__FILE__,"Rethrowing Exception"); \
+ RaiseException( EXCEPT_VULCAN, 0, 0, 0 );
+# else // DBG == 0 && OFSDBG == 0 ++++++++++++++++++++++++++++++++++++++++++++
+
+# define RETHROW() \
+ RaiseException( EXCEPT_VULCAN, 0, 0, 0 );
+
+# endif // DBG == 0 && OFSDBG == 0 ++++++++++++++++++++++++++++++++++++++++++++
+
+#endif // !KERNEL
+
+#define TRY \
+ { \
+ CTry _trycontext; \
+ __try
+
+EXPORTDEF ULONG APINOT Unwind( struct _EXCEPTION_POINTERS * pdisp,
+ CTry * ptry );
+
+#if DBG == 1 || OFSDBG == 1 // +++++++++++++++++++++++++++++++++++++++++++++++
+
+#define CATCH(class, e) \
+ __except( Unwind( GetExceptionInformation(), &_trycontext ) ) \
+ { \
+ CExceptionContext& _exceptioncontext = _ExceptionContext(); \
+ if (_exceptioncontext._exception.IsKindOf(#class)) \
+ { \
+ ExceptionReport(__LINE__,__FILE__,"Catching Exception"); \
+ class & e = (class &)_exceptioncontext._exception;
+
+#define AND_CATCH(class, e) \
+ } \
+ else if (_exceptioncontext._exception.IsKindOf(#class)) \
+ { \
+ ExceptionReport(__LINE__,__FILE__,"Catching Exception"); \
+ class & e = (class &)_exceptioncontext._exception;
+
+#else // DBG == 0 ++++++++++++++++++++++++++++++++++++++++++++
+
+#define CATCH(class, e) \
+ __except( Unwind( GetExceptionInformation(), &_trycontext ) ) \
+ { \
+ CExceptionContext& _exceptioncontext = _ExceptionContext(); \
+ if (_exceptioncontext._exception.IsKindOf(#class)) \
+ { \
+ class & e = (class &)_exceptioncontext._exception;
+
+#define AND_CATCH(class, e) \
+ } \
+ else if (_exceptioncontext._exception.IsKindOf(#class)) \
+ { \
+ class & e = ( class &)_exceptioncontext._exception;
+
+#endif // DBG == 0 +++++++++++++++++++++++++++++++++++++++++++
+
+#define END_CATCH \
+ } \
+ else \
+ { \
+ RETHROW(); \
+ } \
+ } \
+ }
+
+#else // NOT WIN32 -------------------------------------------------
+
+#define TRY \
+ { \
+ CTry _trycontext; \
+ if (setjmp(_trycontext._jb) == 0) \
+
+
+
+#if DBG == 1 || OFSDBG == 1 // ++++++++++++++++++++++++++++++++++++++++++++++++
+
+#define CATCH(class, e) \
+ \
+ else \
+ { \
+ CExceptionContext& _exceptioncontext = _ExceptionContext(); \
+ if (_exceptioncontext._exception.IsKindOf(#class)) \
+ { \
+ ExceptionReport(__LINE__,__FILE__,"Catching Exception"); \
+ class & e = (class &)_exceptioncontext._exception;
+
+#define AND_CATCH(class, e) \
+ \
+ } \
+ else if (_exceptioncontext._exception.IsKindOf(#class)) \
+ { \
+ ExceptionReport(__LINE__,__FILE__,"Catching Exception"); \
+ class & e = (class &)_exceptioncontext._exception;
+
+
+#else // DBG == 0 +++++++++++++++++++++++++++++++++++++++++++++
+
+#define CATCH(class, e) \
+ \
+ else \
+ { \
+ CExceptionContext& _exceptioncontext = _ExceptionContext(); \
+ if (_exceptioncontext._exception.IsKindOf(#class)) \
+ { \
+ class & e = (class &)_exceptioncontext._exception;
+
+#define AND_CATCH(class, e) \
+ \
+ } \
+ else if (_exceptioncontext._exception.IsKindOf(#class)) \
+ { \
+ class & e = (class &)_exceptioncontext._exception;
+
+#endif // DBG == 0 +++++++++++++++++++++++++++++++++++++++++++
+
+
+#define END_CATCH \
+ } \
+ else \
+ { \
+ _exceptioncontext.Throw(); \
+ } \
+ } \
+ }
+
+#define RETHROW() \
+ _exceptioncontext.Throw()
+
+#endif // NOT WIN32 ------------------------------------------------
+
+//+---------------------------------------------------------------------------
+//
+// The following macros prepare a class for stack unwinding. Any class
+// with a destructor should be prepared to deal with stack unwind.
+// The macros are used as follows:
+//
+// First, in the .hxx file...
+//
+// class CClassWithADestructor : INHERIT_UNWIND // , other inheritance
+// {
+// DECLARE_UNWIND
+//
+// //
+// // The rest of the class declaration goes here...
+// //
+// }
+//
+// And then in the .cxx file...
+//
+// IMPLEMENT_UNWIND(CClassWithADestructor)
+//
+// CClassWithADestructor::CClassWithADestructor(...)
+// {
+// //
+// // User construction activity.
+// //
+//
+// //
+// // The following should precede every return from the
+// // constructor.
+// //
+//
+// END_CONSTRUCTION(CClassWithADestructor)
+// }
+//
+// INHERIT_UNWIND must be the first inheritance.
+//
+// For further levels of inheritance, you do not need to inherit from
+// INHERIT_UNWIND (more to the point, you can't). The other macros
+// must be used for all levels.
+//
+// INHERIT_VIRTUAL_UNWIND must be used in place of INHERIT_UNWIND on a class
+// that contains virtual methods. If INHERIT_VIRTUAL_UNWIND also fails,
+// then find me (KyleP) and I'll try to figure out what went wrong.
+//
+// Multiple inheritance is untested. It may work, or it may not. If you
+// really need multiple inheritance see me (KyleP).
+//
+// History: 19-Nov-91 KyleP Added multiple-inheritance support
+// 22-May-91 KyleP Created Interface.
+// 13-Nov-92 KyleP Added support for classes with virtual
+// methods.
+//
+//----------------------------------------------------------------------------
+
+#define INHERIT_UNWIND \
+ \
+ public CUnwindable
+
+#define INHERIT_VIRTUAL_UNWIND \
+ \
+ public CVirtualUnwindable
+
+
+#define END_MULTINHERITED_CONSTRUCTION(class, base1) \
+ \
+ base1::_Activate(sizeof(class), &class::_ObjectUnwind);
+
+
+//
+// Why such a complicated test below? Because we are nearly ready to
+// ship Daytona and Ole includes except.hxx but requires the macros
+// do nothing. We are unable to change the Ole sources this late in
+// the game, so you get exceptions only if you are:
+// a) In a Cairo build and didn't define NOEXCEPTIONS, or
+// b) Defined YESEXCEPTIONS in any build.
+//
+// The above would be true and interesting if anybody except OFS wanted
+// to use ofsNew or ofsDelete. As it is, the declarations below (and
+// most of the rest of this file) should be moved to the OFS project
+//
+#if ((WIN32 == 300) && !defined(NOEXCEPTIONS)) || defined(YESEXCEPTIONS)
+
+#if (OFSDBG == 1)
+ void* _CRTAPI1 ofsNew( size_t size, FAIL_BEHAVIOR FailBehavior );
+ inline void* _CRTAPI1 operator new ( size_t size, FAIL_BEHAVIOR FailBehavior)
+ { return ofsNew(size, FailBehavior); }
+
+ void _CRTAPI1 ofsDelete( void * p );
+ inline void _CRTAPI1 operator delete ( void * p )
+ { ofsDelete( p ); }
+#endif // (OFSDBG == 1)
+
+#define INHERIT_UNWIND_IF_CAIRO : INHERIT_UNWIND
+
+#define DECLARE_UNWIND \
+ \
+ static void APINOT _ObjectUnwind(void * pthis);
+
+#if DBG == 1 || OFSDBG == 1
+
+# define IMPLEMENT_UNWIND(class) \
+ \
+ void APINOT class::_ObjectUnwind(void * pthis) \
+ { \
+ ((class *)pthis)->class::~class(); \
+ } \
+ \
+ struct __Check##class \
+ { \
+ __Check##class() \
+ { \
+ if ( (CUnwindable *)((class *)10) != (CUnwindable *)10 || \
+ (CVirtualUnwindable *) \
+ ((class *)10) != (CVirtualUnwindable *)10 ) \
+ { \
+ exDebugOut(( DEB_ERROR, \
+ "INVALID UNWINDABLE CLASS: %s.\n", \
+ #class )); \
+ } \
+ } \
+ }; \
+ \
+ __Check##class __check_except_##class;
+
+#else // DBG == 0
+
+# define IMPLEMENT_UNWIND(class) \
+ \
+ void APINOT class::_ObjectUnwind(void * pthis) \
+ { \
+ ((class *)pthis)->class::~class(); \
+ }
+
+#endif // DBG
+
+#define END_CONSTRUCTION(class) \
+ \
+ _Activate( sizeof(class), &class::_ObjectUnwind );
+
+// The following macro will (probably) need to be redefined (to null) when
+// compiler support for exceptions arrives.
+
+#define INLINE_UNWIND(cls) \
+ static void _ObjectUnwind ( void * pthis ) \
+ { ((cls *)pthis)->cls::~cls(); };
+#else
+
+#define INHERIT_UNWIND_IF_CAIRO
+
+#define DECLARE_UNWIND
+
+#define END_CONSTRUCTION(class)
+
+#define INLINE_UNWIND(cls)
+
+#define IMPLEMENT_UNWIND(cls)
+
+#endif
+
+#endif // __EXCEPT_HXX__