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.

1287 lines
35 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1998 - 1999
  6. //
  7. // File: detect.c
  8. //
  9. //--------------------------------------------------------------------------
  10. #include "hdwwiz.h"
  11. typedef
  12. UINT
  13. (*PINSTALLSELECTEDDEVICE)(
  14. HWND hwndParent,
  15. HDEVINFO hDeviceInfo,
  16. PDWORD pReboot
  17. );
  18. PINSTALLSELECTEDDEVICE pInstallSelectedDevice = NULL;
  19. /*
  20. * BuildMissingAndNew
  21. *
  22. * worker routine for BuildDeviceDetection.
  23. *
  24. * On entry:
  25. * Missing contains known devices prior to class installer detection.
  26. * Detected contains devices detected by class installer.
  27. * NewDevices is an empty list.
  28. *
  29. * If a device is in Missing and not in Detected, then it is missing.
  30. * If a device is in Detected and not in Missing, then it is newly detected.
  31. *
  32. * On Exit:
  33. * Missing contains only missing devices,
  34. * Detected gone.
  35. * NewDevices contains those that were newly detectd
  36. *
  37. */
  38. BOOL
  39. BuildMissingAndNew(
  40. HWND hwndParent,
  41. PCLASSDEVINFO ClassDevInfo
  42. )
  43. {
  44. HDEVINFO Missing, Detected;
  45. int iMissing, iDetect;
  46. ULONG DevNodeStatus, Problem;
  47. SP_DEVINFO_DATA DevInfoDataDetect;
  48. SP_DEVINFO_DATA DevInfoDataMissing;
  49. TCHAR DetectedId[MAX_DEVICE_ID_LEN +sizeof(TCHAR)];
  50. BOOL Removed;
  51. Detected = ClassDevInfo->Detected;
  52. Missing = ClassDevInfo->Missing;
  53. DevInfoDataMissing.cbSize = sizeof(DevInfoDataMissing);
  54. DevInfoDataDetect.cbSize = sizeof(DevInfoDataDetect);
  55. //
  56. // For each member of the detected list, fetch its Device ID
  57. // and see if it exists in the missing list.
  58. //
  59. BMNBuildDetectedList:
  60. Removed = FALSE;
  61. iMissing = 0;
  62. while (SetupDiEnumDeviceInfo(Missing, iMissing++, &DevInfoDataMissing)) {
  63. iDetect = 0;
  64. while (SetupDiEnumDeviceInfo(Detected, iDetect++, &DevInfoDataDetect)) {
  65. //
  66. // If Found in both lists, its not a new device and exists(not missing).
  67. // remove it from both lists.
  68. //
  69. if (DevInfoDataDetect.DevInst == DevInfoDataMissing.DevInst) {
  70. SetupDiDeleteDeviceInfo(Missing, &DevInfoDataMissing);
  71. SetupDiDeleteDeviceInfo(Detected, &DevInfoDataDetect);
  72. Removed = TRUE;
  73. break;
  74. }
  75. }
  76. }
  77. //
  78. // If a device info was removed, the enumeration index changes
  79. // and we will miss some in the list. Rescan until none are deleted.
  80. //
  81. if (Removed && SetupDiEnumDeviceInfo(Detected, 0, &DevInfoDataDetect)) {
  82. goto BMNBuildDetectedList;
  83. }
  84. //
  85. // Remove devices which are up and running from the misssing list,
  86. // since they are obviously present. Class installers may not report
  87. // all devices which are present, if they are already installed and
  88. // running. e.g. Bios enumerated devices. We also check that it is
  89. // a Root Enumerated Device (not a PnP BIOS device) and that it was
  90. // not a manually installed device.
  91. //
  92. BMNRemoveLiveFromMissing:
  93. Removed = FALSE;
  94. iMissing = 0;
  95. while (SetupDiEnumDeviceInfo(Missing, iMissing++, &DevInfoDataMissing)) {
  96. if ((CM_Get_DevNode_Status(&DevNodeStatus,
  97. &Problem,
  98. DevInfoDataMissing.DevInst,
  99. 0) == CR_SUCCESS) &&
  100. ((DevNodeStatus & DN_STARTED) &&
  101. !(DevNodeStatus & DN_HAS_PROBLEM)) ||
  102. !(DevNodeStatus & DN_ROOT_ENUMERATED) ||
  103. (DevNodeStatus & DN_MANUAL)) {
  104. SetupDiDeleteDeviceInfo(Missing, &DevInfoDataMissing);
  105. Removed = TRUE;
  106. }
  107. }
  108. if (Removed) {
  109. goto BMNRemoveLiveFromMissing;
  110. }
  111. //
  112. // Register the newly detected devices
  113. //
  114. BMNRegisterDetected:
  115. Removed = FALSE;
  116. iDetect = 0;
  117. while (SetupDiEnumDeviceInfo(Detected, iDetect++, &DevInfoDataDetect)) {
  118. if (!SetupDiCallClassInstaller(DIF_REGISTERDEVICE,
  119. Detected,
  120. &DevInfoDataDetect
  121. )) {
  122. SetupDiDeleteDeviceInfo(Detected, &DevInfoDataDetect);
  123. Removed = TRUE;
  124. }
  125. }
  126. if (Removed) {
  127. goto BMNRegisterDetected;
  128. }
  129. //
  130. // if the missing devices list is empty, don't need it anymore either
  131. //
  132. if (!SetupDiEnumDeviceInfo(Missing, 0, &DevInfoDataMissing)) {
  133. SetupDiDestroyDeviceInfoList(Missing);
  134. ClassDevInfo->Missing = NULL;
  135. }
  136. return SetupDiEnumDeviceInfo(Detected, 0, &DevInfoDataDetect) || ClassDevInfo->Missing;
  137. }
  138. BOOL
  139. DevInstIsSelected(
  140. HWND hwndListView,
  141. DEVINST DevInst
  142. )
  143. {
  144. LVITEM lvItem;
  145. lvItem.mask = LVIF_PARAM;
  146. lvItem.iSubItem = 0;
  147. lvItem.iItem = -1;
  148. while ((lvItem.iItem = ListView_GetNextItem(hwndListView, lvItem.iItem, LVNI_ALL)) != -1) {
  149. ListView_GetItem(hwndListView, &lvItem);
  150. if (lvItem.lParam == (LPARAM)DevInst) {
  151. // Image list is 0 based, and one means checked.
  152. return (ListView_GetCheckState(hwndListView, lvItem.iItem) == 1);
  153. }
  154. }
  155. return FALSE;
  156. }
  157. void
  158. RemoveDeviceInfo(
  159. HDEVINFO DeviceInfo,
  160. HWND hwndListView
  161. )
  162. {
  163. int Index;
  164. SP_REMOVEDEVICE_PARAMS RemoveDeviceParams;
  165. SP_DEVINFO_DATA DevInfoData;
  166. Index = 0;
  167. DevInfoData.cbSize = sizeof(DevInfoData);
  168. while (SetupDiEnumDeviceInfo(DeviceInfo, Index++, &DevInfoData)) {
  169. if (!hwndListView || DevInstIsSelected(hwndListView, DevInfoData.DevInst)) {
  170. RemoveDeviceParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
  171. RemoveDeviceParams.ClassInstallHeader.InstallFunction = DIF_REMOVE;
  172. RemoveDeviceParams.Scope = DI_REMOVEDEVICE_GLOBAL;
  173. RemoveDeviceParams.HwProfile = 0;
  174. if (SetupDiSetClassInstallParams(DeviceInfo,
  175. &DevInfoData,
  176. (PSP_CLASSINSTALL_HEADER)&RemoveDeviceParams,
  177. sizeof(RemoveDeviceParams)
  178. )) {
  179. SetupDiCallClassInstaller(DIF_REMOVE, DeviceInfo, &DevInfoData);
  180. }
  181. //
  182. // Clear the class install parameters.
  183. //
  184. SetupDiSetClassInstallParams(DeviceInfo,
  185. &DevInfoData,
  186. NULL,
  187. 0
  188. );
  189. }
  190. }
  191. SetupDiDestroyDeviceInfoList(DeviceInfo);
  192. }
  193. void
  194. DestroyClassDevinfo(
  195. PCLASSDEVINFO ClassDevInfo
  196. )
  197. {
  198. if (ClassDevInfo->Missing) {
  199. SetupDiDestroyDeviceInfoList(ClassDevInfo->Missing);
  200. ClassDevInfo->Missing = NULL;
  201. }
  202. if (ClassDevInfo->Detected) {
  203. SetupDiDestroyDeviceInfoList(ClassDevInfo->Detected);
  204. ClassDevInfo->Detected = NULL;
  205. }
  206. }
  207. void
  208. DestroyDeviceDetection(
  209. PHARDWAREWIZ HardwareWiz,
  210. BOOL DetectionCancelled
  211. )
  212. {
  213. int ClassGuidNum;
  214. PCLASSDEVINFO ClassDevInfo;
  215. LPGUID ClassGuid;
  216. if (!HardwareWiz->DeviceDetection) {
  217. return;
  218. }
  219. ClassGuidNum = HardwareWiz->ClassGuidNum;
  220. ClassGuid = HardwareWiz->ClassGuidList;
  221. ClassDevInfo = HardwareWiz->DeviceDetection->ClassDevInfo;
  222. while (ClassGuidNum--) {
  223. if (DetectionCancelled) {
  224. //
  225. // If there is a detected list,
  226. // then invoke the class installer DIF_DETECTCANCEL for its cleanup.
  227. //
  228. if (ClassDevInfo->Detected) {
  229. SetupDiCallClassInstaller(DIF_DETECTCANCEL, ClassDevInfo->Detected, NULL);
  230. //
  231. // Remove all newly detected devices.
  232. //
  233. if (ClassDevInfo->Detected) {
  234. RemoveDeviceInfo(ClassDevInfo->Detected, NULL);
  235. ClassDevInfo->Detected = NULL;
  236. }
  237. }
  238. }
  239. DestroyClassDevinfo(ClassDevInfo);
  240. ClassDevInfo++;
  241. ClassGuid++;
  242. }
  243. if (DetectionCancelled) {
  244. HardwareWiz->Reboot = FALSE;
  245. }
  246. LocalFree(HardwareWiz->DeviceDetection);
  247. HardwareWiz->DeviceDetection = NULL;
  248. }
  249. BOOL
  250. DetectProgressNotify(
  251. PVOID pvProgressNotifyParam,
  252. DWORD DetectComplete
  253. )
  254. {
  255. PHARDWAREWIZ HardwareWiz = pvProgressNotifyParam;
  256. BOOL ExitDetect;
  257. try {
  258. ExitDetect = HardwareWiz->ExitDetect;
  259. HardwareWiz->DeviceDetection->ClassProgress += (UCHAR)DetectComplete;
  260. SendDlgItemMessage(HardwareWiz->DeviceDetection->hDlg,
  261. IDC_HDW_DETWARN_PROGRESSBAR,
  262. PBM_SETPOS,
  263. DetectComplete,
  264. 0
  265. );
  266. SendDlgItemMessage(HardwareWiz->DeviceDetection->hDlg,
  267. IDC_HDW_DETWARN_TOTALPROGRESSBAR,
  268. PBM_SETPOS,
  269. (HardwareWiz->DeviceDetection->TotalProgress + DetectComplete/100),
  270. 0
  271. );
  272. }
  273. except(EXCEPTION_EXECUTE_HANDLER) {
  274. ExitDetect = TRUE;
  275. }
  276. return ExitDetect;
  277. }
  278. VOID
  279. SortClassGuidListForDetection(
  280. IN OUT LPGUID GuidList,
  281. IN ULONG GuidCount
  282. )
  283. /*++
  284. Routine Description:
  285. This routine sorts the supplied list of GUID based on a (partial) ordering
  286. specified in the [DetectionOrder] section of syssetup.inf. This allows us
  287. to maintain a detection ordering similar to previous versions of NT.
  288. Arguments:
  289. GuidList - address of the array of GUIDs to be sorted.
  290. GuidCount - the number of GUIDs in the array.
  291. Return Value:
  292. none.
  293. --*/
  294. {
  295. HINF SyssetupInf;
  296. LONG LineCount, LineIndex, GuidIndex, NextTopmost;
  297. PCWSTR CurGuidString;
  298. INFCONTEXT InfContext;
  299. GUID CurGuid;
  300. if ((SyssetupInf = SetupOpenInfFile(L"syssetup.inf",
  301. NULL,
  302. INF_STYLE_WIN4,
  303. NULL
  304. )
  305. ) == INVALID_HANDLE_VALUE) {
  306. return;
  307. }
  308. LineCount = SetupGetLineCount(SyssetupInf, L"DetectionOrder");
  309. NextTopmost = 0;
  310. for(LineIndex = 0; LineIndex < LineCount; LineIndex++) {
  311. if(!SetupGetLineByIndex(SyssetupInf, L"DetectionOrder", LineIndex, &InfContext) ||
  312. ((CurGuidString = pSetupGetField(&InfContext, 1)) == NULL) ||
  313. (pSetupGuidFromString((PWCHAR)CurGuidString, &CurGuid) != NO_ERROR)) {
  314. continue;
  315. }
  316. //
  317. // Search through the GUID list looking for this GUID. If found, move the GUID from
  318. // it's current position to the next topmost position.
  319. //
  320. for(GuidIndex = 0; GuidIndex < (LONG)GuidCount; GuidIndex++) {
  321. if(IsEqualGUID(&CurGuid, &(GuidList[GuidIndex]))) {
  322. if(NextTopmost != GuidIndex) {
  323. //
  324. // We should never be moving the GUID _down_ the list.
  325. //
  326. MoveMemory(&(GuidList[NextTopmost + 1]),
  327. &(GuidList[NextTopmost]),
  328. (GuidIndex - NextTopmost) * sizeof(GUID)
  329. );
  330. CopyMemory(&(GuidList[NextTopmost]),
  331. &CurGuid,
  332. sizeof(GUID)
  333. );
  334. }
  335. NextTopmost++;
  336. break;
  337. }
  338. }
  339. }
  340. SetupCloseInfFile(SyssetupInf);
  341. }
  342. void
  343. BuildDeviceDetection(
  344. HWND hwndParent,
  345. PHARDWAREWIZ HardwareWiz
  346. )
  347. {
  348. HDEVINFO hDeviceInfo;
  349. int ClassGuidNum;
  350. LPGUID ClassGuid;
  351. PCLASSDEVINFO ClassDevInfo;
  352. BOOL MissingOrNew = FALSE;
  353. SP_DETECTDEVICE_PARAMS DetectDeviceParams;
  354. TCHAR ClassName[MAX_PATH];
  355. TCHAR Buffer[MAX_PATH + 64];
  356. TCHAR Format[64];
  357. ClassGuidNum = HardwareWiz->ClassGuidNum;
  358. ClassGuid = HardwareWiz->ClassGuidList;
  359. ClassDevInfo = HardwareWiz->DeviceDetection->ClassDevInfo;
  360. SortClassGuidListForDetection(ClassGuid, ClassGuidNum);
  361. DetectDeviceParams.ClassInstallHeader.cbSize = sizeof(DetectDeviceParams.ClassInstallHeader);
  362. DetectDeviceParams.ClassInstallHeader.InstallFunction = DIF_DETECT;
  363. DetectDeviceParams.DetectProgressNotify = DetectProgressNotify;
  364. DetectDeviceParams.ProgressNotifyParam = HardwareWiz;
  365. HardwareWiz->DeviceDetection->TotalProgress = 0;
  366. HardwareWiz->DeviceDetection->hDlg = hwndParent;
  367. SetDlgText(hwndParent, IDC_HDW_DETWARN_PROGRESSTEXT, IDS_DETECTPROGRESS, IDS_DETECTPROGRESS);
  368. while (!HardwareWiz->ExitDetect && ClassGuidNum--)
  369. {
  370. hDeviceInfo = SetupDiGetClassDevs(ClassGuid,
  371. REGSTR_KEY_ROOTENUM,
  372. hwndParent,
  373. DIGCF_PROFILE
  374. );
  375. if (hDeviceInfo != INVALID_HANDLE_VALUE)
  376. {
  377. ClassDevInfo->Missing = hDeviceInfo;
  378. }
  379. hDeviceInfo = SetupDiCreateDeviceInfoList(ClassGuid, hwndParent);
  380. if (hDeviceInfo != INVALID_HANDLE_VALUE)
  381. {
  382. ClassDevInfo->Detected = hDeviceInfo;
  383. }
  384. HardwareWiz->DeviceDetection->ClassGuid = ClassGuid;
  385. HardwareWiz->DeviceDetection->ClassProgress = 0;
  386. // set progress bar to zero.
  387. SendDlgItemMessage(hwndParent,
  388. IDC_HDW_DETWARN_PROGRESSBAR,
  389. PBM_SETPOS,
  390. 0,
  391. 0
  392. );
  393. if (!SetupDiGetClassDescription(HardwareWiz->DeviceDetection->ClassGuid,
  394. ClassName,
  395. sizeof(ClassName)/sizeof(TCHAR),
  396. NULL
  397. )
  398. &&
  399. !SetupDiClassNameFromGuid(HardwareWiz->DeviceDetection->ClassGuid,
  400. ClassName,
  401. sizeof(ClassName)/sizeof(TCHAR),
  402. NULL
  403. ))
  404. {
  405. *ClassName = TEXT('\0');
  406. }
  407. LoadString(hHdwWiz, IDS_DETECTCLASS, Format, sizeof(Format)/sizeof(TCHAR));
  408. wsprintf(Buffer, Format, ClassName);
  409. SetDlgItemText(hwndParent,
  410. IDC_HDW_DETWARN_PROGRESSTEXT,
  411. Buffer
  412. );
  413. if (!IsEqualGUID(ClassGuid, &GUID_NULL) &&
  414. !IsEqualGUID(ClassGuid, &GUID_DEVCLASS_UNKNOWN) &&
  415. ClassDevInfo->Missing &&
  416. ClassDevInfo->Detected &&
  417. SetupDiSetClassInstallParams(ClassDevInfo->Detected,
  418. NULL,
  419. &DetectDeviceParams.ClassInstallHeader,
  420. sizeof(DetectDeviceParams)
  421. )
  422. &&
  423. SetupDiCallClassInstaller(DIF_DETECT, ClassDevInfo->Detected, NULL))
  424. {
  425. SP_DEVINSTALL_PARAMS DeviceInstallParams;
  426. SendDlgItemMessage(hwndParent,
  427. IDC_HDW_DETWARN_TOTALPROGRESSBAR,
  428. PBM_SETPOS,
  429. HardwareWiz->DeviceDetection->TotalProgress,
  430. 0
  431. );
  432. //
  433. // Clear the class install parameters.
  434. //
  435. SetupDiSetClassInstallParams(ClassDevInfo->Detected,
  436. NULL,
  437. NULL,
  438. 0
  439. );
  440. //
  441. // Get the device install parameters for the reboot flags.
  442. //
  443. DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
  444. if (SetupDiGetDeviceInstallParams(ClassDevInfo->Detected,
  445. NULL,
  446. &DeviceInstallParams
  447. ))
  448. {
  449. HardwareWiz->DeviceDetection->Reboot |= DeviceInstallParams.Flags & (DI_NEEDRESTART | DI_NEEDREBOOT);
  450. }
  451. if (BuildMissingAndNew(hwndParent, ClassDevInfo))
  452. {
  453. HardwareWiz->DeviceDetection->MissingOrNew = TRUE;
  454. }
  455. }
  456. else
  457. {
  458. DestroyClassDevinfo(ClassDevInfo);
  459. }
  460. HardwareWiz->DeviceDetection->TotalProgress += 10;
  461. SendDlgItemMessage(hwndParent, IDC_HDW_DETWARN_PROGRESSBAR, PBM_SETPOS, 100, 0);
  462. SendDlgItemMessage(hwndParent, IDC_HDW_DETWARN_TOTALPROGRESSBAR, PBM_STEPIT, 0, 0);
  463. ClassDevInfo++;
  464. ClassGuid++;
  465. }
  466. }
  467. INT_PTR CALLBACK
  468. HdwDetectionDlgProc(
  469. HWND hDlg,
  470. UINT wMsg,
  471. WPARAM wParam,
  472. LPARAM lParam
  473. )
  474. {
  475. PHARDWAREWIZ HardwareWiz = (PHARDWAREWIZ)GetWindowLongPtr(hDlg, DWLP_USER);
  476. HWND hwndParentDlg=GetParent(hDlg);
  477. switch (wMsg) {
  478. case WM_INITDIALOG: {
  479. LPPROPSHEETPAGE lppsp = (LPPROPSHEETPAGE)lParam;
  480. HardwareWiz = (PHARDWAREWIZ)lppsp->lParam;
  481. SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)HardwareWiz);
  482. break;
  483. }
  484. case WM_DESTROY:
  485. CancelSearchRequest(HardwareWiz);
  486. DestroyDeviceDetection(HardwareWiz, FALSE);
  487. break;
  488. break;
  489. case WM_NOTIFY:
  490. switch (((NMHDR FAR *)lParam)->code) {
  491. case PSN_SETACTIVE: {
  492. int Len, PrevPage;
  493. PrevPage = HardwareWiz->PrevPage;
  494. HardwareWiz->PrevPage = IDD_ADDDEVICE_DETECTION;
  495. // Coming back, after doing a previous detection
  496. if (PrevPage == IDD_ADDDEVICE_DETECTINSTALL) {
  497. DestroyDeviceDetection(HardwareWiz, TRUE);
  498. PropSheet_PressButton(hwndParentDlg, PSBTN_BACK);
  499. break;
  500. }
  501. //
  502. // Only back,cancel button, when detection completes ok, we will
  503. // jump directly to the next page.
  504. //
  505. PropSheet_SetWizButtons(hwndParentDlg, PSWIZB_BACK );
  506. // refresh the class guid list
  507. HdwBuildClassInfoList(HardwareWiz,
  508. DIBCI_NOINSTALLCLASS,
  509. HardwareWiz->hMachine ? HardwareWiz->MachineName : NULL
  510. );
  511. // allocate memory for DeviceDetection data
  512. Len = sizeof(DEVICEDETECTION) + (HardwareWiz->ClassGuidNum * sizeof(CLASSDEVINFO));
  513. HardwareWiz->DeviceDetection = LocalAlloc(LPTR, Len);
  514. if (!HardwareWiz->DeviceDetection) {
  515. PropSheet_PressButton(hwndParentDlg, PSBTN_BACK);
  516. break;
  517. }
  518. memset(HardwareWiz->DeviceDetection, 0, Len);
  519. HardwareWiz->ExitDetect = FALSE;
  520. // set progress bar to zero.
  521. SendDlgItemMessage(hDlg,
  522. IDC_HDW_DETWARN_TOTALPROGRESSBAR,
  523. PBM_SETPOS,
  524. 0,
  525. 0
  526. );
  527. // set the range to 10 * number of classes
  528. SendDlgItemMessage(hDlg,
  529. IDC_HDW_DETWARN_TOTALPROGRESSBAR,
  530. PBM_SETRANGE,
  531. 0,
  532. MAKELPARAM(0, 10 * HardwareWiz->ClassGuidNum)
  533. );
  534. // set the step to 10.
  535. SendDlgItemMessage(hDlg,
  536. IDC_HDW_DETWARN_TOTALPROGRESSBAR,
  537. PBM_SETSTEP,
  538. 10,
  539. 0
  540. );
  541. HardwareWiz->CurrCursor = HardwareWiz->IdcAppStarting;
  542. SetCursor(HardwareWiz->CurrCursor);
  543. SearchThreadRequest(HardwareWiz->SearchThread,
  544. hDlg,
  545. SEARCH_DETECT,
  546. 0
  547. );
  548. }
  549. break;
  550. case PSN_QUERYCANCEL:
  551. if (HardwareWiz->ExitDetect) {
  552. SetDlgMsgResult(hDlg, wMsg, TRUE);
  553. }
  554. HardwareWiz->ExitDetect = TRUE;
  555. HardwareWiz->CurrCursor = HardwareWiz->IdcWait;
  556. SetCursor(HardwareWiz->CurrCursor);
  557. CancelSearchRequest(HardwareWiz);
  558. HardwareWiz->CurrCursor = NULL;
  559. SetDlgMsgResult(hDlg, wMsg, FALSE);
  560. break;
  561. case PSN_RESET:
  562. DestroyDeviceDetection(HardwareWiz, TRUE);
  563. break;
  564. //
  565. // we receive back if
  566. // coming back from a previous search result
  567. // when user wants to stop current search.
  568. //
  569. case PSN_WIZBACK:
  570. if (HardwareWiz->DeviceDetection) {
  571. if (HardwareWiz->ExitDetect) {
  572. SetDlgMsgResult(hDlg, wMsg, -1);
  573. break;
  574. }
  575. HardwareWiz->ExitDetect = TRUE;
  576. HardwareWiz->CurrCursor = HardwareWiz->IdcWait;
  577. SetCursor(HardwareWiz->CurrCursor);
  578. CancelSearchRequest(HardwareWiz);
  579. HardwareWiz->CurrCursor = NULL;
  580. DestroyDeviceDetection(HardwareWiz, TRUE);
  581. }
  582. SetDlgMsgResult(hDlg, wMsg, IDD_ADDDEVICE_ASKDETECT);
  583. break;
  584. //
  585. // next button is off, we only receive this after doing detection.
  586. //
  587. case PSN_WIZNEXT:
  588. SetDlgMsgResult(hDlg, wMsg, IDD_ADDDEVICE_DETECTINSTALL);
  589. break;
  590. }
  591. break;
  592. case WUM_DETECT:
  593. HardwareWiz->CurrCursor = NULL;
  594. SetCursor(HardwareWiz->IdcArrow);
  595. if (HardwareWiz->ExitDetect == TRUE) {
  596. break;
  597. }
  598. //
  599. // finish building the missing\detected stuff
  600. //
  601. PropSheet_PressButton(hwndParentDlg, PSBTN_NEXT);
  602. break;
  603. case WM_SETCURSOR:
  604. if (HardwareWiz->CurrCursor) {
  605. SetCursor(HardwareWiz->CurrCursor);
  606. break;
  607. }
  608. // fall thru to return(FALSE);
  609. default:
  610. return(FALSE);
  611. }
  612. return(TRUE);
  613. }
  614. DWORD
  615. InstallNewDevices(
  616. HWND hwndParent,
  617. HDEVINFO NewDevices,
  618. HWND hwndListView
  619. )
  620. {
  621. DWORD Reboot, dwRet = 0;
  622. int iNewDevices;
  623. SP_DEVINFO_DATA DevInfoData;
  624. DevInfoData.cbSize = sizeof(DevInfoData);
  625. iNewDevices = 0;
  626. Reboot = 0;
  627. while (SetupDiEnumDeviceInfo(NewDevices, iNewDevices++, &DevInfoData)) {
  628. if (DevInstIsSelected(hwndListView, DevInfoData.DevInst)) {
  629. SetupDiSetSelectedDevice(NewDevices, &DevInfoData);
  630. if (hNewDev) {
  631. if (!pInstallSelectedDevice) {
  632. pInstallSelectedDevice = (PVOID) GetProcAddress(hNewDev, "InstallSelectedDevice");
  633. }
  634. }
  635. if (pInstallSelectedDevice) {
  636. pInstallSelectedDevice(hwndParent,
  637. NewDevices,
  638. &dwRet
  639. );
  640. }
  641. } else {
  642. SP_REMOVEDEVICE_PARAMS RemoveDeviceParams;
  643. RemoveDeviceParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
  644. RemoveDeviceParams.ClassInstallHeader.InstallFunction = DIF_REMOVE;
  645. RemoveDeviceParams.Scope = DI_REMOVEDEVICE_GLOBAL;
  646. RemoveDeviceParams.HwProfile = 0;
  647. if (SetupDiSetClassInstallParams(NewDevices,
  648. &DevInfoData,
  649. (PSP_CLASSINSTALL_HEADER)&RemoveDeviceParams,
  650. sizeof(RemoveDeviceParams)
  651. )) {
  652. SetupDiCallClassInstaller(DIF_REMOVE, NewDevices, &DevInfoData);
  653. }
  654. //
  655. // Clear the class install parameters.
  656. //
  657. SetupDiSetClassInstallParams(NewDevices,
  658. &DevInfoData,
  659. NULL,
  660. 0
  661. );
  662. }
  663. Reboot |= dwRet;
  664. }
  665. SetupDiDestroyDeviceInfoList(NewDevices);
  666. return Reboot;
  667. }
  668. /*
  669. * InstallMissingAndNewDevices
  670. *
  671. * Missing devices are removed.
  672. * NewDevices are installed by invoking InstallDevic
  673. *
  674. */
  675. void
  676. InstallDetectedDevices(
  677. HWND hwndParent,
  678. PHARDWAREWIZ HardwareWiz
  679. )
  680. {
  681. int ClassGuidNum;
  682. PCLASSDEVINFO ClassDevInfo;
  683. LPGUID ClassGuid;
  684. HWND hwndDetectList;
  685. if (!HardwareWiz->DeviceDetection) {
  686. return;
  687. }
  688. ClassGuidNum = HardwareWiz->ClassGuidNum;
  689. ClassGuid = HardwareWiz->ClassGuidList;
  690. ClassDevInfo = HardwareWiz->DeviceDetection->ClassDevInfo;
  691. hwndDetectList = GetDlgItem(hwndParent,IDC_HDW_INSTALLDET_LIST);;
  692. while (ClassGuidNum--) {
  693. if (ClassDevInfo->Missing) {
  694. RemoveDeviceInfo(ClassDevInfo->Missing, hwndDetectList);
  695. ClassDevInfo->Missing = NULL;
  696. }
  697. if (ClassDevInfo->Detected) {
  698. HardwareWiz->Reboot |= InstallNewDevices(hwndParent, ClassDevInfo->Detected, hwndDetectList);
  699. ClassDevInfo->Detected = NULL;
  700. }
  701. ClassDevInfo++;
  702. ClassGuid++;
  703. }
  704. HardwareWiz->DeviceDetection->MissingOrNew = FALSE;
  705. }
  706. void
  707. AddDeviceDescription(
  708. PHARDWAREWIZ HardwareWiz,
  709. HWND hListView,
  710. HDEVINFO Devices,
  711. BOOL Install
  712. )
  713. {
  714. PTCHAR FriendlyName;
  715. LV_ITEM lviItem;
  716. int iItem;
  717. int iDevices;
  718. GUID ClassGuid;
  719. SP_DEVINFO_DATA DevInfoData;
  720. SP_DRVINFO_DATA DriverInfoData;
  721. TCHAR Format[LINE_LEN];
  722. TCHAR DeviceDesc[MAX_PATH*2];
  723. TCHAR String[LINE_LEN];
  724. if (Install) {
  725. LoadString(hHdwWiz, IDS_INSTALL_LEGACY_DEVICE, Format, sizeof(Format)/sizeof(TCHAR));
  726. } else {
  727. LoadString(hHdwWiz, IDS_UNINSTALL_LEGACY_DEVICE, Format, sizeof(Format)/sizeof(TCHAR));
  728. }
  729. lviItem.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE;
  730. lviItem.iItem = -1;
  731. lviItem.iSubItem = 0;
  732. lviItem.state = 0;
  733. lviItem.stateMask = LVIS_SELECTED;
  734. if (HardwareWiz->ClassImageList.cbSize &&
  735. SetupDiGetDeviceInfoListClass(Devices, &ClassGuid) &&
  736. SetupDiGetClassImageIndex(&HardwareWiz->ClassImageList,
  737. &ClassGuid,
  738. &lviItem.iImage
  739. ))
  740. {
  741. lviItem.mask |= LVIF_IMAGE;
  742. }
  743. DevInfoData.cbSize = sizeof(DevInfoData);
  744. DriverInfoData.cbSize = sizeof(DriverInfoData);
  745. iDevices = 0;
  746. while (SetupDiEnumDeviceInfo(Devices, iDevices++, &DevInfoData)) {
  747. lviItem.lParam = DevInfoData.DevInst;
  748. if (SetupDiGetSelectedDriver(Devices,
  749. &DevInfoData,
  750. &DriverInfoData
  751. )
  752. &&
  753. *DriverInfoData.Description)
  754. {
  755. wcscpy(DeviceDesc, DriverInfoData.Description);
  756. }
  757. else
  758. {
  759. FriendlyName = BuildFriendlyName(DevInfoData.DevInst, NULL);
  760. if (FriendlyName) {
  761. wcscpy(DeviceDesc, FriendlyName);
  762. LocalFree(FriendlyName);
  763. }
  764. else {
  765. lstrcpyn(DeviceDesc, szUnknown, SIZECHARS(DeviceDesc));
  766. }
  767. }
  768. wsprintf(String, Format, DeviceDesc);
  769. lviItem.pszText = String;
  770. //
  771. // Send it to the listview
  772. //
  773. iItem = ListView_InsertItem(hListView, &lviItem);
  774. if (iItem != -1) {
  775. // set the checkbox, control uses one based index, while imageindex is zero based
  776. ListView_SetItemState(hListView, iItem, INDEXTOSTATEIMAGEMASK(2), LVIS_STATEIMAGEMASK);
  777. }
  778. }
  779. }
  780. void
  781. ShowDetectedDevices(
  782. HWND hDlg,
  783. PHARDWAREWIZ HardwareWiz
  784. )
  785. {
  786. INT lvIndex;
  787. int ClassGuidNum;
  788. PCLASSDEVINFO ClassDevInfo;
  789. LPGUID ClassGuid;
  790. HWND hwndDetectList;
  791. PTCHAR FriendlyName;
  792. LPTSTR Description;
  793. hwndDetectList = GetDlgItem(hDlg,IDC_HDW_INSTALLDET_LIST);
  794. SendMessage(hwndDetectList, WM_SETREDRAW, FALSE, 0L);
  795. ListView_DeleteAllItems(hwndDetectList);
  796. if (HardwareWiz->ClassImageList.cbSize) {
  797. ListView_SetImageList(hwndDetectList,
  798. HardwareWiz->ClassImageList.ImageList,
  799. LVSIL_SMALL
  800. );
  801. }
  802. //
  803. // Display the new devices
  804. //
  805. ClassGuidNum = HardwareWiz->ClassGuidNum;
  806. ClassGuid = HardwareWiz->ClassGuidList;
  807. ClassDevInfo = HardwareWiz->DeviceDetection->ClassDevInfo;
  808. while (ClassGuidNum--) {
  809. if (ClassDevInfo->Detected) {
  810. AddDeviceDescription(HardwareWiz, hwndDetectList, ClassDevInfo->Detected, TRUE);
  811. }
  812. ClassDevInfo++;
  813. ClassGuid++;
  814. }
  815. //
  816. // Display the missing devices
  817. //
  818. ClassGuidNum = HardwareWiz->ClassGuidNum;
  819. ClassGuid = HardwareWiz->ClassGuidList;
  820. ClassDevInfo = HardwareWiz->DeviceDetection->ClassDevInfo;
  821. while (ClassGuidNum--) {
  822. if (ClassDevInfo->Missing) {
  823. AddDeviceDescription(HardwareWiz, hwndDetectList, ClassDevInfo->Missing, FALSE);
  824. }
  825. ClassDevInfo++;
  826. ClassGuid++;
  827. }
  828. //
  829. // scroll the first item into view.
  830. //
  831. ListView_EnsureVisible(hwndDetectList, , 0, FALSE);
  832. ListView_SetColumnWidth(hwndDetectList, , 0, LVSCW_AUTOSIZE_USEHEADER);
  833. SendMessage(hwndDetectList, WM_SETREDRAW, TRUE, 0L);
  834. }
  835. INT_PTR CALLBACK
  836. HdwDetectInstallDlgProc(
  837. HWND hDlg,
  838. UINT wMsg,
  839. WPARAM wParam,
  840. LPARAM lParam
  841. )
  842. {
  843. PHARDWAREWIZ HardwareWiz = (PHARDWAREWIZ)GetWindowLongPtr(hDlg, DWLP_USER);
  844. HWND hwndParentDlg=GetParent(hDlg);
  845. TCHAR PropSheetHeaderTitle[MAX_PATH];
  846. switch (wMsg) {
  847. case WM_INITDIALOG: {
  848. HWND hwndDetectList;
  849. LV_COLUMN lvcCol;
  850. LPPROPSHEETPAGE lppsp = (LPPROPSHEETPAGE)lParam;
  851. HardwareWiz = (PHARDWAREWIZ)lppsp->lParam;
  852. SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)HardwareWiz);
  853. hwndDetectList = GetDlgItem(hDlg, IDC_HDW_INSTALLDET_LIST);
  854. // Insert a column for the class list
  855. lvcCol.mask = LVCF_FMT | LVCF_WIDTH;
  856. lvcCol.fmt = LVCFMT_LEFT;
  857. lvcCol.iSubItem = 0;
  858. ListView_InsertColumn(hwndDetectList, 0, &lvcCol);
  859. ListView_SetExtendedListViewStyleEx(hwndDetectList, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES);
  860. break;
  861. }
  862. case WM_DESTROY:
  863. break;
  864. case WM_NOTIFY:
  865. switch (((NMHDR FAR *)lParam)->code) {
  866. case PSN_SETACTIVE:
  867. HardwareWiz->PrevPage = IDD_ADDDEVICE_DETECTINSTALL;
  868. if (HardwareWiz->DeviceDetection->MissingOrNew) {
  869. ShowDetectedDevices(hDlg, HardwareWiz);
  870. SetDlgText(hDlg, IDC_HDW_TEXT, IDS_HDW_INSTALLDET1, IDS_HDW_INSTALLDET1);
  871. PropSheet_SetWizButtons(hwndParentDlg, PSWIZB_BACK | PSWIZB_NEXT);
  872. ShowWindow(GetDlgItem(hDlg, IDC_HDW_INSTALLDET_LISTTITLE), SW_SHOW);
  873. ShowWindow(GetDlgItem(hDlg, IDC_HDW_INSTALLDET_LIST), SW_SHOW);
  874. }
  875. else if (HardwareWiz->DeviceDetection->Reboot) {
  876. PropSheet_SetWizButtons(hwndParentDlg, 0);
  877. SetDlgMsgResult(hDlg, wMsg, IDD_ADDDEVICE_DETECTREBOOT);
  878. break;
  879. }
  880. else {
  881. //
  882. // hide the list box
  883. //
  884. ShowWindow(GetDlgItem(hDlg, IDC_HDW_INSTALLDET_LISTTITLE), SW_HIDE);
  885. ShowWindow(GetDlgItem(hDlg, IDC_HDW_INSTALLDET_LIST), SW_HIDE);
  886. SetDlgText(hDlg, IDC_HDW_TEXT, IDS_HDW_NONEDET1, IDS_HDW_NONEDET1);
  887. if (LoadString(hHdwWiz,
  888. IDS_ADDDEVICE_DETECTINSTALL_NONE,
  889. PropSheetHeaderTitle,
  890. SIZECHARS(PropSheetHeaderTitle)
  891. )) {
  892. PropSheet_SetHeaderTitle(GetParent(hDlg),
  893. PropSheet_IdToIndex(GetParent(hDlg), IDD_ADDDEVICE_DETECTINSTALL),
  894. PropSheetHeaderTitle
  895. );
  896. }
  897. PropSheet_SetWizButtons(hwndParentDlg, PSWIZB_BACK | PSWIZB_NEXT);
  898. }
  899. break;
  900. case PSN_WIZBACK:
  901. SetDlgMsgResult(hDlg, wMsg, IDD_ADDDEVICE_DETECTION);
  902. break;
  903. case PSN_WIZNEXT:
  904. if (HardwareWiz->DeviceDetection->MissingOrNew) {
  905. InstallDetectedDevices(hDlg, HardwareWiz);
  906. HardwareWiz->Reboot |= HardwareWiz->DeviceDetection->Reboot;
  907. SetDlgMsgResult(hDlg, wMsg, IDD_ADDDEVICE_DETECTREBOOT);
  908. }
  909. else {
  910. DestroyDeviceDetection(HardwareWiz, FALSE);
  911. SetDlgMsgResult(hDlg, wMsg, IDD_ADDDEVICE_SELECTCLASS);
  912. }
  913. break;
  914. case PSN_RESET:
  915. DestroyDeviceDetection(HardwareWiz, TRUE);
  916. break;
  917. }
  918. break;
  919. default:
  920. return(FALSE);
  921. }
  922. return(TRUE);
  923. }
  924. INT_PTR CALLBACK
  925. HdwDetectRebootDlgProc(
  926. HWND hDlg,
  927. UINT wMsg,
  928. WPARAM wParam,
  929. LPARAM lParam
  930. )
  931. {
  932. PHARDWAREWIZ HardwareWiz = (PHARDWAREWIZ)GetWindowLongPtr(hDlg, DWLP_USER);
  933. HWND hwndParentDlg=GetParent(hDlg);
  934. switch (wMsg) {
  935. case WM_INITDIALOG: {
  936. LPPROPSHEETPAGE lppsp = (LPPROPSHEETPAGE)lParam;
  937. HardwareWiz = (PHARDWAREWIZ)lppsp->lParam;
  938. SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)HardwareWiz);
  939. SetWindowFont(GetDlgItem(hDlg, IDC_HDWNAME), HardwareWiz->hfontTextBigBold, TRUE);
  940. break;
  941. }
  942. case WM_DESTROY:
  943. break;
  944. case WM_NOTIFY:
  945. switch (((NMHDR FAR *)lParam)->code) {
  946. case PSN_SETACTIVE:
  947. HardwareWiz->PrevPage = IDD_ADDDEVICE_DETECTREBOOT;
  948. if (HardwareWiz->Reboot && HardwareWiz->PromptForReboot) {
  949. SetDlgText(hDlg, IDC_HDW_TEXT, IDS_HDW_REBOOTDET, IDS_HDW_REBOOTDET);
  950. }
  951. else {
  952. SetDlgText(hDlg, IDC_HDW_TEXT, IDS_HDW_NOREBOOTDET, IDS_HDW_NOREBOOTDET);
  953. }
  954. //
  955. // no back, no next! This page is just to confirm that the
  956. // user will continue detection after rebooting.
  957. //
  958. PropSheet_SetWizButtons(hwndParentDlg, PSWIZB_FINISH);
  959. EnableWindow(GetDlgItem(hwndParentDlg, IDCANCEL), FALSE);
  960. break;
  961. case PSN_WIZFINISH:
  962. DestroyDeviceDetection(HardwareWiz, FALSE);
  963. break;
  964. }
  965. break;
  966. default:
  967. return(FALSE);
  968. }
  969. return(TRUE);
  970. }