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.

701 lines
17 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 2000 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // SmartClasses.h
  7. //
  8. // Description:
  9. // Definitions of "smart" classes used to make sure resources such as
  10. // memory and handles are deallocated or closed properly.
  11. //
  12. // Maintained By:
  13. // David Potter (DavidP) 08-SEP-1999
  14. // Vij Vasu (Vvasu) 16-SEP-1999
  15. //
  16. // Notes:
  17. // 1. These classes are functionally identical to version 3 of the
  18. // standard library's auto_ptr class. They are redefined here since this
  19. // version of auto_ptr has not yet found it's way into our build
  20. // environment.
  21. //
  22. // 2. These classes are not intended to be used as a base class. They are
  23. // meant to be space and time efficient wrappers. Using these as base
  24. // classes may require the use of virtual functions which will only make
  25. // their memory footprint larger.
  26. //
  27. //
  28. /////////////////////////////////////////////////////////////////////////////
  29. // Make sure that this header is included only once
  30. #pragma once
  31. /////////////////////////////////////////////////////////////////////////////
  32. // External Declarations
  33. /////////////////////////////////////////////////////////////////////////////
  34. /////////////////////////////////////////////////////////////////////////////
  35. // Include Files
  36. /////////////////////////////////////////////////////////////////////////////
  37. #include <unknwn.h>
  38. /////////////////////////////////////////////////////////////////////////////
  39. // Type Definitions
  40. /////////////////////////////////////////////////////////////////////////////
  41. /////////////////////////////////////////////////////////////////////////////
  42. // Constant Definitions
  43. /////////////////////////////////////////////////////////////////////////////
  44. // Store the warning state.
  45. #pragma warning( push )
  46. // Disable warning 4284. The text of the warning is below:
  47. // Return type for 'identifier::operator ->' is not a UDT or reference to a UDT.
  48. // Will produce errors if applied using infix notation
  49. #pragma warning( disable : 4284 )
  50. /////////////////////////////////////////////////////////////////////////////
  51. //++
  52. //
  53. // class CSmartResource
  54. //
  55. // Description:
  56. // Automatically releases a resource.
  57. //
  58. // Template Arguments:
  59. // t_ResourceTrait
  60. // A class that provides functions and types needed this class. For example,
  61. // this class may have a function that is used to release the resource.
  62. // It must define the type of the resource.
  63. //
  64. // Remarks:
  65. // See Note 2 in the banner comment for this module.
  66. //
  67. //--
  68. /////////////////////////////////////////////////////////////////////////////
  69. template < class t_ResourceTrait >
  70. class CSmartResource
  71. {
  72. private:
  73. //
  74. // Private Types
  75. //
  76. typedef t_ResourceTrait::ResourceType ResourceType;
  77. //
  78. // Private Data
  79. //
  80. ResourceType m_hResource;
  81. public:
  82. //
  83. // Constructors & Destructors
  84. //
  85. // Default constructor
  86. explicit CSmartResource( ResourceType hResource = t_ResourceTrait::HGetNullValue() ) throw()
  87. : m_hResource( hResource )
  88. {
  89. } //*** CSmartResource( ResourceType )
  90. // Copy constructor
  91. CSmartResource( CSmartResource & rsrSourceInout ) throw()
  92. : m_hResource( rsrSourceInout.HRelinquishOwnership() )
  93. {
  94. } //*** CSmartResource( CSmartResource & )
  95. // Destructor
  96. ~CSmartResource() throw()
  97. {
  98. CloseRoutineInternal();
  99. } //*** ~CSmartResource()
  100. //
  101. // Operators
  102. //
  103. // Assignment operator
  104. CSmartResource & operator=( CSmartResource & rsrRHSInout ) throw()
  105. {
  106. // Only perform the assignment if not assigning to self
  107. if ( &rsrRHSInout != this )
  108. {
  109. CloseRoutineInternal();
  110. m_hResource = rsrRHSInout.HRelinquishOwnership();
  111. } // if: not assigning to self
  112. return *this;
  113. } //*** operator=()
  114. // Operator to cast to underlying resource type
  115. operator ResourceType( void ) const throw()
  116. {
  117. return m_hResource;
  118. } //*** operator ResourceType()
  119. //
  120. // Lightweight Access Methods
  121. //
  122. // Get the handle to the resource
  123. ResourceType HHandle( void ) const throw()
  124. {
  125. return m_hResource;
  126. } //*** HResource()
  127. //
  128. // Class Methods
  129. //
  130. // Determine if the resource handle is valid
  131. bool FIsInvalid( void ) const throw()
  132. {
  133. return ( m_hResource == t_ResourceTrait::HGetNullValue() );
  134. } //*** FIsInvalid()
  135. // Assignment function
  136. CSmartResource & Assign( ResourceType hResource ) throw()
  137. {
  138. // Only perform the assignment if not assigning to self
  139. if ( m_hResource != hResource )
  140. {
  141. CloseRoutineInternal();
  142. m_hResource = hResource;
  143. } // if: not assigning to self
  144. return *this;
  145. } //*** Assign()
  146. // Free the resource.
  147. void Free( void ) throw()
  148. {
  149. CloseRoutineInternal();
  150. m_hResource = t_ResourceTrait::HGetNullValue();
  151. } //*** Free()
  152. // Relinquish ownership of the resouce without freeing it.
  153. ResourceType HRelinquishOwnership( void ) throw()
  154. {
  155. ResourceType hHandle = m_hResource;
  156. m_hResource = t_ResourceTrait::HGetNullValue();
  157. return hHandle;
  158. } //*** HRelinquishOwnership()
  159. private:
  160. //
  161. //
  162. // Private operators
  163. //
  164. // The address-of operator
  165. CSmartResource * operator &() throw()
  166. {
  167. return this;
  168. }
  169. //
  170. // Private Class Methods
  171. //
  172. // Check and release the resource
  173. void CloseRoutineInternal( void ) throw()
  174. {
  175. if ( m_hResource != t_ResourceTrait::HGetNullValue() )
  176. {
  177. t_ResourceTrait::CloseRoutine( m_hResource );
  178. } // if: resource handle isn't invalid
  179. } //*** CloseRoutineInternal()
  180. }; //*** class CSmartResource
  181. /////////////////////////////////////////////////////////////////////////////
  182. //++
  183. //
  184. // class CPtrTrait
  185. //
  186. // Description:
  187. // Encapsulates the traits of pointers.
  188. //
  189. // Template Arguments:
  190. // t_Ty Type of memory to be managed (e.g. BYTE or int).
  191. //
  192. // Remarks:
  193. // See Note 2 in the banner comment for this module.
  194. //
  195. //--
  196. /////////////////////////////////////////////////////////////////////////////
  197. template < class t_Ty >
  198. class CPtrTrait
  199. {
  200. public:
  201. //////////////////////////////////////////////////////////////////////////
  202. // Public types
  203. //////////////////////////////////////////////////////////////////////////
  204. typedef t_Ty * ResourceType;
  205. typedef t_Ty DataType;
  206. //////////////////////////////////////////////////////////////////////////
  207. // Public methods
  208. //////////////////////////////////////////////////////////////////////////
  209. // A routine used to release a resource.
  210. static void CloseRoutine( ResourceType hResourceIn )
  211. {
  212. delete hResourceIn;
  213. } //*** CloseRoutine()
  214. // Get the null value for this type.
  215. static ResourceType HGetNullValue()
  216. {
  217. return NULL;
  218. } //*** HGetNullValue()
  219. }; //*** class CPtrTrait
  220. /////////////////////////////////////////////////////////////////////////////
  221. //++
  222. //
  223. // class CArrayPtrTrait
  224. //
  225. // Description:
  226. // Encapsulates the traits of pointers.
  227. //
  228. // Template Arguments:
  229. // t_Ty Type of memory to be managed (e.g. BYTE or int).
  230. //
  231. // Remarks:
  232. // See Note 2 in the banner comment for this module.
  233. //
  234. //--
  235. /////////////////////////////////////////////////////////////////////////////
  236. template < class t_Ty >
  237. class CArrayPtrTrait
  238. {
  239. public:
  240. //////////////////////////////////////////////////////////////////////////
  241. // Public types
  242. //////////////////////////////////////////////////////////////////////////
  243. typedef t_Ty * ResourceType;
  244. typedef t_Ty DataType;
  245. //////////////////////////////////////////////////////////////////////////
  246. // Public methods
  247. //////////////////////////////////////////////////////////////////////////
  248. // A routine used to release a resource
  249. static void CloseRoutine( ResourceType hResourceIn )
  250. {
  251. delete [] hResourceIn;
  252. } //*** CloseRoutine()
  253. // Get the null value for this type.
  254. static ResourceType HGetNullValue()
  255. {
  256. return NULL;
  257. } //*** HGetNullValue()
  258. }; //*** class CArrayPtrTrait
  259. //////////////////////////////////////////////////////////////////////////////
  260. //++
  261. //
  262. // class CHandleTrait
  263. //
  264. // Description:
  265. // The class is a handle trait class that can be used with handles whose
  266. // close routines take only one argument.
  267. //
  268. // t_Ty
  269. // Type of handle to be managed (e.g. HWND).
  270. //
  271. // t_CloseRoutineReturnType
  272. // The return type of the routine used to close the handle.
  273. //
  274. // t_CloseRoutine
  275. // The routine used to close the handle. This function cannot throw
  276. // exceptions.
  277. //
  278. // t_hNULL_VALUE
  279. // Null handle value. Defaults to NULL.
  280. //
  281. //--
  282. //////////////////////////////////////////////////////////////////////////////
  283. template <
  284. class t_Ty
  285. , class t_CloseRoutineReturnType
  286. , t_CloseRoutineReturnType (*t_CloseRoutine)( t_Ty hHandleIn ) throw()
  287. , t_Ty t_hNULL_VALUE = NULL
  288. >
  289. class CHandleTrait
  290. {
  291. public:
  292. //////////////////////////////////////////////////////////////////////////
  293. // Public types
  294. //////////////////////////////////////////////////////////////////////////
  295. typedef t_Ty ResourceType;
  296. //////////////////////////////////////////////////////////////////////////
  297. // Public methods
  298. //////////////////////////////////////////////////////////////////////////
  299. // A routine used to close a handle.
  300. static void CloseRoutine( ResourceType hResourceIn )
  301. {
  302. t_CloseRoutine( hResourceIn );
  303. } //*** CloseRoutine()
  304. // Get the null value for this type.
  305. static ResourceType HGetNullValue()
  306. {
  307. return t_hNULL_VALUE;
  308. } //*** HGetNullValue()
  309. }; //*** class CHandleTrait
  310. /////////////////////////////////////////////////////////////////////////////
  311. //++
  312. //
  313. // class CSmartGenericPtr
  314. //
  315. // Description:
  316. // Automatically handles deallocation of memory.
  317. //
  318. // Template Arguments:
  319. // t_PtrTrait
  320. // Trait class for the memory to be managed (e.g. CPtrTrait< int > ).
  321. //
  322. // Remarks:
  323. // See Note 2 in the banner comment for this module.
  324. // It is ok for this class to derive from CSmartResource since the
  325. // derivation is private and the lack of virtual functions will
  326. // therefore not cause any problems.
  327. //
  328. //--
  329. /////////////////////////////////////////////////////////////////////////////
  330. template < class t_PtrTrait >
  331. class CSmartGenericPtr : private CSmartResource< t_PtrTrait >
  332. {
  333. private:
  334. //
  335. // Private Types
  336. //
  337. typedef CSmartResource< t_PtrTrait > BaseClass;
  338. public:
  339. //
  340. // Public Types
  341. //
  342. typedef t_PtrTrait::DataType DataType;
  343. //
  344. // Constructors & Destructors
  345. //
  346. // Default and memory pointer constructor
  347. explicit CSmartGenericPtr( DataType * pMemIn = NULL ) throw()
  348. : BaseClass( pMemIn )
  349. {
  350. } //*** CSmartGenericPtr( DataType * )
  351. // Copy constructor
  352. CSmartGenericPtr( CSmartGenericPtr & rsrSourceInout ) throw()
  353. : m_pMem( rsrSourceInout.HRelinquishOwnership() )
  354. {
  355. } //*** CSmartGenericPtr( CSmartGenericPtr & )
  356. // Destructor
  357. ~CSmartGenericPtr( void ) throw()
  358. {
  359. } //*** ~CSmartGenericPtr()
  360. //
  361. // Operators
  362. //
  363. // Assignment operator
  364. CSmartGenericPtr & operator=( CSmartGenericPtr & rapRHSInout ) throw()
  365. {
  366. return static_cast< CSmartGenericPtr & >( BaseClass::operator=( rapRHSInout ) );
  367. } //*** operator=()
  368. // Assign a pointer
  369. CSmartGenericPtr & Assign( DataType * pMemIn ) throw()
  370. {
  371. return static_cast< CSmartGenericPtr & >( BaseClass::Assign( pMemIn ) );
  372. } //*** Assign()
  373. // Pointer dereference operator*
  374. DataType & operator*( void ) const throw()
  375. {
  376. return *HHandle();
  377. } //*** operator*()
  378. // Pointer dereference operator->
  379. DataType * operator->( void ) const throw()
  380. {
  381. return HHandle();
  382. } //*** operator->()
  383. //
  384. // Lightweight Access Methods
  385. //
  386. // Get the memory pointer
  387. DataType * PMem( void ) const throw()
  388. {
  389. return HHandle();
  390. } //*** PMem()
  391. //
  392. // Class Methods
  393. //
  394. // Determine if memory pointer is valid
  395. bool FIsEmpty( void ) const throw()
  396. {
  397. return FIsInvalid();
  398. } //*** FIsEmpty()
  399. // Relinquish our ownership of the memory pointer
  400. DataType * PRelease( void ) throw()
  401. {
  402. return HRelinquishOwnership();
  403. } //*** PRelease()
  404. }; //*** class CSmartGenericPtr
  405. /////////////////////////////////////////////////////////////////////////////
  406. //++
  407. //
  408. // class CSmartIfacePtr
  409. //
  410. // Description:
  411. // Automatically calls AddRef on creation and Release on destruction.
  412. //
  413. // Template Arguments:
  414. // t_Ty Type of pointer to be managed (e.g. IUnknown *).
  415. //
  416. // Remarks:
  417. // This class does not have the destructive copy semantics. That is,
  418. // when a CSmartIfacePtr object is copied, the source is still valid.
  419. //
  420. // See Note 2 in the banner comment for this module.
  421. //
  422. //--
  423. /////////////////////////////////////////////////////////////////////////////
  424. template < class t_Ty >
  425. class CSmartIfacePtr
  426. {
  427. private:
  428. //
  429. // Private Data
  430. //
  431. t_Ty * m_pUnk;
  432. public:
  433. // Class to prevent explicit calls to AddRef() and Release
  434. class INoAddRefRelease : public t_Ty
  435. {
  436. private:
  437. virtual ULONG STDMETHODCALLTYPE AddRef() = 0;
  438. virtual ULONG STDMETHODCALLTYPE Release() = 0;
  439. };
  440. //
  441. // Constructors & Destructors
  442. //
  443. // Default and pointer constructor
  444. CSmartIfacePtr( t_Ty * pUnkIn = NULL ) throw()
  445. : m_pUnk( pUnkIn )
  446. {
  447. AddRefInternal();
  448. } //*** CSmartIfacePtr( t_Ty * )
  449. // Copy constructor
  450. CSmartIfacePtr( const CSmartIfacePtr & rsrSourceIn ) throw()
  451. : m_pUnk( rsrSourceIn.PUnk() )
  452. {
  453. AddRefInternal();
  454. } //*** CSmartIfacePtr( CSmartIfacePtr & )
  455. // Destructor
  456. ~CSmartIfacePtr( void ) throw()
  457. {
  458. ReleaseInternal();
  459. } //*** ~CSmartIfacePtr()
  460. //
  461. // Operators
  462. //
  463. // Assignment operator
  464. INoAddRefRelease & operator=( const CSmartIfacePtr & rapRHSIn ) throw()
  465. {
  466. return Assign( rapRHSIn.PUnk() );
  467. } //*** operator=()
  468. // Pointer dereference operator*
  469. INoAddRefRelease & operator*( void ) const throw()
  470. {
  471. return *( static_cast< INoAddRefRelease * >( m_pUnk ) );
  472. } //*** operator*()
  473. // Pointer dereference operator->
  474. INoAddRefRelease * operator->( void ) const throw()
  475. {
  476. return static_cast< INoAddRefRelease * >( m_pUnk );
  477. } //*** operator->()
  478. //
  479. // Lightweight Access Methods
  480. //
  481. // Get the pointer
  482. INoAddRefRelease * PUnk( void ) const throw()
  483. {
  484. return static_cast< INoAddRefRelease * >( m_pUnk );
  485. } //*** PUnk()
  486. //
  487. // Class Methods
  488. //
  489. // Assignment function.
  490. INoAddRefRelease & Assign( t_Ty * pRHSIn ) throw()
  491. {
  492. // Only perform the assignment if not assigning to self
  493. if ( pRHSIn != m_pUnk )
  494. {
  495. ReleaseInternal();
  496. m_pUnk = pRHSIn;
  497. AddRefInternal();
  498. } // if: not assigning to self
  499. return *( static_cast< INoAddRefRelease * >( m_pUnk ) );
  500. } //*** Assign()
  501. // Attach ( assign without AddRef() )
  502. void Attach( t_Ty * pRHSIn ) throw()
  503. {
  504. // Only perform the attachment if not attaching to self
  505. if ( pRHSIn != m_pUnk )
  506. {
  507. ReleaseInternal();
  508. m_pUnk = pRHSIn;
  509. } // if: not attaching to self
  510. } //*** Attach()
  511. // Release this interface pointer.
  512. void Release() throw()
  513. {
  514. ReleaseInternal();
  515. m_pUnk = NULL;
  516. }
  517. // Query punkSrc for __uuidof( m_pUnk ) and store the result.
  518. HRESULT HrQueryAndAssign( IUnknown * punkSrc ) throw()
  519. {
  520. ReleaseInternal();
  521. return punkSrc->QueryInterface< t_Ty >( &m_pUnk );
  522. } ///*** HrQueryAndAssign()
  523. // Determine if pointer is valid
  524. bool FIsEmpty( void ) const throw()
  525. {
  526. return ( m_pUnk == NULL );
  527. } //*** FIsEmpty()
  528. private:
  529. //
  530. //
  531. // Private operators
  532. //
  533. // The address-of operator
  534. CSmartIfacePtr * operator &()
  535. {
  536. return this;
  537. }
  538. //
  539. // Private Class Methods
  540. //
  541. // Increment the reference count on the pointer
  542. void AddRefInternal( void ) throw()
  543. {
  544. if ( m_pUnk != NULL )
  545. {
  546. m_pUnk->AddRef();
  547. }
  548. } //*** PRelease()
  549. // Release the pointer.
  550. // A call to this function is usually be followed by a reassignment, or else
  551. // this will object may contain an invalid pointer.
  552. void ReleaseInternal( void ) throw()
  553. {
  554. if ( m_pUnk != NULL )
  555. {
  556. m_pUnk->Release();
  557. }
  558. } //*** PRelease()
  559. }; //*** class CSmartIfacePtr
  560. // Restore the warning state.
  561. #pragma warning( pop )