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.

629 lines
15 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1999.
  5. //
  6. // File: I E N U M . C P P
  7. //
  8. // Contents: Implements the IEnumNetCfgBindingInterface,
  9. // IEnumNetCfgBindingPath, and IEnumNetCfgComponent COM
  10. // interfaces.
  11. //
  12. // Notes:
  13. //
  14. // Author: shaunco 15 Jan 1999
  15. //
  16. //----------------------------------------------------------------------------
  17. #include <pch.h>
  18. #pragma hdrstop
  19. #include "ibind.h"
  20. #include "ienum.h"
  21. #include "ncatl.h"
  22. #include "netcfg.h"
  23. /*
  24. A helper function for finishing up the semantics of a IEnumXXX::Next or
  25. IEnumXXX::Skip. Return S_OK if no error passed in and celt == celtFetched.
  26. Return S_FALSE if no error passed in and celt != celtFetched. If returning
  27. an error, release celt IUnknowns from rgelt.
  28. Returns: S_OK, S_FALSE, or an error code
  29. Author: shaunco 13 Jan 1999
  30. */
  31. HRESULT
  32. HrFinishNextOrSkipContract (
  33. IN HRESULT hr,
  34. IN ULONG celtFetched,
  35. IN ULONG celt,
  36. IN OUT IUnknown** rgelt,
  37. OUT ULONG* pceltFetched)
  38. {
  39. if (S_OK == hr)
  40. {
  41. if (pceltFetched)
  42. {
  43. *pceltFetched = celtFetched;
  44. }
  45. hr = (celtFetched == celt) ? S_OK : S_FALSE;
  46. }
  47. else
  48. {
  49. // For any failures, we need to release what we were about to return.
  50. // Set any output parameters to NULL.
  51. //
  52. if (rgelt)
  53. {
  54. for (ULONG ulIndex = 0; ulIndex < celt; ulIndex++)
  55. {
  56. ReleaseObj (rgelt[ulIndex]);
  57. rgelt[ulIndex] = NULL;
  58. }
  59. }
  60. if (pceltFetched)
  61. {
  62. *pceltFetched = 0;
  63. }
  64. }
  65. return hr;
  66. }
  67. //+---------------------------------------------------------------------------
  68. // CImplIEnumNetCfgBindingInterface -
  69. //
  70. /*
  71. Create an instance of a binding interface enumerator.
  72. Returns: S_OK or an error code
  73. Author: shaunco 13 Jan 1999
  74. */
  75. // static
  76. HRESULT
  77. CImplIEnumNetCfgBindingInterface::HrCreateInstance (
  78. IN CImplINetCfg* pINetCfg,
  79. IN CImplINetCfgBindingPath* pIPath,
  80. OUT IEnumNetCfgBindingInterface** ppIEnum)
  81. {
  82. HRESULT hr = E_OUTOFMEMORY;
  83. CImplIEnumNetCfgBindingInterface* pObj;
  84. pObj = new CComObject <CImplIEnumNetCfgBindingInterface>;
  85. if (pObj)
  86. {
  87. hr = S_OK;
  88. // Initialize our members.
  89. //
  90. pObj->m_pIPath = pIPath;
  91. // Do the standard CComCreator::CreateInstance stuff.
  92. //
  93. pObj->SetVoid (NULL);
  94. pObj->InternalFinalConstructAddRef ();
  95. hr = pObj->FinalConstruct ();
  96. pObj->InternalFinalConstructRelease ();
  97. // The last thing we do is addref any interfaces we hold.
  98. // We only do this if we are returning success.
  99. //
  100. if (S_OK == hr)
  101. {
  102. hr = pObj->QueryInterface (IID_IEnumNetCfgBindingInterface,
  103. (VOID**)ppIEnum);
  104. // The last thing we do is addref any interfaces we hold.
  105. // We only do this if we are returning success.
  106. //
  107. if (S_OK == hr)
  108. {
  109. AddRefObj (pIPath->GetUnknown());
  110. pObj->HoldINetCfg (pINetCfg);
  111. }
  112. }
  113. if (S_OK != hr)
  114. {
  115. delete pObj;
  116. }
  117. }
  118. TraceHr (ttidError, FAL, hr, FALSE,
  119. "CImplIEnumNetCfgBindingInterface::HrCreateInstance");
  120. return hr;
  121. }
  122. VOID
  123. CImplIEnumNetCfgBindingInterface::FinalRelease ()
  124. {
  125. AssertH (m_pIPath);
  126. ReleaseObj (m_pIPath->GetUnknown());
  127. CImplINetCfgHolder::FinalRelease();
  128. }
  129. HRESULT
  130. CImplIEnumNetCfgBindingInterface::HrNextOrSkip (
  131. IN ULONG celt,
  132. OUT INetCfgBindingInterface** rgelt,
  133. OUT ULONG* pceltFetched)
  134. {
  135. HRESULT hr;
  136. Assert (m_unIndex >= 1);
  137. // Important to initialize rgelt so that in case we fail, we can
  138. // release only what we put in rgelt.
  139. //
  140. if (rgelt)
  141. {
  142. ZeroMemory (rgelt, sizeof (*rgelt) * celt);
  143. }
  144. hr = HrLockAndTestForValidInterface (IF_DEFAULT);
  145. if (S_OK == hr)
  146. {
  147. // Enumerate the requested number of elements or stop short
  148. // if we don't have that many left to enumerate.
  149. //
  150. ULONG celtFetched = 0;
  151. while ((S_OK == hr)
  152. && (celtFetched < celt)
  153. && (m_unIndex < m_pIPath->m_cpIComp))
  154. {
  155. if (rgelt)
  156. {
  157. hr = CImplINetCfgBindingInterface::HrCreateInstance (
  158. m_pINetCfg,
  159. (CImplINetCfgComponent*)m_pIPath->
  160. m_papIComp[m_unIndex-1],
  161. (CImplINetCfgComponent*)m_pIPath->
  162. m_papIComp[m_unIndex],
  163. rgelt + celtFetched);
  164. }
  165. celtFetched++;
  166. m_unIndex++;
  167. }
  168. Unlock();
  169. hr = HrFinishNextOrSkipContract (hr, celtFetched, celt,
  170. reinterpret_cast<IUnknown**>(rgelt), pceltFetched);
  171. }
  172. TraceHr (ttidError, FAL, hr, S_FALSE == hr,
  173. "CImplIEnumNetCfgBindingInterface::HrNextOrSkip");
  174. return hr;
  175. }
  176. STDMETHODIMP
  177. CImplIEnumNetCfgBindingInterface::Next (
  178. IN ULONG celt,
  179. OUT INetCfgBindingInterface** rgelt,
  180. OUT ULONG* pceltFetched)
  181. {
  182. HRESULT hr;
  183. // Validate parameters.
  184. //
  185. if (!rgelt || (!pceltFetched && (1 != celt)))
  186. {
  187. hr = E_POINTER;
  188. }
  189. else if (rgelt && IsBadWritePtr(rgelt, celt * sizeof(*rgelt)))
  190. {
  191. hr = E_INVALIDARG;
  192. }
  193. else
  194. {
  195. hr = HrNextOrSkip (celt, rgelt, pceltFetched);
  196. }
  197. TraceHr (ttidError, FAL, hr, S_FALSE == hr,
  198. "CImplIEnumNetCfgBindingInterface::Next");
  199. return hr;
  200. }
  201. STDMETHODIMP
  202. CImplIEnumNetCfgBindingInterface::Skip (
  203. IN ULONG celt)
  204. {
  205. HRESULT hr = HrNextOrSkip (celt, NULL, NULL);
  206. TraceHr (ttidError, FAL, hr, S_FALSE == hr,
  207. "CImplIEnumNetCfgBindingInterface::Skip");
  208. return hr;
  209. }
  210. STDMETHODIMP
  211. CImplIEnumNetCfgBindingInterface::Reset ()
  212. {
  213. Lock();
  214. Assert (m_pIPath);
  215. m_unIndex = 1;
  216. Unlock();
  217. return S_OK;
  218. }
  219. STDMETHODIMP
  220. CImplIEnumNetCfgBindingInterface::Clone (
  221. OUT IEnumNetCfgBindingInterface** ppIEnum)
  222. {
  223. return E_NOTIMPL;
  224. }
  225. //+---------------------------------------------------------------------------
  226. // CImplIEnumNetCfgBindingPath -
  227. //
  228. // static
  229. HRESULT
  230. CImplIEnumNetCfgBindingPath::HrCreateInstance (
  231. IN CImplINetCfg* pINetCfg,
  232. IN const CBindingSet* pBindSet OPTIONAL,
  233. IN DWORD dwFlags,
  234. OUT CImplIEnumNetCfgBindingPath** ppIEnum)
  235. {
  236. HRESULT hr = E_OUTOFMEMORY;
  237. Assert (dwFlags);
  238. if (pBindSet)
  239. {
  240. pINetCfg->m_pNetConfig->Core.DbgVerifyBindingSet (pBindSet);
  241. }
  242. CImplIEnumNetCfgBindingPath* pObj;
  243. pObj = new CComObject <CImplIEnumNetCfgBindingPath>;
  244. if (pObj)
  245. {
  246. hr = S_OK;
  247. // Initialize our members.
  248. //
  249. if (dwFlags & EBPC_TAKE_OWNERSHIP)
  250. {
  251. Assert (pBindSet);
  252. pObj->m_pBindSet = pBindSet;
  253. pObj->m_iter = pBindSet->begin();
  254. }
  255. else if (dwFlags & EBPC_COPY_BINDSET)
  256. {
  257. Assert (pBindSet);
  258. hr = pObj->m_InternalBindSet.HrCopyBindingSet(pBindSet);
  259. pObj->m_pBindSet = &pObj->m_InternalBindSet;
  260. pObj->m_iter = pObj->m_InternalBindSet.begin();
  261. }
  262. else
  263. {
  264. Assert (dwFlags & EBPC_CREATE_EMPTY);
  265. pObj->m_pBindSet = &pObj->m_InternalBindSet;
  266. pObj->m_iter = pObj->m_InternalBindSet.begin();
  267. }
  268. if (S_OK == hr)
  269. {
  270. // Do the standard CComCreator::CreateInstance stuff.
  271. //
  272. pObj->SetVoid (NULL);
  273. pObj->InternalFinalConstructAddRef ();
  274. hr = pObj->FinalConstruct ();
  275. pObj->InternalFinalConstructRelease ();
  276. // The last thing we do is addref any interfaces we hold.
  277. // We only do this if we are returning success.
  278. //
  279. if (S_OK == hr)
  280. {
  281. pObj->HoldINetCfg (pINetCfg);
  282. AddRefObj (pObj->GetUnknown());
  283. *ppIEnum = pObj;
  284. }
  285. }
  286. if (S_OK != hr)
  287. {
  288. delete pObj;
  289. }
  290. }
  291. if ((S_OK != hr) && (dwFlags & EBPC_TAKE_OWNERSHIP))
  292. {
  293. delete pBindSet;
  294. }
  295. TraceHr (ttidError, FAL, hr, FALSE,
  296. "CImplIEnumNetCfgBindingPath::HrCreateInstance");
  297. return hr;
  298. }
  299. HRESULT
  300. CImplIEnumNetCfgBindingPath::HrNextOrSkip (
  301. IN ULONG celt,
  302. OUT INetCfgBindingPath** rgelt,
  303. OUT ULONG* pceltFetched)
  304. {
  305. HRESULT hr;
  306. Assert(m_iter >= m_pBindSet->begin());
  307. // Important to initialize rgelt so that in case we fail, we can
  308. // release only what we put in rgelt.
  309. //
  310. if (rgelt)
  311. {
  312. ZeroMemory (rgelt, sizeof (*rgelt) * celt);
  313. }
  314. hr = HrLockAndTestForValidInterface (IF_DEFAULT);
  315. if (S_OK == hr)
  316. {
  317. // Enumerate the requested number of elements or stop short
  318. // if we don't have that many left to enumerate.
  319. //
  320. ULONG celtFetched = 0;
  321. while ((S_OK == hr)
  322. && (celtFetched < celt)
  323. && (m_iter != m_pBindSet->end()))
  324. {
  325. // Don't return interfaces to bindpaths that contain
  326. // components that have had problem loading.
  327. //
  328. if (m_iter->FAllComponentsLoadedOkayIfLoadedAtAll())
  329. {
  330. if (rgelt)
  331. {
  332. hr = CImplINetCfgBindingPath::HrCreateInstance (
  333. m_pINetCfg,
  334. m_iter,
  335. rgelt + celtFetched);
  336. }
  337. celtFetched++;
  338. }
  339. m_iter++;
  340. }
  341. Unlock();
  342. hr = HrFinishNextOrSkipContract (hr, celtFetched, celt,
  343. reinterpret_cast<IUnknown**>(rgelt), pceltFetched);
  344. }
  345. TraceHr (ttidError, FAL, hr, S_FALSE == hr,
  346. "CImplIEnumNetCfgBindingPath::HrNextOrSkip");
  347. return hr;
  348. }
  349. STDMETHODIMP
  350. CImplIEnumNetCfgBindingPath::Next (
  351. IN ULONG celt,
  352. OUT INetCfgBindingPath** rgelt,
  353. OUT ULONG* pceltFetched)
  354. {
  355. HRESULT hr;
  356. // Validate parameters.
  357. //
  358. if (!rgelt || (!pceltFetched && (1 != celt)))
  359. {
  360. hr = E_POINTER;
  361. }
  362. else if (rgelt && IsBadWritePtr(rgelt, celt * sizeof(*rgelt)))
  363. {
  364. hr = E_INVALIDARG;
  365. }
  366. else
  367. {
  368. hr = HrNextOrSkip (celt, rgelt, pceltFetched);
  369. }
  370. TraceHr (ttidError, FAL, hr, S_FALSE == hr,
  371. "CImplIEnumNetCfgBindingPath::Next");
  372. return hr;
  373. }
  374. STDMETHODIMP
  375. CImplIEnumNetCfgBindingPath::Skip (
  376. IN ULONG celt)
  377. {
  378. HRESULT hr = HrNextOrSkip (celt, NULL, NULL);
  379. TraceHr (ttidError, FAL, hr, S_FALSE == hr,
  380. "CImplIEnumNetCfgBindingPath::Skip");
  381. return hr;
  382. }
  383. STDMETHODIMP
  384. CImplIEnumNetCfgBindingPath::Reset ()
  385. {
  386. Lock();
  387. Assert (m_pBindSet);
  388. m_iter = m_pBindSet->begin();
  389. Unlock();
  390. return S_OK;
  391. }
  392. STDMETHODIMP
  393. CImplIEnumNetCfgBindingPath::Clone (
  394. OUT IEnumNetCfgBindingPath** ppIEnum)
  395. {
  396. return E_NOTIMPL;
  397. }
  398. //+---------------------------------------------------------------------------
  399. // CImplIEnumNetCfgComponent -
  400. //
  401. // static
  402. HRESULT
  403. CImplIEnumNetCfgComponent::HrCreateInstance (
  404. IN CImplINetCfg* pINetCfg,
  405. IN NETCLASS Class,
  406. OUT IEnumNetCfgComponent** ppIEnum)
  407. {
  408. HRESULT hr = E_OUTOFMEMORY;
  409. CImplIEnumNetCfgComponent* pObj;
  410. pObj = new CComObject <CImplIEnumNetCfgComponent>;
  411. if (pObj)
  412. {
  413. // Initialize our members.
  414. //
  415. pObj->m_unIndex = 0;
  416. pObj->m_Class = Class;
  417. // Do the standard CComCreator::CreateInstance stuff.
  418. //
  419. pObj->SetVoid (NULL);
  420. pObj->InternalFinalConstructAddRef ();
  421. hr = pObj->FinalConstruct ();
  422. pObj->InternalFinalConstructRelease ();
  423. if (S_OK == hr)
  424. {
  425. hr = pObj->QueryInterface (IID_IEnumNetCfgComponent,
  426. (VOID**)ppIEnum);
  427. // The last thing we do is addref any interfaces we hold.
  428. // We only do this if we are returning success.
  429. //
  430. if (S_OK == hr)
  431. {
  432. pObj->HoldINetCfg (pINetCfg);
  433. }
  434. }
  435. if (S_OK != hr)
  436. {
  437. delete pObj;
  438. }
  439. }
  440. TraceHr (ttidError, FAL, hr, FALSE,
  441. "CImplIEnumNetCfgComponent::HrCreateInstance");
  442. return hr;
  443. }
  444. HRESULT
  445. CImplIEnumNetCfgComponent::HrNextOrSkip (
  446. IN ULONG celt,
  447. OUT INetCfgComponent** rgelt,
  448. OUT ULONG* pceltFetched)
  449. {
  450. HRESULT hr;
  451. // Important to initialize rgelt so that in case we fail, we can
  452. // release only what we put in rgelt.
  453. //
  454. if (rgelt)
  455. {
  456. ZeroMemory (rgelt, sizeof (*rgelt) * celt);
  457. }
  458. hr = HrLockAndTestForValidInterface (IF_DEFAULT);
  459. if (S_OK == hr)
  460. {
  461. CComponentList* pComponents;
  462. CComponent* pComponent;
  463. pComponents = &m_pINetCfg->m_pNetConfig->Core.Components;
  464. // Enumerate the requested number of elements or stop short
  465. // if we don't have that many left to enumerate.
  466. //
  467. ULONG celtFetched = 0;
  468. while ((S_OK == hr)
  469. && (celtFetched < celt)
  470. && (NULL != (pComponent = pComponents->PGetComponentAtIndex(
  471. m_unIndex))))
  472. {
  473. // Don't return interfaces to components that have had
  474. // problem loading.
  475. //
  476. if (((NC_INVALID == m_Class) ||
  477. (m_Class == pComponent->Class())) &&
  478. pComponent->Ext.FLoadedOkayIfLoadedAtAll())
  479. {
  480. if (rgelt)
  481. {
  482. hr = pComponent->HrGetINetCfgComponentInterface(
  483. m_pINetCfg, rgelt + celtFetched);
  484. }
  485. celtFetched++;
  486. }
  487. m_unIndex++;
  488. }
  489. Unlock();
  490. hr = HrFinishNextOrSkipContract (hr, celtFetched, celt,
  491. reinterpret_cast<IUnknown**>(rgelt), pceltFetched);
  492. }
  493. TraceHr (ttidError, FAL, hr, S_FALSE == hr,
  494. "CImplIEnumNetCfgComponent::HrNextOrSkip");
  495. return hr;
  496. }
  497. STDMETHODIMP
  498. CImplIEnumNetCfgComponent::Next (
  499. IN ULONG celt,
  500. OUT INetCfgComponent** rgelt,
  501. OUT ULONG* pceltFetched)
  502. {
  503. HRESULT hr;
  504. // Validate parameters.
  505. //
  506. if (!rgelt || (!pceltFetched && (1 != celt)))
  507. {
  508. hr = E_POINTER;
  509. }
  510. else if (rgelt && IsBadWritePtr(rgelt, celt * sizeof(*rgelt)))
  511. {
  512. hr = E_INVALIDARG;
  513. }
  514. else
  515. {
  516. hr = HrNextOrSkip (celt, rgelt, pceltFetched);
  517. }
  518. TraceHr (ttidError, FAL, hr, S_FALSE == hr,
  519. "CImplIEnumNetCfgComponent::Next");
  520. return hr;
  521. }
  522. STDMETHODIMP
  523. CImplIEnumNetCfgComponent::Skip (
  524. IN ULONG celt)
  525. {
  526. HRESULT hr = HrNextOrSkip (celt, NULL, NULL);
  527. TraceHr (ttidError, FAL, hr, S_FALSE == hr,
  528. "CImplIEnumNetCfgComponent::Skip");
  529. return hr;
  530. }
  531. STDMETHODIMP
  532. CImplIEnumNetCfgComponent::Reset ()
  533. {
  534. Lock();
  535. m_unIndex = 0;
  536. Unlock();
  537. return S_OK;
  538. }
  539. STDMETHODIMP
  540. CImplIEnumNetCfgComponent::Clone (
  541. OUT IEnumNetCfgComponent** ppIEnum)
  542. {
  543. return E_NOTIMPL;
  544. }