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.

1406 lines
37 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1999.
  5. //
  6. // File: N O T I F Y . C P P
  7. //
  8. // Contents: Implements the interface to a component's optional notify
  9. // object. The object defined here is meant to be a member
  10. // of CComponent. This object encapsulates all of its internal
  11. // data in a separate allocation made only if the component
  12. // actually has a notify object.
  13. //
  14. // Notes:
  15. //
  16. // Author: shaunco 15 Jan 1999
  17. //
  18. //----------------------------------------------------------------------------
  19. #include <pch.h>
  20. #pragma hdrstop
  21. #include "diagctx.h"
  22. #include "ibind.h"
  23. #include "inetcfg.h"
  24. #include "nceh.h"
  25. #include "ncmisc.h"
  26. #include "ncprsht.h"
  27. #include "netcfg.h"
  28. #include "notify.h"
  29. //+---------------------------------------------------------------------------
  30. // CNotifyObjectInterface -
  31. //
  32. HRESULT
  33. CNotifyObjectInterface::HrEnsureNotifyObjectInitialized (
  34. IN CImplINetCfg* pINetCfg,
  35. IN BOOL fInstalling)
  36. {
  37. Assert (pINetCfg);
  38. // If we've already been through initialization, return immediately.
  39. //
  40. if (m_fInitialized)
  41. {
  42. return S_OK;
  43. }
  44. // Only perform initialization once, regardless of whether it succeeds
  45. // or not.
  46. //
  47. m_fInitialized = TRUE;
  48. // Get our containing component pointer so we can ask it what the
  49. // CLSID for the notify object is. (If it has one.)
  50. //
  51. CComponent* pThis;
  52. pThis = CONTAINING_RECORD (this, CComponent, Notify);
  53. // Don't bother if we can't have a notify object. Bailing here saves
  54. // uneccesarily loading the external data for netclass components only
  55. // to find that they won't have a notify object below.
  56. //
  57. if (FIsEnumerated (pThis->Class()))
  58. {
  59. return S_OK;
  60. }
  61. HRESULT hrRet;
  62. // Since the notify object clsid is part of the components external data,
  63. // we have to make sure we've loaded this data.
  64. //
  65. hrRet = pThis->Ext.HrEnsureExternalDataLoaded ();
  66. if (S_OK != hrRet)
  67. {
  68. goto finished;
  69. }
  70. // Don't bother if we don't have a notify object.
  71. //
  72. if (!pThis->Ext.FHasNotifyObject())
  73. {
  74. return S_OK;
  75. }
  76. // The component claims to have a notify object. Let's CoCreate it
  77. // and see what we get.
  78. //
  79. HRESULT hr;
  80. INetCfgComponentControl* pCc;
  81. hr = pINetCfg->HrCoCreateWrapper (
  82. *(pThis->Ext.PNotifyObjectClsid()),
  83. NULL, CLSCTX_INPROC_SERVER | CLSCTX_NO_CODE_DOWNLOAD,
  84. IID_INetCfgComponentControl,
  85. (PVOID*)&pCc);
  86. if (S_OK == hr)
  87. {
  88. // So far so good. The notify object implements the required
  89. // INetCfgComponentControl interface.
  90. //
  91. // We now must get the INetCfgComponent interface that we'll
  92. // pass to the notify object during Initialize below.
  93. //
  94. INetCfgComponent* pIComp;
  95. hrRet = pThis->HrGetINetCfgComponentInterface (pINetCfg, &pIComp);
  96. if (S_OK == hrRet)
  97. {
  98. // Allocate space for the various notify interfaces and QI for
  99. // them.
  100. //
  101. hrRet = E_OUTOFMEMORY;
  102. m_pNod = (NOTIFY_OBJECT_DATA*) MemAlloc (sizeof(NOTIFY_OBJECT_DATA));
  103. if (m_pNod)
  104. {
  105. hrRet = S_OK;
  106. ZeroMemory (m_pNod, sizeof(NOTIFY_OBJECT_DATA));
  107. AddRefObj (pCc);
  108. m_pNod->pCc = pCc;
  109. pCc->QueryInterface (IID_INetCfgComponentNotifyBinding,
  110. (PVOID*)&m_pNod->pNb);
  111. pCc->QueryInterface (IID_INetCfgComponentPropertyUi,
  112. (PVOID*)&m_pNod->pCp);
  113. pCc->QueryInterface (IID_INetCfgComponentSetup,
  114. (PVOID*)&m_pNod->pCs);
  115. pCc->QueryInterface (IID_INetCfgComponentUpperEdge,
  116. (PVOID*)&m_pNod->pUe);
  117. pCc->QueryInterface (IID_INetCfgComponentNotifyGlobal,
  118. (PVOID*)&m_pNod->pNg);
  119. if (m_pNod->pNg)
  120. {
  121. // Since it supports INetCfgComponentNotifyGlobal,
  122. // get the mask that indicates which global notifications
  123. // it is interested in.
  124. //
  125. hr = m_pNod->pNg->GetSupportedNotifications(
  126. &m_pNod->dwNotifyGlobalFlags);
  127. if (FAILED(hr))
  128. {
  129. m_pNod->dwNotifyGlobalFlags = 0;
  130. }
  131. }
  132. // We now need to initialize the notify object and indicate
  133. // if we are installing its component or not.
  134. //
  135. pINetCfg->RaiseRpl (RPL_DISALLOW);
  136. NC_TRY
  137. {
  138. Assert (pIComp);
  139. Assert (pINetCfg);
  140. (VOID) pCc->Initialize (pIComp, pINetCfg, fInstalling);
  141. }
  142. NC_CATCH_ALL
  143. {
  144. ; // ignored
  145. }
  146. pINetCfg->LowerRpl (RPL_DISALLOW);
  147. }
  148. ReleaseObj (pIComp);
  149. }
  150. ReleaseObj (pCc);
  151. }
  152. finished:
  153. TraceHr (ttidError, FAL, hrRet, FALSE,
  154. "CNotifyObjectInterface::HrEnsureNotifyObjectInitialized");
  155. return hrRet;
  156. }
  157. VOID
  158. CNotifyObjectInterface::ApplyPnpChanges (
  159. IN CImplINetCfg* pINetCfg,
  160. OUT BOOL* pfNeedReboot) const
  161. {
  162. HRESULT hr;
  163. Assert (pINetCfg);
  164. Assert (pfNeedReboot);
  165. Assert (m_fInitialized);
  166. *pfNeedReboot = FALSE;
  167. if (!m_pNod)
  168. {
  169. return;
  170. }
  171. Assert (m_pNod->pCc);
  172. CComponent* pThis;
  173. pThis = CONTAINING_RECORD (this, CComponent, Notify);
  174. pINetCfg->RaiseRpl (RPL_DISALLOW);
  175. NC_TRY
  176. {
  177. g_pDiagCtx->Printf (ttidBeDiag,
  178. " calling %S->ApplyPnpChanges\n",
  179. pThis->m_pszInfId);
  180. hr = m_pNod->pCc->ApplyPnpChanges (pINetCfg);
  181. if (FAILED(hr) || (NETCFG_S_REBOOT == hr))
  182. {
  183. *pfNeedReboot = TRUE;
  184. }
  185. }
  186. NC_CATCH_ALL
  187. {
  188. *pfNeedReboot = TRUE;
  189. }
  190. pINetCfg->LowerRpl (RPL_DISALLOW);
  191. }
  192. VOID
  193. CNotifyObjectInterface::ApplyRegistryChanges (
  194. IN CImplINetCfg* pINetCfg,
  195. OUT BOOL* pfNeedReboot) const
  196. {
  197. HRESULT hr;
  198. Assert (pINetCfg);
  199. Assert (pfNeedReboot);
  200. Assert (m_fInitialized);
  201. *pfNeedReboot = FALSE;
  202. if (!m_pNod)
  203. {
  204. return;
  205. }
  206. Assert (m_pNod->pCc);
  207. pINetCfg->RaiseRpl (RPL_DISALLOW);
  208. NC_TRY
  209. {
  210. hr = m_pNod->pCc->ApplyRegistryChanges ();
  211. if (FAILED(hr) || (NETCFG_S_REBOOT == hr))
  212. {
  213. *pfNeedReboot = TRUE;
  214. }
  215. }
  216. NC_CATCH_ALL
  217. {
  218. *pfNeedReboot = TRUE;
  219. }
  220. pINetCfg->LowerRpl (RPL_DISALLOW);
  221. }
  222. HRESULT
  223. CNotifyObjectInterface::HrGetInterfaceIdsForAdapter (
  224. IN CImplINetCfg* pINetCfg,
  225. IN const CComponent* pAdapter,
  226. OUT DWORD* pcInterfaces,
  227. OUT GUID** ppguidInterfaceIds) const
  228. {
  229. HRESULT hr;
  230. Assert (pAdapter);
  231. Assert (pcInterfaces);
  232. Assert (m_fInitialized);
  233. *pcInterfaces = 0;
  234. if (ppguidInterfaceIds)
  235. {
  236. *ppguidInterfaceIds = NULL;
  237. }
  238. if (!m_pNod || !m_pNod->pUe)
  239. {
  240. return S_FALSE;
  241. }
  242. Assert (pAdapter->GetINetCfgComponentInterface());
  243. pINetCfg->RaiseRpl (RPL_DISALLOW);
  244. NC_TRY
  245. {
  246. hr = m_pNod->pUe->GetInterfaceIdsForAdapter (
  247. pAdapter->GetINetCfgComponentInterface(),
  248. pcInterfaces, ppguidInterfaceIds);
  249. if (S_FALSE == hr)
  250. {
  251. *pcInterfaces = 0;
  252. if (ppguidInterfaceIds)
  253. {
  254. *ppguidInterfaceIds = NULL;
  255. }
  256. }
  257. }
  258. NC_CATCH_ALL
  259. {
  260. ; // ignored
  261. }
  262. pINetCfg->LowerRpl (RPL_DISALLOW);
  263. TraceHr (ttidError, FAL, hr, (S_FALSE == hr),
  264. "CNotifyObjectInterface::HrGetInterfaceIdsForAdapter");
  265. return hr;
  266. }
  267. HRESULT
  268. CNotifyObjectInterface::HrQueryPropertyUi (
  269. IN CImplINetCfg* pINetCfg,
  270. IN IUnknown* punkContext OPTIONAL)
  271. {
  272. HRESULT hr;
  273. CComponent* pThis;
  274. Assert (this);
  275. Assert (pINetCfg);
  276. Assert (m_fInitialized);
  277. if (!m_pNod || !m_pNod->pCp)
  278. {
  279. return S_FALSE;
  280. }
  281. pThis = CONTAINING_RECORD (this, CComponent, Notify);
  282. Assert (pThis);
  283. if (!(pThis->m_dwCharacter & NCF_HAS_UI))
  284. {
  285. return S_FALSE;
  286. }
  287. hr = S_OK;
  288. pINetCfg->RaiseRpl (RPL_DISALLOW);
  289. NC_TRY
  290. {
  291. Assert (m_pNod && m_pNod->pCp);
  292. hr = m_pNod->pCp->QueryPropertyUi (punkContext);
  293. }
  294. NC_CATCH_ALL
  295. {
  296. hr = E_UNEXPECTED;
  297. }
  298. pINetCfg->LowerRpl (RPL_DISALLOW);
  299. TraceHr (ttidError, FAL, hr, FALSE,
  300. "CNotifyObjectInterface::HrQueryPropertyUi");
  301. return hr;
  302. }
  303. HRESULT
  304. CNotifyObjectInterface::HrShowPropertyUi (
  305. IN CImplINetCfg* pINetCfg,
  306. IN HWND hwndParent,
  307. IN IUnknown* punkContext OPTIONAL)
  308. {
  309. HRESULT hr;
  310. DWORD cDefPages;
  311. UINT cPages;
  312. HPROPSHEETPAGE* ahpsp;
  313. PCWSTR pszStartPage;
  314. Assert (this);
  315. Assert (pINetCfg);
  316. Assert (m_fInitialized);
  317. if (!m_pNod || !m_pNod->pCp)
  318. {
  319. return E_NOINTERFACE;
  320. }
  321. Assert (m_pNod && m_pNod->pCp);
  322. // If given a context, let the notify object know what it is.
  323. //
  324. if (punkContext)
  325. {
  326. SetUiContext (pINetCfg, punkContext);
  327. }
  328. hr = S_OK;
  329. cDefPages = 0;
  330. ahpsp = NULL;
  331. cPages = 0;
  332. pszStartPage = NULL;
  333. pINetCfg->RaiseRpl (RPL_DISALLOW);
  334. NC_TRY
  335. {
  336. hr = m_pNod->pCp->MergePropPages (
  337. &cDefPages,
  338. (BYTE**)&ahpsp,
  339. &cPages,
  340. hwndParent,
  341. &pszStartPage);
  342. }
  343. NC_CATCH_ALL
  344. {
  345. hr = E_UNEXPECTED;
  346. }
  347. pINetCfg->LowerRpl (RPL_DISALLOW);
  348. if ((S_OK == hr) && cPages)
  349. {
  350. PROPSHEETHEADER psh;
  351. CAPAGES caPages;
  352. CAINCP cai;
  353. CComponent* pThis;
  354. pThis = CONTAINING_RECORD (this, CComponent, Notify);
  355. Assert (pThis);
  356. ZeroMemory(&psh, sizeof(psh));
  357. ZeroMemory(&caPages, sizeof(caPages));
  358. ZeroMemory(&cai, sizeof(cai));
  359. psh.dwSize = sizeof(psh);
  360. psh.dwFlags = PSH_PROPTITLE | PSH_NOAPPLYNOW;
  361. psh.hwndParent = hwndParent;
  362. psh.hInstance = _Module.GetModuleInstance();
  363. psh.pszCaption = pThis->Ext.PszDescription();
  364. caPages.nCount = cPages;
  365. caPages.ahpsp = ahpsp;
  366. cai.nCount = 1;
  367. cai.apncp = &m_pNod->pCp;
  368. hr = HrNetCfgPropertySheet (&psh, caPages, pszStartPage, cai);
  369. // S_FALSE is returned if no changes were made.
  370. //
  371. if (S_OK == hr)
  372. {
  373. if (pINetCfg->m_WriteLock.FIsOwnedByMe ())
  374. {
  375. pINetCfg->m_pNetConfig->ModifyCtx.HrBeginBatchOperation ();
  376. }
  377. BOOL bCommitNow = FALSE;
  378. // Call ApplyProperties
  379. //
  380. pINetCfg->RaiseRpl (RPL_ALLOW_INSTALL_REMOVE);
  381. NC_TRY
  382. {
  383. hr = m_pNod->pCp->ApplyProperties ();
  384. if(NETCFG_S_COMMIT_NOW == hr)
  385. {
  386. bCommitNow = TRUE;
  387. }
  388. }
  389. NC_CATCH_ALL
  390. {
  391. hr = E_UNEXPECTED;
  392. }
  393. pINetCfg->LowerRpl (RPL_ALLOW_INSTALL_REMOVE);
  394. if (pINetCfg->m_WriteLock.FIsOwnedByMe ())
  395. {
  396. // Set this component as dirty so we call its Apply method
  397. // if INetCfg is applied.
  398. //
  399. hr = pINetCfg->m_pNetConfig->ModifyCtx.HrDirtyComponent(
  400. pThis);
  401. // Notify other components that this component changed.
  402. //
  403. pINetCfg->m_pNetConfig->Notify.NgSysNotifyComponent (
  404. NCN_PROPERTYCHANGE,
  405. pThis);
  406. hr = pINetCfg->m_pNetConfig->ModifyCtx.
  407. HrEndBatchOperation (bCommitNow ? EBO_COMMIT_NOW : EBO_DEFER_COMMIT_UNTIL_APPLY);
  408. }
  409. }
  410. else
  411. {
  412. // Don't overwrite hr. It is what we need to return.
  413. //
  414. // Call CancelProperties
  415. //
  416. pINetCfg->RaiseRpl (RPL_DISALLOW);
  417. NC_TRY
  418. {
  419. (VOID) m_pNod->pCp->CancelProperties ();
  420. }
  421. NC_CATCH_ALL
  422. {
  423. hr = E_UNEXPECTED;
  424. }
  425. pINetCfg->LowerRpl (RPL_DISALLOW);
  426. }
  427. }
  428. // This is outside the above if in case a notify object actually
  429. // allocates it but returns zero pages.
  430. //
  431. CoTaskMemFree (ahpsp);
  432. // If given a context, let the notify object know it is no longer valid.
  433. //
  434. if (punkContext)
  435. {
  436. SetUiContext (pINetCfg, NULL);
  437. }
  438. TraceHr (ttidError, FAL, hr,
  439. (HRESULT_FROM_WIN32(ERROR_CANCELLED) == hr),
  440. "CNotifyObjectInterface::HrShowPropertyUi");
  441. return hr;
  442. }
  443. VOID
  444. CNotifyObjectInterface::SetUiContext (
  445. IN CImplINetCfg* pINetCfg,
  446. IN IUnknown* punkContext)
  447. {
  448. Assert (m_fInitialized);
  449. Assert (m_pNod && m_pNod->pCp);
  450. pINetCfg->RaiseRpl (RPL_DISALLOW);
  451. NC_TRY
  452. {
  453. (VOID) m_pNod->pCp->SetContext (punkContext);
  454. }
  455. NC_CATCH_ALL
  456. {
  457. ; // ignored
  458. }
  459. pINetCfg->LowerRpl (RPL_DISALLOW);
  460. }
  461. VOID
  462. CNotifyObjectInterface::NbQueryOrNotifyBindingPath (
  463. IN CImplINetCfg* pINetCfg,
  464. IN QN_FLAG Flag,
  465. IN DWORD dwChangeFlag,
  466. IN INetCfgBindingPath* pIPath,
  467. OUT BOOL* pfDisabled)
  468. {
  469. RPL_FLAGS RplFlag;
  470. Assert (pINetCfg);
  471. Assert ((QN_QUERY == Flag) || (QN_NOTIFY == Flag));
  472. Assert (pIPath);
  473. Assert (FImplies(QN_QUERY == Flag, pfDisabled));
  474. Assert (m_fInitialized);
  475. if (pfDisabled)
  476. {
  477. *pfDisabled = FALSE;
  478. }
  479. if (m_pNod && m_pNod->pNb)
  480. {
  481. RplFlag = (QN_NOTIFY == Flag) ? RPL_ALLOW_INSTALL_REMOVE
  482. : RPL_DISALLOW;
  483. pINetCfg->RaiseRpl (RplFlag);
  484. NC_TRY
  485. {
  486. if (QN_QUERY == Flag)
  487. {
  488. HRESULT hr;
  489. hr = m_pNod->pNb->QueryBindingPath (dwChangeFlag, pIPath);
  490. if (NETCFG_S_DISABLE_QUERY == hr)
  491. {
  492. *pfDisabled = TRUE;
  493. }
  494. }
  495. else
  496. {
  497. (VOID) m_pNod->pNb->NotifyBindingPath (dwChangeFlag, pIPath);
  498. }
  499. }
  500. NC_CATCH_ALL
  501. {
  502. ; // ignored
  503. }
  504. pINetCfg->LowerRpl (RplFlag);
  505. }
  506. }
  507. HRESULT
  508. CNotifyObjectInterface::QueryNotifyObject (
  509. IN CImplINetCfg* pINetCfg,
  510. IN REFIID riid,
  511. OUT VOID** ppvObject)
  512. {
  513. HRESULT hr;
  514. *ppvObject = NULL;
  515. hr = HrEnsureNotifyObjectInitialized (pINetCfg, FALSE);
  516. if (S_OK == hr)
  517. {
  518. if (m_pNod && m_pNod->pCc)
  519. {
  520. hr = m_pNod->pCc->QueryInterface (riid, ppvObject);
  521. }
  522. else
  523. {
  524. hr = E_NOINTERFACE;
  525. }
  526. }
  527. TraceHr (ttidError, FAL, hr, FALSE,
  528. "CNotifyObjectInterface::QueryNotifyObject");
  529. return hr;
  530. }
  531. VOID
  532. CNotifyObjectInterface::ReleaseNotifyObject (
  533. IN CImplINetCfg* pINetCfg,
  534. IN BOOL fCancel)
  535. {
  536. Assert (FIff(pINetCfg, fCancel));
  537. if (m_pNod)
  538. {
  539. // Tell the notify object to cancel if requested.
  540. //
  541. if (fCancel)
  542. {
  543. pINetCfg->RaiseRpl (RPL_DISALLOW);
  544. NC_TRY
  545. {
  546. (VOID) m_pNod->pCc->CancelChanges ();
  547. }
  548. NC_CATCH_ALL
  549. {
  550. ; // ignored
  551. }
  552. pINetCfg->LowerRpl (RPL_DISALLOW);
  553. }
  554. // Release all of the interfaces we are holding.
  555. //
  556. ReleaseObj (m_pNod->pCc);
  557. ReleaseObj (m_pNod->pNb);
  558. ReleaseObj (m_pNod->pCp);
  559. ReleaseObj (m_pNod->pCs);
  560. ReleaseObj (m_pNod->pUe);
  561. ReleaseObj (m_pNod->pNg);
  562. MemFree (m_pNod);
  563. m_pNod = NULL;
  564. }
  565. m_fInitialized = FALSE;
  566. }
  567. HRESULT
  568. CNotifyObjectInterface::NewlyAdded (
  569. IN CImplINetCfg* pINetCfg,
  570. IN const NETWORK_INSTALL_PARAMS* pnip)
  571. {
  572. HRESULT hr;
  573. //$REVIEW: Calling HrEnsureNotifyObjectInitialized is probably not needed
  574. // because when we have the write lock and call notify objects, we always
  575. // ensure they are loaded before we get here.
  576. //
  577. hr = HrEnsureNotifyObjectInitialized (pINetCfg, TRUE);
  578. if ((S_OK == hr) && m_pNod && m_pNod->pCs)
  579. {
  580. // Inform the notify object that its component is being installed
  581. // and tell it to read the answerfile if we are using one.
  582. //
  583. DWORD dwSetupFlags;
  584. if (pnip)
  585. {
  586. dwSetupFlags = pnip->dwSetupFlags;
  587. }
  588. else
  589. {
  590. dwSetupFlags = FInSystemSetup() ? NSF_PRIMARYINSTALL
  591. : NSF_POSTSYSINSTALL;
  592. }
  593. // Raise the reentrancy protection level to only allow
  594. // install or remove before calling the notify object's Install
  595. // method.
  596. //
  597. pINetCfg->RaiseRpl (RPL_ALLOW_INSTALL_REMOVE);
  598. NC_TRY
  599. {
  600. hr = m_pNod->pCs->Install (dwSetupFlags);
  601. if (SUCCEEDED(hr) && pnip &&
  602. pnip->pszAnswerFile &&
  603. pnip->pszAnswerSection)
  604. {
  605. // Raise the reentrancy protection level to disallow
  606. // all reentrancy before calling the notify object's
  607. // ReadAnswerFile method.
  608. //
  609. pINetCfg->RaiseRpl (RPL_DISALLOW);
  610. NC_TRY
  611. {
  612. hr = m_pNod->pCs->ReadAnswerFile (
  613. pnip->pszAnswerFile,
  614. pnip->pszAnswerSection);
  615. }
  616. NC_FINALLY
  617. {
  618. pINetCfg->LowerRpl (RPL_DISALLOW);
  619. }
  620. }
  621. }
  622. NC_CATCH_ALL
  623. {
  624. ;
  625. }
  626. pINetCfg->LowerRpl (RPL_ALLOW_INSTALL_REMOVE);
  627. hr = S_OK;
  628. }
  629. TraceHr (ttidError, FAL, hr, FALSE,
  630. "CNotifyObjectInterface::NewlyAdded");
  631. return hr;
  632. }
  633. VOID
  634. CNotifyObjectInterface::Removed (
  635. IN CImplINetCfg* pINetCfg)
  636. {
  637. Assert (m_fInitialized);
  638. if (!m_pNod || !m_pNod->pCs)
  639. {
  640. return;
  641. }
  642. // Raise the reentrancy protection level to only allow
  643. // install or remove before calling the notify object's Install
  644. // method.
  645. //
  646. pINetCfg->RaiseRpl (RPL_ALLOW_INSTALL_REMOVE);
  647. NC_TRY
  648. {
  649. // Inform the notify object that its component is being removed.
  650. //
  651. (VOID) m_pNod->pCs->Removing ();
  652. }
  653. NC_CATCH_ALL
  654. {
  655. ;
  656. }
  657. pINetCfg->LowerRpl (RPL_ALLOW_INSTALL_REMOVE);
  658. }
  659. VOID
  660. CNotifyObjectInterface::Updated (
  661. IN CImplINetCfg* pINetCfg,
  662. IN DWORD dwSetupFlags,
  663. IN DWORD dwUpgradeFromBuildNo)
  664. {
  665. Assert (m_fInitialized);
  666. if (!m_pNod || !m_pNod->pCs)
  667. {
  668. return;
  669. }
  670. // Raise the reentrancy protection level to only allow
  671. // install or remove before calling the notify object's Install
  672. // method.
  673. //
  674. pINetCfg->RaiseRpl (RPL_ALLOW_INSTALL_REMOVE);
  675. NC_TRY
  676. {
  677. HRESULT hrNotify;
  678. // Inform the notify object that its component is being updated.
  679. //
  680. hrNotify = m_pNod->pCs->Upgrade (dwSetupFlags,
  681. dwUpgradeFromBuildNo);
  682. // If Upgrade returns S_OK, it means they recognized and
  683. // handled the event and are now dirty because of it.
  684. //
  685. if (S_OK == hrNotify)
  686. {
  687. CComponent* pThis;
  688. pThis = CONTAINING_RECORD (this, CComponent, Notify);
  689. Assert (pThis);
  690. (VOID) pINetCfg->m_pNetConfig->ModifyCtx.
  691. HrDirtyComponent (pThis);
  692. }
  693. }
  694. NC_CATCH_ALL
  695. {
  696. ;
  697. }
  698. pINetCfg->LowerRpl (RPL_ALLOW_INSTALL_REMOVE);
  699. }
  700. //+---------------------------------------------------------------------------
  701. // CGlobalNotifyInterface -
  702. //
  703. VOID
  704. CGlobalNotifyInterface::HoldINetCfg (
  705. CImplINetCfg* pINetCfg)
  706. {
  707. AssertH (pINetCfg);
  708. AssertH (!m_pINetCfg);
  709. AddRefObj (pINetCfg->GetUnknown());
  710. m_pINetCfg = pINetCfg;
  711. }
  712. VOID
  713. CGlobalNotifyInterface::ReleaseAllNotifyObjects (
  714. IN CComponentList& Components,
  715. IN BOOL fCancel)
  716. {
  717. CComponentList::iterator iter;
  718. CComponent* pComponent;
  719. CImplINetCfg* pINetCfg;
  720. // We need to pass a non-NULL pINetCfg if we are not cancelling.
  721. //
  722. pINetCfg = (fCancel) ? m_pINetCfg : NULL;
  723. for (iter = Components.begin();
  724. iter != Components.end();
  725. iter++)
  726. {
  727. pComponent = *iter;
  728. Assert (pComponent);
  729. pComponent->Notify.ReleaseNotifyObject (pINetCfg, fCancel);
  730. }
  731. m_fInitialized = FALSE;
  732. }
  733. VOID
  734. CGlobalNotifyInterface::ReleaseINetCfg ()
  735. {
  736. // If we have a cached INetCfg interface, we need to tell it
  737. // that we no longer exist. Then we need to release the interface,
  738. // of course.
  739. //
  740. if (m_pINetCfg)
  741. {
  742. // Get our containing CNetConfig pointer.
  743. //
  744. CNetConfig* pThis;
  745. pThis = CONTAINING_RECORD(this, CNetConfig, Notify);
  746. Assert (pThis == m_pINetCfg->m_pNetConfig);
  747. m_pINetCfg->m_pNetConfig = NULL;
  748. ReleaseObj (m_pINetCfg->GetUnknown());
  749. m_pINetCfg = NULL;
  750. }
  751. }
  752. HRESULT
  753. CGlobalNotifyInterface::HrEnsureNotifyObjectsInitialized ()
  754. {
  755. // If we've already been through initialization, return immediately.
  756. //
  757. if (m_fInitialized)
  758. {
  759. return S_OK;
  760. }
  761. // Only perform initialization once, regardless of whether it succeeds
  762. // or not.
  763. //
  764. m_fInitialized = TRUE;
  765. // Get our containing CNetConfig pointer so we can enumerate all components.
  766. //
  767. CNetConfig* pThis;
  768. pThis = CONTAINING_RECORD(this, CNetConfig, Notify);
  769. HRESULT hr = S_OK;
  770. // If we don't have an INetCfg interface pointer yet, it means we are
  771. // creating one instead of it creating CNetConfig. If we had one, it
  772. // would have been handed to us via HoldINetCfg which is called when
  773. // CNetConfig is created by CImplINetCfg.
  774. //
  775. if (!m_pINetCfg)
  776. {
  777. hr = CImplINetCfg::HrCreateInstance (pThis, &m_pINetCfg);
  778. Assert (!m_pINetCfg->m_fOwnNetConfig);
  779. }
  780. if (S_OK == hr)
  781. {
  782. Assert (m_pINetCfg);
  783. CComponentList::iterator iter;
  784. CComponent* pComponent;
  785. for (iter = pThis->Core.Components.begin();
  786. iter != pThis->Core.Components.end();
  787. iter++)
  788. {
  789. pComponent = *iter;
  790. Assert (pComponent);
  791. hr = pComponent->Notify.HrEnsureNotifyObjectInitialized (m_pINetCfg, FALSE);
  792. if (S_OK != hr)
  793. {
  794. break;
  795. }
  796. }
  797. }
  798. TraceHr (ttidError, FAL, hr, FALSE,
  799. "CGlobalNotifyInterface::HrEnsureNotifyObjectsInitialized");
  800. return hr;
  801. }
  802. VOID
  803. CGlobalNotifyInterface::NgSysQueryOrNotifyBindingPath (
  804. IN QN_FLAG Flag,
  805. IN DWORD dwChangeFlag,
  806. IN INetCfgBindingPath* pIPath,
  807. IN BOOL* pfDisabled)
  808. {
  809. RPL_FLAGS RplFlag;
  810. CNetConfig* pThis;
  811. CComponentList::iterator iter;
  812. CComponent* pComponent;
  813. Assert (m_pINetCfg);
  814. Assert ((QN_QUERY == Flag) || (QN_NOTIFY == Flag));
  815. Assert (pIPath);
  816. Assert (FImplies(QN_QUERY == Flag, pfDisabled));
  817. Assert (m_fInitialized);
  818. if (pfDisabled)
  819. {
  820. *pfDisabled = FALSE;
  821. }
  822. // Get our containing CNetConfig pointer so we can enumerate
  823. // all components.
  824. //
  825. pThis = CONTAINING_RECORD(this, CNetConfig, Notify);
  826. RplFlag = (QN_NOTIFY == Flag) ? RPL_ALLOW_INSTALL_REMOVE
  827. : RPL_DISALLOW;
  828. m_pINetCfg->RaiseRpl (RplFlag);
  829. for (iter = pThis->Core.Components.begin();
  830. iter != pThis->Core.Components.end();
  831. iter++)
  832. {
  833. pComponent = *iter;
  834. Assert (pComponent);
  835. if (!pComponent->Notify.m_pNod ||
  836. !pComponent->Notify.m_pNod->pNg ||
  837. !(pComponent->Notify.m_pNod->dwNotifyGlobalFlags & NCN_BINDING_PATH))
  838. {
  839. continue;
  840. }
  841. // If the component has not registered for what we are changing,
  842. // (NCN_ADD, NCN_REMOVE, NCN_ENABLE, NCN_DISABLE) then
  843. // skip it.
  844. //
  845. if (!(pComponent->Notify.m_pNod->dwNotifyGlobalFlags & dwChangeFlag))
  846. {
  847. continue;
  848. }
  849. NC_TRY
  850. {
  851. HRESULT hr;
  852. if (QN_QUERY == Flag)
  853. {
  854. hr = pComponent->Notify.m_pNod->pNg->
  855. SysQueryBindingPath (dwChangeFlag, pIPath);
  856. if (NETCFG_S_DISABLE_QUERY == hr)
  857. {
  858. *pfDisabled = TRUE;
  859. break;
  860. }
  861. }
  862. else
  863. {
  864. hr = pComponent->Notify.m_pNod->pNg->
  865. SysNotifyBindingPath (dwChangeFlag, pIPath);
  866. // If SysNotifyBindingPath returns S_OK, it means they
  867. // recognized and handled the event and are now dirty
  868. // because of it. Because some notify objects let
  869. // success codes such as NETCFG_S_REBOOT slip through,
  870. // consider them dirty if they don't return S_FALSE.
  871. //
  872. if (S_FALSE != hr)
  873. {
  874. hr = m_pINetCfg->m_pNetConfig->ModifyCtx.
  875. HrDirtyComponent(pComponent);
  876. }
  877. }
  878. }
  879. NC_CATCH_ALL
  880. {
  881. ;
  882. }
  883. }
  884. m_pINetCfg->LowerRpl (RplFlag);
  885. }
  886. HRESULT
  887. CGlobalNotifyInterface::NgSysNotifyComponent (
  888. IN DWORD dwChangeFlag,
  889. IN CComponent* pComponentOfInterest)
  890. {
  891. HRESULT hr;
  892. INetCfgComponent* pICompOfInterest;
  893. // We should have called HrEnsureNotifyObjectsInitialized by now.
  894. //
  895. Assert (m_fInitialized);
  896. // If the component of interest has not had its data loaded successfully,
  897. // we shouldn't bother sending the notification. The notify objects are
  898. // just going to call back on the interface to the component and fail
  899. // if they call a method that requires this data.
  900. //
  901. if (!pComponentOfInterest->Ext.FLoadedOkayIfLoadedAtAll())
  902. {
  903. return S_OK;
  904. }
  905. hr = pComponentOfInterest->HrGetINetCfgComponentInterface (
  906. m_pINetCfg, &pICompOfInterest);
  907. if (S_OK == hr)
  908. {
  909. DWORD dwMask = 0;
  910. NETCLASS Class = pComponentOfInterest->Class();
  911. CNetConfig* pThis;
  912. CComponentList::iterator iter;
  913. CComponent* pComponent;
  914. if (FIsConsideredNetClass(Class))
  915. {
  916. dwMask = NCN_NET;
  917. }
  918. else if (NC_NETTRANS == Class)
  919. {
  920. dwMask = NCN_NETTRANS;
  921. }
  922. else if (NC_NETCLIENT == Class)
  923. {
  924. dwMask = NCN_NETCLIENT;
  925. }
  926. else if (NC_NETSERVICE == Class)
  927. {
  928. dwMask = NCN_NETSERVICE;
  929. }
  930. // Get our containing CNetConfig pointer so we can enumerate
  931. // all components.
  932. //
  933. pThis = CONTAINING_RECORD(this, CNetConfig, Notify);
  934. // Raise the reentrancy protection level to only allow
  935. // install or remove before calling the notify object's
  936. // SysNotifyComponent method.
  937. //
  938. m_pINetCfg->RaiseRpl (RPL_ALLOW_INSTALL_REMOVE);
  939. for (iter = pThis->Core.Components.begin();
  940. iter != pThis->Core.Components.end();
  941. iter++)
  942. {
  943. pComponent = *iter;
  944. Assert (pComponent);
  945. if (!pComponent->Notify.m_pNod ||
  946. !pComponent->Notify.m_pNod->pNg)
  947. {
  948. continue;
  949. }
  950. // If the component has not registered for one of NCN_NET,
  951. // NCN_NETTRANS, etc. then skip it.
  952. //
  953. if (!(pComponent->Notify.m_pNod->dwNotifyGlobalFlags & dwMask))
  954. {
  955. continue;
  956. }
  957. // If the component has not registered for what we are changing,
  958. // (NCN_ADD, NCN_REMOVE, NCN_UPDATE, NCN_PROPERTYCHANGE) then
  959. // skip it.
  960. //
  961. if (!(pComponent->Notify.m_pNod->dwNotifyGlobalFlags & dwChangeFlag))
  962. {
  963. continue;
  964. }
  965. NC_TRY
  966. {
  967. HRESULT hrNotify;
  968. hrNotify = pComponent->Notify.m_pNod->pNg->SysNotifyComponent (
  969. dwMask | dwChangeFlag,
  970. pICompOfInterest);
  971. // If SysNotifyComponent returns S_OK, it means they
  972. // recognized and handled the event and are now dirty
  973. // because of it. Because some notify objects let
  974. // success codes such as NETCFG_S_REBOOT slip through,
  975. // consider them dirty if they don't return S_FALSE.
  976. //
  977. if (S_FALSE != hrNotify)
  978. {
  979. hr = m_pINetCfg->m_pNetConfig->ModifyCtx.
  980. HrDirtyComponent(pComponent);
  981. }
  982. }
  983. NC_CATCH_ALL
  984. {
  985. ;
  986. }
  987. }
  988. m_pINetCfg->LowerRpl (RPL_ALLOW_INSTALL_REMOVE);
  989. ReleaseObj (pICompOfInterest);
  990. }
  991. TraceHr (ttidError, FAL, hr, FALSE,
  992. "CGlobalNotifyInterface::NgSysNotifyComponent");
  993. return hr;
  994. }
  995. HRESULT
  996. CGlobalNotifyInterface::ComponentAdded (
  997. IN CComponent* pComponent,
  998. IN const NETWORK_INSTALL_PARAMS* pnip)
  999. {
  1000. HRESULT hr;
  1001. Assert (pComponent);
  1002. // Initialize the notify object for the component and call
  1003. // its Install method followed by ReadAnswerFile if we are installing
  1004. // with one.
  1005. //
  1006. hr = pComponent->Notify.NewlyAdded (m_pINetCfg, pnip);
  1007. if (S_OK == hr)
  1008. {
  1009. // Notify all notify objects that are interested in component
  1010. // additions.
  1011. //
  1012. hr = NgSysNotifyComponent(NCN_ADD, pComponent);
  1013. }
  1014. TraceHr (ttidError, FAL, hr, FALSE,
  1015. "CGlobalNotifyInterface::ComponentAdded");
  1016. return hr;
  1017. }
  1018. HRESULT
  1019. CGlobalNotifyInterface::ComponentRemoved (
  1020. IN CComponent* pComponent)
  1021. {
  1022. HRESULT hr;
  1023. Assert (pComponent);
  1024. pComponent->Notify.Removed (m_pINetCfg);
  1025. hr = NgSysNotifyComponent(NCN_REMOVE, pComponent);
  1026. TraceHr (ttidError, FAL, hr, FALSE,
  1027. "CGlobalNotifyInterface::ComponentRemoved");
  1028. return hr;
  1029. }
  1030. HRESULT
  1031. CGlobalNotifyInterface::ComponentUpdated (
  1032. IN CComponent* pComponent,
  1033. IN DWORD dwSetupFlags,
  1034. IN DWORD dwUpgradeFromBuildNo)
  1035. {
  1036. HRESULT hr;
  1037. Assert (pComponent);
  1038. pComponent->Notify.Updated (m_pINetCfg,
  1039. dwSetupFlags, dwUpgradeFromBuildNo);
  1040. hr = NgSysNotifyComponent(NCN_UPDATE, pComponent);
  1041. TraceHr (ttidError, FAL, hr, FALSE,
  1042. "CGlobalNotifyInterface::ComponentUpdated");
  1043. return hr;
  1044. }
  1045. VOID
  1046. CGlobalNotifyInterface::NotifyBindPath (
  1047. IN DWORD dwChangeFlag,
  1048. IN CBindPath* pBindPath,
  1049. IN INetCfgBindingPath* pIPath OPTIONAL)
  1050. {
  1051. HRESULT hr;
  1052. CImplINetCfg* pINetCfg;
  1053. CComponent* pOwner;
  1054. BOOL fReleasePath;
  1055. Assert (m_fInitialized);
  1056. Assert ((dwChangeFlag & NCN_ADD) ||
  1057. (dwChangeFlag & NCN_REMOVE) ||
  1058. (dwChangeFlag & NCN_ENABLE) ||
  1059. (dwChangeFlag & NCN_DISABLE));
  1060. Assert (FImplies(dwChangeFlag & NCN_REMOVE, !(dwChangeFlag & NCN_DISABLE)));
  1061. Assert (FImplies(dwChangeFlag & NCN_ADD, !(dwChangeFlag & NCN_REMOVE)));
  1062. Assert (FImplies(dwChangeFlag & NCN_REMOVE, !(dwChangeFlag & NCN_ADD)));
  1063. Assert (pBindPath);
  1064. hr = S_OK;
  1065. pINetCfg = PINetCfg();
  1066. pOwner = pBindPath->POwner();
  1067. fReleasePath = FALSE;
  1068. // Create an INetCfgBindingPath representation of the path for
  1069. // the notify objects if we were not given one.
  1070. //
  1071. if (!pIPath)
  1072. {
  1073. // If the bindpath contains components that have had a problem
  1074. // loading, we shouldn't bother sending the notification.
  1075. // The notify objects are just going to call back on the interface
  1076. // to the component and fail if they call a method that requires
  1077. // this data.
  1078. //
  1079. if (!pBindPath->FAllComponentsLoadedOkayIfLoadedAtAll())
  1080. {
  1081. return;
  1082. }
  1083. hr = CImplINetCfgBindingPath::HrCreateInstance (
  1084. pINetCfg, pBindPath, &pIPath);
  1085. fReleasePath = TRUE;
  1086. }
  1087. if (S_OK == hr)
  1088. {
  1089. Assert (pIPath);
  1090. // If adding...
  1091. //
  1092. if (dwChangeFlag & NCN_ADD)
  1093. {
  1094. BOOL fDisabled;
  1095. fDisabled = FALSE;
  1096. // First, query the owner of the bindpath to see if he wants
  1097. // it disabled.
  1098. //
  1099. pOwner->Notify.NbQueryOrNotifyBindingPath (
  1100. pINetCfg,
  1101. QN_QUERY,
  1102. dwChangeFlag,
  1103. pIPath,
  1104. &fDisabled);
  1105. // If the owner doesn't want it disabled, see if any global
  1106. // notify objects do.
  1107. //
  1108. if (!fDisabled)
  1109. {
  1110. NgSysQueryOrNotifyBindingPath (
  1111. QN_QUERY,
  1112. dwChangeFlag,
  1113. pIPath,
  1114. &fDisabled);
  1115. }
  1116. // If someone wants it disabled, adjust the change flag
  1117. // for notify and add the bindpath to our disabled list.
  1118. //
  1119. if (fDisabled)
  1120. {
  1121. dwChangeFlag = NCN_ADD | NCN_DISABLE;
  1122. (VOID)pINetCfg->m_pNetConfig->Core.HrDisableBindPath (pBindPath);
  1123. }
  1124. }
  1125. //if (g_pDiagCtx->Flags() & DF_SHOW_CONSOLE_OUTPUT)
  1126. {
  1127. WCHAR pszBindPath [1024];
  1128. ULONG cch;
  1129. cch = celems(pszBindPath) - 1;
  1130. if (pBindPath->FGetPathToken (pszBindPath, &cch))
  1131. {
  1132. g_pDiagCtx->Printf (ttidBeDiag, " %S (%s)\n",
  1133. pszBindPath,
  1134. (dwChangeFlag & NCN_ENABLE)
  1135. ? "enabled"
  1136. : (dwChangeFlag & NCN_DISABLE)
  1137. ? "disabled"
  1138. : "removed");
  1139. }
  1140. }
  1141. pOwner->Notify.NbQueryOrNotifyBindingPath (
  1142. pINetCfg,
  1143. QN_NOTIFY,
  1144. dwChangeFlag,
  1145. pIPath,
  1146. NULL);
  1147. NgSysQueryOrNotifyBindingPath (
  1148. QN_NOTIFY,
  1149. dwChangeFlag,
  1150. pIPath,
  1151. NULL);
  1152. if (fReleasePath)
  1153. {
  1154. ReleaseObj (pIPath);
  1155. }
  1156. }
  1157. }
  1158. HRESULT
  1159. CGlobalNotifyInterface::QueryAndNotifyBindPaths (
  1160. IN DWORD dwBaseChangeFlag,
  1161. IN CBindingSet* pBindSet,
  1162. IN UINT cSkipFirstBindPaths)
  1163. {
  1164. CBindPath* pBindPath;
  1165. DWORD dwChangeFlag;
  1166. PCSTR pszDiagMsg;
  1167. // We should have called HrEnsureNotifyObjectsInitialized by now.
  1168. //
  1169. Assert (m_fInitialized);
  1170. Assert ((dwBaseChangeFlag & NCN_ADD) || (dwBaseChangeFlag & NCN_REMOVE));
  1171. if (dwBaseChangeFlag & NCN_ADD)
  1172. {
  1173. dwChangeFlag = NCN_ADD | NCN_ENABLE;
  1174. pszDiagMsg = "Query and notify the following bindings:\n";
  1175. }
  1176. else
  1177. {
  1178. dwChangeFlag = NCN_REMOVE;
  1179. pszDiagMsg = "Notify the following bindings are removed:\n";
  1180. }
  1181. g_pDiagCtx->Printf (ttidBeDiag, pszDiagMsg);
  1182. // Iterate the newly added bindpaths by picking up where the
  1183. // previous set ended and going to the end of the binding set.
  1184. // Note, because this may recurse, pBindSet may change during
  1185. // iteration, so a simple pointer increment through begin() to end()
  1186. // may fail if the bindset is reallocated or grown.
  1187. // Note too that we save off the current count of bindpaths in
  1188. // iStopAtBindPath. If we did not, when we come out of a recursion where
  1189. // the binding set grew, we'd re-notify the newly added bindpaths
  1190. // if we used a direct comparison of 'i < pBindSet->CountBindPaths()'.
  1191. //
  1192. UINT iStopAtBindPath = pBindSet->CountBindPaths();
  1193. for (UINT i = cSkipFirstBindPaths; i < iStopAtBindPath; i++)
  1194. {
  1195. pBindPath = pBindSet->PGetBindPathAtIndex(i);
  1196. NotifyBindPath (dwChangeFlag, pBindPath, NULL);
  1197. }
  1198. return S_OK;
  1199. }