Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3413 lines
109 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1997 - 1999
  6. //
  7. // File: search.c
  8. //
  9. //--------------------------------------------------------------------------
  10. #include "newdevp.h"
  11. #include <infstr.h>
  12. typedef struct _DirectoryNameList {
  13. struct _DirectoryNameList *Next;
  14. UNICODE_STRING DirectoryName;
  15. WCHAR NameBuffer[1];
  16. } DIRNAMES, *PDIRNAMES;
  17. // CDM exports (there is no public header)
  18. typedef
  19. BOOL
  20. (*PFNCDMINTERNETAVAILABLE)(
  21. void
  22. );
  23. WCHAR StarDotStar[]=L"*.*";
  24. BOOL
  25. IsSearchCanceled(
  26. PNEWDEVWIZ NewDevWiz
  27. )
  28. {
  29. DWORD Result;
  30. //
  31. // If the caller doesn't pass us a cancel event then that just means they can't
  32. // cancel the search.
  33. //
  34. if (!NewDevWiz->CancelEvent) {
  35. return FALSE;
  36. }
  37. Result = WaitForSingleObject(NewDevWiz->CancelEvent, 0);
  38. //
  39. // If Result is WAIT_OBJECT_0 then someone set the event. This means that
  40. // we should cancel the driver search.
  41. //
  42. if (Result == WAIT_OBJECT_0) {
  43. return TRUE;
  44. }
  45. return FALSE;
  46. }
  47. void
  48. GetDriverSearchPolicy(
  49. PULONG SearchPolicy
  50. )
  51. {
  52. HKEY hKey;
  53. DWORD CurrentPolicy;
  54. ULONG cbData;
  55. OSVERSIONINFOEX info;
  56. //
  57. // Assume that all search locations are valid.
  58. //
  59. *SearchPolicy = 0;
  60. if (RegOpenKeyEx(HKEY_CURRENT_USER,
  61. TEXT("Software\\Policies\\Microsoft\\Windows\\DriverSearching"),
  62. 0,
  63. KEY_READ,
  64. &hKey
  65. ) == ERROR_SUCCESS) {
  66. //
  67. // Check if we can search the CD
  68. //
  69. CurrentPolicy = 0;
  70. cbData = sizeof(CurrentPolicy);
  71. if ((RegQueryValueEx(hKey,
  72. TEXT("DontSearchCD"),
  73. NULL,
  74. NULL,
  75. (LPBYTE)&CurrentPolicy,
  76. &cbData
  77. ) == ERROR_SUCCESS) &&
  78. (CurrentPolicy)) {
  79. *SearchPolicy |= SEARCH_CDROM;
  80. }
  81. //
  82. // Check if we can search the Floppies
  83. //
  84. CurrentPolicy = 0;
  85. cbData = sizeof(CurrentPolicy);
  86. if ((RegQueryValueEx(hKey,
  87. TEXT("DontSearchFloppies"),
  88. NULL,
  89. NULL,
  90. (LPBYTE)&CurrentPolicy,
  91. &cbData
  92. ) == ERROR_SUCCESS) &&
  93. (CurrentPolicy)) {
  94. *SearchPolicy |= SEARCH_FLOPPY;
  95. }
  96. //
  97. // Check if we can search Windows Update. Note that on DataCenter
  98. // machines we never search Windows Update.
  99. //
  100. info.dwOSVersionInfoSize = sizeof(info);
  101. if (GetVersionEx((POSVERSIONINFOW)&info) &&
  102. (info.wSuiteMask & VER_SUITE_DATACENTER)) {
  103. //
  104. // This is a DataCenter machine so don't search Windows Update.
  105. //
  106. *SearchPolicy |= SEARCH_INET;
  107. *SearchPolicy |= SEARCH_INET_IF_CONNECTED;
  108. } else {
  109. CurrentPolicy = 0;
  110. cbData = sizeof(CurrentPolicy);
  111. if ((RegQueryValueEx(hKey,
  112. TEXT("DontSearchWindowsUpdate"),
  113. NULL,
  114. NULL,
  115. (LPBYTE)&CurrentPolicy,
  116. &cbData
  117. ) == ERROR_SUCCESS) &&
  118. (CurrentPolicy)) {
  119. *SearchPolicy |= SEARCH_INET;
  120. *SearchPolicy |= SEARCH_INET_IF_CONNECTED;
  121. }
  122. }
  123. //
  124. // Check if we can search locally
  125. //
  126. CurrentPolicy = 0;
  127. cbData = sizeof(CurrentPolicy);
  128. if ((RegQueryValueEx(hKey,
  129. TEXT("DontSearchLocally"),
  130. NULL,
  131. NULL,
  132. (LPBYTE)&CurrentPolicy,
  133. &cbData
  134. ) == ERROR_SUCCESS) &&
  135. (CurrentPolicy)) {
  136. *SearchPolicy |= (SEARCH_DEFAULT | SEARCH_DEFAULT_EXCLUDE_OLD_INET);
  137. }
  138. RegCloseKey(hKey);
  139. }
  140. }
  141. DWORD
  142. GetWUDriverRank(
  143. PNEWDEVWIZ NewDevWiz,
  144. LPTSTR HardwareId
  145. )
  146. {
  147. DWORD Rank = 0xFFFF;
  148. TCHAR TempBuffer[REGSTR_VAL_MAX_HCID_LEN];
  149. ULONG TempBufferLen;
  150. LPTSTR TempBufferPos;
  151. int RankCounter;
  152. //
  153. // First of all we will start off with a Rank of 0xFFFF which is the worst possible.
  154. //
  155. // We will assume that WU will only return an INF Hardware Id match to us. This means
  156. // that if we match against one of the device's HardwareIds then Rank will be between
  157. // 0x0000 and 0x0999. Otherwise if we match against one of the device's Compatible Ids
  158. // then the Rank will be between 0x2000 and 0x2999.
  159. //
  160. ZeroMemory(TempBuffer, sizeof(TempBuffer));
  161. TempBufferLen = sizeof(TempBuffer);
  162. if (CM_Get_DevInst_Registry_Property(NewDevWiz->DeviceInfoData.DevInst,
  163. CM_DRP_HARDWAREID,
  164. NULL,
  165. TempBuffer,
  166. &TempBufferLen,
  167. 0
  168. ) == CR_SUCCESS) {
  169. if (TempBufferLen > 2 * sizeof(TCHAR)) {
  170. RankCounter = 0x0000;
  171. for (TempBufferPos = TempBuffer;
  172. *TempBufferPos;
  173. TempBufferPos += (lstrlen(TempBufferPos) + 1), RankCounter++) {
  174. if (!lstrcmpi(TempBufferPos, HardwareId)) {
  175. //
  176. // Matched against a Hardware Id
  177. //
  178. Rank = RankCounter;
  179. break;
  180. }
  181. }
  182. }
  183. }
  184. if (Rank == 0xFFFF) {
  185. //
  186. // We didn't match against a HardwareId so let's go through the Compatible Ids
  187. //
  188. ZeroMemory(TempBuffer, sizeof(TempBuffer));
  189. TempBufferLen = sizeof(TempBuffer);
  190. if (CM_Get_DevInst_Registry_Property(NewDevWiz->DeviceInfoData.DevInst,
  191. CM_DRP_COMPATIBLEIDS,
  192. NULL,
  193. TempBuffer,
  194. &TempBufferLen,
  195. 0
  196. ) == CR_SUCCESS) {
  197. if (TempBufferLen > 2 * sizeof(TCHAR)) {
  198. RankCounter = 0x2000;
  199. for (TempBufferPos = TempBuffer;
  200. *TempBufferPos;
  201. TempBufferPos += (lstrlen(TempBufferPos) + 1), RankCounter++) {
  202. if (!lstrcmpi(TempBufferPos, HardwareId)) {
  203. //
  204. // Matcheds against a compatible Id
  205. //
  206. Rank = RankCounter;
  207. break;
  208. }
  209. }
  210. }
  211. }
  212. }
  213. return Rank;
  214. }
  215. BOOL
  216. IsWUDriverBetter(
  217. PNEWDEVWIZ NewDevWiz,
  218. LPTSTR HardwareId,
  219. LPTSTR DriverVer
  220. )
  221. {
  222. BOOL bWUDriverIsBetter = FALSE;
  223. DWORD WURank;
  224. SP_DRVINFO_DATA DriverInfoData;
  225. SP_DRVINSTALL_PARAMS DriverInstallParams;
  226. FILETIME WUFileTime;
  227. //
  228. // WU must at least give us a Hardware Id to compare against.
  229. //
  230. if (!HardwareId) {
  231. return FALSE;
  232. }
  233. //
  234. // If we can't get the selected driver then return TRUE. This will
  235. // usually happen if we did not find a local driver.
  236. //
  237. DriverInfoData.cbSize = sizeof(DriverInfoData);
  238. if (!SetupDiGetSelectedDriver(NewDevWiz->hDeviceInfo,
  239. &NewDevWiz->DeviceInfoData,
  240. &DriverInfoData
  241. )) {
  242. return TRUE;
  243. }
  244. //
  245. // Get the Driver Install Params so we can get the Rank of the selected (best)
  246. // driver.
  247. //
  248. DriverInstallParams.cbSize = sizeof(DriverInstallParams);
  249. if (!SetupDiGetDriverInstallParams(NewDevWiz->hDeviceInfo,
  250. &NewDevWiz->DeviceInfoData,
  251. &DriverInfoData,
  252. &DriverInstallParams
  253. )) {
  254. return TRUE;
  255. }
  256. //
  257. // Get the Rank of the HardwareId that WU returned to us.
  258. //
  259. WURank = GetWUDriverRank(NewDevWiz, HardwareId);
  260. if (WURank < DriverInstallParams.Rank) {
  261. bWUDriverIsBetter = TRUE;
  262. } else if (WURank == DriverInstallParams.Rank) {
  263. //
  264. // Need to compare the DriverDates.
  265. //
  266. if (pSetupGetDriverDate(DriverVer,
  267. &WUFileTime
  268. )) {
  269. //
  270. // If CompareFileTime returns 1 then the best driver date is larger. If
  271. // it returns 0 or -1 then the dates are the same or the WUFileTime is
  272. // better, which means we should download this driver.
  273. //
  274. if (CompareFileTime(&DriverInfoData.DriverDate, &WUFileTime) != 1) {
  275. bWUDriverIsBetter = TRUE;
  276. }
  277. }
  278. }
  279. //
  280. // default is that the Best driver found is better than the WUDriver.
  281. //
  282. return bWUDriverIsBetter;
  283. }
  284. BOOL
  285. SearchWindowsUpdateCache(
  286. PNEWDEVWIZ NewDevWiz
  287. )
  288. {
  289. ULONG SearchPolicy = 0;
  290. FIND_MATCHING_DRIVER_PROC pfnFindMatchingDriver;
  291. DOWNLOADINFO DownloadInfo;
  292. WUDRIVERINFO WUDriverInfo;
  293. TCHAR DeviceInstanceId[MAX_DEVICE_ID_LEN];
  294. BOOL FoundBetterDriver = FALSE;
  295. //
  296. // Verify that this user is allowed to search Windows Update before we continue.
  297. //
  298. GetDriverSearchPolicy(&SearchPolicy);
  299. if (SearchPolicy & SEARCH_INET) {
  300. //
  301. // This user is NOT allowed to search Windows Update!
  302. //
  303. return FALSE;
  304. }
  305. //
  306. // Check if the search has been canceled.
  307. //
  308. if (IsSearchCanceled(NewDevWiz)) {
  309. goto clean0;
  310. }
  311. //
  312. // Load the Cdm DLL and open a context handle if needed. If we can't then
  313. // bail out.
  314. //
  315. if (!OpenCdmContextIfNeeded(&NewDevWiz->hCdmInstance,
  316. &NewDevWiz->hCdmContext
  317. )) {
  318. goto clean0;
  319. }
  320. //
  321. // Check if the search has been canceled.
  322. //
  323. if (IsSearchCanceled(NewDevWiz)) {
  324. goto clean0;
  325. }
  326. pfnFindMatchingDriver = (FIND_MATCHING_DRIVER_PROC)GetProcAddress(NewDevWiz->hCdmInstance,
  327. "FindMatchingDriver"
  328. );
  329. if (!pfnFindMatchingDriver) {
  330. goto clean0;
  331. }
  332. //
  333. // First select the best driver in the list of drivers we have built so far
  334. //
  335. SetupDiCallClassInstaller(DIF_SELECTBESTCOMPATDRV,
  336. NewDevWiz->hDeviceInfo,
  337. &NewDevWiz->DeviceInfoData
  338. );
  339. //
  340. // Fill in the DOWNLOADINFO structure to pass to CDM.DLL
  341. //
  342. ZeroMemory(&DownloadInfo, sizeof(DownloadInfo));
  343. DownloadInfo.dwDownloadInfoSize = sizeof(DOWNLOADINFO);
  344. DownloadInfo.lpFile = NULL;
  345. DeviceInstanceId[0] = TEXT('\0');
  346. CM_Get_Device_ID(NewDevWiz->DeviceInfoData.DevInst,
  347. DeviceInstanceId,
  348. SIZECHARS(DeviceInstanceId),
  349. 0
  350. );
  351. DownloadInfo.lpDeviceInstanceID = (LPCTSTR)DeviceInstanceId;
  352. GetVersionEx((OSVERSIONINFO*)&DownloadInfo.OSVersionInfo);
  353. //
  354. // Set dwArchitecture to PROCESSOR_ARCHITECTURE_UNKNOWN, this
  355. // causes Windows Update to get the architecture of the machine
  356. // itself.
  357. //
  358. DownloadInfo.dwArchitecture = PROCESSOR_ARCHITECTURE_UNKNOWN;
  359. DownloadInfo.dwFlags = 0;
  360. DownloadInfo.dwClientID = 0;
  361. DownloadInfo.localid = 0;
  362. //
  363. // Fill in the WUDRIVERINFO structure to pass to CDM.DLL
  364. //
  365. ZeroMemory(&WUDriverInfo, sizeof(WUDriverInfo));
  366. WUDriverInfo.dwStructSize = sizeof(WUDRIVERINFO);
  367. //
  368. // Check if the search has been canceled.
  369. //
  370. if (IsSearchCanceled(NewDevWiz)) {
  371. goto clean0;
  372. }
  373. if (pfnFindMatchingDriver(NewDevWiz->hCdmContext,
  374. &DownloadInfo,
  375. &WUDriverInfo
  376. )) {
  377. //
  378. // Check to see if the WU Driver is better than the best selected
  379. // driver.
  380. //
  381. FoundBetterDriver = IsWUDriverBetter(NewDevWiz,
  382. WUDriverInfo.wszHardwareID,
  383. WUDriverInfo.wszDriverVer
  384. );
  385. }
  386. clean0:
  387. ;
  388. return FoundBetterDriver;
  389. }
  390. BOOL
  391. FixUpDriverListForInet(
  392. PNEWDEVWIZ NewDevWiz
  393. )
  394. /*++
  395. If the best driver is an old Internet driver then it must also be the
  396. currently installed driver. If it is not the currently installed driver
  397. then we will mark it with DNF_BAD_DRIVER and call DIF_SELECTBESTCOMPATDRV
  398. again. We will keep doing this until the best driver is either NOT a Internet
  399. driver, or it is the currently installed driver.
  400. One issue here is if the class installer does not pay attention to the DNF_BAD_DRIVER
  401. flag and returns it as the best driver anyway. If this happens then we will return
  402. FALSE which will cause us to re-build the list filtering out all Old Internet drivers.
  403. --*/
  404. {
  405. BOOL bReturn = TRUE;
  406. SP_DRVINFO_DATA DriverInfoData;
  407. SP_DRVINSTALL_PARAMS DriverInstallParams;
  408. DWORD NumberOfDrivers = 0;
  409. DWORD NumberOfIterations = 0;
  410. ZeroMemory(&DriverInfoData, sizeof(SP_DRVINFO_DATA));
  411. DriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
  412. while (SetupDiEnumDriverInfo(NewDevWiz->hDeviceInfo,
  413. &NewDevWiz->DeviceInfoData,
  414. DriverType,
  415. NumberOfDrivers++,
  416. &DriverInfoData)) {
  417. ;
  418. }
  419. //
  420. // We need to do this over and over again until we get a non Internet Driver or
  421. // the currently installed driver.
  422. //
  423. while (NumberOfIterations++ <= NumberOfDrivers) {
  424. //
  425. // Get the best selected driver
  426. //
  427. if (SetupDiGetSelectedDriver(NewDevWiz->hDeviceInfo,
  428. &NewDevWiz->DeviceInfoData,
  429. &DriverInfoData
  430. ))
  431. {
  432. //
  433. // If it is the currently installed driver then we are fine
  434. //
  435. if (IsInstalledDriver(NewDevWiz, &DriverInfoData)) {
  436. break;
  437. }
  438. ZeroMemory(&DriverInstallParams, sizeof(SP_DRVINSTALL_PARAMS));
  439. DriverInstallParams.cbSize = sizeof(SP_DRVINSTALL_PARAMS);
  440. if (SetupDiGetDriverInstallParams(NewDevWiz->hDeviceInfo,
  441. &NewDevWiz->DeviceInfoData,
  442. &DriverInfoData,
  443. &DriverInstallParams)) {
  444. if (DriverInstallParams.Flags & DNF_OLD_INET_DRIVER) {
  445. //
  446. // If the best driver is already marked with DNF_BAD_DRIVER then we
  447. // have a class installer that is picking a Bad driver as the best.
  448. // This is not a good idea, so this API will return FALSE which will
  449. // cause the entire driver list to get re-built filtering out all
  450. // Old Internet drivers.
  451. //
  452. if (DriverInstallParams.Flags & DNF_BAD_DRIVER) {
  453. bReturn = FALSE;
  454. break;
  455. }
  456. //
  457. // The best driver is an OLD Internet driver, so mark it
  458. // with DNF_BAD_DRIVER and call DIF_SELECTBESTCOMPATDRV
  459. //
  460. else {
  461. DriverInstallParams.Flags = DNF_BAD_DRIVER;
  462. if (!SetupDiSetDriverInstallParams(NewDevWiz->hDeviceInfo,
  463. &NewDevWiz->DeviceInfoData,
  464. &DriverInfoData,
  465. &DriverInstallParams
  466. )) {
  467. //
  468. // If the API fails then just break;
  469. //
  470. break;
  471. }
  472. if (!SetupDiCallClassInstaller(DIF_SELECTBESTCOMPATDRV,
  473. NewDevWiz->hDeviceInfo,
  474. &NewDevWiz->DeviceInfoData
  475. )) {
  476. //
  477. // If the API fails then just break;
  478. //
  479. break;
  480. }
  481. }
  482. } else {
  483. //
  484. // The selected driver is not an Internet driver so were good.
  485. //
  486. break;
  487. }
  488. } else {
  489. //
  490. // If the API fails then just break
  491. //
  492. break;
  493. }
  494. } else {
  495. //
  496. // If the API fails then just break
  497. //
  498. break;
  499. }
  500. }
  501. //
  502. // If we went through every driver and we still haven't selected a best one then the
  503. // class installer is probably removing the DNF_BAD_DRIVER flag and keeps choose the
  504. // same Old Internet driver over and over again. If this happens then we will just
  505. // return FALSE which will cause us to rebuild the driver list without any old Internet
  506. // drivers and then select the best driver.
  507. //
  508. if (NumberOfIterations > NumberOfDrivers) {
  509. bReturn = FALSE;
  510. }
  511. return bReturn;
  512. }
  513. void
  514. DoDriverSearchInSpecifiedLocations(
  515. HWND hWnd,
  516. PNEWDEVWIZ NewDevWiz,
  517. ULONG SearchOptions,
  518. DWORD DriverType
  519. )
  520. /*++
  521. --*/
  522. {
  523. SP_DEVINSTALL_PARAMS DeviceInstallParams;
  524. //
  525. // Set the Device Install Params to set the parent window handle.
  526. //
  527. DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
  528. if (SetupDiGetDeviceInstallParams(NewDevWiz->hDeviceInfo,
  529. &NewDevWiz->DeviceInfoData,
  530. &DeviceInstallParams
  531. ))
  532. {
  533. DeviceInstallParams.hwndParent = hWnd;
  534. if (SearchOptions & SEARCH_DEFAULT_EXCLUDE_OLD_INET) {
  535. DeviceInstallParams.FlagsEx |= DI_FLAGSEX_EXCLUDE_OLD_INET_DRIVERS;
  536. }
  537. SetupDiSetDeviceInstallParams(NewDevWiz->hDeviceInfo,
  538. &NewDevWiz->DeviceInfoData,
  539. &DeviceInstallParams
  540. );
  541. }
  542. //
  543. // Search any single INFs (this only comes in through the UpdateDriverForPlugAndPlayDevices
  544. // API. We don't need to update the UI in this case since this is currently always a silent
  545. // install (upgrade).
  546. //
  547. if (!IsSearchCanceled(NewDevWiz) && (SearchOptions & SEARCH_SINGLEINF)) {
  548. SP_DRVINFO_DATA DrvInfoData;
  549. SetDriverPath(NewDevWiz, NewDevWiz->SingleInfPath);
  550. //
  551. // OR in the DI_ENUMSINGLEINF flag so that we only look at this specific INF
  552. //
  553. DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
  554. if (SetupDiGetDeviceInstallParams(NewDevWiz->hDeviceInfo,
  555. &NewDevWiz->DeviceInfoData,
  556. &DeviceInstallParams
  557. ))
  558. {
  559. DeviceInstallParams.Flags |= DI_ENUMSINGLEINF;
  560. SetupDiSetDeviceInstallParams(NewDevWiz->hDeviceInfo,
  561. &NewDevWiz->DeviceInfoData,
  562. &DeviceInstallParams
  563. );
  564. }
  565. //
  566. // Build up the list in this specific INF file
  567. //
  568. SetupDiBuildDriverInfoList(NewDevWiz->hDeviceInfo,
  569. &NewDevWiz->DeviceInfoData,
  570. DriverType
  571. );
  572. //
  573. // Clear the DI_ENUMSINGLEINF flag in case we build from the default
  574. // INF path next.
  575. //
  576. DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
  577. if (SetupDiGetDeviceInstallParams(NewDevWiz->hDeviceInfo,
  578. &NewDevWiz->DeviceInfoData,
  579. &DeviceInstallParams
  580. ))
  581. {
  582. DeviceInstallParams.Flags &= ~DI_ENUMSINGLEINF;
  583. SetupDiSetDeviceInstallParams(NewDevWiz->hDeviceInfo,
  584. &NewDevWiz->DeviceInfoData,
  585. &DeviceInstallParams
  586. );
  587. }
  588. //
  589. // At this point we should have a list of drivers in the INF that the caller
  590. // of the UpdateDriverForPlugAndPlayDevices specified. If the list is empty
  591. // then the INF they passed us cannot be used on the Hardware Id that they
  592. // passed in. In this case we will SetLastError to ERROR_DI_BAD_PATH.
  593. //
  594. ZeroMemory(&DrvInfoData, sizeof(SP_DRVINFO_DATA));
  595. DrvInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
  596. if (!SetupDiEnumDriverInfo(NewDevWiz->hDeviceInfo,
  597. &NewDevWiz->DeviceInfoData,
  598. DriverType,
  599. 0,
  600. &DrvInfoData
  601. )) {
  602. //
  603. // We wern't able to find any drivers in the specified INF that match
  604. // the specified hardware ID.
  605. //
  606. NewDevWiz->LastError = ERROR_DI_BAD_PATH;
  607. }
  608. }
  609. //
  610. // Get the currently installed driver for this device only
  611. //
  612. if (!IsSearchCanceled(NewDevWiz) && (SearchOptions & SEARCH_CURRENTDRIVER)) {
  613. //
  614. // When getting the currently installed driver we don't need to set
  615. // the DriverPath because setupapi will figure that out.
  616. //
  617. // Set the DI_FLAGSEX_INSTALLEDDRIVER flag to let setupapi know that we
  618. // just want the installed driver added to the list.
  619. //
  620. DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
  621. if (SetupDiGetDeviceInstallParams(NewDevWiz->hDeviceInfo,
  622. &NewDevWiz->DeviceInfoData,
  623. &DeviceInstallParams
  624. ))
  625. {
  626. DeviceInstallParams.Flags |= DI_FLAGSEX_INSTALLEDDRIVER;
  627. SetupDiSetDeviceInstallParams(NewDevWiz->hDeviceInfo,
  628. &NewDevWiz->DeviceInfoData,
  629. &DeviceInstallParams
  630. );
  631. }
  632. SetupDiBuildDriverInfoList(NewDevWiz->hDeviceInfo,
  633. &NewDevWiz->DeviceInfoData,
  634. DriverType
  635. );
  636. //
  637. // Clear the DI_FLAGSEX_INSTALLEDDRIVER flag now that we have added
  638. // the installed driver to the list.
  639. //
  640. DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
  641. if (SetupDiGetDeviceInstallParams(NewDevWiz->hDeviceInfo,
  642. &NewDevWiz->DeviceInfoData,
  643. &DeviceInstallParams
  644. ))
  645. {
  646. DeviceInstallParams.Flags &= ~DI_FLAGSEX_INSTALLEDDRIVER;
  647. SetupDiSetDeviceInstallParams(NewDevWiz->hDeviceInfo,
  648. &NewDevWiz->DeviceInfoData,
  649. &DeviceInstallParams
  650. );
  651. }
  652. }
  653. //
  654. // Search the default INF path
  655. //
  656. if (!IsSearchCanceled(NewDevWiz) &&
  657. ((SearchOptions & SEARCH_DEFAULT) ||
  658. (SearchOptions & SEARCH_DEFAULT_EXCLUDE_OLD_INET)))
  659. {
  660. SetDriverPath(NewDevWiz, NULL);
  661. SetupDiBuildDriverInfoList(NewDevWiz->hDeviceInfo,
  662. &NewDevWiz->DeviceInfoData,
  663. DriverType
  664. );
  665. }
  666. //
  667. // Search any extra paths that the user specified in the wizard
  668. //
  669. if (!IsSearchCanceled(NewDevWiz) && (SearchOptions & SEARCH_DIRECTORY))
  670. {
  671. SetDriverPath(NewDevWiz, NewDevWiz->BrowsePath);
  672. SetupDiBuildDriverInfoList(NewDevWiz->hDeviceInfo,
  673. &NewDevWiz->DeviceInfoData,
  674. DriverType
  675. );
  676. }
  677. //
  678. // Search any Windows Update paths.
  679. //
  680. if (!IsSearchCanceled(NewDevWiz) && (SearchOptions & SEARCH_WINDOWSUPDATE))
  681. {
  682. BOOL bOldInetDriversAllowed = TRUE;
  683. SetDriverPath(NewDevWiz, NewDevWiz->BrowsePath);
  684. //
  685. // We need to OR in the DI_FLAGSEX_INET_DRIVER flag so that setupapi will
  686. // mark in the INFs PNF that it is from the Internet. This is important
  687. // because we don't want to ever use an Internet INF again since we don't
  688. // have the drivers locally.
  689. //
  690. DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
  691. if (SetupDiGetDeviceInstallParams(NewDevWiz->hDeviceInfo,
  692. &NewDevWiz->DeviceInfoData,
  693. &DeviceInstallParams
  694. ))
  695. {
  696. //
  697. // When searching using Windows Update we must allow old Internet drivers. We need
  698. // to do this since it is posible to backup old Internet drivers and then reinstall
  699. // them.
  700. //
  701. bOldInetDriversAllowed = (DeviceInstallParams.FlagsEx & DI_FLAGSEX_EXCLUDE_OLD_INET_DRIVERS)
  702. ? FALSE : TRUE;
  703. DeviceInstallParams.FlagsEx |= DI_FLAGSEX_INET_DRIVER;
  704. DeviceInstallParams.FlagsEx &= ~DI_FLAGSEX_EXCLUDE_OLD_INET_DRIVERS;
  705. SetupDiSetDeviceInstallParams(NewDevWiz->hDeviceInfo,
  706. &NewDevWiz->DeviceInfoData,
  707. &DeviceInstallParams
  708. );
  709. }
  710. SetupDiBuildDriverInfoList(NewDevWiz->hDeviceInfo,
  711. &NewDevWiz->DeviceInfoData,
  712. DriverType
  713. );
  714. if (!bOldInetDriversAllowed) {
  715. //
  716. // Old Internet drivers were not allowed so we need to reset the DI_FLAGSEX_EXLCUED_OLD_INET_DRIVERS
  717. // FlagsEx
  718. //
  719. DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
  720. if (SetupDiGetDeviceInstallParams(NewDevWiz->hDeviceInfo,
  721. &NewDevWiz->DeviceInfoData,
  722. &DeviceInstallParams
  723. ))
  724. {
  725. DeviceInstallParams.FlagsEx |= DI_FLAGSEX_EXCLUDE_OLD_INET_DRIVERS;
  726. SetupDiSetDeviceInstallParams(NewDevWiz->hDeviceInfo,
  727. &NewDevWiz->DeviceInfoData,
  728. &DeviceInstallParams
  729. );
  730. }
  731. }
  732. }
  733. //
  734. // Search all floppy drives
  735. //
  736. if (!IsSearchCanceled(NewDevWiz) && (SearchOptions & SEARCH_FLOPPY) )
  737. {
  738. UINT DriveNumber=0;
  739. while (!IsSearchCanceled(NewDevWiz) &&
  740. (DriveNumber = GetNextDriveByType(DRIVE_REMOVABLE, ++DriveNumber)))
  741. {
  742. SearchDriveForDrivers(NewDevWiz, DRIVE_REMOVABLE, DriveNumber);
  743. }
  744. }
  745. //
  746. // Search all CD-ROM drives
  747. //
  748. if (!IsSearchCanceled(NewDevWiz) && (SearchOptions & SEARCH_CDROM))
  749. {
  750. UINT DriveNumber=0;
  751. while (!IsSearchCanceled(NewDevWiz) &&
  752. (DriveNumber = GetNextDriveByType(DRIVE_CDROM, ++DriveNumber)))
  753. {
  754. SearchDriveForDrivers(NewDevWiz, DRIVE_CDROM, DriveNumber);
  755. }
  756. }
  757. //
  758. // Search the Internet using CDM.DLL, only if the machine is currently connected
  759. // to the Internet and CDM.DLL says it has the best driver.
  760. //
  761. if (!IsSearchCanceled(NewDevWiz) && (SearchOptions & SEARCH_INET_IF_CONNECTED)) {
  762. //
  763. // If the machine is connected to the Internet and the WU cache says it has
  764. // a better driver then set the SEARCH_INET flag to get the driver from CDM.DLL
  765. //
  766. if (IsInternetAvailable(&NewDevWiz->hCdmInstance) &&
  767. IsConnectedToInternet() &&
  768. SearchWindowsUpdateCache(NewDevWiz)) {
  769. SearchOptions |= SEARCH_INET;
  770. }
  771. }
  772. //
  773. // Search the Internet using CDM.DLL
  774. //
  775. if (!IsSearchCanceled(NewDevWiz) && (SearchOptions & SEARCH_INET))
  776. {
  777. SetDriverPath(NewDevWiz, NULL);
  778. DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
  779. if (SetupDiGetDeviceInstallParams(NewDevWiz->hDeviceInfo,
  780. &NewDevWiz->DeviceInfoData,
  781. &DeviceInstallParams
  782. ))
  783. {
  784. DeviceInstallParams.FlagsEx |= DI_FLAGSEX_DRIVERLIST_FROM_URL;
  785. SetupDiSetDeviceInstallParams(NewDevWiz->hDeviceInfo,
  786. &NewDevWiz->DeviceInfoData,
  787. &DeviceInstallParams
  788. );
  789. }
  790. SetupDiBuildDriverInfoList(NewDevWiz->hDeviceInfo,
  791. &NewDevWiz->DeviceInfoData,
  792. SPDIT_COMPATDRIVER
  793. );
  794. DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
  795. if (SetupDiGetDeviceInstallParams(NewDevWiz->hDeviceInfo,
  796. &NewDevWiz->DeviceInfoData,
  797. &DeviceInstallParams
  798. ))
  799. {
  800. DeviceInstallParams.FlagsEx &= ~DI_FLAGSEX_DRIVERLIST_FROM_URL;
  801. SetupDiSetDeviceInstallParams(NewDevWiz->hDeviceInfo,
  802. &NewDevWiz->DeviceInfoData,
  803. &DeviceInstallParams
  804. );
  805. }
  806. }
  807. }
  808. void
  809. DoDriverSearch(
  810. HWND hWnd,
  811. PNEWDEVWIZ NewDevWiz,
  812. ULONG SearchOptions,
  813. DWORD DriverType,
  814. BOOL bAppendToExistingDriverList
  815. )
  816. {
  817. ULONG SearchPolicy;
  818. SP_DRVINFO_DATA DriverInfoData;
  819. SP_DEVINSTALL_PARAMS DeviceInstallParams;
  820. //
  821. // The first thing that we do in this code is to Reset the CancelEvent in case it was set
  822. // previously.
  823. //
  824. if (NewDevWiz->CancelEvent) {
  825. ResetEvent(NewDevWiz->CancelEvent);
  826. }
  827. //
  828. // Make sure that we filter out the locations that this user is not allowed to search.
  829. //
  830. SearchPolicy = 0;
  831. GetDriverSearchPolicy(&SearchPolicy);
  832. SearchOptions &= ~SearchPolicy;
  833. //
  834. // If the user does not want to append to the existing list then delete the
  835. // current driver list.
  836. //
  837. if (!bAppendToExistingDriverList) {
  838. SetupDiDestroyDriverInfoList(NewDevWiz->hDeviceInfo,
  839. &NewDevWiz->DeviceInfoData,
  840. SPDIT_COMPATDRIVER
  841. );
  842. SetupDiDestroyDriverInfoList(NewDevWiz->hDeviceInfo,
  843. &NewDevWiz->DeviceInfoData,
  844. SPDIT_CLASSDRIVER
  845. );
  846. }
  847. //
  848. // Clear out the selected driver
  849. //
  850. SetupDiSetSelectedDriver(NewDevWiz->hDeviceInfo,
  851. &NewDevWiz->DeviceInfoData,
  852. NULL
  853. );
  854. //
  855. // Set the DI_FLAGSEX_APPENDDRIVERLIST since we will be building a big
  856. // list.
  857. //
  858. DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
  859. if (SetupDiGetDeviceInstallParams(NewDevWiz->hDeviceInfo,
  860. &NewDevWiz->DeviceInfoData,
  861. &DeviceInstallParams
  862. ))
  863. {
  864. DeviceInstallParams.FlagsEx |= DI_FLAGSEX_APPENDDRIVERLIST;
  865. SetupDiSetDeviceInstallParams(NewDevWiz->hDeviceInfo,
  866. &NewDevWiz->DeviceInfoData,
  867. &DeviceInstallParams
  868. );
  869. }
  870. //
  871. // Build up the list of drivers based on the SearchOptions
  872. //
  873. DoDriverSearchInSpecifiedLocations(hWnd, NewDevWiz, SearchOptions, DriverType);
  874. //
  875. //Pick the best driver from the list we just created
  876. //
  877. SetupDiCallClassInstaller(DIF_SELECTBESTCOMPATDRV,
  878. NewDevWiz->hDeviceInfo,
  879. &NewDevWiz->DeviceInfoData
  880. );
  881. if (!IsSearchCanceled(NewDevWiz))
  882. {
  883. //
  884. // We don't allow old Windows Update drivers to be the Best driver
  885. // unless it is also the Currently installed driver. So, if the Best
  886. // driver is an Windows Update driver and not the currently installed driver
  887. // then we need to re-compute the best driver after marking the node as
  888. // BAD.
  889. //
  890. // The worst case is that a bad class installer keeps choosing a bad internet
  891. // driver again and again. If this is the case then FixUpDriverListForInet
  892. // will return FALSE and we will re-do the driver search and filter out all
  893. // of the Old Internet drivers.
  894. //
  895. if (!FixUpDriverListForInet(NewDevWiz)) {
  896. //
  897. // Re-build the entire driver list and filter out all Old Internet drivers
  898. //
  899. SearchOptions &= ~SEARCH_DEFAULT;
  900. SearchOptions |= SEARCH_DEFAULT_EXCLUDE_OLD_INET;
  901. DoDriverSearchInSpecifiedLocations(hWnd, NewDevWiz, SearchOptions, DriverType);
  902. //
  903. //Pick the best driver from the list we just created
  904. //
  905. SetupDiCallClassInstaller(DIF_SELECTBESTCOMPATDRV,
  906. NewDevWiz->hDeviceInfo,
  907. &NewDevWiz->DeviceInfoData
  908. );
  909. }
  910. //
  911. // Update the NewDevWiz->ClassGuidSelected with the class of the selected driver.
  912. //
  913. if (!IsEqualGUID(&NewDevWiz->DeviceInfoData.ClassGuid, &GUID_NULL)) {
  914. NewDevWiz->ClassGuidSelected = &NewDevWiz->DeviceInfoData.ClassGuid;
  915. }
  916. //
  917. // Note whether we found multiple drivers or not.
  918. //
  919. DriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
  920. if (SetupDiEnumDriverInfo(NewDevWiz->hDeviceInfo,
  921. &NewDevWiz->DeviceInfoData,
  922. SPDIT_COMPATDRIVER,
  923. 1,
  924. &DriverInfoData
  925. )) {
  926. NewDevWiz->MultipleDriversFound = TRUE;
  927. } else {
  928. NewDevWiz->MultipleDriversFound = FALSE;
  929. }
  930. }
  931. //
  932. // Clear the DI_FLAGSEX_APPENDDRIVERLIST flag from the Device Install Params.
  933. //
  934. DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
  935. if (SetupDiGetDeviceInstallParams(NewDevWiz->hDeviceInfo,
  936. &NewDevWiz->DeviceInfoData,
  937. &DeviceInstallParams
  938. ))
  939. {
  940. DeviceInstallParams.FlagsEx &= ~DI_FLAGSEX_APPENDDRIVERLIST;
  941. SetupDiSetDeviceInstallParams(NewDevWiz->hDeviceInfo,
  942. &NewDevWiz->DeviceInfoData,
  943. &DeviceInstallParams
  944. );
  945. }
  946. }
  947. void
  948. CancelDriverSearch(
  949. PNEWDEVWIZ NewDevWiz
  950. )
  951. {
  952. //
  953. // First verify that there is a driver search going on by checking that the
  954. // NewDevWiz->DriverSearchThread is not NULL
  955. //
  956. if (NewDevWiz->DriverSearchThread) {
  957. if (NewDevWiz->CancelEvent) {
  958. //
  959. // Set the Cancel Event to that the DoDriverSearch() API knows to stop searching.
  960. //
  961. SetEvent(NewDevWiz->CancelEvent);
  962. }
  963. //
  964. // Tell cdm.dll to stop it's current operation
  965. //
  966. CdmCancelCDMOperation(NewDevWiz->hCdmInstance);
  967. //
  968. // Tell setupapi.dll to stop it's current driver info search
  969. //
  970. SetupDiCancelDriverInfoSearch(NewDevWiz->hDeviceInfo);
  971. //
  972. // We should always have a window handle if the user was able to cancel.
  973. //
  974. if (NewDevWiz->hWnd) {
  975. MSG Msg;
  976. DWORD WaitReturn;
  977. //
  978. // And finaly, wait for the NewDevWiz->DriverSearchThread to terminate
  979. //
  980. while ((WaitReturn = MsgWaitForMultipleObjects(1,
  981. &NewDevWiz->DriverSearchThread,
  982. FALSE,
  983. INFINITE,
  984. QS_ALLINPUT
  985. ))
  986. == WAIT_OBJECT_0 + 1) {
  987. while (PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE)) {
  988. if (!IsDialogMessage(NewDevWiz->hWnd, &Msg)) {
  989. TranslateMessage(&Msg);
  990. DispatchMessage(&Msg);
  991. }
  992. }
  993. }
  994. }
  995. }
  996. }
  997. void
  998. SetDriverPath(
  999. PNEWDEVWIZ NewDevWiz,
  1000. PCTSTR DriverPath
  1001. )
  1002. {
  1003. SP_DEVINSTALL_PARAMS DeviceInstallParams;
  1004. SP_DRVINFO_DATA DriverInfoData;
  1005. DeviceInstallParams.cbSize = sizeof(DeviceInstallParams);
  1006. SetupDiGetDeviceInstallParams(NewDevWiz->hDeviceInfo,
  1007. &NewDevWiz->DeviceInfoData,
  1008. &DeviceInstallParams
  1009. );
  1010. wcscpy(DeviceInstallParams.DriverPath, DriverPath ? DriverPath : L"");
  1011. SetupDiSetDeviceInstallParams(NewDevWiz->hDeviceInfo,
  1012. &NewDevWiz->DeviceInfoData,
  1013. &DeviceInstallParams
  1014. );
  1015. }
  1016. void
  1017. SearchDirectoryForDrivers(
  1018. PNEWDEVWIZ NewDevWiz,
  1019. PCTSTR Directory
  1020. )
  1021. {
  1022. HANDLE FindHandle;
  1023. PDIRNAMES DirNamesHead=NULL;
  1024. PDIRNAMES DirNames, Next;
  1025. PWCHAR AppendSub;
  1026. ULONG Len;
  1027. WIN32_FIND_DATAW FindData;
  1028. WCHAR SubDirName[MAX_PATH+sizeof(WCHAR)];
  1029. if (IsSearchCanceled(NewDevWiz)) {
  1030. return;
  1031. }
  1032. Len = wcslen(Directory);
  1033. memcpy(SubDirName, Directory, Len*sizeof(WCHAR));
  1034. AppendSub = SubDirName + Len;
  1035. //
  1036. // See if there are is anything (files, subdirs) in this dir.
  1037. //
  1038. *AppendSub = L'\\';
  1039. memcpy(AppendSub+1, StarDotStar, sizeof(StarDotStar));
  1040. FindHandle = FindFirstFileW(SubDirName, &FindData);
  1041. if (FindHandle == INVALID_HANDLE_VALUE) {
  1042. return;
  1043. }
  1044. //
  1045. // There might be inf files so invoke setup to look.
  1046. //
  1047. *AppendSub = L'\0';
  1048. SetDriverPath(NewDevWiz, Directory);
  1049. SetupDiBuildDriverInfoList(NewDevWiz->hDeviceInfo,
  1050. &NewDevWiz->DeviceInfoData,
  1051. SPDIT_COMPATDRIVER
  1052. );
  1053. //
  1054. // find all of the subdirs, and save them in a temporary buffer,
  1055. // so that we can close the find handle *before* going recursive.
  1056. //
  1057. do {
  1058. if (IsSearchCanceled(NewDevWiz)) {
  1059. break;
  1060. }
  1061. if ((FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
  1062. wcscmp(FindData.cFileName, L".") &&
  1063. wcscmp(FindData.cFileName, L".."))
  1064. {
  1065. USHORT ulLen;
  1066. ulLen = (USHORT)wcslen(FindData.cFileName) * sizeof(WCHAR);
  1067. DirNames = malloc(sizeof(DIRNAMES) + ulLen);
  1068. if (!DirNames) {
  1069. return;
  1070. }
  1071. DirNames->DirectoryName.Length = ulLen;
  1072. DirNames->DirectoryName.MaximumLength = ulLen + sizeof(WCHAR);
  1073. DirNames->DirectoryName.Buffer = DirNames->NameBuffer;
  1074. memcpy(DirNames->NameBuffer, FindData.cFileName, ulLen + sizeof(WCHAR));
  1075. DirNames->Next = DirNamesHead;
  1076. DirNamesHead = DirNames;
  1077. }
  1078. } while (FindNextFileW(FindHandle, &FindData));
  1079. FindClose(FindHandle);
  1080. if (!DirNamesHead) {
  1081. return;
  1082. }
  1083. *AppendSub++ = L'\\';
  1084. Next = DirNamesHead;
  1085. while (Next) {
  1086. DirNames = Next;
  1087. memcpy(AppendSub,
  1088. DirNames->DirectoryName.Buffer,
  1089. DirNames->DirectoryName.Length + sizeof(WCHAR)
  1090. );
  1091. Next= DirNames->Next;
  1092. free(DirNames);
  1093. SearchDirectoryForDrivers(NewDevWiz, SubDirName);
  1094. }
  1095. }
  1096. void
  1097. SearchDriveForDrivers(
  1098. PNEWDEVWIZ NewDevWiz,
  1099. UINT DriveType,
  1100. UINT DriveNumber
  1101. )
  1102. /*++
  1103. Routine Description:
  1104. This routine will return whether or not the specified media should be
  1105. searched for drivers, and it will return the path where the search should
  1106. start.
  1107. First the specified driver will be checked for an autorun.inf file. If there
  1108. is an autorun.inf with a [DeviceInstall] section that contains a DriverPath=
  1109. value then we will start the search at the path specified by DriverPath=.
  1110. If the [DeviceInstall] section does not contain any DriverPath= values then
  1111. the entire drive will be skipped. This is a good way for CD's that do not
  1112. contain drivers to be excluded from the driver search.
  1113. If there is no [DeviceInstall] section of the autorun.inf, or there is no
  1114. autorun.inf then the following rules apply.
  1115. - DRIVE_REMOVABLE - search the entire drive if the drive root is A: or B:,
  1116. otherwise don't search this media.
  1117. - DRIVE_CDROM - search the entire media if the size is less than 1Gig.
  1118. This means if the media is a CD then we will search the
  1119. entire CD, but if it is another larger media source, like a
  1120. DVD then we will not. We need to search the entire CD for
  1121. backwards compatibility even through it takes quite a while.
  1122. Arguments:
  1123. NewDevWiz - NEWDEVWIZ structure.
  1124. DriveType - specifies the type of drive this is, usually DRIVE_REMOVABLE
  1125. or DRIVE_CDROM.
  1126. DriveNumber - number specifiy the drive to search: 0 for A:, 1 for B:, etc.
  1127. Return Value:
  1128. --*/
  1129. {
  1130. TCHAR szAutoRunFile[MAX_PATH];
  1131. TCHAR szSectionName[MAX_PATH];
  1132. TCHAR szDriverPath[MAX_PATH];
  1133. TCHAR szSearchPath[MAX_PATH];
  1134. TCHAR DriveRoot[]=TEXT("a:");
  1135. HINF hInf = INVALID_HANDLE_VALUE;
  1136. INFCONTEXT Context;
  1137. UINT ErrorLine;
  1138. UINT PrevMode;
  1139. DriveRoot[0] = DriveNumber - 1 + DriveRoot[0];
  1140. PrevMode = SetErrorMode(0);
  1141. SetErrorMode(PrevMode | SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS);
  1142. try {
  1143. //
  1144. // First check the media for a autorun.inf that contains a [DeviceInstall]
  1145. // section with a DriverPath= value.
  1146. //
  1147. lstrcpy(szAutoRunFile, DriveRoot);
  1148. ConcatenatePaths(szAutoRunFile, TEXT("autorun.inf"), MAX_PATH, NULL);
  1149. szSectionName[0] = TEXT('\0');
  1150. hInf = SetupOpenInfFile(szAutoRunFile, NULL, INF_STYLE_OLDNT, &ErrorLine);
  1151. if (hInf != INVALID_HANDLE_VALUE) {
  1152. lstrcpy(szSectionName, TEXT("DeviceInstall"));
  1153. //
  1154. // First try the decorated section.
  1155. //
  1156. if (!GetProcessorExtension(szDriverPath, SIZECHARS(szDriverPath)) ||
  1157. (lstrcat(szSectionName, TEXT(".")) == NULL) ||
  1158. (lstrcat(szSectionName, szDriverPath) == NULL) ||
  1159. (SetupGetLineCount(hInf, szSectionName) == -1)) {
  1160. //
  1161. // Decorated section does not exist so try the undecorated section.
  1162. //
  1163. lstrcpy(szSectionName, TEXT("DeviceInstall"));
  1164. if (SetupGetLineCount(hInf, szSectionName) == -1) {
  1165. //
  1166. // There is no [DeviceInstall] section in this autorun.inf
  1167. //
  1168. szSectionName[0] = TEXT('\0');
  1169. }
  1170. }
  1171. }
  1172. //
  1173. // If szSectionName is not 0 then we have a [DeviceInstall] section. Enumerate
  1174. // this section looking for all of the DriverPath= lines.
  1175. //
  1176. if (szSectionName[0] != TEXT('\0')) {
  1177. if (SetupFindFirstLine(hInf, szSectionName, TEXT("DriverPath"), &Context)) {
  1178. do {
  1179. //
  1180. // Process the DriverPath= line.
  1181. //
  1182. if (SetupGetStringField(&Context,
  1183. 1,
  1184. szDriverPath,
  1185. sizeof(szDriverPath),
  1186. NULL)) {
  1187. //
  1188. // Search this location recursively.
  1189. //
  1190. lstrcpyn(szSearchPath, DriveRoot, SIZECHARS(szSearchPath));
  1191. ConcatenatePaths(szSearchPath, szDriverPath, SIZECHARS(szSearchPath), NULL);
  1192. SearchDirectoryForDrivers(NewDevWiz, (PCTSTR)szSearchPath);
  1193. }
  1194. } while (SetupFindNextMatchLine(&Context, TEXT("DriverPath"), &Context));
  1195. }
  1196. //
  1197. // If we had a valid [DeviceInstall] section then we are done.
  1198. //
  1199. goto clean0;
  1200. }
  1201. //
  1202. // At this point there either was no autorun.inf, or it didn't contain a
  1203. // [DeviceInstall] section or the [DeviceInstall] section didn't contain
  1204. // a DriverPath, so just do the default behavior.
  1205. //
  1206. if (DriveType == DRIVE_REMOVABLE) {
  1207. //
  1208. // We only search A: and B: removable drives by default.
  1209. //
  1210. if ((lstrcmpi(DriveRoot, TEXT("a:")) == 0) ||
  1211. (lstrcmpi(DriveRoot, TEXT("b:")) == 0)) {
  1212. //
  1213. // This is probably a floppy disk since it is A: or B: so search
  1214. // the drive.
  1215. //
  1216. lstrcpyn(szSearchPath, DriveRoot, SIZECHARS(szSearchPath));
  1217. SearchDirectoryForDrivers(NewDevWiz, (PCTSTR)szSearchPath);
  1218. }
  1219. }
  1220. if (DriveType == DRIVE_CDROM) {
  1221. //
  1222. // For DRIVE_CDROM drives we will check the media size and if it is
  1223. // less than 1Gig then we will assume it is a CD media and search it
  1224. // recursively, otherwise we won't search the drive by default.
  1225. //
  1226. ULARGE_INTEGER FreeBytesAvailable;
  1227. ULARGE_INTEGER TotalNumberOfBytes;
  1228. if (GetDiskFreeSpaceEx(DriveRoot,
  1229. &FreeBytesAvailable,
  1230. &TotalNumberOfBytes,
  1231. NULL) &&
  1232. (FreeBytesAvailable.HighPart == 0) &&
  1233. (FreeBytesAvailable.LowPart <= 0x40000000)) {
  1234. //
  1235. // There is less than 1Gig of stuff on this disk so it is probably
  1236. // a CD, so search the entire thing.
  1237. //
  1238. lstrcpyn(szSearchPath, DriveRoot, SIZECHARS(szSearchPath));
  1239. SearchDirectoryForDrivers(NewDevWiz, (PCTSTR)szSearchPath);
  1240. }
  1241. }
  1242. } except(NdwUnhandledExceptionFilter(GetExceptionInformation())) {
  1243. ;
  1244. }
  1245. clean0:
  1246. SetErrorMode(PrevMode);
  1247. if (hInf != INVALID_HANDLE_VALUE) {
  1248. SetupCloseInfFile(hInf);
  1249. }
  1250. }
  1251. WCHAR szINFDIR[]=L"\\inf\\";
  1252. BOOL
  1253. IsSelectedDriver(
  1254. PNEWDEVWIZ NewDevWiz,
  1255. PSP_DRVINFO_DATA DriverInfoData
  1256. )
  1257. /*++
  1258. --*/
  1259. {
  1260. SP_DRVINFO_DETAIL_DATA DriverInfoDetailData;
  1261. SP_DRVINFO_DATA SelectedDriverInfoData;
  1262. SP_DRVINFO_DETAIL_DATA SelectedDriverInfoDetailData;
  1263. SelectedDriverInfoData.cbSize = sizeof(SelectedDriverInfoData);
  1264. if (!SetupDiGetSelectedDriver(NewDevWiz->hDeviceInfo,
  1265. &NewDevWiz->DeviceInfoData,
  1266. &SelectedDriverInfoData
  1267. )) {
  1268. //
  1269. // If we can't get the selected driver then just return FALSE
  1270. //
  1271. return FALSE;
  1272. }
  1273. //
  1274. // Compare the SP_DRVINFO_DATA->Descriptions fields
  1275. //
  1276. if (wcscmp(DriverInfoData->Description, SelectedDriverInfoData.Description)) {
  1277. return FALSE;
  1278. }
  1279. //
  1280. // Compare the SP_DRVINFO_DATA->MfgName fields
  1281. //
  1282. if (wcscmp(DriverInfoData->MfgName, SelectedDriverInfoData.MfgName)) {
  1283. return FALSE;
  1284. }
  1285. //
  1286. // Compare the SP_DRVINFO_DATA->ProviderName fields
  1287. //
  1288. if (wcscmp(DriverInfoData->ProviderName, SelectedDriverInfoData.ProviderName)) {
  1289. return FALSE;
  1290. }
  1291. //
  1292. // Get the SP_DRVINFO_DATAIL_DATA structures for both drivers
  1293. //
  1294. DriverInfoDetailData.cbSize = sizeof(DriverInfoDetailData);
  1295. if (!SetupDiGetDriverInfoDetail(NewDevWiz->hDeviceInfo,
  1296. &NewDevWiz->DeviceInfoData,
  1297. DriverInfoData,
  1298. &DriverInfoDetailData,
  1299. sizeof(DriverInfoDetailData),
  1300. NULL
  1301. )
  1302. &&
  1303. GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
  1304. return FALSE;
  1305. }
  1306. SelectedDriverInfoDetailData.cbSize = sizeof(SelectedDriverInfoDetailData);
  1307. if (!SetupDiGetDriverInfoDetail(NewDevWiz->hDeviceInfo,
  1308. &NewDevWiz->DeviceInfoData,
  1309. &SelectedDriverInfoData,
  1310. &SelectedDriverInfoDetailData,
  1311. sizeof(SelectedDriverInfoDetailData),
  1312. NULL
  1313. )
  1314. &&
  1315. GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
  1316. return FALSE;
  1317. }
  1318. //
  1319. // Compare the SP_DRVINFO_DETAIL_DATA->InfFileName fields
  1320. //
  1321. if (wcscmp(DriverInfoDetailData.InfFileName, SelectedDriverInfoDetailData.InfFileName)) {
  1322. return FALSE;
  1323. }
  1324. //
  1325. // Compare the SP_DRVINFO_DETAIL_DATA->SectionName fields
  1326. //
  1327. if (wcscmp(DriverInfoDetailData.SectionName, SelectedDriverInfoDetailData.SectionName)) {
  1328. return FALSE;
  1329. }
  1330. //
  1331. // Compare the SP_DRVINFO_DETAIL_DATA->DrvDescription fields
  1332. //
  1333. if (wcscmp(DriverInfoDetailData.DrvDescription, SelectedDriverInfoDetailData.DrvDescription)) {
  1334. return FALSE;
  1335. }
  1336. //
  1337. // All of the above comparisons worked so this must be the selected driver
  1338. //
  1339. return TRUE;
  1340. }
  1341. BOOL
  1342. IsInstalledDriver(
  1343. PNEWDEVWIZ NewDevWiz,
  1344. PSP_DRVINFO_DATA DriverInfoData OPTIONAL
  1345. )
  1346. /*++
  1347. Determines if the currently selected driver is the
  1348. currently installed driver. By comparing DriverInfoData
  1349. and DriverInfoDetailData.
  1350. --*/
  1351. {
  1352. BOOL bReturn;
  1353. HKEY hDevRegKey;
  1354. DWORD cbData, Len;
  1355. PWCHAR pwch;
  1356. SP_DRVINFO_DATA SelectedDriverInfoData;
  1357. PSP_DRVINFO_DATA BestDriverInfoData;
  1358. SP_DRVINFO_DETAIL_DATA DriverInfoDetailData;
  1359. TCHAR Buffer[MAX_PATH*2];
  1360. PVOID pvBuffer=Buffer;
  1361. //
  1362. // Use the PSP_DRVINFO_DATA that was passed in. If one wasn't passed in the get the
  1363. // selected driver.
  1364. //
  1365. if (DriverInfoData) {
  1366. BestDriverInfoData = DriverInfoData;
  1367. } else {
  1368. SelectedDriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
  1369. if (SetupDiGetSelectedDriver(NewDevWiz->hDeviceInfo,
  1370. &NewDevWiz->DeviceInfoData,
  1371. &SelectedDriverInfoData
  1372. )) {
  1373. BestDriverInfoData = &SelectedDriverInfoData;
  1374. } else {
  1375. //
  1376. // If there is no currently selected driver then it can't be the installed one
  1377. //
  1378. return FALSE;
  1379. }
  1380. }
  1381. bReturn = FALSE;
  1382. //
  1383. // Open a reg key to the driver specific location
  1384. //
  1385. hDevRegKey = SetupDiOpenDevRegKey(NewDevWiz->hDeviceInfo,
  1386. &NewDevWiz->DeviceInfoData,
  1387. DICS_FLAG_GLOBAL,
  1388. 0,
  1389. DIREG_DRV,
  1390. KEY_READ
  1391. );
  1392. if (hDevRegKey == INVALID_HANDLE_VALUE) {
  1393. goto SIIDExit;
  1394. }
  1395. //
  1396. // Compare Description, Manufacturer, and Provider Name.
  1397. // These are the three unique "keys" within a single inf file.
  1398. // Fetch the drvinfo, drvdetailinfo for the selected device.
  1399. //
  1400. //
  1401. // If the Device Description isn't the same, its a different driver.
  1402. //
  1403. if (!SetupDiGetDeviceRegistryProperty(NewDevWiz->hDeviceInfo,
  1404. &NewDevWiz->DeviceInfoData,
  1405. SPDRP_DEVICEDESC,
  1406. NULL, // regdatatype
  1407. pvBuffer,
  1408. sizeof(Buffer),
  1409. NULL
  1410. )) {
  1411. *Buffer = TEXT('\0');
  1412. }
  1413. if (wcscmp(BestDriverInfoData->Description, Buffer)) {
  1414. goto SIIDExit;
  1415. }
  1416. //
  1417. // If the Manufacturer Name isn't the same, its different
  1418. //
  1419. if (!SetupDiGetDeviceRegistryProperty(NewDevWiz->hDeviceInfo,
  1420. &NewDevWiz->DeviceInfoData,
  1421. SPDRP_MFG,
  1422. NULL, // regdatatype
  1423. pvBuffer,
  1424. sizeof(Buffer),
  1425. NULL
  1426. )) {
  1427. *Buffer = TEXT('\0');
  1428. }
  1429. if (wcscmp(BestDriverInfoData->MfgName, Buffer)) {
  1430. goto SIIDExit;
  1431. }
  1432. //
  1433. // If the Provider Name isn't the same, its different
  1434. //
  1435. cbData = sizeof(Buffer);
  1436. if (RegQueryValueEx(hDevRegKey,
  1437. REGSTR_VAL_PROVIDER_NAME,
  1438. NULL,
  1439. NULL,
  1440. pvBuffer,
  1441. &cbData
  1442. ) != ERROR_SUCCESS) {
  1443. *Buffer = TEXT('\0');
  1444. }
  1445. if (wcscmp(BestDriverInfoData->ProviderName, Buffer)) {
  1446. goto SIIDExit;
  1447. }
  1448. //
  1449. // Check the InfName, InfSection and DriverDesc
  1450. // NOTE: the installed infName will not contain the path to the default windows
  1451. // inf directory. If the same inf name has been found for the selected driver
  1452. // from another location besides the default inf search path, then it will
  1453. // contain a path, and is treated as a *different* driver.
  1454. //
  1455. DriverInfoDetailData.cbSize = sizeof(DriverInfoDetailData);
  1456. if (!SetupDiGetDriverInfoDetail(NewDevWiz->hDeviceInfo,
  1457. &NewDevWiz->DeviceInfoData,
  1458. BestDriverInfoData,
  1459. &DriverInfoDetailData,
  1460. sizeof(DriverInfoDetailData),
  1461. NULL
  1462. )
  1463. &&
  1464. GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
  1465. goto SIIDExit;
  1466. }
  1467. Len = GetWindowsDirectory(Buffer, MAX_PATH);
  1468. if (Len && Len < MAX_PATH) {
  1469. pwch = Buffer + Len - 1;
  1470. if (*pwch != L'\\') {
  1471. pwch++;
  1472. }
  1473. wcscpy(pwch, szINFDIR);
  1474. pwch += sizeof(szINFDIR)/sizeof(WCHAR) - 1;
  1475. cbData = MAX_PATH*sizeof(WCHAR);
  1476. if (RegQueryValueEx(hDevRegKey,
  1477. REGSTR_VAL_INFPATH,
  1478. NULL,
  1479. NULL,
  1480. (PVOID)pwch,
  1481. &cbData
  1482. ) != ERROR_SUCCESS )
  1483. {
  1484. *Buffer = TEXT('\0');
  1485. }
  1486. if (_wcsicmp( DriverInfoDetailData.InfFileName, Buffer)) {
  1487. goto SIIDExit;
  1488. }
  1489. } else {
  1490. goto SIIDExit;
  1491. }
  1492. cbData = sizeof(Buffer);
  1493. if (RegQueryValueEx(hDevRegKey,
  1494. REGSTR_VAL_INFSECTION,
  1495. NULL,
  1496. NULL,
  1497. pvBuffer,
  1498. &cbData
  1499. ) != ERROR_SUCCESS ) {
  1500. *Buffer = TEXT('\0');
  1501. }
  1502. if (wcscmp(DriverInfoDetailData.SectionName, Buffer)) {
  1503. goto SIIDExit;
  1504. }
  1505. cbData = sizeof(Buffer);
  1506. if (RegQueryValueEx(hDevRegKey,
  1507. REGSTR_VAL_DRVDESC,
  1508. NULL,
  1509. NULL,
  1510. pvBuffer,
  1511. &cbData
  1512. ) != ERROR_SUCCESS ) {
  1513. *Buffer = TEXT('\0');
  1514. }
  1515. if (wcscmp(DriverInfoDetailData.DrvDescription, Buffer)) {
  1516. goto SIIDExit;
  1517. }
  1518. bReturn = TRUE;
  1519. SIIDExit:
  1520. if (hDevRegKey != INVALID_HANDLE_VALUE) {
  1521. RegCloseKey(hDevRegKey);
  1522. }
  1523. return bReturn;
  1524. }
  1525. BOOL
  1526. IsDriverNodeInteractiveInstall(
  1527. PNEWDEVWIZ NewDevWiz,
  1528. PSP_DRVINFO_DATA DriverInfoData
  1529. )
  1530. /*++
  1531. This function checks to see if the given PSP_DRVINFO_DATA is listed as a
  1532. InteractiveInstall in the [ControlFlags] section of the INF.
  1533. Return Value:
  1534. TRUE if the driver node is InteractiveInstall, FALSE otherwise.
  1535. --*/
  1536. {
  1537. BOOL b;
  1538. DWORD Err;
  1539. DWORD DriverInfoDetailDataSize;
  1540. HINF hInf;
  1541. INFCONTEXT InfContext;
  1542. TCHAR szBuffer[MAX_PATH];
  1543. DWORD i;
  1544. LPTSTR p;
  1545. PSP_DRVINFO_DETAIL_DATA pDriverInfoDetailData;
  1546. //
  1547. // Get the SP_DRVINFO_DETAIL_DATA so we can get the list of hardware and
  1548. // compatible Ids for this device.
  1549. //
  1550. b = SetupDiGetDriverInfoDetail(NewDevWiz->hDeviceInfo,
  1551. &NewDevWiz->DeviceInfoData,
  1552. DriverInfoData,
  1553. NULL,
  1554. 0,
  1555. &DriverInfoDetailDataSize
  1556. );
  1557. Err = GetLastError();
  1558. //
  1559. // The above call to get the driver info detail data should never succeed because the
  1560. // buffer will always be too small (we're just interested in sizeing the buffer
  1561. // at this point).
  1562. //
  1563. if (b || (Err != ERROR_INSUFFICIENT_BUFFER)) {
  1564. //
  1565. // For some reason the SetupDiGetDriverInfoDetail API failed...so return FALSE.
  1566. //
  1567. return FALSE;
  1568. }
  1569. //
  1570. // Now that we know how big of a buffer we need to hold the driver info details,
  1571. // allocate the buffer and retrieve the information.
  1572. //
  1573. pDriverInfoDetailData = malloc(DriverInfoDetailDataSize);
  1574. if (!pDriverInfoDetailData) {
  1575. return FALSE;
  1576. }
  1577. pDriverInfoDetailData->cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
  1578. if (!SetupDiGetDriverInfoDetail(NewDevWiz->hDeviceInfo,
  1579. &NewDevWiz->DeviceInfoData,
  1580. DriverInfoData,
  1581. pDriverInfoDetailData,
  1582. DriverInfoDetailDataSize,
  1583. NULL)) {
  1584. free(pDriverInfoDetailData);
  1585. return FALSE;
  1586. }
  1587. //
  1588. // At this point we have all of the hardware and compatible IDs for this driver node.
  1589. // Now we need to open up the INF and see if any of them are referenced in an
  1590. // "InteractiveInstall" control flag entry.
  1591. //
  1592. hInf = SetupOpenInfFile(pDriverInfoDetailData->InfFileName,
  1593. NULL,
  1594. INF_STYLE_WIN4,
  1595. NULL
  1596. );
  1597. if (hInf == INVALID_HANDLE_VALUE) {
  1598. //
  1599. // For some reason we couldn't open the INF!
  1600. //
  1601. free(pDriverInfoDetailData);
  1602. return FALSE;
  1603. }
  1604. b = FALSE;
  1605. //
  1606. // Look at each InteractiveInstall line in the INF's [ControlFlags] section...
  1607. //
  1608. if (SetupFindFirstLine(hInf, INFSTR_CONTROLFLAGS_SECTION, INFSTR_KEY_INTERACTIVEINSTALL, &InfContext)) {
  1609. do {
  1610. //
  1611. // and within each line, examine each value...
  1612. //
  1613. for (i = 1;
  1614. SetupGetStringField(&InfContext, i, szBuffer, sizeof(szBuffer) / sizeof(TCHAR), NULL);
  1615. i++) {
  1616. //
  1617. // Check to see if this ID matches up with one of the driver node's hardware
  1618. // or compatible IDs.
  1619. //
  1620. for (p = pDriverInfoDetailData->HardwareID; *p; p+= (lstrlen(p) + 1)) {
  1621. if (!lstrcmpi(p, szBuffer)) {
  1622. //
  1623. // We found a match, this device is marked with
  1624. // InteractiveInstall.
  1625. //
  1626. b = TRUE;
  1627. }
  1628. }
  1629. }
  1630. } while (SetupFindNextMatchLine(&InfContext, INFSTR_KEY_INTERACTIVEINSTALL, &InfContext));
  1631. }
  1632. SetupCloseInfFile(hInf);
  1633. free(pDriverInfoDetailData);
  1634. return b;
  1635. }
  1636. BOOL
  1637. IsDriverAutoInstallable(
  1638. PNEWDEVWIZ NewDevWiz,
  1639. PSP_DRVINFO_DATA BestDriverInfoData
  1640. )
  1641. /*++
  1642. A driver (the selected driver) is considered auto installable if the following are TRUE:
  1643. - It is not a printer
  1644. - This must be a NDWTYPE_FOUNDNEW or NDWTYPE_UPDATE InstallType.
  1645. - There is no "InteractiveInstall" key in the [ControlFlags] section for any of the
  1646. Hardware or Compatible IDs of this device.
  1647. - There are no other drivers in the list that have the same or better Ranks or Dates then
  1648. the selected driver.
  1649. - If this is an Update Driver case the selected driver must not be the current driver
  1650. The reason for this function is that in the Found New Hardware case we want to automatically
  1651. install the best driver we find. We can't do that in the case where we have multiple drivers
  1652. that have the same Rank as the best driver found. The problem is that there are certain cases
  1653. where a user MUST choose the driver in these cases and so we can't automatically make the decision
  1654. for them. If this API does return FALSE that just means that the user will have to hit Next
  1655. on one extra wizard page.
  1656. Return Value:
  1657. TRUE if this device/driver is auto installable.
  1658. FALSE if this device/driver is NOT auto installable. This means that we will stop on the install
  1659. page and the user will have to hit Next to proceede.
  1660. --*/
  1661. {
  1662. DWORD BestRank;
  1663. DWORD DriverIndex;
  1664. DWORD BestRankCount = 0;
  1665. FILETIME BestDriverDate;
  1666. DWORDLONG BestDriverVersion;
  1667. TCHAR BestProviderName[LINE_LEN];
  1668. SP_DRVINFO_DATA DriverInfoData;
  1669. SP_DRVINSTALL_PARAMS DriverInstallParams;
  1670. //
  1671. // We only do Auto Installs if this is a NDWTYPE_FOUNDNEW or NDWTYPE_UPDATE install
  1672. //
  1673. if ((NewDevWiz->InstallType != NDWTYPE_FOUNDNEW) &&
  1674. (NewDevWiz->InstallType != NDWTYPE_UPDATE)) {
  1675. return FALSE;
  1676. }
  1677. //
  1678. // We need to special case printers as usuall.
  1679. //
  1680. if (IsEqualGUID(&NewDevWiz->DeviceInfoData.ClassGuid, &GUID_DEVCLASS_PRINTER)) {
  1681. //
  1682. // This is a printer, so if there is more than one printer driver node
  1683. // in the list, this isn't auto-installable.
  1684. //
  1685. DriverInfoData.cbSize = sizeof(DriverInfoData);
  1686. if (SetupDiEnumDriverInfo(NewDevWiz->hDeviceInfo,
  1687. &NewDevWiz->DeviceInfoData,
  1688. SPDIT_COMPATDRIVER,
  1689. 1,
  1690. &DriverInfoData
  1691. )) {
  1692. return FALSE;
  1693. }
  1694. }
  1695. //
  1696. // Check if the best driver is listed in the INF as InteractiveInstall. If
  1697. // it is, and there is more than one driver in the list, then this driver
  1698. // is not auto-installable.
  1699. //
  1700. if (IsDriverNodeInteractiveInstall(NewDevWiz, BestDriverInfoData)) {
  1701. //
  1702. // The best driver is marked as InteractiveInstall. If there is more
  1703. // than one driver in the list then this driver is NOT auto-installable.
  1704. //
  1705. DriverInfoData.cbSize = sizeof(DriverInfoData);
  1706. if (SetupDiEnumDriverInfo(NewDevWiz->hDeviceInfo,
  1707. &NewDevWiz->DeviceInfoData,
  1708. SPDIT_COMPATDRIVER,
  1709. 1,
  1710. &DriverInfoData
  1711. )) {
  1712. return FALSE;
  1713. }
  1714. }
  1715. //
  1716. // First get the Rank of the selected driver.
  1717. //
  1718. DriverInstallParams.cbSize = sizeof(DriverInstallParams);
  1719. if (!SetupDiGetDriverInstallParams(NewDevWiz->hDeviceInfo,
  1720. &NewDevWiz->DeviceInfoData,
  1721. BestDriverInfoData,
  1722. &DriverInstallParams
  1723. )) {
  1724. //
  1725. // If we can't get the Rank of the best driver then just return FALSE
  1726. //
  1727. return FALSE;
  1728. }
  1729. //
  1730. // Remember the Rank and DriverDate of the selected (best) driver.
  1731. //
  1732. BestRank = DriverInstallParams.Rank;
  1733. memcpy(&BestDriverDate, &BestDriverInfoData->DriverDate, sizeof(BestDriverDate));
  1734. BestDriverVersion = BestDriverInfoData->DriverVersion;
  1735. lstrcpy(BestProviderName, BestDriverInfoData->ProviderName);
  1736. DriverInfoData.cbSize = sizeof(DriverInfoData);
  1737. DriverIndex = 0;
  1738. while (SetupDiEnumDriverInfo(NewDevWiz->hDeviceInfo,
  1739. &NewDevWiz->DeviceInfoData,
  1740. SPDIT_COMPATDRIVER,
  1741. DriverIndex++,
  1742. &DriverInfoData
  1743. )) {
  1744. DriverInstallParams.cbSize = sizeof(DriverInstallParams);
  1745. if (SetupDiGetDriverInstallParams(NewDevWiz->hDeviceInfo,
  1746. &NewDevWiz->DeviceInfoData,
  1747. &DriverInfoData,
  1748. &DriverInstallParams
  1749. )) {
  1750. //
  1751. // Don't bother doing the comparison if this driver is marked as a BAD driver
  1752. //
  1753. if (!(DriverInstallParams.Flags & DNF_BAD_DRIVER) &&
  1754. !(DriverInstallParams.Flags & DNF_OLD_INET_DRIVER)) {
  1755. //
  1756. // Check if the current driver node is identical enough to the
  1757. // best driver that setupapi picked, so that we need the user
  1758. // to manually pick the one to install. This should be very
  1759. // rare that the user would ever need to make this choice.
  1760. //
  1761. if (DriverInstallParams.Rank < BestRank) {
  1762. //
  1763. // We found another driver node in the list that has a
  1764. // better (smaller) rank then the best driver.
  1765. //
  1766. BestRankCount++;
  1767. } else if ((DriverInstallParams.Rank == BestRank) &&
  1768. (CompareFileTime(&DriverInfoData.DriverDate, &BestDriverDate) == 1)) {
  1769. //
  1770. // We found another driver node in the list that has the
  1771. // same rank as the best driver and it has a newer driver
  1772. // date.
  1773. //
  1774. BestRankCount++;
  1775. } else if ((DriverInstallParams.Rank == BestRank) &&
  1776. (CompareFileTime(&DriverInfoData.DriverDate, &BestDriverDate) == 0)) {
  1777. //
  1778. // We found another driver node in the list that has the
  1779. // same rank as the best driver and the driver dates are
  1780. // the same.
  1781. // Check the provider names and if they are the same, then
  1782. // check which driver has the larger version, otherwise
  1783. // the driver version is meaningless so the user will have
  1784. // to make the choice.
  1785. //
  1786. if (lstrcmpi(BestProviderName, DriverInfoData.ProviderName) == 0) {
  1787. //
  1788. // Since the provider names are the same if the current
  1789. // driver node has a better, or the same, version as the
  1790. // best driver then the user will have to manually pick
  1791. // which driver they want.
  1792. //
  1793. if (DriverInfoData.DriverVersion >= BestDriverVersion) {
  1794. BestRankCount++;
  1795. }
  1796. } else {
  1797. //
  1798. // The provider names are different, which means the
  1799. // driver version information is meaningless, so the
  1800. // user will have to pick which driver they want.
  1801. //
  1802. BestRankCount++;
  1803. }
  1804. }
  1805. }
  1806. }
  1807. }
  1808. //
  1809. // If BestRankCount is 2 or more than that means we have multiple drivers with the same or better
  1810. // Rank as the best driver.
  1811. //
  1812. if (BestRankCount >= 2) {
  1813. return FALSE;
  1814. }
  1815. //
  1816. // If we are in a NDWTYPE_UPDATE install then we need to make sure that the selected driver is not
  1817. // the current driver.
  1818. //
  1819. if ((NewDevWiz->InstallType == NDWTYPE_UPDATE) &&
  1820. IsInstalledDriver(NewDevWiz, BestDriverInfoData)) {
  1821. return FALSE;
  1822. }
  1823. //
  1824. // If we have come this far then that means
  1825. // - we're not dealing with a printer
  1826. // - this is either a NDWTYPE_FOUNDNEW or NDWTYPE_UPDATE install
  1827. // - this is not an "InteractiveInstall"
  1828. // - no other driver has the same or better rank then the selected driver.
  1829. // - if this is a NDWTYPE_UPDATE then the selected driver is not the current driver.
  1830. //
  1831. return TRUE;
  1832. }
  1833. DWORD WINAPI
  1834. DriverSearchThreadProc(
  1835. LPVOID lpVoid
  1836. )
  1837. /*++
  1838. Description:
  1839. In the Wizard, we must do the driver search in a separate thread so that the user has the option
  1840. to cancel out.
  1841. --*/
  1842. {
  1843. PNEWDEVWIZ NewDevWiz = (PNEWDEVWIZ)lpVoid;
  1844. //
  1845. // Do the driver search.
  1846. //
  1847. DoDriverSearch(NewDevWiz->hWnd,
  1848. NewDevWiz,
  1849. NewDevWiz->SearchOptions,
  1850. SPDIT_COMPATDRIVER,
  1851. FALSE
  1852. );
  1853. //
  1854. // Post a message to the window to let it know that we are finished with the search
  1855. //
  1856. PostMessage(NewDevWiz->hWnd, WUM_SEARCHDRIVERS, TRUE, GetLastError());
  1857. return GetLastError();
  1858. }
  1859. INT_PTR CALLBACK
  1860. DriverSearchingDlgProc(
  1861. HWND hDlg,
  1862. UINT message,
  1863. WPARAM wParam,
  1864. LPARAM lParam
  1865. )
  1866. {
  1867. PNEWDEVWIZ NewDevWiz;
  1868. TCHAR PropSheetHeaderTitle[MAX_PATH];
  1869. if (message == WM_INITDIALOG) {
  1870. LPPROPSHEETPAGE lppsp = (LPPROPSHEETPAGE)lParam;
  1871. NewDevWiz = (PNEWDEVWIZ)lppsp->lParam;
  1872. SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)NewDevWiz);
  1873. return TRUE;
  1874. }
  1875. NewDevWiz = (PNEWDEVWIZ)GetWindowLongPtr(hDlg, DWLP_USER);
  1876. switch(message) {
  1877. case WM_NOTIFY:
  1878. switch (((NMHDR FAR *)lParam)->code) {
  1879. case PSN_SETACTIVE: {
  1880. HICON hicon;
  1881. int PrevPage;
  1882. SetDriverDescription(hDlg, IDC_DRVUPD_DRVDESC, NewDevWiz);
  1883. hicon = NULL;
  1884. if (NewDevWiz->ClassGuidSelected &&
  1885. SetupDiLoadClassIcon(NewDevWiz->ClassGuidSelected, &hicon, NULL))
  1886. {
  1887. hicon = (HICON)SendDlgItemMessage(hDlg, IDC_CLASSICON, STM_SETICON, (WPARAM)hicon, 0L);
  1888. }
  1889. else {
  1890. SetupDiLoadClassIcon(&GUID_DEVCLASS_UNKNOWN, &hicon, NULL);
  1891. hicon = (HICON)SendDlgItemMessage(hDlg, IDC_CLASSICON, STM_SETICON, (WPARAM)hicon, 0L);
  1892. }
  1893. if (hicon) {
  1894. DestroyIcon(hicon);
  1895. }
  1896. PrevPage = NewDevWiz->PrevPage;
  1897. NewDevWiz->PrevPage = IDD_NEWDEVWIZ_SEARCHING;
  1898. NewDevWiz->ExitDetect = FALSE;
  1899. //
  1900. // if coming from IDD_NEWDEVWIZ_INTRO or IDD_NEWDEVWIZ_ADVANCEDSEARCH
  1901. // page then begin driver search
  1902. //
  1903. if ((PrevPage == IDD_NEWDEVWIZ_INTRO) ||
  1904. (PrevPage == IDD_NEWDEVWIZ_ADVANCEDSEARCH) ||
  1905. (PrevPage == IDD_NEWDEVWIZ_WUPROMPT)) {
  1906. DWORD ThreadId;
  1907. LoadString(hNewDev, IDS_NEWDEVWIZ_SEARCHING, PropSheetHeaderTitle, SIZECHARS(PropSheetHeaderTitle));
  1908. PropSheet_SetHeaderTitle(GetParent(hDlg),
  1909. PropSheet_IdToIndex(GetParent(hDlg), IDD_NEWDEVWIZ_SEARCHING),
  1910. PropSheetHeaderTitle
  1911. );
  1912. PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK);
  1913. ShowWindow(GetDlgItem(hDlg, IDC_ANIMATE_SEARCH), SW_SHOW);
  1914. Animate_Open(GetDlgItem(hDlg, IDC_ANIMATE_SEARCH), MAKEINTRESOURCE(IDA_SEARCHING));
  1915. Animate_Play(GetDlgItem(hDlg, IDC_ANIMATE_SEARCH), 0, -1, -1);
  1916. NewDevWiz->CurrCursor = NewDevWiz->IdcAppStarting;
  1917. SetCursor(NewDevWiz->CurrCursor);
  1918. NewDevWiz->hWnd = hDlg;
  1919. //
  1920. // Start up a separate thread to do the driver search on.
  1921. // When the driver searching is complete the DriverSearchThreadProc
  1922. // will post us a WUM_SEARCHDRIVERS message.
  1923. //
  1924. NewDevWiz->DriverSearchThread = CreateThread(NULL,
  1925. 0,
  1926. (LPTHREAD_START_ROUTINE)DriverSearchThreadProc,
  1927. (LPVOID)NewDevWiz,
  1928. 0,
  1929. &ThreadId
  1930. );
  1931. }
  1932. //
  1933. // if coming back from DRVUPD_FINISH page, search is done,
  1934. // so wait for instructions from user.
  1935. //
  1936. else {
  1937. PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK | PSWIZB_NEXT);
  1938. }
  1939. }
  1940. break;
  1941. case PSN_WIZNEXT:
  1942. NewDevWiz->EnterInto = IDD_NEWDEVWIZ_INSTALLDEV;
  1943. if (NewDevWiz->DoAutoInstall) {
  1944. //
  1945. // This is the case where we found a better driver (or a driver in the
  1946. // Found New Hardware case) and so we will just do an AutoInstall.
  1947. //
  1948. SetDlgMsgResult(hDlg, message, IDD_NEWDEVWIZ_INSTALLDEV);
  1949. } else if (NewDevWiz->CurrentDriverIsSelected) {
  1950. //
  1951. // This is the case where the current driver is the best driver.
  1952. //
  1953. SetDlgMsgResult(hDlg, message, IDD_NEWDEVWIZ_USECURRENT_FINISH);
  1954. } else if (NewDevWiz->NoDriversFound) {
  1955. //
  1956. // This is the case where we could not find any drivers for this device.
  1957. //
  1958. //
  1959. // If we could not find any drivers for this device then we have two choices,
  1960. // we either take the user to the Windows Update prompting wizard page,
  1961. // or take them directly to the no driver found finish page. We will only
  1962. // take them to the Windows Update prompting page if the AlreadySearchedInet
  1963. // BOOL is FALSE and the machine is NOT currently connected to the Internet.
  1964. //
  1965. if (!IsInternetAvailable(&NewDevWiz->hCdmInstance) ||
  1966. NewDevWiz->AlreadySearchedWU ||
  1967. IsConnectedToInternet()) {
  1968. SetDlgMsgResult(hDlg, message, IDD_NEWDEVWIZ_NODRIVER_FINISH);
  1969. } else {
  1970. SetDlgMsgResult(hDlg, message, IDD_NEWDEVWIZ_WUPROMPT);
  1971. }
  1972. } else {
  1973. //
  1974. // If we aren't doing an AutoInstall and this is NOT the current driver or
  1975. // NO driver case, then we need to jump to the page that lists out the drivers.
  1976. //
  1977. SetDlgMsgResult(hDlg, message, IDD_NEWDEVWIZ_LISTDRIVERS);
  1978. }
  1979. break;
  1980. case PSN_WIZBACK:
  1981. if (NewDevWiz->ExitDetect) {
  1982. SetDlgMsgResult(hDlg, message, -1);
  1983. break;
  1984. }
  1985. NewDevWiz->CurrentDriverIsSelected = FALSE;
  1986. NewDevWiz->ExitDetect = TRUE;
  1987. NewDevWiz->CurrCursor = NewDevWiz->IdcWait;
  1988. SetCursor(NewDevWiz->CurrCursor);
  1989. CancelDriverSearch(NewDevWiz);
  1990. NewDevWiz->CurrCursor = NULL;
  1991. EnableWindow(GetDlgItem(GetParent(hDlg), IDCANCEL), TRUE);
  1992. SetDlgMsgResult(hDlg, message, NewDevWiz->EnterFrom);
  1993. Animate_Stop(GetDlgItem(hDlg, IDC_ANIMATE_SEARCH));
  1994. break;
  1995. case PSN_QUERYCANCEL:
  1996. if (NewDevWiz->ExitDetect) {
  1997. SetDlgMsgResult(hDlg, message, TRUE);
  1998. break;
  1999. }
  2000. NewDevWiz->ExitDetect = TRUE;
  2001. NewDevWiz->CurrCursor = NewDevWiz->IdcWait;
  2002. SetCursor(NewDevWiz->CurrCursor);
  2003. CancelDriverSearch(NewDevWiz);
  2004. NewDevWiz->CurrCursor = NULL;
  2005. SetDlgMsgResult(hDlg, message, FALSE);
  2006. break;
  2007. case PSN_RESET:
  2008. Animate_Stop(GetDlgItem(hDlg, IDC_ANIMATE_SEARCH));
  2009. break;
  2010. default:
  2011. return FALSE;
  2012. }
  2013. break;
  2014. case WM_DESTROY:
  2015. CancelDriverSearch(NewDevWiz);
  2016. break;
  2017. case WUM_SEARCHDRIVERS: {
  2018. SP_DRVINFO_DATA DriverInfoData;
  2019. Animate_Stop(GetDlgItem(hDlg, IDC_ANIMATE_SEARCH));
  2020. ShowWindow(GetDlgItem(hDlg, IDC_ANIMATE_SEARCH), SW_HIDE);
  2021. NewDevWiz->CurrCursor = NULL;
  2022. SetCursor(NewDevWiz->IdcArrow);
  2023. if (NewDevWiz->ExitDetect) {
  2024. break;
  2025. }
  2026. DriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
  2027. if (SetupDiGetSelectedDriver(NewDevWiz->hDeviceInfo,
  2028. &NewDevWiz->DeviceInfoData,
  2029. &DriverInfoData
  2030. ))
  2031. {
  2032. //
  2033. // We basically have three cases when we find a driver for the device.
  2034. // 1) The driver is autoinstallable. This means we jump directly to the install page.
  2035. // 2) The driver is the current driver. This means we don't reinstall the driver.
  2036. // 3) We have muliple drivers or the drivers aren't autoinstallable. This means we
  2037. // show a list of the drivers to the user and make them pick.
  2038. //
  2039. NewDevWiz->NoDriversFound = FALSE;
  2040. //
  2041. // If this driver is Auto Installable then we will skip stoping at the Install
  2042. // confirmation page.
  2043. //
  2044. NewDevWiz->DoAutoInstall = IsDriverAutoInstallable(NewDevWiz, &DriverInfoData);
  2045. //
  2046. // If the selected driver is the currently installed driver then jump to the currently
  2047. // installed driver finish page.
  2048. //
  2049. if (IsInstalledDriver(NewDevWiz, &DriverInfoData)) {
  2050. NewDevWiz->CurrentDriverIsSelected = TRUE;
  2051. }
  2052. } else {
  2053. //
  2054. // This is the case where we could not get a selected driver because we didn't
  2055. // find any drivers in the driver search.
  2056. //
  2057. NewDevWiz->NoDriversFound = TRUE;
  2058. }
  2059. //
  2060. // Auto Jump to the next page.
  2061. //
  2062. PropSheet_PressButton(GetParent(hDlg), PSBTN_NEXT);
  2063. break;
  2064. }
  2065. case WM_SETCURSOR:
  2066. if (NewDevWiz->CurrCursor) {
  2067. SetCursor(NewDevWiz->CurrCursor);
  2068. break;
  2069. }
  2070. // fall thru to return(FALSE);
  2071. default:
  2072. return FALSE;
  2073. } // end of switch on message
  2074. return TRUE;
  2075. }
  2076. INT_PTR CALLBACK
  2077. WUPromptDlgProc(
  2078. HWND hDlg,
  2079. UINT message,
  2080. WPARAM wParam,
  2081. LPARAM lParam
  2082. )
  2083. {
  2084. static int pEnterFrom;
  2085. static DWORD dwWizCase = 0;
  2086. HICON hicon;
  2087. PNEWDEVWIZ NewDevWiz = (PNEWDEVWIZ)GetWindowLongPtr(hDlg, DWLP_USER);
  2088. switch (message) {
  2089. case WM_INITDIALOG: {
  2090. LPPROPSHEETPAGE lppsp = (LPPROPSHEETPAGE)lParam;
  2091. NewDevWiz = (PNEWDEVWIZ)lppsp->lParam;
  2092. SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)NewDevWiz);
  2093. //
  2094. // Set the Initial radio button state to connect to the Internet.
  2095. //
  2096. CheckRadioButton(hDlg,
  2097. IDC_WU_SEARCHINET,
  2098. IDC_WU_NOSEARCH,
  2099. IDC_WU_SEARCHINET
  2100. );
  2101. pEnterFrom = NewDevWiz->EnterFrom;
  2102. }
  2103. break;
  2104. case WM_DESTROY:
  2105. hicon = (HICON)LOWORD(SendDlgItemMessage(hDlg, IDC_CLASSICON, STM_GETICON, 0, 0));
  2106. if (hicon) {
  2107. DestroyIcon(hicon);
  2108. }
  2109. break;
  2110. case WM_NOTIFY:
  2111. switch (((NMHDR FAR *)lParam)->code) {
  2112. case PSN_SETACTIVE:
  2113. NewDevWiz->PrevPage = IDD_NEWDEVWIZ_WUPROMPT;
  2114. PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK | PSWIZB_NEXT);
  2115. hicon = NULL;
  2116. if (NewDevWiz->ClassGuidSelected &&
  2117. SetupDiLoadClassIcon(NewDevWiz->ClassGuidSelected, &hicon, NULL))
  2118. {
  2119. hicon = (HICON)SendDlgItemMessage(hDlg, IDC_CLASSICON, STM_SETICON, (WPARAM)hicon, 0L);
  2120. }
  2121. else {
  2122. SetupDiLoadClassIcon(&GUID_DEVCLASS_UNKNOWN, &hicon, NULL);
  2123. hicon = (HICON)SendDlgItemMessage(hDlg, IDC_CLASSICON, STM_SETICON, (WPARAM)hicon, 0L);
  2124. }
  2125. if (hicon) {
  2126. DestroyIcon(hicon);
  2127. }
  2128. SetDriverDescription(hDlg, IDC_DRVUPD_DRVDESC, NewDevWiz);
  2129. break;
  2130. case PSN_RESET:
  2131. break;
  2132. case PSN_WIZNEXT:
  2133. NewDevWiz->AlreadySearchedWU = TRUE;
  2134. NewDevWiz->EnterFrom = IDD_NEWDEVWIZ_WUPROMPT;
  2135. //
  2136. // Set the SEARCH_INET search option and go to the searching
  2137. // wizard page.
  2138. //
  2139. if (IsDlgButtonChecked(hDlg, IDC_WU_SEARCHINET)) {
  2140. NewDevWiz->SearchOptions = SEARCH_INET;
  2141. SetDlgMsgResult(hDlg, message, IDD_NEWDEVWIZ_SEARCHING);
  2142. } else {
  2143. SetDlgMsgResult(hDlg, message, IDD_NEWDEVWIZ_NODRIVER_FINISH);
  2144. }
  2145. break;
  2146. case PSN_WIZBACK:
  2147. NewDevWiz->AlreadySearchedWU = FALSE;
  2148. SetDlgMsgResult(hDlg, message, pEnterFrom);
  2149. break;
  2150. }
  2151. break;
  2152. default:
  2153. return(FALSE);
  2154. }
  2155. return(TRUE);
  2156. }
  2157. void
  2158. FillDriversList(
  2159. HWND hwndList,
  2160. PNEWDEVWIZ NewDevWiz,
  2161. int SignedIconIndex,
  2162. int UnsignedIconIndex
  2163. )
  2164. {
  2165. int IndexDriver;
  2166. int SelectedDriver;
  2167. int lvIndex;
  2168. LV_ITEM lviItem;
  2169. BOOL FoundInstalledDriver;
  2170. BOOL FoundSelectedDriver;
  2171. SP_DRVINFO_DATA DriverInfoData;
  2172. SP_DRVINFO_DETAIL_DATA DriverInfoDetailData;
  2173. SP_DRVINSTALL_PARAMS DriverInstallParams;
  2174. SendMessage(hwndList, WM_SETREDRAW, FALSE, 0L);
  2175. ListView_DeleteAllItems(hwndList);
  2176. ListView_SetExtendedListViewStyle(hwndList, LVS_EX_LABELTIP | LVS_EX_FULLROWSELECT);
  2177. IndexDriver = 0;
  2178. SelectedDriver = 0;
  2179. DriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
  2180. DriverInfoDetailData.cbSize = sizeof(DriverInfoDetailData);
  2181. FoundInstalledDriver = FALSE;
  2182. FoundSelectedDriver = FALSE;
  2183. while (SetupDiEnumDriverInfo(NewDevWiz->hDeviceInfo,
  2184. &NewDevWiz->DeviceInfoData,
  2185. SPDIT_COMPATDRIVER,
  2186. IndexDriver,
  2187. &DriverInfoData
  2188. )) {
  2189. //
  2190. // Get the DriverInstallParams so we can see if we got this driver from the Internet
  2191. //
  2192. DriverInstallParams.cbSize = sizeof(SP_DRVINSTALL_PARAMS);
  2193. if (SetupDiGetDriverInstallParams(NewDevWiz->hDeviceInfo,
  2194. &NewDevWiz->DeviceInfoData,
  2195. &DriverInfoData,
  2196. &DriverInstallParams)) {
  2197. //
  2198. // Don't show old Internet drivers because we don't have the files locally
  2199. // anymore to install these! Also don't show BAD drivers.
  2200. //
  2201. if ((DriverInstallParams.Flags & DNF_OLD_INET_DRIVER) ||
  2202. (DriverInstallParams.Flags & DNF_BAD_DRIVER)) {
  2203. IndexDriver++;
  2204. continue;
  2205. }
  2206. lviItem.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
  2207. lviItem.iItem = IndexDriver;
  2208. lviItem.iSubItem = 0;
  2209. lviItem.pszText = DriverInfoData.Description;
  2210. lviItem.lParam = 0;
  2211. lviItem.iImage = (DriverInstallParams.Flags & DNF_INF_IS_SIGNED)
  2212. ? SignedIconIndex
  2213. : UnsignedIconIndex;
  2214. //
  2215. // If this is the currently installed driver then set the DRIVER_LIST_CURRENT_DRIVER
  2216. // flag in the lParam.
  2217. //
  2218. if (!FoundInstalledDriver &&
  2219. (NewDevWiz->InstallType == NDWTYPE_UPDATE) &&
  2220. IsInstalledDriver(NewDevWiz, &DriverInfoData)) {
  2221. lviItem.lParam |= DRIVER_LIST_CURRENT_DRIVER;
  2222. }
  2223. //
  2224. // If this is the selected driver then set the DRIVER_LIST_SELECTED_DRIVER
  2225. // flag in the lParam
  2226. //
  2227. if (!FoundSelectedDriver &&
  2228. IsSelectedDriver(NewDevWiz, &DriverInfoData)) {
  2229. lviItem.lParam |= DRIVER_LIST_SELECTED_DRIVER;
  2230. SelectedDriver = IndexDriver;
  2231. }
  2232. if (DriverInstallParams.Flags & DNF_INF_IS_SIGNED) {
  2233. lviItem.lParam |= DRIVER_LIST_SIGNED_DRIVER;
  2234. }
  2235. lvIndex = ListView_InsertItem(hwndList, &lviItem);
  2236. if (DriverInfoData.DriverVersion != 0) {
  2237. ULARGE_INTEGER Version;
  2238. TCHAR VersionString[LINE_LEN];
  2239. Version.QuadPart = DriverInfoData.DriverVersion;
  2240. wsprintf(VersionString, TEXT("%0d.%0d.%0d.%0d"),
  2241. HIWORD(Version.HighPart), LOWORD(Version.HighPart),
  2242. HIWORD(Version.LowPart), LOWORD(Version.LowPart));
  2243. ListView_SetItemText(hwndList, lvIndex, 1, VersionString);
  2244. } else {
  2245. ListView_SetItemText(hwndList, lvIndex, 1, szUnknown);
  2246. }
  2247. ListView_SetItemText(hwndList, lvIndex, 2, DriverInfoData.MfgName);
  2248. if (DriverInstallParams.Flags & DNF_INET_DRIVER) {
  2249. //
  2250. // Driver is from the Internet
  2251. //
  2252. TCHAR WindowsUpdate[MAX_PATH];
  2253. LoadString(hNewDev, IDS_DEFAULT_INTERNET_HOST, WindowsUpdate, SIZECHARS(WindowsUpdate));
  2254. ListView_SetItemText(hwndList, lvIndex, 3, WindowsUpdate);
  2255. } else {
  2256. //
  2257. // Driver is not from the Internet
  2258. //
  2259. if (SetupDiGetDriverInfoDetail(NewDevWiz->hDeviceInfo,
  2260. &NewDevWiz->DeviceInfoData,
  2261. &DriverInfoData,
  2262. &DriverInfoDetailData,
  2263. sizeof(DriverInfoDetailData),
  2264. NULL
  2265. )
  2266. ||
  2267. GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
  2268. ListView_SetItemText(hwndList, lvIndex, 3, DriverInfoDetailData.InfFileName);
  2269. } else {
  2270. ListView_SetItemText(hwndList, lvIndex, 3, TEXT(""));
  2271. }
  2272. }
  2273. }
  2274. IndexDriver++;
  2275. }
  2276. //
  2277. // Select the SelectedDriver item in the list and scroll it into view
  2278. // since this is the best driver in the list.
  2279. //
  2280. ListView_SetItemState(hwndList,
  2281. SelectedDriver,
  2282. LVIS_SELECTED|LVIS_FOCUSED,
  2283. LVIS_SELECTED|LVIS_FOCUSED
  2284. );
  2285. ListView_EnsureVisible(hwndList, SelectedDriver, FALSE);
  2286. ListView_SetColumnWidth(hwndList, 0, LVSCW_AUTOSIZE_USEHEADER);
  2287. ListView_SetColumnWidth(hwndList, 1, LVSCW_AUTOSIZE_USEHEADER);
  2288. ListView_SetColumnWidth(hwndList, 2, LVSCW_AUTOSIZE_USEHEADER);
  2289. ListView_SetColumnWidth(hwndList, 3, LVSCW_AUTOSIZE_USEHEADER);
  2290. SendMessage(hwndList, WM_SETREDRAW, TRUE, 0L);
  2291. }
  2292. BOOL
  2293. SelectDriverFromList(
  2294. HWND hwndList,
  2295. PNEWDEVWIZ NewDevWiz
  2296. )
  2297. {
  2298. int lvSelected;
  2299. SP_DRVINFO_DATA DriverInfoData;
  2300. LVITEM lvi;
  2301. DriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
  2302. lvSelected = ListView_GetNextItem(hwndList,
  2303. -1,
  2304. LVNI_SELECTED
  2305. );
  2306. if (SetupDiEnumDriverInfo(NewDevWiz->hDeviceInfo,
  2307. &NewDevWiz->DeviceInfoData,
  2308. SPDIT_COMPATDRIVER,
  2309. lvSelected,
  2310. &DriverInfoData
  2311. ))
  2312. {
  2313. SetupDiSetSelectedDriver(NewDevWiz->hDeviceInfo,
  2314. &NewDevWiz->DeviceInfoData,
  2315. &DriverInfoData
  2316. );
  2317. }
  2318. //
  2319. // if there is no selected driver call DIF_SELECTBESTCOMPATDRV.
  2320. //
  2321. if (!SetupDiGetSelectedDriver(NewDevWiz->hDeviceInfo,
  2322. &NewDevWiz->DeviceInfoData,
  2323. &DriverInfoData
  2324. ))
  2325. {
  2326. if (SetupDiEnumDriverInfo(NewDevWiz->hDeviceInfo,
  2327. &NewDevWiz->DeviceInfoData,
  2328. SPDIT_COMPATDRIVER,
  2329. 0,
  2330. &DriverInfoData
  2331. ))
  2332. {
  2333. //
  2334. //Pick the best driver from the list we just created
  2335. //
  2336. SetupDiCallClassInstaller(DIF_SELECTBESTCOMPATDRV,
  2337. NewDevWiz->hDeviceInfo,
  2338. &NewDevWiz->DeviceInfoData
  2339. );
  2340. }
  2341. else
  2342. {
  2343. SetupDiSetSelectedDriver(NewDevWiz->hDeviceInfo,
  2344. &NewDevWiz->DeviceInfoData,
  2345. NULL
  2346. );
  2347. }
  2348. }
  2349. //
  2350. // Return TRUE if the selected driver in the list is the current driver, otherwise return FALSE
  2351. //
  2352. ZeroMemory(&lvi, sizeof(lvi));
  2353. lvi.iItem = lvSelected;
  2354. lvi.mask = LVIF_PARAM;
  2355. if (ListView_GetItem(hwndList, &lvi) &&
  2356. (lvi.lParam & DRIVER_LIST_CURRENT_DRIVER)) {
  2357. return(TRUE);
  2358. }
  2359. return(FALSE);
  2360. }
  2361. INT_PTR CALLBACK
  2362. ListDriversDlgProc(
  2363. HWND hDlg,
  2364. UINT message,
  2365. WPARAM wParam,
  2366. LPARAM lParam
  2367. )
  2368. {
  2369. PNEWDEVWIZ NewDevWiz = (PNEWDEVWIZ)GetWindowLongPtr(hDlg, DWLP_USER);
  2370. static int pEnterFrom;
  2371. static HIMAGELIST himl = NULL;
  2372. static int SignedIconIndex, UnsignedIconIndex;
  2373. switch (message) {
  2374. case WM_INITDIALOG: {
  2375. HWND hwndParentDlg;
  2376. HWND hwndList;
  2377. LV_COLUMN lvcCol;
  2378. LPPROPSHEETPAGE lppsp = (LPPROPSHEETPAGE)lParam;
  2379. TCHAR Buffer[64];
  2380. HFONT hfont;
  2381. LOGFONT LogFont;
  2382. NewDevWiz = (PNEWDEVWIZ)lppsp->lParam;
  2383. SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)NewDevWiz);
  2384. pEnterFrom = NewDevWiz->EnterFrom;
  2385. //
  2386. // Create the normal and bold fonts
  2387. //
  2388. hfont = (HFONT)SendMessage(GetDlgItem(hDlg, IDC_SIGNED_TEXT), WM_GETFONT, 0, 0);
  2389. GetObject(hfont, sizeof(LogFont), &LogFont);
  2390. NewDevWiz->hfontTextNormal = CreateFontIndirect(&LogFont);
  2391. hfont = (HFONT)SendMessage(GetDlgItem(hDlg, IDC_SIGNED_TEXT), WM_GETFONT, 0, 0);
  2392. GetObject(hfont, sizeof(LogFont), &LogFont);
  2393. LogFont.lfWeight = FW_BOLD;
  2394. NewDevWiz->hfontTextBold = CreateFontIndirect(&LogFont);
  2395. hwndList = GetDlgItem(hDlg, IDC_LISTDRIVERS_LISTVIEW);
  2396. //
  2397. // Create the image list that contains the signed and not signed icons.
  2398. //
  2399. himl = ImageList_Create(GetSystemMetrics(SM_CXSMICON),
  2400. GetSystemMetrics(SM_CYSMICON),
  2401. ILC_MASK |
  2402. (GetWindowLong(GetParent(hDlg), GWL_EXSTYLE) & WS_EX_LAYOUTRTL)
  2403. ? ILC_MIRROR
  2404. : 0,
  2405. 1,
  2406. 1);
  2407. //
  2408. // Associate the image list with the list view.
  2409. //
  2410. if (himl) {
  2411. HICON hIcon;
  2412. ImageList_SetBkColor(himl, GetSysColor(COLOR_WINDOW));
  2413. //
  2414. // Add the signed and unsigned icons to the imagelist.
  2415. //
  2416. if ((hIcon = LoadIcon(hNewDev, MAKEINTRESOURCE(IDI_BLANK))) != NULL) {
  2417. UnsignedIconIndex = ImageList_AddIcon(himl, hIcon);
  2418. }
  2419. if ((hIcon = LoadIcon(hNewDev, MAKEINTRESOURCE(IDI_SIGNED))) != NULL) {
  2420. SignedIconIndex = ImageList_AddIcon(himl, hIcon);
  2421. }
  2422. ListView_SetImageList(hwndList,
  2423. himl,
  2424. LVSIL_SMALL
  2425. );
  2426. }
  2427. //
  2428. // Insert columns for listview.
  2429. // 0 == device name
  2430. // 1 == version
  2431. // 2 == manufacturer
  2432. // 3 == INF location
  2433. //
  2434. lvcCol.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
  2435. lvcCol.fmt = LVCFMT_LEFT;
  2436. lvcCol.pszText = Buffer;
  2437. lvcCol.iSubItem = 0;
  2438. LoadString(hNewDev, IDS_DRIVERDESC, Buffer, SIZECHARS(Buffer));
  2439. ListView_InsertColumn(hwndList, 0, &lvcCol);
  2440. lvcCol.iSubItem = 1;
  2441. LoadString(hNewDev, IDS_DRIVERVERSION, Buffer, SIZECHARS(Buffer));
  2442. ListView_InsertColumn(hwndList, 1, &lvcCol);
  2443. lvcCol.iSubItem = 2;
  2444. LoadString(hNewDev, IDS_DRIVERMFG, Buffer, SIZECHARS(Buffer));
  2445. ListView_InsertColumn(hwndList, 2, &lvcCol);
  2446. lvcCol.iSubItem = 3;
  2447. LoadString(hNewDev, IDS_DRIVERINF, Buffer, SIZECHARS(Buffer));
  2448. ListView_InsertColumn(hwndList, 3, &lvcCol);
  2449. SendMessage(hwndList,
  2450. LVM_SETEXTENDEDLISTVIEWSTYLE,
  2451. LVS_EX_FULLROWSELECT,
  2452. LVS_EX_FULLROWSELECT
  2453. );
  2454. }
  2455. break;
  2456. case WM_DESTROY:
  2457. if (NewDevWiz->hfontTextNormal ) {
  2458. DeleteObject(NewDevWiz->hfontTextNormal);
  2459. NewDevWiz->hfontTextBigBold = NULL;
  2460. }
  2461. if (NewDevWiz->hfontTextBold ) {
  2462. DeleteObject(NewDevWiz->hfontTextBold);
  2463. NewDevWiz->hfontTextBold = NULL;
  2464. }
  2465. if (himl) {
  2466. ImageList_Destroy(himl);
  2467. }
  2468. break;
  2469. case WM_NOTIFY:
  2470. switch (((NMHDR FAR *)lParam)->code) {
  2471. case PSN_SETACTIVE: {
  2472. int PrevPage;
  2473. HICON hicon;
  2474. PrevPage = NewDevWiz->PrevPage;
  2475. NewDevWiz->PrevPage = IDD_NEWDEVWIZ_LISTDRIVERS;
  2476. SetDriverDescription(hDlg, IDC_DRVUPD_DRVDESC, NewDevWiz);
  2477. ShowWindow(GetDlgItem(hDlg, IDC_SIGNED_ICON), SW_HIDE);
  2478. ShowWindow(GetDlgItem(hDlg, IDC_SIGNED_TEXT), SW_HIDE);
  2479. ShowWindow(GetDlgItem(hDlg, IDC_SIGNED_LINK), SW_HIDE);
  2480. hicon = NULL;
  2481. if (NewDevWiz->ClassGuidSelected &&
  2482. SetupDiLoadClassIcon(NewDevWiz->ClassGuidSelected, &hicon, NULL)) {
  2483. hicon = (HICON)SendDlgItemMessage(hDlg, IDC_CLASSICON, STM_SETICON, (WPARAM)hicon, 0L);
  2484. } else {
  2485. SetupDiLoadClassIcon(&GUID_DEVCLASS_UNKNOWN, &hicon, NULL);
  2486. SendDlgItemMessage(hDlg, IDC_CLASSICON, STM_SETICON, (WPARAM)hicon, 0L);
  2487. }
  2488. if (hicon) {
  2489. DestroyIcon(hicon);
  2490. }
  2491. //
  2492. // Fill the list view
  2493. //
  2494. FillDriversList(GetDlgItem(hDlg, IDC_LISTDRIVERS_LISTVIEW),
  2495. NewDevWiz,
  2496. SignedIconIndex,
  2497. UnsignedIconIndex);
  2498. }
  2499. break;
  2500. case PSN_RESET:
  2501. break;
  2502. case PSN_WIZBACK:
  2503. SetDlgMsgResult(hDlg, message, pEnterFrom);
  2504. break;
  2505. case PSN_WIZNEXT:
  2506. NewDevWiz->EnterFrom = IDD_NEWDEVWIZ_LISTDRIVERS;
  2507. if (SelectDriverFromList(GetDlgItem(hDlg, IDC_LISTDRIVERS_LISTVIEW), NewDevWiz)) {
  2508. NewDevWiz->EnterInto = IDD_NEWDEVWIZ_USECURRENT_FINISH;
  2509. SetDlgMsgResult(hDlg, message, IDD_NEWDEVWIZ_USECURRENT_FINISH);
  2510. } else {
  2511. NewDevWiz->EnterInto = IDD_NEWDEVWIZ_INSTALLDEV;
  2512. SetDlgMsgResult(hDlg, message, IDD_NEWDEVWIZ_INSTALLDEV);
  2513. }
  2514. break;
  2515. case LVN_ITEMCHANGED: {
  2516. LPNM_LISTVIEW lpnmlv = (LPNM_LISTVIEW)lParam;
  2517. int StringId = 0;
  2518. int DigitalSignatureSignedId = 0;
  2519. HICON hIcon = NULL;
  2520. if ((lpnmlv->uChanged & LVIF_STATE)) {
  2521. if (lpnmlv->uNewState & LVIS_SELECTED) {
  2522. //
  2523. // lParam & DRIVER_LIST_CURRENT_DRIVER means this is the currently installed driver.
  2524. // lParam & DRIVER_LIST_SELECTED_DRIVER means this is the selected/best driver.
  2525. //
  2526. if (lpnmlv->lParam & DRIVER_LIST_CURRENT_DRIVER) {
  2527. StringId = IDS_DRIVER_CURR;
  2528. }
  2529. DigitalSignatureSignedId = (lpnmlv->lParam & DRIVER_LIST_SIGNED_DRIVER)
  2530. ? IDS_DRIVER_IS_SIGNED
  2531. : IDS_DRIVER_NOT_SIGNED;
  2532. hIcon = LoadImage(hNewDev,
  2533. (lpnmlv->lParam & DRIVER_LIST_SIGNED_DRIVER)
  2534. ? MAKEINTRESOURCE(IDI_SIGNED)
  2535. : MAKEINTRESOURCE(IDI_WARN),
  2536. IMAGE_ICON,
  2537. GetSystemMetrics(SM_CXSMICON),
  2538. GetSystemMetrics(SM_CYSMICON),
  2539. 0
  2540. );
  2541. if (NewDevWiz->hfontTextNormal && NewDevWiz->hfontTextBold) {
  2542. SetWindowFont(GetDlgItem(hDlg, IDC_SIGNED_TEXT),
  2543. (lpnmlv->lParam & DRIVER_LIST_SIGNED_DRIVER)
  2544. ? NewDevWiz->hfontTextNormal
  2545. : NewDevWiz->hfontTextBold,
  2546. TRUE
  2547. );
  2548. }
  2549. ShowWindow(GetDlgItem(hDlg, IDC_SIGNED_ICON), SW_SHOW);
  2550. ShowWindow(GetDlgItem(hDlg, IDC_SIGNED_TEXT), SW_SHOW);
  2551. ShowWindow(GetDlgItem(hDlg, IDC_SIGNED_LINK), SW_SHOW);
  2552. PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK | PSWIZB_NEXT);
  2553. } else {
  2554. ShowWindow(GetDlgItem(hDlg, IDC_SIGNED_ICON), SW_HIDE);
  2555. ShowWindow(GetDlgItem(hDlg, IDC_SIGNED_TEXT), SW_HIDE);
  2556. ShowWindow(GetDlgItem(hDlg, IDC_SIGNED_LINK), SW_HIDE);
  2557. PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK);
  2558. }
  2559. if (!StringId) {
  2560. SetDlgItemText(hDlg, IDC_NDW_TEXT, TEXT(""));
  2561. } else {
  2562. SetDlgText(hDlg, IDC_NDW_TEXT, StringId, StringId);
  2563. }
  2564. if (!DigitalSignatureSignedId) {
  2565. SetDlgItemText(hDlg, IDC_SIGNED_TEXT, TEXT(""));
  2566. } else {
  2567. SetDlgText(hDlg, IDC_SIGNED_TEXT, DigitalSignatureSignedId, DigitalSignatureSignedId);
  2568. }
  2569. if (hIcon) {
  2570. hIcon = (HICON)SendDlgItemMessage(hDlg,
  2571. IDC_SIGNED_ICON,
  2572. STM_SETICON,
  2573. (WPARAM)hIcon,
  2574. 0L
  2575. );
  2576. }
  2577. if (hIcon) {
  2578. DestroyIcon(hIcon);
  2579. }
  2580. }
  2581. }
  2582. break;
  2583. case NM_RETURN:
  2584. case NM_CLICK:
  2585. if((((LPNMHDR)lParam)->idFrom) == IDC_SIGNED_LINK) {
  2586. ShellExecute(hDlg,
  2587. TEXT("open"),
  2588. TEXT("HELPCTR.EXE"),
  2589. TEXT("HELPCTR.EXE -url hcp://services/subsite?node=TopLevelBucket_4/Hardware&topic=MS-ITS%3A%25HELP_LOCATION%25%5Csysdm.chm%3A%3A/logo_testing.htm"),
  2590. NULL,
  2591. SW_SHOWNORMAL
  2592. );
  2593. }
  2594. break;
  2595. }
  2596. break;
  2597. default:
  2598. return(FALSE);
  2599. }
  2600. return(TRUE);
  2601. }
  2602. INT_PTR CALLBACK
  2603. UseCurrentDlgProc(
  2604. HWND hDlg,
  2605. UINT message,
  2606. WPARAM wParam,
  2607. LPARAM lParam
  2608. )
  2609. {
  2610. PNEWDEVWIZ NewDevWiz = (PNEWDEVWIZ)GetWindowLongPtr(hDlg, DWLP_USER);
  2611. switch (message) {
  2612. case WM_INITDIALOG: {
  2613. LPPROPSHEETPAGE lppsp = (LPPROPSHEETPAGE)lParam;
  2614. NewDevWiz = (PNEWDEVWIZ)lppsp->lParam;
  2615. SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)NewDevWiz);
  2616. if (NewDevWiz->hfontTextBigBold) {
  2617. SetWindowFont(GetDlgItem(hDlg, IDC_FINISH_MSG1), NewDevWiz->hfontTextBigBold, TRUE);
  2618. }
  2619. }
  2620. break;
  2621. case WM_DESTROY:
  2622. break;
  2623. case WM_NOTIFY:
  2624. switch (((NMHDR FAR *)lParam)->code) {
  2625. case PSN_SETACTIVE:
  2626. NewDevWiz->PrevPage = IDD_NEWDEVWIZ_USECURRENT_FINISH;
  2627. PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK | PSWIZB_FINISH);
  2628. break;
  2629. case PSN_RESET:
  2630. break;
  2631. case PSN_WIZBACK:
  2632. NewDevWiz->CurrentDriverIsSelected = FALSE;
  2633. SetDlgMsgResult(hDlg, message, NewDevWiz->EnterFrom);
  2634. break;
  2635. }
  2636. break;
  2637. default:
  2638. return(FALSE);
  2639. }
  2640. return(TRUE);
  2641. }
  2642. INT_PTR
  2643. InitNoDriversDlgProc(
  2644. HWND hDlg,
  2645. PNEWDEVWIZ NewDevWiz
  2646. )
  2647. {
  2648. if (NewDevWiz->hfontTextBigBold) {
  2649. SetWindowFont(GetDlgItem(hDlg, IDC_FINISH_MSG1), NewDevWiz->hfontTextBigBold, TRUE);
  2650. }
  2651. if (NDWTYPE_UPDATE == NewDevWiz->InstallType) {
  2652. ShowWindow(GetDlgItem(hDlg, IDC_FINISH_MSG3), SW_HIDE);
  2653. ShowWindow(GetDlgItem(hDlg, IDC_HELPCENTER_ICON), SW_HIDE);
  2654. ShowWindow(GetDlgItem(hDlg, IDC_HELPCENTER_TEXT), SW_HIDE);
  2655. ShowWindow(GetDlgItem(hDlg, IDC_FINISH_PROMPT), SW_HIDE);
  2656. } else {
  2657. CheckDlgButton(hDlg, IDC_FINISH_PROMPT, BST_CHECKED);
  2658. //
  2659. // If this user has the policy set to not send the Hardware Id to Windows
  2660. // Update then don't put in the text about launching help center.
  2661. //
  2662. if (GetLogPnPIdPolicy() == FALSE) {
  2663. ShowWindow(GetDlgItem(hDlg, IDC_FINISH_MSG3), SW_HIDE);
  2664. ShowWindow(GetDlgItem(hDlg, IDC_HELPCENTER_ICON), SW_HIDE);
  2665. ShowWindow(GetDlgItem(hDlg, IDC_HELPCENTER_TEXT), SW_HIDE);
  2666. }
  2667. }
  2668. return TRUE;
  2669. }
  2670. INT_PTR CALLBACK
  2671. NoDriverDlgProc(
  2672. HWND hDlg,
  2673. UINT message,
  2674. WPARAM wParam,
  2675. LPARAM lParam
  2676. )
  2677. {
  2678. PNEWDEVWIZ NewDevWiz = (PNEWDEVWIZ)GetWindowLongPtr(hDlg, DWLP_USER);
  2679. HICON hicon;
  2680. switch (message) {
  2681. case WM_INITDIALOG: {
  2682. LPPROPSHEETPAGE lppsp = (LPPROPSHEETPAGE)lParam;
  2683. NewDevWiz = (PNEWDEVWIZ)lppsp->lParam;
  2684. SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)NewDevWiz);
  2685. InitNoDriversDlgProc(hDlg, NewDevWiz);
  2686. }
  2687. break;
  2688. case WM_DESTROY:
  2689. break;
  2690. case WM_NOTIFY:
  2691. switch (((NMHDR FAR *)lParam)->code) {
  2692. case PSN_SETACTIVE:
  2693. NewDevWiz->PrevPage = IDD_NEWDEVWIZ_USECURRENT_FINISH;
  2694. //
  2695. // Set the Help Center icon next to the text
  2696. //
  2697. hicon = LoadImage(hNewDev,
  2698. MAKEINTRESOURCE(IDI_HELPCENTER),
  2699. IMAGE_ICON,
  2700. GetSystemMetrics(SM_CXSMICON),
  2701. GetSystemMetrics(SM_CYSMICON),
  2702. 0
  2703. );
  2704. if (hicon) {
  2705. hicon = (HICON)SendDlgItemMessage(hDlg, IDC_HELPCENTER_ICON, STM_SETICON, (WPARAM)hicon, 0L);
  2706. }
  2707. if (hicon) {
  2708. DestroyIcon(hicon);
  2709. }
  2710. //
  2711. // Set the Info icon next to the text
  2712. //
  2713. hicon = LoadImage(hNewDev,
  2714. MAKEINTRESOURCE(IDI_INFO),
  2715. IMAGE_ICON,
  2716. GetSystemMetrics(SM_CXSMICON),
  2717. GetSystemMetrics(SM_CYSMICON),
  2718. 0
  2719. );
  2720. if (hicon) {
  2721. hicon = (HICON)SendDlgItemMessage(hDlg, IDC_INFO_ICON, STM_SETICON, (WPARAM)hicon, 0L);
  2722. }
  2723. if (hicon) {
  2724. DestroyIcon(hicon);
  2725. }
  2726. if (NewDevWiz->InstallType == NDWTYPE_FOUNDNEW) {
  2727. SetTimer(hDlg, INSTALL_COMPLETE_CHECK_TIMERID, INSTALL_COMPLETE_CHECK_TIMEOUT, NULL);
  2728. }
  2729. PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK | PSWIZB_FINISH);
  2730. break;
  2731. case PSN_RESET:
  2732. KillTimer(hDlg, INSTALL_COMPLETE_CHECK_TIMERID);
  2733. break;
  2734. case PSN_WIZFINISH:
  2735. KillTimer(hDlg, INSTALL_COMPLETE_CHECK_TIMERID);
  2736. if (IsDlgButtonChecked(hDlg, IDC_FINISH_PROMPT)) {
  2737. InstallNullDriver(hDlg,
  2738. NewDevWiz,
  2739. (NewDevWiz->Capabilities & CM_DEVCAP_RAWDEVICEOK)
  2740. ? FALSE : TRUE
  2741. );
  2742. } else {
  2743. NewDevWiz->LastError = ERROR_CANCELLED;
  2744. }
  2745. //
  2746. // Set the BOOL that tells us to call CDM which will launch HelpCenter
  2747. // if we are in the Found New Hardware Wizard and if the user has the
  2748. // policy set to TRUE.
  2749. //
  2750. if ((NewDevWiz->InstallType == NDWTYPE_FOUNDNEW) &&
  2751. GetLogPnPIdPolicy()) {
  2752. NewDevWiz->CallHelpCenter = TRUE;
  2753. }
  2754. break;
  2755. case PSN_WIZBACK:
  2756. NewDevWiz->CurrentDriverIsSelected = FALSE;
  2757. SetDlgMsgResult(hDlg, message, NewDevWiz->EnterFrom);
  2758. KillTimer(hDlg, INSTALL_COMPLETE_CHECK_TIMERID);
  2759. break;
  2760. }
  2761. break;
  2762. case WM_TIMER:
  2763. if (INSTALL_COMPLETE_CHECK_TIMERID == wParam) {
  2764. if (IsInstallComplete(NewDevWiz->hDeviceInfo, &NewDevWiz->DeviceInfoData)) {
  2765. PropSheet_PressButton(GetParent(hDlg), PSBTN_CANCEL);
  2766. }
  2767. }
  2768. break;
  2769. default:
  2770. return(FALSE);
  2771. }
  2772. return(TRUE);
  2773. }