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.

317 lines
6.3 KiB

  1. //***************************************************************************
  2. //
  3. // Copyright (c) 1998-1999 Microsoft Corporation
  4. //
  5. // CONTVAR.CPP
  6. //
  7. // alanbos 15-Aug-96 Created.
  8. //
  9. // Defines the implementation of IEnumVARIANT for iterators over
  10. // ISWbemNamedValueSet
  11. //
  12. //***************************************************************************
  13. #include "precomp.h"
  14. //***************************************************************************
  15. //
  16. // CContextEnumVar::CContextEnumVar
  17. //
  18. // DESCRIPTION:
  19. //
  20. // Constructor.
  21. //
  22. //***************************************************************************
  23. CContextEnumVar::CContextEnumVar(CSWbemNamedValueSet *pContext, ULONG initialPos)
  24. {
  25. m_cRef = 0;
  26. m_pos = initialPos;
  27. m_pContext = pContext;
  28. m_pContext->AddRef ();
  29. InterlockedIncrement(&g_cObj);
  30. }
  31. //***************************************************************************
  32. //
  33. // CContextEnumVar::~CContextEnumVar
  34. //
  35. // DESCRIPTION:
  36. //
  37. // Destructor.
  38. //
  39. //***************************************************************************
  40. CContextEnumVar::~CContextEnumVar(void)
  41. {
  42. InterlockedDecrement(&g_cObj);
  43. if (m_pContext)
  44. m_pContext->Release ();
  45. }
  46. //***************************************************************************
  47. // HRESULT CContextEnumVar::QueryInterface
  48. // long CContextEnumVar::AddRef
  49. // long CContextEnumVar::Release
  50. //
  51. // DESCRIPTION:
  52. //
  53. // Standard Com IUNKNOWN functions.
  54. //
  55. //***************************************************************************
  56. STDMETHODIMP CContextEnumVar::QueryInterface (
  57. IN REFIID riid,
  58. OUT LPVOID *ppv
  59. )
  60. {
  61. *ppv=NULL;
  62. if (IID_IUnknown==riid || IID_IEnumVARIANT==riid)
  63. *ppv=this;
  64. if (NULL!=*ppv)
  65. {
  66. ((LPUNKNOWN)*ppv)->AddRef();
  67. return NOERROR;
  68. }
  69. return ResultFromScode(E_NOINTERFACE);
  70. }
  71. STDMETHODIMP_(ULONG) CContextEnumVar::AddRef(void)
  72. {
  73. InterlockedIncrement(&m_cRef);
  74. return m_cRef;
  75. }
  76. STDMETHODIMP_(ULONG) CContextEnumVar::Release(void)
  77. {
  78. InterlockedDecrement(&m_cRef);
  79. if (0L!=m_cRef)
  80. return m_cRef;
  81. delete this;
  82. return 0;
  83. }
  84. //***************************************************************************
  85. //
  86. // SCODE CContextEnumVar::Reset
  87. //
  88. // DESCRIPTION:
  89. //
  90. // Reset the enumeration
  91. //
  92. // PARAMETERS:
  93. //
  94. // RETURN VALUES:
  95. //
  96. // S_OK success
  97. // S_FALSE otherwise
  98. //
  99. //***************************************************************************
  100. HRESULT CContextEnumVar::Reset ()
  101. {
  102. m_pos = 0;
  103. return S_OK;
  104. }
  105. //***************************************************************************
  106. //
  107. // SCODE CContextEnumVar::Next
  108. //
  109. // DESCRIPTION:
  110. //
  111. // Get the next object in the enumeration
  112. //
  113. // PARAMETERS:
  114. //
  115. // lTimeout Number of ms to wait for object (or WBEM_INFINITE for
  116. // indefinite)
  117. // ppObject On return may contain the next element (if any)
  118. //
  119. // RETURN VALUES:
  120. //
  121. // S_OK success
  122. // S_FALSE otherwise
  123. //
  124. //***************************************************************************
  125. HRESULT CContextEnumVar::Next (
  126. ULONG cElements,
  127. VARIANT FAR* pVar,
  128. ULONG FAR* pcElementFetched
  129. )
  130. {
  131. HRESULT hr = S_OK;
  132. ULONG l2 = 0;
  133. if (NULL != pcElementFetched)
  134. *pcElementFetched = 0;
  135. if (NULL != pVar)
  136. {
  137. for (ULONG l = 0; l < cElements; l++)
  138. VariantInit (&pVar [l]);
  139. if (m_pContext)
  140. {
  141. // Retrieve the next cElements elements.
  142. if (SeekCurrentPosition ())
  143. {
  144. for (l2 = 0; l2 < cElements; l2++)
  145. {
  146. ISWbemNamedValue *pObject = NULL;
  147. if (SUCCEEDED(m_pContext->Next (0, &pObject)))
  148. {
  149. if (NULL == pObject)
  150. {
  151. break;
  152. }
  153. else
  154. {
  155. // Set the object into the variant array; note that pObject
  156. // has been addref'd as a result of the Next() call above
  157. pVar[l2].vt = VT_DISPATCH;
  158. pVar[l2].pdispVal = pObject;
  159. m_pos++;
  160. }
  161. }
  162. else
  163. break;
  164. }
  165. if (NULL != pcElementFetched)
  166. *pcElementFetched = l2;
  167. }
  168. }
  169. }
  170. return (l2 < cElements) ? S_FALSE : S_OK;
  171. }
  172. //***************************************************************************
  173. //
  174. // SCODE CContextEnumVar::Clone
  175. //
  176. // DESCRIPTION:
  177. //
  178. // Create a copy of this enumeration
  179. //
  180. // PARAMETERS:
  181. //
  182. // ppEnum on successful return addresses the clone
  183. //
  184. // RETURN VALUES:
  185. //
  186. // S_OK success
  187. // E_FAIL otherwise
  188. //
  189. //***************************************************************************
  190. HRESULT CContextEnumVar::Clone (
  191. IEnumVARIANT **ppEnum
  192. )
  193. {
  194. HRESULT hr = E_FAIL;
  195. if (NULL != ppEnum)
  196. {
  197. *ppEnum = NULL;
  198. if (m_pContext)
  199. {
  200. CContextEnumVar *pEnum = new CContextEnumVar (m_pContext, m_pos);
  201. if (!pEnum)
  202. hr = WBEM_E_OUT_OF_MEMORY;
  203. else if (FAILED(hr = pEnum->QueryInterface (IID_IEnumVARIANT, (PPVOID) ppEnum)))
  204. delete pEnum;
  205. }
  206. }
  207. return hr;
  208. }
  209. //***************************************************************************
  210. //
  211. // SCODE CContextEnumVar::Skip
  212. //
  213. // DESCRIPTION:
  214. //
  215. // Create a copy of this enumeration
  216. //
  217. // PARAMETERS:
  218. //
  219. // ppEnum on successful return addresses the clone
  220. //
  221. // RETURN VALUES:
  222. //
  223. // S_OK success
  224. // S_FALSE end of sequence reached prematurely
  225. //
  226. //***************************************************************************
  227. HRESULT CContextEnumVar::Skip(
  228. ULONG cElements
  229. )
  230. {
  231. HRESULT hr = S_FALSE;
  232. long count = 0;
  233. m_pContext->get_Count (&count);
  234. if (((ULONG) count) >= cElements + m_pos)
  235. {
  236. hr = S_OK;
  237. m_pos += cElements;
  238. }
  239. else
  240. m_pos = count;
  241. return hr;
  242. }
  243. //***************************************************************************
  244. //
  245. // SCODE CContextEnumVar::SeekCurrentPosition
  246. //
  247. // DESCRIPTION:
  248. //
  249. // Iterate to current position. Somewhat painful as there is no
  250. // underlying iterator so we have to reset and then step. Note that we
  251. // assume that the access to this iterator is apartment-threaded.
  252. //
  253. // PARAMETERS:
  254. //
  255. // ppEnum on successful return addresses the clone
  256. //
  257. // RETURN VALUES:
  258. //
  259. // S_OK success
  260. // S_FALSE end of sequence reached prematurely
  261. //
  262. //***************************************************************************
  263. bool CContextEnumVar::SeekCurrentPosition ()
  264. {
  265. ISWbemNamedValue *pDummyObject = NULL;
  266. m_pContext->BeginEnumeration ();
  267. // Traverse to the current position
  268. ULONG i = 0;
  269. for (; i < m_pos; i++)
  270. {
  271. if (WBEM_S_NO_ERROR != m_pContext->Next (0, &pDummyObject))
  272. break;
  273. else
  274. pDummyObject->Release ();
  275. }
  276. return (i == m_pos);
  277. }