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.

226 lines
5.6 KiB

  1. // Copyright (C) 1996-1997 Microsoft Corporation. All rights reserved.
  2. //
  3. // implementation of a generic enumerator object.
  4. //
  5. #include "header.h"
  6. #include "StdEnum.H"
  7. #ifndef _DEBUG
  8. #undef THIS_FILE
  9. static const char THIS_FILE[] = __FILE__;
  10. #endif
  11. //=--------------------------------------------------------------------------=
  12. // CStandardEnum::CStandardEnum
  13. //=--------------------------------------------------------------------------=
  14. // create the object and initialize the refcount
  15. //
  16. // Parameters:
  17. // REFCLSID - [in] type of enumerator that we are
  18. // int - [in] number of elements in the enumeration
  19. // int - [in] size of each element
  20. // void * - [in] pointer to element data
  21. // void (WINAPI *pfnCopyElement)(void *, const void *, DWORD)
  22. // - [in] copying function
  23. //
  24. // Notes:
  25. //
  26. #pragma warning(disable:4355) // using 'this' in constructor
  27. CStandardEnum::CStandardEnum
  28. (
  29. REFCLSID rclsid,
  30. int cElements,
  31. int cbElementSize,
  32. void *rgElements,
  33. void (WINAPI *pfnCopyElement)(void *, const void *, DWORD)
  34. )
  35. : CUnknownObject(NULL, (IEnumGeneric *)this),
  36. m_iid(rclsid),
  37. m_cElements(cElements),
  38. m_cbElementSize(cbElementSize),
  39. m_iCurrent(0),
  40. m_rgElements(rgElements),
  41. m_pfnCopyElement(pfnCopyElement)
  42. {
  43. m_pEnumClonedFrom = NULL;
  44. }
  45. // #pragma warning(default:4355) // using 'this' in constructor
  46. CStandardEnum::~CStandardEnum ()
  47. {
  48. // if we're a cloned object, then just release our parent object and
  49. // we're done. otherwise, free up the allocated memory we were given
  50. //
  51. if (m_pEnumClonedFrom)
  52. m_pEnumClonedFrom->Release();
  53. else {
  54. if (m_rgElements)
  55. lcFree(m_rgElements);
  56. }
  57. }
  58. //=--------------------------------------------------------------------------=
  59. // CStandardEnum::InternalQueryInterface
  60. //=--------------------------------------------------------------------------=
  61. // we support our internal iid, and that's all
  62. //
  63. // Parameters:
  64. // REFIID - [in] interface they want
  65. // void ** - [out] where they want to put the resulting object ptr.
  66. //
  67. // Output:
  68. // HRESULT - S_OK, E_NOINTERFACE
  69. //
  70. // Notes:
  71. //
  72. HRESULT CStandardEnum::InternalQueryInterface
  73. (
  74. REFIID riid,
  75. void **ppvObjOut
  76. )
  77. {
  78. if (DO_GUIDS_MATCH(riid, m_iid)) {
  79. ExternalAddRef();
  80. *ppvObjOut = (IEnumGeneric *)this;
  81. return S_OK;
  82. }
  83. return E_NOINTERFACE;
  84. }
  85. //=--------------------------------------------------------------------------=
  86. // CStandardEnum::Next
  87. //=--------------------------------------------------------------------------=
  88. // returns the next dude in our iteration
  89. //
  90. // Parameters:
  91. // unsigned long - [in] count of elements requested
  92. // void * - [out] array of slots to put values in.
  93. // unsigned long * - [out] actual number fetched
  94. //
  95. // Output:
  96. // HRESULT - S_OK, E_INVALIDARG, S_FALSE
  97. //
  98. // Notes:
  99. //
  100. STDMETHODIMP CStandardEnum::Next
  101. (
  102. unsigned long cElm,
  103. void *rgDest,
  104. unsigned long *pcElmOut
  105. )
  106. {
  107. unsigned long cElementsFetched = 0;
  108. void *pElementDest = rgDest;
  109. const void *pElementSrc = (const BYTE *)m_rgElements + (m_cbElementSize * m_iCurrent);
  110. while (cElementsFetched < cElm) {
  111. // if we hit EOF, break out
  112. //
  113. if (m_iCurrent >= m_cElements)
  114. break;
  115. // copy the element out for them
  116. //
  117. m_pfnCopyElement(pElementDest, pElementSrc, m_cbElementSize);
  118. // increase the counters
  119. //
  120. pElementDest = (LPBYTE)pElementDest + m_cbElementSize;
  121. pElementSrc = (const BYTE *)pElementSrc + m_cbElementSize;
  122. m_iCurrent++;
  123. cElementsFetched++;
  124. }
  125. if (pcElmOut)
  126. *pcElmOut = cElementsFetched;
  127. return (cElementsFetched < cElm)? S_FALSE : S_OK;
  128. }
  129. //=--------------------------------------------------------------------------=
  130. // CStandardEnum::Skip
  131. //=--------------------------------------------------------------------------=
  132. // skips the requested number of rows.
  133. //
  134. // Parameters:
  135. // unsigned long - [in] number to skip
  136. //
  137. // Output:
  138. // HRESULT - S_OK, S_FALSE
  139. //
  140. // Notes:
  141. //
  142. STDMETHODIMP CStandardEnum::Skip
  143. (
  144. unsigned long cSkip
  145. )
  146. {
  147. // handle running off the end
  148. //
  149. if (m_iCurrent + (int)cSkip > m_cElements) {
  150. m_iCurrent = m_cElements;
  151. return S_FALSE;
  152. }
  153. m_iCurrent += cSkip;
  154. return S_OK;
  155. }
  156. //=--------------------------------------------------------------------------=
  157. // CStandardEnum::Reset
  158. //=--------------------------------------------------------------------------=
  159. // reset the counter.
  160. //
  161. // Output:
  162. // HRESULT - S_OK
  163. //
  164. // Notes:
  165. //
  166. STDMETHODIMP CStandardEnum::Reset
  167. (
  168. void
  169. )
  170. {
  171. m_iCurrent = 0;
  172. return S_OK;
  173. }
  174. //=--------------------------------------------------------------------------=
  175. // CStandardEnum::Clone
  176. //=--------------------------------------------------------------------------=
  177. // clones the object and gives the new one the same position
  178. //
  179. // Parameters:
  180. // IEnumVARIANT ** - [out] where to put the new object.
  181. //
  182. // Output;
  183. // HRESULT - S_OK, E_OUTOFMEMORY
  184. //
  185. // Notes:
  186. //
  187. STDMETHODIMP CStandardEnum::Clone
  188. (
  189. IEnumGeneric **ppEnumClone
  190. )
  191. {
  192. CStandardEnum *pNewEnum;
  193. pNewEnum = new CStandardEnum(m_iid, m_cElements, m_cbElementSize, m_rgElements, m_pfnCopyElement);
  194. RETURN_ON_NULLALLOC(pNewEnum);
  195. // hold on to who we were cloned from so m_rgElements stays alive, and we don't
  196. // have to copy it.
  197. //
  198. pNewEnum->m_pEnumClonedFrom = this;
  199. // AddRef() ourselves on their behalf.
  200. //
  201. AddRef();
  202. *ppEnumClone = (IEnumGeneric *)pNewEnum;
  203. return S_OK;
  204. }