Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1134 lines
37 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1991 - 1992.
  5. //
  6. // File: Except.hxx
  7. //
  8. // Contents: Macro package for C++ exception support
  9. //
  10. // Classes: CException -- The base for all exception classes
  11. // CExceptionContext -- Per-thread exception context.
  12. // CUnwindable -- Classes with destructors inherit
  13. // from this.
  14. // CTry -- Per/TRY state.
  15. //
  16. // Functions: Macros to implement TRY ... CATCH
  17. // Macros to implement unwind for classes with destructors
  18. //
  19. // History: 22-May-91 KyleP Created Interface.
  20. // 15-Aug-91 SethuR modified THROW,CATCH,AND_CATCH,
  21. // END_CATCH macros
  22. // 18-Oct-91 KyleP Win32 try/except implementation
  23. // 20-Feb-92 KyleP Fixed destruction of classes with
  24. // virtual methods.
  25. // 03-Aug-92 KyleP Kernel implementation
  26. // 13-Nov-92 KyleP Bugfix destruction of heap classes.
  27. // Added assertion checking.
  28. // 27-May-93 Mackm Added definitions for un-exceptional
  29. // operator new.
  30. // 01-Jun-93 RobBear Added definitions for alloc hooking
  31. // 30-Sep-93 KyleP DEVL obsolete
  32. // 14-Dec-93 AlexT Add NOEXCEPTIONS support
  33. //
  34. //----------------------------------------------------------------------------
  35. #pragma warning(4:4509) // SEH used in function w/ _trycontext
  36. #ifndef __EXCEPT_HXX_
  37. #define __EXCEPT_HXX_
  38. #ifdef DISPLAY_INCLUDES
  39. #pragma message( "#include <" __FILE__ ">..." )
  40. #endif
  41. #if defined( KERNEL )
  42. # include <ntstatus.h>
  43. # include <stddef.h>
  44. #else // !KERNEL
  45. # include <memory.h>
  46. # include <stdlib.h>
  47. # include <string.h>
  48. # include <stdio.h>
  49. #endif
  50. #include <debnot.h>
  51. const int maxExceptionSize = 256;
  52. #define DEB_BUDDY 0x10000
  53. #define DEB_UNWIND 0x20000
  54. //
  55. // If EXCEPT_TEST is defined, then the exception code can be compiled
  56. // without use the the 'Win4 environment'. This is only to facilitate
  57. // testing. When EXCEPT_TEST is defined debug messages are printed
  58. // to stdout instead of the debug terminal.
  59. //
  60. //
  61. // REAL CODE -- REAL CODE -- REAL CODE -- REAL CODE
  62. //
  63. #ifndef EXCEPT_TEST
  64. //# if !defined( KERNEL )
  65. //# include <win4p.h>
  66. //# endif // !KERNEL
  67. # if (DBG == 1 || OFSDBG == 1)
  68. //
  69. // VERY UNUSUAL SITUATION:
  70. // Out xxxDebugOut macros are designed to be inline. This causes
  71. // a problem in exceptions because the _xxxInfoLevel flag which
  72. // determines if a message should be printed is not declared in
  73. // every DLL. So. Instead of calling the macro:
  74. //
  75. // DECLARE_DEBUG(ex)
  76. //
  77. // I will:
  78. void exInlineDebugOut2(unsigned long fDebugMask, char const *pszfmt, ...);
  79. // and then export this function from OSM.DLL (or whatever DLL
  80. // exports exception handling.
  81. //
  82. # define exDebugOut( x ) exInlineDebugOut2 x
  83. # define exAssert( x ) Win4Assert( x )
  84. # else // DBG == 0 && OFSDBG == 0
  85. # define exDebugOut( x )
  86. # define exAssert( x )
  87. # endif
  88. //
  89. // TEST ONLY -- TEST ONLY -- TEST ONLY -- TEST ONLY
  90. //
  91. #else // EXCEPT_TEST
  92. typedef unsigned long ULONG;
  93. typedef unsigned char BYTE;
  94. # define TRUE 1
  95. # include <assert.h>
  96. # define exAssert( x ) assert( (x) )
  97. # include <stdarg.h>
  98. inline void exInlineDebugOut( ULONG,
  99. char * msg,
  100. ... )
  101. {
  102. va_list arglist;
  103. va_start(arglist, msg);
  104. vfprintf(stderr, msg, arglist);
  105. }
  106. # define exDebugOut( x ) exInlineDebugOut x
  107. # define _PopUpError( p1, p2, p3 ) 0xFFFFFFFF
  108. # define Win4ExceptionLevel 0xFFFFFFFF
  109. # define EXCEPT_MESSAGE 0x1
  110. # define EXCEPT_POPUP 0x0
  111. # define EXCEPT_BREAK 0x0
  112. # define DEB_FORCE 0x0
  113. # define DEB_WARN 0x0
  114. # define DEB_ERROR 0x0
  115. # define DEB_ITRACE 0x0
  116. #endif // EXCEPT_TEST
  117. //
  118. // END TEST -- END TEST -- END TEST -- END TEST
  119. //
  120. #if defined( WIN32 )
  121. # if !defined( KERNEL )
  122. # include <windows.h>
  123. # endif // !KERNEL
  124. #else // !WIN32
  125. # include <setjmp.h>
  126. #endif // WIN32
  127. class CTry;
  128. typedef void(*PFV)();
  129. extern void terminate();
  130. extern void unexpected();
  131. extern PFV set_terminate(PFV terminate_fn);
  132. extern PFV set_unexpected(PFV unexpected_fn);
  133. #if DBG==1 || OFSDBG == 1
  134. typedef BOOL (* ALLOC_HOOK)(size_t nSize);
  135. EXPORTDEF ALLOC_HOOK MemSetAllocHook( ALLOC_HOOK pfnAllocHook );
  136. extern EXPORTDEF void WINAPI
  137. ExceptionReport(
  138. unsigned int iLine,
  139. char *szFile,
  140. char *szMsg);
  141. #endif // DBG == 1 || OFSDBG == 1
  142. //+---------------------------------------------------------------------------
  143. //
  144. // Class: CException
  145. //
  146. // Purpose: All exception objects (e.g. objects that are THROW)
  147. // inherit from CException.
  148. //
  149. // Interface: ~CException - Destructor
  150. // IsKindOf - Class membership query
  151. //
  152. // History: 22-May-91 KyleP Created.
  153. //
  154. // Notes: This class is a hack, until C7 can provide some support
  155. // for runtime inheritance detection (e.g. a way to generate
  156. // a mangled name). When we get this support a new
  157. // implementation of IsKindOf should be developed. The concept,
  158. // however, would remain the same: C++ exception objects are
  159. // instances of an exception class, but they are caught by class.
  160. //
  161. // A compiler can implement IsKindOf by throwing a
  162. // decorated name which uniquely identifies a class and
  163. // describes its inheritance.
  164. //
  165. // Don't do anything too fancy with subclasses of CException.
  166. // Instances of your subclass are memcpy-ed around. Having
  167. // a user defined destructor, for example, is probably a bad
  168. // idea.
  169. //
  170. //----------------------------------------------------------------------------
  171. class CException
  172. {
  173. public:
  174. EXPORTDEF CException(long lError);
  175. long GetErrorCode() { return _lError;}
  176. EXPORTDEF virtual int WINAPI IsKindOf(const char * szClass) const;
  177. protected:
  178. long _lError;
  179. };
  180. //+---------------------------------------------------------------------------
  181. //
  182. // Class: CExceptionContext
  183. //
  184. // Purpose: Per-thread exception state and throw exception methods.
  185. //
  186. // Interface: CExceptionContext -- Constructor
  187. // ~CExceptionContext -- Destructor
  188. // Push -- Push a new element on the stack of
  189. // elements-to-be-destroyed.
  190. // Pop -- Pop an an element off the stack.
  191. // SetTop -- Set the top of stack to the specified
  192. // element.
  193. // GetTop -- Return the top element.
  194. // Throw -- Throw an exception
  195. //
  196. // History: 19-Nov-91 KyleP Fix heap unwind, multiple inheritance
  197. // 22-May-91 KyleP Created.
  198. //
  199. // Notes: There is only 1 CExceptionContext object per thread.
  200. //
  201. //----------------------------------------------------------------------------
  202. class CExceptionContext
  203. {
  204. public:
  205. CExceptionContext();
  206. ~CExceptionContext();
  207. EXPORTDEF void WINAPI Reserve(void * pthis);
  208. inline void Pop(void * pthis);
  209. EXPORTDEF void WINAPI SetTop(void * pthis,
  210. ULONG cbElement,
  211. void (* pfn)(void *));
  212. inline int GetTop();
  213. #ifndef WIN32
  214. void Throw();
  215. #endif /* WIN32 */
  216. void Unwind( CTry * ptry );
  217. //
  218. // _pTopTry contains the head of a linked list of CTry objects,
  219. // each of which corresponds to a TRY clause.
  220. //
  221. CTry * _pTopTry;
  222. //
  223. // _pLastNew records the address of the most recent free
  224. // store allocation, _cbLastNew the size.
  225. //
  226. BYTE * _pLastNew;
  227. int _cbLastNew;
  228. int _fNewReadyForUnwind;
  229. //
  230. // _exception contains a pointer to the current exception,
  231. // if any. The character buffer following it is for storing
  232. // additional data belonging to subclasses.
  233. //
  234. CException _exception;
  235. char buffer[maxExceptionSize];
  236. private:
  237. //
  238. // Each StackElement contains enough information to destroy a
  239. // completly constructed object, and the determine whether
  240. // objects which have not yet been fully constructed were
  241. // allocated on the heap or the stack.
  242. //
  243. class StackElement
  244. {
  245. public:
  246. BOOL IsThisEqual( void * pthis ) { return( pthis == _pthis ); }
  247. BOOL IsSizeEqual( ULONG cb ) { return( cb == _cbElement ); }
  248. BOOL IsOnStack() { return( _cbElement == 0 ); }
  249. BOOL IsOnHeap() { return( _cbElement != 0 ); }
  250. BOOL IsActive() { return( _pfn != 0 ); }
  251. void SetOnStack() { _cbElement = 0; }
  252. void SetOnHeap( ULONG size ) { _cbElement = size; }
  253. void SetThis( void * pthis ) { _pthis = pthis; }
  254. void SetDtor( void (* pfn)(void *) ) { _pfn = pfn; }
  255. void * GetDtor() { return( _pfn ); }
  256. void * GetThis() { return( _pthis ); }
  257. void Destroy() { _pfn( (BYTE *)_pthis ); }
  258. void Delete() { delete (BYTE *)_pthis; }
  259. private:
  260. void * _pthis; // This for CUnwindable
  261. void (* _pfn)(void *); // 'Static destructor'
  262. ULONG _cbElement; // 0 == On stack. > 0 = Size of class
  263. };
  264. //
  265. // _aStack is the stack of objects-to-be-destroyed in the face
  266. // of an exception (stack unwind).
  267. //
  268. StackElement * _aStack;
  269. //
  270. // _StackTop is the index of the first free element on the stack.
  271. //
  272. int _StackTop;
  273. //
  274. // _StackSize is the maximum number of elements which can be
  275. // stored on the stack.
  276. //
  277. int _StackSize;
  278. EXPORTDEF void APINOT _Grow();
  279. };
  280. //+---------------------------------------------------------------------------
  281. //
  282. // Member: CExceptionContext::Pop, public
  283. //
  284. // Synopsis: Pops the top element off the stack of objects to be destroyed.
  285. //
  286. // Effects: Pop only has an effect if the top element on the stack
  287. // is for [pthis].
  288. //
  289. // Arguments: [pthis] -- Must correspond to the top of stack if the
  290. // element is to be popped.
  291. //
  292. // History: 22-May-91 KyleP Created.
  293. //
  294. //----------------------------------------------------------------------------
  295. inline void CExceptionContext::Pop(void * pthis)
  296. {
  297. //
  298. // Remove the top of stack only if it corresponds to pthis.
  299. // Thus the element will be removed only if this object was
  300. // declared on the stack (as opposed to embedded) and no
  301. // exception was encountered.
  302. //
  303. //
  304. // You should *always* find what you're looking for. No checking
  305. // for runoff. The very bottom element of the stack is a sentinel
  306. // for the case of heap objects which have been fully removed from
  307. // the stack.
  308. //
  309. exAssert( _StackTop > 0 );
  310. if ( _aStack[_StackTop-1].IsThisEqual( pthis ) )
  311. {
  312. //
  313. // The following assertion is hit if an unwindable object
  314. // is destroyed without END_CONSTRUCTION being called.
  315. //
  316. exAssert( _aStack[_StackTop-1].IsActive() );
  317. _StackTop--;
  318. #if DBG == 1 || OFSDBG == 1
  319. exDebugOut(( DEB_ITRACE, "POP %lx %lx( %lx )\n",
  320. _StackTop,
  321. _aStack[_StackTop].GetDtor(),
  322. _aStack[_StackTop].GetThis() ));
  323. #endif // DBG || OFSDBG == 1
  324. }
  325. }
  326. //+---------------------------------------------------------------------------
  327. //
  328. // Member: CExceptionContext::GetTop, public
  329. //
  330. // Returns: The index of the top of the stack of objects to be
  331. // destroyed. This is the first available element.
  332. //
  333. // History: 22-May-91 KyleP Created.
  334. //
  335. //----------------------------------------------------------------------------
  336. inline int CExceptionContext::GetTop()
  337. {
  338. return(_StackTop);
  339. }
  340. EXPORTDEF CExceptionContext& APINOT _ExceptionContext(void);
  341. //----------------------------------------------------------------------------
  342. //
  343. // Various operator new implementations
  344. //
  345. //----------------------------------------------------------------------------
  346. EXPORTDEF int APINOT LeakCheck ( ULONG* pCount );
  347. #if defined( KERNEL )
  348. //
  349. // Prototype for extra operator new used in kernel to specify
  350. // resident vs. swappable heap.
  351. //
  352. void InitExceptionSystem();
  353. void* __cdecl operator new ( size_t size, POOL_TYPE pool );
  354. #if OFSDBG == 1
  355. # define NEW_POOL( pool, pCounter ) new(pool, pCounter)
  356. void* __cdecl operator new ( size_t size, POOL_TYPE pool, ULONG* pCounter );
  357. #else
  358. # define NEW_POOL( pool, pCounter ) new(pool)
  359. #endif
  360. #endif // KERNEL
  361. //
  362. // Allocation with trace context
  363. //
  364. #if OFSDBG == 1 || DBG == 1
  365. # define NEW( pCounter ) new ( pCounter )
  366. void* __cdecl operator new ( size_t size, ULONG* pCounter );
  367. #else
  368. # define NEW( pCounter ) new
  369. #endif
  370. //
  371. // Prototype for extra operator new used in routines which do not
  372. // have an exception handler set up and prefer a null return on
  373. // failed allocations rather than an exception.
  374. //
  375. typedef enum _FAIL_BEHAVIOR
  376. {
  377. NullOnFail,
  378. ExceptOnFail
  379. } FAIL_BEHAVIOR ;
  380. void* __cdecl operator new ( size_t size, FAIL_BEHAVIOR FailBehavior );
  381. #define newx new(ExceptOnFail)
  382. //+---------------------------------------------------------------------------
  383. //
  384. // Class: CSystemException
  385. //
  386. // Purpose: Base class for system (hardware) exceptions which are
  387. // not handled by a specific exception class
  388. //
  389. // Interface:
  390. //
  391. // History: 18-Oct-91 KyleP Created.
  392. //
  393. //----------------------------------------------------------------------------
  394. class CSystemException : public CException
  395. {
  396. public:
  397. EXPORTDEF CSystemException(ULONG ulExcept);
  398. virtual int WINAPI IsKindOf(const char * szClass) const;
  399. ULONG GetSysErrorCode() { return( _ulExcept ); }
  400. private:
  401. ULONG _ulExcept;
  402. };
  403. //+---------------------------------------------------------------------------
  404. //
  405. // Class: CUnwindable, CVirtualUnwindable
  406. //
  407. // Purpose: Per-object exception state and registration/unwind methods.
  408. //
  409. // Interface: CUnwindable -- Constructor
  410. // ~CUnwindable -- Destructor
  411. // _Activate -- Activate object.
  412. //
  413. // History: 22-May-91 KyleP Created.
  414. // 13-Nov-92 KyleP Added virtual version
  415. //
  416. // Notes: CVirtualUnwindable should be used if and only if a
  417. // derived class has some other virtual method.
  418. //
  419. //----------------------------------------------------------------------------
  420. class CUnwindable
  421. {
  422. public:
  423. inline CUnwindable();
  424. inline ~CUnwindable();
  425. inline void _Activate( ULONG cbElement,
  426. void (* pfn)(void *) );
  427. };
  428. class CVirtualUnwindable
  429. {
  430. public:
  431. inline CVirtualUnwindable();
  432. virtual ~CVirtualUnwindable();
  433. inline void _Activate( ULONG cbElement,
  434. void (* pfn)(void *) );
  435. };
  436. //+---------------------------------------------------------------------------
  437. //
  438. // Member: CUnwindable::CUnwindable, public
  439. //
  440. // Synopsis: Initializes the link field of the object.
  441. //
  442. // Effects: Essentially sets up enough state to remember the position
  443. // of the object which inherits from CUnwindable
  444. // within the stack of objects-to-be-destroyed.
  445. //
  446. // History: 22-May-91 KyleP Created.
  447. //
  448. // Notes: This call does not fully link the object into the chain
  449. // of objects to be destroyed. See _Activate.
  450. //
  451. //----------------------------------------------------------------------------
  452. inline CUnwindable::CUnwindable()
  453. {
  454. //
  455. // Initialize by allocating a record on the deletion stack.
  456. //
  457. _ExceptionContext().Reserve(this);
  458. }
  459. inline CVirtualUnwindable::CVirtualUnwindable()
  460. {
  461. //
  462. // Initialize by allocating a record on the deletion stack.
  463. //
  464. _ExceptionContext().Reserve(this);
  465. }
  466. //+---------------------------------------------------------------------------
  467. //
  468. // Member: CUnwindable::~CUnwindable, public
  469. //
  470. // Synopsis: Removes this object from the stack of objects to be destroyed.
  471. //
  472. // Modifies: Per/thread exception context.
  473. //
  474. // History: 22-May-91 KyleP Created.
  475. //
  476. //----------------------------------------------------------------------------
  477. inline CUnwindable::~CUnwindable()
  478. {
  479. _ExceptionContext().Pop(this);
  480. }
  481. inline CVirtualUnwindable::~CVirtualUnwindable()
  482. {
  483. _ExceptionContext().Pop(this);
  484. }
  485. //+---------------------------------------------------------------------------
  486. //
  487. // Member: CUnwindable::_Activate, public
  488. //
  489. // Synopsis: Fully link object into stack of objects to be destroyed.
  490. //
  491. // Effects: After this call, the object which inherits from
  492. // CUnwindable will be destroyed during unwind.
  493. //
  494. // If the object was declared on the heap, then it is
  495. // removed completely from the stack of objects that will
  496. // be destroyed during unwind.
  497. //
  498. // Arguments: [prealthis] -- This pointer of instance. Will differ
  499. // from this pointer of CUnwindable
  500. // if instance has a virtual method.
  501. // [cbElement] -- Size of the instance being activated. If
  502. // an element is declared on the heap and
  503. // [cbElement] is smaller than the allocation
  504. // then the element won't be deleted.
  505. //
  506. // [pfn] -- Pointer to a static destructor. [pfn] takes a
  507. // this pointer.
  508. //
  509. // Modifies: This object is now the top of the stack of objects that
  510. // will be destroyed (_exceptioncontext is modified).
  511. //
  512. // History: 22-May-91 KyleP Created.
  513. //
  514. //----------------------------------------------------------------------------
  515. inline void CUnwindable::_Activate(
  516. ULONG cbElement,
  517. void (* pfn)(void *))
  518. {
  519. _ExceptionContext().SetTop(this, cbElement, pfn);
  520. }
  521. inline void CVirtualUnwindable::_Activate(
  522. ULONG cbElement,
  523. void (* pfn)(void *))
  524. {
  525. _ExceptionContext().SetTop(this, cbElement, pfn);
  526. }
  527. //+---------------------------------------------------------------------------
  528. //
  529. // Class: CTry
  530. //
  531. // Purpose: Containt per/TRY state.
  532. //
  533. // Interface: ~CTry - Destructor
  534. // TryIt - Setup to run the TRY body.
  535. //
  536. // History: 22-May-91 KyleP Created.
  537. //
  538. //----------------------------------------------------------------------------
  539. class CTry
  540. {
  541. public:
  542. inline CTry();
  543. inline ~CTry();
  544. //
  545. // The following function ***MUST*** be declared inline and
  546. // actually be ***IMPLEMENTED*** inline. It calls setjmp;
  547. // and if TryIt is a real procedure then we just set the
  548. // return for longjmp on a piece of stack that is reclaimed!
  549. //
  550. //inline int TryIt();
  551. #ifndef WIN32
  552. //
  553. // _jb is the setjmp buffer indicating the location that will
  554. // be longjmp'ed to when an exception occurs.
  555. //
  556. jmp_buf _jb;
  557. #endif /* WIN32 */
  558. //
  559. // _pPrevTry is a link to the enclosing TRY clause.
  560. //
  561. CTry * _pPrevTry;
  562. //
  563. // _StackTop was the top of the stack of objects-to-be-destroyed
  564. // when the TRY clause was entered.
  565. //
  566. int _StackTop;
  567. };
  568. //+---------------------------------------------------------------------------
  569. //
  570. // Member: CTry::~CTry, public
  571. //
  572. // Synopsis: Unlinks the TRY ... CATCH from the per/thread list.
  573. //
  574. // Modifies: The per/thread list of try clauses in _exceptioncontext.
  575. //
  576. // History: 22-May-91 KyleP Created.
  577. //
  578. //----------------------------------------------------------------------------
  579. inline CTry::~CTry()
  580. {
  581. exDebugOut(( DEB_ITRACE, "END TRY %lx (%lx)\n", _StackTop, this ));
  582. //
  583. // The destructor for CTry is called only during normal (no
  584. // exception) exit from the TRY ... CATCH or when an
  585. // exception was successfully caught in this block.
  586. // In these cases we want to unlink this CTry.
  587. //
  588. // Note that we could delete _exceptioncontext._TheException
  589. // here, which may be non-null if we caught an exception in
  590. // this TRY ... CATCH block. But why bother? That would add
  591. // additional code to the normal case. The last exception
  592. // can wait to be deleted until the next occurs.
  593. //
  594. _ExceptionContext()._pTopTry = _pPrevTry;
  595. }
  596. //+---------------------------------------------------------------------------
  597. //
  598. // Member: CTry::CTry, public
  599. //
  600. // Synopsis: Set up to run the body of a TRY ... CATCH clause.
  601. //
  602. // Effects: Links this CTry into the chain of TRY clauses.
  603. //
  604. // History: 22-May-91 KyleP Created.
  605. //
  606. //----------------------------------------------------------------------------
  607. inline CTry::CTry()
  608. {
  609. CExceptionContext& _exceptioncontext = _ExceptionContext();
  610. _pPrevTry = _exceptioncontext._pTopTry;
  611. _exceptioncontext._pTopTry = this;
  612. _StackTop = _exceptioncontext.GetTop();
  613. exDebugOut(( DEB_ITRACE, "TRY %lx (%lx)\n", _StackTop, this ));
  614. }
  615. //+---------------------------------------------------------------------------
  616. //
  617. // The following macros implement a TRY ... CATCH syntax similar
  618. // to that in C++. They are used as follows:
  619. //
  620. // TRY
  621. // {
  622. // // Body of try goes here...
  623. // }
  624. // CATCH(exclass, e)
  625. // {
  626. // // We get here when an exception of class exclass has
  627. // // been thrown. The variable e is declared as * exclass.
  628. // }
  629. // AND_CATCH(exclass, e)
  630. // {
  631. // // Just like CATCH. Any number of AND_CATCH can follow
  632. // // CATCH. Handlers are tried in order of appearance.
  633. // }
  634. // END_CATCH
  635. //
  636. // To throw an exception, use the THROW macro -- THROW(exclass). To
  637. // re-throw the same exception from within a catch clause use
  638. // RETHROW(). Note that RETHROW() is only valid in a CATCH/AND_CATCH.
  639. //
  640. // History: 22-May-91 KyleP Created Interface.
  641. // 15-Aug-91 SethuR modified THROW,CATCH,AND_CATCH,END_CATCH
  642. // macros
  643. // 18-Oct-91 KyleP Win32 try/except implementation
  644. //
  645. //----------------------------------------------------------------------------
  646. extern EXPORTDEF void APINOT ThrowDebugException(unsigned int iLine,
  647. char * szFile,
  648. CException & ecE );
  649. extern EXPORTDEF void APINOT ThrowException(CException & ecE,
  650. unsigned dummy);
  651. #if DBG == 1 || OFSDBG == 1// +++++++++++++++++++++++++++++++++++++++++++++++
  652. # define THROW(e) \
  653. { \
  654. ThrowDebugException(__LINE__,__FILE__,e); \
  655. }
  656. #else // DBG == 0 && OFSDBG == 0 ++++++++++++++++++++++++++++++++++++++++++++
  657. # define THROW(e) \
  658. { \
  659. ThrowException(e, 1); \
  660. }
  661. #endif // DBG == 0 && OFSDBG == 0 ++++++++++++++++++++++++++++++++++++++++++++
  662. #ifdef WIN32 // ----------------------------------------------------
  663. #define EXCEPT_VULCAN 0xE0000001
  664. # define CALLEX( x ) \
  665. __try \
  666. { \
  667. x; \
  668. } \
  669. __except( EXCEPTION_EXECUTE_HANDLER ) \
  670. { \
  671. THROW( CException( GetExceptionCode() ) ); \
  672. }
  673. #if defined( KERNEL )
  674. # if DBG == 1 || OFSDBG == 1// +++++++++++++++++++++++++++++++++++++++++++++++
  675. # define RETHROW() \
  676. ExceptionReport(__LINE__,__FILE__,"Rethrowing Exception"); \
  677. ExRaiseStatus( EXCEPT_VULCAN );
  678. # else // DBG == 0 && OFSDBG == 0 ++++++++++++++++++++++++++++++++++++++++++++
  679. # define RETHROW() \
  680. ExRaiseStatus( EXCEPT_VULCAN );
  681. # endif // DBG == 0 && OFSDBG == 0 ++++++++++++++++++++++++++++++++++++++++++++
  682. #else // !KERNEL
  683. # if DBG == 1 || OFSDBG == 1// +++++++++++++++++++++++++++++++++++++++++++++++
  684. # define RETHROW() \
  685. ExceptionReport(__LINE__,__FILE__,"Rethrowing Exception"); \
  686. RaiseException( EXCEPT_VULCAN, 0, 0, 0 );
  687. # else // DBG == 0 && OFSDBG == 0 ++++++++++++++++++++++++++++++++++++++++++++
  688. # define RETHROW() \
  689. RaiseException( EXCEPT_VULCAN, 0, 0, 0 );
  690. # endif // DBG == 0 && OFSDBG == 0 ++++++++++++++++++++++++++++++++++++++++++++
  691. #endif // !KERNEL
  692. #define TRY \
  693. { \
  694. CTry _trycontext; \
  695. __try
  696. EXPORTDEF ULONG APINOT Unwind( struct _EXCEPTION_POINTERS * pdisp,
  697. CTry * ptry );
  698. #if DBG == 1 || OFSDBG == 1 // +++++++++++++++++++++++++++++++++++++++++++++++
  699. #define CATCH(class, e) \
  700. __except( Unwind( GetExceptionInformation(), &_trycontext ) ) \
  701. { \
  702. CExceptionContext& _exceptioncontext = _ExceptionContext(); \
  703. if (_exceptioncontext._exception.IsKindOf(#class)) \
  704. { \
  705. ExceptionReport(__LINE__,__FILE__,"Catching Exception"); \
  706. class & e = (class &)_exceptioncontext._exception;
  707. #define AND_CATCH(class, e) \
  708. } \
  709. else if (_exceptioncontext._exception.IsKindOf(#class)) \
  710. { \
  711. ExceptionReport(__LINE__,__FILE__,"Catching Exception"); \
  712. class & e = (class &)_exceptioncontext._exception;
  713. #else // DBG == 0 ++++++++++++++++++++++++++++++++++++++++++++
  714. #define CATCH(class, e) \
  715. __except( Unwind( GetExceptionInformation(), &_trycontext ) ) \
  716. { \
  717. CExceptionContext& _exceptioncontext = _ExceptionContext(); \
  718. if (_exceptioncontext._exception.IsKindOf(#class)) \
  719. { \
  720. class & e = (class &)_exceptioncontext._exception;
  721. #define AND_CATCH(class, e) \
  722. } \
  723. else if (_exceptioncontext._exception.IsKindOf(#class)) \
  724. { \
  725. class & e = ( class &)_exceptioncontext._exception;
  726. #endif // DBG == 0 +++++++++++++++++++++++++++++++++++++++++++
  727. #define END_CATCH \
  728. } \
  729. else \
  730. { \
  731. RETHROW(); \
  732. } \
  733. } \
  734. }
  735. #else // NOT WIN32 -------------------------------------------------
  736. #define TRY \
  737. { \
  738. CTry _trycontext; \
  739. if (setjmp(_trycontext._jb) == 0) \
  740. #if DBG == 1 || OFSDBG == 1 // ++++++++++++++++++++++++++++++++++++++++++++++++
  741. #define CATCH(class, e) \
  742. \
  743. else \
  744. { \
  745. CExceptionContext& _exceptioncontext = _ExceptionContext(); \
  746. if (_exceptioncontext._exception.IsKindOf(#class)) \
  747. { \
  748. ExceptionReport(__LINE__,__FILE__,"Catching Exception"); \
  749. class & e = (class &)_exceptioncontext._exception;
  750. #define AND_CATCH(class, e) \
  751. \
  752. } \
  753. else if (_exceptioncontext._exception.IsKindOf(#class)) \
  754. { \
  755. ExceptionReport(__LINE__,__FILE__,"Catching Exception"); \
  756. class & e = (class &)_exceptioncontext._exception;
  757. #else // DBG == 0 +++++++++++++++++++++++++++++++++++++++++++++
  758. #define CATCH(class, e) \
  759. \
  760. else \
  761. { \
  762. CExceptionContext& _exceptioncontext = _ExceptionContext(); \
  763. if (_exceptioncontext._exception.IsKindOf(#class)) \
  764. { \
  765. class & e = (class &)_exceptioncontext._exception;
  766. #define AND_CATCH(class, e) \
  767. \
  768. } \
  769. else if (_exceptioncontext._exception.IsKindOf(#class)) \
  770. { \
  771. class & e = (class &)_exceptioncontext._exception;
  772. #endif // DBG == 0 +++++++++++++++++++++++++++++++++++++++++++
  773. #define END_CATCH \
  774. } \
  775. else \
  776. { \
  777. _exceptioncontext.Throw(); \
  778. } \
  779. } \
  780. }
  781. #define RETHROW() \
  782. _exceptioncontext.Throw()
  783. #endif // NOT WIN32 ------------------------------------------------
  784. //+---------------------------------------------------------------------------
  785. //
  786. // The following macros prepare a class for stack unwinding. Any class
  787. // with a destructor should be prepared to deal with stack unwind.
  788. // The macros are used as follows:
  789. //
  790. // First, in the .hxx file...
  791. //
  792. // class CClassWithADestructor : INHERIT_UNWIND // , other inheritance
  793. // {
  794. // DECLARE_UNWIND
  795. //
  796. // //
  797. // // The rest of the class declaration goes here...
  798. // //
  799. // }
  800. //
  801. // And then in the .cxx file...
  802. //
  803. // IMPLEMENT_UNWIND(CClassWithADestructor)
  804. //
  805. // CClassWithADestructor::CClassWithADestructor(...)
  806. // {
  807. // //
  808. // // User construction activity.
  809. // //
  810. //
  811. // //
  812. // // The following should precede every return from the
  813. // // constructor.
  814. // //
  815. //
  816. // END_CONSTRUCTION(CClassWithADestructor)
  817. // }
  818. //
  819. // INHERIT_UNWIND must be the first inheritance.
  820. //
  821. // For further levels of inheritance, you do not need to inherit from
  822. // INHERIT_UNWIND (more to the point, you can't). The other macros
  823. // must be used for all levels.
  824. //
  825. // INHERIT_VIRTUAL_UNWIND must be used in place of INHERIT_UNWIND on a class
  826. // that contains virtual methods. If INHERIT_VIRTUAL_UNWIND also fails,
  827. // then find me (KyleP) and I'll try to figure out what went wrong.
  828. //
  829. // Multiple inheritance is untested. It may work, or it may not. If you
  830. // really need multiple inheritance see me (KyleP).
  831. //
  832. // History: 19-Nov-91 KyleP Added multiple-inheritance support
  833. // 22-May-91 KyleP Created Interface.
  834. // 13-Nov-92 KyleP Added support for classes with virtual
  835. // methods.
  836. //
  837. //----------------------------------------------------------------------------
  838. #define INHERIT_UNWIND \
  839. \
  840. public CUnwindable
  841. #define INHERIT_VIRTUAL_UNWIND \
  842. \
  843. public CVirtualUnwindable
  844. #define END_MULTINHERITED_CONSTRUCTION(class, base1) \
  845. \
  846. base1::_Activate(sizeof(class), &class::_ObjectUnwind);
  847. //
  848. // Why such a complicated test below? Because we are nearly ready to
  849. // ship Daytona and Ole includes except.hxx but requires the macros
  850. // do nothing. We are unable to change the Ole sources this late in
  851. // the game, so you get exceptions only if you are:
  852. // a) In a Cairo build and didn't define NOEXCEPTIONS, or
  853. // b) Defined YESEXCEPTIONS in any build.
  854. //
  855. // The above would be true and interesting if anybody except OFS wanted
  856. // to use ofsNew or ofsDelete. As it is, the declarations below (and
  857. // most of the rest of this file) should be moved to the OFS project
  858. //
  859. #if ((WIN32 == 300) && !defined(NOEXCEPTIONS)) || defined(YESEXCEPTIONS)
  860. #if (OFSDBG == 1)
  861. void* __cdecl ofsNew( size_t size, FAIL_BEHAVIOR FailBehavior );
  862. inline void* __cdecl operator new ( size_t size, FAIL_BEHAVIOR FailBehavior)
  863. { return ofsNew(size, FailBehavior); }
  864. void __cdecl ofsDelete( void * p );
  865. inline void __cdecl operator delete ( void * p )
  866. { ofsDelete( p ); }
  867. #endif // (OFSDBG == 1)
  868. #define INHERIT_UNWIND_IF_CAIRO : INHERIT_UNWIND
  869. #define DECLARE_UNWIND \
  870. \
  871. static void APINOT _ObjectUnwind(void * pthis);
  872. #if DBG == 1 || OFSDBG == 1
  873. # define IMPLEMENT_UNWIND(class) \
  874. \
  875. void APINOT class::_ObjectUnwind(void * pthis) \
  876. { \
  877. ((class *)pthis)->class::~class(); \
  878. } \
  879. \
  880. struct __Check##class \
  881. { \
  882. __Check##class() \
  883. { \
  884. if ( (CUnwindable *)((class *)10) != (CUnwindable *)10 || \
  885. (CVirtualUnwindable *) \
  886. ((class *)10) != (CVirtualUnwindable *)10 ) \
  887. { \
  888. exDebugOut(( DEB_ERROR, \
  889. "INVALID UNWINDABLE CLASS: %s.\n", \
  890. #class )); \
  891. } \
  892. } \
  893. }; \
  894. \
  895. __Check##class __check_except_##class;
  896. #else // DBG == 0
  897. # define IMPLEMENT_UNWIND(class) \
  898. \
  899. void APINOT class::_ObjectUnwind(void * pthis) \
  900. { \
  901. ((class *)pthis)->class::~class(); \
  902. }
  903. #endif // DBG
  904. #define END_CONSTRUCTION(class) \
  905. \
  906. _Activate( sizeof(class), &class::_ObjectUnwind );
  907. // The following macro will (probably) need to be redefined (to null) when
  908. // compiler support for exceptions arrives.
  909. #define INLINE_UNWIND(cls) \
  910. static void _ObjectUnwind ( void * pthis ) \
  911. { ((cls *)pthis)->cls::~cls(); };
  912. #else
  913. #define INHERIT_UNWIND_IF_CAIRO
  914. #define DECLARE_UNWIND
  915. #define END_CONSTRUCTION(class)
  916. #define INLINE_UNWIND(cls)
  917. #define IMPLEMENT_UNWIND(cls)
  918. #endif
  919. #endif // __EXCEPT_HXX__