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.

806 lines
20 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1999.
  5. //
  6. // File: I B I N D . C P P
  7. //
  8. // Contents: Implements the INetCfgBindingInterface and INetCfgBindingPath
  9. // COM interfaces.
  10. //
  11. // Notes:
  12. //
  13. // Author: shaunco 15 Jan 1999
  14. //
  15. //----------------------------------------------------------------------------
  16. #include <pch.h>
  17. #pragma hdrstop
  18. #include "ibind.h"
  19. #include "ncvalid.h"
  20. #include "netcfg.h"
  21. #include "util.h"
  22. //static
  23. HRESULT
  24. CImplINetCfgBindingInterface::HrCreateInstance (
  25. IN CImplINetCfg* pINetCfg,
  26. IN CImplINetCfgComponent* pUpper,
  27. IN CImplINetCfgComponent* pLower,
  28. OUT INetCfgBindingInterface** ppv)
  29. {
  30. TraceFileFunc(ttidNetCfgBind);
  31. HRESULT hr = E_OUTOFMEMORY;
  32. CImplINetCfgBindingInterface* pObj;
  33. pObj = new CComObject <CImplINetCfgBindingInterface>;
  34. if (pObj)
  35. {
  36. // Initialize our members.
  37. //
  38. pObj->m_pUpper = pUpper;
  39. pObj->m_pLower = pLower;
  40. // Do the standard CComCreator::CreateInstance stuff.
  41. //
  42. pObj->SetVoid (NULL);
  43. pObj->InternalFinalConstructAddRef ();
  44. hr = pObj->FinalConstruct ();
  45. pObj->InternalFinalConstructRelease ();
  46. if (S_OK == hr)
  47. {
  48. hr = pObj->QueryInterface (IID_INetCfgBindingInterface,
  49. (VOID**)ppv);
  50. // The last thing we do is addref any interfaces we hold.
  51. // We only do this if we are returning success.
  52. //
  53. if (S_OK == hr)
  54. {
  55. AddRefObj (pUpper->GetUnknown());
  56. AddRefObj (pLower->GetUnknown());
  57. pObj->HoldINetCfg (pINetCfg);
  58. }
  59. }
  60. if (S_OK != hr)
  61. {
  62. delete pObj;
  63. }
  64. }
  65. TraceHr (ttidError, FAL, hr, FALSE,
  66. "CImplINetCfgBindingInterface::HrCreateInstance");
  67. return hr;
  68. }
  69. HRESULT
  70. CImplINetCfgBindingInterface::HrLockAndTestForValidInterface (
  71. DWORD dwFlags)
  72. {
  73. TraceFileFunc(ttidNetCfgBind);
  74. HRESULT hr;
  75. Lock();
  76. hr = m_pUpper->HrIsValidInterface (dwFlags);
  77. if (S_OK == hr)
  78. {
  79. hr = m_pLower->HrIsValidInterface (dwFlags);
  80. }
  81. if (S_OK != hr)
  82. {
  83. Unlock();
  84. }
  85. TraceHr (ttidError, FAL, hr, FALSE,
  86. "CImplINetCfgBindingInterface::HrLockAndTestForValidInterface");
  87. return hr;
  88. }
  89. //+---------------------------------------------------------------------------
  90. // INetCfgBindingInterface
  91. //
  92. STDMETHODIMP
  93. CImplINetCfgBindingInterface::GetName (
  94. OUT PWSTR* ppszInterfaceName)
  95. {
  96. TraceFileFunc(ttidNetCfgBind);
  97. HRESULT hr;
  98. // Validate parameters.
  99. //
  100. if (FBadOutPtr(ppszInterfaceName))
  101. {
  102. hr = E_POINTER;
  103. }
  104. else
  105. {
  106. *ppszInterfaceName = NULL;
  107. hr = HrLockAndTestForValidInterface (IF_NEED_COMPONENT_DATA);
  108. if (S_OK == hr)
  109. {
  110. CComponent* pUpper = m_pUpper->m_pComponent;
  111. CComponent* pLower = m_pLower->m_pComponent;
  112. const WCHAR* pch;
  113. ULONG cch;
  114. if (pUpper->FCanDirectlyBindTo (pLower, &pch, &cch))
  115. {
  116. hr = HrCoTaskMemAllocAndDupSzLen (
  117. pch, cch, ppszInterfaceName, MAX_INF_STRING_LENGTH);
  118. }
  119. else
  120. {
  121. AssertSz(0, "Why no match if we have a binding interface "
  122. "created for these components?");
  123. hr = E_UNEXPECTED;
  124. }
  125. Unlock();
  126. }
  127. }
  128. TraceHr (ttidError, FAL, hr, FALSE,
  129. "CImplINetCfgBindingInterface::GetName");
  130. return hr;
  131. }
  132. STDMETHODIMP
  133. CImplINetCfgBindingInterface::GetUpperComponent (
  134. OUT INetCfgComponent** ppComp)
  135. {
  136. TraceFileFunc(ttidNetCfgBind);
  137. HRESULT hr;
  138. // Validate parameters.
  139. //
  140. if (FBadOutPtr(ppComp))
  141. {
  142. hr = E_POINTER;
  143. }
  144. else
  145. {
  146. *ppComp = NULL;
  147. hr = HrLockAndTestForValidInterface (IF_DEFAULT);
  148. if (S_OK == hr)
  149. {
  150. AddRefObj (m_pUpper->GetUnknown());
  151. *ppComp = m_pUpper;
  152. Unlock();
  153. }
  154. }
  155. TraceHr (ttidError, FAL, hr, FALSE,
  156. "CImplINetCfgBindingInterfaceGetName::GetUpperComponent");
  157. return hr;
  158. }
  159. STDMETHODIMP
  160. CImplINetCfgBindingInterface::GetLowerComponent (
  161. OUT INetCfgComponent** ppComp)
  162. {
  163. TraceFileFunc(ttidNetCfgBind);
  164. HRESULT hr;
  165. // Validate parameters.
  166. //
  167. if (FBadOutPtr(ppComp))
  168. {
  169. hr = E_POINTER;
  170. }
  171. else
  172. {
  173. *ppComp = NULL;
  174. hr = HrLockAndTestForValidInterface (IF_DEFAULT);
  175. if (S_OK == hr)
  176. {
  177. AddRefObj (m_pLower->GetUnknown());
  178. *ppComp = m_pLower;
  179. Unlock();
  180. }
  181. }
  182. TraceHr (ttidError, FAL, hr, FALSE,
  183. "CImplINetCfgBindingInterfaceGetName::GetLowerComponent");
  184. return hr;
  185. }
  186. //static
  187. HRESULT
  188. CImplINetCfgBindingPath::HrCreateInstance (
  189. IN CImplINetCfg* pINetCfg,
  190. IN const CBindPath* pBindPath,
  191. OUT INetCfgBindingPath** ppIPath)
  192. {
  193. TraceFileFunc(ttidNetCfgBind);
  194. HRESULT hr;
  195. ULONG ulDepth;
  196. ULONG cbArray;
  197. CComponent* pComponent;
  198. CImplINetCfgBindingPath* pObj;
  199. Assert (pINetCfg);
  200. Assert (pBindPath);
  201. Assert (ppIPath);
  202. // Caller's are responsible for ensuring that if an interface is about
  203. // to be handed out, and the external data has been loaded, that the
  204. // data has been loaded successfully. If we handed out an interface
  205. // and the data was NOT loaded successfully, it just means we are doomed
  206. // to fail later when the client of the interface calls a method that
  207. // requires that data.
  208. //
  209. Assert (pBindPath->FAllComponentsLoadedOkayIfLoadedAtAll());
  210. hr = E_OUTOFMEMORY;
  211. pObj = new CComObject <CImplINetCfgBindingPath>;
  212. if (pObj)
  213. {
  214. // Initialize our members.
  215. //
  216. ulDepth = pBindPath->CountComponents();
  217. cbArray = ulDepth * sizeof(INetCfgComponent*);
  218. AssertSz (0 != ulDepth, "Why are we being asked to expose an empty bindpath?");
  219. AssertSz (1 != ulDepth, "Why are we being asked to expose a bindpath with only one component?");
  220. // If the bindpath has more components than our static
  221. // array has room for, we'll have to use an allocated array.
  222. //
  223. if (cbArray > sizeof(pObj->m_apIComp))
  224. {
  225. // Ensure failure of MemAlloc causes us to return the correct
  226. // error code. (Should be set above and not changed between.)
  227. //
  228. Assert (E_OUTOFMEMORY == hr);
  229. pObj->m_papIComp = (INetCfgComponent**) MemAlloc (cbArray);
  230. if (pObj->m_papIComp)
  231. {
  232. hr = S_OK;
  233. }
  234. }
  235. else
  236. {
  237. pObj->m_papIComp = pObj->m_apIComp;
  238. hr = S_OK;
  239. }
  240. // Now get each INetCfgComponent interface for the components in
  241. // the bindpath.
  242. //
  243. if (S_OK == hr)
  244. {
  245. UINT iComp;
  246. ZeroMemory (pObj->m_papIComp, cbArray);
  247. for (iComp = 0; iComp < ulDepth; iComp++)
  248. {
  249. pComponent = pBindPath->PGetComponentAtIndex (iComp);
  250. Assert (pComponent);
  251. hr = pComponent->HrGetINetCfgComponentInterface (
  252. pINetCfg, pObj->m_papIComp + iComp);
  253. if (S_OK != hr)
  254. {
  255. ReleaseIUnknownArray (iComp+1, (IUnknown**)pObj->m_papIComp);
  256. break;
  257. }
  258. }
  259. }
  260. if (S_OK == hr)
  261. {
  262. pObj->m_cpIComp = ulDepth;
  263. // Do the standard CComCreator::CreateInstance stuff.
  264. //
  265. pObj->SetVoid (NULL);
  266. pObj->InternalFinalConstructAddRef ();
  267. hr = pObj->FinalConstruct ();
  268. pObj->InternalFinalConstructRelease ();
  269. if (S_OK == hr)
  270. {
  271. hr = pObj->QueryInterface (IID_INetCfgBindingPath,
  272. (VOID**)ppIPath);
  273. // The last thing we do is addref any interfaces we hold.
  274. // We only do this if we are returning success.
  275. //
  276. if (S_OK == hr)
  277. {
  278. pObj->HoldINetCfg (pINetCfg);
  279. }
  280. }
  281. }
  282. if (S_OK != hr)
  283. {
  284. if (pObj->m_papIComp != pObj->m_apIComp)
  285. {
  286. MemFree (pObj->m_papIComp);
  287. }
  288. delete pObj;
  289. }
  290. }
  291. TraceHr (ttidError, FAL, hr, FALSE,
  292. "CImplINetCfgBindingPath::HrCreateInstance");
  293. return hr;
  294. }
  295. HRESULT
  296. CImplINetCfgBindingPath::HrIsValidInterface (
  297. IN DWORD dwFlags,
  298. OUT CBindPath* pBindPath)
  299. {
  300. TraceFileFunc(ttidNetCfgBind);
  301. HRESULT hr;
  302. hr = m_pINetCfg->HrIsValidInterface (dwFlags);
  303. if ((S_OK == hr) && pBindPath)
  304. {
  305. Assert (0 == pBindPath->CountComponents());
  306. // When pBindPath is specified, it means the caller wants a
  307. // CBindPath representation of the bindpath we represent.
  308. // We have to build this using the array of INetCfgComponent
  309. // pointer we maintain. Do this by verifying each one is valid
  310. // and then adding its internal CComponent* to pBindPath.
  311. //
  312. hr = pBindPath->HrReserveRoomForComponents (m_cpIComp);
  313. if (S_OK == hr)
  314. {
  315. CImplINetCfgComponent* pIComp;
  316. CComponent* pComponent;
  317. // For each INetCfgComponent* in our array...
  318. //
  319. for (UINT i = 0; i < m_cpIComp; i++)
  320. {
  321. pIComp = (CImplINetCfgComponent*)m_papIComp[i];
  322. if (pIComp == NULL)
  323. {
  324. return(E_OUTOFMEMORY);
  325. }
  326. hr = pIComp->HrIsValidInterface (IF_DEFAULT);
  327. if (S_OK != hr)
  328. {
  329. break;
  330. }
  331. pComponent = pIComp->m_pComponent;
  332. Assert (pComponent);
  333. hr = pBindPath->HrAppendComponent (pComponent);
  334. if (S_OK != hr)
  335. {
  336. break;
  337. }
  338. }
  339. }
  340. }
  341. TraceHr (ttidError, FAL, hr, FALSE,
  342. "CImplINetCfgBindingPath::HrIsValidInterface");
  343. return hr;
  344. }
  345. HRESULT
  346. CImplINetCfgBindingPath::HrLockAndTestForValidInterface (
  347. IN DWORD dwFlags,
  348. OUT CBindPath* pBindPath)
  349. {
  350. TraceFileFunc(ttidNetCfgBind);
  351. HRESULT hr;
  352. Lock();
  353. hr = HrIsValidInterface (dwFlags, pBindPath);
  354. if (S_OK != hr)
  355. {
  356. Unlock();
  357. }
  358. TraceHr (ttidError, FAL, hr, FALSE,
  359. "CImplINetCfgHolder::HrLockAndTestForValidInterface");
  360. return hr;
  361. }
  362. //+---------------------------------------------------------------------------
  363. // INetCfgBindingPath
  364. //
  365. STDMETHODIMP
  366. CImplINetCfgBindingPath::IsSamePathAs (
  367. IN INetCfgBindingPath* pIPath)
  368. {
  369. TraceFileFunc(ttidNetCfgBind);
  370. HRESULT hr;
  371. // Validate parameters.
  372. //
  373. if (FBadInPtr(pIPath))
  374. {
  375. hr = E_POINTER;
  376. }
  377. else
  378. {
  379. hr = HrLockAndTestForValidInterface (IF_DEFAULT, NULL);
  380. if (S_OK == hr)
  381. {
  382. CImplINetCfgBindingPath* pOther = (CImplINetCfgBindingPath*)pIPath;
  383. Assert (m_cpIComp);
  384. Assert (m_papIComp);
  385. Assert (pOther->m_cpIComp);
  386. Assert (pOther->m_papIComp);
  387. // Can't be the same if our length is not the same.
  388. //
  389. if (m_cpIComp != pOther->m_cpIComp)
  390. {
  391. hr = S_FALSE;
  392. }
  393. else
  394. {
  395. UINT cb;
  396. cb = m_cpIComp * sizeof(INetCfgComponent*);
  397. hr = (0 == memcmp (
  398. (BYTE*)(m_papIComp),
  399. (BYTE*)(pOther->m_papIComp),
  400. cb)) ? S_OK : S_FALSE;
  401. }
  402. Unlock();
  403. }
  404. }
  405. TraceHr (ttidError, FAL, hr, (S_FALSE == hr),
  406. "CImplINetCfgBindingPath::IsSamePathAs");
  407. return hr;
  408. }
  409. STDMETHODIMP
  410. CImplINetCfgBindingPath::IsSubPathOf (
  411. IN INetCfgBindingPath* pIPath)
  412. {
  413. TraceFileFunc(ttidNetCfgBind);
  414. HRESULT hr;
  415. // Validate parameters.
  416. //
  417. if (FBadInPtr(pIPath))
  418. {
  419. hr = E_POINTER;
  420. }
  421. else
  422. {
  423. hr = HrLockAndTestForValidInterface (IF_DEFAULT, NULL);
  424. if (S_OK == hr)
  425. {
  426. CImplINetCfgBindingPath* pOther = (CImplINetCfgBindingPath*)pIPath;
  427. Assert (m_cpIComp);
  428. Assert (m_papIComp);
  429. Assert (pOther->m_cpIComp);
  430. Assert (pOther->m_papIComp);
  431. // Can't be a subpath if our length is greater or equal.
  432. //
  433. if (m_cpIComp >= pOther->m_cpIComp)
  434. {
  435. hr = S_FALSE;
  436. }
  437. else
  438. {
  439. UINT cb;
  440. UINT unSkipComponents;
  441. cb = m_cpIComp * sizeof(INetCfgComponent*);
  442. Assert (pOther->m_cpIComp > m_cpIComp);
  443. unSkipComponents = pOther->m_cpIComp - m_cpIComp;
  444. hr = (0 == memcmp (
  445. (BYTE*)(m_papIComp),
  446. (BYTE*)(pOther->m_papIComp + unSkipComponents),
  447. cb)) ? S_OK : S_FALSE;
  448. }
  449. // Special Case: NCF_DONTEXPOSELOWER
  450. // If we're about to return false, let's check for a case like:
  451. // is ms_ipx->adapter a subpath of ms_server->ms_ipx and return
  452. // TRUE. For this case, it really is a subpath, but the binding
  453. // has been broken because of NCF_DONTEXPOSELOWER.
  454. //
  455. // If the last component of pIPath, and the first component of
  456. // this path both are NCF_DONTEXPOSELOWER, then consider this
  457. // path a subpath of pIPath. This assumes that ms_nwipx and
  458. // ms_nwnb are the only components with this characteristic.
  459. //
  460. if (S_FALSE == hr)
  461. {
  462. CImplINetCfgComponent* pIFirst;
  463. CImplINetCfgComponent* pILast;
  464. pIFirst = (CImplINetCfgComponent*)m_papIComp[0];
  465. pILast = (CImplINetCfgComponent*)pOther->m_papIComp[pOther->m_cpIComp - 1];
  466. if ((pIFirst == NULL) ||
  467. (pILast == NULL))
  468. {
  469. return(E_OUTOFMEMORY);
  470. }
  471. if ((S_OK == pIFirst->HrIsValidInterface(IF_DEFAULT)) &&
  472. (S_OK == pILast->HrIsValidInterface(IF_DEFAULT)))
  473. {
  474. Assert (pIFirst->m_pComponent);
  475. Assert (pILast->m_pComponent);
  476. if ((pIFirst->m_pComponent->m_dwCharacter & NCF_DONTEXPOSELOWER) &&
  477. (pILast->m_pComponent->m_dwCharacter & NCF_DONTEXPOSELOWER))
  478. {
  479. if (0 == wcscmp(L"ms_nwipx", pIFirst->m_pComponent->m_pszInfId))
  480. {
  481. hr = S_OK;
  482. }
  483. else if (pIFirst->m_pComponent == pILast->m_pComponent)
  484. {
  485. hr = S_OK;
  486. }
  487. }
  488. }
  489. }
  490. // End Special case
  491. Unlock();
  492. }
  493. }
  494. TraceHr (ttidError, FAL, hr, (S_FALSE == hr),
  495. "CImplINetCfgBindingPath::IsSubPathOf");
  496. return hr;
  497. }
  498. STDMETHODIMP
  499. CImplINetCfgBindingPath::IsEnabled ()
  500. {
  501. TraceFileFunc(ttidNetCfgBind);
  502. HRESULT hr;
  503. CBindPath BindPath;
  504. hr = HrLockAndTestForValidInterface (IF_DEFAULT, &BindPath);
  505. if (S_OK == hr)
  506. {
  507. Assert (m_pINetCfg);
  508. if (m_pINetCfg->m_pNetConfig->Core.FIsBindPathDisabled (
  509. &BindPath, IBD_MATCH_SUBPATHS_TOO))
  510. {
  511. hr = S_FALSE;
  512. }
  513. Unlock();
  514. }
  515. TraceHr (ttidError, FAL, hr, S_FALSE == hr,
  516. "CImplINetCfgBindingPath::IsEnabled");
  517. return hr;
  518. }
  519. STDMETHODIMP
  520. CImplINetCfgBindingPath::Enable (
  521. IN BOOL fEnable)
  522. {
  523. TraceFileFunc(ttidNetCfgBind);
  524. HRESULT hr;
  525. CBindPath BindPath;
  526. hr = HrLockAndTestForValidInterface (IF_NEED_WRITE_LOCK, &BindPath);
  527. if (S_OK == hr)
  528. {
  529. Assert (m_pINetCfg);
  530. hr = m_pINetCfg->m_pNetConfig->ModifyCtx.HrEnableOrDisableBindPath (
  531. (fEnable) ? NCN_ENABLE : NCN_DISABLE,
  532. &BindPath,
  533. this);
  534. Unlock();
  535. }
  536. TraceHr (ttidError, FAL, hr, FALSE,
  537. "CImplINetCfgBindingPath::Enable");
  538. return hr;
  539. }
  540. STDMETHODIMP
  541. CImplINetCfgBindingPath::GetPathToken (
  542. OUT PWSTR* ppszPathToken)
  543. {
  544. TraceFileFunc(ttidNetCfgBind);
  545. HRESULT hr;
  546. // Validate parameters.
  547. //
  548. if (FBadOutPtr(ppszPathToken))
  549. {
  550. hr = E_POINTER;
  551. }
  552. else
  553. {
  554. CBindPath BindPath;
  555. *ppszPathToken = NULL;
  556. hr = HrLockAndTestForValidInterface (IF_DEFAULT, &BindPath);
  557. if (S_OK == hr)
  558. {
  559. ULONG cch;
  560. cch = 0;
  561. BindPath.FGetPathToken (NULL, &cch);
  562. if (cch)
  563. {
  564. hr = HrCoTaskMemAlloc (
  565. ((cch + 1) * sizeof(WCHAR)),
  566. (VOID**)ppszPathToken);
  567. if (S_OK == hr)
  568. {
  569. BindPath.FGetPathToken (*ppszPathToken, &cch);
  570. }
  571. }
  572. Unlock();
  573. }
  574. }
  575. TraceHr (ttidError, FAL, hr, FALSE,
  576. "CImplINetCfgBindingPath::GetPathToken");
  577. return hr;
  578. }
  579. STDMETHODIMP
  580. CImplINetCfgBindingPath::GetOwner (
  581. OUT INetCfgComponent** ppIComp)
  582. {
  583. TraceFileFunc(ttidNetCfgBind);
  584. HRESULT hr;
  585. // Validate parameters.
  586. //
  587. if (FBadOutPtr(ppIComp))
  588. {
  589. hr = E_POINTER;
  590. }
  591. else
  592. {
  593. *ppIComp = NULL;
  594. hr = HrLockAndTestForValidInterface (IF_DEFAULT, NULL);
  595. if (S_OK == hr)
  596. {
  597. Assert (m_cpIComp);
  598. Assert (m_papIComp);
  599. Assert (m_papIComp[0]);
  600. AddRefObj (m_papIComp[0]);
  601. *ppIComp = m_papIComp[0];
  602. Unlock();
  603. }
  604. }
  605. TraceHr (ttidError, FAL, hr, FALSE,
  606. "CImplINetCfgBindingPath::GetOwner");
  607. return hr;
  608. }
  609. STDMETHODIMP
  610. CImplINetCfgBindingPath::GetDepth (
  611. OUT ULONG* pulDepth)
  612. {
  613. TraceFileFunc(ttidNetCfgBind);
  614. HRESULT hr;
  615. // Validate parameters.
  616. //
  617. if (FBadOutPtr(pulDepth))
  618. {
  619. hr = E_POINTER;
  620. }
  621. else
  622. {
  623. *pulDepth = NULL;
  624. hr = HrLockAndTestForValidInterface (IF_DEFAULT, NULL);
  625. if (S_OK == hr)
  626. {
  627. Assert (m_cpIComp);
  628. *pulDepth = m_cpIComp;
  629. Unlock();
  630. }
  631. }
  632. TraceHr (ttidError, FAL, hr, FALSE,
  633. "CImplINetCfgBindingPath::GetDepth");
  634. return hr;
  635. }
  636. STDMETHODIMP
  637. CImplINetCfgBindingPath::EnumBindingInterfaces (
  638. OUT IEnumNetCfgBindingInterface** ppIEnum)
  639. {
  640. TraceFileFunc(ttidNetCfgBind);
  641. HRESULT hr;
  642. // Validate parameters.
  643. //
  644. if (FBadOutPtr(ppIEnum))
  645. {
  646. hr = E_POINTER;
  647. }
  648. else
  649. {
  650. *ppIEnum = NULL;
  651. hr = HrLockAndTestForValidInterface (IF_DEFAULT, NULL);
  652. if (S_OK == hr)
  653. {
  654. hr = CImplIEnumNetCfgBindingInterface::HrCreateInstance (
  655. m_pINetCfg,
  656. this,
  657. ppIEnum);
  658. Unlock();
  659. }
  660. }
  661. TraceHr (ttidError, FAL, hr, FALSE,
  662. "CImplINetCfgBindingPath::EnumBindingInterfaces");
  663. return hr;
  664. }