Leaked source code of windows server 2003
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.

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