Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3457 lines
115 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1999.
  5. //
  6. // File: C L A S S I N S T . C P P
  7. //
  8. // Contents: Defines the interface between the binding engine and the
  9. // network class installer.
  10. //
  11. // Notes:
  12. //
  13. // Author: billbe 15 Jan 1999
  14. //
  15. //----------------------------------------------------------------------------
  16. #include <pch.h>
  17. #pragma hdrstop
  18. #include "adapter.h"
  19. #include "benchmrk.h"
  20. #include "classinst.h"
  21. #include "filtdev.h"
  22. #include "netcfg.h"
  23. #include "iatl.h"
  24. #include "lockdown.h"
  25. #include "ncatl.h"
  26. #include "ncoc.h"
  27. #include "ncreg.h"
  28. #include "ncsetup.h"
  29. #include "ncui.h"
  30. #include "ncwins.h"
  31. #include "persist.h"
  32. #include "provider.h"
  33. #include "resource.h"
  34. #include "util.h"
  35. // HrRegisterNotificationDll functions
  36. enum ciRegisterDllFunction {CIRDF_REGISTER, CIRDF_UNREGISTER};
  37. // The temporary key used for dumping a component's registry entries. This is used
  38. // during the pruning of inapplicable protocols and filter services from the select
  39. // dialog.
  40. static const WCHAR c_szRegKeyTemp[] =
  41. L"System\\CurrentControlSet\\Control\\Network\\FTempKey";
  42. //+--------------------------------------------------------------------------
  43. //
  44. // Function: HrCiRegDeleteComponentNetworkKey
  45. //
  46. // Purpose: This function deletes the component key strInstanceGuid
  47. // (and its subkeys) under the Network\<guidClass> tree.
  48. //
  49. // Arguments:
  50. // Class [in] The class of the component
  51. // pszInstanceGuid [in] The instance guid of the component
  52. //
  53. // Returns: HRESULT. S_OK if successful, an error code otherwise.
  54. //
  55. // Author: billbe 27 Apr 1997
  56. //
  57. // Notes:
  58. //
  59. HRESULT
  60. HrCiRegDeleteComponentNetworkKey (
  61. IN NETCLASS Class,
  62. IN PCWSTR pszInstanceGuid)
  63. {
  64. HRESULT hr = S_OK;
  65. HKEY hkeyClass = NULL;
  66. PCWSTR pszNetworkSubtreePath = MAP_NETCLASS_TO_NETWORK_SUBTREE[Class];
  67. // Open the proper class key in the Network tree
  68. hr = HrRegOpenKeyEx(HKEY_LOCAL_MACHINE, pszNetworkSubtreePath,
  69. KEY_WRITE, &hkeyClass);
  70. // Delete the instance key tree
  71. //
  72. if (S_OK == hr)
  73. {
  74. hr = HrRegDeleteKeyTree(hkeyClass, pszInstanceGuid);
  75. RegSafeCloseKey(hkeyClass);
  76. }
  77. TraceHr (ttidError, FAL, hr, FALSE, "HrCiRegDeleteComponentKey");
  78. return hr;
  79. }
  80. //+--------------------------------------------------------------------------
  81. //
  82. // Function: HrCiRegisterNotificationDll
  83. //
  84. // Purpose: Registers or Unregisters a component's notification dll with
  85. // COM
  86. //
  87. // Arguments:
  88. // hkeyInstance [in] The handle to the instance key for the component
  89. // crdf [in] CIRDF_REGISTER if we are registering,
  90. // CIRDF_UNREGISTER if we are unregistering
  91. //
  92. // Returns: HRESULT. S_OK on if dll is successfully registered,
  93. // S_FALSE, if the component has no dll to
  94. // register, error code otherwise
  95. //
  96. // Author: billbe 23 Mar 1997
  97. //
  98. // Notes:
  99. //
  100. HRESULT
  101. HrCiRegisterNotificationDll(
  102. IN HKEY hkeyInstance,
  103. IN ciRegisterDllFunction crdf)
  104. {
  105. Assert(hkeyInstance);
  106. HKEY hkeyNdi;
  107. HRESULT hr;
  108. // Open the ndi key in the component's instance key so we can get the
  109. // Dll path.
  110. hr = HrRegOpenKeyEx (hkeyInstance, L"Ndi", KEY_READ, &hkeyNdi);
  111. if (S_OK == hr)
  112. {
  113. // Get the notification dll path
  114. tstring strDllPath;
  115. hr = HrRegQueryString (hkeyNdi, L"ComponentDLL", &strDllPath);
  116. if (S_OK == hr)
  117. {
  118. TraceTag (ttidClassInst,
  119. "Attempting to (un)register notification dll '%S'",
  120. strDllPath.c_str());
  121. hr = (CIRDF_REGISTER == crdf) ?
  122. HrRegisterComObject (strDllPath.c_str()) :
  123. HrUnregisterComObject (strDllPath.c_str());
  124. }
  125. else
  126. {
  127. if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
  128. {
  129. // The presence of the value is optional, so return
  130. // S_OK if it was not found
  131. hr = S_OK;
  132. }
  133. }
  134. RegCloseKey (hkeyNdi);
  135. }
  136. TraceHr (ttidError, FAL, hr, FALSE, "HrCiRegisterNotificationDll");
  137. return hr;
  138. }
  139. //+--------------------------------------------------------------------------
  140. //
  141. // Function: HrCiInstallServices
  142. //
  143. // Purpose: Processes any Inf service sections using strInfSection as a
  144. // base name
  145. //
  146. // Arguments:
  147. // hinfFile [in] A handle to the inf file
  148. // pszInfSection [in] The base section name
  149. //
  150. // Returns: HRESULT. S_OK if successful, error code otherwise
  151. //
  152. // Author: billbe 2 Apr 1997
  153. //
  154. // Notes: See SetupInstallServicesFromInfSection in SetupApi for more
  155. // info.
  156. //
  157. HRESULT
  158. HrCiInstallServices(
  159. IN HINF hinfFile,
  160. IN PCWSTR pszInfSection)
  161. {
  162. Assert (IsValidHandle(hinfFile));
  163. Assert (pszInfSection && *pszInfSection);
  164. BOOL fSuccess;
  165. WCHAR szServiceSection[_MAX_PATH];
  166. // append .Services to the section name
  167. //
  168. swprintf (szServiceSection, L"%s.%s", pszInfSection,
  169. INFSTR_SUBKEY_SERVICES);
  170. // Process the Services section
  171. fSuccess = SetupInstallServicesFromInfSection (hinfFile,
  172. szServiceSection, 0);
  173. if (!fSuccess)
  174. {
  175. // Since the section is optional, we can ignore
  176. // ERROR_SECTION_NOT_FOUND
  177. if (ERROR_SECTION_NOT_FOUND == GetLastError())
  178. {
  179. fSuccess = TRUE;
  180. }
  181. }
  182. // Any errors must be converted
  183. HRESULT hr = S_OK;
  184. if (!fSuccess)
  185. {
  186. hr = HrFromLastWin32Error();
  187. }
  188. TraceHr (ttidError, FAL, hr, FALSE,
  189. "HrCiInstallServices (%S)", szServiceSection);
  190. return hr;
  191. }
  192. //+--------------------------------------------------------------------------
  193. //
  194. // Function: HrCiInstallFromInfSection
  195. //
  196. // Purpose: A wrapper function for SetupInstallFromInfSection. This
  197. // function handles setting up the copy files process for
  198. // SetupInstallFromInfSection as well.
  199. //
  200. // Arguments:
  201. // hinfFile [in] A handle to the inf file to install from
  202. // pszInfSectionName [in] The section to install
  203. // hkeyRelative [in] The key that will be used as the section's
  204. // HKR
  205. // hwndParent [in] The HWND to the parent window, used for UI
  206. // dwInstallFlags [in] See SetupInstallFromInfSection for info on
  207. // these flags
  208. //
  209. // Returns: HRESULT. S_OK if successful, error code otherwise
  210. //
  211. // Author: billbe 4 Apr 1997
  212. //
  213. // Notes: See SetupApi documentation for more info on
  214. // SetupInstallFromInfSection and
  215. // SetupInstallFilesFromInfSection
  216. //
  217. HRESULT
  218. HrCiInstallFromInfSection(
  219. IN HINF hinfFile,
  220. IN PCWSTR pszInfSectionName,
  221. IN HKEY hkeyRelative,
  222. IN HWND hwndParent,
  223. IN DWORD dwInstallFlags)
  224. {
  225. Assert (IsValidHandle (hinfFile));
  226. Assert (pszInfSectionName && *pszInfSectionName);
  227. HRESULT hr = S_OK;
  228. if (dwInstallFlags & SPINST_FILES)
  229. {
  230. // The next three variables are used for SetupApi's copy files process
  231. PSP_FILE_CALLBACK pfc;
  232. PVOID pvCtx;
  233. HSPFILEQ hfq;
  234. // If the inf file has a layout entry in its version section
  235. // we need to append its information for proper locations
  236. // of any files we need to copy. If the call fails we can
  237. // still install, it just means the prompt for files will not
  238. // have the correct directory to begin with
  239. (VOID) SetupOpenAppendInfFile (NULL, hinfFile, NULL);
  240. // We need to create our own file queue so we can scan all the
  241. // files to be copied. Scanning before committing our queue will
  242. // prompt the user if the files already exist in the destination
  243. //
  244. hr = HrSetupOpenFileQueue (&hfq);
  245. if (S_OK == hr)
  246. {
  247. BOOL fInGuiModeSetup = FInSystemSetup();
  248. hr = HrSetupInstallFilesFromInfSection (hinfFile, NULL, hfq,
  249. pszInfSectionName, NULL, 0);
  250. // Set the default callback context
  251. // If the we are in system setup, we need to make sure the
  252. // callback doesn't display UI
  253. //
  254. if (S_OK == hr)
  255. {
  256. hr = HrSetupInitDefaultQueueCallbackEx (hwndParent,
  257. (fInGuiModeSetup ? (HWND)INVALID_HANDLE_VALUE : NULL),
  258. 0, 0, NULL, &pvCtx);
  259. if (S_OK == hr)
  260. {
  261. // Not doing anything special so use SetupApi default
  262. // handler for file copy.
  263. pfc = SetupDefaultQueueCallback;
  264. // Scan the queue to see if the files are already in the
  265. // destination and if so, prune them out.
  266. DWORD dwScanResult;
  267. hr = HrSetupScanFileQueueWithNoCallback (hfq,
  268. SPQ_SCAN_FILE_VALIDITY |
  269. SPQ_SCAN_PRUNE_COPY_QUEUE, hwndParent,
  270. &dwScanResult);
  271. // Now commit the queue so any files needing to be
  272. // copied, will be. If the scan result is 1 then there
  273. // is nothing to commit.
  274. //
  275. if ((S_OK == hr) && (1 != dwScanResult))
  276. {
  277. hr = HrSetupCommitFileQueue (hwndParent, hfq, pfc, pvCtx);
  278. }
  279. // We need to release the default context and close our
  280. // file queue
  281. //
  282. SetupTermDefaultQueueCallback (pvCtx);
  283. SetupCloseFileQueue (hfq);
  284. }
  285. }
  286. }
  287. }
  288. if ((S_OK == hr) && (dwInstallFlags & ~SPINST_FILES))
  289. {
  290. Assert (hkeyRelative);
  291. // Now we run all sections but CopyFiles
  292. hr = HrSetupInstallFromInfSection (hwndParent, hinfFile,
  293. pszInfSectionName, (dwInstallFlags & ~SPINST_FILES),
  294. hkeyRelative, NULL, 0, NULL, NULL, NULL, NULL);
  295. }
  296. TraceHr (ttidError, FAL, hr, HRESULT_FROM_WIN32(ERROR_CANCELLED) == hr,
  297. "HrCiInstallFromInfSection");
  298. return hr;
  299. }
  300. //+--------------------------------------------------------------------------
  301. //
  302. // Function: HrCiDoCompleteSectionInstall
  303. //
  304. // Purpose: Runs all relevant sections of an inf file using strSection
  305. // as the base section name.
  306. //
  307. // Arguments:
  308. // hinfFile [in] SetupApi handle to an inf file
  309. // hkeyRelative [in] The registry key that will be the HKR
  310. // key during inf processing.
  311. // pszSection [in] Section name to install
  312. // hwndParent [in] The handle to the parent, for
  313. // displaying UI
  314. // fEnumerated [in] TRUE if this component is PnP enumerated
  315. // FALSE otherwise
  316. //
  317. // Returns: HRESULT. S_OK if sucessful, error code otherwise
  318. //
  319. // Author: billbe 15 Apr 1997
  320. //
  321. // Notes:
  322. //
  323. HRESULT
  324. HrCiDoCompleteSectionInstall(
  325. IN HINF hinfFile,
  326. IN HKEY hkeyRelative,
  327. IN PCWSTR pszSection,
  328. IN HWND hwndParent,
  329. IN BOOL fEnumerated)
  330. {
  331. Assert (IsValidHandle (hinfFile));
  332. Assert (FImplies (!fEnumerated, hkeyRelative));
  333. HRESULT hr = S_OK;
  334. // Only do this if there is a section name to work with
  335. if (pszSection && *pszSection)
  336. {
  337. // If this is an enumerated device, the service section and
  338. // the copy files section will be processed by the Device Installer
  339. // fcn SetupDiInstallDevice so we can exclude it from the following
  340. // calls. But we do some processing based on registry and log config
  341. // entries so we will pre-run the registry section for enumerated
  342. // devices and exclude the others
  343. //
  344. // Run the section found using hkeyRelative as the HKR
  345. hr = HrCiInstallFromInfSection (hinfFile, pszSection,
  346. hkeyRelative, hwndParent,
  347. (fEnumerated ? (SPINST_REGISTRY | SPINST_LOGCONFIG) :
  348. SPINST_ALL & ~SPINST_REGSVR));
  349. if (!fEnumerated)
  350. {
  351. // We need to run the Services section and
  352. // check for Winsock dependency if they aren't specified to be
  353. // excluded.
  354. //
  355. // Note: Other sections may be added later. The default is to
  356. // run all sections not listed in dwExcludeSectionFlags
  357. //
  358. if (S_OK == hr)
  359. {
  360. // run services section if it exists
  361. hr = HrCiInstallServices (hinfFile, pszSection);
  362. if (S_OK == hr)
  363. {
  364. // Bug #383239: Wait till services are installed before
  365. // running the RegisterDlls section
  366. //
  367. hr = HrCiInstallFromInfSection (hinfFile, pszSection,
  368. hkeyRelative, hwndParent,
  369. SPINST_REGSVR);
  370. }
  371. }
  372. }
  373. if (S_OK == hr)
  374. {
  375. //sb This part can be called for either add or remove. We
  376. //sb are moving only the remove part forward. This should
  377. //sb still be performed for add.
  378. //
  379. // Determine if a .Winsock section exists for the
  380. // section specified in szActualSection
  381. PCWSTR pszSubSection = wcsstr(pszSection, L".Remove");
  382. if(!pszSubSection || wcscmp(pszSubSection, L".Remove"))
  383. {
  384. hr = HrAddOrRemoveWinsockDependancy (hinfFile, pszSection);
  385. }
  386. // These other extensions are undocumented and some have been
  387. // added by external groups. We don't want any of them
  388. // processed for enumerated components.
  389. //
  390. if ((S_OK == hr) && !fEnumerated)
  391. {
  392. // Process the additional INF extensions (SNMP Agent,
  393. // PrintMonitors, etc.)
  394. //
  395. hr = HrProcessAllINFExtensions (hinfFile, pszSection);
  396. }
  397. }
  398. }
  399. TraceHr (ttidError, FAL, hr, (HRESULT_FROM_WIN32(ERROR_CANCELLED) == hr),
  400. "HrCiDoCompleteSectionInstall");
  401. return hr;
  402. }
  403. //+--------------------------------------------------------------------------
  404. //
  405. // Function: HrCiRemoveNonEnumeratedComponent
  406. //
  407. // Purpose: This will run the remove section and delete the network
  408. // instance key for the component if necessary. This
  409. // function is called for partially (i.e. failed install)
  410. // and fully installed components
  411. //
  412. // Arguments:
  413. // hinf [in] The handle to the component's inf file
  414. // hkeyInstance [in] The handle to the component's instance key
  415. // Class [in] The class of the component
  416. // InstanceGuid [in] The instance guid of the component
  417. // pstrRemoveSection [out] Optional pointer to a tstring which receives
  418. // the remove section name.
  419. //
  420. // Returns: HRESULT. S_OK if successful, NETCFG_S_REBOOT if successful
  421. // but a reboot is required, or an error code otherwise
  422. //
  423. // Author: billbe 10 Dec 1996
  424. // Revised 27 Apr 1997
  425. //
  426. // Notes:
  427. //
  428. HRESULT
  429. HrCiRemoveNonEnumeratedComponent(
  430. IN HINF hinf,
  431. IN HKEY hkeyInstance,
  432. IN NETCLASS Class,
  433. IN const GUID& InstanceGuid,
  434. OUT tstring* pstrRemoveSection OPTIONAL)
  435. {
  436. Assert (IsValidHandle (hinf));
  437. Assert (IsValidHandle (hkeyInstance));
  438. static const WCHAR c_szRemoveSectionSuffix[] = L".Remove";
  439. // We get the remove section name and process all relevant sections
  440. // We also try to unregister any Notify objects available
  441. //
  442. WCHAR szRemoveSection[_MAX_PATH];
  443. DWORD cbBuffer = sizeof (szRemoveSection);
  444. HRESULT hr = HrRegQuerySzBuffer (hkeyInstance, REGSTR_VAL_INFSECTION,
  445. szRemoveSection, &cbBuffer);
  446. if (S_OK == hr)
  447. {
  448. wcscat (szRemoveSection, c_szRemoveSectionSuffix);
  449. if (pstrRemoveSection)
  450. {
  451. pstrRemoveSection->assign(szRemoveSection);
  452. }
  453. hr = HrCiDoCompleteSectionInstall (hinf, hkeyInstance,
  454. szRemoveSection, NULL, NULL);
  455. }
  456. // Whether unregistering the notify object is successful or not,
  457. // we must fully remove the component.
  458. (VOID) HrCiRegisterNotificationDll (hkeyInstance, CIRDF_UNREGISTER);
  459. // Now we need to remove the component key in the Network tree
  460. // We need to do this regardless of any previous errors
  461. // so we don't need the return value.
  462. WCHAR szGuid[c_cchGuidWithTerm];
  463. StringFromGUID2 (InstanceGuid, szGuid, c_cchGuidWithTerm);
  464. (VOID) HrCiRegDeleteComponentNetworkKey (Class, szGuid);
  465. // if all went well, set the return value based on whether a reboot
  466. // is required or not or any error from HrRegisterNotificationDll.
  467. //
  468. if (S_FALSE == hr)
  469. {
  470. // S_FALSE is okay but should not be returned by this fcn.
  471. hr = S_OK;
  472. }
  473. TraceHr (ttidError, FAL, hr, FALSE, "HrCiRemoveNonEnumeratedComponent");
  474. return hr;
  475. }
  476. //+--------------------------------------------------------------------------
  477. //
  478. // Function: HrCiRemoveComponent
  479. //
  480. // Purpose: Called from INetCfg, this will uninstall a network component.
  481. //
  482. // Arguments:
  483. // pComponent [in] The component to uninstall.
  484. // pstrRemoveSection [out] Optional pointer to a tstring which receives
  485. // the remove section name.
  486. //
  487. // Returns: HRESULT. S_OK if successful, NETCFG_S_REBOOT if successful
  488. // but a reboot is required, or an error code otherwise
  489. //
  490. // Author: billbe 10 Dec 1996
  491. // Revised 27 Apr 1997
  492. //
  493. // Notes:
  494. //
  495. HRESULT
  496. HrCiRemoveComponent(
  497. IN const CComponent* pComponent,
  498. OUT tstring* pstrRemoveSection OPTIONAL)
  499. {
  500. Assert (pComponent);
  501. HINF hinf = NULL;
  502. HDEVINFO hdi = NULL;
  503. SP_DEVINFO_DATA deid;
  504. HKEY hkeyInstance = NULL;
  505. HRESULT hr = S_OK;
  506. // If this is an enumerated net class component, then we need to
  507. // create the Device Installer structures for HrSetupDiRemoveDevice
  508. //
  509. if (FIsEnumerated (pComponent->Class()))
  510. {
  511. if (pComponent->m_dwCharacter & NCF_PHYSICAL)
  512. {
  513. // The binding engine calls us to remove physical devices
  514. // only when we need to potentially cleanup the information
  515. // we saved away when the class installer removed the device.
  516. // This happens when the class installer is told to remove
  517. // the device (which it does) and then notifies the binding
  518. // engine to remove it from its data structures. The binding
  519. // engine then calls this method to cleanup this info we
  520. // set so that the binding engine could notify components of
  521. // its removal.
  522. //
  523. // We can also be called here when a physical component is
  524. // removed (with the binding engine write lock held by someone)
  525. // and then readded immediately. The new component will get
  526. // the same PnpId as the removed one but the bindng engine still
  527. // has the removed component in its structures. When this
  528. // condition is detected, the binding engine will remove the
  529. // old instance (by calling us here). In this case, if we were
  530. // to open the device info on pComponent->m_pszPnpId, we'd open
  531. // the new instance that was added. We don't want to do this.
  532. // We just want to cleanup any of the information that we set
  533. // for the binding engine when we first removed the device.
  534. //
  535. HKEY hkeyComponent;
  536. hr = HrRegOpenKeyEx (HKEY_LOCAL_MACHINE,
  537. c_szTempNetcfgStorageForUninstalledEnumeratedComponent,
  538. KEY_WRITE, &hkeyComponent);
  539. if (S_OK == hr)
  540. {
  541. WCHAR szGuid[c_cchGuidWithTerm];
  542. INT cch = StringFromGUID2 (pComponent->m_InstanceGuid, szGuid,
  543. c_cchGuidWithTerm);
  544. Assert (c_cchGuidWithTerm == cch);
  545. (VOID) HrRegDeleteKeyTree (hkeyComponent, szGuid);
  546. RegCloseKey (hkeyComponent);
  547. }
  548. }
  549. else
  550. {
  551. // Create a device info list
  552. hr = HrOpenDeviceInfo (pComponent->Class(),
  553. pComponent->m_pszPnpId, &hdi, &deid);
  554. if (S_OK == hr)
  555. {
  556. // removals must go through device installer
  557. // hook (NetClassInstaller). The function we are
  558. // in can only be called if the caller has the write lock
  559. // so we need to indicate this to the device installer hook
  560. // through our reserved data.
  561. ADAPTER_REMOVE_PARAMS arp = {0};
  562. CiSetReservedField (hdi, &deid, &arp);
  563. // removals must go through device installer
  564. // hook (NetClassInstaller).
  565. hr = HrSetupDiCallClassInstaller (DIF_REMOVE, hdi, &deid);
  566. // clear the reserved field so we don't delete it later
  567. CiClearReservedField (hdi, &deid);
  568. if (S_OK == hr)
  569. {
  570. hr = FSetupDiCheckIfRestartNeeded (hdi, &deid) ?
  571. NETCFG_S_REBOOT : S_OK;
  572. #ifdef ENABLETRACE
  573. if (NETCFG_S_REBOOT == hr)
  574. {
  575. TraceTag (ttidClassInst, "***********************************"
  576. "**************************************************");
  577. TraceTag (ttidClassInst, "The component %S needs a reboot "
  578. "in order to function", pComponent->m_pszPnpId);
  579. TraceTag (ttidClassInst, "***********************************"
  580. "**************************************************");
  581. }
  582. #endif //ENABLETRACE
  583. }
  584. SetupDiDestroyDeviceInfoList (hdi);
  585. }
  586. }
  587. }
  588. else
  589. {
  590. // For non enumerated components, the instance key is the
  591. // component key
  592. hr = pComponent->HrOpenInstanceKey (KEY_ALL_ACCESS, &hkeyInstance,
  593. NULL, NULL);
  594. if (S_OK == hr)
  595. {
  596. if (NC_NETCLIENT == pComponent->Class ())
  597. {
  598. hr = HrCiDeleteNetProviderInfo (hkeyInstance, NULL, NULL);
  599. }
  600. if (S_OK == hr)
  601. {
  602. hr = pComponent->HrOpenInfFile(&hinf);
  603. if( S_OK == hr )
  604. {
  605. // Remove the component
  606. hr = HrCiRemoveNonEnumeratedComponent ( hinf,
  607. hkeyInstance, pComponent->Class(),
  608. pComponent->m_InstanceGuid,
  609. pstrRemoveSection);
  610. }
  611. }
  612. }
  613. RegSafeCloseKey (hkeyInstance);
  614. }
  615. TraceHr (ttidError, FAL, hr, NETCFG_S_REBOOT == hr,
  616. "HrCiRemoveComponent (%S)", pComponent->PszGetPnpIdOrInfId());
  617. return hr;
  618. }
  619. //+--------------------------------------------------------------------------
  620. //
  621. // Function: HrCiGetDriverInfo
  622. //
  623. // Purpose: Finds a component's driver information (in the inf file) and
  624. // creates a Device Info Data structure containing that
  625. // information as the structure's selected driver.
  626. // (see Device Installer Api for more info).
  627. //
  628. // Arguments:
  629. // hdi [in] See Device Installer Api documentation for more info.
  630. // pdeid [in, out] See Device Installer Api documentation for
  631. // more info. Should be allocated by caller, but empty.
  632. // guidClass [in] The class guid for the component.
  633. // pszInfId [in] The id of the component as found in its inf.
  634. // pszInfFile [in] Optional. The inf file for the component.
  635. //
  636. // Returns: HRESULT. S_OK if successful, error code otherwise.
  637. //
  638. // Author: billbe 11 Mar 1997
  639. //
  640. // Notes:
  641. //
  642. HRESULT
  643. HrCiGetDriverInfo (
  644. IN HDEVINFO hdi,
  645. IN OUT PSP_DEVINFO_DATA pdeid,
  646. IN const GUID& guidClass,
  647. IN PCWSTR pszInfId,
  648. IN PCWSTR pszInfFile OPTIONAL)
  649. {
  650. HRESULT hr;
  651. Assert (IsValidHandle (hdi));
  652. Assert (pdeid);
  653. Assert (pszInfId);
  654. // Copy the Id since we may need to change it.
  655. //
  656. WCHAR szId[_MAX_PATH];
  657. wcscpy (szId, pszInfId);
  658. // We cannot generate ids via HrSetupDiCreateDeviceInfo if they contain
  659. // slashes (e.g. Eisa\*pnp0232), so we need to convert any slashes in
  660. // the instance id to ampersands.
  661. //
  662. int iPos = 0;
  663. while (szId[iPos])
  664. {
  665. if (L'\\' == szId[iPos])
  666. {
  667. szId[iPos] = L'&';
  668. }
  669. ++iPos;
  670. }
  671. // First, create a [temporary] device info. This will be used to
  672. // find the component's Inf file.
  673. hr = HrSetupDiCreateDeviceInfo (hdi, szId, guidClass, NULL, NULL,
  674. DICD_GENERATE_ID, pdeid);
  675. if (S_OK == hr)
  676. {
  677. // In order to find the Inf file, Device Installer Api needs the
  678. // component id which it calls the Hardware id.
  679. //
  680. // We need to include an extra null since this registry value is a
  681. // multi-sz
  682. //
  683. wcsncpy (szId, pszInfId, iPos);
  684. szId[iPos + 1] = 0;
  685. hr = HrSetupDiSetDeviceRegistryProperty (hdi, pdeid, SPDRP_HARDWAREID,
  686. (const BYTE*)szId, CbOfSzAndTerm (szId) + sizeof(WCHAR));
  687. if (S_OK == hr)
  688. {
  689. // Get the install params and set the class for compat flag
  690. // This will use the device's class guid as a filter when
  691. // searching through infs, speeding things up. We can also
  692. // let Device Installer Api know that we want to use a single
  693. // inf. if we can't get the params and set it it isn't an error
  694. // since it only slows things down a bit
  695. //
  696. SP_DEVINSTALL_PARAMS deip;
  697. hr = HrSetupDiGetDeviceInstallParams (hdi, pdeid, &deip);
  698. if (S_OK == hr)
  699. {
  700. deip.FlagsEx |= DI_FLAGSEX_USECLASSFORCOMPAT;
  701. // If we were not given an inf file to use...
  702. // We have a map of known components and their inf files.
  703. // If this component is in the map then we can set the
  704. // driver path in the device info data and
  705. // set the enumerate a single inf flag. This will
  706. // cause the device installer to just look at the specified
  707. // inf file for the driver node.
  708. //
  709. // We only do this if the node doesn't already have a file
  710. // name set.
  711. //
  712. if (!(*deip.DriverPath))
  713. {
  714. if (pszInfFile && *pszInfFile)
  715. {
  716. wcscpy (deip.DriverPath, pszInfFile);
  717. }
  718. else
  719. {
  720. FInfFileFromComponentId (pszInfId, deip.DriverPath);
  721. }
  722. }
  723. if (*deip.DriverPath)
  724. {
  725. TraceTag (ttidClassInst, "Class Installer was given %S "
  726. "as a filename for %S", deip.DriverPath,
  727. pszInfId);
  728. deip.Flags |= DI_ENUMSINGLEINF;
  729. if ((0 == _wcsicmp(L"netrasa.inf", deip.DriverPath)) ||
  730. (0 == _wcsicmp(L"netpsa.inf", deip.DriverPath)))
  731. {
  732. deip.Flags |= DI_NOFILECOPY;
  733. }
  734. }
  735. // For non-device classes, we need to allow excluded
  736. // drivers in order to get any driver list returned.
  737. if (!FIsEnumerated (guidClass))
  738. {
  739. deip.FlagsEx |= DI_FLAGSEX_ALLOWEXCLUDEDDRVS;
  740. }
  741. (VOID) HrSetupDiSetDeviceInstallParams (hdi, pdeid, &deip);
  742. }
  743. // Now we let Device Installer Api build a driver list based on
  744. // the information we have given so far. This will result in the
  745. // Inf file being found if it exists in the usual Inf directory
  746. //
  747. #ifdef ENABLETRACE
  748. CBenchmark bmrk;
  749. bmrk.Start ("SetupDiBuildDriverInfoList");
  750. #endif //ENABLETRACE
  751. hr = HrSetupDiBuildDriverInfoList (hdi, pdeid,
  752. SPDIT_COMPATDRIVER);
  753. #ifdef ENABLETRACE
  754. bmrk.Stop();
  755. TraceTag (ttidBenchmark, "%s : %s seconds",
  756. bmrk.SznDescription(), bmrk.SznBenchmarkSeconds (2));
  757. #endif //ENABLETRACE
  758. if (S_OK == hr)
  759. {
  760. // HrSetupDiSelectBestCompatDrv finds and selects the best
  761. // driver for the device.
  762. //
  763. SP_DRVINFO_DATA drid;
  764. hr = HrSetupDiSelectBestCompatDrv(hdi, pdeid);
  765. if (HRESULT_FROM_SETUPAPI(ERROR_NO_COMPAT_DRIVERS) == hr)
  766. {
  767. // Make the ERROR_NO_COMPAT_DRIVERS case look like what
  768. // it really means -- the requested component's driver
  769. // info (i.e. inf) could not be found.
  770. //
  771. hr = SPAPI_E_NO_DRIVER_SELECTED;
  772. }
  773. }
  774. else if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
  775. {
  776. // We couldn't find an inf file which means we cannot
  777. // selected the driver for this component.
  778. //
  779. hr = SPAPI_E_NO_DRIVER_SELECTED;
  780. }
  781. }
  782. // if anything failed, we should remove the device node we created
  783. if (FAILED(hr))
  784. {
  785. (VOID) SetupDiDeleteDeviceInfo (hdi, pdeid);
  786. }
  787. }
  788. TraceHr (ttidError, FAL, hr, FALSE, "HrCiGetDriverInfo");
  789. return hr;
  790. }
  791. //+--------------------------------------------------------------------------
  792. //
  793. // Function: HrCiGetClassAndInfFileOfInfId
  794. //
  795. // Purpose: Finds a component's class and inf file.
  796. //
  797. // Arguments:
  798. // pszInfId [in] The Id of the component as found in its Inf.
  799. // pClass [out] The class of the component.
  800. // pszInfFile [out] The filename of the component's inf
  801. // (must be _MAX_PATH long).
  802. //
  803. // Returns: HRESULT. S_OK if successful, error code otherwise.
  804. //
  805. // Author: billbe 16 Mar 1998
  806. //
  807. // Notes:
  808. //
  809. HRESULT
  810. HrCiGetClassAndInfFileOfInfId (
  811. IN PCWSTR pszInfId,
  812. OUT NETCLASS* pClass,
  813. OUT PWSTR pszInfFile) // Must be _MAX_PATH long
  814. {
  815. HRESULT hr;
  816. const COMPONENT_INFO* pCompInfo;
  817. HDEVINFO hdi;
  818. Assert (pszInfId && *pszInfId);
  819. Assert (pClass);
  820. Assert (pszInfFile);
  821. hr = S_OK;
  822. // First, try the fast route by seeing if it's in our internal map.
  823. //
  824. pCompInfo = PComponentInfoFromComponentId (pszInfId);
  825. if (pCompInfo)
  826. {
  827. *pClass = NetClassEnumFromGuid (*pCompInfo->pguidClass);
  828. if (FIsValidNetClass (*pClass))
  829. {
  830. wcsncpy (pszInfFile, pCompInfo->pszInfFile, _MAX_PATH);
  831. pszInfFile [_MAX_PATH - 1] = 0;
  832. }
  833. else
  834. {
  835. hr = SPAPI_E_INVALID_CLASS;
  836. }
  837. }
  838. else
  839. {
  840. // Create a device info list.
  841. //
  842. hr = HrSetupDiCreateDeviceInfoList (NULL, NULL, &hdi);
  843. if (S_OK == hr)
  844. {
  845. SP_DEVINFO_DATA deid;
  846. // Get the driver info for the component and set it as the
  847. // selected driver
  848. //
  849. hr = HrCiGetDriverInfo (hdi, &deid, GUID_NULL, pszInfId, NULL);
  850. if (S_OK == hr)
  851. {
  852. SP_DRVINFO_DATA drid;
  853. // Get the selected driver.
  854. //
  855. hr = HrSetupDiGetSelectedDriver (hdi, &deid, &drid);
  856. if (S_OK == hr)
  857. {
  858. // Set the class output parameter from the dev info data
  859. // structure (HrGetDriverInfo updates this field if a driver
  860. // was found)
  861. //
  862. *pClass = NetClassEnumFromGuid (deid.ClassGuid);
  863. if (!FIsValidNetClass (*pClass))
  864. {
  865. hr = SPAPI_E_INVALID_CLASS;
  866. }
  867. else
  868. {
  869. PSP_DRVINFO_DETAIL_DATA pdridd;
  870. // Now get the driver's detailed information
  871. //
  872. hr = HrCiGetDriverDetail (hdi, &deid, &drid,
  873. &pdridd);
  874. if (S_OK == hr)
  875. {
  876. // Get the inf filename and set the
  877. // output parameter.
  878. //
  879. wcsncpy (pszInfFile, pdridd->InfFileName,
  880. _MAX_PATH);
  881. pszInfFile[_MAX_PATH - 1] = 0;
  882. MemFree (pdridd);
  883. }
  884. }
  885. }
  886. }
  887. SetupDiDestroyDeviceInfoList (hdi);
  888. }
  889. }
  890. if (S_OK != hr)
  891. {
  892. *pClass = NC_INVALID;
  893. *pszInfFile = 0;
  894. }
  895. TraceHr (ttidError, FAL, hr, FALSE, "HrCiGetClassAndInfFileOfInfId");
  896. return hr;
  897. }
  898. //+--------------------------------------------------------------------------
  899. //
  900. // Function: HrCiGetDriverDetail
  901. //
  902. // Purpose: Creates and fills a PSP_DRVINFO_DETAIL_DATA structure
  903. // with detailed information about the pDevInfoData's
  904. // selected driver
  905. //
  906. // Arguments:
  907. // hdi [in] See Device Installer Api documentation for more info
  908. // pdeid [in] See Device Installer Api documentation for more info
  909. // This value is NULL for non-physical net
  910. // components.
  911. // pdrid [in] See Device Installer Api documentation for more info
  912. // ppdridd [out] See Device Installer Api documentation for more info
  913. //
  914. // Returns: HRESULT. S_OK if successful, error code otherwise
  915. //
  916. // Author: billbe 11 Mar 1997
  917. //
  918. // Notes:
  919. //
  920. HRESULT
  921. HrCiGetDriverDetail (
  922. IN HDEVINFO hdi,
  923. IN PSP_DEVINFO_DATA pdeid OPTIONAL,
  924. OUT PSP_DRVINFO_DATA pdrid,
  925. OUT PSP_DRVINFO_DETAIL_DATA* ppdridd)
  926. {
  927. Assert(IsValidHandle(hdi));
  928. Assert(pdrid);
  929. Assert(ppdridd);
  930. // initialize pdrid and set its cbSize field
  931. ZeroMemory (pdrid, sizeof (SP_DRVINFO_DATA));
  932. pdrid->cbSize = sizeof (SP_DRVINFO_DATA);
  933. HRESULT hr = S_OK;
  934. *ppdridd = NULL;
  935. // Get the selected driver for the component
  936. hr = HrSetupDiGetSelectedDriver (hdi, pdeid, pdrid);
  937. if (S_OK == hr)
  938. {
  939. // Get driver detail info
  940. hr = HrSetupDiGetDriverInfoDetail (hdi, pdeid, pdrid, ppdridd);
  941. }
  942. // clean up on failure
  943. if (FAILED(hr))
  944. {
  945. if (*ppdridd)
  946. {
  947. MemFree (*ppdridd);
  948. *ppdridd = NULL;
  949. }
  950. }
  951. TraceHr (ttidError, FAL, hr, FALSE, "HrCiGetDriverDetail");
  952. return hr;
  953. }
  954. //+--------------------------------------------------------------------------
  955. //
  956. // Function: HrCiRegSetComponentInformation
  957. //
  958. // Purpose: Stores component information under the instance key of
  959. // the component.
  960. //
  961. // Arguments:
  962. // hkeyInstance [in] Component's instance registry key.
  963. // pcii [in] Component's information to store in hkeyInstance.
  964. //
  965. // Returns: HRESULT. S_OK if successful, error code otherwise.
  966. //
  967. // Author: billbe 11 Mar 1997
  968. //
  969. // Notes:
  970. //
  971. HRESULT
  972. HrCiRegSetComponentInformation(
  973. IN HKEY hkeyInstance,
  974. IN COMPONENT_INSTALL_INFO* pcii)
  975. {
  976. Assert(hkeyInstance);
  977. Assert(pcii);
  978. HRESULT hr = S_OK;
  979. BOOL fIsEnumerated = FIsEnumerated (pcii->Class);
  980. // Store the characteristics, inf path, and main
  981. // install section for the component
  982. //
  983. hr = HrRegSetDword (hkeyInstance, L"Characteristics", pcii->dwCharacter);
  984. if (FAILED(hr))
  985. {
  986. goto exit;
  987. }
  988. if (!fIsEnumerated)
  989. {
  990. hr = HrRegSetSz (hkeyInstance, L"InfPath" /*REGSTR_VAL_INFPATH*/,
  991. pcii->pszInfFile);
  992. if (FAILED(hr))
  993. {
  994. goto exit;
  995. }
  996. hr = HrRegSetSz (hkeyInstance, L"InfSection"/*REGSTR_VAL_INFSECTION*/,
  997. pcii->pszSectionName);
  998. if (FAILED(hr))
  999. {
  1000. goto exit;
  1001. }
  1002. }
  1003. // For non-enumerated components, store description into the registry.
  1004. //
  1005. if (!fIsEnumerated)
  1006. {
  1007. hr = HrRegSetSz (hkeyInstance, L"Description", pcii->pszDescription);
  1008. if (FAILED(hr))
  1009. {
  1010. goto exit;
  1011. }
  1012. }
  1013. // If this component is already installed, then there is no need to write
  1014. // the following information
  1015. //
  1016. if (FIsEnumerated (pcii->Class) && !pcii->fPreviouslyInstalled &&
  1017. FIsPhysicalAdapter (pcii->Class, pcii->dwCharacter) &&
  1018. (InterfaceTypeUndefined != pcii->BusType))
  1019. {
  1020. hr = HrRegSetSzAsUlong (hkeyInstance, L"BusType",
  1021. pcii->BusType, c_nBase10);
  1022. if (FAILED(hr))
  1023. {
  1024. goto exit;
  1025. }
  1026. }
  1027. hr = HrRegSetSz (hkeyInstance, L"ComponentId", pcii->pszInfId);
  1028. exit:
  1029. TraceHr (ttidError, FAL, hr, FALSE, "HrCiRegSetComponentInformation");
  1030. return hr;
  1031. }
  1032. //+--------------------------------------------------------------------------
  1033. //
  1034. // Function: HrCiCreateInstanceKey
  1035. //
  1036. // Purpose: Creates an instance key for the component. For enumerated
  1037. // devices, this is
  1038. // HKLM\System\CCS\Control\Class\<net guid>\<instance id>
  1039. // For non-enumerated components, this is under
  1040. // HKLM\System\CCS\Control\Network\<Class Guid>\<Instance Guid>
  1041. //
  1042. // Arguments:
  1043. // pcii [inout] Component install info structure.
  1044. // phkeyInstance [out] The component's registry instance key.
  1045. //
  1046. // Returns: HRESULT
  1047. //
  1048. // Author: billbe 22 Mar 1997
  1049. //
  1050. // Notes:
  1051. //
  1052. HRESULT
  1053. HrCiCreateInstanceKey(
  1054. IN COMPONENT_INSTALL_INFO* pcii,
  1055. OUT HKEY* phkeyInstance)
  1056. {
  1057. Assert (pcii);
  1058. Assert (phkeyInstance);
  1059. Assert (FImplies (FIsEnumerated (pcii->Class),
  1060. IsValidHandle (pcii->hdi) && pcii->pdeid));
  1061. HRESULT hr = S_OK;
  1062. // initialize the HKEY parameter
  1063. *phkeyInstance = NULL;
  1064. // Create the instance key for this component under the
  1065. // Network\<net guid> tree. This will be the component's
  1066. // instance key for all but physical net class components. Their
  1067. // instance key is created by Device Installer Api and lives under the
  1068. // Pnp Net Class driver tree.
  1069. // If the object is an enumerated component then we let
  1070. // the Device Installer api do the work
  1071. //
  1072. if (FIsEnumerated (pcii->Class))
  1073. {
  1074. // We need to create the adapter's driver key under
  1075. // the Pnp Net Class Driver tree.
  1076. //
  1077. hr = HrSetupDiCreateDevRegKey (pcii->hdi,
  1078. pcii->pdeid, DICS_FLAG_GLOBAL, 0, DIREG_DRV,
  1079. NULL, NULL, phkeyInstance);
  1080. }
  1081. else
  1082. {
  1083. // Not a physical net adapter so the component key is
  1084. // the instance key
  1085. // First, create the instance GUID
  1086. hr = CoCreateGuid (&pcii->InstanceGuid);
  1087. // Now create the key
  1088. if (S_OK == hr)
  1089. {
  1090. WCHAR szInstanceKeyPath[_MAX_PATH];
  1091. CreateInstanceKeyPath (pcii->Class, pcii->InstanceGuid,
  1092. szInstanceKeyPath);
  1093. hr = HrRegCreateKeyEx (HKEY_LOCAL_MACHINE,
  1094. szInstanceKeyPath,
  1095. REG_OPTION_NON_VOLATILE,
  1096. KEY_ALL_ACCESS,
  1097. NULL,
  1098. phkeyInstance,
  1099. NULL);
  1100. }
  1101. }
  1102. TraceHr (ttidError, FAL, hr, FALSE, "HrCiCreateInstanceKey");
  1103. return hr;
  1104. }
  1105. //+--------------------------------------------------------------------------
  1106. //
  1107. // Function: HrCiGetPropertiesFromInf
  1108. //
  1109. // Purpose: Retrieves a set of the component's proerties from the inf
  1110. // file.
  1111. //
  1112. // Arguments:
  1113. // hinfFile [in] A handle to the component's inf file
  1114. // pcii [inout] The component info structure
  1115. // See compinfo.h for more info
  1116. //
  1117. // Returns: HRESULT. S_OK if successful, error code otherwise
  1118. //
  1119. // Author: billbe 14 Jun 1997
  1120. //
  1121. // Notes:
  1122. //
  1123. HRESULT
  1124. HrCiGetPropertiesFromInf (
  1125. IN HINF hinfFile,
  1126. IN OUT COMPONENT_INSTALL_INFO* pcii)
  1127. {
  1128. Assert (IsValidHandle (hinfFile));
  1129. Assert (pcii);
  1130. Assert (pcii->pszSectionName);
  1131. // Find the inf line that contains Characteristics and retrieve it
  1132. HRESULT hr = HrSetupGetFirstDword (hinfFile, pcii->pszSectionName,
  1133. L"Characteristics", &pcii->dwCharacter);
  1134. if ((S_OK == hr) &&
  1135. (FIsPhysicalAdapter(pcii->Class, pcii->dwCharacter)))
  1136. {
  1137. hr = HrCiGetBusInfoFromInf (hinfFile, pcii);
  1138. }
  1139. #ifdef DBG
  1140. else if (FAILED(hr))
  1141. {
  1142. TraceTag(ttidError, "Inf contains no Characteristics field");
  1143. }
  1144. #endif // DBG
  1145. TraceHr (ttidError, FAL, hr, FALSE, "HrCiGetPropertiesFromInf");
  1146. return hr;
  1147. }
  1148. //+--------------------------------------------------------------------------
  1149. //
  1150. // Function: HrCiIsInstalledComponent
  1151. //
  1152. // Purpose: Checks if the component is already installed
  1153. //
  1154. //
  1155. // Arguments:
  1156. // pcici [in] A structure containing the component information
  1157. // See compinst.h for definition
  1158. // phkey [out] The registry instance key of the adapter
  1159. // during inf processing. only set if fcn returns S_OK
  1160. //
  1161. // Returns: HRESULT - S_OK if the component is already installed
  1162. // S_FALSE if the component is not already installed
  1163. // A win32 converted error otherwise
  1164. //
  1165. // Author: billbe 17 Sep 1997
  1166. //
  1167. // Notes:
  1168. //
  1169. HRESULT
  1170. HrCiIsInstalledComponent (
  1171. IN COMPONENT_INSTALL_INFO* pcii,
  1172. OUT HKEY* phkey)
  1173. {
  1174. HRESULT hr;
  1175. Assert(pcii);
  1176. if (phkey)
  1177. {
  1178. *phkey = NULL;
  1179. }
  1180. // If this is an enumerated component, we just check for NetCfgInstanceId
  1181. // in the instance (driver) key.
  1182. //
  1183. if (FIsEnumerated (pcii->Class))
  1184. {
  1185. HKEY hkey;
  1186. hr = HrSetupDiOpenDevRegKey (pcii->hdi, pcii->pdeid, DICS_FLAG_GLOBAL,
  1187. 0, DIREG_DRV, KEY_ALL_ACCESS, &hkey);
  1188. if (S_OK == hr)
  1189. {
  1190. WCHAR szGuid[c_cchGuidWithTerm];
  1191. DWORD cbGuid = sizeof (szGuid);
  1192. hr = HrRegQuerySzBuffer (hkey, L"NetCfgInstanceId", szGuid,
  1193. &cbGuid);
  1194. if (S_OK == hr)
  1195. {
  1196. IIDFromString (szGuid, &pcii->InstanceGuid);
  1197. if (phkey)
  1198. {
  1199. *phkey = hkey;
  1200. }
  1201. }
  1202. else
  1203. {
  1204. RegCloseKey (hkey);
  1205. hr = S_FALSE;
  1206. }
  1207. }
  1208. else if ((SPAPI_E_KEY_DOES_NOT_EXIST == hr) ||
  1209. (SPAPI_E_DEVINFO_NOT_REGISTERED == hr))
  1210. {
  1211. TraceTag(ttidClassInst, "Component is not known by Net Config");
  1212. hr = S_FALSE;
  1213. }
  1214. }
  1215. else
  1216. {
  1217. // For non-enumerated components, we check the netcfg "config blob" to
  1218. // determine if this component is isntalled.
  1219. CNetConfig NetConfig;
  1220. hr = HrLoadNetworkConfigurationFromRegistry (KEY_READ, &NetConfig);
  1221. if (S_OK == hr)
  1222. {
  1223. CComponent* pComponent;
  1224. pComponent = NetConfig.Core.Components.
  1225. PFindComponentByInfId(pcii->pszInfId, NULL);
  1226. if (pComponent)
  1227. {
  1228. pcii->InstanceGuid = pComponent->m_InstanceGuid;
  1229. if (phkey)
  1230. {
  1231. hr = pComponent->HrOpenInstanceKey(KEY_ALL_ACCESS, phkey,
  1232. NULL, NULL);
  1233. }
  1234. }
  1235. else
  1236. {
  1237. hr = S_FALSE;
  1238. }
  1239. }
  1240. }
  1241. TraceHr (ttidError, FAL, hr, S_FALSE == hr, "HrCiIsInstalledComponent");
  1242. return hr;
  1243. }
  1244. //+--------------------------------------------------------------------------
  1245. //
  1246. // Function: HrCiCreateInstanceKeyAndProcessMainInfSection
  1247. //
  1248. // Purpose: Processes a component's main inf section and
  1249. // storing, in the registry, any extra information needed for
  1250. // component initialization
  1251. //
  1252. // Arguments:
  1253. // hinf [in] Handle to the component's inf file.
  1254. // pcii [inout] Will be filled with information about the
  1255. // component.
  1256. // phkey [out] Handle to the component's registry instance key.
  1257. //
  1258. //
  1259. // Returns: HRESULT. S_OK if successful, error code otherwise
  1260. //
  1261. // Author: billbe 15 Nov 1996
  1262. //
  1263. // Notes:
  1264. //
  1265. HRESULT
  1266. HrCiCreateInstanceKeyAndProcessMainInfSection(
  1267. IN HINF hinf,
  1268. IN COMPONENT_INSTALL_INFO* pcii,
  1269. OUT HKEY* phkey)
  1270. {
  1271. #if defined(REMOTE_BOOT)
  1272. GUID c_guidRemoteBoot;
  1273. static const WCHAR c_szRemoteBootAdapterGuid[] =
  1274. L"{54C7D140-09EF-11D1-B25A-F5FE627ED95E}";
  1275. DEFINE_GUID(c_guidRemoteBoot, 0x54c7d140, 0x09ef, 0x11d1, 0xb2, 0x5a, 0xf5, 0xfe, 0x62, 0x7e, 0xd9, 0x5e);
  1276. #endif // defined(REMOTE_BOOT)
  1277. Assert (IsValidHandle (hinf));
  1278. Assert (pcii);
  1279. Assert (phkey);
  1280. // The properties retrieved here will be written to the registry
  1281. // later.
  1282. HRESULT hr = HrCiGetPropertiesFromInf (hinf, pcii);
  1283. if (S_OK == hr)
  1284. {
  1285. BOOL fEnumerated = FIsEnumerated (pcii->Class);
  1286. // If this component is enumerated, then we need to know if it
  1287. // is a remote boot adapter.
  1288. if (fEnumerated)
  1289. {
  1290. Assert (IsValidHandle (pcii->hdi));
  1291. Assert (pcii->pdeid);
  1292. #if defined(REMOTE_BOOT)
  1293. // If this adapter is a remote boot adapter, then we have
  1294. // to use a pre-determined GUID
  1295. //
  1296. if (S_OK == HrIsRemoteBootAdapter(pcii->hdi, pcii->pdeid))
  1297. {
  1298. pcai->m_fRemoteBoot = TRUE;
  1299. pcii->InstanceGuid = c_guidRemoteBoot;
  1300. }
  1301. #endif // defined(REMOTE_BOOT)
  1302. }
  1303. // Is this a fresh install or a reinstall?
  1304. hr = HrCiIsInstalledComponent(pcii, phkey);
  1305. if (S_FALSE == hr)
  1306. {
  1307. hr = S_OK;
  1308. // Fresh install
  1309. //
  1310. if (S_OK == hr)
  1311. {
  1312. // For non-physical components, the relative key will
  1313. // be the driver instance key which is under the class
  1314. // branch of the Network key. Its form is
  1315. // <Class GUID>/<instance GUID>.
  1316. // For physical components, the key is under
  1317. // the Pnp class driver tree. The next call will
  1318. // create this key
  1319. hr = HrCiCreateInstanceKey(pcii, phkey);
  1320. if (fEnumerated)
  1321. {
  1322. // If we don't have an instance
  1323. // guid (i.e. not remote boot adapter),
  1324. // get one
  1325. if (GUID_NULL == pcii->InstanceGuid)
  1326. {
  1327. hr = CoCreateGuid(&pcii->InstanceGuid);
  1328. #ifdef ENABLETRACE
  1329. WCHAR szGuid[c_cchGuidWithTerm];
  1330. StringFromGUID2(pcii->InstanceGuid, szGuid,
  1331. c_cchGuidWithTerm);
  1332. TraceTag(ttidClassInst, "NetCfg Instance Guid %S "
  1333. "generated for %S",
  1334. szGuid,
  1335. pcii->pszInfId);
  1336. #endif // ENABLETRACE
  1337. }
  1338. }
  1339. }
  1340. }
  1341. else if (S_OK == hr)
  1342. {
  1343. // This component is being reinstalled
  1344. pcii->fPreviouslyInstalled = TRUE;
  1345. }
  1346. if (S_OK == hr)
  1347. {
  1348. // Now that the instance key is created, we need to run
  1349. // the main inf sections
  1350. //
  1351. hr = HrCiDoCompleteSectionInstall(hinf, *phkey,
  1352. pcii->pszSectionName,
  1353. pcii->hwndParent, fEnumerated);
  1354. // On failure of fresh installs, remove components
  1355. if (FAILED(hr) && !pcii->fPreviouslyInstalled)
  1356. {
  1357. if (!fEnumerated)
  1358. {
  1359. HrCiRemoveNonEnumeratedComponent (hinf, *phkey,
  1360. pcii->Class, pcii->InstanceGuid, NULL);
  1361. }
  1362. }
  1363. }
  1364. }
  1365. TraceHr (ttidError, FAL, hr, FALSE,
  1366. "HrCiCreateInstanceKeyAndProcessMainInfSection");
  1367. return hr;
  1368. }
  1369. //+--------------------------------------------------------------------------
  1370. //
  1371. // Function: HrCiDoOemFileCopyIfNeeded
  1372. //
  1373. // Purpose: Calls HrSetupCopyOemInf if strInfPath is not already in the
  1374. // inf directory. This will copy an Oem inf to the inf
  1375. // directory with a new name.
  1376. //
  1377. // Arguments:
  1378. // pszInfPath [in] Path to the inf file
  1379. // pszNewName [out] The new name of the copied inf file
  1380. //
  1381. // Returns: HRESULT. S_OK if successful, error code otherwise
  1382. //
  1383. // Author: billbe 15 May 1997
  1384. //
  1385. // Notes:
  1386. //
  1387. HRESULT
  1388. HrCiDoOemFileCopyIfNeeded(
  1389. IN PCWSTR pszInfPath,
  1390. OUT PWSTR pszNewName)
  1391. {
  1392. Assert (pszInfPath);
  1393. Assert (pszNewName);
  1394. HRESULT hr = S_OK;
  1395. WCHAR szInfDir[_MAX_PATH] = {0};
  1396. // fill buffer with path to %windir%
  1397. GetSystemWindowsDirectory (szInfDir, _MAX_PATH);
  1398. // the inf directory is %windir%\inf
  1399. //
  1400. wcscat (szInfDir, L"\\");
  1401. wcscat (szInfDir, L"Inf");
  1402. // Extract the directory from the filename
  1403. //
  1404. PWSTR pszEnd = wcsrchr (pszInfPath, L'\\');
  1405. DWORD cch;
  1406. if (pszEnd)
  1407. {
  1408. cch = (DWORD)(pszEnd - pszInfPath);
  1409. }
  1410. else
  1411. {
  1412. cch = wcslen (pszInfPath);
  1413. }
  1414. // if the inf is not already in the inf directory, copy it there
  1415. //
  1416. if ((cch != wcslen (szInfDir)) ||
  1417. (0 != _wcsnicmp (pszInfPath, szInfDir, cch)))
  1418. {
  1419. WCHAR szDestFilePath[_MAX_PATH];
  1420. PWSTR pszDestFilename;
  1421. hr = HrSetupCopyOemInfBuffer (pszInfPath, NULL, SPOST_PATH, 0,
  1422. szDestFilePath, _MAX_PATH, &pszDestFilename);
  1423. if (S_OK == hr)
  1424. {
  1425. wcscpy (pszNewName, pszDestFilename);
  1426. }
  1427. }
  1428. else
  1429. {
  1430. // The inf is already in the right directory so just copy the
  1431. // current filename component.
  1432. if (pszEnd)
  1433. {
  1434. wcscpy (pszNewName, pszEnd + 1);
  1435. }
  1436. else
  1437. {
  1438. wcscpy (pszNewName, pszInfPath);
  1439. }
  1440. }
  1441. TraceHr (ttidError, FAL, hr, FALSE, "HrCiDoOemFileCopyIfNeeded");
  1442. return hr;
  1443. }
  1444. //+--------------------------------------------------------------------------
  1445. //
  1446. // Function: HrCiInstallNonEnumeratedComponent
  1447. //
  1448. // Purpose: This function completes the installation of a non-enumerated
  1449. // component
  1450. //
  1451. // Arguments:
  1452. // hinf [in] SetupApi handle to an inf file
  1453. // hkey [in] The registry instance key of the adapter
  1454. // during inf processing.
  1455. // pcii [in] A structure containing the component information
  1456. //
  1457. // Returns: HRESULT. S_OK if successful, or error code otherwise
  1458. //
  1459. // Author: billbe 28 Apr 1997
  1460. //
  1461. // Notes:
  1462. //
  1463. HRESULT
  1464. HrCiInstallNonEnumeratedComponent (
  1465. IN HINF hinf,
  1466. IN HKEY hkey,
  1467. IN COMPONENT_INSTALL_INFO* pcii)
  1468. {
  1469. // Register the notification dll for this component,
  1470. // if it exists.
  1471. HRESULT hr = HrCiRegisterNotificationDll(hkey, CIRDF_REGISTER);
  1472. // Device Installer Api handles OEM files for
  1473. // enumerated components in InstallDevice
  1474. // Since this component is non-enumerated
  1475. // we need to handle any oem files
  1476. // manually.
  1477. //
  1478. // Copy the inf file if needed then store
  1479. // the new inf name
  1480. // Note: if the inf file does not need to
  1481. // be copied, the new name will be the
  1482. // old name without the directory info.
  1483. //
  1484. if (S_OK == hr)
  1485. {
  1486. WCHAR szNewName[_MAX_PATH];;
  1487. hr = HrCiDoOemFileCopyIfNeeded (pcii->pszInfFile, szNewName);
  1488. if (S_OK == hr)
  1489. {
  1490. // set the new path value in the registry.
  1491. hr = HrRegSetSz (hkey, REGSTR_VAL_INFPATH, szNewName);
  1492. if ((S_OK == hr) && (NC_NETCLIENT == pcii->Class))
  1493. {
  1494. // if this is a network client, do appropriate processing.
  1495. hr = HrCiAddNetProviderInfo (hinf, pcii->pszSectionName,
  1496. hkey, pcii->fPreviouslyInstalled);
  1497. }
  1498. }
  1499. }
  1500. // On failures of first time installs, remove the component.
  1501. //
  1502. if (FAILED(hr) && !pcii->fPreviouslyInstalled)
  1503. {
  1504. TraceTag (ttidClassInst, "Install canceled. Removing...");
  1505. (VOID) HrCiRemoveNonEnumeratedComponent (hinf, hkey, pcii->Class,
  1506. pcii->InstanceGuid, NULL);
  1507. }
  1508. TraceHr (ttidError, FAL, hr, FALSE, "HrCiInstallNonEnumeratedComponent");
  1509. return hr;
  1510. }
  1511. //+--------------------------------------------------------------------------
  1512. //
  1513. // Function: HrCiInstallComponentInternal
  1514. //
  1515. // Purpose: Installs a component
  1516. //
  1517. // Arguments:
  1518. // pcii [in, out] Will be filled with information about the
  1519. // component.
  1520. //
  1521. // Returns: HRESULT. S_OK if successful, error code otherwise
  1522. //
  1523. // Author: billbe 15 Nov 1996
  1524. //
  1525. // Notes:
  1526. //
  1527. HRESULT
  1528. HrCiInstallComponentInternal (
  1529. IN OUT COMPONENT_INSTALL_INFO* pcii)
  1530. {
  1531. HRESULT hr = S_OK;
  1532. HINF hinfInstallFile = NULL;
  1533. HKEY hkeyInstance = NULL;
  1534. TraceTag (ttidClassInst, "Installing %S from %S",
  1535. pcii->pszInfId, pcii->pszInfFile);
  1536. // Open the component's inf file.
  1537. hr = HrSetupOpenInfFile (pcii->pszInfFile, NULL, INF_STYLE_WIN4,
  1538. NULL, &hinfInstallFile);
  1539. // Continue only if we have opened the file.
  1540. if (S_OK == hr)
  1541. {
  1542. // The section we have currently might need to be decorated
  1543. // with OS and Platform specific suffixes. The next call
  1544. // will return the actual decorated section name or our
  1545. // current section name if the decorated one does not exist.
  1546. //
  1547. // Store the original section name pointer so we can restore
  1548. // it after we have finished.
  1549. PCWSTR pszOriginalSectionName = pcii->pszSectionName;
  1550. // Now we get the actual section name.
  1551. //
  1552. WCHAR szActualSection[_MAX_PATH];
  1553. hr = HrSetupDiGetActualSectionToInstallWithBuffer (hinfInstallFile,
  1554. pcii->pszSectionName, szActualSection, _MAX_PATH, NULL,
  1555. NULL);
  1556. if (S_OK == hr)
  1557. {
  1558. pcii->pszSectionName = szActualSection;
  1559. hr = HrCiCreateInstanceKeyAndProcessMainInfSection (
  1560. hinfInstallFile, pcii, &hkeyInstance);
  1561. if (S_OK == hr)
  1562. {
  1563. // Set up the registry with the component info.
  1564. hr = HrCiRegSetComponentInformation (hkeyInstance, pcii);
  1565. if (S_OK == hr)
  1566. {
  1567. // We do different things during install based
  1568. // on whether PnP knows about the component
  1569. // (i.e. enumerated) or not.
  1570. if (FIsEnumerated (pcii->Class))
  1571. {
  1572. hr = HrCiInstallEnumeratedComponent (
  1573. hinfInstallFile, hkeyInstance, *pcii);
  1574. }
  1575. else
  1576. {
  1577. hr = HrCiInstallNonEnumeratedComponent (
  1578. hinfInstallFile, hkeyInstance, pcii);
  1579. }
  1580. }
  1581. RegSafeCloseKey(hkeyInstance);
  1582. }
  1583. // set the section name back
  1584. pcii->pszSectionName = pszOriginalSectionName;
  1585. }
  1586. SetupCloseInfFile(hinfInstallFile);
  1587. }
  1588. TraceHr (ttidError, FAL, hr, FALSE, "HrCiInstallComponentInternal");
  1589. return hr;
  1590. }
  1591. //+--------------------------------------------------------------------------
  1592. //
  1593. // Function: HrCiCallClassInstallerToInstallComponent
  1594. //
  1595. // Purpose: This function invokes the class installer to install an
  1596. // enumerated component.
  1597. //
  1598. // Arguments:
  1599. // hdi [in] See Device Installer docs for more info.
  1600. // pdeid [in]
  1601. //
  1602. // Returns: HRESULT. S_OK if successful, or error code otherwise
  1603. //
  1604. // Author: billbe 28 Apr 1997
  1605. //
  1606. // Notes: This should only be called while the INetCfg lock is held.
  1607. //
  1608. HRESULT
  1609. HrCiCallClassInstallerToInstallComponent(HDEVINFO hdi, PSP_DEVINFO_DATA pdeid)
  1610. {
  1611. HRESULT hr;
  1612. Assert(IsValidHandle(hdi));
  1613. Assert(pdeid);
  1614. // We need to register the device before we do any work on it.
  1615. hr = HrSetupDiCallClassInstaller (DIF_REGISTERDEVICE, hdi, pdeid);
  1616. if (S_OK == hr)
  1617. {
  1618. // Check if we can install of this component. i.e. is the inf
  1619. // a valid Windows 2000 inf.
  1620. hr = HrSetupDiCallClassInstaller (DIF_ALLOW_INSTALL, hdi, pdeid);
  1621. if (S_OK == hr)
  1622. {
  1623. BOOL fFileCopy = TRUE;
  1624. SP_DEVINSTALL_PARAMS deip;
  1625. // Fu fu fu: SetupApi is ignoring DI_NOFILECOPY so we'll overcome
  1626. // their shortcomings and do it ourselves.
  1627. //
  1628. hr = HrSetupDiGetDeviceInstallParams (hdi, pdeid, &deip);
  1629. if (S_OK == hr)
  1630. {
  1631. if (deip.Flags & DI_NOFILECOPY)
  1632. {
  1633. fFileCopy = FALSE;
  1634. }
  1635. }
  1636. if (fFileCopy)
  1637. {
  1638. // Install needed files.
  1639. hr = HrSetupDiCallClassInstaller (DIF_INSTALLDEVICEFILES, hdi,
  1640. pdeid);
  1641. }
  1642. if (S_OK == hr)
  1643. {
  1644. // Now that all files have been copied, we need to set the
  1645. // no file copy flag. Otherwise, setupapi will try to copy
  1646. // files at each dif code. This results in multiple (1 per
  1647. // dif code) unsigned driver popups if the driver was
  1648. // unsigned.
  1649. // We'll only do this if the no copy file flag wasn't already
  1650. // set. i.e. if fFileCopy is TRUE.
  1651. //
  1652. if (fFileCopy)
  1653. {
  1654. // An error here isn't bad enough to stop installation.
  1655. //
  1656. HRESULT hrTemp;
  1657. hrTemp = HrSetupDiSetDeipFlags (hdi, pdeid, DI_NOFILECOPY,
  1658. SDDFT_FLAGS, SDFBO_OR);
  1659. TraceHr (ttidError, FAL, hrTemp, FALSE,
  1660. "HrCiCallClassInstallerToInstallComponent: "
  1661. "HrSetupDiSetDeipFlags");
  1662. }
  1663. // Device co-installers need to be registered at this point
  1664. // so they can do work.
  1665. hr = HrSetupDiCallClassInstaller (DIF_REGISTER_COINSTALLERS,
  1666. hdi, pdeid);
  1667. if (S_OK == hr)
  1668. {
  1669. hr = HrSetupDiCallClassInstaller (DIF_INSTALLINTERFACES,
  1670. hdi, pdeid);
  1671. if (S_OK == hr)
  1672. {
  1673. hr = HrSetupDiCallClassInstaller (DIF_INSTALLDEVICE,
  1674. hdi, pdeid);
  1675. }
  1676. }
  1677. }
  1678. }
  1679. // If we failed for any reason, we need to clean up since
  1680. // we initiated this install.
  1681. if (FAILED(hr))
  1682. {
  1683. ADAPTER_REMOVE_PARAMS arp;
  1684. arp.fBadDevInst = TRUE;
  1685. arp.fNotifyINetCfg = FALSE;
  1686. CiSetReservedField (hdi, pdeid, &arp);
  1687. HrSetupDiCallClassInstaller (DIF_REMOVE, hdi, pdeid);
  1688. CiClearReservedField (hdi, pdeid);
  1689. }
  1690. }
  1691. TraceHr (ttidError, FAL, hr, FALSE,
  1692. "HrCiCallClassInstallerToInstallComponent");
  1693. return hr;
  1694. }
  1695. //+--------------------------------------------------------------------------
  1696. //
  1697. // Function: HrCiInstallComponent
  1698. //
  1699. // Purpose: This function takes a Network Component's Id and its class
  1700. // guid and gathers the information needed by
  1701. // HrCiInstallComponent. Since it is called from INetCfg, we
  1702. // have the write lock
  1703. //
  1704. // Arguments:
  1705. // Params [in] Component install params. See install.h
  1706. // ppComponent [out] A created CComponent representing the installed
  1707. // component.
  1708. // pdwNewCharacter [out] Optional pointer to a DWORD to receive the
  1709. // characteristics of the component.
  1710. //
  1711. // Returns: HRESULT. S_OK is successful, NETCFG_S_REBOOT if a reboot is
  1712. // needed to start the device, or an error code
  1713. //
  1714. // Author: billbe 16 Mar 1997
  1715. //
  1716. // Notes:
  1717. //
  1718. HRESULT
  1719. HrCiInstallComponent (
  1720. IN const COMPONENT_INSTALL_PARAMS& Params,
  1721. OUT CComponent** ppComponent,
  1722. OUT DWORD* pdwNewCharacter)
  1723. {
  1724. Assert (FIsValidNetClass (Params.Class));
  1725. Assert (Params.pszInfId && *Params.pszInfId);
  1726. Assert (!Params.pComponent);
  1727. HRESULT hr = S_OK;
  1728. HDEVINFO hdi = NULL;
  1729. SP_DEVINFO_DATA deid;
  1730. const GUID* pguidClass = MAP_NETCLASS_TO_GUID[Params.Class];
  1731. if (ppComponent)
  1732. {
  1733. *ppComponent = NULL;
  1734. }
  1735. if (pdwNewCharacter)
  1736. {
  1737. *pdwNewCharacter = 0;
  1738. }
  1739. // If we're about to install the component, it better not be in
  1740. // lockdown.
  1741. //
  1742. Assert (!FIsComponentLockedDown (Params.pszInfId));
  1743. // First create a device info set
  1744. hr = HrSetupDiCreateDeviceInfoList (pguidClass, NULL, &hdi);
  1745. if (S_OK == hr)
  1746. {
  1747. // This will create an node in the enum tree for this component.
  1748. // If it is enumerated, we will register it which will make
  1749. // it persist. If non-enumerated, we will not register it and
  1750. // the node will be deleted in the call to SetDiDestroyDeviceInfoList.
  1751. //
  1752. hr = HrCiGetDriverInfo (hdi, &deid, *pguidClass,
  1753. Params.pszInfId, Params.pszInfFile);
  1754. // Get the driver info for the component
  1755. if (S_OK == hr)
  1756. {
  1757. BASIC_COMPONENT_DATA Data = {0};
  1758. Data.Class = Params.Class;
  1759. Data.pszInfId = Params.pszInfId;
  1760. if (FIsEnumerated (Params.Class))
  1761. {
  1762. // If the component is enumerated, we will need a place to
  1763. // store its pnp id.
  1764. WCHAR szPnpId[MAX_DEVICE_ID_LEN];
  1765. ADAPTER_OUT_PARAMS AdapterOutParams;
  1766. ZeroMemory (&AdapterOutParams, sizeof(AdapterOutParams));
  1767. // Net class components have to go through the device
  1768. // installer hook (aka NetClassInstaller)
  1769. //
  1770. if (FInSystemSetup())
  1771. {
  1772. // if we are in GUI mode we need to make the
  1773. // device install quiet and always copy from
  1774. // the source location even if the files are
  1775. // already present. We also need to set
  1776. // the in system setup flag. This is what
  1777. // syssetup would do if it initiated the install
  1778. // so INetCfg initiated installs must do the same.
  1779. //
  1780. // We should also set the parent hwnd.
  1781. //
  1782. SP_DEVINSTALL_PARAMS deip;
  1783. HRESULT hrTemp = HrSetupDiGetDeviceInstallParams (
  1784. hdi, &deid, &deip);
  1785. if (S_OK == hr)
  1786. {
  1787. deip.hwndParent = Params.hwndParent;
  1788. deip.Flags |= DI_QUIETINSTALL | DI_FORCECOPY;
  1789. deip.FlagsEx |= DI_FLAGSEX_IN_SYSTEM_SETUP;
  1790. hrTemp = HrSetupDiSetDeviceInstallParams (
  1791. hdi, &deid, &deip);
  1792. }
  1793. TraceHr (ttidError, FAL, hrTemp, FALSE, "Error "
  1794. "getting and setting device params.");
  1795. }
  1796. CiSetReservedField (hdi, &deid, &AdapterOutParams);
  1797. // Officially call the class installer to install
  1798. // this device
  1799. //
  1800. hr = HrCiCallClassInstallerToInstallComponent (hdi, &deid);
  1801. CiClearReservedField (hdi, &deid);
  1802. Data.dwCharacter = AdapterOutParams.dwCharacter;
  1803. Data.InstanceGuid = AdapterOutParams.InstanceGuid;
  1804. if (S_OK == hr)
  1805. {
  1806. hr = HrSetupDiGetDeviceInstanceId (hdi, &deid, szPnpId,
  1807. MAX_DEVICE_ID_LEN, NULL);
  1808. if (S_OK == hr)
  1809. {
  1810. Data.pszPnpId = szPnpId;
  1811. }
  1812. }
  1813. }
  1814. else // Non-net class components
  1815. {
  1816. COMPONENT_INSTALL_INFO cii;
  1817. PSP_DRVINFO_DETAIL_DATA pdridd = NULL;
  1818. SP_DRVINFO_DATA drid;
  1819. // Now get the driver's detailed information
  1820. hr = HrCiGetDriverDetail (hdi, &deid, &drid, &pdridd);
  1821. if (S_OK == hr)
  1822. {
  1823. ZeroMemory (&cii, sizeof(cii));
  1824. cii.Class = Params.Class;
  1825. cii.pszInfId = Params.pszInfId;
  1826. cii.pszInfFile = pdridd->InfFileName;
  1827. cii.hwndParent = Params.hwndParent;
  1828. cii.pszDescription = drid.Description;
  1829. cii.pszSectionName = pdridd->SectionName;
  1830. HINF hinf;
  1831. hr = HrSetupOpenInfFile (pdridd->InfFileName, NULL,
  1832. INF_STYLE_WIN4, NULL, &hinf);
  1833. if (S_OK == hr)
  1834. {
  1835. // Make sure this is an NT5 inf network inf
  1836. //
  1837. hr = HrSetupIsValidNt5Inf (hinf);
  1838. SetupCloseInfFile (hinf);
  1839. }
  1840. if (S_OK == hr)
  1841. {
  1842. hr = HrCiInstallComponentInternal (&cii);
  1843. if (S_OK == hr)
  1844. {
  1845. Data.InstanceGuid = cii.InstanceGuid;
  1846. Data.dwCharacter = cii.dwCharacter;
  1847. }
  1848. }
  1849. MemFree (pdridd);
  1850. }
  1851. }
  1852. if ((S_OK == hr) && ppComponent) // !previously installed
  1853. {
  1854. CComponent* pComponent;
  1855. hr = CComponent::HrCreateInstance (
  1856. &Data,
  1857. CCI_ENSURE_EXTERNAL_DATA_LOADED,
  1858. Params.pOboToken,
  1859. &pComponent);
  1860. if (S_OK == hr)
  1861. {
  1862. *ppComponent = pComponent;
  1863. }
  1864. }
  1865. if ((S_OK == hr) && pdwNewCharacter)
  1866. {
  1867. *pdwNewCharacter = Data.dwCharacter;
  1868. }
  1869. }
  1870. SetupDiDestroyDeviceInfoList(hdi);
  1871. }
  1872. #ifdef ENABLETRACE
  1873. if (S_OK == hr)
  1874. {
  1875. TraceTag(ttidClassInst, "Component now installed!");
  1876. }
  1877. #endif //ENABLETRACE
  1878. TraceHr (ttidError, FAL, hr, FALSE,
  1879. "HrCiInstallComponent (%S)", Params.pszInfId);
  1880. return hr;
  1881. }
  1882. //+--------------------------------------------------------------------------
  1883. //
  1884. // Function: SetBadDriverFlagIfNeededInList
  1885. //
  1886. // Purpose: Enumerates a driver list setting the DNF_BAD_DRIVER flag
  1887. // in every node that has a DNF_EXCLUDEFROMLIST flag.
  1888. //
  1889. // Arguments:
  1890. // hdi [in] See Device Installer Api documentaion for details
  1891. //
  1892. // Returns: HRESULT. S_OK
  1893. //
  1894. // Author: billbe 24 Nov 1998
  1895. //
  1896. // Notes: SetupDi forces us to use the DNF_BAD_DRIVER flag for non-netdevice
  1897. // classes if we want to exclude them from the select device dialog.
  1898. // This means to non-netclass components that
  1899. // DNF_BAD_DRIVER = DNF_EXCLUDEFROMLIST.
  1900. //
  1901. VOID
  1902. SetBadDriverFlagIfNeededInList(HDEVINFO hdi)
  1903. {
  1904. Assert(IsValidHandle(hdi));
  1905. HRESULT hr = S_OK;
  1906. SP_DRVINSTALL_PARAMS drip;
  1907. SP_DRVINFO_DATA drid;
  1908. DWORD dwIndex = 0;
  1909. // Enumerate each driver in hdi
  1910. while (S_OK == (hr = HrSetupDiEnumDriverInfo(hdi, NULL,
  1911. SPDIT_CLASSDRIVER, dwIndex++, &drid)))
  1912. {
  1913. hr = HrSetupDiGetDriverInstallParams(hdi, NULL, &drid, &drip);
  1914. if (S_OK == hr)
  1915. {
  1916. // If the driver already has the bad driver flag set,
  1917. // go on to the next one.
  1918. if (drip.Flags & DNF_BAD_DRIVER)
  1919. {
  1920. continue;
  1921. }
  1922. // If the driver has the exclude flag set, then set the
  1923. // bad driver flag.
  1924. if (drip.Flags & DNF_EXCLUDEFROMLIST)
  1925. {
  1926. drip.Flags |= DNF_BAD_DRIVER;
  1927. (VOID) HrSetupDiSetDriverInstallParams(hdi, NULL, &drid,
  1928. &drip);
  1929. }
  1930. }
  1931. }
  1932. if (HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr)
  1933. {
  1934. hr = S_OK;
  1935. }
  1936. TraceHr (ttidError, FAL, hr, FALSE, "SetBadDriverFlagIfNeededInList");
  1937. }
  1938. //+--------------------------------------------------------------------------
  1939. //
  1940. // Function: HrCiExcludeNonNetClassDriverFromSelectUsingInfId
  1941. //
  1942. // Purpose: Locates a driver in a driver list and sets its exclude from
  1943. // select flag.
  1944. //
  1945. // Arguments:
  1946. // hdi [in] See Device Installer Api documentaion for details
  1947. // pszInfId [in] The INF id of the component to exclude
  1948. //
  1949. // Returns: HRESULT. S_OK
  1950. //
  1951. // Author: billbe 29 Oct 1998
  1952. //
  1953. // Notes:
  1954. //
  1955. HRESULT
  1956. HrCiExcludeNonNetClassDriverFromSelectUsingInfId(
  1957. IN HDEVINFO hdi,
  1958. IN PCWSTR pszInfId)
  1959. {
  1960. Assert(IsValidHandle(hdi));
  1961. Assert(pszInfId);
  1962. HRESULT hr = S_OK;
  1963. SP_DRVINSTALL_PARAMS drip;
  1964. SP_DRVINFO_DATA drid;
  1965. PSP_DRVINFO_DETAIL_DATA pdridd;
  1966. DWORD dwIndex = 0;
  1967. // Enumerate each driver in hdi
  1968. while (S_OK == (hr = HrSetupDiEnumDriverInfo (hdi, NULL,
  1969. SPDIT_CLASSDRIVER, dwIndex++, &drid)))
  1970. {
  1971. (VOID) HrSetupDiGetDriverInstallParams (hdi, NULL, &drid, &drip);
  1972. // If the driver is already excluded for some other reason
  1973. // don't bother trying to determine if it should be excluded.
  1974. // Note that setupdi forces us to use DNF_BAD_DRIVER to exclude
  1975. // non-device drivers rather than using DNF_EXCLUDEFROMLIST.
  1976. if (drip.Flags & DNF_BAD_DRIVER)
  1977. {
  1978. continue;
  1979. }
  1980. // Get driver detail info
  1981. hr = HrSetupDiGetDriverInfoDetail (hdi, NULL, &drid, &pdridd);
  1982. if (S_OK == hr)
  1983. {
  1984. // If the IDs match, exclude it from the dialog
  1985. //
  1986. if (0 == lstrcmpiW (pdridd->HardwareID, pszInfId))
  1987. {
  1988. // Non-device drivers can't use DNF_EXCLUDEFROMLIST
  1989. // and must use DNF_BAD_DRIVER.
  1990. drip.Flags |= DNF_BAD_DRIVER;
  1991. (VOID) HrSetupDiSetDriverInstallParams (hdi, NULL,
  1992. &drid, &drip);
  1993. }
  1994. MemFree (pdridd);
  1995. }
  1996. }
  1997. if (HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr)
  1998. {
  1999. hr = S_OK;
  2000. }
  2001. TraceHr (ttidError, FAL, hr, FALSE,
  2002. "HrCiExcludeNonNetClassDriverFromSelectUsingInfId");
  2003. return hr;
  2004. }
  2005. //+---------------------------------------------------------------------------
  2006. //
  2007. // Function: ExcludeLockedDownComponents
  2008. //
  2009. // Purpose: A callback function compatible with EnumLockedDownComponents
  2010. // that is used to exclude locked down components from
  2011. // selection. Called from HrCiPrepareSelectDeviceDialog.
  2012. // This call back is called for each locked down component.
  2013. //
  2014. // Arguments:
  2015. // pszInfId [in] the INF ID to exclude.
  2016. // pvCallerData [in] the HDEVINFO cast to PVOID
  2017. //
  2018. // Returns: nothing
  2019. //
  2020. // Author: shaunco 24 May 1999
  2021. //
  2022. // Notes: The callback interface was chosen so that the class installer
  2023. // is not burdended with the details of how/where the locked
  2024. // down components are implemented.
  2025. //
  2026. VOID
  2027. CALLBACK
  2028. ExcludeLockedDownComponents (
  2029. IN PCWSTR pszInfId,
  2030. IN PVOID pvCallerData)
  2031. {
  2032. Assert (pszInfId && *pszInfId);
  2033. Assert (pvCallerData);
  2034. HDEVINFO hdi = (HDEVINFO)pvCallerData;
  2035. HrCiExcludeNonNetClassDriverFromSelectUsingInfId (hdi, pszInfId);
  2036. }
  2037. //+--------------------------------------------------------------------------
  2038. //
  2039. // Function: HrCiBuildExcludedDriverList
  2040. //
  2041. // Purpose: Non-Net class components can only be installed once
  2042. // So we need to iterate through the installed
  2043. // components, find their matching driver node in
  2044. // a Device Installer Api built driver list for the class,
  2045. // and set their exclude from select flag. This list
  2046. // will then be given to SetupDiSelectDevice which
  2047. // will not display the nodes with the exclude flag set.
  2048. //
  2049. // Arguments:
  2050. // hdi [in] See Device Installer Api documentaion for details
  2051. // guidClass [in] The class of components to build a driver list for
  2052. // pNetCfg [out] The current network configuration (i.e. what is
  2053. // installed).
  2054. //
  2055. // Returns: HRESULT. S_OK
  2056. //
  2057. // Author: billbe 10 Dec 1996
  2058. //
  2059. // Notes: Device Installer Api builds the driver list by rummaging
  2060. // through the inf directory and finding the components
  2061. // that are in files with the same class guid as the
  2062. // HDEVINFO. This is the same processing done
  2063. // in SetupDiSelectDevice, but the process is
  2064. // not repeated twice because we will give the
  2065. // list we built here to SetupDiSelectDevice.
  2066. //
  2067. HRESULT
  2068. HrCiBuildExcludedDriverList(
  2069. IN HDEVINFO hdi,
  2070. IN NETCLASS Class,
  2071. IN CNetConfig* pNetConfig)
  2072. {
  2073. HRESULT hr;
  2074. Assert(IsValidHandle(hdi));
  2075. Assert(pNetConfig);
  2076. // This might take some time. We are doing the same work as
  2077. // SetupDiSelectDevice would do. When we are done, we will
  2078. // hand the driver list to SetupDiSelectDevice so it won't
  2079. // need to rummage through the inf directory
  2080. //
  2081. CWaitCursor wc;
  2082. // For non-device classes, we need to allow excluded drivers
  2083. // in order to get a list returned.
  2084. hr = HrSetupDiSetDeipFlags(hdi, NULL,
  2085. DI_FLAGSEX_ALLOWEXCLUDEDDRVS,
  2086. SDDFT_FLAGSEX, SDFBO_OR);
  2087. if (S_OK == hr)
  2088. {
  2089. #ifdef ENABLETRACE
  2090. CBenchmark bmrk;
  2091. bmrk.Start("SetupDiBuildDriverInfoList");
  2092. #endif //ENABLETRACE
  2093. hr = HrSetupDiBuildDriverInfoList(hdi, NULL, SPDIT_CLASSDRIVER);
  2094. #ifdef ENABLETRACE
  2095. bmrk.Stop();
  2096. TraceTag(ttidBenchmark, "%s : %s seconds",
  2097. bmrk.SznDescription(), bmrk.SznBenchmarkSeconds(2));
  2098. #endif //ENABLETRACE
  2099. }
  2100. // Go through the network configuration and hide already installed
  2101. // components. Note: We only do this the first time. We show installed
  2102. // components if the user selects Have Disk on the dialog.
  2103. CComponent* pComponent;
  2104. CComponentList::const_iterator iter;
  2105. for (iter = pNetConfig->Core.Components.begin();
  2106. iter != pNetConfig->Core.Components.end();
  2107. iter++)
  2108. {
  2109. pComponent = *iter;
  2110. Assert (pComponent);
  2111. if (Class == pComponent->Class())
  2112. {
  2113. // Hide the driver
  2114. hr = HrCiExcludeNonNetClassDriverFromSelectUsingInfId(
  2115. hdi, pComponent->m_pszInfId);
  2116. }
  2117. }
  2118. TraceHr (ttidError, FAL, hr, FALSE, "HrCiBuildExcludedDriverList");
  2119. return hr;
  2120. }
  2121. //+--------------------------------------------------------------------------
  2122. //
  2123. // Function: HrCiSelectComponent
  2124. //
  2125. // Purpose: This function displays the Select Device dialog for the
  2126. // class of components specified by guidClass. Once the
  2127. // component has been selected, it is installed.. Since
  2128. // this fcn is called from INetCfg, we have the write lock.
  2129. //
  2130. // Arguments:
  2131. // Class [in] The class of components to display in the
  2132. // Select Device dialog
  2133. // hwndParent [in] The HWND of the parent window, used to display
  2134. // the UI
  2135. // pcfi [in] A structure used to determine what
  2136. // components should be filtered out of
  2137. // the select dialog (defined in netcfg.h)
  2138. // ppParams [out] Params used to install the component.
  2139. //
  2140. // Returns: HRESULT. S_OK if successful, S_FALSE if the component
  2141. // selected is being reinstalled instead of fresh
  2142. // installed, an error code otherwise
  2143. //
  2144. // Author: billbe 11 Nov 1996
  2145. //
  2146. // Notes: Filtering is only performed when selecting protocols,
  2147. // services, and clients.
  2148. //
  2149. HRESULT
  2150. HrCiSelectComponent(
  2151. IN NETCLASS Class,
  2152. IN HWND hwndParent,
  2153. IN const CI_FILTER_INFO* pcfi,
  2154. OUT COMPONENT_INSTALL_PARAMS** ppParams)
  2155. {
  2156. Assert (ppParams);
  2157. Assert (!FIsEnumerated (Class));
  2158. HRESULT hr;
  2159. HDEVINFO hdi;
  2160. // We need to create a DeviceInfoSet item to use the SelectDevice dialog.
  2161. hr = HrSetupDiCreateDeviceInfoList(
  2162. MAP_NETCLASS_TO_GUID[Class], hwndParent, &hdi);
  2163. if (S_OK == hr)
  2164. {
  2165. // call the class installer to bring up the select device dialog
  2166. // for enumerated components. This will notify any coinstallers
  2167. //
  2168. // This will be a map of component ids to instance guids
  2169. // for all installed components of Class.
  2170. CNetConfig NetConfig;
  2171. hr = HrLoadNetworkConfigurationFromRegistry (KEY_READ, &NetConfig);
  2172. if (S_OK == hr)
  2173. {
  2174. hr = HrCiBuildExcludedDriverList (hdi, Class, &NetConfig);
  2175. }
  2176. if (S_OK == hr)
  2177. {
  2178. // Store the filter info in the hdi
  2179. CiSetReservedField(hdi, NULL, pcfi);
  2180. // We want the Have disk button, but if the call fails we can
  2181. // still continue
  2182. (VOID) HrSetupDiSetDeipFlags(hdi, NULL, DI_SHOWOEM,
  2183. SDDFT_FLAGS, SDFBO_OR);
  2184. // Bring up the dialog
  2185. hr = HrSetupDiCallClassInstaller(DIF_SELECTDEVICE, hdi, NULL);
  2186. if (S_OK == hr)
  2187. {
  2188. SP_DRVINFO_DATA drid;
  2189. PSP_DRVINFO_DETAIL_DATA pdridd;
  2190. // Now get the driver's detailed information
  2191. hr = HrCiGetDriverDetail (hdi, NULL, &drid, &pdridd);
  2192. if (S_OK == hr)
  2193. {
  2194. DWORD cbInfId = CbOfSzAndTerm(pdridd->HardwareID);
  2195. DWORD cbInfFile = CbOfSzAndTerm(pdridd->InfFileName);
  2196. // Create a component install params structure so we
  2197. // can install the component.
  2198. hr = E_OUTOFMEMORY;
  2199. *ppParams = new (extrabytes, cbInfId + cbInfFile)
  2200. COMPONENT_INSTALL_PARAMS;
  2201. if (*ppParams)
  2202. {
  2203. ZeroMemory (*ppParams,
  2204. sizeof (COMPONENT_INSTALL_PARAMS));
  2205. (*ppParams)->Class = Class;
  2206. (*ppParams)->hwndParent = hwndParent;
  2207. (*ppParams)->pszInfId = (PCWSTR)(*ppParams + 1);
  2208. wcscpy ((PWSTR)(*ppParams)->pszInfId,
  2209. pdridd->HardwareID);
  2210. (*ppParams)->pszInfFile =
  2211. (PCWSTR)((BYTE*)(*ppParams)->pszInfId +
  2212. cbInfId);
  2213. wcscpy ((PWSTR)(*ppParams)->pszInfFile,
  2214. pdridd->InfFileName);
  2215. hr = S_OK;
  2216. }
  2217. MemFree (pdridd);
  2218. }
  2219. }
  2220. // Clear the field so we don't try to destroy it later
  2221. // via DIF_DESTROYPRIVATEDATA
  2222. CiClearReservedField(hdi, NULL);
  2223. }
  2224. SetupDiDestroyDeviceInfoList(hdi);
  2225. }
  2226. TraceHr (ttidError, FAL, hr, HRESULT_FROM_WIN32(ERROR_CANCELLED) == hr,
  2227. "HrCiSelectComponent");
  2228. return hr;
  2229. }
  2230. //+--------------------------------------------------------------------------
  2231. //
  2232. // Function: HrCiHideIrrelevantRasProtocols
  2233. //
  2234. // Purpose: Hides protocols from the SelectDevice dialog that RAS does
  2235. // not interact with.
  2236. //
  2237. // Arguments:
  2238. // hdi [in] Contains a list of available drivers.
  2239. // See Device Installer Api documentation for
  2240. // more info
  2241. // eFilter [in] Either FC_RASSRV or FC_RASCLI.
  2242. //
  2243. // Returns: HRESULT. S_OK if successful, error code otherwise
  2244. //
  2245. // Author: billbe 18 May 1998
  2246. //
  2247. // Notes:
  2248. //
  2249. HRESULT
  2250. HrCiHideIrrelevantRasProtocols (
  2251. IN HDEVINFO hdi,
  2252. IN CI_FILTER_COMPONENT eFilter)
  2253. {
  2254. DWORD dwIndex = 0;
  2255. SP_DRVINFO_DATA drid;
  2256. SP_DRVINSTALL_PARAMS drip;
  2257. PSP_DRVINFO_DETAIL_DATA pdridd;
  2258. HRESULT hr;
  2259. extern const WCHAR c_szInfId_MS_AppleTalk[];
  2260. extern const WCHAR c_szInfId_MS_NetMon[];
  2261. extern const WCHAR c_szInfId_MS_NWIPX[];
  2262. extern const WCHAR c_szInfId_MS_TCPIP[];
  2263. static const WCHAR* const c_aszServerProtocols[] = {
  2264. c_szInfId_MS_AppleTalk,
  2265. c_szInfId_MS_NetMon,
  2266. c_szInfId_MS_NWIPX,
  2267. c_szInfId_MS_TCPIP
  2268. };
  2269. static const WCHAR* const c_aszClientProtocols[] = {
  2270. c_szInfId_MS_NetMon,
  2271. c_szInfId_MS_NWIPX,
  2272. c_szInfId_MS_TCPIP
  2273. };
  2274. Assert ((FC_RASSRV == eFilter) || (FC_RASCLI == eFilter));
  2275. const WCHAR* const* aszProtocols;
  2276. DWORD cProtocols;
  2277. // What we show as available protocols to install differs between
  2278. // ras server and ras client (aka Incoming connectoid and Dial-up).
  2279. //
  2280. if (FC_RASSRV == eFilter)
  2281. {
  2282. aszProtocols = c_aszServerProtocols;
  2283. cProtocols = celems(c_aszServerProtocols);
  2284. }
  2285. else
  2286. {
  2287. aszProtocols = c_aszClientProtocols;
  2288. cProtocols = celems(c_aszClientProtocols);
  2289. }
  2290. // Enumerate each driver in hdi
  2291. while (S_OK == (hr = HrSetupDiEnumDriverInfo(hdi, NULL,
  2292. SPDIT_CLASSDRIVER, dwIndex++, &drid)))
  2293. {
  2294. (VOID) HrSetupDiGetDriverInstallParams(hdi, NULL, &drid, &drip);
  2295. // If the driver is already excluded for some other reason
  2296. // don't bother trying to determine if it should be excluded
  2297. // Note that setupdi forces us to use DNF_BAD_DRIVER to exclude
  2298. // non-device drivers rather than using DNF_EXCLUDEFROMLIST.
  2299. if (drip.Flags & DNF_BAD_DRIVER)
  2300. {
  2301. continue;
  2302. }
  2303. // Get driver detail info
  2304. hr = HrSetupDiGetDriverInfoDetail(hdi, NULL, &drid, &pdridd);
  2305. if (S_OK == hr)
  2306. {
  2307. // go through the list of relevant protocols to find which
  2308. // ones can be shown
  2309. //
  2310. // Assume we are going to hide this protocol
  2311. BOOL fHideProtocol = TRUE;
  2312. for (DWORD i = 0; i < cProtocols; i++)
  2313. {
  2314. // If the protocol is on the guest list, we won't boot
  2315. // it out
  2316. //
  2317. if (0 == _wcsicmp(aszProtocols[i], pdridd->HardwareID))
  2318. {
  2319. fHideProtocol = FALSE;
  2320. }
  2321. }
  2322. if (fHideProtocol)
  2323. {
  2324. // exclude from select
  2325. // Note that setupdi forces us to use DNF_BAD_DRIVER to
  2326. // exclude non-device drivers rather than using
  2327. // DNF_EXCLUDEFROMLIST.
  2328. drip.Flags |= DNF_BAD_DRIVER;
  2329. (VOID) HrSetupDiSetDriverInstallParams(hdi, NULL,
  2330. &drid, &drip);
  2331. }
  2332. MemFree (pdridd);
  2333. }
  2334. }
  2335. if (HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr)
  2336. {
  2337. hr = S_OK;
  2338. }
  2339. TraceHr (ttidError, FAL, hr, FALSE, "HrCiHideIrrelevantRasProtocols");
  2340. return hr;
  2341. }
  2342. //+--------------------------------------------------------------------------
  2343. //
  2344. // Function: HrCiHideIrrelevantDrivers
  2345. //
  2346. // Purpose: Enumerates a driver list, opening each driver file and
  2347. // processing its registry entries into a temporary key.
  2348. // The lower range of each driver is then examined for
  2349. // a match with pszUpperRange. If no match is
  2350. // found, the driver's DNF_BAD_DRIVER flag is set
  2351. // which will prevent it from being shown in the
  2352. // Select Device Dialog
  2353. //
  2354. // Arguments:
  2355. // hdi [in] Contains a list of available drivers.
  2356. // See Device Installer Api documentation for
  2357. // more info
  2358. // pszUpperRange [in] The upper range will be used to hide irrelevant
  2359. // drivers.
  2360. //
  2361. // Returns: HRESULT. S_OK if successful, error code otherwise
  2362. //
  2363. // Author: billbe 7 May 1998
  2364. //
  2365. // Notes:
  2366. //
  2367. HRESULT
  2368. HrCiHideIrrelevantDrivers(
  2369. IN HDEVINFO hdi,
  2370. IN PCWSTR pszUpperRange)
  2371. {
  2372. Assert(IsValidHandle(hdi));
  2373. Assert(pszUpperRange);
  2374. // Create a temporary key so we can process each protocol's
  2375. // registry entries in an effort to get its supported
  2376. // lower range of interfaces
  2377. HKEY hkeyTemp;
  2378. HRESULT hr = HrRegCreateKeyEx(HKEY_LOCAL_MACHINE, c_szRegKeyTemp,
  2379. REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL,
  2380. &hkeyTemp, NULL);
  2381. if (S_OK == hr)
  2382. {
  2383. DWORD dwIndex = 0;
  2384. SP_DRVINFO_DATA drid;
  2385. SP_DRVINSTALL_PARAMS drip;
  2386. HKEY hkeyInterfaces;
  2387. // Enumerate each driver in hdi
  2388. while (S_OK == (hr = HrSetupDiEnumDriverInfo(hdi, NULL,
  2389. SPDIT_CLASSDRIVER, dwIndex++, &drid)))
  2390. {
  2391. (VOID) HrSetupDiGetDriverInstallParams(hdi, NULL, &drid, &drip);
  2392. // If the driver is already excluded for some other reason
  2393. // don't bother trying to determine if it should be exluded.
  2394. // Note that setupdi forces us to use DNF_BAD_DRIVER to exclude
  2395. // non-device drivers rather than using DNF_EXCLUDEFROMLIST.
  2396. if (drip.Flags & DNF_BAD_DRIVER)
  2397. {
  2398. continue;
  2399. }
  2400. // Get driver detail info
  2401. PSP_DRVINFO_DETAIL_DATA pdridd = NULL;
  2402. hr = HrSetupDiGetDriverInfoDetail(hdi, NULL, &drid, &pdridd);
  2403. if (S_OK == hr)
  2404. {
  2405. HINF hinf = NULL;
  2406. // Open the driver inf
  2407. hr = HrSetupOpenInfFile(pdridd->InfFileName,
  2408. NULL, INF_STYLE_WIN4, NULL, &hinf);
  2409. WCHAR szActual[_MAX_PATH];
  2410. if (S_OK == hr)
  2411. {
  2412. // Get the actual install section name (i.e. with
  2413. // os/platform extension if it exists)
  2414. hr = HrSetupDiGetActualSectionToInstallWithBuffer (hinf,
  2415. pdridd->SectionName, szActual, _MAX_PATH, NULL,
  2416. NULL);
  2417. if (S_OK == hr)
  2418. {
  2419. // Run the registry sections into the temporary key
  2420. hr = HrCiInstallFromInfSection(hinf, szActual,
  2421. hkeyTemp, NULL, SPINST_REGISTRY);
  2422. }
  2423. }
  2424. if (S_OK == hr)
  2425. {
  2426. // Open the interfaces key of the driver
  2427. hr = HrRegOpenKeyEx(hkeyTemp, L"Ndi\\Interfaces",
  2428. KEY_ALL_ACCESS, &hkeyInterfaces);
  2429. if (S_OK == hr)
  2430. {
  2431. PWSTR pszLowerRange = NULL;
  2432. // Read the lower interfaces value.
  2433. //
  2434. hr = HrRegQuerySzWithAlloc (hkeyInterfaces,
  2435. L"LowerRange", &pszLowerRange);
  2436. // If we succeeded in reading the list and
  2437. // there is no match with one of the upper
  2438. // interfaces...
  2439. if ((S_OK == hr) &&
  2440. !FSubstringMatch (pszUpperRange,
  2441. pszLowerRange, NULL, NULL))
  2442. {
  2443. // exclude from select
  2444. drip.Flags |= DNF_BAD_DRIVER;
  2445. (VOID) HrSetupDiSetDriverInstallParams(hdi,
  2446. NULL, &drid, &drip);
  2447. }
  2448. // Clear lower interface list for next component
  2449. MemFree(pszLowerRange);
  2450. RegDeleteValue (hkeyInterfaces, L"LowerRange");
  2451. RegCloseKey(hkeyInterfaces);
  2452. }
  2453. }
  2454. SetupCloseInfFileSafe(hinf);
  2455. MemFree (pdridd);
  2456. }
  2457. }
  2458. if (HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr)
  2459. {
  2460. hr = S_OK;
  2461. }
  2462. RegCloseKey(hkeyTemp);
  2463. HrRegDeleteKeyTree(HKEY_LOCAL_MACHINE, c_szRegKeyTemp);
  2464. }
  2465. TraceHr (ttidError, FAL, hr, FALSE, "HrCiHideIrrelevantDrivers");
  2466. return hr;
  2467. }
  2468. //+--------------------------------------------------------------------------
  2469. //
  2470. // Function: HrCiHideIrrelevantFilterServices
  2471. //
  2472. // Purpose: Enumerates a driver list, opening each driver file and
  2473. // processing its registry entries into a temporary key.
  2474. // Only filter services are filtered here. If the component is
  2475. // a filter service (characteristics|NCF_FILTER)
  2476. // the FilterMediaTypes and the LowerExclude attributes are examined
  2477. // to see if the filter service can bind to the adapter. The filter
  2478. // services which cannot bind to the adapter are culled from
  2479. // the select dialog
  2480. //
  2481. // Arguments:
  2482. // hdi [in] Contains a list of available drivers.
  2483. // See Device Installer Api documentation for
  2484. // more info
  2485. // pAdapter [in] Pointer to a CComponent object representing the
  2486. // adapter for which filter services are to be hidden.
  2487. //
  2488. // Returns: HRESULT. S_OK if successful, error code otherwise
  2489. //
  2490. // Author: sumeetb October 17, 2001
  2491. //
  2492. // Notes:
  2493. //
  2494. HRESULT
  2495. HrCiHideIrrelevantFilterServices(
  2496. IN HDEVINFO hdi,
  2497. IN const CComponent * const pAdapter)
  2498. {
  2499. Assert(IsValidHandle(hdi));
  2500. Assert(pAdapter);
  2501. // Create a temporary key so we can process each filter's
  2502. // registry entries in an effort to get its FilterMediaTypes and
  2503. // LowerExclude attributes
  2504. HKEY hkeyTemp;
  2505. HRESULT hr = HrRegCreateKeyEx(HKEY_LOCAL_MACHINE, c_szRegKeyTemp,
  2506. REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL,
  2507. &hkeyTemp, NULL);
  2508. if (S_OK == hr)
  2509. {
  2510. DWORD dwIndex = 0;
  2511. SP_DRVINFO_DATA drid;
  2512. SP_DRVINSTALL_PARAMS drip;
  2513. HKEY hkeyInterfaces;
  2514. // Enumerate each driver in hdi
  2515. while (S_OK == (hr = HrSetupDiEnumDriverInfo(hdi, NULL,
  2516. SPDIT_CLASSDRIVER, dwIndex++, &drid)))
  2517. {
  2518. BOOL fCanBind = TRUE;
  2519. (VOID) HrSetupDiGetDriverInstallParams(hdi, NULL, &drid, &drip);
  2520. // If the driver is already excluded for some other reason
  2521. // don't bother trying to determine if it should be excluded.
  2522. // Note that setupdi forces us to use DNF_BAD_DRIVER to exclude
  2523. // non-device drivers rather than using DNF_EXCLUDEFROMLIST.
  2524. if (drip.Flags & DNF_BAD_DRIVER)
  2525. {
  2526. continue;
  2527. }
  2528. // Get driver detail info
  2529. PSP_DRVINFO_DETAIL_DATA pdridd = NULL;
  2530. hr = HrSetupDiGetDriverInfoDetail(hdi, NULL, &drid, &pdridd);
  2531. if (S_OK == hr)
  2532. {
  2533. HINF hinf = NULL;
  2534. // Open the driver inf
  2535. hr = HrSetupOpenInfFile(pdridd->InfFileName,
  2536. NULL, INF_STYLE_WIN4, NULL, &hinf);
  2537. if (S_OK == hr)
  2538. {
  2539. WCHAR szActual[_MAX_PATH];
  2540. // Get the actual install section name (i.e. with
  2541. // os/platform extension if it exists)
  2542. hr = HrSetupDiGetActualSectionToInstallWithBuffer (hinf,
  2543. pdridd->SectionName, szActual, _MAX_PATH, NULL,
  2544. NULL);
  2545. if (S_OK == hr)
  2546. {
  2547. DWORD dwCharacteristics = 0;
  2548. hr = HrSetupGetFirstDword (hinf, szActual,
  2549. L"Characteristics", &dwCharacteristics);
  2550. if (S_OK == hr )
  2551. {
  2552. if (dwCharacteristics & NCF_FILTER)
  2553. {
  2554. // it is a filter.
  2555. // Run the registry sections into the temporary key
  2556. hr = HrCiInstallFromInfSection(hinf, szActual,
  2557. hkeyTemp, NULL, SPINST_REGISTRY);
  2558. if (S_OK == hr)
  2559. {
  2560. hr = HrRegOpenKeyEx(hkeyTemp, L"Ndi\\Interfaces",
  2561. KEY_ALL_ACCESS, &hkeyInterfaces);
  2562. if (S_OK == hr)
  2563. {
  2564. // check filter attributes - FilterMediaTypes and
  2565. // LowerExclude to see if the filter can bind to
  2566. // the adapter
  2567. PWSTR pszFilterMediaTypes = NULL;
  2568. PWSTR pszLowerExclude = NULL;
  2569. (VOID) HrRegQuerySzWithAlloc (hkeyInterfaces,
  2570. L"FilterMediaTypes", &pszFilterMediaTypes);
  2571. (VOID) HrRegQuerySzWithAlloc (hkeyInterfaces,
  2572. L"LowerExclude", &pszLowerExclude);
  2573. fCanBind = pAdapter->FCanDirectlyBindToFilter(
  2574. pszFilterMediaTypes,
  2575. pszLowerExclude);
  2576. MemFree(pszFilterMediaTypes);
  2577. MemFree(pszLowerExclude);
  2578. // clean up the relevant keys from the
  2579. // registry for the filter
  2580. RegDeleteValue (hkeyInterfaces, L"FilterMediaTypes");
  2581. RegDeleteValue (hkeyInterfaces, L"LowerExclude");
  2582. RegCloseKey(hkeyInterfaces);
  2583. } // end open Interface key
  2584. } // end install from inf section
  2585. } // end if filter
  2586. } // end get Characteristics
  2587. } // end get actual install section.
  2588. SetupCloseInfFileSafe(hinf);
  2589. } // end open inf file
  2590. if (!fCanBind)
  2591. {
  2592. drip.Flags |= DNF_BAD_DRIVER;
  2593. (VOID) HrSetupDiSetDriverInstallParams(hdi, NULL, &drid, &drip);
  2594. }
  2595. MemFree (pdridd);
  2596. } // end get driver detail
  2597. } // end while
  2598. if (HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS) == hr)
  2599. {
  2600. hr = S_OK;
  2601. }
  2602. RegCloseKey(hkeyTemp);
  2603. HrRegDeleteKeyTree(HKEY_LOCAL_MACHINE, c_szRegKeyTemp);
  2604. } // end create temp key
  2605. TraceHr (ttidError, FAL, hr, FALSE, "HrCiHideIrrelevantFilterServices");
  2606. return hr;
  2607. }
  2608. //+--------------------------------------------------------------------------
  2609. //
  2610. // Function: HrCiSetSelectDeviceDialogStrings
  2611. //
  2612. // Purpose: This function sets the strings displayed in the Select Device
  2613. // dialog based on the class of devices being selected.
  2614. //
  2615. // Arguments:
  2616. // hdi [in] See Device Installer Api
  2617. // pdeid [in]
  2618. // guidClass [in] The class of device being selected
  2619. //
  2620. // Returns: HRESULT. S_OK if successful, an error code otherwise
  2621. //
  2622. // Author: billbe 11 Nov 1996
  2623. //
  2624. // Notes:
  2625. //
  2626. HRESULT
  2627. HrCiSetSelectDeviceDialogStrings(
  2628. IN HDEVINFO hdi,
  2629. IN PSP_DEVINFO_DATA pdeid,
  2630. IN const GUID& guidClass)
  2631. {
  2632. Assert(IsValidHandle(hdi));
  2633. SP_SELECTDEVICE_PARAMS sdep;
  2634. // The strings used in the dialog are specified through the
  2635. // SP_SELECTDEVICE_PARAMS structure
  2636. //
  2637. HRESULT hr = HrSetupDiGetFixedSizeClassInstallParams(hdi, pdeid,
  2638. (PSP_CLASSINSTALL_HEADER)&sdep, sizeof(sdep));
  2639. if (FAILED(hr))
  2640. {
  2641. // If the error is ERROR_NO_CLASSINSTALL_PARAMS then this function
  2642. // didn't really fail since it is possible
  2643. if (SPAPI_E_NO_CLASSINSTALL_PARAMS == hr)
  2644. {
  2645. hr = S_OK;
  2646. }
  2647. }
  2648. else if (DIF_SELECTDEVICE != sdep.ClassInstallHeader.InstallFunction)
  2649. {
  2650. TraceTag(ttidClassInst, "Incorrect function in Class Install Header "
  2651. "Expected DIF_SELECTDEVICE, got %lX",
  2652. sdep.ClassInstallHeader.InstallFunction);
  2653. }
  2654. BOOL fHaveDiskShown = FALSE;
  2655. if (S_OK == hr)
  2656. {
  2657. // Get the install params and check if the DI_SHOWOEM flag is set
  2658. // if so, the Have Disk button will be shown
  2659. //
  2660. SP_DEVINSTALL_PARAMS deip;
  2661. // If the call fails we can still go on unfazed.
  2662. (VOID) HrSetupDiGetDeviceInstallParams(hdi, pdeid, &deip);
  2663. if (deip.Flags & DI_SHOWOEM)
  2664. {
  2665. fHaveDiskShown = TRUE;
  2666. }
  2667. // Now we set the strings based on the type of component we are
  2668. // selecting
  2669. if (GUID_DEVCLASS_NETCLIENT == guidClass)
  2670. {
  2671. wcscpy (sdep.Title, SzLoadIds (IDS_SELECTDEVICECLIENTTITLE));
  2672. wcscpy (sdep.ListLabel,
  2673. SzLoadIds (IDS_SELECTDEVICECLIENTLISTLABEL));
  2674. wcscpy (sdep.Instructions,
  2675. SzLoadIds (IDS_SELECTDEVICECLIENTINSTRUCTIONS));
  2676. }
  2677. else if (GUID_DEVCLASS_NETSERVICE == guidClass)
  2678. {
  2679. wcscpy (sdep.Title, SzLoadIds (IDS_SELECTDEVICESERVICETITLE));
  2680. wcscpy (sdep.ListLabel,
  2681. SzLoadIds (IDS_SELECTDEVICESERVICELISTLABEL));
  2682. wcscpy (sdep.Instructions,
  2683. SzLoadIds (IDS_SELECTDEVICESERVICEINSTRUCTIONS));
  2684. }
  2685. else if (GUID_DEVCLASS_NETTRANS == guidClass)
  2686. {
  2687. wcscpy (sdep.Title, SzLoadIds (IDS_SELECTDEVICEPROTOCOLTITLE));
  2688. wcscpy (sdep.ListLabel,
  2689. SzLoadIds (IDS_SELECTDEVICEPROTOCOLLISTLABEL));
  2690. wcscpy (sdep.Instructions,
  2691. SzLoadIds (IDS_SELECTDEVICEPROTOCOLINSTRUCTIONS));
  2692. }
  2693. else if (GUID_DEVCLASS_NET == guidClass)
  2694. {
  2695. wcscpy (sdep.Title, SzLoadIds (IDS_SELECTDEVICEADAPTERTITLE));
  2696. wcscpy (sdep.SubTitle,
  2697. SzLoadIds (IDS_SELECTDEVICEADAPTERSUBTITLE));
  2698. wcscpy (sdep.ListLabel,
  2699. SzLoadIds (IDS_SELECTDEVICEADAPTERLISTLABEL));
  2700. wcscpy (sdep.Instructions,
  2701. SzLoadIds (IDS_SELECTDEVICEADAPTERINSTRUCTIONS));
  2702. }
  2703. else if (GUID_DEVCLASS_INFRARED == guidClass)
  2704. {
  2705. wcscpy (sdep.Title, SzLoadIds (IDS_SELECTDEVICEINFRAREDTITLE));
  2706. wcscpy (sdep.SubTitle,
  2707. SzLoadIds (IDS_SELECTDEVICEINFRAREDSUBTITLE));
  2708. wcscpy (sdep.ListLabel,
  2709. SzLoadIds (IDS_SELECTDEVICEINFRAREDLISTLABEL));
  2710. wcscpy (sdep.Instructions,
  2711. SzLoadIds (IDS_SELECTDEVICEINFRAREDINSTRUCTIONS));
  2712. }
  2713. else
  2714. {
  2715. // We should never get here
  2716. AssertSz(FALSE, "Invalid Class");
  2717. }
  2718. // If the Have Disk button is shown, we need to add instructions for
  2719. // it
  2720. if (fHaveDiskShown)
  2721. {
  2722. wcscat (sdep.Instructions, SzLoadIds (IDS_HAVEDISK_INSTRUCTIONS));
  2723. }
  2724. sdep.ClassInstallHeader.InstallFunction = DIF_SELECTDEVICE;
  2725. // Now we update the parameters.
  2726. hr = HrSetupDiSetClassInstallParams (hdi, pdeid,
  2727. (PSP_CLASSINSTALL_HEADER)&sdep,
  2728. sizeof(SP_SELECTDEVICE_PARAMS));
  2729. }
  2730. TraceHr (ttidError, FAL, hr, FALSE, "HrCiSetSelectDeviceDialogStrings");
  2731. return hr;
  2732. }
  2733. //+--------------------------------------------------------------------------
  2734. //
  2735. // Function: HrCiPrepareSelectDeviceDialog
  2736. //
  2737. // Purpose: Sets the strings that will appear in the Select Device
  2738. // dialog based on class type. Also, filters out components
  2739. // based on filtering criteria (note: only for non-net
  2740. // class components
  2741. //
  2742. // Arguments:
  2743. // hdi [in] See Device Installer Api documentation for more info
  2744. // pdeid [in]
  2745. //
  2746. // Returns: HRESULT. S_OK if successful, error code otherwise
  2747. //
  2748. // Author: billbe 26 Jun 1997
  2749. //
  2750. // Notes:
  2751. //
  2752. HRESULT
  2753. HrCiPrepareSelectDeviceDialog(
  2754. IN HDEVINFO hdi,
  2755. IN PSP_DEVINFO_DATA pdeid)
  2756. {
  2757. Assert(IsValidHandle(hdi));
  2758. GUID guidClass;
  2759. CI_FILTER_INFO* pcfi;
  2760. HRESULT hr = S_OK;
  2761. static const WCHAR c_szNetwareInfId[] = L"MS_NwClient";
  2762. static const WCHAR c_szQosInfId[] = L"MS_PSched";
  2763. if (pdeid)
  2764. {
  2765. // Get the class guid from the specified device element
  2766. guidClass = pdeid->ClassGuid;
  2767. }
  2768. else
  2769. {
  2770. // otherwise, get it from the hdi
  2771. hr = HrSetupDiGetDeviceInfoListClass (hdi, &guidClass);
  2772. }
  2773. if ((S_OK == hr) && !FIsEnumerated (guidClass))
  2774. {
  2775. // This might take some time. We are doing the same work as
  2776. // SetupDiSelectDevice would do. When we are done, we will
  2777. // hand the driver list to SetupDiSelectDevice so it won't
  2778. // need to rummage through the inf directory
  2779. //
  2780. CWaitCursor wc;
  2781. // For non-device classes, we need to allow excluded drivers
  2782. // in order to get a list returned.
  2783. hr = HrSetupDiSetDeipFlags(hdi, NULL,
  2784. DI_FLAGSEX_ALLOWEXCLUDEDDRVS,
  2785. SDDFT_FLAGSEX, SDFBO_OR);
  2786. if (S_OK == hr)
  2787. {
  2788. #ifdef ENABLETRACE
  2789. CBenchmark bmrk;
  2790. bmrk.Start("SetupDiBuildDriverInfoList");
  2791. #endif //ENABLETRACE
  2792. // If we have already built a driver list, this will return
  2793. // immediately.
  2794. //
  2795. hr = HrSetupDiBuildDriverInfoList(hdi, NULL, SPDIT_CLASSDRIVER);
  2796. #ifdef ENABLETRACE
  2797. bmrk.Stop();
  2798. TraceTag(ttidBenchmark, "%s : %s seconds",
  2799. bmrk.SznDescription(), bmrk.SznBenchmarkSeconds(2));
  2800. #endif //ENABLETRACE
  2801. }
  2802. if (S_OK == hr)
  2803. {
  2804. // Go through every driver node and set DNF_BAD_DRIVER
  2805. // if DNF_EXCLUDEFROMLIST is set. Note: SetupDi forces us
  2806. // to do this for non netclass driver lists.
  2807. SetBadDriverFlagIfNeededInList(hdi);
  2808. // Exclude components that are in lockdown.
  2809. //
  2810. EnumLockedDownComponents (ExcludeLockedDownComponents, hdi);
  2811. SP_DEVINSTALL_PARAMS deip;
  2812. hr = HrSetupDiGetDeviceInstallParams (hdi, pdeid, &deip);
  2813. if (S_OK == hr)
  2814. {
  2815. pcfi = (CI_FILTER_INFO*)deip.ClassInstallReserved;
  2816. // if filter info was present and we are selecting protocols...
  2817. if (pcfi)
  2818. {
  2819. if (GUID_DEVCLASS_NETTRANS == guidClass)
  2820. {
  2821. // If the filter is for lan or atm and pvReserved is
  2822. // not null...
  2823. if (((FC_LAN == pcfi->eFilter) ||
  2824. (FC_ATM == pcfi->eFilter))
  2825. && pcfi->pvReserved)
  2826. {
  2827. // Hide any drivers that can't bind to pvReserved
  2828. hr = HrCiHideIrrelevantDrivers(hdi,
  2829. (PCWSTR)((CComponent *)pcfi->pvReserved)->Ext.PszUpperRange());
  2830. }
  2831. else if ((FC_RASSRV == pcfi->eFilter) ||
  2832. (FC_RASCLI == pcfi->eFilter))
  2833. {
  2834. // Hide from the select dialog any protocols RAS does
  2835. // not support
  2836. hr = HrCiHideIrrelevantRasProtocols (hdi,
  2837. pcfi->eFilter);
  2838. }
  2839. }
  2840. else if ((GUID_DEVCLASS_NETCLIENT == guidClass) &&
  2841. (FC_ATM == pcfi->eFilter))
  2842. {
  2843. // ATM adapters don't bind to Netware Client so
  2844. // we need to try to hide it from the dialog
  2845. (VOID) HrCiExcludeNonNetClassDriverFromSelectUsingInfId(
  2846. hdi, c_szNetwareInfId);
  2847. }
  2848. else if ((GUID_DEVCLASS_NETSERVICE == guidClass) &&
  2849. (pcfi->pvReserved))
  2850. {
  2851. // Hide any filters that can't bind to this adapter
  2852. hr = HrCiHideIrrelevantFilterServices(hdi,
  2853. (CComponent *)pcfi->pvReserved);
  2854. }
  2855. }
  2856. }
  2857. }
  2858. }
  2859. if (S_OK == hr)
  2860. {
  2861. // Set the strings for the Select Device dialog.
  2862. // This is done by changing the parameters in the DeviceInfoSet.
  2863. // The next call will create this InfoSet
  2864. // If the call fails, we can still go on, we'll just have
  2865. // slightly odd descriptions in the dialog. This is done after
  2866. // the section above because strings change based on the existence
  2867. // of the Have Disk button
  2868. (VOID) HrCiSetSelectDeviceDialogStrings(hdi, pdeid, guidClass);
  2869. // Now we need to indicate that we created a class install params
  2870. // header in the structures and set the select device dialog strings
  2871. // in it. If the call fails, we can still proceed though the
  2872. // dialog will appear a bit strange
  2873. (VOID) HrSetupDiSetDeipFlags(hdi, pdeid,
  2874. DI_USECI_SELECTSTRINGS | DI_CLASSINSTALLPARAMS,
  2875. SDDFT_FLAGS, SDFBO_OR);
  2876. }
  2877. TraceHr (ttidError, FAL, hr, FALSE, "HrCiPrepareSelectDeviceDialog");
  2878. return hr;
  2879. }
  2880. HRESULT
  2881. HrCiInstallFilterDevice (
  2882. IN HDEVINFO hdi,
  2883. IN PCWSTR pszInfId,
  2884. IN CComponent* pAdapter,
  2885. IN CComponent* pFilter,
  2886. IN CFilterDevice** ppFilterDevice)
  2887. {
  2888. HRESULT hr;
  2889. SP_DEVINFO_DATA deid;
  2890. Assert (hdi);
  2891. Assert (pszInfId && *pszInfId);
  2892. Assert (pAdapter);
  2893. Assert (FIsEnumerated(pAdapter->Class()));
  2894. Assert (pFilter);
  2895. Assert (pFilter->FIsFilter());
  2896. Assert (NC_NETSERVICE == pFilter->Class());
  2897. Assert (ppFilterDevice);
  2898. *ppFilterDevice = NULL;
  2899. // Initialize the devinfo data corresponding to the driver the
  2900. // caller wants us to install.
  2901. //
  2902. hr = HrCiGetDriverInfo (hdi, &deid, *MAP_NETCLASS_TO_GUID[NC_NET],
  2903. pszInfId, NULL);
  2904. if (S_OK == hr)
  2905. {
  2906. ADAPTER_OUT_PARAMS AdapterOutParams;
  2907. ZeroMemory (&AdapterOutParams, sizeof(AdapterOutParams));
  2908. CiSetReservedField (hdi, &deid, &AdapterOutParams);
  2909. // Perform the installation.
  2910. //
  2911. hr = HrCiCallClassInstallerToInstallComponent (hdi, &deid);
  2912. CiClearReservedField (hdi, &deid);
  2913. if (S_OK == hr)
  2914. {
  2915. WCHAR szInstanceGuid[c_cchGuidWithTerm];
  2916. INT cch;
  2917. HKEY hkeyInstance;
  2918. // Convert the instance guid to a string.
  2919. //
  2920. cch = StringFromGUID2 (
  2921. AdapterOutParams.InstanceGuid,
  2922. szInstanceGuid,
  2923. c_cchGuidWithTerm);
  2924. Assert (c_cchGuidWithTerm == cch);
  2925. // Open the instance key of the newly installed device
  2926. // so we can write the instance guid and the back pointer
  2927. // to the filter.
  2928. //
  2929. hr = HrSetupDiOpenDevRegKey (hdi, &deid,
  2930. DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_WRITE,
  2931. &hkeyInstance);
  2932. if (S_OK == hr)
  2933. {
  2934. // Write the instance guid.
  2935. //
  2936. hr = HrRegSetSz (hkeyInstance, L"NetCfgInstanceId",
  2937. szInstanceGuid);
  2938. // Write the inf id of the parent filter.
  2939. //
  2940. hr = HrRegSetSz (hkeyInstance, L"FilterInfId",
  2941. pFilter->m_pszInfId);
  2942. RegCloseKey (hkeyInstance);
  2943. }
  2944. // Set the friendly name to include the adapter being
  2945. // filtered.
  2946. //
  2947. if (S_OK == hr)
  2948. {
  2949. PWSTR pszFilterDesc;
  2950. hr = HrSetupDiGetDeviceRegistryPropertyWithAlloc (
  2951. hdi, &deid, SPDRP_DEVICEDESC,
  2952. NULL, (BYTE**)&pszFilterDesc);
  2953. if (S_OK == hr)
  2954. {
  2955. #define SZ_NAME_SEP L" - "
  2956. PWSTR pszName;
  2957. ULONG cb;
  2958. // sizeof(SZ_NAME_SEP) includes the NULL-terminator
  2959. // so that will automatically add room for the
  2960. // NULL-terminator we need to allocate for pszName.
  2961. //
  2962. cb = CbOfSzSafe (pAdapter->Ext.PszDescription()) +
  2963. sizeof(SZ_NAME_SEP) +
  2964. CbOfSzSafe (pszFilterDesc);
  2965. pszName = (PWSTR)MemAlloc (cb);
  2966. if (pszName)
  2967. {
  2968. wcscpy (pszName, pAdapter->Ext.PszDescription());
  2969. wcscat (pszName, SZ_NAME_SEP);
  2970. wcscat (pszName, pszFilterDesc);
  2971. Assert (cb == CbOfSzAndTerm(pszName));
  2972. hr = HrSetupDiSetDeviceRegistryProperty (
  2973. hdi, &deid,
  2974. SPDRP_FRIENDLYNAME,
  2975. (const BYTE*)pszName,
  2976. cb);
  2977. MemFree (pszName);
  2978. }
  2979. MemFree (pszFilterDesc);
  2980. }
  2981. // If the above fails, its not a big deal.
  2982. //
  2983. hr = S_OK;
  2984. }
  2985. if (S_OK == hr)
  2986. {
  2987. hr = CFilterDevice::HrCreateInstance (
  2988. pAdapter,
  2989. pFilter,
  2990. &deid,
  2991. szInstanceGuid,
  2992. ppFilterDevice);
  2993. }
  2994. }
  2995. }
  2996. TraceHr (ttidError, FAL, hr, FALSE, "HrCiInstallFilterDevice");
  2997. return hr;
  2998. }
  2999. HRESULT
  3000. HrCiRemoveFilterDevice (
  3001. IN HDEVINFO hdi,
  3002. IN SP_DEVINFO_DATA* pdeid)
  3003. {
  3004. HRESULT hr;
  3005. ADAPTER_REMOVE_PARAMS arp = {0};
  3006. Assert (hdi);
  3007. Assert (pdeid);
  3008. CiSetReservedField (hdi, pdeid, &arp);
  3009. hr = HrSetupDiCallClassInstaller (DIF_REMOVE, hdi, pdeid);
  3010. CiClearReservedField (hdi, pdeid);
  3011. TraceHr (ttidError, FAL, hr, FALSE, "HrCiRemoveFilterDevice");
  3012. return hr;
  3013. }