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

3194 lines
109 KiB

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