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.

1044 lines
23 KiB

  1. #ifndef __UTILS__H
  2. #define __UTILS__H
  3. /*++
  4. Copyright (C) Microsoft Corporation
  5. Module Name:
  6. utils.h
  7. Abstract:
  8. This module declares utilities classes
  9. Author:
  10. William Hsieh (williamh) created
  11. Revision History:
  12. --*/
  13. //
  14. // Memory allocation exception class
  15. //
  16. class CMemoryException
  17. {
  18. public:
  19. CMemoryException(BOOL Global)
  20. {
  21. m_Global = Global;
  22. m_Message[0] = _T('\0');
  23. m_Caption[0] = _T('\0');
  24. m_Options = MB_OK | MB_ICONHAND;
  25. }
  26. BOOL SetMessage(LPCTSTR Message)
  27. {
  28. if (!Message || lstrlen(Message) >= ARRAYLEN(m_Message))
  29. {
  30. return FALSE;
  31. }
  32. StringCchCopy(m_Message, ARRAYLEN(m_Message), Message);
  33. return TRUE;
  34. }
  35. BOOL SetCaption(LPCTSTR Caption)
  36. {
  37. if (!Caption || lstrlen(Caption) >= ARRAYLEN(m_Caption))
  38. {
  39. return FALSE;
  40. }
  41. StringCchCopy(m_Caption, ARRAYLEN(m_Caption), Caption);
  42. return TRUE;
  43. }
  44. void ReportError(HWND hwndParent = NULL)
  45. {
  46. MessageBox(hwndParent, m_Message, m_Caption, m_Options);
  47. }
  48. void Delete()
  49. {
  50. if (!m_Global)
  51. {
  52. delete this;
  53. }
  54. }
  55. private:
  56. TCHAR m_Message[128];
  57. TCHAR m_Caption[128];
  58. DWORD m_Options;
  59. BOOL m_Global;
  60. };
  61. //
  62. // data buffer control class for String class
  63. //
  64. class StringData
  65. {
  66. public:
  67. StringData() : Ref(1), ptsz(NULL), Len(0)
  68. {}
  69. ~StringData()
  70. {
  71. delete [] ptsz;
  72. }
  73. long AddRef()
  74. {
  75. Ref++;
  76. return Ref;
  77. }
  78. long Release()
  79. {
  80. ASSERT(Ref);
  81. if (!(--Ref))
  82. {
  83. delete this;
  84. return 0;
  85. }
  86. return Ref;
  87. }
  88. TCHAR* ptsz;
  89. long Len;
  90. private:
  91. long Ref;
  92. };
  93. class CBlock
  94. {
  95. public:
  96. CBlock(CBlock* BlockHead, UINT unitCount, UINT unitSize)
  97. {
  98. data = new BYTE[unitCount * unitSize];
  99. if (data)
  100. {
  101. if (BlockHead)
  102. {
  103. m_Next = BlockHead->m_Next;
  104. BlockHead->m_Next = this;
  105. }
  106. else
  107. {
  108. m_Next = NULL;
  109. }
  110. }
  111. else
  112. {
  113. throw &g_MemoryException;
  114. }
  115. }
  116. ~CBlock()
  117. {
  118. if (data)
  119. delete [] data;
  120. if (m_Next)
  121. delete m_Next;
  122. }
  123. void* data;
  124. private:
  125. CBlock* m_Next;
  126. };
  127. //
  128. // Text string class
  129. //
  130. class String
  131. {
  132. public:
  133. // constructors
  134. String();
  135. String(LPCTSTR lptsz);
  136. String(const String& strSrc);
  137. ~String()
  138. {
  139. m_pData->Release();
  140. }
  141. //operators
  142. TCHAR& operator[](int Index);
  143. operator LPTSTR();
  144. const TCHAR& operator[](int Index) const
  145. {
  146. ASSERT(Index < m_pData->Len && m_pData->ptsz);
  147. return m_pData->ptsz[Index];
  148. }
  149. operator LPCTSTR () const
  150. {
  151. return m_pData->ptsz;
  152. }
  153. String& operator=(const String& strSrc);
  154. String& operator=(LPCTSTR ptsz);
  155. String& operator+=(const String& strSrc);
  156. String& operator+=(LPCTSTR prsz);
  157. friend String operator+(const String& str1, const String& str2);
  158. int GetLength() const
  159. {
  160. return m_pData->Len;
  161. }
  162. BOOL IsEmpty() const
  163. {
  164. return (0 == m_pData->Len);
  165. }
  166. int Compare(const String& strSrc) const
  167. {
  168. return lstrcmp(m_pData->ptsz, strSrc.m_pData->ptsz);
  169. }
  170. int CompareNoCase(const String& strSrc) const
  171. {
  172. return lstrcmpi(m_pData->ptsz, strSrc.m_pData->ptsz);
  173. }
  174. void Empty();
  175. BOOL LoadString(HINSTANCE hInstance, int ResourceId);
  176. BOOL GetComputerName();
  177. BOOL GetSystemWindowsDirectory();
  178. BOOL GetSystemDirectory();
  179. void Format(LPCTSTR FormatString, ...);
  180. StringData* m_pData;
  181. protected:
  182. String(int Len);
  183. };
  184. //
  185. // Command line parsing class
  186. //
  187. class CCommandLine
  188. {
  189. public:
  190. void ParseCommandLine(LPCTSTR cmdline);
  191. virtual void ParseParam(LPCTSTR Param, BOOL bFlag) = 0;
  192. };
  193. //
  194. // Safe registry class
  195. //
  196. class CSafeRegistry
  197. {
  198. public:
  199. CSafeRegistry(HKEY hKey = NULL) : m_hKey(hKey)
  200. {}
  201. ~CSafeRegistry()
  202. {
  203. if (m_hKey)
  204. {
  205. RegCloseKey(m_hKey);
  206. }
  207. }
  208. operator HKEY()
  209. {
  210. return m_hKey;
  211. }
  212. BOOL Open(HKEY hKeyAncestor, LPCTSTR KeyName, REGSAM Access = KEY_ALL_ACCESS);
  213. void Close()
  214. {
  215. if (m_hKey)
  216. {
  217. RegCloseKey(m_hKey);
  218. }
  219. m_hKey = NULL;
  220. }
  221. BOOL Create(HKEY hKeyAncestor, LPCTSTR KeyName,
  222. REGSAM Access = KEY_ALL_ACCESS,
  223. DWORD * pDisposition = NULL, DWORD Options = 0,
  224. LPSECURITY_ATTRIBUTES pSecurity = NULL);
  225. BOOL SetValue(LPCTSTR ValueName, DWORD Type, PBYTE pData, DWORD DataLen);
  226. BOOL SetValue(LPCTSTR ValueName, LPCTSTR Value);
  227. BOOL GetValue(LPCTSTR ValueName, DWORD* pType, PBYTE Buffer, DWORD* BufferLen);
  228. BOOL GetValue(LPCTSTR ValueName, String& str);
  229. BOOL DeleteValue(LPCTSTR ValueName);
  230. BOOL DeleteSubkey(LPCTSTR SubkeyName);
  231. BOOL EnumerateSubkey(DWORD Index, LPTSTR Buffer, DWORD* BufferSize);
  232. private:
  233. HKEY m_hKey;
  234. };
  235. // define iteration context. To be used by CLIST
  236. struct tagPosition{ };
  237. typedef tagPosition* POSITION;
  238. template<class TYPE>
  239. inline void ConstructElements(TYPE* pElements, int Count)
  240. {
  241. memset((void*)&pElements, 0, Count * sizeof(TYPE));
  242. for (; Count; Count--, pElements++)
  243. {
  244. // call the contructor -- note the placement
  245. ::new((void*)pElements) TYPE;
  246. }
  247. }
  248. template<class TYPE>
  249. inline void DestructElements(TYPE* pElements, int Count)
  250. {
  251. for (; Count; Count--, pElements++)
  252. {
  253. pElements->~TYPE();
  254. }
  255. }
  256. //
  257. // TEMPLATEs
  258. //
  259. //
  260. // CList template, adapted from MFC
  261. //
  262. template<class TYPE, class ARG_TYPE>
  263. class CList
  264. {
  265. protected:
  266. struct CNode
  267. {
  268. CNode* pNext;
  269. CNode* pPrev;
  270. TYPE data;
  271. };
  272. public:
  273. // Construction
  274. CList(int nBlockSize = 10);
  275. // Attributes (head and tail)
  276. // count of elements
  277. int GetCount() const;
  278. BOOL IsEmpty() const;
  279. // peek at head or tail
  280. TYPE& GetHead();
  281. TYPE GetHead() const;
  282. TYPE& GetTail();
  283. TYPE GetTail() const;
  284. // Operations
  285. // get head or tail (and remove it) - don't call on empty list !
  286. TYPE RemoveHead();
  287. TYPE RemoveTail();
  288. // add before head or after tail
  289. POSITION AddHead(ARG_TYPE newElement);
  290. POSITION AddTail(ARG_TYPE newElement);
  291. // add another list of elements before head or after tail
  292. void AddHead(CList* pNewList);
  293. void AddTail(CList* pNewList);
  294. // remove all elements
  295. void RemoveAll();
  296. // iteration
  297. POSITION GetHeadPosition() const;
  298. POSITION GetTailPosition() const;
  299. TYPE& GetNext(POSITION& rPosition); // return *Position++
  300. TYPE GetNext(POSITION& rPosition) const; // return *Position++
  301. TYPE& GetPrev(POSITION& rPosition); // return *Position--
  302. TYPE GetPrev(POSITION& rPosition) const; // return *Position--
  303. // getting/modifying an element at a given position
  304. TYPE& GetAt(POSITION position);
  305. TYPE GetAt(POSITION position) const;
  306. void SetAt(POSITION pos, ARG_TYPE newElement);
  307. void RemoveAt(POSITION position);
  308. // inserting before or after a given position
  309. POSITION InsertBefore(POSITION position, ARG_TYPE newElement);
  310. POSITION InsertAfter(POSITION position, ARG_TYPE newElement);
  311. POSITION FindIndex(int nIndex) const;
  312. // get the 'nIndex'th element (may return NULL)
  313. // Implementation
  314. protected:
  315. CNode* m_pNodeHead;
  316. CNode* m_pNodeTail;
  317. int m_nCount;
  318. CNode* m_pNodeFree;
  319. CBlock* m_pBlocks;
  320. int m_nBlockSize;
  321. CNode* NewNode(CNode*, CNode*);
  322. void FreeNode(CNode*);
  323. public:
  324. ~CList();
  325. };
  326. /////////////////////////////////////////////////////////////////////////////
  327. // CList<TYPE, ARG_TYPE> inline functions
  328. template<class TYPE, class ARG_TYPE>
  329. inline int CList<TYPE, ARG_TYPE>::GetCount() const
  330. { return m_nCount; }
  331. template<class TYPE, class ARG_TYPE>
  332. inline BOOL CList<TYPE, ARG_TYPE>::IsEmpty() const
  333. { return m_nCount == 0; }
  334. template<class TYPE, class ARG_TYPE>
  335. inline TYPE& CList<TYPE, ARG_TYPE>::GetHead()
  336. { ASSERT(m_pNodeHead != NULL);
  337. return m_pNodeHead->data; }
  338. template<class TYPE, class ARG_TYPE>
  339. inline TYPE CList<TYPE, ARG_TYPE>::GetHead() const
  340. { ASSERT(m_pNodeHead != NULL);
  341. return m_pNodeHead->data; }
  342. template<class TYPE, class ARG_TYPE>
  343. inline TYPE& CList<TYPE, ARG_TYPE>::GetTail()
  344. { ASSERT(m_pNodeTail != NULL);
  345. return m_pNodeTail->data; }
  346. template<class TYPE, class ARG_TYPE>
  347. inline TYPE CList<TYPE, ARG_TYPE>::GetTail() const
  348. { ASSERT(m_pNodeTail != NULL);
  349. return m_pNodeTail->data; }
  350. template<class TYPE, class ARG_TYPE>
  351. inline POSITION CList<TYPE, ARG_TYPE>::GetHeadPosition() const
  352. { return (POSITION) m_pNodeHead; }
  353. template<class TYPE, class ARG_TYPE>
  354. inline POSITION CList<TYPE, ARG_TYPE>::GetTailPosition() const
  355. { return (POSITION) m_pNodeTail; }
  356. template<class TYPE, class ARG_TYPE>
  357. inline TYPE& CList<TYPE, ARG_TYPE>::GetNext(POSITION& rPosition) // return *Position++
  358. { CNode* pNode = (CNode*) rPosition;
  359. rPosition = (POSITION) pNode->pNext;
  360. return pNode->data; }
  361. template<class TYPE, class ARG_TYPE>
  362. inline TYPE CList<TYPE, ARG_TYPE>::GetNext(POSITION& rPosition) const // return *Position++
  363. { CNode* pNode = (CNode*) rPosition;
  364. rPosition = (POSITION) pNode->pNext;
  365. return pNode->data; }
  366. template<class TYPE, class ARG_TYPE>
  367. inline TYPE& CList<TYPE, ARG_TYPE>::GetPrev(POSITION& rPosition) // return *Position--
  368. { CNode* pNode = (CNode*) rPosition;
  369. rPosition = (POSITION) pNode->pPrev;
  370. return pNode->data; }
  371. template<class TYPE, class ARG_TYPE>
  372. inline TYPE CList<TYPE, ARG_TYPE>::GetPrev(POSITION& rPosition) const // return *Position--
  373. { CNode* pNode = (CNode*) rPosition;
  374. rPosition = (POSITION) pNode->pPrev;
  375. return pNode->data; }
  376. template<class TYPE, class ARG_TYPE>
  377. inline TYPE& CList<TYPE, ARG_TYPE>::GetAt(POSITION position)
  378. { CNode* pNode = (CNode*) position;
  379. return pNode->data; }
  380. template<class TYPE, class ARG_TYPE>
  381. inline TYPE CList<TYPE, ARG_TYPE>::GetAt(POSITION position) const
  382. { CNode* pNode = (CNode*) position;
  383. return pNode->data; }
  384. template<class TYPE, class ARG_TYPE>
  385. inline void CList<TYPE, ARG_TYPE>::SetAt(POSITION pos, ARG_TYPE newElement)
  386. { CNode* pNode = (CNode*) pos;
  387. pNode->data = newElement; }
  388. template<class TYPE, class ARG_TYPE>
  389. CList<TYPE, ARG_TYPE>::CList(int nBlockSize)
  390. {
  391. ASSERT(nBlockSize > 0);
  392. m_nCount = 0;
  393. m_pNodeHead = m_pNodeTail = m_pNodeFree = NULL;
  394. m_pBlocks = NULL;
  395. m_nBlockSize = nBlockSize;
  396. }
  397. template<class TYPE, class ARG_TYPE>
  398. void CList<TYPE, ARG_TYPE>::RemoveAll()
  399. {
  400. // destroy elements
  401. CNode* pNode;
  402. for (pNode = m_pNodeHead; pNode != NULL; pNode = pNode->pNext)
  403. {
  404. DestructElements<TYPE>(&pNode->data, 1);
  405. }
  406. m_nCount = 0;
  407. m_pNodeHead = m_pNodeTail = m_pNodeFree = NULL;
  408. delete m_pBlocks;
  409. m_pBlocks = NULL;
  410. }
  411. template<class TYPE, class ARG_TYPE>
  412. CList<TYPE, ARG_TYPE>::~CList()
  413. {
  414. RemoveAll();
  415. ASSERT(m_nCount == 0);
  416. }
  417. /////////////////////////////////////////////////////////////////////////////
  418. // Node helpers
  419. //
  420. template<class TYPE, class ARG_TYPE>
  421. typename CList<TYPE, ARG_TYPE>::CNode*
  422. CList<TYPE, ARG_TYPE>::NewNode(CNode* pPrev, CNode* pNext)
  423. {
  424. if (m_pNodeFree == NULL)
  425. {
  426. // add another block
  427. CBlock* pNewBlock = new CBlock(m_pBlocks, m_nBlockSize, sizeof(CNode));
  428. if (!pNewBlock) {
  429. throw &g_MemoryException;
  430. }
  431. if (m_pBlocks == NULL)
  432. {
  433. m_pBlocks = pNewBlock;
  434. }
  435. // chain them into free list
  436. CNode* pNode = (CNode*) pNewBlock->data;
  437. // free in reverse order to make it easier to debug
  438. pNode += m_nBlockSize - 1;
  439. for (int i = m_nBlockSize-1; i >= 0; i--, pNode--)
  440. {
  441. pNode->pNext = m_pNodeFree;
  442. m_pNodeFree = pNode;
  443. }
  444. }
  445. ASSERT(m_pNodeFree != NULL); // we must have something
  446. CList::CNode* pNode = m_pNodeFree;
  447. m_pNodeFree = m_pNodeFree->pNext;
  448. pNode->pPrev = pPrev;
  449. pNode->pNext = pNext;
  450. m_nCount++;
  451. ASSERT(m_nCount > 0); // make sure we don't overflow
  452. ConstructElements<TYPE>(&pNode->data, 1);
  453. return pNode;
  454. }
  455. template<class TYPE, class ARG_TYPE>
  456. void CList<TYPE, ARG_TYPE>::FreeNode(CNode* pNode)
  457. {
  458. DestructElements<TYPE>(&pNode->data, 1);
  459. pNode->pNext = m_pNodeFree;
  460. m_pNodeFree = pNode;
  461. m_nCount--;
  462. ASSERT(m_nCount >= 0); // make sure we don't underflow
  463. // if no more elements, cleanup completely
  464. if (m_nCount == 0)
  465. RemoveAll();
  466. }
  467. template<class TYPE, class ARG_TYPE>
  468. POSITION CList<TYPE, ARG_TYPE>::AddHead(ARG_TYPE newElement)
  469. {
  470. CNode* pNewNode = NewNode(NULL, m_pNodeHead);
  471. pNewNode->data = newElement;
  472. if (m_pNodeHead != NULL)
  473. {
  474. m_pNodeHead->pPrev = pNewNode;
  475. }
  476. else
  477. {
  478. m_pNodeTail = pNewNode;
  479. }
  480. m_pNodeHead = pNewNode;
  481. return (POSITION) pNewNode;
  482. }
  483. template<class TYPE, class ARG_TYPE>
  484. POSITION CList<TYPE, ARG_TYPE>::AddTail(ARG_TYPE newElement)
  485. {
  486. CNode* pNewNode = NewNode(m_pNodeTail, NULL);
  487. pNewNode->data = newElement;
  488. if (m_pNodeTail != NULL)
  489. {
  490. m_pNodeTail->pNext = pNewNode;
  491. }
  492. else
  493. {
  494. m_pNodeHead = pNewNode;
  495. }
  496. m_pNodeTail = pNewNode;
  497. return (POSITION) pNewNode;
  498. }
  499. template<class TYPE, class ARG_TYPE>
  500. void CList<TYPE, ARG_TYPE>::AddHead(CList* pNewList)
  501. {
  502. ASSERT(pNewList != NULL);
  503. // add a list of same elements to head (maintain order)
  504. POSITION pos = pNewList->GetTailPosition();
  505. while (pos != NULL)
  506. {
  507. AddHead(pNewList->GetPrev(pos));
  508. }
  509. }
  510. template<class TYPE, class ARG_TYPE>
  511. void CList<TYPE, ARG_TYPE>::AddTail(CList* pNewList)
  512. {
  513. ASSERT(pNewList != NULL);
  514. // add a list of same elements
  515. POSITION pos = pNewList->GetHeadPosition();
  516. while (pos != NULL)
  517. {
  518. AddTail(pNewList->GetNext(pos));
  519. }
  520. }
  521. template<class TYPE, class ARG_TYPE>
  522. TYPE CList<TYPE, ARG_TYPE>::RemoveHead()
  523. {
  524. ASSERT(m_pNodeHead != NULL); // don't call on empty list !!!
  525. CNode* pOldNode = m_pNodeHead;
  526. TYPE returnValue = pOldNode->data;
  527. m_pNodeHead = pOldNode->pNext;
  528. if (m_pNodeHead != NULL)
  529. {
  530. m_pNodeHead->pPrev = NULL;
  531. }
  532. else
  533. {
  534. m_pNodeTail = NULL;
  535. }
  536. FreeNode(pOldNode);
  537. return returnValue;
  538. }
  539. template<class TYPE, class ARG_TYPE>
  540. TYPE CList<TYPE, ARG_TYPE>::RemoveTail()
  541. {
  542. ASSERT(m_pNodeTail != NULL); // don't call on empty list !!!
  543. CNode* pOldNode = m_pNodeTail;
  544. TYPE returnValue = pOldNode->data;
  545. m_pNodeTail = pOldNode->pPrev;
  546. if (m_pNodeTail != NULL)
  547. {
  548. m_pNodeTail->pNext = NULL;
  549. }
  550. else
  551. {
  552. m_pNodeHead = NULL;
  553. }
  554. FreeNode(pOldNode);
  555. return returnValue;
  556. }
  557. template<class TYPE, class ARG_TYPE>
  558. POSITION CList<TYPE, ARG_TYPE>::InsertBefore(POSITION position, ARG_TYPE newElement)
  559. {
  560. if (position == NULL)
  561. {
  562. return AddHead(newElement); // insert before nothing -> head of the list
  563. }
  564. // Insert it before position
  565. CNode* pOldNode = (CNode*) position;
  566. CNode* pNewNode = NewNode(pOldNode->pPrev, pOldNode);
  567. pNewNode->data = newElement;
  568. if (pOldNode->pPrev != NULL)
  569. {
  570. pOldNode->pPrev->pNext = pNewNode;
  571. }
  572. else
  573. {
  574. ASSERT(pOldNode == m_pNodeHead);
  575. m_pNodeHead = pNewNode;
  576. }
  577. pOldNode->pPrev = pNewNode;
  578. return (POSITION) pNewNode;
  579. }
  580. template<class TYPE, class ARG_TYPE>
  581. POSITION CList<TYPE, ARG_TYPE>::InsertAfter(POSITION position, ARG_TYPE newElement)
  582. {
  583. if (position == NULL)
  584. {
  585. return AddTail(newElement); // insert after nothing -> tail of the list
  586. }
  587. // Insert it before position
  588. CNode* pOldNode = (CNode*) position;
  589. CNode* pNewNode = NewNode(pOldNode, pOldNode->pNext);
  590. pNewNode->data = newElement;
  591. if (pOldNode->pNext != NULL)
  592. {
  593. pOldNode->pNext->pPrev = pNewNode;
  594. }
  595. else
  596. {
  597. ASSERT(pOldNode == m_pNodeTail);
  598. m_pNodeTail = pNewNode;
  599. }
  600. pOldNode->pNext = pNewNode;
  601. return (POSITION) pNewNode;
  602. }
  603. template<class TYPE, class ARG_TYPE>
  604. void CList<TYPE, ARG_TYPE>::RemoveAt(POSITION position)
  605. {
  606. CNode* pOldNode = (CNode*) position;
  607. // remove pOldNode from list
  608. if (pOldNode == m_pNodeHead)
  609. {
  610. m_pNodeHead = pOldNode->pNext;
  611. }
  612. else
  613. {
  614. pOldNode->pPrev->pNext = pOldNode->pNext;
  615. }
  616. if (pOldNode == m_pNodeTail)
  617. {
  618. m_pNodeTail = pOldNode->pPrev;
  619. }
  620. else
  621. {
  622. pOldNode->pNext->pPrev = pOldNode->pPrev;
  623. }
  624. FreeNode(pOldNode);
  625. }
  626. template<class TYPE, class ARG_TYPE>
  627. POSITION CList<TYPE, ARG_TYPE>::FindIndex(int nIndex) const
  628. {
  629. ASSERT(nIndex >= 0);
  630. if (nIndex >= m_nCount)
  631. {
  632. return NULL; // went too far
  633. }
  634. CNode* pNode = m_pNodeHead;
  635. while (nIndex--)
  636. {
  637. pNode = pNode->pNext;
  638. }
  639. return (POSITION) pNode;
  640. }
  641. // NOTE:
  642. // dereferencing operator -> is not supported in this template
  643. // because this is designed to allocate intrinsic data types only
  644. //
  645. template<class T>
  646. class BufferPtr
  647. {
  648. public:
  649. BufferPtr(UINT Size) : m_pBase(NULL), m_Size(Size)
  650. {
  651. ASSERT(Size);
  652. m_pBase = new T[Size];
  653. m_pCur = m_pBase;
  654. if (!m_pBase)
  655. {
  656. throw &g_MemoryException;
  657. }
  658. }
  659. BufferPtr()
  660. {
  661. m_pBase = NULL;
  662. m_pCur = NULL;
  663. m_Size = 0;
  664. }
  665. ~BufferPtr()
  666. {
  667. if (m_pBase)
  668. {
  669. delete [] m_pBase;
  670. }
  671. }
  672. // casting operator
  673. operator T*()
  674. {
  675. return m_pCur;
  676. }
  677. operator T&()
  678. {
  679. ASSERT(m_pCur < m_pBase + m_Size);
  680. return *m_pCur;
  681. }
  682. operator void*()
  683. {
  684. return m_pCur;
  685. }
  686. T& operator*()
  687. {
  688. ASSERT(m_pCur < m_pBase + m_Size);
  689. return *m_pCur;
  690. }
  691. // increment/decrement
  692. T* operator+(UINT Inc)
  693. {
  694. ASSERT(m_pBase + m_Size > m_pCur + Inc);
  695. return (m_pBase + Inc);
  696. }
  697. T* operator-(UINT Dec)
  698. {
  699. ASSERT(m_pBase >= m_pCur - Dec);
  700. m_pCur -= Dec;
  701. return m_pCur;
  702. }
  703. //prefix
  704. T* operator++()
  705. {
  706. ASSERT(m_pBase + m_Size > m_pCur - 1);
  707. return ++m_pCur;
  708. }
  709. //postfix
  710. T* operator++(int inc)
  711. {
  712. pCur
  713. ASSERT(m_pBase + m_Size > m_pCur);
  714. return m_pCur++;
  715. }
  716. //prefix
  717. T* operator--()
  718. {
  719. ASSERT(m_pCur > m_pBase);
  720. return --m_pCur;
  721. }
  722. //postfix
  723. T* operator--(int inc)
  724. {
  725. ASSERT(m_pCur > m_pBase);
  726. return m_pCur--;
  727. }
  728. T** operator&()
  729. {
  730. return &m_pBase;
  731. }
  732. // subscripting
  733. T& operator[](UINT Index)
  734. {
  735. ASSERT(Index < m_Size);
  736. return m_pBase[Index];
  737. }
  738. void Attach(T* pT, UINT Size = 1)
  739. {
  740. ASSERT(!m_pBase);
  741. m_pBase = pT;
  742. m_pCur = m_pBase;
  743. m_Size = Size;
  744. }
  745. void Detach()
  746. {
  747. m_pBase = NULL;
  748. }
  749. UINT GetSize()
  750. {
  751. return m_Size;
  752. }
  753. private:
  754. T* m_pBase;
  755. T* m_pCur;
  756. UINT m_Size;
  757. };
  758. template<class T>
  759. class SafePtr
  760. {
  761. public:
  762. SafePtr(T* p)
  763. {
  764. __p = p;
  765. }
  766. SafePtr()
  767. {
  768. __p = NULL;
  769. }
  770. ~SafePtr()
  771. {
  772. if (__p)
  773. {
  774. delete __p;
  775. }
  776. }
  777. void Attach(T* p)
  778. {
  779. ASSERT(NULL == __p);
  780. __p = p;
  781. }
  782. void Detach()
  783. {
  784. __p = NULL;
  785. }
  786. T* operator->()
  787. {
  788. ASSERT(__p);
  789. return __p;
  790. }
  791. T& operator*()
  792. {
  793. ASSERT(__p);
  794. return *__p;
  795. }
  796. operator T*()
  797. {
  798. return __p;
  799. }
  800. operator T&()
  801. {
  802. ASSERT(__p);
  803. return *__p;
  804. }
  805. private:
  806. T* __p;
  807. };
  808. class CPropPageProvider;
  809. class CPropSheetData
  810. {
  811. public:
  812. CPropSheetData();
  813. ~CPropSheetData();
  814. virtual BOOL Create(HINSTANCE hInst, HWND hwndParent, UINT MaxPages, LONG_PTR lConsoleHandle = 0);
  815. BOOL InsertPage(HPROPSHEETPAGE hPage, int Index = -1);
  816. INT_PTR DoSheet()
  817. {
  818. return ::PropertySheet(&m_psh);
  819. }
  820. HWND GetWindowHandle()
  821. {
  822. return m_hWnd;
  823. }
  824. void PageCreateNotify(HWND hWnd);
  825. void PageDestroyNotify(HWND hWnd);
  826. PROPSHEETHEADER m_psh;
  827. BOOL PropertyChangeNotify(LPARAM lParam);
  828. void AddProvider(CPropPageProvider* pProvider)
  829. {
  830. m_listProvider.AddTail(pProvider);
  831. }
  832. protected:
  833. UINT m_MaxPages;
  834. LONG_PTR m_lConsoleHandle;
  835. HWND m_hWnd;
  836. private:
  837. CList<CPropPageProvider*, CPropPageProvider*> m_listProvider;
  838. };
  839. class CDialog
  840. {
  841. public:
  842. CDialog(int TemplateId) : m_hDlg(NULL), m_TemplateId(TemplateId)
  843. {}
  844. virtual ~CDialog()
  845. {}
  846. static INT_PTR CALLBACK DialogWndProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
  847. INT_PTR DoModal(HWND hwndParent, LPARAM lParam )
  848. {
  849. return DialogBoxParam(g_hInstance, MAKEINTRESOURCE(m_TemplateId), hwndParent, DialogWndProc, lParam);
  850. }
  851. void DoModaless(HWND hwndParent, LPARAM lParam)
  852. {
  853. m_hDlg = CreateDialogParam(g_hInstance, MAKEINTRESOURCE(m_TemplateId), hwndParent, DialogWndProc, lParam);
  854. }
  855. virtual BOOL OnInitDialog()
  856. {
  857. return TRUE;
  858. }
  859. virtual void OnCommand(WPARAM wParam, LPARAM lParam)
  860. {
  861. UNREFERENCED_PARAMETER(wParam);
  862. UNREFERENCED_PARAMETER(lParam);
  863. }
  864. virtual BOOL OnNotify(LPNMHDR pnmhdr)
  865. {
  866. UNREFERENCED_PARAMETER(pnmhdr);
  867. return FALSE;
  868. }
  869. virtual BOOL OnDestroy()
  870. {
  871. return FALSE;
  872. }
  873. virtual BOOL OnHelp(LPHELPINFO pHelpInfo)
  874. {
  875. UNREFERENCED_PARAMETER(pHelpInfo);
  876. return FALSE;
  877. }
  878. virtual BOOL OnContextMenu(HWND hWnd, WORD xPos, WORD yPos)
  879. {
  880. UNREFERENCED_PARAMETER(hWnd);
  881. UNREFERENCED_PARAMETER(xPos);
  882. UNREFERENCED_PARAMETER(yPos);
  883. return FALSE;
  884. }
  885. HWND GetControl(int idControl)
  886. {
  887. return GetDlgItem(m_hDlg, idControl);
  888. }
  889. operator HWND()
  890. {
  891. return m_hDlg;
  892. }
  893. HWND m_hDlg;
  894. private:
  895. int m_TemplateId;
  896. };
  897. #endif // __UTILS_H_