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.

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