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.

384 lines
11 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 1997.
  5. //
  6. // File: myhandle.hxx
  7. //
  8. // Contents: handle classes
  9. //
  10. // Classes: CAutoHandle, CFileHandle, CFindHandle, RegKeyHandle
  11. // CAutoHandleTemplate<DWORD,BOOL (*)(HANDLE)>
  12. //
  13. // Functions:
  14. //
  15. // Coupling:
  16. //
  17. // Notes:
  18. //
  19. // History: 1-15-1997 ericne Created
  20. //
  21. //----------------------------------------------------------------------------
  22. #ifndef _CMYHANDLE
  23. #define _CMYHANDLE
  24. #include <crtdbg.h>
  25. #ifndef NEW
  26. #define NEW new
  27. #endif
  28. #define NOT_NULL_OR_INVALID( h ) ( (h) && ~((UINT_PTR)(h)) )
  29. //+---------------------------------------------------------------------------
  30. //
  31. // Class: autohandle_base
  32. //
  33. // Purpose: factor out code common to all handles
  34. //
  35. // Interface: operator== --
  36. // operator!= --
  37. // operator== --
  38. // operator!= --
  39. // operator== --
  40. // operator!= --
  41. // autohandle_base --
  42. // ~autohandle_base --
  43. // IsWrongHandle --
  44. // m_handle --
  45. //
  46. // History: 5-13-1998 ericne Created
  47. //
  48. // Notes:
  49. //
  50. //----------------------------------------------------------------------------
  51. class autohandle_base
  52. {
  53. public:
  54. // Comparison operators
  55. inline bool operator==( const autohandle_base & right ) const
  56. {
  57. #ifdef _DEBUG
  58. if( IsWrongHandle( right.m_handle ) )
  59. _RPT1( _CRT_ASSERT, "Bad handle comparison detected!"
  60. " this = %p", this );
  61. #endif
  62. return ( m_handle == right.m_handle );
  63. }
  64. inline bool operator!=( const autohandle_base & right ) const
  65. {
  66. return ! operator==( right );
  67. }
  68. // For comparisons with HANDLE types, including INVALID_HANDLE_VALUE
  69. friend inline bool operator==( const HANDLE left,
  70. const autohandle_base & right )
  71. {
  72. return right.operator==( left );
  73. }
  74. friend inline bool operator!=( const HANDLE left,
  75. const autohandle_base & right )
  76. {
  77. return ! right.operator==( left );
  78. }
  79. inline bool operator==( const HANDLE right ) const
  80. {
  81. #ifdef _DEBUG
  82. if( IsWrongHandle( right ) )
  83. _RPT1( _CRT_ASSERT, "Bad handle comparison detected!"
  84. " this = %p", this );
  85. #endif
  86. return ( m_handle == right );
  87. }
  88. inline bool operator!=( const HANDLE right ) const
  89. {
  90. return ! operator==( right );
  91. }
  92. // These are for comparisons with NULL
  93. friend inline bool operator==( const int left,
  94. const autohandle_base & right )
  95. {
  96. return right.operator==( left );
  97. }
  98. friend inline int operator!=( const int left,
  99. const autohandle_base & right )
  100. {
  101. return ! right.operator==( left );
  102. }
  103. inline bool operator==( const int right ) const
  104. {
  105. #ifdef _DEBUG
  106. if( IsWrongHandle( (HANDLE)right ) )
  107. _RPT1( _CRT_ASSERT, "Bad handle comparison detected!"
  108. " this = %p", this );
  109. #endif
  110. return ( m_handle == (HANDLE)right );
  111. }
  112. inline bool operator!=( const int right ) const
  113. {
  114. return ! operator==( right );
  115. }
  116. protected:
  117. autohandle_base( HANDLE h ) : m_handle( h ) {}
  118. virtual ~autohandle_base() {}
  119. virtual bool IsWrongHandle( const HANDLE ) const = 0;
  120. HANDLE m_handle;
  121. };
  122. //+---------------------------------------------------------------------------
  123. //
  124. // Class: basic_autohandle ()
  125. //
  126. // Purpose: To simplify the use of handles, and to prevent handle leaks
  127. //
  128. // Interface:
  129. //
  130. // History: 1-15-1997 ericne Created
  131. //
  132. // Notes: It is a template on UINT_PTR instead of HANDLE because you
  133. // cannot template on a void pointer. The second template
  134. // argument is the function to call in the destructor.
  135. //
  136. //----------------------------------------------------------------------------
  137. template< UINT_PTR H, BOOL (*CLOSE)(HANDLE) >
  138. class basic_autohandle : public autohandle_base
  139. {
  140. public:
  141. basic_autohandle( const HANDLE ToCopy = (HANDLE)H )
  142. : autohandle_base( ToCopy ),
  143. m_pulRefCount( NULL )
  144. {
  145. if( NOT_NULL_OR_INVALID( m_handle ) )
  146. m_pulRefCount = NEW LONG(1);
  147. #ifdef _DEBUG
  148. if( IsWrongHandle( ToCopy ) )
  149. _RPT1( _CRT_ASSERT, "Bad handle assignment detected!"
  150. " this = %p", this );
  151. #endif
  152. }
  153. basic_autohandle( const basic_autohandle<H,CLOSE>& ToCopy )
  154. : autohandle_base( ToCopy.m_handle ),
  155. m_pulRefCount( ToCopy.m_pulRefCount )
  156. {
  157. if( NOT_NULL_OR_INVALID( m_handle ) )
  158. {
  159. _ASSERT( NULL != m_pulRefCount );
  160. (void)AddRef();
  161. }
  162. #ifdef _DEBUG
  163. if( IsWrongHandle( ToCopy.m_handle ) )
  164. _RPT1( _CRT_ASSERT, "Bad handle assignment detected!"
  165. " this = %p", this );
  166. #endif
  167. }
  168. virtual ~basic_autohandle()
  169. {
  170. (void)Release();
  171. }
  172. basic_autohandle<H,CLOSE> & operator=(
  173. const basic_autohandle<H,CLOSE> & ToCopy )
  174. {
  175. if( ( this != &ToCopy ) && ( m_handle != ToCopy.m_handle ) )
  176. {
  177. this->basic_autohandle<H,CLOSE>::~basic_autohandle<H,CLOSE>();
  178. this->basic_autohandle<H,CLOSE>::basic_autohandle<H,CLOSE>(ToCopy);
  179. }
  180. return *this;
  181. }
  182. basic_autohandle<H,CLOSE> & operator=( const HANDLE ToCopy )
  183. {
  184. if( m_handle != ToCopy )
  185. {
  186. this->basic_autohandle<H,CLOSE>::~basic_autohandle<H,CLOSE>();
  187. this->basic_autohandle<H,CLOSE>::basic_autohandle<H,CLOSE>(ToCopy);
  188. }
  189. return *this;
  190. }
  191. inline HANDLE GetHandle()
  192. {
  193. return m_handle;
  194. }
  195. //
  196. // These are for controlling the reference count on the handle
  197. // These should not be needed usually, since the other members
  198. // maintain the ref count. Use Release to Close a handle before
  199. // the handle object goes out of scope
  200. //
  201. ULONG AddRef()
  202. {
  203. if( NULL == m_pulRefCount )
  204. return 0;
  205. return InterlockedIncrement( m_pulRefCount );
  206. }
  207. ULONG Release()
  208. {
  209. if( NULL == m_pulRefCount )
  210. return 0;
  211. ULONG ulToReturn = InterlockedDecrement( m_pulRefCount );
  212. if( 0 == ulToReturn )
  213. {
  214. if( NOT_NULL_OR_INVALID( m_handle ) )
  215. {
  216. if( ! CLOSE( m_handle ) )
  217. _RPT1( _CRT_WARN, "Failed to close a handle. GetLast"
  218. "Error() returned 0x%08X", GetLastError() );
  219. m_handle = (HANDLE)H;
  220. }
  221. delete m_pulRefCount;
  222. m_pulRefCount = NULL;
  223. }
  224. return ulToReturn;
  225. }
  226. protected:
  227. virtual bool IsWrongHandle( const HANDLE ToCopy ) const
  228. {
  229. return( ~H == (UINT_PTR)ToCopy );
  230. }
  231. LONG * m_pulRefCount;
  232. };
  233. //
  234. // These are the most commonly used handles
  235. //
  236. // The AutoHandle has a default value of NULL ( 0 ) and calls CloseHandle
  237. typedef basic_autohandle< (UINT_PTR) NULL, CloseHandle > CAutoHandle;
  238. // The FileHandle has a default value of INVALID_HANDLE_VALUE ( -1 )
  239. // and calls CloseHandle
  240. typedef basic_autohandle< (UINT_PTR) INVALID_HANDLE_VALUE, CloseHandle >
  241. CFileHandle;
  242. // The FindHandle has a default value of INVALID_HANDLE_VALUE ( -1 )
  243. // and calls FindClose
  244. typedef basic_autohandle< (UINT_PTR) INVALID_HANDLE_VALUE, FindClose >
  245. CFindHandle;
  246. //+---------------------------------------------------------------------------
  247. //
  248. // Class: RegKeyHandle ()
  249. //
  250. // Purpose: Smart registry key handle which closes itself when it
  251. // goes out of scope.
  252. //
  253. // Interface:
  254. //
  255. // History: 11-08-1996 ericne Created
  256. //
  257. // Notes:
  258. //
  259. //----------------------------------------------------------------------------
  260. class RegKeyHandle
  261. {
  262. public:
  263. RegKeyHandle() : m_hKey( NULL ) {}
  264. RegKeyHandle( const HKEY& hKey ) : m_hKey( hKey ) {}
  265. ~RegKeyHandle()
  266. {
  267. if( NOT_NULL_OR_INVALID( m_hKey ) )
  268. {
  269. LONG lRetVal = RegCloseKey( m_hKey );
  270. if( lRetVal != ERROR_SUCCESS )
  271. _RPT1( _CRT_WARN, "RegCloseKey returned 0x%08X\r\n",
  272. lRetVal );
  273. }
  274. m_hKey = NULL;
  275. }
  276. RegKeyHandle & operator=( const RegKeyHandle & hKey )
  277. {
  278. if( ( this != &hKey ) && ( m_hKey != hKey.m_hKey ) )
  279. {
  280. this->RegKeyHandle::~RegKeyHandle();
  281. this->RegKeyHandle::RegKeyHandle( hKey );
  282. }
  283. return *this;
  284. }
  285. RegKeyHandle & operator=( const HKEY & hKey )
  286. {
  287. if( m_hKey != hKey )
  288. {
  289. this->RegKeyHandle::~RegKeyHandle();
  290. this->RegKeyHandle::RegKeyHandle( hKey );
  291. }
  292. return *this;
  293. }
  294. operator HKEY()
  295. {
  296. return m_hKey;
  297. }
  298. operator PHKEY()
  299. {
  300. return &m_hKey;
  301. }
  302. bool operator==( const int right )
  303. {
  304. return (int)( (void *const)right == m_hKey );
  305. }
  306. bool operator!=( const int right )
  307. {
  308. return (int)( (void *const)right != m_hKey );
  309. }
  310. friend bool operator==( const int left, const RegKeyHandle & right )
  311. {
  312. return( (void *const)left == right.m_hKey );
  313. }
  314. friend bool operator!=( const int left, const RegKeyHandle & right )
  315. {
  316. return( (void *const)left != right.m_hKey );
  317. }
  318. private:
  319. HKEY m_hKey;
  320. };
  321. #endif