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.

1264 lines
32 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 if (wcslen (pszInfId) >= MAX_DEVICE_ID_LEN)
  399. {
  400. //impose the same limit on infid as imposed by pnp on pnpid.
  401. hr = E_INVALIDARG;
  402. }
  403. else
  404. {
  405. if (ppIComp)
  406. {
  407. *ppIComp = NULL;
  408. }
  409. hr = HrLockAndTestForValidInterface (IF_DEFAULT);
  410. if (S_OK == hr)
  411. {
  412. CComponent* pComponent;
  413. pComponent = m_pNetConfig->Core.Components.
  414. PFindComponentByInfId (pszInfId, NULL);
  415. // Don't return interfaces to components that have had
  416. // problem loading.
  417. //
  418. if (pComponent &&
  419. pComponent->Ext.FLoadedOkayIfLoadedAtAll())
  420. {
  421. hr = S_OK;
  422. if (ppIComp)
  423. {
  424. hr = pComponent->HrGetINetCfgComponentInterface (
  425. this, ppIComp);
  426. }
  427. }
  428. else
  429. {
  430. hr = S_FALSE;
  431. }
  432. Unlock();
  433. }
  434. }
  435. TraceHr (ttidError, FAL, hr, (S_FALSE == hr),
  436. "CImplINetCfg::FindComponent");
  437. return hr;
  438. }
  439. STDMETHODIMP
  440. CImplINetCfg::QueryNetCfgClass (
  441. IN const GUID* pguidClass,
  442. IN REFIID riid,
  443. OUT VOID** ppv)
  444. {
  445. HRESULT hr;
  446. NETCLASS Class;
  447. // Validate parameters.
  448. //
  449. if (FBadInPtr(pguidClass) || FBadInPtr(&riid) || FBadOutPtr(ppv))
  450. {
  451. hr = E_POINTER;
  452. }
  453. else if (NC_INVALID == (Class = NetClassEnumFromGuid(*pguidClass)))
  454. {
  455. hr = E_INVALIDARG;
  456. *ppv = NULL;
  457. }
  458. else
  459. {
  460. *ppv = NULL;
  461. hr = HrLockAndTestForValidInterface (IF_DEFAULT);
  462. if (S_OK == hr)
  463. {
  464. // Get the INetCfgClass interface from our cache.
  465. //
  466. Assert(Class < celems(m_apINetCfgClass));
  467. INetCfgClass* pIClass = m_apINetCfgClass[Class];
  468. // If we don't have it yet, create it.
  469. //
  470. if (!pIClass)
  471. {
  472. hr = CImplINetCfgClass::HrCreateInstance (
  473. this,
  474. Class,
  475. &pIClass);
  476. if (S_OK == hr)
  477. {
  478. pIClass = m_apINetCfgClass[Class] = pIClass;
  479. Assert(pIClass);
  480. }
  481. }
  482. // Give the caller the requested interface.
  483. //
  484. if (S_OK == hr)
  485. {
  486. hr = pIClass->QueryInterface (riid, ppv);
  487. }
  488. Unlock();
  489. }
  490. }
  491. TraceHr (ttidError, FAL, hr, FALSE, "CImplINetCfg::QueryNetCfgClass");
  492. return hr;
  493. }
  494. //+---------------------------------------------------------------------------
  495. // INetCfgLock -
  496. //
  497. STDMETHODIMP
  498. CImplINetCfg::AcquireWriteLock (
  499. IN DWORD cmsTimeout,
  500. IN PCWSTR pszClientDescription,
  501. OUT PWSTR* ppszClientDescription OPTIONAL)
  502. {
  503. HRESULT hr;
  504. // Validate parameters.
  505. //
  506. if (FBadInPtr (pszClientDescription) ||
  507. FBadOutPtrOptional (ppszClientDescription))
  508. {
  509. hr = E_POINTER;
  510. }
  511. else
  512. {
  513. TraceTag (ttidNetcfgBase, "%S is asking for the write lock",
  514. pszClientDescription);
  515. // Initialize the optional output parameter.
  516. //
  517. if (ppszClientDescription)
  518. {
  519. *ppszClientDescription = NULL;
  520. }
  521. // Only administrators and netconfig operators can make changes requiring the write lock.
  522. //
  523. if (!FIsUserAdmin() && !FIsUserNetworkConfigOps())
  524. {
  525. hr = E_ACCESSDENIED;
  526. }
  527. else
  528. {
  529. hr = HrLockAndTestForValidInterface (
  530. IF_NEED_UNINITIALIZED | IF_REFUSE_REENTRANCY);
  531. if (S_OK == hr)
  532. {
  533. // Wait for the mutex to become available.
  534. //
  535. if (m_WriteLock.WaitToAcquire (cmsTimeout,
  536. pszClientDescription, ppszClientDescription))
  537. {
  538. hr = S_OK;
  539. }
  540. else
  541. {
  542. hr = S_FALSE;
  543. }
  544. Unlock();
  545. }
  546. }
  547. }
  548. TraceHr (ttidError, FAL, hr, S_FALSE == hr,
  549. "CImplINetCfg::AcquireWriteLock");
  550. return hr;
  551. }
  552. STDMETHODIMP
  553. CImplINetCfg::ReleaseWriteLock ()
  554. {
  555. HRESULT hr;
  556. // This method that can be called whether we are initialized or
  557. // not. That is why we don't call HrLockAndTestForValidInterface.
  558. //
  559. Lock ();
  560. // Check if we need to refuse re-entrancy.
  561. //
  562. hr = HrCheckForReentrancy (IF_DEFAULT);
  563. if (S_OK == hr)
  564. {
  565. m_WriteLock.ReleaseIfOwned ();
  566. }
  567. Unlock();
  568. TraceHr (ttidError, FAL, hr, FALSE,
  569. "CImplINetCfg::ReleaseWriteLock");
  570. return hr;
  571. }
  572. STDMETHODIMP
  573. CImplINetCfg::IsWriteLocked (
  574. OUT PWSTR* ppszClientDescription)
  575. {
  576. HRESULT hr;
  577. // Validate parameters.
  578. //
  579. if (FBadOutPtrOptional (ppszClientDescription))
  580. {
  581. hr = E_POINTER;
  582. }
  583. else
  584. {
  585. if (ppszClientDescription)
  586. {
  587. *ppszClientDescription = NULL;
  588. }
  589. // This method that can be called whether we are initialized or
  590. // not. That is why we don't call HrLockAndTestForValidInterface.
  591. //
  592. Lock ();
  593. // Check if we need to refuse re-entrancy.
  594. //
  595. hr = HrCheckForReentrancy (IF_DEFAULT);
  596. if (S_OK == hr)
  597. {
  598. hr = (m_WriteLock.FIsLockedByAnyone (ppszClientDescription))
  599. ? S_OK : S_FALSE;
  600. }
  601. Unlock ();
  602. }
  603. TraceHr (ttidError, FAL, hr, S_FALSE == hr,
  604. "CImplINetCfg::IsWriteLocked");
  605. return hr;
  606. }
  607. //+---------------------------------------------------------------------------
  608. // INetCfgInternalSetup -
  609. //
  610. STDMETHODIMP
  611. CImplINetCfg::BeginBatchOperation ()
  612. {
  613. HRESULT hr;
  614. hr = HrLockAndTestForValidInterface (IF_NEED_WRITE_LOCK);
  615. if (S_OK == hr)
  616. {
  617. hr = m_pNetConfig->ModifyCtx.HrBeginBatchOperation ();
  618. Unlock();
  619. }
  620. TraceHr (ttidError, FAL, hr, FALSE, "BeginBatchOperation");
  621. return hr;
  622. }
  623. STDMETHODIMP
  624. CImplINetCfg::CommitBatchOperation ()
  625. {
  626. HRESULT hr;
  627. hr = HrLockAndTestForValidInterface (IF_NEED_WRITE_LOCK);
  628. if (S_OK == hr)
  629. {
  630. hr = m_pNetConfig->ModifyCtx.HrEndBatchOperation (EBO_COMMIT_NOW);
  631. Unlock();
  632. }
  633. TraceHr (ttidError, FAL, hr, FALSE, "CommitBatchOperation");
  634. return hr;
  635. }
  636. STDMETHODIMP
  637. CImplINetCfg::SelectWithFilterAndInstall (
  638. IN HWND hwndParent,
  639. IN const GUID* pClassGuid,
  640. IN OBO_TOKEN* pOboToken OPTIONAL,
  641. IN const CI_FILTER_INFO* pcfi OPTIONAL,
  642. OUT INetCfgComponent** ppIComp OPTIONAL)
  643. {
  644. Assert (pClassGuid);
  645. HRESULT hr;
  646. NETCLASS Class;
  647. if (FBadInPtr(pClassGuid))
  648. {
  649. hr = E_POINTER;
  650. }
  651. else if (FIsEnumerated ((Class = NetClassEnumFromGuid(*pClassGuid))))
  652. {
  653. // This fcn is only for selecting non-enumerated components.
  654. //
  655. return E_INVALIDARG;
  656. }
  657. else if (!FOboTokenValidForClass(pOboToken, Class) ||
  658. FBadOutPtrOptional(ppIComp))
  659. {
  660. hr = E_POINTER;
  661. }
  662. else if (hwndParent && !IsWindow(hwndParent))
  663. {
  664. hr = E_INVALIDARG;
  665. }
  666. else if (S_OK == (hr = HrProbeOboToken(pOboToken)))
  667. {
  668. if (ppIComp)
  669. {
  670. *ppIComp = NULL;
  671. }
  672. hr = HrLockAndTestForValidInterface (
  673. IF_NEED_WRITE_LOCK | IF_ALLOW_INSTALL_OR_REMOVE);
  674. if (S_OK == hr)
  675. {
  676. Assert (m_pNetConfig->ModifyCtx.m_fPrepared);
  677. // if a filter info was specified, and it is for FC_LAN or FC_ATM,
  678. // we need to set up the reserved member of the filter info for
  679. // the class installer.
  680. //
  681. if (pcfi &&
  682. ((FC_LAN == pcfi->eFilter) || (FC_ATM == pcfi->eFilter)))
  683. {
  684. // If the pIComp member was NULL, then return invalid
  685. // argument.
  686. //
  687. Assert (pcfi->pIComp);
  688. CImplINetCfgComponent* pICompImpl;
  689. pICompImpl = (CImplINetCfgComponent*)pcfi->pIComp;
  690. hr = pICompImpl->HrIsValidInterface (IF_NEED_COMPONENT_DATA);
  691. if (S_OK == hr)
  692. {
  693. // The class installer needs to access adapter's attributes
  694. // like lower and upper range. So we store a pointer to
  695. // the associated CComponent in the reserved field of the filter
  696. // info
  697. Assert (pICompImpl->m_pComponent);
  698. ((CI_FILTER_INFO*)pcfi)->pvReserved = (void*)
  699. pICompImpl->m_pComponent;
  700. }
  701. }
  702. COMPONENT_INSTALL_PARAMS* pParams;
  703. hr = HrCiSelectComponent (Class, hwndParent, pcfi, &pParams);
  704. if (pcfi)
  705. {
  706. // Don't want to return the private data to the client.
  707. //
  708. ((CI_FILTER_INFO*)pcfi)->pvReserved = NULL;
  709. }
  710. // Check for installing a NET_SERVICE and active RAS connections
  711. // exist. If so, warn the user that this may disconnect those
  712. // connections. (This assumes that all filter components are
  713. // of class NET_SERVICE.)
  714. //
  715. if (S_OK == hr)
  716. {
  717. Assert (pParams);
  718. if ((NC_NETSERVICE == pParams->Class) &&
  719. FExistActiveRasConnections ())
  720. {
  721. INT nRet;
  722. nRet = NcMsgBox (
  723. _Module.GetResourceInstance(),
  724. hwndParent,
  725. IDS_WARNING_CAPTION,
  726. IDS_ACTIVE_RAS_CONNECTION_WARNING,
  727. MB_ICONQUESTION | MB_YESNO);
  728. if (IDYES != nRet)
  729. {
  730. hr = HRESULT_FROM_WIN32(ERROR_CANCELLED);
  731. }
  732. }
  733. }
  734. if (S_OK == hr)
  735. {
  736. Assert(pParams);
  737. CComponent* pComponent;
  738. // Check to see if the user selected a component that
  739. // is already installed. If so, we need to reinstall.
  740. //
  741. pComponent = m_pNetConfig->Core.Components.
  742. PFindComponentByInfId(pParams->pszInfId, NULL);
  743. if (!pComponent)
  744. {
  745. pParams->pOboToken = pOboToken;
  746. hr = m_pNetConfig->ModifyCtx.
  747. HrInstallNewOrReferenceExistingComponent (
  748. *pParams, &pComponent);
  749. }
  750. else
  751. {
  752. // reinstall. call Update.
  753. hr = UpdateNonEnumeratedComponent (
  754. pComponent->GetINetCfgComponentInterface(),
  755. NSF_COMPONENT_UPDATE, 0);
  756. }
  757. // The above may return NETCFG_S_REBOOT so use SUCCEEDED instead
  758. // of checking for S_OK only.
  759. //
  760. if (SUCCEEDED(hr) && ppIComp)
  761. {
  762. pComponent->HrGetINetCfgComponentInterface (
  763. this,
  764. ppIComp);
  765. }
  766. delete pParams;
  767. }
  768. Unlock();
  769. }
  770. }
  771. TraceHr (ttidError, FAL, hr,
  772. (HRESULT_FROM_WIN32(ERROR_CANCELLED) == hr) ||
  773. (NETCFG_S_REBOOT == hr),
  774. "SelectWithFilterAndInstall");
  775. return hr;
  776. }
  777. STDMETHODIMP
  778. CImplINetCfg::EnumeratedComponentInstalled (
  779. IN PVOID pv /* type of CComponent */)
  780. {
  781. HRESULT hr;
  782. CComponent* pComponent;
  783. pComponent = (CComponent*)pv;
  784. Assert (pComponent);
  785. Assert (FIsEnumerated(pComponent->Class()));
  786. Assert (pComponent->m_pszInfId && *pComponent->m_pszInfId);
  787. Assert (pComponent->m_pszPnpId && *pComponent->m_pszPnpId);
  788. hr = HrLockAndTestForValidInterface (IF_NEED_WRITE_LOCK |
  789. IF_ALLOW_INSTALL_OR_REMOVE);
  790. if (S_OK == hr)
  791. {
  792. COMPONENT_INSTALL_PARAMS Params;
  793. CComponent* pReturned;
  794. Assert (m_pNetConfig->ModifyCtx.m_fPrepared);
  795. ZeroMemory(&Params, sizeof(Params));
  796. Params.pComponent = (CComponent*)pComponent;
  797. hr = m_pNetConfig->ModifyCtx.HrInstallNewOrReferenceExistingComponent (
  798. Params,
  799. &pReturned);
  800. if (S_OK == hr)
  801. {
  802. Assert (pComponent == pReturned);
  803. }
  804. Unlock();
  805. }
  806. TraceHr (ttidError, FAL, hr, FALSE, "EnumeratedComponentInstalled");
  807. return hr;
  808. }
  809. STDMETHODIMP
  810. CImplINetCfg::EnumeratedComponentUpdated (
  811. IN PCWSTR pszPnpId)
  812. {
  813. HRESULT hr;
  814. Assert (pszPnpId && *pszPnpId);
  815. hr = HrLockAndTestForValidInterface (IF_NEED_WRITE_LOCK);
  816. if (S_OK == hr)
  817. {
  818. CComponent* pComponent;
  819. Assert (m_pNetConfig->ModifyCtx.m_fPrepared);
  820. pComponent = m_pNetConfig->Core.Components.
  821. PFindComponentByPnpId (pszPnpId);
  822. if (pComponent)
  823. {
  824. // Note: Core info may have changed so load core info from driver key.
  825. // If not a remote boot adapter, do a binding analysis to see if
  826. // anything has changed.
  827. hr = S_OK;
  828. }
  829. Unlock();
  830. }
  831. TraceHr (ttidError, FAL, hr, FALSE, "EnumeratedComponentUpdated");
  832. return hr;
  833. }
  834. STDMETHODIMP
  835. CImplINetCfg::UpdateNonEnumeratedComponent (
  836. IN INetCfgComponent* pIComp,
  837. IN DWORD dwSetupFlags,
  838. IN DWORD dwUpgradeFromBuildNo)
  839. {
  840. HRESULT hr;
  841. Assert (pIComp);
  842. hr = HrLockAndTestForValidInterface (IF_NEED_WRITE_LOCK |
  843. IF_ALLOW_INSTALL_OR_REMOVE);
  844. if (S_OK == hr)
  845. {
  846. CImplINetCfgComponent* pICompToUpdate;
  847. Assert (m_pNetConfig->ModifyCtx.m_fPrepared);
  848. pICompToUpdate = (CImplINetCfgComponent*)pIComp;
  849. if (pICompToUpdate == NULL)
  850. {
  851. return E_OUTOFMEMORY;
  852. }
  853. hr = pICompToUpdate->HrIsValidInterface (IF_NEED_COMPONENT_DATA);
  854. if (S_OK == hr)
  855. {
  856. HKEY hkeyInstance;
  857. CComponent* pComponent = pICompToUpdate->m_pComponent;
  858. hr = pComponent->HrOpenInstanceKey (KEY_READ_WRITE_DELETE, &hkeyInstance,
  859. NULL, NULL);
  860. if (S_OK == hr)
  861. {
  862. DWORD dwNewCharacter;
  863. COMPONENT_INSTALL_PARAMS Params;
  864. ZeroMemory (&Params, sizeof (Params));
  865. Params.Class = pComponent->Class();
  866. Params.pszInfId = pComponent->m_pszInfId;
  867. hr = HrCiInstallComponent (Params, NULL, &dwNewCharacter);
  868. // The driver could not be selected because
  869. // this component's section or inf is missing.
  870. // We will remove the component in this case.
  871. //
  872. if (SPAPI_E_NO_DRIVER_SELECTED == hr)
  873. {
  874. pComponent->Refs.RemoveAllReferences();
  875. hr = m_pNetConfig->ModifyCtx.
  876. HrRemoveComponentIfNotReferenced (pComponent,
  877. NULL, NULL);
  878. }
  879. else if (S_OK == hr)
  880. {
  881. pComponent->m_dwCharacter = dwNewCharacter;
  882. AddOrRemoveDontExposeLowerCharacteristicIfNeeded (
  883. pComponent);
  884. hr = m_pNetConfig->ModifyCtx.HrUpdateComponent (
  885. pComponent,
  886. dwSetupFlags,
  887. dwUpgradeFromBuildNo);
  888. }
  889. RegCloseKey (hkeyInstance);
  890. }
  891. }
  892. Unlock();
  893. }
  894. TraceHr (ttidError, FAL, hr, FALSE, "UpdateNonEnumeratedComponent");
  895. return S_OK;
  896. }
  897. STDMETHODIMP
  898. CImplINetCfg::EnumeratedComponentRemoved (
  899. IN PCWSTR pszPnpId)
  900. {
  901. HRESULT hr;
  902. Assert (pszPnpId);
  903. hr = HrLockAndTestForValidInterface (IF_NEED_WRITE_LOCK |
  904. IF_ALLOW_INSTALL_OR_REMOVE);
  905. if (S_OK == hr)
  906. {
  907. CComponent* pComponent;
  908. Assert (m_pNetConfig->ModifyCtx.m_fPrepared);
  909. pComponent = m_pNetConfig->Core.Components.
  910. PFindComponentByPnpId (pszPnpId);
  911. // If we found it, remove it. Otherwise our work here is done.
  912. //
  913. if (pComponent)
  914. {
  915. hr = m_pNetConfig->ModifyCtx.
  916. HrRemoveComponentIfNotReferenced (pComponent, NULL, NULL);
  917. }
  918. Unlock();
  919. }
  920. TraceHr (ttidError, FAL, hr, FALSE, "EnumeratedComponentRemoved");
  921. return hr;
  922. }
  923. //+---------------------------------------------------------------------------
  924. // INetCfgSpecialCase -
  925. //
  926. STDMETHODIMP
  927. CImplINetCfg::GetAdapterOrder (
  928. OUT DWORD* pcAdapters,
  929. OUT INetCfgComponent*** papAdapters,
  930. OUT BOOL* pfWanAdaptersFirst)
  931. {
  932. return E_NOTIMPL;
  933. }
  934. STDMETHODIMP
  935. CImplINetCfg::SetAdapterOrder (
  936. IN DWORD cAdapters,
  937. IN INetCfgComponent** apAdapters,
  938. IN BOOL fWanAdaptersFirst)
  939. {
  940. return E_NOTIMPL;
  941. }
  942. STDMETHODIMP
  943. CImplINetCfg::GetWanAdaptersFirst (
  944. OUT BOOL* pfWanAdaptersFirst)
  945. {
  946. HRESULT hr;
  947. // Validate parameters.
  948. //
  949. if (FBadOutPtr (pfWanAdaptersFirst))
  950. {
  951. hr = E_POINTER;
  952. }
  953. else
  954. {
  955. hr = HrLockAndTestForValidInterface (IF_DEFAULT);
  956. if (S_OK == hr)
  957. {
  958. *pfWanAdaptersFirst = m_pNetConfig->Core.
  959. StackTable.m_fWanAdaptersFirst;
  960. Unlock();
  961. }
  962. }
  963. TraceHr (ttidError, FAL, hr, FALSE,
  964. "CImplINetCfg::GetWanAdaptersFirst");
  965. return hr;
  966. }
  967. STDMETHODIMP
  968. CImplINetCfg::SetWanAdaptersFirst (
  969. IN BOOL fWanAdaptersFirst)
  970. {
  971. HRESULT hr;
  972. hr = HrLockAndTestForValidInterface (IF_NEED_WRITE_LOCK);
  973. if (S_OK == hr)
  974. {
  975. Assert (m_pNetConfig->ModifyCtx.m_fPrepared);
  976. m_pNetConfig->Core.StackTable.SetWanAdapterOrder (!!fWanAdaptersFirst);
  977. Unlock();
  978. }
  979. TraceHr (ttidError, FAL, hr, FALSE,
  980. "CImplINetCfg::SetWanAdaptersFirst");
  981. return hr;
  982. }
  983. //+---------------------------------------------------------------------------
  984. // INetCfgPnpReconfigCallback -
  985. //
  986. STDMETHODIMP
  987. CImplINetCfg::SendPnpReconfig (
  988. IN NCPNP_RECONFIG_LAYER Layer,
  989. IN PCWSTR pszUpper,
  990. IN PCWSTR pszLower,
  991. IN PVOID pvData,
  992. IN DWORD dwSizeOfData)
  993. {
  994. HRESULT hr;
  995. if ((NCRL_NDIS != Layer) && (NCRL_TDI != Layer))
  996. {
  997. hr = E_INVALIDARG;
  998. }
  999. else if (FBadInPtr(pszUpper) || FBadInPtr(pszLower) ||
  1000. IsBadReadPtr(pvData, dwSizeOfData))
  1001. {
  1002. hr = E_POINTER;
  1003. }
  1004. else
  1005. {
  1006. BOOL fOk;
  1007. UNICODE_STRING LowerString;
  1008. UNICODE_STRING UpperString;
  1009. UNICODE_STRING BindList;
  1010. WCHAR szLower [_MAX_PATH];
  1011. hr = S_OK;
  1012. *szLower = 0;
  1013. if (*pszLower)
  1014. {
  1015. wcscpy (szLower, L"\\Device\\");
  1016. wcsncat (szLower, pszLower, celems(szLower) - wcslen(szLower));
  1017. }
  1018. RtlInitUnicodeString (&LowerString, szLower);
  1019. RtlInitUnicodeString (&UpperString, pszUpper);
  1020. RtlInitUnicodeString (&BindList, NULL);
  1021. fOk = NdisHandlePnPEvent (
  1022. (NCRL_NDIS == Layer) ? NDIS : TDI,
  1023. RECONFIGURE,
  1024. &LowerString,
  1025. &UpperString,
  1026. &BindList,
  1027. pvData,
  1028. dwSizeOfData);
  1029. if (!fOk)
  1030. {
  1031. hr = HrFromLastWin32Error ();
  1032. }
  1033. }
  1034. TraceHr (ttidError, FAL, hr, FALSE, "CImplINetCfg::SendPnpReconfig");
  1035. return hr;
  1036. }
  1037. //+---------------------------------------------------------------------------
  1038. // CImplINetCfgHolder -
  1039. //
  1040. VOID
  1041. CImplINetCfgHolder::HoldINetCfg (
  1042. CImplINetCfg* pINetCfg)
  1043. {
  1044. Assert(pINetCfg);
  1045. AddRefObj (pINetCfg->GetUnknown());
  1046. m_pINetCfg = pINetCfg;
  1047. }
  1048. HRESULT
  1049. CImplINetCfgHolder::HrLockAndTestForValidInterface (
  1050. DWORD dwFlags)
  1051. {
  1052. HRESULT hr;
  1053. Lock();
  1054. hr = m_pINetCfg->HrIsValidInterface (dwFlags);
  1055. if (S_OK != hr)
  1056. {
  1057. Unlock();
  1058. }
  1059. TraceHr (ttidError, FAL, hr, FALSE,
  1060. "CImplINetCfgHolder::HrLockAndTestForValidInterface");
  1061. return hr;
  1062. }