Leaked source code of windows server 2003
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.

263 lines
6.0 KiB

  1. /*************************************************************************
  2. **
  3. ** This is a part of the Microsoft Source Code Samples.
  4. **
  5. ** Copyright 1992 - 1998 Microsoft Corporation. All rights reserved.
  6. **
  7. ** This source code is only intended as a supplement to Microsoft Development
  8. ** Tools and/or WinHelp documentation. See these sources for detailed
  9. ** information regarding the Microsoft samples programs.
  10. **
  11. ** OLE Automation TypeLibrary Browse Helper Sample
  12. **
  13. ** enumvar.cpp
  14. **
  15. ** CEnumVariant implementation
  16. **
  17. ** Written by Microsoft Product Support Services, Windows Developer Support
  18. **
  19. *************************************************************************/
  20. #include <windows.h>
  21. #include "precomp.h"
  22. #include "Enumvar.h"
  23. /*
  24. * CEnumVariant::Create
  25. *
  26. * Purpose:
  27. * Creates an instance of the IEnumVARIANT enumerator object and initializes it.
  28. *
  29. * Parameters:
  30. * psa Safe array containing items to be enumerated.
  31. * cElements Number of items to be enumerated.
  32. * ppenumvariant Returns enumerator object.
  33. *
  34. * Return Value:
  35. * HRESULT
  36. *
  37. */
  38. //static
  39. HRESULT
  40. CEnumVariant::Create(SAFEARRAY FAR* psa, ULONG cElements, CEnumVariant** ppenumvariant)
  41. {
  42. HRESULT hr;
  43. CEnumVariant FAR* penumvariant = NULL;
  44. long lLBound;
  45. *ppenumvariant = NULL;
  46. penumvariant = new CEnumVariant();
  47. if (penumvariant == NULL)
  48. goto error;
  49. penumvariant->m_cRef = 0;
  50. // Copy elements into safe array that is used in enumerator implemenatation and
  51. // initialize state of enumerator.
  52. hr = SafeArrayGetLBound(psa, 1, &lLBound);
  53. if (FAILED(hr))
  54. goto error;
  55. penumvariant->m_cElements = cElements;
  56. penumvariant->m_lLBound = lLBound;
  57. penumvariant->m_lCurrent = lLBound;
  58. hr = SafeArrayCopy(psa, &penumvariant->m_psa);
  59. if (FAILED(hr))
  60. goto error;
  61. *ppenumvariant = penumvariant;
  62. return NOERROR;
  63. error:
  64. if (penumvariant == NULL)
  65. return E_OUTOFMEMORY;
  66. if (penumvariant->m_psa)
  67. SafeArrayDestroy(penumvariant->m_psa);
  68. penumvariant->m_psa = NULL;
  69. delete penumvariant;
  70. return hr;
  71. }
  72. /*
  73. * CEnumVariant::CEnumVariant
  74. *
  75. * Purpose:
  76. * Constructor for CEnumVariant object. Initializes members to NULL.
  77. *
  78. */
  79. CEnumVariant::CEnumVariant()
  80. {
  81. m_psa = NULL;
  82. }
  83. /*
  84. * CEnumVariant::~CEnumVariant
  85. *
  86. * Purpose:
  87. * Destructor for CEnumVariant object.
  88. *
  89. */
  90. CEnumVariant::~CEnumVariant()
  91. {
  92. if (m_psa) SafeArrayDestroy(m_psa);
  93. }
  94. /*
  95. * CEnumVariant::QueryInterface, AddRef, Release
  96. *
  97. * Purpose:
  98. * Implements IUnknown::QueryInterface, AddRef, Release
  99. *
  100. */
  101. STDMETHODIMP
  102. CEnumVariant::QueryInterface(REFIID iid, void FAR* FAR* ppv)
  103. {
  104. *ppv = NULL;
  105. if (iid == IID_IUnknown || iid == IID_IEnumVARIANT)
  106. *ppv = this;
  107. else return E_NOINTERFACE;
  108. AddRef();
  109. return NOERROR;
  110. }
  111. STDMETHODIMP_(ULONG)
  112. CEnumVariant::AddRef(void)
  113. {
  114. #ifdef _DEBUG
  115. TCHAR ach[50];
  116. wsprintf(ach, TEXT("Ref = %ld, Enum\r\n"), m_cRef+1);
  117. TRACE_OUT((ach));
  118. #endif
  119. return ++m_cRef; // AddRef Application Object if enumerator will outlive application object
  120. }
  121. STDMETHODIMP_(ULONG)
  122. CEnumVariant::Release(void)
  123. {
  124. #ifdef _DEBUG
  125. TCHAR ach[50];
  126. wsprintf(ach, TEXT("Ref = %ld, Enum\r\n"), m_cRef-1);
  127. TRACE_OUT((ach));
  128. #endif
  129. if(--m_cRef == 0)
  130. {
  131. delete this;
  132. return 0;
  133. }
  134. return m_cRef;
  135. }
  136. /*
  137. * CEnumVariant::Next
  138. *
  139. * Purpose:
  140. * Retrieves the next cElements elements. Implements IEnumVARIANT::Next.
  141. *
  142. */
  143. STDMETHODIMP
  144. CEnumVariant::Next(ULONG cElements, VARIANT FAR* pvar, ULONG FAR* pcElementFetched)
  145. {
  146. HRESULT hr;
  147. ULONG l;
  148. long l1;
  149. ULONG l2;
  150. if (pcElementFetched != NULL)
  151. *pcElementFetched = 0;
  152. // Retrieve the next cElements elements.
  153. for (l1=m_lCurrent, l2=0; l1<(long)(m_lLBound+m_cElements) && l2<cElements; l1++, l2++)
  154. {
  155. hr = SafeArrayGetElement(m_psa, &l1, &pvar[l2]);
  156. if (FAILED(hr))
  157. goto error;
  158. }
  159. // Set count of elements retrieved
  160. if (pcElementFetched != NULL)
  161. *pcElementFetched = l2;
  162. m_lCurrent = l1;
  163. return (l2 < cElements) ? S_FALSE : NOERROR;
  164. error:
  165. for (l=0; l<cElements; l++)
  166. VariantClear(&pvar[l]);
  167. return hr;
  168. }
  169. /*
  170. * CEnumVariant::Skip
  171. *
  172. * Purpose:
  173. * Skips the next cElements elements. Implements IEnumVARIANT::Skip.
  174. *
  175. */
  176. STDMETHODIMP
  177. CEnumVariant::Skip(ULONG cElements)
  178. {
  179. m_lCurrent += cElements;
  180. if (m_lCurrent > (long)(m_lLBound+m_cElements))
  181. {
  182. m_lCurrent = m_lLBound+m_cElements;
  183. return S_FALSE;
  184. }
  185. else return NOERROR;
  186. }
  187. /*
  188. * CEnumVariant::Reset
  189. *
  190. * Purpose:
  191. * Resets the current element in the enumerator to the beginning. Implements IEnumVARIANT::Reset.
  192. *
  193. */
  194. STDMETHODIMP
  195. CEnumVariant::Reset()
  196. {
  197. m_lCurrent = m_lLBound;
  198. return NOERROR;
  199. }
  200. /*
  201. * CEnumVariant::Clone
  202. *
  203. * Purpose:
  204. * Creates a copy of the current enumeration state. Implements IEnumVARIANT::Clone.
  205. *
  206. */
  207. STDMETHODIMP
  208. CEnumVariant::Clone(IEnumVARIANT FAR* FAR* ppenum)
  209. {
  210. CEnumVariant FAR* penum = NULL;
  211. HRESULT hr;
  212. *ppenum = NULL;
  213. hr = CEnumVariant::Create(m_psa, m_cElements, &penum);
  214. if (FAILED(hr))
  215. goto error;
  216. penum->AddRef();
  217. penum->m_lCurrent = m_lCurrent;
  218. *ppenum = penum;
  219. return NOERROR;
  220. error:
  221. if (penum)
  222. penum->Release();
  223. return hr;
  224. }