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.

1493 lines
49 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1991 - 1992.
  5. //
  6. // File: ciexcpt.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. // 25-Apr-95 DwightKr Native C++ exception support
  34. // 11-Map-95 DwightKr Add autocheck support
  35. //
  36. //----------------------------------------------------------------------------
  37. #pragma warning(4:4509) // SEH used in function w/ _trycontext
  38. #pragma warning(4:4535) // _set_se_translator used w/o /EHa
  39. #pragma once
  40. #include <eh.h>
  41. const int maxExceptionSize = 256;
  42. #define DEB_UNWIND 0x10000
  43. //
  44. // If EXCEPT_TEST is defined, then the exception code can be compiled
  45. // without use the the 'Win4 environment'. This is only to facilitate
  46. // testing. When EXCEPT_TEST is defined debug messages are printed
  47. // to stdout instead of the debug terminal.
  48. //
  49. //
  50. // REAL CODE -- REAL CODE -- REAL CODE -- REAL CODE
  51. //
  52. #ifndef EXCEPT_TEST
  53. # if (DBG == 1 || CIDBG == 1)
  54. //
  55. // VERY UNUSUAL SITUATION:
  56. // Out xxxDebugOut macros are designed to be inline. This causes
  57. // a problem in exceptions because the _xxxInfoLevel flag which
  58. // determines if a message should be printed is not declared in
  59. // every DLL. So. Instead of calling the macro:
  60. //
  61. // DECLARE_DEBUG(ex)
  62. //
  63. // I will:
  64. void exInlineDebugOut2(unsigned long fDebugMask, char const *pszfmt, ...);
  65. // and then export this function from OSM.DLL (or whatever DLL
  66. // exports exception handling.
  67. //
  68. # define exDebugOut( x ) exInlineDebugOut2 x
  69. # define exAssert( x ) Win4Assert( x )
  70. # else // DBG == 0 && CIDBG == 0
  71. # define exDebugOut( x )
  72. # define exAssert( x )
  73. # endif
  74. //
  75. // TEST ONLY -- TEST ONLY -- TEST ONLY -- TEST ONLY
  76. //
  77. #else // EXCEPT_TEST
  78. typedef unsigned long ULONG;
  79. typedef unsigned char BYTE;
  80. # define TRUE 1
  81. # include <assert.h>
  82. # define exAssert( x ) assert( (x) )
  83. # include <stdarg.h>
  84. inline void exInlineDebugOut( ULONG,
  85. char * msg,
  86. ... )
  87. {
  88. va_list arglist;
  89. va_start(arglist, msg);
  90. vfprintf(stderr, msg, arglist);
  91. }
  92. # define exDebugOut( x ) exInlineDebugOut x
  93. # define _PopUpError( p1, p2, p3 ) 0xFFFFFFFF
  94. # define Win4ExceptionLevel 0xFFFFFFFF
  95. # define EXCEPT_MESSAGE 0x1
  96. # define EXCEPT_POPUP 0x0
  97. # define EXCEPT_BREAK 0x0
  98. # define DEB_FORCE 0x0
  99. # define DEB_WARN 0x0
  100. # define DEB_ERROR 0x0
  101. # define DEB_ITRACE 0x0
  102. #endif // EXCEPT_TEST
  103. //
  104. // END TEST -- END TEST -- END TEST -- END TEST
  105. //
  106. //----------------------------------------------------------------------------
  107. //----------------------------------------------------------------------------
  108. //
  109. // Various operator new implementations
  110. //
  111. //----------------------------------------------------------------------------
  112. //----------------------------------------------------------------------------
  113. EXPORTDEF int APINOT LeakCheck ( ULONG* pCount );
  114. BOOL ExceptDllMain( HANDLE hDll, DWORD dwReason, LPVOID lpReserved );
  115. void* ciNew( size_t size );
  116. inline void * __cdecl operator new ( size_t size )
  117. {
  118. return ciNew( size );
  119. }
  120. BOOL ciIsValidPointer( const void * p );
  121. void ciDelete( void * p );
  122. //
  123. // We MUST force this to be inlined - o/w, a call to delete is made which
  124. // leads to collision in the new/delete operators.
  125. //
  126. static inline void __cdecl operator delete ( void * p )
  127. {
  128. ciDelete( p );
  129. }
  130. #if DBG==1 || CIDBG == 1
  131. typedef BOOL (* ALLOC_HOOK)(size_t nSize);
  132. EXPORTDEF ALLOC_HOOK MemSetAllocHook( ALLOC_HOOK pfnAllocHook );
  133. #endif // DBG == 1 || CIDBG == 1
  134. //
  135. // The default is to print exception messages to debug terminal.
  136. //
  137. #if DBG == 1 || CIDBG == 1
  138. extern "C" ULONG GetWin4ExceptionLevel(void);
  139. #endif // DBG == 1 || CIDBG == 1
  140. //+---------------------------------------------------------------------------
  141. //----------------------------------------------------------------------------
  142. //
  143. // Function prototypes to be used in all implemenations (user & kernel;
  144. // native C++ exceptions & C++ exception macros) are defined here.
  145. //
  146. //----------------------------------------------------------------------------
  147. //----------------------------------------------------------------------------
  148. EXPORTIMP void APINOT
  149. ExceptionReport(
  150. unsigned int iLine,
  151. char *szFile,
  152. char *szMsg,
  153. long lError = long(-1) );
  154. //+---------------------------------------------------------------------------
  155. //----------------------------------------------------------------------------
  156. //
  157. // Code to support native C++ exceptions in user & kernel start here.
  158. // Macros to support C++ exceptions flllow below. Native C++ exception
  159. // support is used if NATIVE_EH is defined.
  160. //
  161. //----------------------------------------------------------------------------
  162. //----------------------------------------------------------------------------
  163. #if defined(NATIVE_EH)
  164. void _cdecl SystemExceptionTranslator( unsigned int uiWhat,
  165. struct _EXCEPTION_POINTERS * pexcept );
  166. #define TRANSLATE_EXCEPTIONS _se_translator_function __tf = _set_se_translator( SystemExceptionTranslator );
  167. #define UNTRANSLATE_EXCEPTIONS _set_se_translator( __tf );
  168. class CTranslateSystemExceptions
  169. {
  170. public:
  171. CTranslateSystemExceptions()
  172. {
  173. _tf = _set_se_translator( SystemExceptionTranslator );
  174. }
  175. ~CTranslateSystemExceptions()
  176. {
  177. _set_se_translator( _tf );
  178. }
  179. private:
  180. _se_translator_function _tf;
  181. };
  182. class CException
  183. {
  184. public:
  185. CException(long lError) : _lError(lError), _dbgInfo(0) {}
  186. CException();
  187. long GetErrorCode() { return _lError;}
  188. void SetInfo(unsigned dbgInfo) { _dbgInfo = dbgInfo; }
  189. unsigned long GetInfo(void) const { return _dbgInfo; }
  190. protected:
  191. long _lError;
  192. unsigned long _dbgInfo;
  193. };
  194. //+---------------------------------------------------------------------------
  195. //
  196. // Class: CCiNullClass
  197. //
  198. // Purpose: An empty class to satisfy the macros.
  199. //
  200. //----------------------------------------------------------------------------
  201. class CCiNullClass
  202. {
  203. };
  204. EXPORTIMP SCODE APINOT GetOleError(CException & e);
  205. EXPORTIMP SCODE APINOT GetScodeError(CException & e);
  206. #define INHERIT_UNWIND public CCiNullClass
  207. #define INHERIT_VIRTUAL_UNWIND public CCiNullClass
  208. #define DECLARE_UNWIND
  209. #define IMPLEMENT_UNWIND(class)
  210. #define END_CONSTRUCTION(class)
  211. #define INLINE_UNWIND(class)
  212. #define INLINE_TEMPL_UNWIND(class1, class2)
  213. #undef try
  214. #undef catch
  215. #define TRY try
  216. # if DBG == 1 || CIDBG == 1
  217. //+---------------------------------------------------------------------------
  218. //
  219. // Macro: THROW - throw a CException
  220. // QUIETTHROW - throws a CException without an exception report
  221. //
  222. // Synopsis: Throws an exception
  223. // debug, kernel & user
  224. //
  225. // History: 29-Mar-95 DwightKr Created.
  226. //
  227. //----------------------------------------------------------------------------
  228. template<class T> inline void doThrowTempl ( unsigned int iLine,
  229. char * pszFile,
  230. int fVerbose,
  231. T & e )
  232. {
  233. if ( fVerbose )
  234. e.SetInfo( GetWin4ExceptionLevel() | EXCEPT_VERBOSE );
  235. else
  236. e.SetInfo( GetWin4ExceptionLevel() & ~EXCEPT_VERBOSE );
  237. if ( e.GetInfo() & EXCEPT_VERBOSE)
  238. ExceptionReport( iLine, pszFile, "Throwing Exception",
  239. e.GetErrorCode() );
  240. throw e;
  241. }
  242. #define THROW( e ) \
  243. { \
  244. doThrowTempl( __LINE__, \
  245. __FILE__, \
  246. 1, \
  247. e ); \
  248. }
  249. #define QUIETTHROW( e ) \
  250. { \
  251. doThrowTempl( __LINE__, \
  252. __FILE__, \
  253. 0, \
  254. e ); \
  255. }
  256. //+---------------------------------------------------------------------------
  257. //
  258. // Macro: RETHROW
  259. //
  260. // Synopsis: Rethrows an exception
  261. // debug, kernel & user
  262. //
  263. // History: 29-Mar-95 DwightKr Created.
  264. //
  265. //----------------------------------------------------------------------------
  266. #define RETHROW() \
  267. { \
  268. if ( e.GetInfo() & EXCEPT_VERBOSE ) \
  269. ExceptionReport( __LINE__, \
  270. __FILE__, \
  271. "Rethrowing Exception", \
  272. e.GetErrorCode() ); \
  273. throw; \
  274. }
  275. //+---------------------------------------------------------------------------
  276. //
  277. // Macro: CATCH
  278. //
  279. // Synopsis: catches an exception
  280. // debug, kernel & user
  281. //
  282. // History: 29-Mar-95 DwightKr Created.
  283. //
  284. //----------------------------------------------------------------------------
  285. #define CATCH(class,e) catch( class & e ) \
  286. { \
  287. if ( e.GetInfo() & EXCEPT_VERBOSE) \
  288. ExceptionReport( __LINE__, \
  289. __FILE__, \
  290. "Catching Exception", \
  291. e.GetErrorCode() );
  292. //+---------------------------------------------------------------------------
  293. //
  294. // Macro: AND_CATCH
  295. //
  296. // Synopsis: catches an exception
  297. // debug, kernel & user
  298. //
  299. // History: 29-Mar-95 DwightKr Created.
  300. //
  301. //----------------------------------------------------------------------------
  302. #define AND_CATCH(class,e) } CATCH(class, e)
  303. //+---------------------------------------------------------------------------
  304. //
  305. // Macro: END_CATCH
  306. //
  307. // Synopsis: end of a try\catch block
  308. // debug, user & kernel
  309. //
  310. // History: 29-Mar-95 DwightKr Created.
  311. //
  312. //----------------------------------------------------------------------------
  313. #define END_CATCH }
  314. # else // DBG == 0 && CIDBG == 0
  315. //+---------------------------------------------------------------------------
  316. //
  317. // Macro: THROW
  318. //
  319. // Synopsis: Throws an exception
  320. // retail, user & kernel
  321. //
  322. // History: 29-Mar-95 DwightKr Created.
  323. //
  324. //----------------------------------------------------------------------------
  325. # define THROW(e) \
  326. throw e;
  327. //+---------------------------------------------------------------------------
  328. //
  329. // Macro: QUIETTHROW
  330. //
  331. // Synopsis: Throws an exception
  332. // retail, user & kernel
  333. //
  334. // History: 29-Mar-95 DwightKr Created.
  335. //
  336. //----------------------------------------------------------------------------
  337. # define QUIETTHROW(e) \
  338. throw e;
  339. //+---------------------------------------------------------------------------
  340. //
  341. // Macro: RETHROW
  342. //
  343. // Synopsis: Rethrows an exception
  344. // retail, user & kernel
  345. //
  346. // History: 29-Mar-95 DwightKr Created.
  347. //
  348. //----------------------------------------------------------------------------
  349. # define RETHROW() \
  350. throw;
  351. //+---------------------------------------------------------------------------
  352. //
  353. // Macro: CATCH
  354. //
  355. // Synopsis: catches an exception
  356. // retail, user & kernel
  357. //
  358. // History: 29-Mar-95 DwightKr Created.
  359. //
  360. //----------------------------------------------------------------------------
  361. #define CATCH(class,e) catch( class & e )
  362. //+---------------------------------------------------------------------------
  363. //
  364. // Macro: AND_CATCH
  365. //
  366. // Synopsis: catches an exception
  367. // retail, user & kernel
  368. //
  369. // History: 29-Mar-95 DwightKr Created.
  370. //
  371. //----------------------------------------------------------------------------
  372. #define AND_CATCH(class,e) catch( class & e )
  373. //+---------------------------------------------------------------------------
  374. //
  375. // Macro: CATCH_ALL
  376. //
  377. // Synopsis: catches all exceptions
  378. // retail, user & kernel
  379. //
  380. // History: 29-Mar-95 DwightKr Created.
  381. //
  382. //----------------------------------------------------------------------------
  383. #define CATCH_ALL catch( ... )
  384. //+---------------------------------------------------------------------------
  385. //
  386. // Macro: END_CATCH
  387. //
  388. // Synopsis: end of a try\catch block
  389. // retail, user & kernel
  390. //
  391. // History: 29-Mar-95 DwightKr Created.
  392. //
  393. //----------------------------------------------------------------------------
  394. #define END_CATCH
  395. # endif // DBG == 0 && CIDBG == 0
  396. #else // #if defined(NATIVE_EH)
  397. #define TRANSLATE_EXCEPTIONS
  398. #define UNTRANSLATE_EXCEPTIONS
  399. //------------------------------------------------------------------
  400. //------------------------------------------------------------------
  401. //
  402. // Support for compilers which do NOT support native C++ exceptions
  403. // exists after this point.
  404. //
  405. //------------------------------------------------------------------
  406. //------------------------------------------------------------------
  407. #define EXCEPT_VULCAN 0xE0000001
  408. typedef void(*PFV)();
  409. extern void terminate();
  410. extern void unexpected();
  411. extern PFV set_terminate(PFV terminate_fn);
  412. extern PFV set_unexpected(PFV unexpected_fn);
  413. //+---------------------------------------------------------------------------
  414. //
  415. // Class: CException
  416. //
  417. // Purpose: All exception objects (e.g. objects that are THROW)
  418. // inherit from CException.
  419. //
  420. // Interface: ~CException - Destructor
  421. // IsKindOf - Class membership query
  422. //
  423. // History: 22-May-91 KyleP Created.
  424. //
  425. // Notes: This class is a hack, until C7 can provide some support
  426. // for runtime inheritance detection (e.g. a way to generate
  427. // a mangled name). When we get this support a new
  428. // implementation of IsKindOf should be developed. The concept,
  429. // however, would remain the same: C++ exception objects are
  430. // instances of an exception class, but they are caught by class.
  431. //
  432. // A compiler can implement IsKindOf by throwing a
  433. // decorated name which uniquely identifies a class and
  434. // describes its inheritance.
  435. //
  436. // Don't do anything too fancy with subclasses of CException.
  437. // Instances of your subclass are memcpy-ed around. Having
  438. // a user defined destructor, for example, is probably a bad
  439. // idea.
  440. //
  441. // WARNING: There is an implemtation of this class in the C-runtime
  442. // package. Don't add functions to this class as they will not
  443. // exist in the native C++ support. This class exists to
  444. // support those C++ compilers which do not support native C++
  445. // exceptions.
  446. //
  447. //----------------------------------------------------------------------------
  448. class CException
  449. {
  450. public:
  451. EXPORTDEF CException(long lError);
  452. CException();
  453. long GetErrorCode() { return _lError;}
  454. EXPORTDEF virtual int WINAPI IsKindOf(const char * szClass) const;
  455. void SetInfo(unsigned dbgInfo) { _dbgInfo = dbgInfo; }
  456. unsigned long GetInfo(void) const { return _dbgInfo; }
  457. #if DBG == 1 || CIDBG == 1
  458. EXPORTDEF virtual void WINAPI Report(unsigned int iLine,char *szFile,char *szMsg);
  459. #endif // DBG == 1 || CIDBG == 1
  460. protected:
  461. long _lError;
  462. unsigned long _dbgInfo;
  463. };
  464. //+---------------------------------------------------------------------------
  465. //
  466. // Class: CExceptionContext
  467. //
  468. // Purpose: Per-thread exception state and throw exception methods.
  469. //
  470. // Interface: CExceptionContext -- Constructor
  471. // ~CExceptionContext -- Destructor
  472. // Push -- Push a new element on the stack of
  473. // elements-to-be-destroyed.
  474. // Pop -- Pop an an element off the stack.
  475. // SetTop -- Set the top of stack to the specified
  476. // element.
  477. // GetTop -- Return the top element.
  478. // Throw -- Throw an exception
  479. //
  480. // History: 19-Nov-91 KyleP Fix heap unwind, multiple inheritance
  481. // 22-May-91 KyleP Created.
  482. //
  483. // Notes: There is only 1 CExceptionContext object per thread.
  484. //
  485. //----------------------------------------------------------------------------
  486. class CTry;
  487. class CExceptionContextPool;
  488. class CExceptionContext
  489. {
  490. public:
  491. CExceptionContext();
  492. ~CExceptionContext();
  493. EXPORTDEF void WINAPI Reserve(void * pthis);
  494. inline void Pop(void * pthis);
  495. EXPORTDEF void WINAPI SetTop(void * pthis,
  496. ULONG cbElement,
  497. void (* pfn)(void *));
  498. inline int GetTop();
  499. void Unwind( CTry * ptry );
  500. //
  501. // _pTopTry contains the head of a linked list of CTry objects,
  502. // each of which corresponds to a TRY clause.
  503. //
  504. CTry * _pTopTry;
  505. //
  506. // _pLastNew records the address of the most recent free
  507. // store allocation, _cbLastNew the size.
  508. //
  509. BYTE * _pLastNew;
  510. int _cbLastNew;
  511. int _fNewReadyForUnwind;
  512. //
  513. // _exception contains a pointer to the current exception,
  514. // if any. The character buffer following it is for storing
  515. // additional data belonging to subclasses.
  516. //
  517. CException _exception;
  518. char buffer[maxExceptionSize];
  519. private:
  520. //
  521. // Each StackElement contains enough information to destroy a
  522. // completly constructed object, and the determine whether
  523. // objects which have not yet been fully constructed were
  524. // allocated on the heap or the stack.
  525. //
  526. class StackElement
  527. {
  528. public:
  529. BOOL IsThisEqual( void * pthis ) { return( pthis == _pthis ); }
  530. BOOL IsSizeEqual( ULONG cb ) { return( cb == _cbElement ); }
  531. BOOL IsOnStack() { return( _cbElement == 0 ); }
  532. BOOL IsOnHeap() { return( _cbElement != 0 ); }
  533. BOOL IsActive() { return( _pfn != 0 ); }
  534. void SetOnStack() { _cbElement = 0; }
  535. void SetOnHeap( ULONG size ) { _cbElement = size; }
  536. void SetThis( void * pthis ) { _pthis = pthis; }
  537. void SetDtor( void (* pfn)(void *) ) { _pfn = pfn; }
  538. void * GetDtor() { return( _pfn ); }
  539. void * GetThis() { return( _pthis ); }
  540. void Destroy() { _pfn( (BYTE *)_pthis ); }
  541. void Delete() { delete (BYTE *)_pthis; }
  542. private:
  543. void * _pthis; // This for CUnwindable
  544. void (* _pfn)(void *); // 'Static destructor'
  545. ULONG _cbElement; // 0 == On stack. > 0 = Size of class
  546. };
  547. //
  548. // _aStack is the stack of objects-to-be-destroyed in the face
  549. // of an exception (stack unwind).
  550. //
  551. StackElement * _aStack;
  552. //
  553. // _StackTop is the index of the first free element on the stack.
  554. //
  555. int _StackTop;
  556. //
  557. // _StackSize is the maximum number of elements which can be
  558. // stored on the stack.
  559. //
  560. int _StackSize;
  561. EXPORTDEF void APINOT _Grow();
  562. };
  563. //+---------------------------------------------------------------------------
  564. //
  565. // Member: CExceptionContext::Pop, public
  566. //
  567. // Synopsis: Pops the top element off the stack of objects to be destroyed.
  568. //
  569. // Effects: Pop only has an effect if the top element on the stack
  570. // is for [pthis].
  571. //
  572. // Arguments: [pthis] -- Must correspond to the top of stack if the
  573. // element is to be popped.
  574. //
  575. // History: 22-May-91 KyleP Created.
  576. //
  577. //----------------------------------------------------------------------------
  578. inline void CExceptionContext::Pop(void * pthis)
  579. {
  580. //
  581. // Remove the top of stack only if it corresponds to pthis.
  582. // Thus the element will be removed only if this object was
  583. // declared on the stack (as opposed to embedded) and no
  584. // exception was encountered.
  585. //
  586. //
  587. // You should *always* find what you're looking for. No checking
  588. // for runoff. The very bottom element of the stack is a sentinel
  589. // for the case of heap objects which have been fully removed from
  590. // the stack.
  591. //
  592. exAssert( _StackTop > 0 );
  593. if ( _aStack[_StackTop-1].IsThisEqual( pthis ) )
  594. {
  595. //
  596. // The following assertion is hit if an unwindable object
  597. // is destroyed without END_CONSTRUCTION being called.
  598. //
  599. exAssert( _aStack[_StackTop-1].IsActive() );
  600. _StackTop--;
  601. #if DBG == 1 || CIDBG == 1
  602. exDebugOut(( DEB_ITRACE, "POP %lx %lx( %lx )\n",
  603. _StackTop,
  604. _aStack[_StackTop].GetDtor(),
  605. _aStack[_StackTop].GetThis() ));
  606. #endif // DBG || CIDBG == 1
  607. }
  608. }
  609. //+---------------------------------------------------------------------------
  610. //
  611. // Member: CExceptionContext::GetTop, public
  612. //
  613. // Returns: The index of the top of the stack of objects to be
  614. // destroyed. This is the first available element.
  615. //
  616. // History: 22-May-91 KyleP Created.
  617. //
  618. //----------------------------------------------------------------------------
  619. inline int CExceptionContext::GetTop()
  620. {
  621. return(_StackTop);
  622. }
  623. EXPORTDEF CExceptionContext& APINOT _ExceptionContext(void);
  624. EXPORTIMP SCODE APINOT GetOleError(CException & e);
  625. EXPORTIMP SCODE APINOT GetScodeError(CException & e);
  626. //+---------------------------------------------------------------------------
  627. //
  628. // Class: CUnwindable, CVirtualUnwindable
  629. //
  630. // Purpose: Per-object exception state and registration/unwind methods.
  631. //
  632. // Interface: CUnwindable -- Constructor
  633. // ~CUnwindable -- Destructor
  634. // _Activate -- Activate object.
  635. //
  636. // History: 22-May-91 KyleP Created.
  637. // 13-Nov-92 KyleP Added virtual version
  638. //
  639. // Notes: CVirtualUnwindable should be used if and only if a
  640. // derived class has some other virtual method.
  641. //
  642. //----------------------------------------------------------------------------
  643. class CUnwindable
  644. {
  645. public:
  646. inline CUnwindable();
  647. inline ~CUnwindable();
  648. inline void _Activate( ULONG cbElement,
  649. void (* pfn)(void *) );
  650. };
  651. class CVirtualUnwindable
  652. {
  653. public:
  654. inline CVirtualUnwindable();
  655. virtual ~CVirtualUnwindable();
  656. inline void _Activate( ULONG cbElement,
  657. void (* pfn)(void *) );
  658. };
  659. //+---------------------------------------------------------------------------
  660. //
  661. // Member: CUnwindable::CUnwindable, public
  662. //
  663. // Synopsis: Initializes the link field of the object.
  664. //
  665. // Effects: Essentially sets up enough state to remember the position
  666. // of the object which inherits from CUnwindable
  667. // within the stack of objects-to-be-destroyed.
  668. //
  669. // History: 22-May-91 KyleP Created.
  670. //
  671. // Notes: This call does not fully link the object into the chain
  672. // of objects to be destroyed. See _Activate.
  673. //
  674. //----------------------------------------------------------------------------
  675. inline CUnwindable::CUnwindable()
  676. {
  677. //
  678. // Initialize by allocating a record on the deletion stack.
  679. //
  680. _ExceptionContext().Reserve(this);
  681. }
  682. inline CVirtualUnwindable::CVirtualUnwindable()
  683. {
  684. //
  685. // Initialize by allocating a record on the deletion stack.
  686. //
  687. _ExceptionContext().Reserve(this);
  688. }
  689. //+---------------------------------------------------------------------------
  690. //
  691. // Member: CUnwindable::~CUnwindable, public
  692. //
  693. // Synopsis: Removes this object from the stack of objects to be destroyed.
  694. //
  695. // Modifies: Per/thread exception context.
  696. //
  697. // History: 22-May-91 KyleP Created.
  698. //
  699. //----------------------------------------------------------------------------
  700. inline CUnwindable::~CUnwindable()
  701. {
  702. _ExceptionContext().Pop(this);
  703. }
  704. inline CVirtualUnwindable::~CVirtualUnwindable()
  705. {
  706. _ExceptionContext().Pop(this);
  707. }
  708. //+---------------------------------------------------------------------------
  709. //
  710. // Member: CUnwindable::_Activate, public
  711. //
  712. // Synopsis: Fully link object into stack of objects to be destroyed.
  713. //
  714. // Effects: After this call, the object which inherits from
  715. // CUnwindable will be destroyed during unwind.
  716. //
  717. // If the object was declared on the heap, then it is
  718. // removed completely from the stack of objects that will
  719. // be destroyed during unwind.
  720. //
  721. // Arguments: [prealthis] -- This pointer of instance. Will differ
  722. // from this pointer of CUnwindable
  723. // if instance has a virtual method.
  724. // [cbElement] -- Size of the instance being activated. If
  725. // an element is declared on the heap and
  726. // [cbElement] is smaller than the allocation
  727. // then the element won't be deleted.
  728. //
  729. // [pfn] -- Pointer to a static destructor. [pfn] takes a
  730. // this pointer.
  731. //
  732. // Modifies: This object is now the top of the stack of objects that
  733. // will be destroyed (_exceptioncontext is modified).
  734. //
  735. // History: 22-May-91 KyleP Created.
  736. //
  737. //----------------------------------------------------------------------------
  738. inline void CUnwindable::_Activate(
  739. ULONG cbElement,
  740. void (* pfn)(void *))
  741. {
  742. _ExceptionContext().SetTop(this, cbElement, pfn);
  743. }
  744. inline void CVirtualUnwindable::_Activate(
  745. ULONG cbElement,
  746. void (* pfn)(void *))
  747. {
  748. _ExceptionContext().SetTop(this, cbElement, pfn);
  749. }
  750. //+---------------------------------------------------------------------------
  751. //
  752. // Class: CTry
  753. //
  754. // Purpose: Containt per/TRY state.
  755. //
  756. // Interface: ~CTry - Destructor
  757. // TryIt - Setup to run the TRY body.
  758. //
  759. // History: 22-May-91 KyleP Created.
  760. //
  761. //----------------------------------------------------------------------------
  762. class CTry
  763. {
  764. public:
  765. inline CTry();
  766. inline ~CTry();
  767. //
  768. // _pPrevTry is a link to the enclosing TRY clause.
  769. //
  770. CTry * _pPrevTry;
  771. //
  772. // _StackTop was the top of the stack of objects-to-be-destroyed
  773. // when the TRY clause was entered.
  774. //
  775. int _StackTop;
  776. };
  777. //+---------------------------------------------------------------------------
  778. //
  779. // Member: CTry::~CTry, public
  780. //
  781. // Synopsis: Unlinks the TRY ... CATCH from the per/thread list.
  782. //
  783. // Modifies: The per/thread list of try clauses in _exceptioncontext.
  784. //
  785. // History: 22-May-91 KyleP Created.
  786. //
  787. //----------------------------------------------------------------------------
  788. inline CTry::~CTry()
  789. {
  790. exDebugOut(( DEB_ITRACE, "END TRY %lx (%lx)\n", _StackTop, this ));
  791. //
  792. // The destructor for CTry is called only during normal (no
  793. // exception) exit from the TRY ... CATCH or when an
  794. // exception was successfully caught in this block.
  795. // In these cases we want to unlink this CTry.
  796. //
  797. // Note that we could delete _exceptioncontext._TheException
  798. // here, which may be non-null if we caught an exception in
  799. // this TRY ... CATCH block. But why bother? That would add
  800. // additional code to the normal case. The last exception
  801. // can wait to be deleted until the next occurs.
  802. //
  803. _ExceptionContext()._pTopTry = _pPrevTry;
  804. }
  805. //+---------------------------------------------------------------------------
  806. //
  807. // Member: CTry::CTry, public
  808. //
  809. // Synopsis: Set up to run the body of a TRY ... CATCH clause.
  810. //
  811. // Effects: Links this CTry into the chain of TRY clauses.
  812. //
  813. // History: 22-May-91 KyleP Created.
  814. //
  815. //----------------------------------------------------------------------------
  816. inline CTry::CTry()
  817. {
  818. CExceptionContext& _exceptioncontext = _ExceptionContext();
  819. _pPrevTry = _exceptioncontext._pTopTry;
  820. _exceptioncontext._pTopTry = this;
  821. _StackTop = _exceptioncontext.GetTop();
  822. exDebugOut(( DEB_ITRACE, "TRY %lx (%lx)\n", _StackTop, this ));
  823. }
  824. //+---------------------------------------------------------------------------
  825. //
  826. // The following macros implement a TRY ... CATCH syntax similar
  827. // to that in C++. They are used as follows:
  828. //
  829. // TRY
  830. // {
  831. // // Body of try goes here...
  832. // }
  833. // CATCH(exclass, e)
  834. // {
  835. // // We get here when an exception of class exclass has
  836. // // been thrown. The variable e is declared as * exclass.
  837. // }
  838. // AND_CATCH(exclass, e)
  839. // {
  840. // // Just like CATCH. Any number of AND_CATCH can follow
  841. // // CATCH. Handlers are tried in order of appearance.
  842. // }
  843. // END_CATCH
  844. //
  845. // To throw an exception, use the THROW macro -- THROW(exclass). To
  846. // re-throw the same exception from within a catch clause use
  847. // RETHROW(). Note that RETHROW() is only valid in a CATCH/AND_CATCH.
  848. //
  849. // History: 22-May-91 KyleP Created Interface.
  850. // 15-Aug-91 SethuR modified THROW,CATCH,AND_CATCH,END_CATCH
  851. // macros
  852. // 18-Oct-91 KyleP Win32 try/except implementation
  853. //
  854. //----------------------------------------------------------------------------
  855. extern EXPORTDEF void APINOT ThrowDebugException(unsigned int iLine,
  856. char * szFile,
  857. CException & ecE );
  858. extern EXPORTDEF void APINOT ThrowException(CException & ecE,
  859. unsigned dummy);
  860. #if DBG == 1 || CIDBG == 1// +++++++++++++++++++++++++++++++++++++++++++++++
  861. //+---------------------------------------------------------------------------
  862. //
  863. // Macro: THROW
  864. //
  865. // Synopsis: Throws an exception
  866. // debug
  867. //
  868. // History: 22-May-91 KyleP Created.
  869. //
  870. //----------------------------------------------------------------------------
  871. # define THROW(e) \
  872. { \
  873. e.SetInfo( GetWin4ExceptionLevel() | EXCEPT_VERBOSE); \
  874. ThrowDebugException( __LINE__, __FILE__, e); \
  875. }
  876. //+---------------------------------------------------------------------------
  877. //
  878. // Macro: QUIETTHROW
  879. //
  880. // Synopsis: Throws a quiet exception
  881. // debug
  882. //
  883. // History: 29-Mar-95 DwightKr Created.
  884. //
  885. //----------------------------------------------------------------------------
  886. #define QUIETTHROW(e) \
  887. { \
  888. e.SetInfo( GetWin4ExceptionLevel() ); \
  889. ThrowDebugException( __LINE__, __FILE__, e); \
  890. }
  891. #else // DBG == 0 && CIDBG == 0 ++++++++++++++++++++++++++++++++++++++++++++
  892. //+---------------------------------------------------------------------------
  893. //
  894. // Macro: THROW
  895. //
  896. // Synopsis: Throws an exception
  897. // retail
  898. //
  899. // History: 22-May-91 KyleP Created.
  900. //
  901. //----------------------------------------------------------------------------
  902. # define THROW(e) \
  903. { \
  904. ThrowException(e, 1); \
  905. }
  906. //+---------------------------------------------------------------------------
  907. //
  908. // Macro: QUIETTHROW
  909. //
  910. // Synopsis: Throws a quiet exception
  911. // retail
  912. //
  913. // History: 29-Mar-95 DwightKr Created.
  914. //
  915. //----------------------------------------------------------------------------
  916. #define QUIETTHROW(e) THROW(e)
  917. #endif // DBG == 0 && CIDBG == 0 ++++++++++++++++++++++++++++++++++++++++++++
  918. # if DBG == 1 || CIDBG == 1// +++++++++++++++++++++++++++++++++++++++++++++++
  919. //+---------------------------------------------------------------------------
  920. //
  921. // Macro: RETHROW
  922. //
  923. // Synopsis: Rethrows an exception
  924. // debug, user
  925. //
  926. // History: 22-May-91 KyleP Created.
  927. //
  928. //----------------------------------------------------------------------------
  929. # define RETHROW() \
  930. { \
  931. if ( ((class CException &)_exceptioncontext._exception).GetInfo() & EXCEPT_VERBOSE ) \
  932. ExceptionReport(__LINE__,__FILE__,"Rethrowing Exception"); \
  933. RaiseException( EXCEPT_VULCAN, 0, 0, 0 ); \
  934. }
  935. #else // DBG == 0 && CIDBG == 0 ++++++++++++++++++++++++++++++++++++++++++++
  936. //+---------------------------------------------------------------------------
  937. //
  938. // Macro: RETHROW
  939. //
  940. // Synopsis: Rethrows an exception
  941. // retail, user
  942. //
  943. // History: 22-May-91 KyleP Created.
  944. //
  945. //----------------------------------------------------------------------------
  946. # define RETHROW() \
  947. RaiseException( EXCEPT_VULCAN, 0, 0, 0 );
  948. #endif // DBG == 0 && CIDBG == 0 ++++++++++++++++++++++++++++++++++++++++++++
  949. //+---------------------------------------------------------------------------
  950. //
  951. // Macro: TRY
  952. //
  953. // Synopsis: Begin TRY block
  954. //
  955. // History: 22-May-91 KyleP Created.
  956. //
  957. //----------------------------------------------------------------------------
  958. #define TRY \
  959. { \
  960. CTry _trycontext; \
  961. __try
  962. EXPORTDEF ULONG APINOT Unwind( struct _EXCEPTION_POINTERS * pdisp,
  963. CTry * ptry );
  964. #if DBG == 1 || CIDBG == 1 // +++++++++++++++++++++++++++++++++++++++++++++++
  965. //+---------------------------------------------------------------------------
  966. //
  967. // Macro: CATCH
  968. //
  969. // Synopsis: Begin CATCH block
  970. // debug
  971. //
  972. // History: 22-May-91 KyleP Created.
  973. //
  974. //----------------------------------------------------------------------------
  975. #define CATCH(class, e) \
  976. __except( Unwind( GetExceptionInformation(), &_trycontext ) ) \
  977. { \
  978. CExceptionContext& _exceptioncontext = _ExceptionContext(); \
  979. if (_exceptioncontext._exception.IsKindOf(#class)) \
  980. { \
  981. class & e = (class &)_exceptioncontext._exception; \
  982. if ( e.GetInfo() & EXCEPT_VERBOSE ) \
  983. e.Report( __LINE__, \
  984. __FILE__, \
  985. "Catching Exception");
  986. //+---------------------------------------------------------------------------
  987. //
  988. // Macro: AND_CATCH
  989. //
  990. // Synopsis: Begin another CATCH block
  991. // debug
  992. //
  993. // History: 22-May-91 KyleP Created.
  994. //
  995. //----------------------------------------------------------------------------
  996. #define AND_CATCH(class, e) \
  997. } \
  998. else if ( _exceptioncontext._exception.IsKindOf(#class) ) \
  999. { \
  1000. class & e = (class &)_exceptioncontext._exception; \
  1001. if ( e.GetInfo() & EXCEPT_VERBOSE ) \
  1002. e.Report( __LINE__, \
  1003. __FILE__, \
  1004. "Catching Exception");
  1005. #else // DBG == 0 ++++++++++++++++++++++++++++++++++++++++++++
  1006. //+---------------------------------------------------------------------------
  1007. //
  1008. // Macro: CATCH
  1009. //
  1010. // Synopsis: Begin CATCH block
  1011. // retail
  1012. //
  1013. // History: 22-May-91 KyleP Created.
  1014. //
  1015. //----------------------------------------------------------------------------
  1016. #define CATCH(class, e) \
  1017. __except( Unwind( GetExceptionInformation(), &_trycontext ) ) \
  1018. { \
  1019. CExceptionContext& _exceptioncontext = _ExceptionContext(); \
  1020. if (_exceptioncontext._exception.IsKindOf(#class)) \
  1021. { \
  1022. class & e = (class &)_exceptioncontext._exception;
  1023. //+---------------------------------------------------------------------------
  1024. //
  1025. // Macro: AND_CATCH
  1026. //
  1027. // Synopsis: Begin another CATCH block
  1028. // retail
  1029. //
  1030. // History: 22-May-91 KyleP Created.
  1031. //
  1032. //----------------------------------------------------------------------------
  1033. #define AND_CATCH(class, e) \
  1034. } \
  1035. else if (_exceptioncontext._exception.IsKindOf(#class)) \
  1036. { \
  1037. class & e = ( class &)_exceptioncontext._exception;
  1038. #endif // DBG == 0 +++++++++++++++++++++++++++++++++++++++++++
  1039. //+---------------------------------------------------------------------------
  1040. //
  1041. // Macro: END_CATCH
  1042. //
  1043. // Synopsis: End of CATCH block
  1044. //
  1045. // History: 22-May-91 KyleP Created.
  1046. //
  1047. //----------------------------------------------------------------------------
  1048. #define END_CATCH \
  1049. } \
  1050. else \
  1051. { \
  1052. RETHROW(); \
  1053. } \
  1054. } \
  1055. }
  1056. //+---------------------------------------------------------------------------
  1057. //
  1058. // The following macros prepare a class for stack unwinding. Any class
  1059. // with a destructor should be prepared to deal with stack unwind.
  1060. // The macros are used as follows:
  1061. //
  1062. // First, in the .hxx file...
  1063. //
  1064. // class CClassWithADestructor : INHERIT_UNWIND // , other inheritance
  1065. // {
  1066. // DECLARE_UNWIND
  1067. //
  1068. // //
  1069. // // The rest of the class declaration goes here...
  1070. // //
  1071. // }
  1072. //
  1073. // And then in the .cxx file...
  1074. //
  1075. // IMPLEMENT_UNWIND(CClassWithADestructor)
  1076. //
  1077. // CClassWithADestructor::CClassWithADestructor(...)
  1078. // {
  1079. // //
  1080. // // User construction activity.
  1081. // //
  1082. //
  1083. // //
  1084. // // The following should precede every return from the
  1085. // // constructor.
  1086. // //
  1087. //
  1088. // END_CONSTRUCTION(CClassWithADestructor)
  1089. // }
  1090. //
  1091. // INHERIT_UNWIND must be the first inheritance.
  1092. //
  1093. // For further levels of inheritance, you do not need to inherit from
  1094. // INHERIT_UNWIND (more to the point, you can't). The other macros
  1095. // must be used for all levels.
  1096. //
  1097. // INHERIT_VIRTUAL_UNWIND must be used in place of INHERIT_UNWIND on a class
  1098. // that contains virtual methods. If INHERIT_VIRTUAL_UNWIND also fails,
  1099. // then find me (KyleP) and I'll try to figure out what went wrong.
  1100. //
  1101. // Multiple inheritance is untested. It may work, or it may not. If you
  1102. // really need multiple inheritance see me (KyleP).
  1103. //
  1104. // History: 19-Nov-91 KyleP Added multiple-inheritance support
  1105. // 22-May-91 KyleP Created Interface.
  1106. // 13-Nov-92 KyleP Added support for classes with virtual
  1107. // methods.
  1108. //
  1109. //----------------------------------------------------------------------------
  1110. //+---------------------------------------------------------------------------
  1111. //
  1112. // Macro: INHERIT_UNWIND
  1113. //
  1114. // Synopsis: Inherit unwindable behavior
  1115. // class DOES NOT contain virtual functions
  1116. //
  1117. // History: 22-May-91 KyleP Created.
  1118. //
  1119. //----------------------------------------------------------------------------
  1120. #define INHERIT_UNWIND \
  1121. \
  1122. public CUnwindable
  1123. //+---------------------------------------------------------------------------
  1124. //
  1125. // Macro: INHERIT_VIRTUAL_UNWIND
  1126. //
  1127. // Synopsis: Inherit unwindable behavior
  1128. // class contains virtual functions
  1129. //
  1130. // History: 22-May-91 KyleP Created.
  1131. //
  1132. //----------------------------------------------------------------------------
  1133. #define INHERIT_VIRTUAL_UNWIND \
  1134. \
  1135. public CVirtualUnwindable
  1136. //+---------------------------------------------------------------------------
  1137. //
  1138. // Macro: INLINE_UNWIND
  1139. //
  1140. // Synopsis: Defines inline static destructor
  1141. //
  1142. // History: 22-May-91 KyleP Created.
  1143. //
  1144. //----------------------------------------------------------------------------
  1145. #define INLINE_UNWIND(cls) \
  1146. static void _ObjectUnwind ( void * pthis ) \
  1147. { ((cls *)pthis)->cls::~cls(); };
  1148. //+---------------------------------------------------------------------------
  1149. //
  1150. // Macro: INLINE_TEMPL_UNWIND
  1151. //
  1152. // Synopsis: Defines inline static destructor, used in templates
  1153. //
  1154. // History: 22-May-91 KyleP Created.
  1155. //
  1156. //----------------------------------------------------------------------------
  1157. #define INLINE_TEMPL_UNWIND(tclass, tparam) \
  1158. static void _ObjectUnwind ( void * pthis ) \
  1159. { ((tclass<tparam> *)pthis)->~tclass(); };
  1160. //+---------------------------------------------------------------------------
  1161. //
  1162. // Macro: END_CONSTRUCTION
  1163. //
  1164. // Synopsis: Activates automatic unwinding
  1165. //
  1166. // History: 22-May-91 KyleP Created.
  1167. //
  1168. //----------------------------------------------------------------------------
  1169. #define END_CONSTRUCTION(class) \
  1170. \
  1171. _Activate( sizeof(class), &class::_ObjectUnwind );
  1172. //+---------------------------------------------------------------------------
  1173. //
  1174. // Macro: END_MULTIINHERITED_CONSTRUCTION
  1175. //
  1176. // Synopsis: Activates automatic unwinding
  1177. // for classes with multiple inheritance
  1178. //
  1179. // History: 22-May-91 KyleP Created.
  1180. //
  1181. //----------------------------------------------------------------------------
  1182. #define END_MULTINHERITED_CONSTRUCTION(class, base1) \
  1183. \
  1184. base1::_Activate(sizeof(class), &class::_ObjectUnwind);
  1185. //+---------------------------------------------------------------------------
  1186. //
  1187. // Macro: DECLARE_UNWIND
  1188. //
  1189. // Synopsis: Declares static destructor
  1190. // Obsolete!
  1191. //
  1192. // History: 22-May-91 KyleP Created.
  1193. //
  1194. //----------------------------------------------------------------------------
  1195. #define DECLARE_UNWIND \
  1196. \
  1197. static void APINOT _ObjectUnwind(void * pthis);
  1198. #if DBG == 1 || CIDBG == 1
  1199. //+---------------------------------------------------------------------------
  1200. //
  1201. // Macro: IMPLEMENT_UNWIND
  1202. //
  1203. // Synopsis: Defines static destructor
  1204. // Obsolete!
  1205. // debug
  1206. //
  1207. // History: 22-May-91 KyleP Created.
  1208. //
  1209. //----------------------------------------------------------------------------
  1210. # define IMPLEMENT_UNWIND(class) \
  1211. \
  1212. void APINOT class::_ObjectUnwind(void * pthis) \
  1213. { \
  1214. ((class *)pthis)->class::~class(); \
  1215. } \
  1216. \
  1217. struct __Check##class \
  1218. { \
  1219. __Check##class() \
  1220. { \
  1221. if ( (CUnwindable *)((class *)10) != (CUnwindable *)10 || \
  1222. (CVirtualUnwindable *) \
  1223. ((class *)10) != (CVirtualUnwindable *)10 ) \
  1224. { \
  1225. exDebugOut(( DEB_ERROR, \
  1226. "INVALID UNWINDABLE CLASS: %s.\n", \
  1227. #class )); \
  1228. } \
  1229. } \
  1230. }; \
  1231. \
  1232. __Check##class __check_except_##class;
  1233. #else // DBG == 0
  1234. //+---------------------------------------------------------------------------
  1235. //
  1236. // Macro: IMPLEMENT_UNWIND
  1237. //
  1238. // Synopsis: Defines static destructor
  1239. // Obsolete!
  1240. // retail
  1241. //
  1242. // History: 22-May-91 KyleP Created.
  1243. //
  1244. //----------------------------------------------------------------------------
  1245. # define IMPLEMENT_UNWIND(class) \
  1246. \
  1247. void APINOT class::_ObjectUnwind(void * pthis) \
  1248. { \
  1249. ((class *)pthis)->class::~class(); \
  1250. }
  1251. #endif // DBG
  1252. //
  1253. // Use to implement unwindable templates
  1254. // For intstance if you have
  1255. //
  1256. // template tclass<tparam>
  1257. //
  1258. // then use
  1259. //
  1260. // IMPLEMENT_TEMPL_UNWIND(tclass, tparam>
  1261. //
  1262. //+---------------------------------------------------------------------------
  1263. //
  1264. // Macro: IMPLEMENT_TEMPLATE_UNWIND
  1265. //
  1266. // Synopsis: Defines static destructor
  1267. // Obsolete!
  1268. //
  1269. // History: 22-May-91 KyleP Created.
  1270. //
  1271. //----------------------------------------------------------------------------
  1272. #define IMPLEMENT_TEMPL_UNWIND(tclass, tparam) \
  1273. \
  1274. void APINOT tclass<tparam>::_ObjectUnwind(void * pthis) \
  1275. { \
  1276. ((tclass<tparam> *)pthis)->~tclass(); \
  1277. }
  1278. #endif // defined(NATIVE_EH)