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.

1258 lines
30 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1999.
  5. //
  6. // File: I N E T C F G . C P P
  7. //
  8. // Contents: Implements the COM interfaces on the top-level NetCfg object.
  9. // These interfaces are: INetCfg and INetCfgLock. Also
  10. // implements a base C++ class inherited by sub-level NetCfg
  11. // objects which hold a reference to the top-level object.
  12. //
  13. // Notes:
  14. //
  15. // Author: shaunco 15 Jan 1999
  16. //
  17. //----------------------------------------------------------------------------
  18. #include <pch.h>
  19. #pragma hdrstop
  20. #include "classinst.h"
  21. #include "iclass.h"
  22. #include "icomp.h"
  23. #include "ienum.h"
  24. #include "inetcfg.h"
  25. #include "ncperms.h"
  26. #include "ncras.h"
  27. #include "ncreg.h"
  28. #include "ncui.h"
  29. #include "ncvalid.h"
  30. #include "ndispnp.h"
  31. #include "netcfg.h"
  32. #include "obotoken.h"
  33. #include "resource.h"
  34. // static
  35. HRESULT
  36. CImplINetCfg::HrCreateInstance (
  37. CNetConfig* pNetConfig,
  38. CImplINetCfg** ppINetCfg)
  39. {
  40. Assert (pNetConfig);
  41. Assert (ppINetCfg);
  42. HRESULT hr = E_OUTOFMEMORY;
  43. CImplINetCfg* pObj;
  44. pObj = new CComObject <CImplINetCfg>;
  45. if (pObj)
  46. {
  47. // Initialize our members.
  48. //
  49. pObj->m_pNetConfig = pNetConfig;
  50. Assert (!pObj->m_fOwnNetConfig);
  51. // Do the standard CComCreator::CreateInstance stuff.
  52. //
  53. pObj->SetVoid (NULL);
  54. pObj->InternalFinalConstructAddRef ();
  55. hr = pObj->FinalConstruct ();
  56. pObj->InternalFinalConstructRelease ();
  57. if (S_OK == hr)
  58. {
  59. AddRefObj (pObj->GetUnknown());
  60. *ppINetCfg = pObj;
  61. }
  62. if (S_OK != hr)
  63. {
  64. delete pObj;
  65. }
  66. }
  67. TraceHr (ttidError, FAL, hr, FALSE,
  68. "CImplINetCfg::HrCreateInstance");
  69. return hr;
  70. }
  71. HRESULT
  72. CImplINetCfg::HrCoCreateWrapper (
  73. IN REFCLSID rclsid,
  74. IN LPUNKNOWN punkOuter,
  75. IN DWORD dwClsContext,
  76. IN REFIID riid,
  77. OUT LPVOID FAR* ppv)
  78. {
  79. /*
  80. HRESULT hr = S_OK;
  81. if (!m_fComInitialized)
  82. {
  83. m_fComInitialized = TRUE;
  84. hr = CoInitializeEx (
  85. NULL,
  86. COINIT_DISABLE_OLE1DDE | COINIT_APARTMENTTHREADED);
  87. if (SUCCEEDED(hr))
  88. {
  89. m_fUninitCom = TRUE;
  90. hr = S_OK; // mask S_FALSE
  91. }
  92. else if (RPC_E_CHANGED_MODE == hr)
  93. {
  94. hr = S_OK;
  95. Assert (!m_fUninitCom);
  96. }
  97. }
  98. if (S_OK == hr)
  99. {
  100. hr = CoCreateInstance (rclsid, punkOuter, dwClsContext, riid, ppv);
  101. }
  102. */
  103. HRESULT hr;
  104. hr = CoCreateInstance (rclsid, punkOuter, dwClsContext, riid, ppv);
  105. TraceHr (ttidError, FAL, hr, FALSE,
  106. "CImplINetCfg::HrCoCreateWrapper");
  107. return hr;
  108. }
  109. HRESULT
  110. CImplINetCfg::HrCheckForReentrancy (
  111. IN DWORD dwFlags)
  112. {
  113. Assert (FImplies(dwFlags & IF_ALLOW_INSTALL_OR_REMOVE,
  114. dwFlags & IF_REFUSE_REENTRANCY));
  115. if (dwFlags & IF_ALLOW_INSTALL_OR_REMOVE)
  116. {
  117. if (m_LastAllowedSetupRpl != m_CurrentRpl)
  118. {
  119. return E_FAIL;
  120. }
  121. }
  122. else if (0 != m_CurrentRpl)
  123. {
  124. return E_FAIL;
  125. }
  126. return S_OK;
  127. }
  128. HRESULT
  129. CImplINetCfg::HrIsValidInterface (
  130. IN DWORD dwFlags)
  131. {
  132. HRESULT hr;
  133. // Check if we need to refuse re-entrancy.
  134. //
  135. if (dwFlags & IF_REFUSE_REENTRANCY)
  136. {
  137. hr = HrCheckForReentrancy (dwFlags);
  138. if (S_OK != hr)
  139. {
  140. return hr;
  141. }
  142. }
  143. // Check if initialized/uninitalized as required.
  144. //
  145. if ((dwFlags & IF_NEED_UNINITIALIZED) && m_pNetConfig)
  146. {
  147. return NETCFG_E_ALREADY_INITIALIZED;
  148. }
  149. else if (!(dwFlags & IF_NEED_UNINITIALIZED) && !m_pNetConfig)
  150. {
  151. return NETCFG_E_NOT_INITIALIZED;
  152. }
  153. // Check for the write lock.
  154. //
  155. if (dwFlags & IF_NEED_WRITE_LOCK)
  156. {
  157. if (!m_WriteLock.FIsOwnedByMe ())
  158. {
  159. return NETCFG_E_NO_WRITE_LOCK;
  160. }
  161. // Needing the write lock means we need the modify context to
  162. // be prepared (unless the caller specified
  163. // IF_DONT_PREPARE_MODIFY_CONTEXT).
  164. //
  165. if (!m_pNetConfig->ModifyCtx.m_fPrepared &&
  166. !(dwFlags & IF_DONT_PREPARE_MODIFY_CONTEXT))
  167. {
  168. hr = m_pNetConfig->ModifyCtx.HrPrepare ();
  169. if (S_OK != hr)
  170. {
  171. return hr;
  172. }
  173. }
  174. }
  175. if (!(dwFlags & IF_UNINITIALIZING))
  176. {
  177. // Check for an error that occured during the current modification
  178. // that has not been rolled back yet. i.e. keep people out until
  179. // we unwind enough to cleanup our modify context.
  180. //
  181. if (m_pNetConfig && (S_OK != m_pNetConfig->ModifyCtx.m_hr))
  182. {
  183. return m_pNetConfig->ModifyCtx.m_hr;
  184. }
  185. }
  186. Assert (FImplies(!m_pNetConfig, (dwFlags & IF_NEED_UNINITIALIZED)));
  187. return S_OK;
  188. }
  189. VOID
  190. CImplINetCfg::LowerRpl (
  191. IN RPL_FLAGS Flags)
  192. {
  193. if (RPL_ALLOW_INSTALL_REMOVE == Flags)
  194. {
  195. Assert (m_LastAllowedSetupRpl > 0);
  196. m_LastAllowedSetupRpl--;
  197. }
  198. Assert (m_CurrentRpl > 0);
  199. m_CurrentRpl--;
  200. }
  201. VOID
  202. CImplINetCfg::RaiseRpl (
  203. IN RPL_FLAGS Flags)
  204. {
  205. m_CurrentRpl++;
  206. if (RPL_ALLOW_INSTALL_REMOVE == Flags)
  207. {
  208. m_LastAllowedSetupRpl++;
  209. }
  210. }
  211. HRESULT
  212. CImplINetCfg::HrLockAndTestForValidInterface (
  213. DWORD dwFlags)
  214. {
  215. HRESULT hr;
  216. Lock();
  217. hr = HrIsValidInterface (dwFlags);
  218. if (S_OK != hr)
  219. {
  220. Unlock();
  221. }
  222. return hr;
  223. }
  224. //+---------------------------------------------------------------------------
  225. // INetCfg -
  226. //
  227. STDMETHODIMP
  228. CImplINetCfg::Initialize (
  229. IN PVOID pvReserved)
  230. {
  231. HRESULT hr;
  232. ULONG* pReserved = (ULONG*)pvReserved;
  233. // Validate parameters.
  234. //
  235. if (FBadInPtrOptional(pReserved))
  236. {
  237. hr = E_POINTER;
  238. }
  239. else
  240. {
  241. hr = HrLockAndTestForValidInterface (
  242. IF_NEED_UNINITIALIZED | IF_REFUSE_REENTRANCY);
  243. if (S_OK == hr)
  244. {
  245. Assert (!m_pNetConfig);
  246. hr = CNetConfig::HrCreateInstance (
  247. this,
  248. &m_pNetConfig);
  249. if (S_OK == hr)
  250. {
  251. Assert (m_pNetConfig);
  252. m_fOwnNetConfig = TRUE;
  253. }
  254. Unlock();
  255. }
  256. }
  257. TraceHr (ttidError, FAL, hr, FALSE, "CImplINetCfg::Initialize");
  258. return hr;
  259. }
  260. STDMETHODIMP
  261. CImplINetCfg::Uninitialize ()
  262. {
  263. HRESULT hr;
  264. hr = HrLockAndTestForValidInterface (
  265. IF_REFUSE_REENTRANCY | IF_UNINITIALIZING);
  266. if (S_OK == hr)
  267. {
  268. Assert (m_pNetConfig);
  269. Assert (m_fOwnNetConfig);
  270. delete m_pNetConfig;
  271. // CGlobalNotifyInterface::ReleaseINetCfg (called via the above
  272. // delete call) will set m_pNetConfig to NULL for us.
  273. // Verify it is so.
  274. //
  275. Assert (!m_pNetConfig);
  276. // Release our cache of INetCfgClass pointers.
  277. //
  278. ReleaseIUnknownArray (celems(m_apINetCfgClass), (IUnknown**)m_apINetCfgClass);
  279. ZeroMemory (m_apINetCfgClass, sizeof(m_apINetCfgClass));
  280. Unlock();
  281. }
  282. TraceHr (ttidError, FAL, hr, NETCFG_E_NOT_INITIALIZED == hr,
  283. "CImplINetCfg::Uninitialize");
  284. return hr;
  285. }
  286. STDMETHODIMP
  287. CImplINetCfg::Validate ()
  288. {
  289. HRESULT hr;
  290. hr = HrLockAndTestForValidInterface (IF_REFUSE_REENTRANCY);
  291. if (S_OK == hr)
  292. {
  293. Unlock();
  294. }
  295. TraceHr (ttidError, FAL, hr, FALSE, "CImplINetCfg::Validate");
  296. return hr;
  297. }
  298. STDMETHODIMP
  299. CImplINetCfg::Cancel ()
  300. {
  301. HRESULT hr;
  302. hr = HrLockAndTestForValidInterface (IF_REFUSE_REENTRANCY);
  303. if (S_OK == hr)
  304. {
  305. // Only cancel the changes if we have a prepared modify context.
  306. //
  307. if (m_pNetConfig->ModifyCtx.m_fPrepared)
  308. {
  309. hr = m_pNetConfig->ModifyCtx.HrApplyIfOkOrCancel (FALSE);
  310. }
  311. Unlock();
  312. }
  313. TraceHr (ttidError, FAL, hr, FALSE, "CImplINetCfg::Cancel");
  314. return hr;
  315. }
  316. STDMETHODIMP
  317. CImplINetCfg::Apply ()
  318. {
  319. HRESULT hr;
  320. // We need the write lock to Apply, but we don't want to prepare the
  321. // modify context if it has not been prepared. (This case amounts to
  322. // applying no changes.) Hence we use the IF_DONT_PREPARE_MODIFY_CONTEXT
  323. // flag.
  324. //
  325. hr = HrLockAndTestForValidInterface (
  326. IF_NEED_WRITE_LOCK | IF_REFUSE_REENTRANCY |
  327. IF_DONT_PREPARE_MODIFY_CONTEXT);
  328. if (S_OK == hr)
  329. {
  330. // Only apply the changes if we have a prepared modify context.
  331. //
  332. if (m_pNetConfig->ModifyCtx.m_fPrepared)
  333. {
  334. hr = m_pNetConfig->ModifyCtx.HrApplyIfOkOrCancel (TRUE);
  335. }
  336. // If there is nothing to apply, but we've previously applied
  337. // something that indicated a reboot was recommened or required,
  338. // return an indication.
  339. //
  340. else if (m_pNetConfig->ModifyCtx.m_fRebootRecommended ||
  341. m_pNetConfig->ModifyCtx.m_fRebootRequired)
  342. {
  343. hr = NETCFG_S_REBOOT;
  344. }
  345. Unlock();
  346. }
  347. TraceHr (ttidError, FAL, hr, NETCFG_S_REBOOT == hr,
  348. "CImplINetCfg::Apply");
  349. return hr;
  350. }
  351. STDMETHODIMP
  352. CImplINetCfg::EnumComponents (
  353. IN const GUID* pguidClass OPTIONAL,
  354. OUT IEnumNetCfgComponent** ppIEnum)
  355. {
  356. HRESULT hr;
  357. NETCLASS Class;
  358. // Validate parameters.
  359. //
  360. if (FBadInPtrOptional(pguidClass) || FBadOutPtr(ppIEnum))
  361. {
  362. hr = E_POINTER;
  363. }
  364. else if (pguidClass &&
  365. (NC_INVALID == (Class = NetClassEnumFromGuid(*pguidClass))))
  366. {
  367. hr = E_INVALIDARG;
  368. *ppIEnum = NULL;
  369. }
  370. else
  371. {
  372. *ppIEnum = NULL;
  373. hr = HrLockAndTestForValidInterface (IF_DEFAULT);
  374. if (S_OK == hr)
  375. {
  376. hr = CImplIEnumNetCfgComponent::HrCreateInstance (
  377. this,
  378. (pguidClass) ? Class : NC_INVALID,
  379. ppIEnum);
  380. Unlock();
  381. }
  382. }
  383. TraceHr (ttidError, FAL, hr, FALSE, "CImplINetCfg::EnumComponents");
  384. return hr;
  385. }
  386. STDMETHODIMP
  387. CImplINetCfg::FindComponent (
  388. IN PCWSTR pszInfId,
  389. OUT INetCfgComponent** ppIComp OPTIONAL)
  390. {
  391. HRESULT hr;
  392. // Validate parameters.
  393. //
  394. if (FBadInPtr(pszInfId) || FBadOutPtrOptional(ppIComp))
  395. {
  396. hr = E_POINTER;
  397. }
  398. else
  399. {
  400. if (ppIComp)
  401. {
  402. *ppIComp = NULL;
  403. }
  404. hr = HrLockAndTestForValidInterface (IF_DEFAULT);
  405. if (S_OK == hr)
  406. {
  407. CComponent* pComponent;
  408. pComponent = m_pNetConfig->Core.Components.
  409. PFindComponentByInfId (pszInfId, NULL);
  410. // Don't return interfaces to components that have had
  411. // problem loading.
  412. //
  413. if (pComponent &&
  414. pComponent->Ext.FLoadedOkayIfLoadedAtAll())
  415. {
  416. hr = S_OK;
  417. if (ppIComp)
  418. {
  419. hr = pComponent->HrGetINetCfgComponentInterface (
  420. this, ppIComp);
  421. }
  422. }
  423. else
  424. {
  425. hr = S_FALSE;
  426. }
  427. Unlock();
  428. }
  429. }
  430. TraceHr (ttidError, FAL, hr, (S_FALSE == hr),
  431. "CImplINetCfg::FindComponent");
  432. return hr;
  433. }
  434. STDMETHODIMP
  435. CImplINetCfg::QueryNetCfgClass (
  436. IN const GUID* pguidClass,
  437. IN REFIID riid,
  438. OUT VOID** ppv)
  439. {
  440. HRESULT hr;
  441. NETCLASS Class;
  442. // Validate parameters.
  443. //
  444. if (FBadInPtr(pguidClass) || FBadInPtr(&riid) || FBadOutPtr(ppv))
  445. {
  446. hr = E_POINTER;
  447. }
  448. else if (NC_INVALID == (Class = NetClassEnumFromGuid(*pguidClass)))
  449. {
  450. hr = E_INVALIDARG;
  451. *ppv = NULL;
  452. }
  453. else
  454. {
  455. *ppv = NULL;
  456. hr = HrLockAndTestForValidInterface (IF_DEFAULT);
  457. if (S_OK == hr)
  458. {
  459. // Get the INetCfgClass interface from our cache.
  460. //
  461. Assert(Class < celems(m_apINetCfgClass));
  462. INetCfgClass* pIClass = m_apINetCfgClass[Class];
  463. // If we don't have it yet, create it.
  464. //
  465. if (!pIClass)
  466. {
  467. hr = CImplINetCfgClass::HrCreateInstance (
  468. this,
  469. Class,
  470. &pIClass);
  471. if (S_OK == hr)
  472. {
  473. pIClass = m_apINetCfgClass[Class] = pIClass;
  474. Assert(pIClass);
  475. }
  476. }
  477. // Give the caller the requested interface.
  478. //
  479. if (S_OK == hr)
  480. {
  481. hr = pIClass->QueryInterface (riid, ppv);
  482. }
  483. Unlock();
  484. }
  485. }
  486. TraceHr (ttidError, FAL, hr, FALSE, "CImplINetCfg::QueryNetCfgClass");
  487. return hr;
  488. }
  489. //+---------------------------------------------------------------------------
  490. // INetCfgLock -
  491. //
  492. STDMETHODIMP
  493. CImplINetCfg::AcquireWriteLock (
  494. IN DWORD cmsTimeout,
  495. IN PCWSTR pszClientDescription,
  496. OUT PWSTR* ppszClientDescription OPTIONAL)
  497. {
  498. HRESULT hr;
  499. // Validate parameters.
  500. //
  501. if (FBadInPtr (pszClientDescription) ||
  502. FBadOutPtrOptional (ppszClientDescription))
  503. {
  504. hr = E_POINTER;
  505. }
  506. else
  507. {
  508. TraceTag (ttidNetcfgBase, "%S is asking for the write lock",
  509. pszClientDescription);
  510. // Initialize the optional output parameter.
  511. //
  512. if (ppszClientDescription)
  513. {
  514. *ppszClientDescription = NULL;
  515. }
  516. // Only administrators and netconfig operators can make changes requiring the write lock.
  517. //
  518. if (!FIsUserAdmin() && !FIsUserNetworkConfigOps())
  519. {
  520. hr = E_ACCESSDENIED;
  521. }
  522. else
  523. {
  524. hr = HrLockAndTestForValidInterface (
  525. IF_NEED_UNINITIALIZED | IF_REFUSE_REENTRANCY);
  526. if (S_OK == hr)
  527. {
  528. // Wait for the mutex to become available.
  529. //
  530. if (m_WriteLock.WaitToAcquire (cmsTimeout,
  531. pszClientDescription, ppszClientDescription))
  532. {
  533. hr = S_OK;
  534. }
  535. else
  536. {
  537. hr = S_FALSE;
  538. }
  539. Unlock();
  540. }
  541. }
  542. }
  543. TraceHr (ttidError, FAL, hr, S_FALSE == hr,
  544. "CImplINetCfg::AcquireWriteLock");
  545. return hr;
  546. }
  547. STDMETHODIMP
  548. CImplINetCfg::ReleaseWriteLock ()
  549. {
  550. HRESULT hr;
  551. // This method that can be called whether we are initialized or
  552. // not. That is why we don't call HrLockAndTestForValidInterface.
  553. //
  554. Lock ();
  555. // Check if we need to refuse re-entrancy.
  556. //
  557. hr = HrCheckForReentrancy (IF_DEFAULT);
  558. if (S_OK == hr)
  559. {
  560. m_WriteLock.ReleaseIfOwned ();
  561. }
  562. Unlock();
  563. TraceHr (ttidError, FAL, hr, FALSE,
  564. "CImplINetCfg::ReleaseWriteLock");
  565. return hr;
  566. }
  567. STDMETHODIMP
  568. CImplINetCfg::IsWriteLocked (
  569. OUT PWSTR* ppszClientDescription)
  570. {
  571. HRESULT hr;
  572. // Validate parameters.
  573. //
  574. if (FBadOutPtrOptional (ppszClientDescription))
  575. {
  576. hr = E_POINTER;
  577. }
  578. else
  579. {
  580. if (ppszClientDescription)
  581. {
  582. *ppszClientDescription = NULL;
  583. }
  584. // This method that can be called whether we are initialized or
  585. // not. That is why we don't call HrLockAndTestForValidInterface.
  586. //
  587. Lock ();
  588. // Check if we need to refuse re-entrancy.
  589. //
  590. hr = HrCheckForReentrancy (IF_DEFAULT);
  591. if (S_OK == hr)
  592. {
  593. hr = (m_WriteLock.FIsLockedByAnyone (ppszClientDescription))
  594. ? S_OK : S_FALSE;
  595. }
  596. Unlock ();
  597. }
  598. TraceHr (ttidError, FAL, hr, S_FALSE == hr,
  599. "CImplINetCfg::IsWriteLocked");
  600. return hr;
  601. }
  602. //+---------------------------------------------------------------------------
  603. // INetCfgInternalSetup -
  604. //
  605. STDMETHODIMP
  606. CImplINetCfg::BeginBatchOperation ()
  607. {
  608. HRESULT hr;
  609. hr = HrLockAndTestForValidInterface (IF_NEED_WRITE_LOCK);
  610. if (S_OK == hr)
  611. {
  612. hr = m_pNetConfig->ModifyCtx.HrBeginBatchOperation ();
  613. Unlock();
  614. }
  615. TraceHr (ttidError, FAL, hr, FALSE, "BeginBatchOperation");
  616. return hr;
  617. }
  618. STDMETHODIMP
  619. CImplINetCfg::CommitBatchOperation ()
  620. {
  621. HRESULT hr;
  622. hr = HrLockAndTestForValidInterface (IF_NEED_WRITE_LOCK);
  623. if (S_OK == hr)
  624. {
  625. hr = m_pNetConfig->ModifyCtx.HrEndBatchOperation (EBO_COMMIT_NOW);
  626. Unlock();
  627. }
  628. TraceHr (ttidError, FAL, hr, FALSE, "CommitBatchOperation");
  629. return hr;
  630. }
  631. STDMETHODIMP
  632. CImplINetCfg::SelectWithFilterAndInstall (
  633. IN HWND hwndParent,
  634. IN const GUID* pClassGuid,
  635. IN OBO_TOKEN* pOboToken OPTIONAL,
  636. IN const CI_FILTER_INFO* pcfi OPTIONAL,
  637. OUT INetCfgComponent** ppIComp OPTIONAL)
  638. {
  639. Assert (pClassGuid);
  640. HRESULT hr;
  641. NETCLASS Class;
  642. if (FBadInPtr(pClassGuid))
  643. {
  644. hr = E_POINTER;
  645. }
  646. else if (FIsEnumerated ((Class = NetClassEnumFromGuid(*pClassGuid))))
  647. {
  648. // This fcn is only for selecting non-enumerated components.
  649. //
  650. return E_INVALIDARG;
  651. }
  652. else if (!FOboTokenValidForClass(pOboToken, Class) ||
  653. FBadOutPtrOptional(ppIComp))
  654. {
  655. hr = E_POINTER;
  656. }
  657. else if (hwndParent && !IsWindow(hwndParent))
  658. {
  659. hr = E_INVALIDARG;
  660. }
  661. else if (S_OK == (hr = HrProbeOboToken(pOboToken)))
  662. {
  663. if (ppIComp)
  664. {
  665. *ppIComp = NULL;
  666. }
  667. hr = HrLockAndTestForValidInterface (
  668. IF_NEED_WRITE_LOCK | IF_ALLOW_INSTALL_OR_REMOVE);
  669. if (S_OK == hr)
  670. {
  671. Assert (m_pNetConfig->ModifyCtx.m_fPrepared);
  672. // if a filter info was specified, and it is for FC_LAN or FC_ATM,
  673. // we need to set up the reserved member of the filter info for
  674. // the class installer.
  675. //
  676. if (pcfi &&
  677. ((FC_LAN == pcfi->eFilter) || (FC_ATM == pcfi->eFilter)))
  678. {
  679. // If the pIComp member was NULL, then return invalid
  680. // argument.
  681. //
  682. Assert (pcfi->pIComp);
  683. CImplINetCfgComponent* pICompImpl;
  684. pICompImpl = (CImplINetCfgComponent*)pcfi->pIComp;
  685. hr = pICompImpl->HrIsValidInterface (IF_NEED_COMPONENT_DATA);
  686. if (S_OK == hr)
  687. {
  688. // The class installer only needs the component's
  689. // range of upper interfaces so we need to store that in the
  690. // reserved field of the filter info
  691. Assert (pICompImpl->m_pComponent);
  692. ((CI_FILTER_INFO*)pcfi)->pvReserved = (void*)
  693. pICompImpl->m_pComponent->Ext.PszUpperRange();
  694. }
  695. }
  696. COMPONENT_INSTALL_PARAMS* pParams;
  697. hr = HrCiSelectComponent (Class, hwndParent, pcfi, &pParams);
  698. if (pcfi)
  699. {
  700. // Don't want to return the private data to the client.
  701. //
  702. ((CI_FILTER_INFO*)pcfi)->pvReserved = NULL;
  703. }
  704. // Check for installing a NET_SERVICE and active RAS connections
  705. // exist. If so, warn the user that this may disconnect those
  706. // connections. (This assumes that all filter components are
  707. // of class NET_SERVICE.)
  708. //
  709. if (S_OK == hr)
  710. {
  711. Assert (pParams);
  712. if ((NC_NETSERVICE == pParams->Class) &&
  713. FExistActiveRasConnections ())
  714. {
  715. INT nRet;
  716. nRet = NcMsgBox (
  717. _Module.GetResourceInstance(),
  718. hwndParent,
  719. IDS_WARNING_CAPTION,
  720. IDS_ACTIVE_RAS_CONNECTION_WARNING,
  721. MB_ICONQUESTION | MB_YESNO);
  722. if (IDYES != nRet)
  723. {
  724. hr = HRESULT_FROM_WIN32(ERROR_CANCELLED);
  725. }
  726. }
  727. }
  728. if (S_OK == hr)
  729. {
  730. Assert(pParams);
  731. CComponent* pComponent;
  732. // Check to see if the user selected a component that
  733. // is already installed. If so, we need to reinstall.
  734. //
  735. pComponent = m_pNetConfig->Core.Components.
  736. PFindComponentByInfId(pParams->pszInfId, NULL);
  737. if (!pComponent)
  738. {
  739. pParams->pOboToken = pOboToken;
  740. hr = m_pNetConfig->ModifyCtx.
  741. HrInstallNewOrReferenceExistingComponent (
  742. *pParams, &pComponent);
  743. }
  744. else
  745. {
  746. // reinstall. call Update.
  747. hr = UpdateNonEnumeratedComponent (
  748. pComponent->GetINetCfgComponentInterface(),
  749. NSF_COMPONENT_UPDATE, 0);
  750. }
  751. // The above may return NETCFG_S_REBOOT so use SUCCEEDED instead
  752. // of checking for S_OK only.
  753. //
  754. if (SUCCEEDED(hr) && ppIComp)
  755. {
  756. pComponent->HrGetINetCfgComponentInterface (
  757. this,
  758. ppIComp);
  759. }
  760. delete pParams;
  761. }
  762. Unlock();
  763. }
  764. }
  765. TraceHr (ttidError, FAL, hr,
  766. (HRESULT_FROM_WIN32(ERROR_CANCELLED) == hr) ||
  767. (NETCFG_S_REBOOT == hr),
  768. "SelectWithFilterAndInstall");
  769. return hr;
  770. }
  771. STDMETHODIMP
  772. CImplINetCfg::EnumeratedComponentInstalled (
  773. IN PVOID pv /* type of CComponent */)
  774. {
  775. HRESULT hr;
  776. CComponent* pComponent;
  777. pComponent = (CComponent*)pv;
  778. Assert (pComponent);
  779. Assert (FIsEnumerated(pComponent->Class()));
  780. Assert (pComponent->m_pszInfId && *pComponent->m_pszInfId);
  781. Assert (pComponent->m_pszPnpId && *pComponent->m_pszPnpId);
  782. hr = HrLockAndTestForValidInterface (IF_NEED_WRITE_LOCK |
  783. IF_ALLOW_INSTALL_OR_REMOVE);
  784. if (S_OK == hr)
  785. {
  786. COMPONENT_INSTALL_PARAMS Params;
  787. CComponent* pReturned;
  788. Assert (m_pNetConfig->ModifyCtx.m_fPrepared);
  789. ZeroMemory(&Params, sizeof(Params));
  790. Params.pComponent = (CComponent*)pComponent;
  791. hr = m_pNetConfig->ModifyCtx.HrInstallNewOrReferenceExistingComponent (
  792. Params,
  793. &pReturned);
  794. if (S_OK == hr)
  795. {
  796. Assert (pComponent == pReturned);
  797. }
  798. Unlock();
  799. }
  800. TraceHr (ttidError, FAL, hr, FALSE, "EnumeratedComponentInstalled");
  801. return hr;
  802. }
  803. STDMETHODIMP
  804. CImplINetCfg::EnumeratedComponentUpdated (
  805. IN PCWSTR pszPnpId)
  806. {
  807. HRESULT hr;
  808. Assert (pszPnpId && *pszPnpId);
  809. hr = HrLockAndTestForValidInterface (IF_NEED_WRITE_LOCK);
  810. if (S_OK == hr)
  811. {
  812. CComponent* pComponent;
  813. Assert (m_pNetConfig->ModifyCtx.m_fPrepared);
  814. pComponent = m_pNetConfig->Core.Components.
  815. PFindComponentByPnpId (pszPnpId);
  816. if (pComponent)
  817. {
  818. // Note: Core info may have changed so load core info from driver key.
  819. // If not a remote boot adapter, do a binding analysis to see if
  820. // anything has changed.
  821. hr = S_OK;
  822. }
  823. Unlock();
  824. }
  825. TraceHr (ttidError, FAL, hr, FALSE, "EnumeratedComponentUpdated");
  826. return hr;
  827. }
  828. STDMETHODIMP
  829. CImplINetCfg::UpdateNonEnumeratedComponent (
  830. IN INetCfgComponent* pIComp,
  831. IN DWORD dwSetupFlags,
  832. IN DWORD dwUpgradeFromBuildNo)
  833. {
  834. HRESULT hr;
  835. Assert (pIComp);
  836. hr = HrLockAndTestForValidInterface (IF_NEED_WRITE_LOCK |
  837. IF_ALLOW_INSTALL_OR_REMOVE);
  838. if (S_OK == hr)
  839. {
  840. CImplINetCfgComponent* pICompToUpdate;
  841. Assert (m_pNetConfig->ModifyCtx.m_fPrepared);
  842. pICompToUpdate = (CImplINetCfgComponent*)pIComp;
  843. if (pICompToUpdate == NULL)
  844. {
  845. return E_OUTOFMEMORY;
  846. }
  847. hr = pICompToUpdate->HrIsValidInterface (IF_NEED_COMPONENT_DATA);
  848. if (S_OK == hr)
  849. {
  850. HKEY hkeyInstance;
  851. CComponent* pComponent = pICompToUpdate->m_pComponent;
  852. hr = pComponent->HrOpenInstanceKey (KEY_READ_WRITE_DELETE, &hkeyInstance,
  853. NULL, NULL);
  854. if (S_OK == hr)
  855. {
  856. DWORD dwNewCharacter;
  857. COMPONENT_INSTALL_PARAMS Params;
  858. ZeroMemory (&Params, sizeof (Params));
  859. Params.Class = pComponent->Class();
  860. Params.pszInfId = pComponent->m_pszInfId;
  861. hr = HrCiInstallComponent (Params, NULL, &dwNewCharacter);
  862. // The driver could not be selected because
  863. // this component's section or inf is missing.
  864. // We will remove the component in this case.
  865. //
  866. if (SPAPI_E_NO_DRIVER_SELECTED == hr)
  867. {
  868. pComponent->Refs.RemoveAllReferences();
  869. hr = m_pNetConfig->ModifyCtx.
  870. HrRemoveComponentIfNotReferenced (pComponent,
  871. NULL, NULL);
  872. }
  873. else if (S_OK == hr)
  874. {
  875. pComponent->m_dwCharacter = dwNewCharacter;
  876. AddOrRemoveDontExposeLowerCharacteristicIfNeeded (
  877. pComponent);
  878. hr = m_pNetConfig->ModifyCtx.HrUpdateComponent (
  879. pComponent,
  880. dwSetupFlags,
  881. dwUpgradeFromBuildNo);
  882. }
  883. RegCloseKey (hkeyInstance);
  884. }
  885. }
  886. Unlock();
  887. }
  888. TraceHr (ttidError, FAL, hr, FALSE, "UpdateNonEnumeratedComponent");
  889. return S_OK;
  890. }
  891. STDMETHODIMP
  892. CImplINetCfg::EnumeratedComponentRemoved (
  893. IN PCWSTR pszPnpId)
  894. {
  895. HRESULT hr;
  896. Assert (pszPnpId);
  897. hr = HrLockAndTestForValidInterface (IF_NEED_WRITE_LOCK |
  898. IF_ALLOW_INSTALL_OR_REMOVE);
  899. if (S_OK == hr)
  900. {
  901. CComponent* pComponent;
  902. Assert (m_pNetConfig->ModifyCtx.m_fPrepared);
  903. pComponent = m_pNetConfig->Core.Components.
  904. PFindComponentByPnpId (pszPnpId);
  905. // If we found it, remove it. Otherwise our work here is done.
  906. //
  907. if (pComponent)
  908. {
  909. hr = m_pNetConfig->ModifyCtx.
  910. HrRemoveComponentIfNotReferenced (pComponent, NULL, NULL);
  911. }
  912. Unlock();
  913. }
  914. TraceHr (ttidError, FAL, hr, FALSE, "EnumeratedComponentRemoved");
  915. return hr;
  916. }
  917. //+---------------------------------------------------------------------------
  918. // INetCfgSpecialCase -
  919. //
  920. STDMETHODIMP
  921. CImplINetCfg::GetAdapterOrder (
  922. OUT DWORD* pcAdapters,
  923. OUT INetCfgComponent*** papAdapters,
  924. OUT BOOL* pfWanAdaptersFirst)
  925. {
  926. return E_NOTIMPL;
  927. }
  928. STDMETHODIMP
  929. CImplINetCfg::SetAdapterOrder (
  930. IN DWORD cAdapters,
  931. IN INetCfgComponent** apAdapters,
  932. IN BOOL fWanAdaptersFirst)
  933. {
  934. return E_NOTIMPL;
  935. }
  936. STDMETHODIMP
  937. CImplINetCfg::GetWanAdaptersFirst (
  938. OUT BOOL* pfWanAdaptersFirst)
  939. {
  940. HRESULT hr;
  941. // Validate parameters.
  942. //
  943. if (FBadOutPtr (pfWanAdaptersFirst))
  944. {
  945. hr = E_POINTER;
  946. }
  947. else
  948. {
  949. hr = HrLockAndTestForValidInterface (IF_DEFAULT);
  950. if (S_OK == hr)
  951. {
  952. *pfWanAdaptersFirst = m_pNetConfig->Core.
  953. StackTable.m_fWanAdaptersFirst;
  954. Unlock();
  955. }
  956. }
  957. TraceHr (ttidError, FAL, hr, FALSE,
  958. "CImplINetCfg::GetWanAdaptersFirst");
  959. return hr;
  960. }
  961. STDMETHODIMP
  962. CImplINetCfg::SetWanAdaptersFirst (
  963. IN BOOL fWanAdaptersFirst)
  964. {
  965. HRESULT hr;
  966. hr = HrLockAndTestForValidInterface (IF_NEED_WRITE_LOCK);
  967. if (S_OK == hr)
  968. {
  969. Assert (m_pNetConfig->ModifyCtx.m_fPrepared);
  970. m_pNetConfig->Core.StackTable.SetWanAdapterOrder (!!fWanAdaptersFirst);
  971. Unlock();
  972. }
  973. TraceHr (ttidError, FAL, hr, FALSE,
  974. "CImplINetCfg::SetWanAdaptersFirst");
  975. return hr;
  976. }
  977. //+---------------------------------------------------------------------------
  978. // INetCfgPnpReconfigCallback -
  979. //
  980. STDMETHODIMP
  981. CImplINetCfg::SendPnpReconfig (
  982. IN NCPNP_RECONFIG_LAYER Layer,
  983. IN PCWSTR pszUpper,
  984. IN PCWSTR pszLower,
  985. IN PVOID pvData,
  986. IN DWORD dwSizeOfData)
  987. {
  988. HRESULT hr;
  989. if ((NCRL_NDIS != Layer) && (NCRL_TDI != Layer))
  990. {
  991. hr = E_INVALIDARG;
  992. }
  993. else if (FBadInPtr(pszUpper) || FBadInPtr(pszLower) ||
  994. IsBadReadPtr(pvData, dwSizeOfData))
  995. {
  996. hr = E_POINTER;
  997. }
  998. else
  999. {
  1000. BOOL fOk;
  1001. UNICODE_STRING LowerString;
  1002. UNICODE_STRING UpperString;
  1003. UNICODE_STRING BindList;
  1004. WCHAR szLower [_MAX_PATH];
  1005. hr = S_OK;
  1006. *szLower = 0;
  1007. if (*pszLower)
  1008. {
  1009. wcscpy (szLower, L"\\Device\\");
  1010. wcsncat (szLower, pszLower, celems(szLower) - wcslen(szLower));
  1011. }
  1012. RtlInitUnicodeString (&LowerString, szLower);
  1013. RtlInitUnicodeString (&UpperString, pszUpper);
  1014. RtlInitUnicodeString (&BindList, NULL);
  1015. fOk = NdisHandlePnPEvent (
  1016. (NCRL_NDIS == Layer) ? NDIS : TDI,
  1017. RECONFIGURE,
  1018. &LowerString,
  1019. &UpperString,
  1020. &BindList,
  1021. pvData,
  1022. dwSizeOfData);
  1023. if (!fOk)
  1024. {
  1025. hr = HrFromLastWin32Error ();
  1026. }
  1027. }
  1028. TraceHr (ttidError, FAL, hr, FALSE, "CImplINetCfg::SendPnpReconfig");
  1029. return hr;
  1030. }
  1031. //+---------------------------------------------------------------------------
  1032. // CImplINetCfgHolder -
  1033. //
  1034. VOID
  1035. CImplINetCfgHolder::HoldINetCfg (
  1036. CImplINetCfg* pINetCfg)
  1037. {
  1038. Assert(pINetCfg);
  1039. AddRefObj (pINetCfg->GetUnknown());
  1040. m_pINetCfg = pINetCfg;
  1041. }
  1042. HRESULT
  1043. CImplINetCfgHolder::HrLockAndTestForValidInterface (
  1044. DWORD dwFlags)
  1045. {
  1046. HRESULT hr;
  1047. Lock();
  1048. hr = m_pINetCfg->HrIsValidInterface (dwFlags);
  1049. if (S_OK != hr)
  1050. {
  1051. Unlock();
  1052. }
  1053. TraceHr (ttidError, FAL, hr, FALSE,
  1054. "CImplINetCfgHolder::HrLockAndTestForValidInterface");
  1055. return hr;
  1056. }