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.

371 lines
8.3 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997 - 2000
  5. //
  6. // File: H N C E N U M . H
  7. //
  8. // Contents: Generic WMI enumerator template
  9. //
  10. // Notes:
  11. //
  12. // Author: jonburs 20 June 2000
  13. //
  14. //----------------------------------------------------------------------------
  15. template<
  16. class EnumInterface,
  17. class ItemInterface,
  18. class WrapperClass
  19. >
  20. class CHNCEnum :
  21. public CComObjectRootEx<CComMultiThreadModel>,
  22. public EnumInterface
  23. {
  24. private:
  25. typedef CHNCEnum<EnumInterface, ItemInterface, WrapperClass> _ThisClass;
  26. //
  27. // The IEnumWbemClassObject we're wrapping
  28. //
  29. IEnumWbemClassObject *m_pwcoEnum;
  30. //
  31. // The IWbemServices for our namespace
  32. //
  33. IWbemServices *m_pwsNamespace;
  34. public:
  35. BEGIN_COM_MAP(_ThisClass)
  36. COM_INTERFACE_ENTRY(EnumInterface)
  37. END_COM_MAP()
  38. DECLARE_PROTECT_FINAL_CONSTRUCT()
  39. //
  40. // Object Creation
  41. //
  42. CHNCEnum()
  43. {
  44. m_pwcoEnum = NULL;
  45. m_pwsNamespace = NULL;
  46. };
  47. HRESULT
  48. Initialize(
  49. IWbemServices *pwsNamespace,
  50. IEnumWbemClassObject *pwcoEnum
  51. )
  52. {
  53. _ASSERT(NULL == m_pwsNamespace);
  54. _ASSERT(NULL == m_pwcoEnum);
  55. _ASSERT(NULL != pwsNamespace);
  56. _ASSERT(NULL != pwcoEnum);
  57. m_pwcoEnum = pwcoEnum;
  58. m_pwcoEnum->AddRef();
  59. m_pwsNamespace = pwsNamespace;
  60. m_pwsNamespace->AddRef();
  61. return S_OK;
  62. };
  63. //
  64. // Object Destruction
  65. //
  66. HRESULT
  67. FinalRelease()
  68. {
  69. if (NULL != m_pwcoEnum)
  70. {
  71. m_pwcoEnum->Release();
  72. }
  73. if (NULL != m_pwsNamespace)
  74. {
  75. m_pwsNamespace->Release();
  76. }
  77. return S_OK;
  78. };
  79. //
  80. // EnumInterface methods
  81. //
  82. STDMETHODIMP
  83. Next(
  84. ULONG cElt,
  85. ItemInterface **rgElt,
  86. ULONG *pcEltFetched
  87. )
  88. {
  89. HRESULT hr = S_OK;
  90. ULONG cInstancesFetched = 0;
  91. IWbemClassObject **rgpwcoInstances = NULL;
  92. CComObject<WrapperClass> *pWrapper = NULL;
  93. LONG i;
  94. _ASSERT(NULL != m_pwcoEnum);
  95. if (NULL == rgElt)
  96. {
  97. hr = E_POINTER;
  98. }
  99. else if (0 == cElt)
  100. {
  101. hr = E_INVALIDARG;
  102. }
  103. else if (1 != cElt && NULL == pcEltFetched)
  104. {
  105. hr = E_POINTER;
  106. }
  107. if (S_OK == hr)
  108. {
  109. //
  110. // Zero the output array
  111. //
  112. ZeroMemory(rgElt, cElt * sizeof(ItemInterface*));
  113. //
  114. // Allocate enough memory to hold pointers to the instances we
  115. // were asked to fetch.
  116. //
  117. rgpwcoInstances = new IWbemClassObject*[cElt];
  118. if (NULL != rgpwcoInstances)
  119. {
  120. ZeroMemory(rgpwcoInstances, sizeof(IWbemClassObject*) * cElt);
  121. }
  122. else
  123. {
  124. hr = E_OUTOFMEMORY;
  125. }
  126. }
  127. if (S_OK == hr)
  128. {
  129. //
  130. // Grab the requested number of instances from the contained
  131. // WMI enumeration.
  132. //
  133. hr = m_pwcoEnum->Next(
  134. WBEM_INFINITE,
  135. cElt,
  136. rgpwcoInstances,
  137. &cInstancesFetched
  138. );
  139. }
  140. if (SUCCEEDED(hr))
  141. {
  142. //
  143. // For each instance we retrieved, create the wrapper
  144. // object.
  145. //
  146. for (i = 0;
  147. static_cast<ULONG>(i) < cInstancesFetched;
  148. i++)
  149. {
  150. hr = CComObject<WrapperClass>::CreateInstance(&pWrapper);
  151. if (SUCCEEDED(hr))
  152. {
  153. pWrapper->AddRef();
  154. hr = pWrapper->Initialize(
  155. m_pwsNamespace,
  156. rgpwcoInstances[i]
  157. );
  158. if (SUCCEEDED(hr))
  159. {
  160. //
  161. // QI for the desired interface, and place into
  162. // the output array
  163. //
  164. hr = pWrapper->QueryInterface(
  165. IID_PPV_ARG(ItemInterface, &rgElt[i])
  166. );
  167. //
  168. // This can only fail if we were given incorrect
  169. // template arguments.
  170. //
  171. _ASSERT(SUCCEEDED(hr));
  172. }
  173. pWrapper->Release();
  174. }
  175. if (FAILED(hr))
  176. {
  177. break;
  178. }
  179. }
  180. if (FAILED(hr))
  181. {
  182. //
  183. // Something went wrong, and we destroy all of the objects
  184. // we just created and QI'd. (The position of the last object
  185. // created is one less than the current value of i.)
  186. //
  187. for (i-- ; i >= 0; i--)
  188. {
  189. if (NULL != rgElt[i])
  190. {
  191. rgElt[i]->Release();
  192. }
  193. }
  194. }
  195. //
  196. // Release all of the instances we retrieved
  197. //
  198. for (ULONG j = 0; j < cInstancesFetched; j++)
  199. {
  200. if (NULL != rgpwcoInstances[j])
  201. {
  202. rgpwcoInstances[j]->Release();
  203. }
  204. }
  205. }
  206. //
  207. // If necessary, release the memory we used to hold the
  208. // instance pointers.
  209. //
  210. if (NULL != rgpwcoInstances)
  211. {
  212. delete [] rgpwcoInstances;
  213. }
  214. if (SUCCEEDED(hr))
  215. {
  216. //
  217. // Set the number of items we retrieved
  218. //
  219. if (NULL != pcEltFetched)
  220. {
  221. *pcEltFetched = cInstancesFetched;
  222. }
  223. //
  224. // Normalize return value
  225. //
  226. if (cInstancesFetched == cElt)
  227. {
  228. hr = S_OK;
  229. }
  230. else
  231. {
  232. hr = S_FALSE;
  233. }
  234. }
  235. return hr;
  236. };
  237. STDMETHODIMP
  238. Clone(
  239. EnumInterface **ppEnum
  240. )
  241. {
  242. HRESULT hr = S_OK;
  243. IEnumWbemClassObject *pwcoClonedEnum;
  244. CComObject<_ThisClass> *pNewEnum;
  245. if (NULL == ppEnum)
  246. {
  247. hr = E_POINTER;
  248. }
  249. else
  250. {
  251. //
  252. // Attempt to clone the embedded enumeration.
  253. //
  254. pwcoClonedEnum = NULL;
  255. hr = m_pwcoEnum->Clone(&pwcoClonedEnum);
  256. }
  257. if (WBEM_S_NO_ERROR == hr)
  258. {
  259. //
  260. // Create an initialized a new instance of ourselves
  261. //
  262. hr = CComObject<_ThisClass>::CreateInstance(&pNewEnum);
  263. if (SUCCEEDED(hr))
  264. {
  265. pNewEnum->AddRef();
  266. hr = pNewEnum->Initialize(m_pwsNamespace, pwcoClonedEnum);
  267. if (SUCCEEDED(hr))
  268. {
  269. hr = pNewEnum->QueryInterface(
  270. IID_PPV_ARG(EnumInterface, ppEnum)
  271. );
  272. //
  273. // This QI should never fail, unless we were given
  274. // bogus template arguments.
  275. //
  276. _ASSERT(SUCCEEDED(hr));
  277. }
  278. pNewEnum->Release();
  279. }
  280. //
  281. // Release the cloned enum. New enum object will have
  282. // AddReffed it...
  283. //
  284. pwcoClonedEnum->Release();
  285. }
  286. return hr;
  287. };
  288. //
  289. // Skip and Reset simply delegate to the contained enumeration.
  290. //
  291. STDMETHODIMP
  292. Reset()
  293. {
  294. _ASSERT(NULL != m_pwcoEnum);
  295. return m_pwcoEnum->Reset();
  296. };
  297. STDMETHODIMP
  298. Skip(
  299. ULONG cElt
  300. )
  301. {
  302. _ASSERT(NULL != m_pwcoEnum);
  303. return m_pwcoEnum->Skip(WBEM_INFINITE, cElt);
  304. };
  305. };