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.

616 lines
11 KiB

  1. #pragma once
  2. #include <atlbase.h>
  3. #include <utility>
  4. #include <assert.h>
  5. #include "dexception.h"
  6. // AutoPtrBase
  7. //
  8. // Safe pointer class that knows to delete the referrent object when
  9. // the pointer goes out of scope or is replaced, etc.
  10. template<class _TYPE> class AutoPtrBase
  11. {
  12. protected:
  13. mutable BOOL m_bOwns;
  14. _TYPE * m_pRaw;
  15. public:
  16. // Create from raw pointer. This auto pointer now owns the data.
  17. AutoPtrBase(_TYPE * pRaw = NULL)
  18. {
  19. m_bOwns = (pRaw != NULL);
  20. m_pRaw = pRaw;
  21. assert( !m_bOwns || m_pRaw );
  22. }
  23. // Create from other auto pointer. Other auto pointer disowns the data.
  24. AutoPtrBase(const AutoPtrBase<_TYPE> & ptrOther)
  25. {
  26. m_bOwns = ptrOther.m_bOwns;
  27. m_pRaw = (_TYPE *) const_cast<AutoPtrBase<_TYPE> &>(ptrOther)._disownptr();
  28. }
  29. AutoPtrBase<_TYPE> & take(_TYPE * pRawIn)
  30. {
  31. if (m_pRaw != pRawIn)
  32. {
  33. if (m_bOwns)
  34. nukeit();
  35. }
  36. m_bOwns = (pRawIn != NULL);
  37. m_pRaw = pRawIn;
  38. assert( !m_bOwns || m_pRaw );
  39. return *this;
  40. }
  41. virtual ~AutoPtrBase()
  42. {
  43. }
  44. virtual void nukeit()
  45. {
  46. delete m_pRaw;
  47. }
  48. AutoPtrBase<_TYPE> & operator=(_TYPE * pRawIn)
  49. {
  50. take(pRawIn);
  51. return *this;
  52. }
  53. // Assignment of other auto pointer to ourselves. If we are not the
  54. // same object, we take ownership of the data, first releasing any
  55. // we already own.
  56. AutoPtrBase<_TYPE> & operator=(const AutoPtrBase<_TYPE> & ptrOther)
  57. {
  58. if ((void *)this != (void *)&ptrOther)
  59. {
  60. _TYPE * pRaw = const_cast<AutoPtrBase<_TYPE>&>(ptrOther)._disownptr();
  61. take(pRaw);
  62. }
  63. return *this;
  64. }
  65. AutoPtrBase<_TYPE> & replace(const AutoPtrBase<_TYPE>& ptrOtherIn)
  66. {
  67. return *this = ptrOtherIn;
  68. }
  69. virtual operator _TYPE*()
  70. {
  71. return get();
  72. }
  73. virtual operator const _TYPE*() const
  74. {
  75. return get();
  76. }
  77. /* Not allowed, since void * wouldn't worl
  78. _TYPE& operator*() const
  79. {
  80. return (*get());
  81. }
  82. */
  83. _TYPE ** operator&()
  84. {
  85. return _getoutptr();
  86. }
  87. // Will produce errors if applied using infix notation
  88. //#pragma warning(disable:4284)
  89. // _TYPE *operator->() const
  90. // {
  91. // return (get());
  92. // }
  93. //#pragma warning(default:4284)
  94. _TYPE *get() const
  95. {
  96. return (m_pRaw);
  97. }
  98. _TYPE * _disownptr()
  99. {
  100. m_bOwns = FALSE;
  101. return m_pRaw;
  102. }
  103. _TYPE ** _getoutptr()
  104. {
  105. if (m_bOwns)
  106. nukeit();
  107. m_bOwns = TRUE;
  108. return (&m_pRaw);
  109. }
  110. };
  111. // AutoHLOCK
  112. //
  113. template<class _TYPE>
  114. class AutoHLOCK : public AutoPtrBase<_TYPE>
  115. {
  116. private:
  117. protected:
  118. HGLOBAL m_hGlobal;
  119. virtual void nukeit()
  120. {
  121. // If the memory object is still locked after decrementing the lock count,
  122. // the return value is a nonzero value. If the function fails, the return
  123. // value is zero. To get extended error information, we call GetLastError.
  124. // If GetLastError returns NO_ERROR, the memory object is unlocked.
  125. if (0 == GlobalUnlock( m_hGlobal) )
  126. assert(NO_ERROR == GetLastError());
  127. }
  128. public:
  129. AutoHLOCK<_TYPE>& operator=(HGLOBAL _H)
  130. {
  131. if (m_hGlobal != _H)
  132. {
  133. if (m_bOwns)
  134. nukeit();
  135. m_pRaw = _H ? ((_TYPE*) GlobalLock(_H)) : NULL;
  136. m_bOwns = (NULL != m_pRaw);
  137. m_hGlobal = _H;
  138. assert( !m_bOwns || m_pRaw );
  139. }
  140. return *this;
  141. }
  142. ~AutoHLOCK()
  143. {
  144. if (m_bOwns)
  145. this->nukeit();
  146. }
  147. AutoHLOCK(HGLOBAL _H = 0)
  148. : m_hGlobal(NULL)
  149. {
  150. *this = _H;
  151. }
  152. };
  153. // AutoHPALETTE (HPALETTE)
  154. //
  155. class AutoHPALETTE : public AutoPtrBase<struct HPALETTE__>
  156. {
  157. virtual void nukeit()
  158. {
  159. DeleteObject((HPALETTE)m_pRaw);
  160. }
  161. public:
  162. ~AutoHPALETTE()
  163. {
  164. if (m_bOwns)
  165. this->nukeit();
  166. }
  167. AutoHPALETTE(HPALETTE pRawIn = 0)
  168. : AutoPtrBase<struct HPALETTE__>(pRawIn)
  169. {
  170. }
  171. };
  172. /*
  173. // AutoHPROPSHEETPAGE
  174. //
  175. class AutoHPROPSHEETPAGE : public AutoPtrBase<struct _PSP>
  176. {
  177. virtual void nukeit()
  178. {
  179. DestroyPropertySheetPage((HPROPSHEETPAGE)m_pRaw);
  180. }
  181. public:
  182. ~AutoHPROPSHEETPAGE()
  183. {
  184. if (m_bOwns)
  185. this->nukeit();
  186. }
  187. AutoHPROPSHEETPAGE(HPROPSHEETPAGE pRawIn = 0)
  188. : AutoPtrBase<struct _PSP>(pRawIn)
  189. {
  190. }
  191. };
  192. */
  193. //
  194. // AutoHKEY (HKEY)
  195. //
  196. class AutoHKEY : public AutoPtrBase<struct HKEY__>
  197. {
  198. virtual void nukeit()
  199. {
  200. RegCloseKey((HKEY)m_pRaw);
  201. }
  202. public:
  203. ~AutoHKEY()
  204. {
  205. if (m_bOwns)
  206. this->nukeit();
  207. }
  208. AutoHKEY(HKEY pRawIn = 0)
  209. : AutoPtrBase<struct HKEY__>(pRawIn)
  210. {
  211. }
  212. };
  213. // AutoHICON (HICON)
  214. //
  215. class AutoHICON : public AutoPtrBase<struct HICON__>
  216. {
  217. virtual void nukeit()
  218. {
  219. DestroyIcon((HICON)m_pRaw);
  220. }
  221. public:
  222. ~AutoHICON()
  223. {
  224. if (m_bOwns)
  225. this->nukeit();
  226. }
  227. AutoHICON& operator=(struct HICON__ * pRawIn)
  228. {
  229. take(pRawIn);
  230. return *this;
  231. }
  232. AutoHICON(HICON pRawIn = 0)
  233. : AutoPtrBase<struct HICON__>(pRawIn)
  234. {
  235. }
  236. };
  237. // AutoHBITMAP (HBITMAP)
  238. //
  239. class AutoHBITMAP : public AutoPtrBase<struct HBITMAP__>
  240. {
  241. virtual void nukeit()
  242. {
  243. DeleteObject((HBITMAP)m_pRaw);
  244. }
  245. public:
  246. ~AutoHBITMAP()
  247. {
  248. if (m_bOwns)
  249. this->nukeit();
  250. }
  251. AutoHBITMAP& operator=(struct HBITMAP__ * pRawIn)
  252. {
  253. take(pRawIn);
  254. return *this;
  255. }
  256. AutoHBITMAP(HBITMAP pRawIn = 0)
  257. : AutoPtrBase<struct HBITMAP__>(pRawIn)
  258. {
  259. }
  260. };
  261. // AutoHDC (HDC)
  262. //
  263. typedef pair<HDC, HWND> WindowDCPair;
  264. class AutoHDC : public AutoPtrBase<WindowDCPair>
  265. {
  266. // If this was from GetDC() call, we'll have the handle of the
  267. // window against which we will need to release it. If not,
  268. // we assume we need to actually DeleteDC() on it.
  269. virtual void nukeit()
  270. {
  271. if (get()->second)
  272. ReleaseDC(get()->second, get()->first);
  273. else
  274. DeleteDC(get()->first);
  275. }
  276. protected:
  277. HDC m_hDC;
  278. public:
  279. ~AutoHDC()
  280. {
  281. if (m_bOwns)
  282. this->nukeit();
  283. }
  284. AutoHDC& operator=(HDC pRawIn)
  285. {
  286. take( &WindowDCPair(pRawIn, NULL) );
  287. return *this;
  288. }
  289. AutoHDC& operator=( WindowDCPair in)
  290. {
  291. take(&in);
  292. return *this;
  293. }
  294. AutoHDC(HDC hdc = NULL, HWND hwndFrom = NULL)
  295. : AutoPtrBase<WindowDCPair>( &WindowDCPair(hdc, hwndFrom) )
  296. {
  297. }
  298. AutoHDC(HWND hwndFrom)
  299. : AutoPtrBase<WindowDCPair>( &WindowDCPair(GetDC(hwndFrom), hwndFrom) )
  300. {
  301. if (NULL == get()->first)
  302. throw new win32error;
  303. }
  304. operator HDC()
  305. {
  306. return get()->first;
  307. }
  308. operator const HDC() const
  309. {
  310. return get()->first;
  311. }
  312. };
  313. // AutoHGLOBAL (HGLOBAL)
  314. //
  315. class AutoHGLOBAL : public AutoPtrBase<void>
  316. {
  317. virtual void nukeit()
  318. {
  319. GlobalFree((HGLOBAL)m_pRaw);
  320. }
  321. public:
  322. ~AutoHGLOBAL()
  323. {
  324. if (m_bOwns)
  325. this->nukeit();
  326. }
  327. AutoHGLOBAL(HGLOBAL pRawIn = 0)
  328. : AutoPtrBase<void>(pRawIn)
  329. {
  330. }
  331. };
  332. class AutoFindHandle
  333. {
  334. public:
  335. AutoFindHandle(HANDLE handle = INVALID_HANDLE_VALUE)
  336. : m_handle(handle), m_bOwns(INVALID_HANDLE_VALUE != handle) { }
  337. AutoFindHandle(const AutoFindHandle& rhs)
  338. : m_handle(INVALID_HANDLE_VALUE), m_bOwns(false)
  339. { *this = rhs; }
  340. ~AutoFindHandle(void)
  341. { Close(); }
  342. void Close(void);
  343. HANDLE Detach(void) const
  344. { m_bOwns = false; return m_handle; }
  345. void Attach(HANDLE handle)
  346. { Close(); m_handle = handle; m_bOwns = true; }
  347. operator HANDLE() const
  348. { return m_handle; }
  349. bool IsValid(void) const
  350. { return INVALID_HANDLE_VALUE != m_handle; }
  351. AutoFindHandle& operator = (HANDLE handle)
  352. { Attach(handle); return *this; }
  353. AutoFindHandle& operator = (const AutoFindHandle& rhs);
  354. private:
  355. mutable HANDLE m_handle;
  356. mutable bool m_bOwns;
  357. };
  358. // AutoPtr
  359. //
  360. template<class _TYPE>
  361. class AutoPtr : public AutoPtrBase<_TYPE>
  362. {
  363. virtual void nukeit()
  364. {
  365. delete m_pRaw;
  366. }
  367. public:
  368. ~AutoPtr()
  369. {
  370. if (m_bOwns)
  371. this->nukeit();
  372. }
  373. AutoPtr(_TYPE *pRawIn = 0)
  374. : AutoPtrBase<_TYPE>(pRawIn)
  375. {
  376. }
  377. AutoPtr<_TYPE> & operator=(const AutoPtr<_TYPE> & ptrOther)
  378. {
  379. if (this != &ptrOther)
  380. {
  381. AutoPtr<_TYPE> * pptrOther = const_cast<AutoPtr<_TYPE> *>(&ptrOther);
  382. m_bOwns = pptrOther->m_bOwns;
  383. m_pRaw = (_TYPE *) (pptrOther->_disownptr());
  384. }
  385. return *this;
  386. }
  387. AutoPtr(const AutoPtr<_TYPE> & ptrOther)
  388. {
  389. *this = ptrOther;
  390. }
  391. // AutoPtr<_TYPE> & operator=(_TYPE * pRawIn)
  392. AutoPtr<_TYPE> & operator=(_TYPE * pRawIn)
  393. {
  394. take(pRawIn);
  395. return *this;
  396. }
  397. };
  398. // AutoComPtr
  399. //
  400. // Smart pointer that calls _disownptr() on the referent when the pointer itself
  401. // goes out of scope
  402. template <class _TYPE>
  403. class AutoComPtr : public CComPtr<_TYPE>
  404. {
  405. public:
  406. AutoComPtr(void) { }
  407. AutoComPtr(_TYPE *p)
  408. : CComPtr<_TYPE>(p) { }
  409. AutoComPtr(const AutoComPtr<_TYPE>& rhs)
  410. : CComPtr<_TYPE>(rhs.p) { }
  411. AutoComPtr& operator = (const AutoComPtr& rhs)
  412. {
  413. if (this != &rhs)
  414. {
  415. CComPtr<_TYPE>::operator = (rhs);
  416. }
  417. return *this;
  418. }
  419. //
  420. // Retrieve the address of the contained interface ptr.
  421. // ptr._getoutptr() is equivalent to &ptr.p
  422. //
  423. _TYPE **_getoutptr(void)
  424. {
  425. return &p;
  426. }
  427. _TYPE * _disownptr(void)
  428. {
  429. return Detach();
  430. }
  431. //
  432. // WARNING: This hides the CComPtr implementation of operator&().
  433. // It's intentional. Otherwise you can't pass the address
  434. // of an AutoComPtr to a function and get the expected semantics.
  435. // CComPtr's implementation returns the address of the contained
  436. // pointer. If this is what you want, use AutoComtPtr::_getoutptr().
  437. //
  438. AutoComPtr *operator& (void)
  439. {
  440. return this;
  441. }
  442. };
  443. #ifdef USE_SHELL_AUTOPTR
  444. #include <cshalloc.h>
  445. // App must declare a global instance of this class
  446. extern CSHAlloc g_SHAlloc;
  447. // AutoShellPtr
  448. //
  449. // Smart pointer that manually runs the referent's destructor and then
  450. // calls the shell's task allocator to free the object's memory footprint
  451. template<class _TYPE>
  452. class AutoShellPtr : virtual public AutoPtrBase<_TYPE>
  453. {
  454. virtual void nukeit()
  455. {
  456. if (m_pRaw)
  457. {
  458. m_pRaw->~_TYPE();
  459. g_SHAlloc.Free(m_pRaw);
  460. }
  461. }
  462. public:
  463. ~AutoShellPtr()
  464. {
  465. if (m_bOwns)
  466. this->nukeit();
  467. }
  468. AutoShellPtr(_TYPE *pRawIn = 0)
  469. : AutoPtrBase<_TYPE>(pRawIn)
  470. {
  471. }
  472. AutoShellPtr<_TYPE> & operator=(_TYPE * pRawIn)
  473. {
  474. take(pRawIn);
  475. return *this;
  476. }
  477. };
  478. #endif