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.

277 lines
7.6 KiB

  1. //=--------------------------------------------------------------------------=
  2. // StandardEnum.Cpp
  3. //=--------------------------------------------------------------------------=
  4. // Copyright 1995 Microsoft Corporation. All Rights Reserved.
  5. //
  6. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  7. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  8. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  9. // PARTICULAR PURPOSE.
  10. //=--------------------------------------------------------------------------=
  11. //
  12. // implementation of a generic enumerator object.
  13. //
  14. #include "pch.h"
  15. #include "StdEnum.H"
  16. SZTHISFILE
  17. //=--------------------------------------------------------------------------=
  18. // CStandardEnum::CStandardEnum
  19. //=--------------------------------------------------------------------------=
  20. // create the object and initialize the refcount
  21. //
  22. // Parameters:
  23. // none
  24. //
  25. // Notes: This default constructor only exists so that derived classes can be created
  26. // Internal debug checks have been added to confirm that internal
  27. // state is correctly set before use (calls to Next, Skip, etc)
  28. //
  29. //
  30. #pragma warning(disable:4355) // using 'this' in constructor
  31. CStandardEnum::CStandardEnum()
  32. : CUnknownObject(NULL, (IEnumGeneric *)this),
  33. m_iid(IID_IUnknown),
  34. m_cElements(0),
  35. m_cbElementSize(0),
  36. m_iCurrent(0),
  37. m_rgElements(NULL),
  38. m_pfnCopyElement(NULL)
  39. {
  40. m_pEnumClonedFrom = NULL;
  41. }
  42. #pragma warning(default:4355) // using 'this' in constructor
  43. //=--------------------------------------------------------------------------=
  44. // CStandardEnum::CStandardEnum
  45. //=--------------------------------------------------------------------------=
  46. // create the object and initialize the refcount
  47. //
  48. // Parameters:
  49. // REFCLSID - [in] type of enumerator that we are
  50. // int - [in] number of elements in the enumeration
  51. // int - [in] size of each element
  52. // void * - [in] pointer to element data
  53. // void (WINAPI *pfnCopyElement)(void *, const void *, DWORD)
  54. // - [in] copying function
  55. //
  56. // Notes:
  57. //
  58. #pragma warning(disable:4355) // using 'this' in constructor
  59. CStandardEnum::CStandardEnum
  60. (
  61. REFCLSID rclsid,
  62. int cElements,
  63. int cbElementSize,
  64. void *rgElements,
  65. void (WINAPI *pfnCopyElement)(void *, const void *, DWORD)
  66. )
  67. : CUnknownObject(NULL, (IEnumGeneric *)this),
  68. m_iid(rclsid),
  69. m_cElements(cElements),
  70. m_cbElementSize(cbElementSize),
  71. m_iCurrent(0),
  72. m_rgElements(rgElements),
  73. m_pfnCopyElement(pfnCopyElement)
  74. {
  75. m_pEnumClonedFrom = NULL;
  76. }
  77. #pragma warning(default:4355) // using 'this' in constructor
  78. //=--------------------------------------------------------------------------=
  79. // CStandardEnum::CStandardEnum
  80. //=--------------------------------------------------------------------------=
  81. // "it is not death, but dying, which is terrible."
  82. // - Henry Fielding (1707-54)
  83. //
  84. // Notes:
  85. //
  86. CStandardEnum::~CStandardEnum ()
  87. {
  88. // if we're a cloned object, then just release our parent object and
  89. // we're done. otherwise, free up the allocated memory we were given
  90. //
  91. if (m_pEnumClonedFrom)
  92. m_pEnumClonedFrom->Release();
  93. else {
  94. if (m_rgElements) CtlHeapFree(g_hHeap, 0, m_rgElements);
  95. }
  96. }
  97. //=--------------------------------------------------------------------------=
  98. // CStandardEnum::InternalQueryInterface
  99. //=--------------------------------------------------------------------------=
  100. // we support our internal iid, and that's all
  101. //
  102. // Parameters:
  103. // REFIID - [in] interface they want
  104. // void ** - [out] where they want to put the resulting object ptr.
  105. //
  106. // Output:
  107. // HRESULT - S_OK, E_NOINTERFACE
  108. //
  109. // Notes:
  110. //
  111. HRESULT CStandardEnum::InternalQueryInterface
  112. (
  113. REFIID riid,
  114. void **ppvObjOut
  115. )
  116. {
  117. if (DO_GUIDS_MATCH(riid, m_iid) || DO_GUIDS_MATCH(riid, IID_IUnknown))
  118. {
  119. ExternalAddRef();
  120. *ppvObjOut = (IEnumGeneric *)this;
  121. return S_OK;
  122. }
  123. return E_NOINTERFACE;
  124. }
  125. //=--------------------------------------------------------------------------=
  126. // CStandardEnum::Next
  127. //=--------------------------------------------------------------------------=
  128. // returns the next dude in our iteration
  129. //
  130. // Parameters:
  131. // unsigned long - [in] count of elements requested
  132. // void * - [out] array of slots to put values in.
  133. // unsigned long * - [out] actual number fetched
  134. //
  135. // Output:
  136. // HRESULT - S_OK, E_INVALIDARG, S_FALSE
  137. //
  138. // Notes:
  139. //
  140. STDMETHODIMP CStandardEnum::Next
  141. (
  142. unsigned long cElm,
  143. void *rgDest,
  144. unsigned long *pcElmOut
  145. )
  146. {
  147. ASSERT(m_pfnCopyElement, "NULL m_pfnCopyElement is invalid CStandardEnum state!");
  148. unsigned long cElementsFetched = 0;
  149. void *pElementDest = rgDest;
  150. const void *pElementSrc = (const BYTE *)m_rgElements + (m_cbElementSize * m_iCurrent);
  151. while (cElementsFetched < cElm) {
  152. // if we hit EOF, break out
  153. //
  154. if (m_iCurrent >= m_cElements)
  155. break;
  156. // copy the element out for them
  157. //
  158. m_pfnCopyElement(pElementDest, pElementSrc, m_cbElementSize);
  159. // increase the counters
  160. //
  161. pElementDest = (LPBYTE)pElementDest + m_cbElementSize;
  162. pElementSrc = (const BYTE *)pElementSrc + m_cbElementSize;
  163. m_iCurrent++;
  164. cElementsFetched++;
  165. }
  166. if (pcElmOut)
  167. *pcElmOut = cElementsFetched;
  168. return (cElementsFetched < cElm)? S_FALSE : S_OK;
  169. }
  170. //=--------------------------------------------------------------------------=
  171. // CStandardEnum::Skip
  172. //=--------------------------------------------------------------------------=
  173. // skips the requested number of rows.
  174. //
  175. // Parameters:
  176. // unsigned long - [in] number to skip
  177. //
  178. // Output:
  179. // HRESULT - S_OK, S_FALSE
  180. //
  181. // Notes:
  182. //
  183. STDMETHODIMP CStandardEnum::Skip
  184. (
  185. unsigned long cSkip
  186. )
  187. {
  188. ASSERT(m_pfnCopyElement, "NULL m_pfnCopyElement is invalid CStandardEnum state!");
  189. // handle running off the end
  190. //
  191. if (m_iCurrent + (int)cSkip > m_cElements) {
  192. m_iCurrent = m_cElements;
  193. return S_FALSE;
  194. }
  195. m_iCurrent += cSkip;
  196. return S_OK;
  197. }
  198. //=--------------------------------------------------------------------------=
  199. // CStandardEnum::Reset
  200. //=--------------------------------------------------------------------------=
  201. // reset the counter.
  202. //
  203. // Output:
  204. // HRESULT - S_OK
  205. //
  206. // Notes:
  207. //
  208. STDMETHODIMP CStandardEnum::Reset
  209. (
  210. void
  211. )
  212. {
  213. m_iCurrent = 0;
  214. return S_OK;
  215. }
  216. //=--------------------------------------------------------------------------=
  217. // CStandardEnum::Clone
  218. //=--------------------------------------------------------------------------=
  219. // clones the object and gives the new one the same position
  220. //
  221. // Parameters:
  222. // IEnumVARIANT ** - [out] where to put the new object.
  223. //
  224. // Output;
  225. // HRESULT - S_OK, E_OUTOFMEMORY
  226. //
  227. // Notes:
  228. //
  229. STDMETHODIMP CStandardEnum::Clone
  230. (
  231. IEnumGeneric **ppEnumClone
  232. )
  233. {
  234. ASSERT(m_pfnCopyElement, "NULL m_pfnCopyElement is invalid CStandardEnum state!");
  235. CStandardEnum *pNewEnum;
  236. *ppEnumClone = NULL;
  237. pNewEnum = New CStandardEnum(m_iid, m_cElements, m_cbElementSize, m_rgElements, m_pfnCopyElement);
  238. RETURN_ON_NULLALLOC(pNewEnum);
  239. // hold on to who we were cloned from so m_rgElements stays alive, and we don't
  240. // have to copy it.
  241. //
  242. pNewEnum->m_pEnumClonedFrom = this;
  243. pNewEnum->m_iCurrent = m_iCurrent;
  244. // AddRef() ourselves on their behalf.
  245. //
  246. AddRef();
  247. *ppEnumClone = (IEnumGeneric *)pNewEnum;
  248. return S_OK;
  249. }