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.

768 lines
26 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 2000.
  5. //
  6. // File: N C S Y S P R P . C P P
  7. //
  8. // Contents: Functions that related to SysPrep.exe requiremnts.
  9. //
  10. // Notes: 1.
  11. // 1.a sysprep calls NetSetupPrepareSysPrep
  12. // 1.b NetSetup saves adapter specific settings into $ncsp$.inf file.
  13. // NetSetup does this by calling INetCfgComponent::SaveAdapterParameters
  14. // implemented by notify object.
  15. //
  16. // 2.
  17. // 2.a Mini-Setup calls NetSetupRequestWizardPages passing the
  18. // "SETUPOPER_MINISETUP" flag right after PnP device installation.
  19. // 2.b NetSetup's InstallUpgradeWorkThrd thread checks the "SETUPOPER_MINISETUP" flag,
  20. // if set, it calls FNetSetupApplySysPrep which reads Answer-File "$ncsp$.inf".
  21. // It then calls notify object's INetCfgComponent::RestoreAdapterParameters
  22. // to restore adapter specific parameter settings from "$ncsp$.inf" Answer-File.
  23. //
  24. // 3. Only ONE network adapter card is supported on this version.
  25. //
  26. // Author: FrankLi 22-April-2000
  27. //
  28. //----------------------------------------------------------------------------
  29. #include "pch.h"
  30. #pragma hdrstop
  31. #include "kkcwinf.h"
  32. #include "ncstring.h"
  33. #include "netcfgp.h"
  34. #include "nsbase.h"
  35. #include "kkutils.h"
  36. #include "ncnetcfg.h"
  37. #include "lancmn.h"
  38. #include "ncreg.h"
  39. #include "ncsysprp.h"
  40. #include "resource.h"
  41. // constants from ncnetcfg\netinfid.cpp
  42. extern WCHAR c_szInfId_MS_TCPIP[] = L"ms_tcpip";
  43. extern WCHAR c_szInfId_MS_MSClient[] = L"ms_msclient";
  44. extern WCHAR c_szInfId_MS_NWClient[] = L"ms_nwclient";
  45. // constants from ncbase\afilestr.cpp
  46. extern WCHAR c_szRegKeyAnswerFileMap[] = L"SYSTEM\\Setup\\AnswerFileMap";
  47. // constants for adapter specific sections
  48. const WCHAR c_szParams_MS_TCPIP_Adapter01[] = L"params.ms_tcpip_Adapter01";
  49. //const WCHAR c_szParams_MS_MSClient_Adapter01[] = L"params.ms_msclient_Adapter01";
  50. //const WCHAR c_szParams_MS_NWClient_Adapter01[] = L"params.ms_nwclient_Adapter01";
  51. // The Answer-File name to save registry settings
  52. static const WCHAR c_szNetConfigSysPrepAnswerFile[] = L"\\$ncsp$.inf";
  53. // struct to map component Id to its corresponding adapter specific parameter
  54. // Answer-File section
  55. struct
  56. {
  57. PCWSTR pwszId;
  58. PCWSTR pwszIdAdapterParamsSection;
  59. } g_IdMap[] = {{c_szInfId_MS_TCPIP, c_szParams_MS_TCPIP_Adapter01},
  60. // no adapter specific parameters for MSClient and NWClient
  61. //{c_szInfId_MS_MSClient, c_szParams_MS_MSClient_Adapter01},
  62. //{c_szInfId_MS_NWClient, c_szParams_MS_NWClient_Adapter01}
  63. };
  64. // forward declaration
  65. HRESULT HrSaveNetworkComponentsForSysPrep(INetCfg* pNetCfg);
  66. HRESULT HrRestoreNetworkComponentsForSysPrep(INetCfg* pNetCfg);
  67. HRESULT HrGetFirstAdapterInstanceGuid(INetCfg * pnc, BOOL fDuringSetup, GUID * pGuidAdapter);
  68. BOOL FSectionHasAtLeastOneKey(IN CWInfFile* pwifAnswerFile, IN PCWSTR pszSection);
  69. //-------------------------------------------------------------------------
  70. // internal helper APIs used by CNetCfgSysPrep implementation
  71. // to save settings from notify object:
  72. // Purpose: save REG_DWORD to our internal CWinfFile object
  73. inline HRESULT HrSetupSetFirstDword(IN HWIF hwif,
  74. IN PCWSTR pwszSection,
  75. IN PCWSTR pwszKey,
  76. IN DWORD dwValue)
  77. {
  78. Assert (hwif && pwszSection && pwszKey);
  79. CWInfFile* pwifAnswerFile = reinterpret_cast<PCWInfFile>(hwif);
  80. PCWInfSection pwifSection = pwifAnswerFile->FindSection(pwszSection);
  81. if (pwifSection)
  82. {
  83. pwifAnswerFile->GotoEndOfSection(pwifSection);
  84. pwifAnswerFile->AddKey(pwszKey, dwValue);
  85. return S_OK;
  86. }
  87. else
  88. return S_FALSE;
  89. }
  90. // Purpose: save REG_SZ to our internal CWinfFile object
  91. inline HRESULT HrSetupSetFirstString(IN HWIF hwif,
  92. IN PCWSTR pwszSection,
  93. IN PCWSTR pwszKey,
  94. IN PCWSTR pwszValue)
  95. {
  96. Assert (hwif && pwszSection && pwszKey && pwszValue);
  97. CWInfFile* pwifAnswerFile = reinterpret_cast<PCWInfFile>(hwif);
  98. PCWInfSection pwifSection = pwifAnswerFile->FindSection(pwszSection);
  99. if (pwifSection)
  100. {
  101. pwifAnswerFile->GotoEndOfSection(pwifSection);
  102. pwifAnswerFile->AddKey(pwszKey, pwszValue);
  103. return S_OK;
  104. }
  105. else
  106. return S_FALSE;
  107. }
  108. // Purpose: save BOOL data to our internal CWinfFile object
  109. inline HRESULT HrSetupSetFirstStringAsBool(IN HWIF hwif,
  110. IN PCWSTR pwszSection,
  111. IN PCWSTR pwszKey,
  112. IN BOOL fValue)
  113. {
  114. Assert (hwif && pwszSection && pwszKey);
  115. CWInfFile* pwifAnswerFile = reinterpret_cast<PCWInfFile>(hwif);
  116. PCWInfSection pwifSection = pwifAnswerFile->FindSection(pwszSection);
  117. if (pwifSection)
  118. {
  119. pwifAnswerFile->GotoEndOfSection(pwifSection);
  120. pwifAnswerFile->AddBoolKey(pwszKey, fValue);
  121. return S_OK;
  122. }
  123. else
  124. return S_FALSE;
  125. }
  126. // Purpose: save MULTI_SZ to our internal CWinfFile object
  127. HRESULT HrSetupSetFirstMultiSzField(IN HWIF hwif,
  128. IN PCWSTR pwszSection,
  129. IN PCWSTR pwszKey,
  130. IN PCWSTR pmszValue)
  131. {
  132. HRESULT hr = S_OK;
  133. Assert (hwif && pwszSection && pwszKey && pmszValue);
  134. TStringList slValues;
  135. MultiSzToColString(pmszValue, &slValues);
  136. if (slValues.empty())
  137. {
  138. // empty pmszValue
  139. return HrSetupSetFirstString(hwif, pwszSection, pwszKey, pmszValue);
  140. }
  141. else
  142. {
  143. CWInfFile* pwifAnswerFile = reinterpret_cast<PCWInfFile>(hwif);
  144. PCWInfSection pwifSection = pwifAnswerFile->FindSection(pwszSection);
  145. if (pwifSection)
  146. {
  147. pwifAnswerFile->GotoEndOfSection(pwifSection);
  148. pwifAnswerFile->AddKey(pwszKey, slValues);
  149. }
  150. else
  151. hr = S_FALSE;
  152. }
  153. EraseAndDeleteAll(&slValues);
  154. return hr;
  155. }
  156. //--------------------------------------------------------------------------
  157. // Implementation of INetCfgSysPrep component
  158. inline HRESULT CNetCfgSysPrep::HrSetupSetFirstDword(
  159. IN PCWSTR pwszSection,
  160. IN PCWSTR pwszKey,
  161. IN DWORD dwValue)
  162. {
  163. HRESULT hr = S_OK;
  164. EnterCriticalSection(&m_csWrite);
  165. if (m_hwif)
  166. {
  167. hr = ::HrSetupSetFirstDword(
  168. m_hwif,
  169. pwszSection,
  170. pwszKey,
  171. dwValue);
  172. }
  173. else
  174. {
  175. hr = E_FAIL;
  176. }
  177. LeaveCriticalSection(&m_csWrite);
  178. return hr;
  179. }
  180. inline HRESULT CNetCfgSysPrep::HrSetupSetFirstString(
  181. IN PCWSTR pwszSection,
  182. IN PCWSTR pwszKey,
  183. IN PCWSTR pwszValue)
  184. {
  185. HRESULT hr = S_OK;
  186. EnterCriticalSection(&m_csWrite);
  187. if (m_hwif)
  188. {
  189. hr = ::HrSetupSetFirstString(
  190. m_hwif,
  191. pwszSection,
  192. pwszKey,
  193. pwszValue);
  194. }
  195. else
  196. {
  197. hr = E_FAIL;
  198. }
  199. LeaveCriticalSection(&m_csWrite);
  200. return hr;
  201. }
  202. inline HRESULT CNetCfgSysPrep::HrSetupSetFirstStringAsBool(
  203. IN PCWSTR pwszSection,
  204. IN PCWSTR pwszKey,
  205. IN BOOL fValue)
  206. {
  207. HRESULT hr = S_OK;
  208. EnterCriticalSection(&m_csWrite);
  209. if (m_hwif)
  210. {
  211. hr = ::HrSetupSetFirstStringAsBool(
  212. m_hwif,
  213. pwszSection,
  214. pwszKey,
  215. fValue);
  216. }
  217. else
  218. {
  219. hr = E_FAIL;
  220. }
  221. LeaveCriticalSection(&m_csWrite);
  222. return hr;
  223. }
  224. inline HRESULT CNetCfgSysPrep::HrSetupSetFirstMultiSzField(
  225. IN PCWSTR pwszSection,
  226. IN PCWSTR pwszKey,
  227. IN PCWSTR pmszValue)
  228. {
  229. HRESULT hr = S_OK;
  230. EnterCriticalSection(&m_csWrite);
  231. if (m_hwif)
  232. {
  233. hr = ::HrSetupSetFirstMultiSzField(
  234. m_hwif,
  235. pwszSection,
  236. pwszKey,
  237. pmszValue);
  238. }
  239. else
  240. {
  241. hr = E_FAIL;
  242. }
  243. LeaveCriticalSection(&m_csWrite);
  244. return hr;
  245. }
  246. //
  247. // Function: FNetSetupPrepareSysPrep
  248. //
  249. // Purpose: wrapper for HrSaveNetworkComponentsForSysPrep
  250. //
  251. // Parameters:
  252. //
  253. // Returns: TRUE on success, otherwise, FALSE
  254. //
  255. //
  256. BOOL FNetSetupPrepareSysPrep()
  257. {
  258. INetCfg* pNetCfg = NULL;
  259. BOOL fInitCom = TRUE;
  260. HRESULT hr;
  261. DefineFunctionName("FNetSetupPrepareSysPrep");
  262. TraceFunctionEntry(ttidNetSetup);
  263. hr = HrCreateAndInitializeINetCfg(&fInitCom, &pNetCfg,
  264. FALSE, // no write lock
  265. 0, // don't wait for it
  266. L"Save Configuration for SysPrep",
  267. NULL);
  268. if (SUCCEEDED(hr))
  269. {
  270. // Retain our success in initializing COM only if we asked to
  271. // initialize COM in the first place.
  272. if (! fInitCom)
  273. {
  274. TraceTag(ttidNetSetup, "%s: Failed to init COM", __FUNCNAME__);
  275. return FALSE;
  276. }
  277. // Save network component per adapter registry settings
  278. hr = HrSaveNetworkComponentsForSysPrep(pNetCfg);
  279. if (hr == S_OK)
  280. {
  281. // delete the HKLM\SYSTEM\Setup\AnswerFileMap registry key if it exits
  282. HrRegDeleteKeyTree(HKEY_LOCAL_MACHINE, c_szRegKeyAnswerFileMap);
  283. }
  284. HrUninitializeAndReleaseINetCfg (fInitCom, pNetCfg, FALSE);
  285. }
  286. TraceError("FNetSetupPrepareSysPrep", hr);
  287. return (hr == S_OK)? TRUE : FALSE;
  288. }
  289. //
  290. // Function: HrSaveNetworkComponentsForSysPrep
  291. //
  292. // Purpose: Ask notify object to save adapter specific settings
  293. //
  294. // Parameters: pNetCfg [IN] - An INetCfg interface
  295. //
  296. // Returns: HRESULT, S_OK on success
  297. //
  298. //
  299. // Note: only 1 network adapter card is supported. If there are more than 1,
  300. // we'll pick the first working one.
  301. HRESULT HrSaveNetworkComponentsForSysPrep(INetCfg* pNetCfg)
  302. {
  303. HRESULT hr = S_OK;
  304. GUID guidAdapter; // network adapter's Instance GUID
  305. BOOL fApplyWrite = FALSE; // flag to save internal registry settings to Answer-File
  306. BOOL fRet = TRUE;
  307. DefineFunctionName("HrSaveNetworkComponentsForSysPrep");
  308. hr = HrGetFirstAdapterInstanceGuid(pNetCfg, FALSE, &guidAdapter); // FALSE ==> not in setup
  309. if (hr != S_OK)
  310. {
  311. TraceTag(ttidNetSetup, "%s: HrGetFirstAdapterInstanceGuid failed 0x%08x", __FUNCNAME__, hr);
  312. return S_FALSE;
  313. }
  314. CWInfFile* pwifAnswerFile = new CWInfFile();
  315. // initialize answer file class
  316. if ((pwifAnswerFile == NULL) || (pwifAnswerFile->Init() == FALSE))
  317. {
  318. AssertSz(FALSE,"HrSaveNetworkComponentsForSysPrep - Failed to initialize CWInfFile");
  319. if (pwifAnswerFile)
  320. delete pwifAnswerFile;
  321. return(E_OUTOFMEMORY);
  322. }
  323. // access INetCfgSysPrep ATL component using C++ instead of CoCreateInstance
  324. CComObject<CNetCfgSysPrep>* pncsp = new CComObject<CNetCfgSysPrep>;
  325. // initialize CNetCfgSysPrep class
  326. if ((pncsp == NULL) || (pncsp->HrInit((HWIF) pwifAnswerFile) != S_OK))
  327. {
  328. AssertSz(FALSE,"HrSaveNetworkComponentsForSysPrep - Failed to initialize CWInfFile");
  329. delete pwifAnswerFile;
  330. if (pncsp)
  331. delete pncsp;
  332. return(E_OUTOFMEMORY);
  333. }
  334. pncsp->AddRef(); // keep a reference to our component
  335. for (UINT nIdx = 0; nIdx < celems(g_IdMap); nIdx++)
  336. {
  337. INetCfgComponent* pINetCfgComponent;
  338. PCWSTR pwszInfId;
  339. PCWSTR pwszAdapterParamsSections;
  340. pwszInfId = g_IdMap[nIdx].pwszId;
  341. pwszAdapterParamsSections = g_IdMap[nIdx].pwszIdAdapterParamsSection;
  342. hr = pNetCfg->FindComponent(pwszInfId, &pINetCfgComponent);
  343. if (hr == S_OK)
  344. {
  345. Assert (pINetCfgComponent);
  346. // Component has already installed, we'll call notify object's
  347. // INetCfgComponentSysPrep::SaveAdapterParameters
  348. // Need to query for the private component interface which
  349. // gives us access to the notify object.
  350. //
  351. INetCfgComponentPrivate* pComponentPrivate;
  352. hr = pINetCfgComponent->QueryInterface(
  353. IID_INetCfgComponentPrivate,
  354. reinterpret_cast<void**>(&pComponentPrivate));
  355. if (hr == S_OK)
  356. {
  357. INetCfgComponentSysPrep* pINetCfgComponentSysPrep;
  358. // Query the notify object for its INetCfgComponentSysPrep interface.
  359. // If it doesn't support it, that's okay, we can continue.
  360. //
  361. hr = pComponentPrivate->QueryNotifyObject(
  362. IID_INetCfgComponentSysPrep,
  363. (void**) &pINetCfgComponentSysPrep);
  364. if (S_OK == hr)
  365. {
  366. // add a section first
  367. pwifAnswerFile->AddSection(pwszAdapterParamsSections);
  368. // trigger Notify object to save registry settings
  369. hr = pINetCfgComponentSysPrep->SaveAdapterParameters(
  370. reinterpret_cast<INetCfgSysPrep*>(pncsp), pwszAdapterParamsSections, &guidAdapter);
  371. if (hr == S_OK)
  372. fApplyWrite = TRUE;
  373. ReleaseObj(pINetCfgComponentSysPrep);
  374. }
  375. else if (hr == E_NOINTERFACE)
  376. {
  377. TraceTag(ttidNetSetup, "%s: %S component doesn't support IID_INetCfgComponentSysPrep", __FUNCNAME__, pwszInfId);
  378. }
  379. else
  380. fRet = FALSE; // unexpected error
  381. ReleaseObj(pComponentPrivate);
  382. }
  383. else
  384. {
  385. TraceTag(ttidNetSetup, "%s: can't find IID_INetCfgComponentPrivate for component %S", __FUNCNAME__, pwszInfId);
  386. fRet = FALSE;
  387. }
  388. ReleaseObj (pINetCfgComponent);
  389. }
  390. else
  391. {
  392. // it is okay that this component has not been installed
  393. TraceTag(ttidNetSetup, "%s: Can't find %S component", __FUNCNAME__, pwszInfId);
  394. }
  395. } // end for
  396. pncsp->SetHWif(NULL); // no more writes for those components holding our INetCfgSysPrep interface
  397. ReleaseObj(pncsp); // done with the usage of INetCfgSysPrep component
  398. if (fApplyWrite)
  399. {
  400. WCHAR wszSystemDir[MAX_PATH];
  401. // get the path to $ncsp$.inf (NetConfig SysPrep Answer-File)
  402. if (GetSystemDirectory(wszSystemDir, MAX_PATH) != 0)
  403. {
  404. tstring strAnswerFile;
  405. strAnswerFile = wszSystemDir;
  406. strAnswerFile += c_szNetConfigSysPrepAnswerFile;
  407. // save the parameters filled by notify object to Answer-File
  408. if (! pwifAnswerFile->SaveAsEx(strAnswerFile.c_str()))
  409. fRet = FALSE;
  410. }
  411. else
  412. {
  413. TraceTag(ttidNetSetup, "%s: GetSystemDirectory failed 0x%8x", __FUNCNAME__, GetLastError());
  414. fRet = FALSE;
  415. }
  416. }
  417. delete pwifAnswerFile;
  418. return fRet? S_OK : S_FALSE;
  419. }
  420. //
  421. // Function: FNetSetupApplySysPrep
  422. //
  423. // Purpose: wrapper for HrRestoreNetworkComponentsForSysPrep
  424. //
  425. // Parameters:
  426. //
  427. // Returns: TRUE on success, otherwise, FALSE
  428. //
  429. // Notes: This causes NetSetup to load the content of
  430. // %systemroot%\system32\$ncsp$.inf into a CWInfFile object.
  431. // Then, NetSetup will instruct notify object to restore their
  432. // per adatper settings from the corresponding sections of the
  433. // $ncsp$.inf file.
  434. BOOL FNetSetupApplySysPrep()
  435. {
  436. INetCfg* pNetCfg = NULL;
  437. BOOL fInitCom = TRUE;
  438. HRESULT hr;
  439. DefineFunctionName("FNetSetupApplySysPrep");
  440. TraceFunctionEntry(ttidNetSetup);
  441. hr = HrCreateAndInitializeINetCfg(&fInitCom, &pNetCfg,
  442. FALSE, // no write lock
  443. 0, // don't wait for it
  444. L"Restore Configuration for SysPrep",
  445. NULL);
  446. if (SUCCEEDED(hr))
  447. {
  448. // Retain our success in initializing COM only if we asked to
  449. // initialize COM in the first place.
  450. if (! fInitCom)
  451. {
  452. TraceTag(ttidNetSetup, "%s: Failed to init COM", __FUNCNAME__);
  453. return FALSE;
  454. }
  455. // Restore network component per adapter registry settings
  456. hr = HrRestoreNetworkComponentsForSysPrep(pNetCfg);
  457. HrUninitializeAndReleaseINetCfg (fInitCom, pNetCfg, FALSE);
  458. }
  459. TraceError("FNetSetupApplySysPrep", hr);
  460. return (hr == S_OK)? TRUE : FALSE;
  461. }
  462. //
  463. // Function: HrRestoreNetworkComponentsForSysPrep
  464. //
  465. // Purpose: read $ncsp$.inf file. If this file has
  466. // adapter specific sections, trigger the corresponding
  467. // notify object to restore the settings to registry.
  468. //
  469. // Parameters: pNetCfg [IN] - An INetCfg interface
  470. //
  471. // Returns: HRESULT, S_OK on success
  472. //
  473. //
  474. HRESULT HrRestoreNetworkComponentsForSysPrep(INetCfg* pNetCfg)
  475. {
  476. HRESULT hr = S_OK;
  477. GUID guidAdapter; // network adapter's Instance GUID
  478. WCHAR wszSystemDir[MAX_PATH]; // system32 directory
  479. tstring strAnswerFile; // Answer-File which was saved by SysPrep
  480. BOOL fRet = TRUE; // notify object's status in restore settings
  481. DefineFunctionName("HrRestoreNetworkComponentsForSysPrep");
  482. // get the path to $ncsp$.inf (NetConfig SysPrep Answer-File)
  483. if (GetSystemDirectory(wszSystemDir, MAX_PATH) != 0)
  484. {
  485. strAnswerFile = wszSystemDir;
  486. strAnswerFile += c_szNetConfigSysPrepAnswerFile;
  487. }
  488. else
  489. {
  490. TraceTag(ttidNetSetup, "%s: GetSystemDirectory failed 0x%8x", __FUNCNAME__, GetLastError());
  491. return S_FALSE;
  492. }
  493. hr = HrGetFirstAdapterInstanceGuid(pNetCfg, TRUE, &guidAdapter); // TRUE ==> during setup
  494. if (hr != S_OK)
  495. {
  496. TraceTag(ttidNetSetup, "%s: HrGetFirstAdapterInstanceGuid failed 0x%08x", __FUNCNAME__, hr);
  497. return S_FALSE;
  498. }
  499. CWInfFile* pwifAnswerFile = new CWInfFile();
  500. // initialize answer file class
  501. if ((pwifAnswerFile == NULL) || (pwifAnswerFile->Init() == FALSE))
  502. {
  503. AssertSz(FALSE,"HrRestoreNetworkComponentsForSysPrep - Failed to initialize CWInfFile");
  504. if (pwifAnswerFile)
  505. delete pwifAnswerFile;
  506. return(E_OUTOFMEMORY);
  507. }
  508. // read $ncsp$.inf Answer-File into pwifAnswerFile object
  509. if (pwifAnswerFile->Open(strAnswerFile.c_str()) == FALSE)
  510. {
  511. TraceTag(ttidNetSetup, "%s: pwifAnswerFile->Open failed 0x%08x", __FUNCNAME__);
  512. delete pwifAnswerFile;
  513. return S_FALSE;
  514. }
  515. for (UINT nIdx = 0; nIdx < celems(g_IdMap); nIdx++)
  516. {
  517. INetCfgComponent* pINetCfgComponent;
  518. PCWSTR pwszInfId; // component ID
  519. PCWSTR pwszAdapterParamsSections; // adapter specific parameter section
  520. pwszInfId = g_IdMap[nIdx].pwszId;
  521. pwszAdapterParamsSections = g_IdMap[nIdx].pwszIdAdapterParamsSection;
  522. // trigger Notify object to restore registry settings if
  523. // the section has at least one line of parameter
  524. pwifAnswerFile->FindSection(pwszAdapterParamsSections);
  525. if (FSectionHasAtLeastOneKey(pwifAnswerFile, pwszAdapterParamsSections))
  526. {
  527. hr = pNetCfg->FindComponent(pwszInfId, &pINetCfgComponent);
  528. if (hr == S_OK)
  529. {
  530. Assert (pINetCfgComponent);
  531. // Component has already installed, just call notify object's
  532. // INetCfgComponentSysPrep::RestoreAdapterParameters
  533. // Need to query for the private component interface which
  534. // gives us access to the notify object.
  535. //
  536. INetCfgComponentPrivate* pComponentPrivate;
  537. hr = pINetCfgComponent->QueryInterface(
  538. IID_INetCfgComponentPrivate,
  539. reinterpret_cast<void**>(&pComponentPrivate));
  540. if (hr == S_OK)
  541. {
  542. INetCfgComponentSysPrep* pINetCfgComponentSysPrep;
  543. // Query the notify object for its INetCfgComponentSysPrep interface.
  544. // If it doesn't support it, that's okay, we can continue.
  545. //
  546. hr = pComponentPrivate->QueryNotifyObject(
  547. IID_INetCfgComponentSysPrep,
  548. (void**) &pINetCfgComponentSysPrep);
  549. if (S_OK == hr)
  550. {
  551. hr = pINetCfgComponentSysPrep->RestoreAdapterParameters(
  552. strAnswerFile.c_str(), pwszAdapterParamsSections, &guidAdapter);
  553. if (hr != S_OK)
  554. fRet = FALSE; // notify object can't restore settings
  555. ReleaseObj(pINetCfgComponentSysPrep);
  556. }
  557. else if (hr == E_NOINTERFACE)
  558. {
  559. TraceTag(ttidNetSetup, "%s: %S component doesn't support IID_INetCfgComponentSysPrep", __FUNCNAME__, pwszInfId);
  560. }
  561. else
  562. fRet = FALSE; // unexpected error
  563. ReleaseObj(pComponentPrivate);
  564. }
  565. else
  566. {
  567. TraceTag(ttidNetSetup, "%s: can't find IID_INetCfgComponentPrivate for component %S", __FUNCNAME__, pwszInfId);
  568. fRet = FALSE;
  569. }
  570. ReleaseObj (pINetCfgComponent);
  571. }
  572. else
  573. {
  574. // this component wasn't installed before SysPrep
  575. TraceTag(ttidNetSetup, "%s: Can't find %S component", __FUNCNAME__, pwszInfId);
  576. }
  577. } // end if section has at least one key to restore setting
  578. } // end for
  579. // delete the Answer-File in free build.
  580. #ifndef DBG
  581. DeleteFile(strAnswerFile.c_str());
  582. #endif
  583. delete pwifAnswerFile;
  584. return fRet? S_OK : S_FALSE;
  585. }
  586. //
  587. // Function: FSectionHasAtLeastOneKey
  588. //
  589. // Purpose: Check if an Answer-File section has at least one key
  590. //
  591. // Parameters: pwifAnswerFile [IN] - pointer to a CWInfFile object
  592. // pszSection [IN] - the section to check
  593. //
  594. // Returns: TRUE if found else FALSE
  595. //
  596. BOOL FSectionHasAtLeastOneKey(IN CWInfFile* pwifAnswerFile, IN PCWSTR pwszSection)
  597. {
  598. Assert(pwifAnswerFile && pwszSection);
  599. PCWInfSection pwifs = pwifAnswerFile->FindSection(pwszSection);
  600. if (pwifs == NULL)
  601. return FALSE;
  602. PCWInfKey pwifk = pwifs->FirstKey();
  603. if (pwifs == NULL)
  604. return FALSE;
  605. return TRUE;
  606. }
  607. //
  608. // Function: HrGetFirstAdapterInstanceGuid
  609. //
  610. // Purpose: Get the first installed adapter instance guid
  611. //
  612. // Parameters: pnc [IN] - An INetCfg interface
  613. // fDuringSetup [IN] - TRUE when this is being called during the setup time
  614. // pGuidAdapter [IN,OUT] - Receives an instance GUID of an adapter
  615. //
  616. // Returns: HRESULT, S_OK on success
  617. //
  618. HRESULT HrGetFirstAdapterInstanceGuid(INetCfg * pnc, BOOL fDuringSetup, GUID * pGuidAdapter)
  619. {
  620. HRESULT hr = S_OK;
  621. DefineFunctionName("HrGetFirstAdapterInstanceGuid");
  622. TraceTag(ttidNetSetup, "HrGetFirstAdapterInstanceGuid - Enter Find first available adapter");
  623. // Enumerate the available adapters
  624. Assert(pnc && pGuidAdapter);
  625. CIterNetCfgComponent nccIter(pnc, &GUID_DEVCLASS_NET);
  626. INetCfgComponent* pncc;
  627. while (SUCCEEDED(hr) && (S_OK == (hr = nccIter.HrNext(&pncc))))
  628. {
  629. hr = HrIsLanCapableAdapter(pncc);
  630. TraceError("HrIsLanCapableAdapter", hr);
  631. if (S_OK == hr)
  632. {
  633. DWORD dw;
  634. ULONG ul;
  635. TraceTag(ttidNetSetup, "%s: Found HrIsLanCapableAdapter", __FUNCNAME__);
  636. if (! fDuringSetup)
  637. {
  638. // Is it in used in a connection?
  639. hr = HrIsConnection(pncc);
  640. if (hr != S_OK)
  641. {
  642. TraceError("HrGetFirstAdapterInstanceGuid: HrIsConnection", hr);
  643. goto NextAdapter;
  644. }
  645. }
  646. // Is this a virtual adapter?
  647. hr = pncc->GetCharacteristics(&dw);
  648. if (hr != S_OK)
  649. {
  650. TraceError("GetCharacteristics", hr);
  651. goto NextAdapter;
  652. }
  653. if (! (dw & NCF_PHYSICAL))
  654. {
  655. TraceTag(ttidNetSetup, "%s: It is not a PHYSICAL adapter", __FUNCNAME__);
  656. goto NextAdapter;
  657. }
  658. // Check device, if not present skip it
  659. //
  660. hr = pncc->GetDeviceStatus(&ul);
  661. if ((hr != S_OK) || (ul != 0))
  662. {
  663. TraceTag(ttidNetSetup, "%s: device is not active.", __FUNCNAME__);
  664. goto NextAdapter;
  665. }
  666. // Get the adapter instance guid
  667. hr = pncc->GetInstanceGuid(pGuidAdapter);
  668. if (hr != S_OK)
  669. {
  670. TraceError("GetInstanceGuid", hr); //
  671. goto NextAdapter;
  672. }
  673. ReleaseObj(pncc);
  674. return S_OK;
  675. }
  676. NextAdapter:
  677. ReleaseObj(pncc);
  678. hr = S_OK;
  679. }
  680. return hr;
  681. }