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.

1133 lines
24 KiB

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