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.

340 lines
7.0 KiB

  1. // Util.h : Helper functions and classes
  2. #ifndef __UTIL_H_
  3. #define __UTIL_H_
  4. #include "mlatl.h"
  5. extern class CMLAlloc* g_pMalloc;
  6. /////////////////////////////////////////////////////////////////////////////
  7. // CMLAlloc
  8. class CMLAlloc
  9. {
  10. public:
  11. CMLAlloc(void);
  12. ~CMLAlloc(void);
  13. void* Alloc(ULONG cb);
  14. void* Realloc(void* pv, ULONG cb);
  15. void Free(void* pv);
  16. private:
  17. IMalloc* m_pIMalloc;
  18. };
  19. /////////////////////////////////////////////////////////////////////////////
  20. // CMLList
  21. class CMLList
  22. {
  23. public:
  24. inline CMLList(int cbCell, int cbIncrement);
  25. inline ~CMLList(void);
  26. HRESULT Add(void** ppv);
  27. HRESULT Remove(void* pv);
  28. struct CCell
  29. {
  30. CCell* m_pNext;
  31. };
  32. protected:
  33. inline void AssertPV(void*pv) const;
  34. inline void* MemAlloc(ULONG cb) {return ::g_pMalloc->Alloc(cb);}
  35. inline void* MemRealloc(void* pv, ULONG cb) {return ::g_pMalloc->Realloc(pv, cb);}
  36. inline void MemFree(void* pv) {::g_pMalloc->Free(pv);}
  37. private:
  38. const int m_cbCell; // The size, in bytes, of a cell
  39. const int m_cbIncrement; // The size, in bytes, to increase the buffer at a time
  40. CCell* m_pBuf; // Pointer to the buffer
  41. int m_cCell; // The number of cells allocated
  42. CCell* m_pFree; // Pointer to a cell the top of free link
  43. };
  44. CMLList::CMLList(int cbCell, int cbIncrement) :
  45. m_cbCell(cbCell),
  46. m_cbIncrement(cbIncrement),
  47. m_pBuf(NULL),
  48. m_cCell(0),
  49. m_pFree(NULL)
  50. {
  51. ASSERT(cbCell >= sizeof(CCell));
  52. ASSERT(cbIncrement >= cbCell);
  53. }
  54. CMLList::~CMLList(void)
  55. {
  56. if (m_pBuf)
  57. {
  58. #ifdef DEBUG
  59. int cCell = 0;
  60. for (CCell* pCell = m_pFree; pCell; pCell = pCell->m_pNext)
  61. {
  62. if (++cCell > m_cCell)
  63. {
  64. ASSERT(FALSE); // Free link is broken
  65. break;
  66. }
  67. }
  68. ASSERT(cCell < m_cCell); // Memory leak!?
  69. #endif
  70. MemFree(m_pBuf);
  71. }
  72. }
  73. void CMLList::AssertPV(void*pv) const
  74. {
  75. ASSERT(pv >= m_pBuf);
  76. ASSERT(pv < m_pBuf + m_cbCell * m_cCell);
  77. ASSERT(((CCell*)pv - m_pBuf) % m_cbCell == 0);
  78. }
  79. /////////////////////////////////////////////////////////////////////////////
  80. // CMLListLru
  81. class CMLListLru : public CMLList
  82. {
  83. public:
  84. inline CMLListLru(int cbCell, int cbIncrement);
  85. inline ~CMLListLru(void);
  86. HRESULT Add(void** ppv);
  87. HRESULT Remove(void* pv);
  88. inline HRESULT Top(void** ppv) const;
  89. inline HRESULT Next(void* pv, void** ppv) const;
  90. typedef CMLList::CCell CCell;
  91. private:
  92. CCell* m_pTop;
  93. };
  94. CMLListLru::CMLListLru(int cbCell, int cbIncrement) :
  95. CMLList(cbCell, cbIncrement),
  96. m_pTop(NULL)
  97. {
  98. }
  99. CMLListLru::~CMLListLru(void)
  100. {
  101. #ifdef DEBUG
  102. ASSERT(!m_pTop); // Memory Leak?
  103. while (m_pTop)
  104. Remove(m_pTop);
  105. #endif
  106. }
  107. HRESULT CMLListLru::Top(void** ppv) const
  108. {
  109. *ppv = (void*)m_pTop;
  110. return S_OK;
  111. }
  112. HRESULT CMLListLru::Next(void* pv, void** ppv) const
  113. {
  114. AssertPV(pv);
  115. const CCell* const pCell = (const CCell* const)pv;
  116. if (pCell->m_pNext)
  117. AssertPV(pCell->m_pNext);
  118. *ppv = (void*)pCell->m_pNext;
  119. return S_OK;
  120. }
  121. /////////////////////////////////////////////////////////////////////////////
  122. // CMLListFast - double linked list
  123. class CMLListFast : public CMLList
  124. {
  125. public:
  126. inline CMLListFast(int cbCell, int cbIncrement);
  127. inline ~CMLListFast(void);
  128. HRESULT Add(void** ppv);
  129. HRESULT Remove(void* pv);
  130. inline HRESULT Top(void** ppv) const;
  131. inline HRESULT Bottom(void** ppv) const;
  132. inline HRESULT Next(void* pv, void** ppv) const;
  133. inline HRESULT Prev(void* pv, void** ppv) const;
  134. struct CCell : public CMLList::CCell
  135. {
  136. CCell* m_pPrev;
  137. };
  138. private:
  139. CCell* m_pTop;
  140. };
  141. CMLListFast::CMLListFast(int cbCell, int cbIncrement) :
  142. CMLList(cbCell, cbIncrement),
  143. m_pTop(NULL)
  144. {
  145. ASSERT(cbCell >= sizeof(CCell));
  146. }
  147. CMLListFast::~CMLListFast(void)
  148. {
  149. #ifdef DEBUG
  150. ASSERT(!m_pTop); // Memory Leak?
  151. while (m_pTop)
  152. Remove(m_pTop);
  153. #endif
  154. }
  155. HRESULT CMLListFast::Top(void** ppv) const
  156. {
  157. *ppv = (void*)m_pTop;
  158. return S_OK;
  159. }
  160. HRESULT CMLListFast::Bottom(void** ppv) const
  161. {
  162. if (m_pTop)
  163. {
  164. return Prev(m_pTop, ppv);
  165. }
  166. else
  167. {
  168. *ppv = NULL;
  169. return S_OK;
  170. }
  171. }
  172. HRESULT CMLListFast::Next(void* pv, void** ppv) const
  173. {
  174. AssertPV(pv);
  175. const CCell* const pCell = (const CCell* const)pv;
  176. if (pCell->m_pNext)
  177. AssertPV(pCell->m_pNext);
  178. *ppv = (void*)pCell->m_pNext;
  179. return S_OK;
  180. }
  181. HRESULT CMLListFast::Prev(void* pv, void** ppv) const
  182. {
  183. AssertPV(pv);
  184. const CCell* const pCell = (const CCell* const)pv;
  185. if (pCell->m_pPrev)
  186. AssertPV(pCell->m_pPrev);
  187. *ppv = (void*)pCell->m_pPrev;
  188. return S_OK;
  189. }
  190. /////////////////////////////////////////////////////////////////////////////
  191. // CFireConnection
  192. template <class T, const IID* piid>
  193. class CFireConnection
  194. {
  195. public:
  196. inline CFireConnection(HRESULT& rhr);
  197. inline CFireConnection(HRESULT& rhr, IUnknown* const pUnk);
  198. inline ~CFireConnection(void);
  199. inline BOOL Next(void);
  200. inline T* Sink(void);
  201. protected:
  202. HRESULT* const m_phr;
  203. IEnumConnections* m_pEnumConn;
  204. CONNECTDATA m_cd;
  205. T* m_pSink;
  206. };
  207. template <class T, const IID* piid>
  208. CFireConnection<T, piid>::CFireConnection(HRESULT& rhr) :
  209. m_phr(&rhr),
  210. m_pEnumConn(NULL),
  211. m_pSink(NULL)
  212. {
  213. ASSERT_THIS;
  214. ASSERT_READ_PTR(piid);
  215. ASSERT_WRITE_PTR(m_phr);
  216. *m_phr = S_OK;
  217. }
  218. template <class T, const IID* piid>
  219. CFireConnection<T, piid>::CFireConnection(HRESULT& rhr, IUnknown* const pUnk) :
  220. m_phr(&rhr),
  221. m_pEnumConn(NULL),
  222. m_pSink(NULL)
  223. {
  224. ASSERT_THIS;
  225. ASSERT_READ_PTR(piid);
  226. ASSERT_WRITE_PTR(m_phr);
  227. ASSERT_READ_PTR(pUnk);
  228. IConnectionPointContainer* pcpc;
  229. if (SUCCEEDED(*m_phr = pUnk->QueryInterface(IID_IConnectionPointContainer, (void**)&pcpc)))
  230. {
  231. ASSERT_READ_PTR(pcpc);
  232. IConnectionPoint* pcp;
  233. if (SUCCEEDED(*m_phr = pcpc->FindConnectionPoint(*piid, &pcp)))
  234. {
  235. ASSERT_READ_PTR(pcp);
  236. if (SUCCEEDED(*m_phr = pcp->EnumConnections(&m_pEnumConn)))
  237. {
  238. ASSERT_READ_PTR(m_pEnumConn);
  239. }
  240. else
  241. {
  242. m_pEnumConn = NULL;
  243. }
  244. pcp->Release();
  245. }
  246. pcpc->Release();
  247. }
  248. }
  249. template <class T, const IID* piid>
  250. CFireConnection<T, piid>::~CFireConnection(void)
  251. {
  252. if (m_pSink)
  253. m_pSink->Release();
  254. if (m_pEnumConn)
  255. m_pEnumConn->Release();
  256. }
  257. template <class T, const IID* piid>
  258. BOOL CFireConnection<T, piid>::Next(void)
  259. {
  260. if (SUCCEEDED(*m_phr))
  261. ASSERT_READ_PTR(m_pEnumConn);
  262. if (SUCCEEDED(*m_phr) &&
  263. (*m_phr = m_pEnumConn->Next(1, &m_cd, NULL)) == S_OK)
  264. {
  265. if (m_pSink)
  266. {
  267. m_pSink->Release();
  268. m_pSink = NULL;
  269. }
  270. if (SUCCEEDED(*m_phr = m_cd.pUnk->QueryInterface(*piid, (void**)&m_pSink)))
  271. ASSERT_READ_PTR(m_pSink);
  272. }
  273. return SUCCEEDED(*m_phr);
  274. }
  275. template <class T, const IID* piid>
  276. T* CFireConnection<T, piid>::Sink(void)
  277. {
  278. return m_pSink;
  279. }
  280. #endif //__UTIL_H_