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.

2141 lines
60 KiB

  1. #include "pch.h"
  2. #pragma hdrstop
  3. #include "adapter.h"
  4. #include "diag.h"
  5. #include "inetcfg.h"
  6. #include "lanamap.h"
  7. #include "ncreg.h"
  8. #include "ncsetup.h"
  9. #include "netcfg.h"
  10. #include "persist.h"
  11. #include "util.h"
  12. #include <conio.h> // _kbhit
  13. //move to classinst.cpp
  14. HRESULT
  15. HrCiDoCompleteSectionInstall(
  16. HINF hinfFile,
  17. HKEY hkeyRelative,
  18. PCWSTR szSection,
  19. HWND hwndParent,
  20. BOOL fEnumerated);
  21. class CNetCfgInternalDiagnostic
  22. {
  23. public:
  24. static VOID
  25. DoCreateReleaseDiagnostic (
  26. IN const DIAG_OPTIONS* pOptions,
  27. BOOL fPrime);
  28. static VOID
  29. DoEnumAllDiagnostic (
  30. IN const DIAG_OPTIONS* pOptions);
  31. static VOID
  32. DoSaveLoadDiagnostic (
  33. IN const DIAG_OPTIONS* pOptions,
  34. IN CNetConfig* pNetConfig);
  35. static VOID
  36. DoWriteLockDiagnostic (
  37. IN const DIAG_OPTIONS* pOptions,
  38. IN CNetConfig* pNetConfig);
  39. static VOID
  40. CmdFullDiagnostic (
  41. IN const DIAG_OPTIONS* pOptions,
  42. IN CNetConfig* pNetConfig);
  43. };
  44. VOID
  45. PromptForLeakCheck (
  46. IN const DIAG_OPTIONS* pOptions,
  47. IN PCSTR psz)
  48. {
  49. if (pOptions->fLeakCheck)
  50. {
  51. g_pDiagCtx->Printf (ttidBeDiag, psz);
  52. while (!_kbhit())
  53. {
  54. Sleep (50);
  55. }
  56. _getch ();
  57. g_pDiagCtx->Printf (ttidBeDiag, "\n");
  58. }
  59. }
  60. HRESULT
  61. HrCreateINetCfg (
  62. IN BOOL fAcquireWriteLock,
  63. OUT CImplINetCfg** ppINetCfg)
  64. {
  65. HRESULT hr;
  66. CImplINetCfg* pINetCfg;
  67. hr = CComCreator<CComObject <CImplINetCfg> >::CreateInstance(
  68. NULL, IID_INetCfg, (VOID**)&pINetCfg);
  69. if (S_OK == hr)
  70. {
  71. if (fAcquireWriteLock)
  72. {
  73. hr = pINetCfg->AcquireWriteLock (100, L"ncdiag", NULL);
  74. if (S_FALSE == hr)
  75. {
  76. g_pDiagCtx->Printf (ttidBeDiag, "The write lock could not be acquired.\n");
  77. }
  78. else if (NETCFG_E_NEED_REBOOT == hr)
  79. {
  80. g_pDiagCtx->Printf (ttidBeDiag, "A reboot is required before any futher "
  81. "changes can be made.\n");
  82. }
  83. }
  84. if (S_OK == hr)
  85. {
  86. hr = pINetCfg->Initialize (NULL);
  87. if (S_OK == hr)
  88. {
  89. *ppINetCfg = pINetCfg;
  90. }
  91. }
  92. if (S_OK != hr)
  93. {
  94. ReleaseObj (pINetCfg->GetUnknown());
  95. }
  96. }
  97. return hr;
  98. }
  99. HRESULT
  100. HrFindBindPath (
  101. IN CImplINetCfg* pINetCfg,
  102. IN PCWSTR pszPathToken,
  103. OUT INetCfgBindingPath** ppIPath,
  104. OUT INetCfgComponentBindings** ppIOwner)
  105. {
  106. HRESULT hr;
  107. const WCHAR szDelim[] = L"->";
  108. WCHAR szBindPath [_MAX_PATH];
  109. PCWSTR pszInfId;
  110. PWSTR pszNext;
  111. INetCfgComponent* pIComp;
  112. *ppIPath = NULL;
  113. if (ppIOwner)
  114. {
  115. *ppIOwner = NULL;
  116. }
  117. wcscpy (szBindPath, pszPathToken);
  118. pszInfId = GetNextStringToken (szBindPath, szDelim, &pszNext);
  119. hr = pINetCfg->FindComponent (pszInfId, &pIComp);
  120. if (S_OK == hr)
  121. {
  122. INetCfgComponentBindings* pIBind;
  123. hr = pIComp->QueryInterface (IID_INetCfgComponentBindings,
  124. (VOID**)&pIBind);
  125. if (S_OK == hr)
  126. {
  127. IEnumNetCfgBindingPath* pIEnumPath;
  128. hr = pIBind->EnumBindingPaths (EBP_BELOW, &pIEnumPath);
  129. if (S_OK == hr)
  130. {
  131. INetCfgBindingPath* rgIPath [256];
  132. ULONG cIPath;
  133. hr = pIEnumPath->Next (celems(rgIPath), rgIPath, &cIPath);
  134. if (SUCCEEDED(hr) && cIPath)
  135. {
  136. for (ULONG iPath = 0;
  137. (iPath < cIPath) && !(*ppIPath);
  138. iPath++)
  139. {
  140. PWSTR pszToken;
  141. hr = rgIPath[iPath]->GetPathToken (&pszToken);
  142. if (S_OK == hr)
  143. {
  144. if (0 == wcscmp (pszPathToken, pszToken))
  145. {
  146. AddRefObj (rgIPath[iPath]);
  147. *ppIPath = rgIPath[iPath];
  148. if (ppIOwner)
  149. {
  150. INetCfgComponent* pICompOwner;
  151. hr = rgIPath[0]->GetOwner(&pICompOwner);
  152. Assert (S_OK == hr);
  153. pICompOwner->QueryInterface (
  154. IID_INetCfgComponentBindings,
  155. (VOID**)ppIOwner);
  156. ReleaseObj (pICompOwner);
  157. }
  158. }
  159. CoTaskMemFree (pszToken);
  160. }
  161. }
  162. ReleaseIUnknownArray(cIPath, (IUnknown**)rgIPath);
  163. hr = S_OK;
  164. }
  165. ReleaseObj (pIEnumPath);
  166. }
  167. ReleaseObj (pIBind);
  168. }
  169. ReleaseObj (pIComp);
  170. }
  171. else if (S_FALSE == hr)
  172. {
  173. hr = S_OK;
  174. }
  175. return hr;
  176. }
  177. // This test ensures proper circular reference behavior between CNetConfig
  178. // and CImplINetCfg.
  179. // The following is performed:
  180. // create a CNetConfig and have it create its INetCfg for the notify objects.
  181. // AddRef its INetCfg
  182. // destroy the CNetConfig
  183. // Try to Uninitialize the INetCfg which should fail because it never
  184. // owned its internal CNetConfig pointer.
  185. // Release the INetCfg and ensure that nothing is leaked.
  186. //
  187. VOID
  188. CNetCfgInternalDiagnostic::DoCreateReleaseDiagnostic (
  189. IN const DIAG_OPTIONS* pOptions,
  190. IN BOOL fPrime)
  191. {
  192. HRESULT hr;
  193. CImplINetCfg* pINetCfg = NULL;
  194. if (!fPrime)
  195. {
  196. PromptForLeakCheck (pOptions,
  197. "Create/Release diagnostic...(dump heap)");
  198. }
  199. // Scoping brackets so that NetConfig will be created and destroyed
  200. // in this scope.
  201. //
  202. {
  203. CNetConfig NetConfig;
  204. hr = HrLoadNetworkConfigurationFromRegistry (KEY_READ, &NetConfig);
  205. if (S_OK == hr)
  206. {
  207. // Shouldn't have internal INetCfg created yet.
  208. //
  209. Assert (!NetConfig.Notify.m_pINetCfg);
  210. hr = NetConfig.Notify.HrEnsureNotifyObjectsInitialized ();
  211. if (S_OK == hr)
  212. {
  213. // Should now have internal INetCfg created.
  214. //
  215. Assert (NetConfig.Notify.m_pINetCfg);
  216. pINetCfg = NetConfig.Notify.m_pINetCfg;
  217. // INetCfg should be pointing back to our CNetConfig object.
  218. //
  219. Assert (&NetConfig == pINetCfg->m_pNetConfig);
  220. // Let's hang on to it and see what happens after we let
  221. // the parent CNetConfig be destroyed.
  222. //
  223. pINetCfg = NetConfig.Notify.m_pINetCfg;
  224. AddRefObj (pINetCfg->GetUnknown());
  225. }
  226. }
  227. }
  228. if ((S_OK == hr) && pINetCfg)
  229. {
  230. // Now that CNetConfig is destroyed, it should not be pointing to
  231. // any CNetConfig object.
  232. //
  233. Assert (!pINetCfg->m_pNetConfig);
  234. hr = pINetCfg->Uninitialize();
  235. Assert (NETCFG_E_NOT_INITIALIZED == hr);
  236. ReleaseObj (pINetCfg->GetUnknown());
  237. }
  238. if (NETCFG_E_NOT_INITIALIZED == hr)
  239. {
  240. g_pDiagCtx->Printf (ttidBeDiag, "Passed Create/Release diagnostic.\n");
  241. }
  242. else
  243. {
  244. g_pDiagCtx->Printf (ttidBeDiag, "FAILED Create/Release diagnostic.\n");
  245. }
  246. if (!fPrime)
  247. {
  248. PromptForLeakCheck (pOptions,
  249. "Create/Release diagnostic...(dump heap and compare)");
  250. }
  251. }
  252. VOID
  253. CNetCfgInternalDiagnostic::DoEnumAllDiagnostic (
  254. IN const DIAG_OPTIONS* pOptions)
  255. {
  256. HRESULT hr;
  257. CImplINetCfg* pINetCfg;
  258. PromptForLeakCheck (pOptions, "Enumerate All diagnostic...(dump heap)");
  259. hr = HrCreateINetCfg (FALSE, &pINetCfg);
  260. if (S_OK == hr)
  261. {
  262. IEnumNetCfgComponent* pIEnum;
  263. hr = pINetCfg->EnumComponents (NULL, &pIEnum);
  264. if (S_OK == hr)
  265. {
  266. INetCfgComponent* rgIComp[128];
  267. ULONG cIComp;
  268. hr = pIEnum->Next (celems(rgIComp), rgIComp, &cIComp);
  269. if (SUCCEEDED(hr) && cIComp)
  270. {
  271. INetCfgComponentBindings* pIBind;
  272. IEnumNetCfgBindingPath* pIEnumPath;
  273. INetCfgBindingPath* rgIPath[256];
  274. PWSTR pszInfId;
  275. ULONG cIPath;
  276. ULONG cIPathTotal = 0;
  277. ULONG cIIntTotal = 0;
  278. for (ULONG iComp = 0; iComp < cIComp; iComp++)
  279. {
  280. hr = rgIComp[iComp]->GetId (&pszInfId);
  281. if (S_OK == hr)
  282. {
  283. hr = (*pszInfId) ? S_OK : E_FAIL;
  284. if (S_OK != hr)
  285. {
  286. break;
  287. }
  288. hr = rgIComp[iComp]->QueryInterface (IID_INetCfgComponentBindings, (VOID**)&pIBind);
  289. if (S_OK == hr)
  290. {
  291. hr = pIBind->EnumBindingPaths (EBP_BELOW, &pIEnumPath);
  292. if (S_OK == hr)
  293. {
  294. hr = pIEnumPath->Next (celems(rgIPath), rgIPath, &cIPath);
  295. if (SUCCEEDED(hr))
  296. {
  297. for (ULONG iPath = 0; iPath < cIPath; iPath++)
  298. {
  299. ULONG ulDepth;
  300. hr = rgIPath[iPath]->GetDepth(&ulDepth);
  301. if (S_OK == hr)
  302. {
  303. IEnumNetCfgBindingInterface* pIEnumInt;
  304. INetCfgBindingInterface* rgIInt[128];
  305. ULONG cIInt;
  306. hr = rgIPath[iPath]->EnumBindingInterfaces (&pIEnumInt);
  307. if (S_OK == hr)
  308. {
  309. hr = pIEnumInt->Next (celems(rgIInt), rgIInt, &cIInt);
  310. if (SUCCEEDED(hr))
  311. {
  312. cIIntTotal += cIInt;
  313. ReleaseIUnknownArray(cIInt, (IUnknown**)rgIInt);
  314. }
  315. else if (S_FALSE == hr)
  316. {
  317. hr = S_OK;
  318. }
  319. ReleaseObj (pIEnumInt);
  320. }
  321. }
  322. }
  323. cIPathTotal += cIPath;
  324. ReleaseIUnknownArray(cIPath, (IUnknown**)rgIPath);
  325. hr = S_OK;
  326. }
  327. ReleaseObj (pIEnumPath);
  328. }
  329. ReleaseObj (pIBind);
  330. }
  331. CoTaskMemFree (pszInfId);
  332. }
  333. if (S_OK != hr)
  334. {
  335. break;
  336. }
  337. }
  338. ReleaseIUnknownArray(cIComp, (IUnknown**)rgIComp);
  339. // Note: Total bindpaths are not total unique bindpaths.
  340. // (A component's bindpaths which end in ms_ipx have
  341. // ms_ipx's lower bindings added. These additional
  342. // bindings are counted for every component which has
  343. // bindpaths that end in ms_ipx.)
  344. //
  345. g_pDiagCtx->Printf (ttidBeDiag, "Passed Enumerate All diagnostic. (%d components, %d (non-unique) bindpaths, %d interfaces)\n", cIComp, cIPathTotal, cIIntTotal);
  346. }
  347. else if (S_FALSE == hr)
  348. {
  349. hr = S_OK;
  350. }
  351. ReleaseObj (pIEnum);
  352. }
  353. HRESULT hrT = pINetCfg->Uninitialize ();
  354. Assert (S_OK == hrT);
  355. ReleaseObj (pINetCfg->GetUnknown());
  356. }
  357. if (S_OK != hr)
  358. {
  359. g_pDiagCtx->Printf (ttidBeDiag, "FAILED Enumerate All diagnostic.\n");
  360. }
  361. PromptForLeakCheck (pOptions, "Enumerate All diagnostic...(dump heap and compare)");
  362. }
  363. VOID
  364. CNetCfgInternalDiagnostic::DoSaveLoadDiagnostic (
  365. IN const DIAG_OPTIONS* pOptions,
  366. IN CNetConfig* pNetConfig)
  367. {
  368. HRESULT hr;
  369. BOOL fClearDisabledBindings = FALSE;
  370. CBindingSet BindingSet;
  371. CComponentList::iterator iter;
  372. CComponent* pComponent;
  373. // Generate a full set of bindings so we test persisting them as
  374. // disabled bindings, but only if we don't already have disabled
  375. // bindings.
  376. //
  377. if (0 == pNetConfig->Core.DisabledBindings.CountBindPaths())
  378. {
  379. fClearDisabledBindings = TRUE;
  380. for (iter = pNetConfig->Core.Components.begin();
  381. iter != pNetConfig->Core.Components.end();
  382. iter++)
  383. {
  384. pComponent = *iter;
  385. Assert (pComponent);
  386. hr = pNetConfig->Core.HrGetComponentBindings (
  387. pComponent,
  388. GBF_ADD_TO_BINDSET,
  389. &pNetConfig->Core.DisabledBindings);
  390. if (S_OK != hr) return;
  391. }
  392. }
  393. PBYTE pbBuf;
  394. ULONG cbBuf;
  395. hr = HrSaveNetworkConfigurationToBufferWithAlloc (
  396. pNetConfig, &pbBuf, &cbBuf);
  397. if (S_OK == hr)
  398. {
  399. CNetConfig NetConfigCopy;
  400. hr = HrLoadNetworkConfigurationFromBuffer (
  401. pbBuf, cbBuf, &NetConfigCopy);
  402. if (S_OK == hr)
  403. {
  404. PBYTE pbBufCopy;
  405. ULONG cbBufCopy;
  406. hr = HrSaveNetworkConfigurationToBufferWithAlloc (
  407. &NetConfigCopy, &pbBufCopy, &cbBufCopy);
  408. if (S_OK == hr)
  409. {
  410. if ((cbBufCopy == cbBuf) && (0 == memcmp(pbBufCopy, pbBuf, cbBuf)))
  411. {
  412. g_pDiagCtx->Printf (ttidBeDiag, "Passed Save/Load diagnostic. (%d bytes)\n", cbBuf);
  413. }
  414. else
  415. {
  416. g_pDiagCtx->Printf (ttidBeDiag, "FAILED compare for Save/Load diagnostic.\n");
  417. }
  418. MemFree (pbBufCopy);
  419. }
  420. }
  421. MemFree (pbBuf);
  422. }
  423. // Leave the disabled bindings as we found them.
  424. //
  425. if (fClearDisabledBindings)
  426. {
  427. pNetConfig->Core.DisabledBindings.Clear();
  428. }
  429. if (S_OK != hr)
  430. {
  431. g_pDiagCtx->Printf (ttidBeDiag, "FAILED Save/Load diagnostic.\n");
  432. }
  433. }
  434. VOID
  435. CNetCfgInternalDiagnostic::DoWriteLockDiagnostic (
  436. IN const DIAG_OPTIONS* pOptions,
  437. IN CNetConfig* pNetConfig)
  438. {
  439. HRESULT hr;
  440. CImplINetCfg* pINetCfg;
  441. BOOL fFailed = FALSE;
  442. PromptForLeakCheck (pOptions, "WriteLock diagnostic...(dump heap)");
  443. hr = CComCreator<CComObject <CImplINetCfg> >::CreateInstance(
  444. NULL, IID_INetCfg, (VOID**)&pINetCfg);
  445. if (S_OK == hr)
  446. {
  447. PWSTR psz;
  448. hr = pINetCfg->IsWriteLocked (&psz);
  449. if (S_FALSE != hr) fFailed = TRUE;
  450. if (psz) fFailed = TRUE;
  451. hr = pINetCfg->AcquireWriteLock (100, L"ncdiag", &psz);
  452. if (S_OK != hr) fFailed = TRUE;
  453. if (psz) fFailed = TRUE;
  454. if (S_OK == hr)
  455. {
  456. hr = pINetCfg->IsWriteLocked (&psz);
  457. if (S_OK != hr) fFailed = TRUE;
  458. if (!psz) fFailed = TRUE;
  459. if (S_OK == hr)
  460. {
  461. if (0 != wcscmp(L"ncdiag", psz))
  462. {
  463. fFailed = TRUE;
  464. }
  465. }
  466. CoTaskMemFree (psz);
  467. hr = pINetCfg->ReleaseWriteLock ();
  468. if (S_OK != hr) fFailed = TRUE;
  469. hr = pINetCfg->IsWriteLocked (&psz);
  470. if (S_FALSE != hr) fFailed = TRUE;
  471. if (psz) fFailed = TRUE;
  472. }
  473. ReleaseObj (pINetCfg->GetUnknown());
  474. }
  475. if (!fFailed)
  476. {
  477. PromptForLeakCheck (pOptions, "WriteLock diagnostic...(dump heap and compare)");
  478. g_pDiagCtx->Printf (ttidBeDiag, "Passed WriteLock diagnostic.\n");
  479. }
  480. else
  481. {
  482. g_pDiagCtx->Printf (ttidBeDiag, "FAILED WriteLock diagnostic.\n");
  483. }
  484. }
  485. VOID
  486. CNetCfgInternalDiagnostic::CmdFullDiagnostic (
  487. IN const DIAG_OPTIONS* pOptions,
  488. IN CNetConfig* pNetConfig)
  489. {
  490. DoCreateReleaseDiagnostic (pOptions, TRUE);
  491. if (pOptions->fLeakCheck)
  492. {
  493. DoCreateReleaseDiagnostic (pOptions, FALSE);
  494. }
  495. DoEnumAllDiagnostic (pOptions);
  496. DoSaveLoadDiagnostic (pOptions, pNetConfig);
  497. DoWriteLockDiagnostic (pOptions, pNetConfig);
  498. }
  499. VOID
  500. CmdAddComponent (
  501. IN const DIAG_OPTIONS* pOptions,
  502. IN CNetConfig* pNetConfig)
  503. {
  504. HRESULT hr;
  505. CImplINetCfg* pINetCfg;
  506. PromptForLeakCheck (pOptions, "Add component...(dump heap)");
  507. hr = HrCreateINetCfg (TRUE, &pINetCfg);
  508. if (S_OK == hr)
  509. {
  510. INetCfgClassSetup* pSetup;
  511. hr = pINetCfg->QueryNetCfgClass (
  512. &pOptions->ClassGuid,
  513. IID_INetCfgClassSetup,
  514. (VOID**)&pSetup);
  515. if (S_OK == hr)
  516. {
  517. OBO_TOKEN OboToken;
  518. INetCfgComponent* pIComp;
  519. ZeroMemory (&OboToken, sizeof(OboToken));
  520. OboToken.Type = OBO_USER;
  521. hr = pSetup->Install (
  522. pOptions->pszInfId,
  523. &OboToken,
  524. 0, 0, NULL, NULL,
  525. &pIComp);
  526. if (SUCCEEDED(hr))
  527. {
  528. ReleaseObj (pIComp);
  529. }
  530. if (NETCFG_S_REBOOT == hr)
  531. {
  532. hr = S_OK;
  533. g_pDiagCtx->Printf (ttidBeDiag, "%S was installed, but a reboot is required.\n",
  534. pOptions->pszInfId);
  535. }
  536. else if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
  537. {
  538. hr = S_OK;
  539. g_pDiagCtx->Printf (ttidBeDiag, "The INF file for %S could not be found.\n",
  540. pOptions->pszInfId);
  541. }
  542. ReleaseObj (pSetup);
  543. }
  544. HRESULT hrT = pINetCfg->Uninitialize ();
  545. Assert (S_OK == hrT);
  546. ReleaseObj (pINetCfg->GetUnknown());
  547. }
  548. if (S_OK != hr)
  549. {
  550. g_pDiagCtx->Printf (ttidBeDiag, "FAILED Add component.\n");
  551. }
  552. PromptForLeakCheck (pOptions, "Add component...(dump heap and compare)");
  553. }
  554. VOID
  555. CmdAddRemoveStress (
  556. IN const DIAG_OPTIONS* pOptions,
  557. IN CNetConfig* pNetConfig)
  558. {
  559. HRESULT hr;
  560. CImplINetCfg* pINetCfg;
  561. NETCLASS Class;
  562. PCWSTR pszInfId;
  563. PRODUCT_FLAVOR Flavor;
  564. BOOL fPrompted;
  565. static const struct
  566. {
  567. NETCLASS Class;
  568. PCWSTR pszInfId;
  569. BOOL fServerOnly;
  570. } aPassInfo [] =
  571. {
  572. { NC_NETCLIENT, L"ms_msclient", FALSE },
  573. { NC_NETCLIENT, L"ms_nwclient", FALSE },
  574. // { NC_NETSERVICE, L"ms_fpnw", FALSE }, // requries copy files
  575. { NC_NETSERVICE, L"ms_netbios", FALSE },
  576. { NC_NETSERVICE, L"ms_nwsapagent", FALSE },
  577. { NC_NETSERVICE, L"ms_psched", FALSE },
  578. { NC_NETSERVICE, L"ms_rsvp", FALSE },
  579. { NC_NETSERVICE, L"ms_server", FALSE },
  580. // { NC_NETSERVICE, L"ms_wlbs", FALSE },
  581. { NC_NETTRANS, L"ms_appletalk", FALSE },
  582. { NC_NETTRANS, L"ms_atmarps", TRUE },
  583. { NC_NETTRANS, L"ms_atmlane", FALSE },
  584. { NC_NETTRANS, L"ms_atmuni", FALSE },
  585. { NC_NETTRANS, L"ms_irda", FALSE },
  586. // { NC_NETTRANS, L"ms_isotpsys", FALSE },
  587. { NC_NETTRANS, L"ms_rawwan", FALSE },
  588. // { NC_NETTRANS, L"ms_streams", FALSE },
  589. // { NC_NETTRANS, L"ms_tcpip", FALSE },
  590. };
  591. GetProductFlavor (NULL, &Flavor);
  592. fPrompted = FALSE;
  593. g_pDiagCtx->SetFlags (
  594. DF_SHOW_CONSOLE_OUTPUT | DF_DONT_START_SERVICES |
  595. DF_DONT_DO_PNP_BINDS | DF_SUPRESS_E_NEED_REBOOT);
  596. hr = HrCreateINetCfg (TRUE, &pINetCfg);
  597. if (S_OK == hr)
  598. {
  599. UINT cSkip = 0;
  600. for (BOOL fInstall = TRUE;
  601. !_kbhit() && (S_OK == hr);
  602. fInstall = !fInstall)
  603. {
  604. for (UINT i = cSkip;
  605. (i < celems(aPassInfo)) && (S_OK == hr);
  606. i += (1 + cSkip))
  607. {
  608. INetCfgClassSetup* pSetup;
  609. INetCfgComponent* pIComp;
  610. if (aPassInfo[i].fServerOnly && (PF_WORKSTATION == Flavor))
  611. {
  612. continue;
  613. }
  614. Class = aPassInfo[i].Class;
  615. pszInfId = aPassInfo[i].pszInfId;
  616. if (fInstall)
  617. {
  618. g_pDiagCtx->Printf (ttidBeDiag, "--------------------\n"
  619. "Installing %S\n", pszInfId);
  620. hr = pINetCfg->QueryNetCfgClass (
  621. MAP_NETCLASS_TO_GUID[Class],
  622. IID_INetCfgClassSetup,
  623. (VOID**)&pSetup);
  624. if (S_OK == hr)
  625. {
  626. OBO_TOKEN OboToken;
  627. ZeroMemory (&OboToken, sizeof(OboToken));
  628. OboToken.Type = OBO_USER;
  629. hr = pSetup->Install (
  630. pszInfId,
  631. &OboToken,
  632. 0, 0, NULL, NULL,
  633. &pIComp);
  634. if (SUCCEEDED(hr))
  635. {
  636. ReleaseObj (pIComp);
  637. }
  638. if (NETCFG_S_REBOOT == hr)
  639. {
  640. hr = S_OK;
  641. g_pDiagCtx->Printf (ttidBeDiag, "%S was installed, but a reboot is required.\n",
  642. pszInfId);
  643. }
  644. ReleaseObj (pSetup);
  645. }
  646. }
  647. else
  648. {
  649. hr = pINetCfg->FindComponent (pszInfId, &pIComp);
  650. if (S_OK == hr)
  651. {
  652. GUID ClassGuid;
  653. g_pDiagCtx->Printf (ttidBeDiag, "--------------------\n"
  654. "Removing %S\n", pszInfId);
  655. hr = pIComp->GetClassGuid (&ClassGuid);
  656. if (S_OK == hr)
  657. {
  658. hr = pINetCfg->QueryNetCfgClass (
  659. &ClassGuid,
  660. IID_INetCfgClassSetup,
  661. (VOID**)&pSetup);
  662. if (S_OK == hr)
  663. {
  664. OBO_TOKEN OboToken;
  665. ZeroMemory (&OboToken, sizeof(OboToken));
  666. OboToken.Type = OBO_USER;
  667. hr = pSetup->DeInstall (
  668. pIComp,
  669. &OboToken,
  670. NULL);
  671. if (NETCFG_S_REBOOT == hr)
  672. {
  673. hr = S_OK;
  674. g_pDiagCtx->Printf (ttidBeDiag, "%S was removed, but a reboot is required.\n",
  675. pszInfId);
  676. }
  677. if (NETCFG_S_STILL_REFERENCED == hr)
  678. {
  679. hr = S_OK;
  680. g_pDiagCtx->Printf (ttidBeDiag, "%S is still referenced\n",
  681. pszInfId);
  682. }
  683. if (E_INVALIDARG == hr)
  684. {
  685. hr = S_OK;
  686. g_pDiagCtx->Printf (ttidBeDiag, "%S is installed, but not on behalf of "
  687. "the user, so we can't remove it. (Proceeding.)\n",
  688. pszInfId);
  689. }
  690. ReleaseObj (pSetup);
  691. }
  692. }
  693. ReleaseObj (pIComp);
  694. }
  695. else if (S_FALSE == hr)
  696. {
  697. hr = S_OK;
  698. }
  699. }
  700. }
  701. cSkip++;
  702. if (cSkip >= celems(aPassInfo))
  703. {
  704. cSkip = 0;
  705. }
  706. g_pDiagCtx->Printf (ttidBeDiag, "\n");
  707. if (!fPrompted)
  708. {
  709. PromptForLeakCheck (pOptions, "Add/Remove stress...(dump heap)");
  710. fPrompted = TRUE;
  711. }
  712. }
  713. if (S_OK == hr)
  714. {
  715. _getch ();
  716. }
  717. HRESULT hrT = pINetCfg->Uninitialize ();
  718. Assert (S_OK == hrT);
  719. ReleaseObj (pINetCfg->GetUnknown());
  720. }
  721. if (S_OK != hr)
  722. {
  723. g_pDiagCtx->Printf (ttidBeDiag, "FAILED Add/Remove stress component.\n");
  724. }
  725. if (fPrompted)
  726. {
  727. PromptForLeakCheck (pOptions, "Add/Remove stress...(dump heap and compare)");
  728. }
  729. }
  730. VOID
  731. CmdCleanup (
  732. IN const DIAG_OPTIONS* pOptions,
  733. IN CNetConfig* pNetConfig)
  734. {
  735. HRESULT hr;
  736. NETCLASS Class;
  737. PCWSTR pszSubtree;
  738. HKEY hkeySubtree;
  739. DWORD dwIndex;
  740. HKEY hkeyInstance;
  741. GUID InstanceGuid;
  742. BOOL fDeleteKey;
  743. WCHAR szInfPath [_MAX_PATH];
  744. WCHAR szInfSection [_MAX_PATH];
  745. DWORD cbData;
  746. static const struct
  747. {
  748. NETCLASS Class;
  749. PCWSTR pszSubtree;
  750. } aPassInfo [] =
  751. {
  752. { NC_NET, NULL },
  753. { NC_INFRARED, NULL },
  754. { NC_NETTRANS, NULL },
  755. { NC_NETCLIENT, NULL },
  756. { NC_NETSERVICE, NULL },
  757. { NC_NET, L"System\\CurrentControlSet\\Control\\Network\\{4d36e972-e325-11ce-bfc1-08002be10318}" },
  758. };
  759. for (UINT i = 0; i < celems(aPassInfo); i++)
  760. {
  761. Class = aPassInfo[i].Class;
  762. pszSubtree = aPassInfo[i].pszSubtree;
  763. Assert (FIsValidNetClass(Class));
  764. if (!pszSubtree)
  765. {
  766. pszSubtree = MAP_NETCLASS_TO_NETWORK_SUBTREE[Class];
  767. }
  768. // Play it safe and assume we don't be deleting anything.
  769. //
  770. fDeleteKey = FALSE;
  771. if (!FIsEnumerated (Class))
  772. {
  773. hr = HrRegOpenKeyEx (HKEY_LOCAL_MACHINE,
  774. pszSubtree,
  775. KEY_READ,
  776. &hkeySubtree);
  777. if (S_OK == hr)
  778. {
  779. DWORD cchGuid;
  780. WCHAR szInstanceGuid [c_cchGuidWithTerm];
  781. FILETIME ftLastWrite;
  782. for (dwIndex = 0; S_OK == hr; dwIndex++)
  783. {
  784. fDeleteKey = FALSE;
  785. cchGuid = celems(szInstanceGuid);
  786. hr = HrRegEnumKeyEx (
  787. hkeySubtree, dwIndex, szInstanceGuid, &cchGuid,
  788. NULL, NULL, &ftLastWrite);
  789. if ((S_OK == hr) && ((c_cchGuidWithTerm-1) == cchGuid))
  790. {
  791. hr = IIDFromString (szInstanceGuid, &InstanceGuid);
  792. if (S_OK == hr)
  793. {
  794. if (!pNetConfig->Core.Components.PFindComponentByInstanceGuid(&InstanceGuid))
  795. {
  796. fDeleteKey = TRUE;
  797. hr = HrRegOpenKeyEx (
  798. hkeySubtree,
  799. szInstanceGuid,
  800. KEY_READ,
  801. &hkeyInstance);
  802. if (S_OK == hr)
  803. {
  804. *szInfPath = 0;
  805. *szInfSection = 0;
  806. cbData = sizeof(szInfPath);
  807. HrRegQuerySzBuffer (hkeyInstance,
  808. REGSTR_VAL_INFPATH,
  809. szInfPath, &cbData);
  810. cbData = sizeof(szInfSection) - sizeof(L".Remove");
  811. HrRegQuerySzBuffer (hkeyInstance,
  812. REGSTR_VAL_INFSECTION,
  813. szInfSection, &cbData);
  814. if (*szInfPath && *szInfSection)
  815. {
  816. HINF hinf;
  817. hr = HrSetupOpenInfFile (
  818. szInfPath,
  819. NULL, INF_STYLE_WIN4, NULL,
  820. &hinf);
  821. if (S_OK == hr)
  822. {
  823. wcscat (szInfSection, L".Remove");
  824. g_pDiagCtx->Printf (ttidBeDiag, "Running %S...\n", szInfSection);
  825. hr = HrCiDoCompleteSectionInstall(
  826. hinf, hkeyInstance,
  827. szInfSection, NULL,
  828. FIsEnumerated(Class));
  829. SetupCloseInfFile (hinf);
  830. }
  831. }
  832. RegCloseKey (hkeyInstance);
  833. }
  834. }
  835. }
  836. if (fDeleteKey)
  837. {
  838. g_pDiagCtx->Printf (ttidBeDiag, "Deleting tree %S...\n", szInstanceGuid);
  839. (VOID) HrRegDeleteKeyTree (hkeySubtree, szInstanceGuid);
  840. fDeleteKey = FALSE;
  841. // Back the index up by one since we just
  842. // delete the current element.
  843. //
  844. dwIndex--;
  845. }
  846. }
  847. }
  848. if (HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr)
  849. {
  850. hr = S_OK;
  851. }
  852. RegCloseKey (hkeySubtree);
  853. }
  854. }
  855. else
  856. {
  857. HDEVINFO hdi;
  858. hr = HrSetupDiGetClassDevs (MAP_NETCLASS_TO_GUID[Class],
  859. NULL, NULL, DIGCF_PROFILE, &hdi);
  860. if (S_OK == hr)
  861. {
  862. SP_DEVINFO_DATA deid;
  863. WCHAR szPnpId [2 * _MAX_PATH];
  864. BOOL fr;
  865. for (dwIndex = 0; S_OK == hr; dwIndex++)
  866. {
  867. hr = HrSetupDiEnumDeviceInfo (hdi, dwIndex, &deid);
  868. if (S_OK == hr)
  869. {
  870. fr = SetupDiGetDeviceInstanceId (
  871. hdi, &deid,
  872. szPnpId, celems(szPnpId), NULL);
  873. if (fr)
  874. {
  875. if (!pNetConfig->Core.Components.PFindComponentByPnpId(szPnpId))
  876. {
  877. g_pDiagCtx->Printf (ttidBeDiag, "Removing %S...\n", szPnpId);
  878. ADAPTER_REMOVE_PARAMS arp = {0};
  879. CiSetReservedField (hdi, &deid, &arp);
  880. hr = HrSetupDiCallClassInstaller (
  881. DIF_REMOVE, hdi, &deid);
  882. CiClearReservedField (hdi, &deid);
  883. }
  884. }
  885. }
  886. }
  887. if (HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr)
  888. {
  889. hr = S_OK;
  890. }
  891. SetupDiDestroyDeviceInfoList (hdi);
  892. }
  893. }
  894. }
  895. }
  896. VOID
  897. CmdRemoveComponent (
  898. IN const DIAG_OPTIONS* pOptions,
  899. IN CNetConfig* pNetConfig)
  900. {
  901. HRESULT hr;
  902. CImplINetCfg* pINetCfg;
  903. PromptForLeakCheck (pOptions, "Remove component...(dump heap)");
  904. hr = HrCreateINetCfg (TRUE, &pINetCfg);
  905. if (S_OK == hr)
  906. {
  907. INetCfgComponent* pIComp;
  908. hr = pINetCfg->FindComponent (pOptions->pszInfId, &pIComp);
  909. if (S_OK == hr)
  910. {
  911. GUID ClassGuid;
  912. hr = pIComp->GetClassGuid (&ClassGuid);
  913. if (S_OK == hr)
  914. {
  915. INetCfgClassSetup* pSetup;
  916. hr = pINetCfg->QueryNetCfgClass (
  917. &ClassGuid,
  918. IID_INetCfgClassSetup,
  919. (VOID**)&pSetup);
  920. if (S_OK == hr)
  921. {
  922. OBO_TOKEN OboToken;
  923. ZeroMemory (&OboToken, sizeof(OboToken));
  924. OboToken.Type = OBO_USER;
  925. hr = pSetup->DeInstall (
  926. pIComp,
  927. &OboToken,
  928. NULL);
  929. if (NETCFG_S_REBOOT == hr)
  930. {
  931. hr = S_OK;
  932. g_pDiagCtx->Printf (ttidBeDiag, "%S was removed, but a reboot is required.\n",
  933. pOptions->pszInfId);
  934. }
  935. if (NETCFG_S_STILL_REFERENCED == hr)
  936. {
  937. hr = S_OK;
  938. g_pDiagCtx->Printf (ttidBeDiag, "%S is still referenced\n",
  939. pOptions->pszInfId);
  940. }
  941. if (E_INVALIDARG == hr)
  942. {
  943. hr = S_OK;
  944. g_pDiagCtx->Printf (ttidBeDiag, "%S is installed, but not on behalf of "
  945. "the user, so it was not removed.\n",
  946. pOptions->pszInfId);
  947. }
  948. ReleaseObj (pSetup);
  949. }
  950. }
  951. ReleaseObj (pIComp);
  952. }
  953. else if (S_FALSE == hr)
  954. {
  955. g_pDiagCtx->Printf (ttidBeDiag, "%S was not found.\n", pOptions->pszInfId);
  956. hr = S_OK;
  957. }
  958. HRESULT hrT = pINetCfg->Uninitialize ();
  959. Assert (S_OK == hrT);
  960. ReleaseObj (pINetCfg->GetUnknown());
  961. }
  962. else if (NETCFG_E_NEED_REBOOT == hr)
  963. {
  964. hr = S_OK;
  965. }
  966. if (S_OK != hr)
  967. {
  968. g_pDiagCtx->Printf (ttidBeDiag, "FAILED Remove component.\n");
  969. }
  970. PromptForLeakCheck (pOptions, "Remove component...(dump heap and compare)");
  971. }
  972. VOID
  973. CmdUpdateComponent (
  974. IN const DIAG_OPTIONS* pOptions,
  975. IN CNetConfig* pNetConfig)
  976. {
  977. HRESULT hr;
  978. CImplINetCfg* pINetCfg;
  979. PromptForLeakCheck (pOptions, "Update component...(dump heap)");
  980. hr = HrCreateINetCfg (TRUE, &pINetCfg);
  981. if (S_OK == hr)
  982. {
  983. INetCfgComponent* pIComp;
  984. hr = pINetCfg->FindComponent (pOptions->pszInfId, &pIComp);
  985. if (S_OK == hr)
  986. {
  987. INetCfgInternalSetup* pSetup;
  988. hr = pINetCfg->GetUnknown()->QueryInterface (
  989. IID_INetCfgInternalSetup,
  990. (VOID**)&pSetup);
  991. if (S_OK == hr)
  992. {
  993. hr = pSetup->UpdateNonEnumeratedComponent (
  994. pIComp,
  995. NSF_POSTSYSINSTALL,
  996. 0);
  997. if (S_OK == hr)
  998. {
  999. hr = pINetCfg->Apply ();
  1000. if (NETCFG_S_REBOOT == hr)
  1001. {
  1002. hr = S_OK;
  1003. g_pDiagCtx->Printf (ttidBeDiag, "%S was removed, but a reboot is required.\n",
  1004. pOptions->pszInfId);
  1005. }
  1006. }
  1007. ReleaseObj (pSetup);
  1008. }
  1009. ReleaseObj (pIComp);
  1010. }
  1011. else if (S_FALSE == hr)
  1012. {
  1013. g_pDiagCtx->Printf (ttidBeDiag, "%S was not found.\n", pOptions->pszInfId);
  1014. hr = S_OK;
  1015. }
  1016. HRESULT hrT = pINetCfg->Uninitialize ();
  1017. Assert (S_OK == hrT);
  1018. ReleaseObj (pINetCfg->GetUnknown());
  1019. }
  1020. else if (NETCFG_E_NEED_REBOOT == hr)
  1021. {
  1022. hr = S_OK;
  1023. }
  1024. if (S_OK != hr)
  1025. {
  1026. g_pDiagCtx->Printf (ttidBeDiag, "FAILED Update component.\n");
  1027. }
  1028. PromptForLeakCheck (pOptions, "Update component...(dump heap and compare)");
  1029. }
  1030. VOID
  1031. CmdRemoveReferences (
  1032. IN const DIAG_OPTIONS* pOptions,
  1033. IN CNetConfig* pNetConfig)
  1034. {
  1035. Assert (pOptions->pszInfId);
  1036. CComponent* pComponent;
  1037. pComponent = pNetConfig->Core.Components.PFindComponentByInfId (
  1038. pOptions->pszInfId, NULL);
  1039. if (pComponent)
  1040. {
  1041. pComponent->Refs.RemoveAllReferences();
  1042. HrSaveNetworkConfigurationToRegistry (pNetConfig);
  1043. }
  1044. }
  1045. VOID
  1046. CmdShowBindings (
  1047. IN const DIAG_OPTIONS* pOptions,
  1048. IN CNetConfig* pNetConfig)
  1049. {
  1050. HRESULT hr = S_OK;
  1051. CComponent* pComponent;
  1052. CBindingSet BindingSet;
  1053. tstring strBindingSet;
  1054. if (SHOW_DISABLED == pOptions->ShowBindParam)
  1055. {
  1056. pNetConfig->Core.DisabledBindings.Printf (ttidBeDiag, NULL);
  1057. return;
  1058. }
  1059. else if (CST_BY_NAME == pOptions->CompSpecifier.Type)
  1060. {
  1061. pComponent = pNetConfig->Core.Components.PFindComponentByPnpId (
  1062. pOptions->CompSpecifier.pszInfOrPnpId);
  1063. if (!pComponent)
  1064. {
  1065. pComponent = pNetConfig->Core.Components.PFindComponentByInfId (
  1066. pOptions->CompSpecifier.pszInfOrPnpId, NULL);
  1067. }
  1068. if (!pComponent)
  1069. {
  1070. g_pDiagCtx->Printf (ttidBeDiag, "Component not found.");
  1071. return;
  1072. }
  1073. if (SHOW_BELOW == pOptions->ShowBindParam)
  1074. {
  1075. hr = pNetConfig->Core.HrGetComponentBindings (
  1076. pComponent, GBF_DEFAULT, &BindingSet);
  1077. }
  1078. else if (SHOW_INVOLVING == pOptions->ShowBindParam)
  1079. {
  1080. hr = pNetConfig->Core.HrGetBindingsInvolvingComponent (
  1081. pComponent, GBF_DEFAULT, &BindingSet);
  1082. }
  1083. if ((SHOW_UPPER == pOptions->ShowBindParam) &&
  1084. FIsEnumerated(pComponent->Class()))
  1085. {
  1086. hr = pNetConfig->Core.HrGetComponentUpperBindings (
  1087. pComponent, GBF_DEFAULT, &BindingSet);
  1088. }
  1089. }
  1090. else if (CST_ALL == pOptions->CompSpecifier.Type)
  1091. {
  1092. CComponentList::const_iterator iter;
  1093. for (iter = pNetConfig->Core.Components.begin();
  1094. iter != pNetConfig->Core.Components.end();
  1095. iter++)
  1096. {
  1097. pComponent = *iter;
  1098. Assert (pComponent);
  1099. hr = pNetConfig->Core.HrGetComponentBindings (
  1100. pComponent,
  1101. GBF_ADD_TO_BINDSET,
  1102. &BindingSet);
  1103. if (S_OK != hr) break;
  1104. }
  1105. }
  1106. if ((S_OK == hr) && !BindingSet.FIsEmpty())
  1107. {
  1108. BindingSet.Printf (ttidBeDiag, NULL);
  1109. }
  1110. }
  1111. VOID
  1112. CmdShowComponents (
  1113. IN const DIAG_OPTIONS* pOptions,
  1114. IN CNetConfig* pNetConfig)
  1115. {
  1116. HRESULT hr;
  1117. CComponentList::const_iterator iter;
  1118. const CComponent* pComponent;
  1119. WCHAR szBuffer [256];
  1120. CHAR* pszNetClass;
  1121. UINT CountRefdBy;
  1122. UINT i;
  1123. hr = pNetConfig->HrEnsureExternalDataLoadedForAllComponents ();
  1124. if (S_OK != hr)
  1125. {
  1126. return;
  1127. }
  1128. for (iter = pNetConfig->Core.Components.begin();
  1129. iter != pNetConfig->Core.Components.end();
  1130. iter++)
  1131. {
  1132. pComponent = *iter;
  1133. Assert (pComponent);
  1134. StringFromGUID2 (pComponent->m_InstanceGuid,
  1135. szBuffer, celems(szBuffer));
  1136. switch (pComponent->Class())
  1137. {
  1138. case NC_NET:
  1139. pszNetClass = "NET ";
  1140. break;
  1141. case NC_INFRARED:
  1142. pszNetClass = "INFRARED ";
  1143. break;
  1144. case NC_NETTRANS:
  1145. pszNetClass = "TRANSPORT";
  1146. break;
  1147. case NC_NETCLIENT:
  1148. pszNetClass = "CLIENT ";
  1149. break;
  1150. case NC_NETSERVICE:
  1151. pszNetClass = "SERVICE ";
  1152. break;
  1153. default:
  1154. pszNetClass = "(Invalid)";
  1155. break;
  1156. }
  1157. tstring strChars;
  1158. SzFromCharacteristics(pComponent->m_dwCharacter, &strChars);
  1159. g_pDiagCtx->Printf (ttidBeDiag,
  1160. "\n"
  1161. "%S %S\n" // InfId PnpId
  1162. " Description: %S\n"
  1163. " Class: %s\n"
  1164. " Character: (0x%08x) %S\n"
  1165. " Guid: %S\n"
  1166. " NotifyObject?: %s\n"
  1167. " BindForm: %S\n"
  1168. " BindName: %S\n"
  1169. " Service (CoServices): %S (%S)\n"
  1170. " Ref'd by User?: %s\n",
  1171. pComponent->m_pszInfId,
  1172. (pComponent->m_pszPnpId) ? pComponent->m_pszPnpId : L"",
  1173. (pComponent->Ext.PszDescription()) ? pComponent->Ext.PszDescription() : L"<no description>",
  1174. pszNetClass, pComponent->m_dwCharacter, strChars.c_str(), szBuffer,
  1175. pComponent->Ext.FHasNotifyObject() ? "Yes" : "No",
  1176. (pComponent->Ext.PszBindForm()) ? pComponent->Ext.PszBindForm() : L"<default>",
  1177. pComponent->Ext.PszBindName(),
  1178. (pComponent->Ext.PszService()) ? pComponent->Ext.PszService() : L"(none)",
  1179. (pComponent->Ext.PszCoServices()) ? pComponent->Ext.PszCoServices() : L"none",
  1180. (pComponent->Refs.FIsReferencedByUser()) ? "Yes" : "No");
  1181. CountRefdBy = pComponent->Refs.CountComponentsReferencedBy();
  1182. if (CountRefdBy)
  1183. {
  1184. *szBuffer = 0;
  1185. for (i = 0; i < CountRefdBy; i++)
  1186. {
  1187. CComponent* pRefdBy;
  1188. pRefdBy = pComponent->Refs.PComponentReferencedByAtIndex(i);
  1189. Assert (pRefdBy);
  1190. wcscat (szBuffer, pRefdBy->PszGetPnpIdOrInfId());
  1191. wcscat (szBuffer, L" ");
  1192. }
  1193. }
  1194. else
  1195. {
  1196. wcscpy (szBuffer, L"(none)");
  1197. }
  1198. g_pDiagCtx->Printf (ttidBeDiag,
  1199. " Ref'd by Components: %S\n", szBuffer);
  1200. CountRefdBy = pComponent->Refs.CountSoftwareReferencedBy();
  1201. if (CountRefdBy)
  1202. {
  1203. *szBuffer = 0;
  1204. for (i = 0; i < CountRefdBy; i++)
  1205. {
  1206. const CWideString* pRefdBy;
  1207. pRefdBy = pComponent->Refs.PSoftwareReferencedByAtIndex(i);
  1208. Assert (pRefdBy);
  1209. wcscat (szBuffer, pRefdBy->c_str());
  1210. wcscat (szBuffer, L" ");
  1211. }
  1212. }
  1213. else
  1214. {
  1215. wcscpy (szBuffer, L"(none)");
  1216. }
  1217. g_pDiagCtx->Printf (ttidBeDiag,
  1218. " Ref'd by Software: %S\n", szBuffer);
  1219. }
  1220. g_pDiagCtx->Printf (ttidBeDiag, "\n");
  1221. }
  1222. VOID
  1223. CmdShowStackTable (
  1224. IN const DIAG_OPTIONS* pOptions,
  1225. IN CNetConfig* pNetConfig)
  1226. {
  1227. const CStackEntry* pStackEntry;
  1228. g_pDiagCtx->Printf (ttidBeDiag, "\n%15s | %s\n"
  1229. "---------------------------------\n",
  1230. "Upper",
  1231. "Lower");
  1232. for (pStackEntry = pNetConfig->Core.StackTable.begin();
  1233. pStackEntry != pNetConfig->Core.StackTable.end();
  1234. pStackEntry++)
  1235. {
  1236. g_pDiagCtx->Printf (ttidBeDiag, "%15S | %S\n",
  1237. pStackEntry->pUpper->PszGetPnpIdOrInfId(),
  1238. pStackEntry->pLower->PszGetPnpIdOrInfId());
  1239. }
  1240. g_pDiagCtx->Printf (ttidBeDiag, "\n");
  1241. g_pDiagCtx->Printf (ttidBeDiag, "WAN adapters are ordered %s\n\n",
  1242. (pNetConfig->Core.StackTable.m_fWanAdaptersFirst)
  1243. ? "first" : "last");
  1244. }
  1245. VOID
  1246. CmdShowLanAdapterPnpIds (
  1247. IN const DIAG_OPTIONS* pOptions,
  1248. IN CNetConfig* pNetConfig)
  1249. {
  1250. HRESULT hr;
  1251. CComponentList::const_iterator iter;
  1252. const CComponent* pComponent;
  1253. hr = pNetConfig->HrEnsureExternalDataLoadedForAllComponents ();
  1254. if (S_OK != hr)
  1255. {
  1256. return;
  1257. }
  1258. for (iter = pNetConfig->Core.Components.begin();
  1259. iter != pNetConfig->Core.Components.end();
  1260. iter++)
  1261. {
  1262. pComponent = *iter;
  1263. Assert (pComponent);
  1264. if (!FSubstringMatch (pComponent->Ext.PszUpperRange (), L"ndis5",
  1265. NULL, NULL))
  1266. {
  1267. continue;
  1268. }
  1269. g_pDiagCtx->Printf (ttidBeDiag, "%S\n", pComponent->m_pszPnpId);
  1270. }
  1271. }
  1272. VOID
  1273. CmdEnableOrDisableBinding (
  1274. IN const DIAG_OPTIONS* pOptions,
  1275. IN BOOL fEnable)
  1276. {
  1277. HRESULT hr;
  1278. CImplINetCfg* pINetCfg;
  1279. hr = HrCreateINetCfg (TRUE, &pINetCfg);
  1280. if (S_OK == hr)
  1281. {
  1282. INetCfgBindingPath* pIPath;
  1283. hr = HrFindBindPath (pINetCfg, pOptions->pszBindPath, &pIPath, NULL);
  1284. if ((S_OK == hr) && pIPath)
  1285. {
  1286. pIPath->Enable (fEnable);
  1287. ReleaseObj (pIPath);
  1288. }
  1289. hr = pINetCfg->Apply ();
  1290. if (S_OK != hr)
  1291. {
  1292. g_pDiagCtx->Printf (ttidBeDiag, "FAILED to %s binding\n",
  1293. (fEnable) ? "enable" : "disable");
  1294. }
  1295. HRESULT hrT = pINetCfg->Uninitialize ();
  1296. Assert (S_OK == hrT);
  1297. ReleaseObj (pINetCfg->GetUnknown());
  1298. }
  1299. }
  1300. VOID
  1301. CmdMoveBinding (
  1302. IN const DIAG_OPTIONS* pOptions)
  1303. {
  1304. HRESULT hr;
  1305. CImplINetCfg* pINetCfg;
  1306. hr = HrCreateINetCfg (TRUE, &pINetCfg);
  1307. if (S_OK == hr)
  1308. {
  1309. INetCfgBindingPath* pIPath;
  1310. INetCfgBindingPath* pIOtherPath;
  1311. INetCfgComponentBindings* pIOwner;
  1312. hr = HrFindBindPath (pINetCfg, pOptions->pszBindPath, &pIPath, &pIOwner);
  1313. if ((S_OK == hr) && pIPath)
  1314. {
  1315. if (0 == _wcsicmp(pOptions->pszOtherBindPath, L"null"))
  1316. {
  1317. pIOtherPath = NULL;
  1318. }
  1319. else
  1320. {
  1321. hr = HrFindBindPath (pINetCfg, pOptions->pszOtherBindPath,
  1322. &pIOtherPath, NULL);
  1323. }
  1324. if (S_OK == hr)
  1325. {
  1326. if (pOptions->fMoveBefore)
  1327. {
  1328. hr = pIOwner->MoveBefore (pIPath, pIOtherPath);
  1329. }
  1330. else
  1331. {
  1332. hr = pIOwner->MoveAfter (pIPath, pIOtherPath);
  1333. }
  1334. ReleaseObj (pIOtherPath);
  1335. }
  1336. ReleaseObj (pIPath);
  1337. ReleaseObj (pIOwner);
  1338. }
  1339. hr = pINetCfg->Apply ();
  1340. if (S_OK != hr)
  1341. {
  1342. g_pDiagCtx->Printf (ttidBeDiag, "FAILED to move binding\n");
  1343. }
  1344. HRESULT hrT = pINetCfg->Uninitialize ();
  1345. Assert (S_OK == hrT);
  1346. ReleaseObj (pINetCfg->GetUnknown());
  1347. }
  1348. }
  1349. VOID
  1350. CmdWriteBindings (
  1351. IN const DIAG_OPTIONS* pOptions OPTIONAL,
  1352. IN CNetConfig* pNetConfig)
  1353. {
  1354. HRESULT hr;
  1355. CComponentList::const_iterator iter;
  1356. const CComponent* pComponent;
  1357. CRegistryBindingsContext RegBindCtx;
  1358. hr = RegBindCtx.HrPrepare (pNetConfig);
  1359. if (S_OK != hr)
  1360. {
  1361. return;
  1362. }
  1363. for (iter = pNetConfig->Core.Components.begin();
  1364. iter != pNetConfig->Core.Components.end();
  1365. iter++)
  1366. {
  1367. pComponent = *iter;
  1368. Assert (pComponent);
  1369. hr = RegBindCtx.HrWriteBindingsForComponent (pComponent);
  1370. }
  1371. }
  1372. VOID
  1373. CmdSetWanOrder (
  1374. IN const DIAG_OPTIONS* pOptions)
  1375. {
  1376. HRESULT hr;
  1377. CImplINetCfg* pINetCfg;
  1378. hr = HrCreateINetCfg (TRUE, &pINetCfg);
  1379. if (S_OK == hr)
  1380. {
  1381. INetCfgSpecialCase* pSpecialCase;
  1382. hr = pINetCfg->GetUnknown()->QueryInterface (
  1383. IID_INetCfgSpecialCase,
  1384. (VOID**)&pSpecialCase);
  1385. Assert (S_OK == hr);
  1386. hr = pSpecialCase->SetWanAdaptersFirst (pOptions->fWanAdaptersFirst);
  1387. ReleaseObj (pSpecialCase);
  1388. hr = pINetCfg->Apply ();
  1389. if (S_OK != hr)
  1390. {
  1391. g_pDiagCtx->Printf (ttidBeDiag, "FAILED to move binding\n");
  1392. }
  1393. HRESULT hrT = pINetCfg->Uninitialize ();
  1394. Assert (S_OK == hrT);
  1395. ReleaseObj (pINetCfg->GetUnknown());
  1396. }
  1397. }
  1398. VOID
  1399. CmdShowLanaDiag (
  1400. IN const DIAG_OPTIONS* pOptions)
  1401. {
  1402. CLanaMap LanaMap;
  1403. HRESULT hr;
  1404. hr = LanaMap.HrLoadLanaMap();
  1405. if (S_OK == hr)
  1406. {
  1407. g_pDiagCtx->Printf (ttidBeDiag, "NetBios Bindings and Lana Information\n"
  1408. "-------------------------------------\n");
  1409. CWideString str;
  1410. LanaMap.Dump (&str);
  1411. g_pDiagCtx->Printf (ttidBeDiag, "%S", str.c_str());
  1412. HKEY hkeyNetBios;
  1413. hr = HrRegOpenKeyEx (HKEY_LOCAL_MACHINE,
  1414. L"System\\currentcontrolset\\services\\netbios\\parameters",
  1415. KEY_READ, &hkeyNetBios);
  1416. if (S_OK == hr)
  1417. {
  1418. DWORD MaxLana;
  1419. hr = HrRegQueryDword (hkeyNetBios, L"MaxLana", &MaxLana);
  1420. if (S_OK == hr)
  1421. {
  1422. g_pDiagCtx->Printf (ttidBeDiag, "\nMaximum Lana: %d\n", MaxLana);
  1423. }
  1424. RegCloseKey (hkeyNetBios);
  1425. }
  1426. HKEY hkeyRpc;
  1427. hr = HrRegOpenKeyEx (HKEY_LOCAL_MACHINE,
  1428. L"Software\\microsoft\\rpc\\netbios", KEY_READ, &hkeyRpc);
  1429. if (S_OK == hr)
  1430. {
  1431. DWORD Index = 0;
  1432. WCHAR szValueName [_MAX_PATH];
  1433. DWORD cbValueName = _MAX_PATH * sizeof (WCHAR);
  1434. DWORD Lana;
  1435. DWORD cbLana = sizeof (DWORD);
  1436. DWORD Type;
  1437. g_pDiagCtx->Printf (ttidBeDiag, "\nRPC information\n"
  1438. "---------------\n");
  1439. while (S_OK == HrRegEnumValue (hkeyRpc, Index, szValueName,
  1440. &cbValueName, &Type, (BYTE*)&Lana, &cbLana))
  1441. {
  1442. if (REG_DWORD == Type)
  1443. {
  1444. g_pDiagCtx->Printf (ttidBeDiag, "Lana: %3d\tProvider: %S\n", Lana, szValueName);
  1445. }
  1446. cbLana = sizeof (DWORD);
  1447. cbValueName = _MAX_PATH * sizeof (WCHAR);
  1448. Index++;
  1449. }
  1450. RegCloseKey (hkeyRpc);
  1451. }
  1452. }
  1453. }
  1454. HRESULT
  1455. HrPrintComponentDescriptionsFromBindPath (
  1456. IN PCWSTR pszBindPath,
  1457. IN CNetConfig* pNetConfig)
  1458. {
  1459. HRESULT hr = S_OK;
  1460. PCWSTR pszBindName;
  1461. PCWSTR pszEnd;
  1462. DWORD cchComponent;
  1463. CComponent* pComponent;
  1464. WCHAR szComponentBindName[_MAX_PATH] = {0};
  1465. Assert (pszBindPath && *pszBindPath);
  1466. GetFirstComponentFromBindPath (pszBindPath, &pszBindName,
  1467. &cchComponent);
  1468. while (pszBindName && *pszBindName)
  1469. {
  1470. wcsncpy (szComponentBindName, pszBindName, cchComponent);
  1471. pComponent = pNetConfig->Core.Components.
  1472. PFindComponentByBindName (NC_INVALID, szComponentBindName);
  1473. if (pComponent)
  1474. {
  1475. g_pDiagCtx->Printf (ttidBeDiag, "-->%S", pComponent->Ext.PszDescription());
  1476. }
  1477. #ifdef ENABLETRACE
  1478. else
  1479. {
  1480. g_pDiagCtx->Printf (ttidBeDiag, "%S", szComponentBindName);
  1481. }
  1482. #endif // ENABLETRACE
  1483. pszBindName = wcschr (pszBindName, L'_');
  1484. if (pszBindName)
  1485. {
  1486. pszBindName++;
  1487. pszEnd = wcschr (pszBindName, L'_');
  1488. if (pszEnd)
  1489. {
  1490. cchComponent = pszEnd - pszBindName;
  1491. }
  1492. else
  1493. {
  1494. cchComponent = wcslen (pszBindName);
  1495. }
  1496. }
  1497. }
  1498. TraceHr (ttidError, FAL, hr, FALSE,
  1499. "HrPrintComponentDescriptionsFromBindPath");
  1500. return hr;
  1501. }
  1502. VOID
  1503. CmdShowLanaPaths (
  1504. IN const DIAG_OPTIONS* pOptions,
  1505. IN CNetConfig* pNetConfig)
  1506. {
  1507. HRESULT hr;
  1508. CLanaMap LanaMap;
  1509. PCWSTR pszBindPath;
  1510. CLanaEntry* pEntry;
  1511. PromptForLeakCheck (pOptions,
  1512. "Show Lana UI info diagnostic...(dump heap)");
  1513. hr = pNetConfig->HrEnsureExternalDataLoadedForAllComponents();
  1514. if (S_OK != hr)
  1515. {
  1516. return;
  1517. }
  1518. hr = LanaMap.HrLoadLanaMap();
  1519. if (S_OK == hr)
  1520. {
  1521. PCWSTR pszBindName;
  1522. PCWSTR pszEnd;
  1523. DWORD cchComponent;
  1524. CComponent* pComponent;
  1525. WCHAR szComponentBindName[_MAX_PATH] = {0};
  1526. for (pEntry = LanaMap.begin(); pEntry != LanaMap.end();
  1527. pEntry++)
  1528. {
  1529. if (1 == pEntry->RegLanaEntry.Exported)
  1530. {
  1531. g_pDiagCtx->Printf (ttidNcDiag, "Lana: %3d\n",
  1532. pEntry->RegLanaEntry.LanaNumber);
  1533. pszBindPath = pEntry->pszBindPath;
  1534. GetFirstComponentFromBindPath (pszBindPath,
  1535. &pszBindName, &cchComponent);
  1536. while (pszBindName && *pszBindName)
  1537. {
  1538. wcsncpy (szComponentBindName, pszBindName, cchComponent);
  1539. szComponentBindName[cchComponent] = 0;
  1540. pComponent = pNetConfig->Core.Components.
  1541. PFindComponentByBindName (NC_INVALID,
  1542. szComponentBindName);
  1543. if (pComponent)
  1544. {
  1545. g_pDiagCtx->Printf (ttidNcDiag, "-->%S",
  1546. pComponent->Ext.PszDescription());
  1547. }
  1548. #ifdef ENABLETRACE
  1549. else
  1550. {
  1551. g_pDiagCtx->Printf (ttidNcDiag, "-->%S", szComponentBindName);
  1552. }
  1553. #endif // ENABLETRACE
  1554. pszBindName = wcschr (pszBindName, L'_');
  1555. if (pszBindName)
  1556. {
  1557. pszBindName++;
  1558. pszEnd = wcschr (pszBindName, L'_');
  1559. if (pszEnd)
  1560. {
  1561. cchComponent = pszEnd - pszBindName;
  1562. }
  1563. else
  1564. {
  1565. cchComponent = wcslen (pszBindName);
  1566. }
  1567. }
  1568. }
  1569. if (FAILED(hr))
  1570. {
  1571. break;
  1572. }
  1573. g_pDiagCtx->Printf (ttidNcDiag, "\n\n");
  1574. }
  1575. }
  1576. }
  1577. PromptForLeakCheck (pOptions,
  1578. "Show Lana UI info diagnostic...(dump heap and compare)");
  1579. }
  1580. VOID
  1581. CmdSetLanaNumber (
  1582. IN const DIAG_OPTIONS* pOptions,
  1583. IN CNetConfig* pNetConfig)
  1584. {
  1585. CLanaMap LanaMap;
  1586. HRESULT hr;
  1587. hr = pNetConfig->HrEnsureExternalDataLoadedForAllComponents();
  1588. if (S_OK != hr)
  1589. {
  1590. return;
  1591. }
  1592. hr = LanaMap.HrLoadLanaMap();
  1593. if (S_OK == hr)
  1594. {
  1595. if (pOptions->OldLanaNumber != pOptions->NewLanaNumber)
  1596. {
  1597. hr = LanaMap.HrSetLanaNumber (pOptions->OldLanaNumber,
  1598. pOptions->NewLanaNumber);
  1599. if (S_OK == hr)
  1600. {
  1601. hr = LanaMap.HrWriteLanaConfiguration (
  1602. pNetConfig->Core.Components);
  1603. g_pDiagCtx->Printf (ttidNcDiag, "\nLana changed.\n");
  1604. }
  1605. }
  1606. else
  1607. {
  1608. g_pDiagCtx->Printf (ttidNcDiag, "\nNo change.\n");
  1609. }
  1610. }
  1611. if (S_OK != hr)
  1612. {
  1613. if (HRESULT_FROM_WIN32(ERROR_OBJECT_NOT_FOUND) == hr)
  1614. {
  1615. g_pDiagCtx->Printf (ttidNcDiag, "\nThe old lana number is not currently "
  1616. "assigned to a bind path.\n");
  1617. }
  1618. else if (HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS) == hr)
  1619. {
  1620. g_pDiagCtx->Printf (ttidNcDiag, "\nThe new lana number is currently assigned "
  1621. "to a bind path.\n");
  1622. }
  1623. else
  1624. {
  1625. g_pDiagCtx->Printf (ttidNcDiag, "\nError %X occurred\n", hr);
  1626. }
  1627. }
  1628. }
  1629. VOID
  1630. CmdRewriteLanaInfo (
  1631. IN const DIAG_OPTIONS* pOptions,
  1632. IN CNetConfig* pNetConfig)
  1633. {
  1634. HRESULT hr;
  1635. const CComponent* pComponent;
  1636. CRegistryBindingsContext RegBindCtx;
  1637. hr = RegBindCtx.HrPrepare (pNetConfig);
  1638. if (S_OK == hr)
  1639. {
  1640. pComponent = pNetConfig->Core.Components.
  1641. PFindComponentByInfId (L"MS_NetBios", NULL);
  1642. if (pComponent)
  1643. {
  1644. hr = RegBindCtx.HrWriteBindingsForComponent (pComponent);
  1645. }
  1646. else
  1647. {
  1648. g_pDiagCtx->Printf (ttidNcDiag, "\nNetBios is not installed.\n");
  1649. }
  1650. }
  1651. }
  1652. EXTERN_C
  1653. VOID
  1654. WINAPI
  1655. NetCfgDiagFromCommandArgs (
  1656. IN DIAG_OPTIONS* pOptions)
  1657. {
  1658. Assert (pOptions);
  1659. Assert (pOptions->pDiagCtx);
  1660. g_pDiagCtx = pOptions->pDiagCtx;
  1661. CNetConfig NetConfig;
  1662. HrLoadNetworkConfigurationFromRegistry (KEY_READ, &NetConfig);
  1663. switch (pOptions->Command)
  1664. {
  1665. case CMD_SHOW_BINDINGS:
  1666. CmdShowBindings (pOptions, &NetConfig);
  1667. break;
  1668. case CMD_SHOW_COMPONENTS:
  1669. CmdShowComponents (pOptions, &NetConfig);
  1670. break;
  1671. case CMD_SHOW_STACK_TABLE:
  1672. CmdShowStackTable (pOptions, &NetConfig);
  1673. break;
  1674. case CMD_SHOW_LAN_ADAPTER_PNPIDS:
  1675. CmdShowLanAdapterPnpIds (pOptions, &NetConfig);
  1676. break;
  1677. case CMD_ADD_COMPONENT:
  1678. CmdAddComponent (pOptions, &NetConfig);
  1679. break;
  1680. case CMD_REMOVE_COMPONENT:
  1681. CmdRemoveComponent (pOptions, &NetConfig);
  1682. break;
  1683. case CMD_UPDATE_COMPONENT:
  1684. CmdUpdateComponent (pOptions, &NetConfig);
  1685. break;
  1686. case CMD_REMOVE_REFS:
  1687. CmdRemoveReferences (pOptions, &NetConfig);
  1688. break;
  1689. case CMD_ENABLE_BINDING:
  1690. CmdEnableOrDisableBinding (pOptions, TRUE);
  1691. break;
  1692. case CMD_DISABLE_BINDING:
  1693. CmdEnableOrDisableBinding (pOptions, FALSE);
  1694. break;
  1695. case CMD_MOVE_BINDING:
  1696. CmdMoveBinding (pOptions);
  1697. break;
  1698. case CMD_WRITE_BINDINGS:
  1699. CmdWriteBindings (pOptions, &NetConfig);
  1700. break;
  1701. case CMD_SET_WANORDER:
  1702. CmdSetWanOrder (pOptions);
  1703. break;
  1704. case CMD_FULL_DIAGNOSTIC:
  1705. CNetCfgInternalDiagnostic::CmdFullDiagnostic (pOptions, &NetConfig);
  1706. break;
  1707. case CMD_CLEANUP:
  1708. CmdCleanup (pOptions, &NetConfig);
  1709. break;
  1710. case CMD_ADD_REMOVE_STRESS:
  1711. CmdAddRemoveStress (pOptions, &NetConfig);
  1712. break;
  1713. default:
  1714. break;
  1715. }
  1716. g_pDiagCtx = NULL;
  1717. }
  1718. EXTERN_C
  1719. VOID
  1720. WINAPI
  1721. NetCfgDiagRepairRegistryBindings (
  1722. IN FILE* pLogFile)
  1723. {
  1724. HRESULT hr;
  1725. BOOL fCoUninitialize = TRUE;
  1726. hr = CoInitializeEx (NULL,
  1727. COINIT_DISABLE_OLE1DDE | COINIT_APARTMENTTHREADED);
  1728. if (FAILED(hr))
  1729. {
  1730. fCoUninitialize = FALSE;
  1731. if (RPC_E_CHANGED_MODE == hr)
  1732. {
  1733. hr = S_OK;
  1734. }
  1735. else
  1736. {
  1737. fprintf(pLogFile, "CoInitializeEx failed. (hr=0x%08x)\n", hr);
  1738. }
  1739. }
  1740. if (SUCCEEDED(hr))
  1741. {
  1742. CDiagContext DiagCtx;
  1743. CNetConfig NetConfig;
  1744. DiagCtx.SetFlags (DF_REPAIR_REGISTRY_BINDINGS);
  1745. DiagCtx.SetLogFile (pLogFile);
  1746. g_pDiagCtx = &DiagCtx;
  1747. hr = HrLoadNetworkConfigurationFromRegistry (KEY_READ, &NetConfig);
  1748. if (S_OK == hr)
  1749. {
  1750. CmdWriteBindings (NULL, &NetConfig);
  1751. }
  1752. else
  1753. {
  1754. fprintf(pLogFile,
  1755. "Failed to load network configuration "
  1756. "from the registry. (hr=0x%08x)\n", hr);
  1757. }
  1758. g_pDiagCtx = NULL;
  1759. if (fCoUninitialize)
  1760. {
  1761. CoUninitialize ();
  1762. }
  1763. }
  1764. }
  1765. EXTERN_C
  1766. VOID
  1767. WINAPI
  1768. LanaCfgFromCommandArgs (
  1769. IN DIAG_OPTIONS* pOptions)
  1770. {
  1771. Assert (pOptions);
  1772. Assert (pOptions->pDiagCtx);
  1773. g_pDiagCtx = pOptions->pDiagCtx;
  1774. CNetConfig NetConfig;
  1775. HrLoadNetworkConfigurationFromRegistry (KEY_READ, &NetConfig);
  1776. switch (pOptions->Command)
  1777. {
  1778. case CMD_SHOW_LANA_DIAG:
  1779. CmdShowLanaDiag (pOptions);
  1780. break;
  1781. case CMD_SHOW_LANA_PATHS:
  1782. CmdShowLanaPaths (pOptions, &NetConfig);
  1783. break;
  1784. case CMD_SET_LANA_NUMBER:
  1785. CmdSetLanaNumber (pOptions, &NetConfig);
  1786. break;
  1787. case CMD_REWRITE_LANA_INFO:
  1788. CmdRewriteLanaInfo (pOptions, &NetConfig);
  1789. break;
  1790. default:
  1791. break;
  1792. }
  1793. g_pDiagCtx = NULL;
  1794. }