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.

280 lines
5.4 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997 - 2000
  5. //
  6. // File: H N C A E N U M . H
  7. //
  8. // Contents: Array enumerator
  9. //
  10. // Notes:
  11. //
  12. // Author: maiken 13 Dec 2000
  13. //
  14. //----------------------------------------------------------------------------
  15. //
  16. // This simple template acts as an enumerator for an array of COM pointers.
  17. //
  18. template<
  19. class EnumInterface,
  20. class ItemInterface
  21. >
  22. class CHNCArrayEnum :
  23. public CComObjectRootEx<CComMultiThreadModel>,
  24. public EnumInterface
  25. {
  26. private:
  27. typedef CHNCArrayEnum<EnumInterface, ItemInterface> _ThisClass;
  28. //
  29. // The array of pointers we're holding
  30. //
  31. ItemInterface **m_rgItems;
  32. //
  33. // Our position counter
  34. //
  35. ULONG m_pos;
  36. //
  37. // Number of pointers in m_rgItems
  38. //
  39. ULONG m_numItems;
  40. protected:
  41. VOID
  42. SetPos(
  43. ULONG pos
  44. )
  45. {
  46. _ASSERT( pos < m_numItems );
  47. m_pos = pos;
  48. };
  49. public:
  50. BEGIN_COM_MAP(_ThisClass)
  51. COM_INTERFACE_ENTRY(EnumInterface)
  52. END_COM_MAP()
  53. DECLARE_PROTECT_FINAL_CONSTRUCT()
  54. //
  55. // Object Creation
  56. //
  57. CHNCArrayEnum()
  58. {
  59. m_rgItems = NULL;
  60. m_pos = 0L;
  61. m_numItems = 0L;
  62. };
  63. HRESULT
  64. Initialize(
  65. ItemInterface **pItems,
  66. ULONG countItems
  67. )
  68. {
  69. HRESULT hr = S_OK;
  70. // pItems can be NULL to indicate an enumeration of nothing
  71. if( NULL != pItems )
  72. {
  73. _ASSERT( countItems > 0L );
  74. m_rgItems = new ItemInterface*[countItems];
  75. if( NULL == m_rgItems )
  76. {
  77. hr = E_OUTOFMEMORY;
  78. }
  79. else
  80. {
  81. ULONG i;
  82. for( i = 0L; i < countItems; i++ )
  83. {
  84. m_rgItems[i] = pItems[i];
  85. m_rgItems[i]->AddRef();
  86. }
  87. m_numItems = countItems;
  88. }
  89. }
  90. return hr;
  91. };
  92. //
  93. // Object Destruction
  94. //
  95. HRESULT
  96. FinalRelease()
  97. {
  98. if( m_rgItems != NULL )
  99. {
  100. ULONG i;
  101. for( i = 0L; i < m_numItems; i++ )
  102. {
  103. m_rgItems[i]->Release();
  104. }
  105. delete [] m_rgItems;
  106. }
  107. return S_OK;
  108. };
  109. //
  110. // EnumInterface methods
  111. //
  112. STDMETHODIMP
  113. Next(
  114. ULONG cElt,
  115. ItemInterface **rgElt,
  116. ULONG *pcEltFetched
  117. )
  118. {
  119. HRESULT hr = S_OK;
  120. ULONG ulCopied = 0L;
  121. if (NULL == rgElt)
  122. {
  123. hr = E_POINTER;
  124. }
  125. else if (0 == cElt)
  126. {
  127. hr = E_INVALIDARG;
  128. }
  129. else if (1 != cElt && NULL == pcEltFetched)
  130. {
  131. hr = E_POINTER;
  132. }
  133. if( S_OK == hr )
  134. {
  135. ulCopied = 0L;
  136. // Copy until we run out of items to copy;
  137. while( (m_pos < m_numItems) && (ulCopied < cElt) )
  138. {
  139. rgElt[ulCopied] = m_rgItems[m_pos];
  140. rgElt[ulCopied]->AddRef();
  141. m_pos++;
  142. ulCopied++;
  143. }
  144. if( ulCopied == cElt )
  145. {
  146. // Copied all the requested items
  147. hr = S_OK;
  148. }
  149. else
  150. {
  151. // Copied a subset of the requested items (or none)
  152. hr = S_FALSE;
  153. }
  154. if( pcEltFetched != NULL )
  155. {
  156. *pcEltFetched = ulCopied;
  157. }
  158. }
  159. return hr;
  160. };
  161. STDMETHODIMP
  162. Clone(
  163. EnumInterface **ppEnum
  164. )
  165. {
  166. HRESULT hr = S_OK;
  167. if (NULL == ppEnum)
  168. {
  169. hr = E_POINTER;
  170. }
  171. else
  172. {
  173. CComObject<_ThisClass> *pNewEnum;
  174. //
  175. // Create an initialized, new instance of ourselves
  176. //
  177. hr = CComObject<_ThisClass>::CreateInstance(&pNewEnum);
  178. if (SUCCEEDED(hr))
  179. {
  180. pNewEnum->AddRef();
  181. hr = pNewEnum->Initialize(m_rgItems, m_numItems);
  182. if (SUCCEEDED(hr))
  183. {
  184. pNewEnum->SetPos( m_pos );
  185. hr = pNewEnum->QueryInterface(
  186. IID_PPV_ARG(EnumInterface, ppEnum)
  187. );
  188. //
  189. // This QI should never fail, unless we were given
  190. // bogus template arguments.
  191. //
  192. _ASSERT(SUCCEEDED(hr));
  193. }
  194. pNewEnum->Release();
  195. }
  196. }
  197. return hr;
  198. };
  199. //
  200. // Skip and Reset simply delegate to the contained enumeration.
  201. //
  202. STDMETHODIMP
  203. Reset()
  204. {
  205. m_pos = 0L;;
  206. return S_OK;
  207. };
  208. STDMETHODIMP
  209. Skip(
  210. ULONG cElt
  211. )
  212. {
  213. HRESULT hr;
  214. if( m_pos + cElt < m_numItems )
  215. {
  216. m_pos += cElt;
  217. hr = S_OK;
  218. }
  219. else
  220. {
  221. m_pos = m_numItems - 1;
  222. hr = S_FALSE;
  223. }
  224. return hr;
  225. };
  226. };