//+------------------------------------------------------------------------- // // Microsoft Windows // // Copyright (C) Microsoft Corporation, 1998 - 1999 // // File: detect.c // //-------------------------------------------------------------------------- #include "hdwwiz.h" typedef UINT (*PINSTALLSELECTEDDEVICE)( HWND hwndParent, HDEVINFO hDeviceInfo, PDWORD pReboot ); PINSTALLSELECTEDDEVICE pInstallSelectedDevice = NULL; /* * BuildMissingAndNew * * worker routine for BuildDeviceDetection. * * On entry: * Missing contains known devices prior to class installer detection. * Detected contains devices detected by class installer. * NewDevices is an empty list. * * If a device is in Missing and not in Detected, then it is missing. * If a device is in Detected and not in Missing, then it is newly detected. * * On Exit: * Missing contains only missing devices, * Detected gone. * NewDevices contains those that were newly detectd * */ BOOL BuildMissingAndNew( HWND hwndParent, PCLASSDEVINFO ClassDevInfo ) { HDEVINFO Missing, Detected; int iMissing, iDetect; ULONG DevNodeStatus, Problem; SP_DEVINFO_DATA DevInfoDataDetect; SP_DEVINFO_DATA DevInfoDataMissing; TCHAR DetectedId[MAX_DEVICE_ID_LEN +sizeof(TCHAR)]; BOOL Removed; Detected = ClassDevInfo->Detected; Missing = ClassDevInfo->Missing; DevInfoDataMissing.cbSize = sizeof(DevInfoDataMissing); DevInfoDataDetect.cbSize = sizeof(DevInfoDataDetect); // // For each member of the detected list, fetch its Device ID // and see if it exists in the missing list. // BMNBuildDetectedList: Removed = FALSE; iMissing = 0; while (SetupDiEnumDeviceInfo(Missing, iMissing++, &DevInfoDataMissing)) { iDetect = 0; while (SetupDiEnumDeviceInfo(Detected, iDetect++, &DevInfoDataDetect)) { // // If Found in both lists, its not a new device and exists(not missing). // remove it from both lists. // if (DevInfoDataDetect.DevInst == DevInfoDataMissing.DevInst) { SetupDiDeleteDeviceInfo(Missing, &DevInfoDataMissing); SetupDiDeleteDeviceInfo(Detected, &DevInfoDataDetect); Removed = TRUE; break; } } } // // If a device info was removed, the enumeration index changes // and we will miss some in the list. Rescan until none are deleted. // if (Removed && SetupDiEnumDeviceInfo(Detected, 0, &DevInfoDataDetect)) { goto BMNBuildDetectedList; } // // Remove devices which are up and running from the misssing list, // since they are obviously present. Class installers may not report // all devices which are present, if they are already installed and // running. e.g. Bios enumerated devices. We also check that it is // a Root Enumerated Device (not a PnP BIOS device) and that it was // not a manually installed device. // BMNRemoveLiveFromMissing: Removed = FALSE; iMissing = 0; while (SetupDiEnumDeviceInfo(Missing, iMissing++, &DevInfoDataMissing)) { if ((CM_Get_DevNode_Status(&DevNodeStatus, &Problem, DevInfoDataMissing.DevInst, 0) == CR_SUCCESS) && ((DevNodeStatus & DN_STARTED) && !(DevNodeStatus & DN_HAS_PROBLEM)) || !(DevNodeStatus & DN_ROOT_ENUMERATED) || (DevNodeStatus & DN_MANUAL)) { SetupDiDeleteDeviceInfo(Missing, &DevInfoDataMissing); Removed = TRUE; } } if (Removed) { goto BMNRemoveLiveFromMissing; } // // Register the newly detected devices // BMNRegisterDetected: Removed = FALSE; iDetect = 0; while (SetupDiEnumDeviceInfo(Detected, iDetect++, &DevInfoDataDetect)) { if (!SetupDiCallClassInstaller(DIF_REGISTERDEVICE, Detected, &DevInfoDataDetect )) { SetupDiDeleteDeviceInfo(Detected, &DevInfoDataDetect); Removed = TRUE; } } if (Removed) { goto BMNRegisterDetected; } // // if the missing devices list is empty, don't need it anymore either // if (!SetupDiEnumDeviceInfo(Missing, 0, &DevInfoDataMissing)) { SetupDiDestroyDeviceInfoList(Missing); ClassDevInfo->Missing = NULL; } return SetupDiEnumDeviceInfo(Detected, 0, &DevInfoDataDetect) || ClassDevInfo->Missing; } BOOL DevInstIsSelected( HWND hwndListView, DEVINST DevInst ) { LVITEM lvItem; lvItem.mask = LVIF_PARAM; lvItem.iSubItem = 0; lvItem.iItem = -1; while ((lvItem.iItem = ListView_GetNextItem(hwndListView, lvItem.iItem, LVNI_ALL)) != -1) { ListView_GetItem(hwndListView, &lvItem); if (lvItem.lParam == (LPARAM)DevInst) { // Image list is 0 based, and one means checked. return (ListView_GetCheckState(hwndListView, lvItem.iItem) == 1); } } return FALSE; } void RemoveDeviceInfo( HDEVINFO DeviceInfo, HWND hwndListView ) { int Index; SP_REMOVEDEVICE_PARAMS RemoveDeviceParams; SP_DEVINFO_DATA DevInfoData; Index = 0; DevInfoData.cbSize = sizeof(DevInfoData); while (SetupDiEnumDeviceInfo(DeviceInfo, Index++, &DevInfoData)) { if (!hwndListView || DevInstIsSelected(hwndListView, DevInfoData.DevInst)) { RemoveDeviceParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER); RemoveDeviceParams.ClassInstallHeader.InstallFunction = DIF_REMOVE; RemoveDeviceParams.Scope = DI_REMOVEDEVICE_GLOBAL; RemoveDeviceParams.HwProfile = 0; if (SetupDiSetClassInstallParams(DeviceInfo, &DevInfoData, (PSP_CLASSINSTALL_HEADER)&RemoveDeviceParams, sizeof(RemoveDeviceParams) )) { SetupDiCallClassInstaller(DIF_REMOVE, DeviceInfo, &DevInfoData); } // // Clear the class install parameters. // SetupDiSetClassInstallParams(DeviceInfo, &DevInfoData, NULL, 0 ); } } SetupDiDestroyDeviceInfoList(DeviceInfo); } void DestroyClassDevinfo( PCLASSDEVINFO ClassDevInfo ) { if (ClassDevInfo->Missing) { SetupDiDestroyDeviceInfoList(ClassDevInfo->Missing); ClassDevInfo->Missing = NULL; } if (ClassDevInfo->Detected) { SetupDiDestroyDeviceInfoList(ClassDevInfo->Detected); ClassDevInfo->Detected = NULL; } } void DestroyDeviceDetection( PHARDWAREWIZ HardwareWiz, BOOL DetectionCancelled ) { int ClassGuidNum; PCLASSDEVINFO ClassDevInfo; LPGUID ClassGuid; if (!HardwareWiz->DeviceDetection) { return; } ClassGuidNum = HardwareWiz->ClassGuidNum; ClassGuid = HardwareWiz->ClassGuidList; ClassDevInfo = HardwareWiz->DeviceDetection->ClassDevInfo; while (ClassGuidNum--) { if (DetectionCancelled) { // // If there is a detected list, // then invoke the class installer DIF_DETECTCANCEL for its cleanup. // if (ClassDevInfo->Detected) { SetupDiCallClassInstaller(DIF_DETECTCANCEL, ClassDevInfo->Detected, NULL); // // Remove all newly detected devices. // if (ClassDevInfo->Detected) { RemoveDeviceInfo(ClassDevInfo->Detected, NULL); ClassDevInfo->Detected = NULL; } } } DestroyClassDevinfo(ClassDevInfo); ClassDevInfo++; ClassGuid++; } if (DetectionCancelled) { HardwareWiz->Reboot = FALSE; } LocalFree(HardwareWiz->DeviceDetection); HardwareWiz->DeviceDetection = NULL; } BOOL DetectProgressNotify( PVOID pvProgressNotifyParam, DWORD DetectComplete ) { PHARDWAREWIZ HardwareWiz = pvProgressNotifyParam; BOOL ExitDetect; try { ExitDetect = HardwareWiz->ExitDetect; HardwareWiz->DeviceDetection->ClassProgress += (UCHAR)DetectComplete; SendDlgItemMessage(HardwareWiz->DeviceDetection->hDlg, IDC_HDW_DETWARN_PROGRESSBAR, PBM_SETPOS, DetectComplete, 0 ); SendDlgItemMessage(HardwareWiz->DeviceDetection->hDlg, IDC_HDW_DETWARN_TOTALPROGRESSBAR, PBM_SETPOS, (HardwareWiz->DeviceDetection->TotalProgress + DetectComplete/100), 0 ); } except(EXCEPTION_EXECUTE_HANDLER) { ExitDetect = TRUE; } return ExitDetect; } VOID SortClassGuidListForDetection( IN OUT LPGUID GuidList, IN ULONG GuidCount ) /*++ Routine Description: This routine sorts the supplied list of GUID based on a (partial) ordering specified in the [DetectionOrder] section of syssetup.inf. This allows us to maintain a detection ordering similar to previous versions of NT. Arguments: GuidList - address of the array of GUIDs to be sorted. GuidCount - the number of GUIDs in the array. Return Value: none. --*/ { HINF SyssetupInf; LONG LineCount, LineIndex, GuidIndex, NextTopmost; PCWSTR CurGuidString; INFCONTEXT InfContext; GUID CurGuid; if ((SyssetupInf = SetupOpenInfFile(L"syssetup.inf", NULL, INF_STYLE_WIN4, NULL ) ) == INVALID_HANDLE_VALUE) { return; } LineCount = SetupGetLineCount(SyssetupInf, L"DetectionOrder"); NextTopmost = 0; for(LineIndex = 0; LineIndex < LineCount; LineIndex++) { if(!SetupGetLineByIndex(SyssetupInf, L"DetectionOrder", LineIndex, &InfContext) || ((CurGuidString = pSetupGetField(&InfContext, 1)) == NULL) || (pSetupGuidFromString((PWCHAR)CurGuidString, &CurGuid) != NO_ERROR)) { continue; } // // Search through the GUID list looking for this GUID. If found, move the GUID from // it's current position to the next topmost position. // for(GuidIndex = 0; GuidIndex < (LONG)GuidCount; GuidIndex++) { if(IsEqualGUID(&CurGuid, &(GuidList[GuidIndex]))) { if(NextTopmost != GuidIndex) { // // We should never be moving the GUID _down_ the list. // MoveMemory(&(GuidList[NextTopmost + 1]), &(GuidList[NextTopmost]), (GuidIndex - NextTopmost) * sizeof(GUID) ); CopyMemory(&(GuidList[NextTopmost]), &CurGuid, sizeof(GUID) ); } NextTopmost++; break; } } } SetupCloseInfFile(SyssetupInf); } void BuildDeviceDetection( HWND hwndParent, PHARDWAREWIZ HardwareWiz ) { HDEVINFO hDeviceInfo; int ClassGuidNum; LPGUID ClassGuid; PCLASSDEVINFO ClassDevInfo; BOOL MissingOrNew = FALSE; SP_DETECTDEVICE_PARAMS DetectDeviceParams; TCHAR ClassName[MAX_PATH]; TCHAR Buffer[MAX_PATH + 64]; TCHAR Format[64]; ClassGuidNum = HardwareWiz->ClassGuidNum; ClassGuid = HardwareWiz->ClassGuidList; ClassDevInfo = HardwareWiz->DeviceDetection->ClassDevInfo; SortClassGuidListForDetection(ClassGuid, ClassGuidNum); DetectDeviceParams.ClassInstallHeader.cbSize = sizeof(DetectDeviceParams.ClassInstallHeader); DetectDeviceParams.ClassInstallHeader.InstallFunction = DIF_DETECT; DetectDeviceParams.DetectProgressNotify = DetectProgressNotify; DetectDeviceParams.ProgressNotifyParam = HardwareWiz; HardwareWiz->DeviceDetection->TotalProgress = 0; HardwareWiz->DeviceDetection->hDlg = hwndParent; SetDlgText(hwndParent, IDC_HDW_DETWARN_PROGRESSTEXT, IDS_DETECTPROGRESS, IDS_DETECTPROGRESS); while (!HardwareWiz->ExitDetect && ClassGuidNum--) { hDeviceInfo = SetupDiGetClassDevs(ClassGuid, REGSTR_KEY_ROOTENUM, hwndParent, DIGCF_PROFILE ); if (hDeviceInfo != INVALID_HANDLE_VALUE) { ClassDevInfo->Missing = hDeviceInfo; } hDeviceInfo = SetupDiCreateDeviceInfoList(ClassGuid, hwndParent); if (hDeviceInfo != INVALID_HANDLE_VALUE) { ClassDevInfo->Detected = hDeviceInfo; } HardwareWiz->DeviceDetection->ClassGuid = ClassGuid; HardwareWiz->DeviceDetection->ClassProgress = 0; // set progress bar to zero. SendDlgItemMessage(hwndParent, IDC_HDW_DETWARN_PROGRESSBAR, PBM_SETPOS, 0, 0 ); if (!SetupDiGetClassDescription(HardwareWiz->DeviceDetection->ClassGuid, ClassName, sizeof(ClassName)/sizeof(TCHAR), NULL ) && !SetupDiClassNameFromGuid(HardwareWiz->DeviceDetection->ClassGuid, ClassName, sizeof(ClassName)/sizeof(TCHAR), NULL )) { *ClassName = TEXT('\0'); } LoadString(hHdwWiz, IDS_DETECTCLASS, Format, sizeof(Format)/sizeof(TCHAR)); wsprintf(Buffer, Format, ClassName); SetDlgItemText(hwndParent, IDC_HDW_DETWARN_PROGRESSTEXT, Buffer ); if (!IsEqualGUID(ClassGuid, &GUID_NULL) && !IsEqualGUID(ClassGuid, &GUID_DEVCLASS_UNKNOWN) && ClassDevInfo->Missing && ClassDevInfo->Detected && SetupDiSetClassInstallParams(ClassDevInfo->Detected, NULL, &DetectDeviceParams.ClassInstallHeader, sizeof(DetectDeviceParams) ) && SetupDiCallClassInstaller(DIF_DETECT, ClassDevInfo->Detected, NULL)) { SP_DEVINSTALL_PARAMS DeviceInstallParams; SendDlgItemMessage(hwndParent, IDC_HDW_DETWARN_TOTALPROGRESSBAR, PBM_SETPOS, HardwareWiz->DeviceDetection->TotalProgress, 0 ); // // Clear the class install parameters. // SetupDiSetClassInstallParams(ClassDevInfo->Detected, NULL, NULL, 0 ); // // Get the device install parameters for the reboot flags. // DeviceInstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS); if (SetupDiGetDeviceInstallParams(ClassDevInfo->Detected, NULL, &DeviceInstallParams )) { HardwareWiz->DeviceDetection->Reboot |= DeviceInstallParams.Flags & (DI_NEEDRESTART | DI_NEEDREBOOT); } if (BuildMissingAndNew(hwndParent, ClassDevInfo)) { HardwareWiz->DeviceDetection->MissingOrNew = TRUE; } } else { DestroyClassDevinfo(ClassDevInfo); } HardwareWiz->DeviceDetection->TotalProgress += 10; SendDlgItemMessage(hwndParent, IDC_HDW_DETWARN_PROGRESSBAR, PBM_SETPOS, 100, 0); SendDlgItemMessage(hwndParent, IDC_HDW_DETWARN_TOTALPROGRESSBAR, PBM_STEPIT, 0, 0); ClassDevInfo++; ClassGuid++; } } INT_PTR CALLBACK HdwDetectionDlgProc( HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam ) { PHARDWAREWIZ HardwareWiz = (PHARDWAREWIZ)GetWindowLongPtr(hDlg, DWLP_USER); HWND hwndParentDlg=GetParent(hDlg); switch (wMsg) { case WM_INITDIALOG: { LPPROPSHEETPAGE lppsp = (LPPROPSHEETPAGE)lParam; HardwareWiz = (PHARDWAREWIZ)lppsp->lParam; SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)HardwareWiz); break; } case WM_DESTROY: CancelSearchRequest(HardwareWiz); DestroyDeviceDetection(HardwareWiz, FALSE); break; break; case WM_NOTIFY: switch (((NMHDR FAR *)lParam)->code) { case PSN_SETACTIVE: { int Len, PrevPage; PrevPage = HardwareWiz->PrevPage; HardwareWiz->PrevPage = IDD_ADDDEVICE_DETECTION; // Coming back, after doing a previous detection if (PrevPage == IDD_ADDDEVICE_DETECTINSTALL) { DestroyDeviceDetection(HardwareWiz, TRUE); PropSheet_PressButton(hwndParentDlg, PSBTN_BACK); break; } // // Only back,cancel button, when detection completes ok, we will // jump directly to the next page. // PropSheet_SetWizButtons(hwndParentDlg, PSWIZB_BACK ); // refresh the class guid list HdwBuildClassInfoList(HardwareWiz, DIBCI_NOINSTALLCLASS, HardwareWiz->hMachine ? HardwareWiz->MachineName : NULL ); // allocate memory for DeviceDetection data Len = sizeof(DEVICEDETECTION) + (HardwareWiz->ClassGuidNum * sizeof(CLASSDEVINFO)); HardwareWiz->DeviceDetection = LocalAlloc(LPTR, Len); if (!HardwareWiz->DeviceDetection) { PropSheet_PressButton(hwndParentDlg, PSBTN_BACK); break; } memset(HardwareWiz->DeviceDetection, 0, Len); HardwareWiz->ExitDetect = FALSE; // set progress bar to zero. SendDlgItemMessage(hDlg, IDC_HDW_DETWARN_TOTALPROGRESSBAR, PBM_SETPOS, 0, 0 ); // set the range to 10 * number of classes SendDlgItemMessage(hDlg, IDC_HDW_DETWARN_TOTALPROGRESSBAR, PBM_SETRANGE, 0, MAKELPARAM(0, 10 * HardwareWiz->ClassGuidNum) ); // set the step to 10. SendDlgItemMessage(hDlg, IDC_HDW_DETWARN_TOTALPROGRESSBAR, PBM_SETSTEP, 10, 0 ); HardwareWiz->CurrCursor = HardwareWiz->IdcAppStarting; SetCursor(HardwareWiz->CurrCursor); SearchThreadRequest(HardwareWiz->SearchThread, hDlg, SEARCH_DETECT, 0 ); } break; case PSN_QUERYCANCEL: if (HardwareWiz->ExitDetect) { SetDlgMsgResult(hDlg, wMsg, TRUE); } HardwareWiz->ExitDetect = TRUE; HardwareWiz->CurrCursor = HardwareWiz->IdcWait; SetCursor(HardwareWiz->CurrCursor); CancelSearchRequest(HardwareWiz); HardwareWiz->CurrCursor = NULL; SetDlgMsgResult(hDlg, wMsg, FALSE); break; case PSN_RESET: DestroyDeviceDetection(HardwareWiz, TRUE); break; // // we receive back if // coming back from a previous search result // when user wants to stop current search. // case PSN_WIZBACK: if (HardwareWiz->DeviceDetection) { if (HardwareWiz->ExitDetect) { SetDlgMsgResult(hDlg, wMsg, -1); break; } HardwareWiz->ExitDetect = TRUE; HardwareWiz->CurrCursor = HardwareWiz->IdcWait; SetCursor(HardwareWiz->CurrCursor); CancelSearchRequest(HardwareWiz); HardwareWiz->CurrCursor = NULL; DestroyDeviceDetection(HardwareWiz, TRUE); } SetDlgMsgResult(hDlg, wMsg, IDD_ADDDEVICE_ASKDETECT); break; // // next button is off, we only receive this after doing detection. // case PSN_WIZNEXT: SetDlgMsgResult(hDlg, wMsg, IDD_ADDDEVICE_DETECTINSTALL); break; } break; case WUM_DETECT: HardwareWiz->CurrCursor = NULL; SetCursor(HardwareWiz->IdcArrow); if (HardwareWiz->ExitDetect == TRUE) { break; } // // finish building the missing\detected stuff // PropSheet_PressButton(hwndParentDlg, PSBTN_NEXT); break; case WM_SETCURSOR: if (HardwareWiz->CurrCursor) { SetCursor(HardwareWiz->CurrCursor); break; } // fall thru to return(FALSE); default: return(FALSE); } return(TRUE); } DWORD InstallNewDevices( HWND hwndParent, HDEVINFO NewDevices, HWND hwndListView ) { DWORD Reboot, dwRet = 0; int iNewDevices; SP_DEVINFO_DATA DevInfoData; DevInfoData.cbSize = sizeof(DevInfoData); iNewDevices = 0; Reboot = 0; while (SetupDiEnumDeviceInfo(NewDevices, iNewDevices++, &DevInfoData)) { if (DevInstIsSelected(hwndListView, DevInfoData.DevInst)) { SetupDiSetSelectedDevice(NewDevices, &DevInfoData); if (hNewDev) { if (!pInstallSelectedDevice) { pInstallSelectedDevice = (PVOID) GetProcAddress(hNewDev, "InstallSelectedDevice"); } } if (pInstallSelectedDevice) { pInstallSelectedDevice(hwndParent, NewDevices, &dwRet ); } } else { SP_REMOVEDEVICE_PARAMS RemoveDeviceParams; RemoveDeviceParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER); RemoveDeviceParams.ClassInstallHeader.InstallFunction = DIF_REMOVE; RemoveDeviceParams.Scope = DI_REMOVEDEVICE_GLOBAL; RemoveDeviceParams.HwProfile = 0; if (SetupDiSetClassInstallParams(NewDevices, &DevInfoData, (PSP_CLASSINSTALL_HEADER)&RemoveDeviceParams, sizeof(RemoveDeviceParams) )) { SetupDiCallClassInstaller(DIF_REMOVE, NewDevices, &DevInfoData); } // // Clear the class install parameters. // SetupDiSetClassInstallParams(NewDevices, &DevInfoData, NULL, 0 ); } Reboot |= dwRet; } SetupDiDestroyDeviceInfoList(NewDevices); return Reboot; } /* * InstallMissingAndNewDevices * * Missing devices are removed. * NewDevices are installed by invoking InstallDevic * */ void InstallDetectedDevices( HWND hwndParent, PHARDWAREWIZ HardwareWiz ) { int ClassGuidNum; PCLASSDEVINFO ClassDevInfo; LPGUID ClassGuid; HWND hwndDetectList; if (!HardwareWiz->DeviceDetection) { return; } ClassGuidNum = HardwareWiz->ClassGuidNum; ClassGuid = HardwareWiz->ClassGuidList; ClassDevInfo = HardwareWiz->DeviceDetection->ClassDevInfo; hwndDetectList = GetDlgItem(hwndParent,IDC_HDW_INSTALLDET_LIST);; while (ClassGuidNum--) { if (ClassDevInfo->Missing) { RemoveDeviceInfo(ClassDevInfo->Missing, hwndDetectList); ClassDevInfo->Missing = NULL; } if (ClassDevInfo->Detected) { HardwareWiz->Reboot |= InstallNewDevices(hwndParent, ClassDevInfo->Detected, hwndDetectList); ClassDevInfo->Detected = NULL; } ClassDevInfo++; ClassGuid++; } HardwareWiz->DeviceDetection->MissingOrNew = FALSE; } void AddDeviceDescription( PHARDWAREWIZ HardwareWiz, HWND hListView, HDEVINFO Devices, BOOL Install ) { PTCHAR FriendlyName; LV_ITEM lviItem; int iItem; int iDevices; GUID ClassGuid; SP_DEVINFO_DATA DevInfoData; SP_DRVINFO_DATA DriverInfoData; TCHAR Format[LINE_LEN]; TCHAR DeviceDesc[MAX_PATH*2]; TCHAR String[LINE_LEN]; if (Install) { LoadString(hHdwWiz, IDS_INSTALL_LEGACY_DEVICE, Format, sizeof(Format)/sizeof(TCHAR)); } else { LoadString(hHdwWiz, IDS_UNINSTALL_LEGACY_DEVICE, Format, sizeof(Format)/sizeof(TCHAR)); } lviItem.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE; lviItem.iItem = -1; lviItem.iSubItem = 0; lviItem.state = 0; lviItem.stateMask = LVIS_SELECTED; if (HardwareWiz->ClassImageList.cbSize && SetupDiGetDeviceInfoListClass(Devices, &ClassGuid) && SetupDiGetClassImageIndex(&HardwareWiz->ClassImageList, &ClassGuid, &lviItem.iImage )) { lviItem.mask |= LVIF_IMAGE; } DevInfoData.cbSize = sizeof(DevInfoData); DriverInfoData.cbSize = sizeof(DriverInfoData); iDevices = 0; while (SetupDiEnumDeviceInfo(Devices, iDevices++, &DevInfoData)) { lviItem.lParam = DevInfoData.DevInst; if (SetupDiGetSelectedDriver(Devices, &DevInfoData, &DriverInfoData ) && *DriverInfoData.Description) { wcscpy(DeviceDesc, DriverInfoData.Description); } else { FriendlyName = BuildFriendlyName(DevInfoData.DevInst, NULL); if (FriendlyName) { wcscpy(DeviceDesc, FriendlyName); LocalFree(FriendlyName); } else { lstrcpyn(DeviceDesc, szUnknown, SIZECHARS(DeviceDesc)); } } wsprintf(String, Format, DeviceDesc); lviItem.pszText = String; // // Send it to the listview // iItem = ListView_InsertItem(hListView, &lviItem); if (iItem != -1) { // set the checkbox, control uses one based index, while imageindex is zero based ListView_SetItemState(hListView, iItem, INDEXTOSTATEIMAGEMASK(2), LVIS_STATEIMAGEMASK); } } } void ShowDetectedDevices( HWND hDlg, PHARDWAREWIZ HardwareWiz ) { INT lvIndex; int ClassGuidNum; PCLASSDEVINFO ClassDevInfo; LPGUID ClassGuid; HWND hwndDetectList; PTCHAR FriendlyName; LPTSTR Description; hwndDetectList = GetDlgItem(hDlg,IDC_HDW_INSTALLDET_LIST); SendMessage(hwndDetectList, WM_SETREDRAW, FALSE, 0L); ListView_DeleteAllItems(hwndDetectList); if (HardwareWiz->ClassImageList.cbSize) { ListView_SetImageList(hwndDetectList, HardwareWiz->ClassImageList.ImageList, LVSIL_SMALL ); } // // Display the new devices // ClassGuidNum = HardwareWiz->ClassGuidNum; ClassGuid = HardwareWiz->ClassGuidList; ClassDevInfo = HardwareWiz->DeviceDetection->ClassDevInfo; while (ClassGuidNum--) { if (ClassDevInfo->Detected) { AddDeviceDescription(HardwareWiz, hwndDetectList, ClassDevInfo->Detected, TRUE); } ClassDevInfo++; ClassGuid++; } // // Display the missing devices // ClassGuidNum = HardwareWiz->ClassGuidNum; ClassGuid = HardwareWiz->ClassGuidList; ClassDevInfo = HardwareWiz->DeviceDetection->ClassDevInfo; while (ClassGuidNum--) { if (ClassDevInfo->Missing) { AddDeviceDescription(HardwareWiz, hwndDetectList, ClassDevInfo->Missing, FALSE); } ClassDevInfo++; ClassGuid++; } // // scroll the first item into view. // ListView_EnsureVisible(hwndDetectList, , 0, FALSE); ListView_SetColumnWidth(hwndDetectList, , 0, LVSCW_AUTOSIZE_USEHEADER); SendMessage(hwndDetectList, WM_SETREDRAW, TRUE, 0L); } INT_PTR CALLBACK HdwDetectInstallDlgProc( HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam ) { PHARDWAREWIZ HardwareWiz = (PHARDWAREWIZ)GetWindowLongPtr(hDlg, DWLP_USER); HWND hwndParentDlg=GetParent(hDlg); TCHAR PropSheetHeaderTitle[MAX_PATH]; switch (wMsg) { case WM_INITDIALOG: { HWND hwndDetectList; LV_COLUMN lvcCol; LPPROPSHEETPAGE lppsp = (LPPROPSHEETPAGE)lParam; HardwareWiz = (PHARDWAREWIZ)lppsp->lParam; SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)HardwareWiz); hwndDetectList = GetDlgItem(hDlg, IDC_HDW_INSTALLDET_LIST); // Insert a column for the class list lvcCol.mask = LVCF_FMT | LVCF_WIDTH; lvcCol.fmt = LVCFMT_LEFT; lvcCol.iSubItem = 0; ListView_InsertColumn(hwndDetectList, 0, &lvcCol); ListView_SetExtendedListViewStyleEx(hwndDetectList, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES); break; } case WM_DESTROY: break; case WM_NOTIFY: switch (((NMHDR FAR *)lParam)->code) { case PSN_SETACTIVE: HardwareWiz->PrevPage = IDD_ADDDEVICE_DETECTINSTALL; if (HardwareWiz->DeviceDetection->MissingOrNew) { ShowDetectedDevices(hDlg, HardwareWiz); SetDlgText(hDlg, IDC_HDW_TEXT, IDS_HDW_INSTALLDET1, IDS_HDW_INSTALLDET1); PropSheet_SetWizButtons(hwndParentDlg, PSWIZB_BACK | PSWIZB_NEXT); ShowWindow(GetDlgItem(hDlg, IDC_HDW_INSTALLDET_LISTTITLE), SW_SHOW); ShowWindow(GetDlgItem(hDlg, IDC_HDW_INSTALLDET_LIST), SW_SHOW); } else if (HardwareWiz->DeviceDetection->Reboot) { PropSheet_SetWizButtons(hwndParentDlg, 0); SetDlgMsgResult(hDlg, wMsg, IDD_ADDDEVICE_DETECTREBOOT); break; } else { // // hide the list box // ShowWindow(GetDlgItem(hDlg, IDC_HDW_INSTALLDET_LISTTITLE), SW_HIDE); ShowWindow(GetDlgItem(hDlg, IDC_HDW_INSTALLDET_LIST), SW_HIDE); SetDlgText(hDlg, IDC_HDW_TEXT, IDS_HDW_NONEDET1, IDS_HDW_NONEDET1); if (LoadString(hHdwWiz, IDS_ADDDEVICE_DETECTINSTALL_NONE, PropSheetHeaderTitle, SIZECHARS(PropSheetHeaderTitle) )) { PropSheet_SetHeaderTitle(GetParent(hDlg), PropSheet_IdToIndex(GetParent(hDlg), IDD_ADDDEVICE_DETECTINSTALL), PropSheetHeaderTitle ); } PropSheet_SetWizButtons(hwndParentDlg, PSWIZB_BACK | PSWIZB_NEXT); } break; case PSN_WIZBACK: SetDlgMsgResult(hDlg, wMsg, IDD_ADDDEVICE_DETECTION); break; case PSN_WIZNEXT: if (HardwareWiz->DeviceDetection->MissingOrNew) { InstallDetectedDevices(hDlg, HardwareWiz); HardwareWiz->Reboot |= HardwareWiz->DeviceDetection->Reboot; SetDlgMsgResult(hDlg, wMsg, IDD_ADDDEVICE_DETECTREBOOT); } else { DestroyDeviceDetection(HardwareWiz, FALSE); SetDlgMsgResult(hDlg, wMsg, IDD_ADDDEVICE_SELECTCLASS); } break; case PSN_RESET: DestroyDeviceDetection(HardwareWiz, TRUE); break; } break; default: return(FALSE); } return(TRUE); } INT_PTR CALLBACK HdwDetectRebootDlgProc( HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam ) { PHARDWAREWIZ HardwareWiz = (PHARDWAREWIZ)GetWindowLongPtr(hDlg, DWLP_USER); HWND hwndParentDlg=GetParent(hDlg); switch (wMsg) { case WM_INITDIALOG: { LPPROPSHEETPAGE lppsp = (LPPROPSHEETPAGE)lParam; HardwareWiz = (PHARDWAREWIZ)lppsp->lParam; SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)HardwareWiz); SetWindowFont(GetDlgItem(hDlg, IDC_HDWNAME), HardwareWiz->hfontTextBigBold, TRUE); break; } case WM_DESTROY: break; case WM_NOTIFY: switch (((NMHDR FAR *)lParam)->code) { case PSN_SETACTIVE: HardwareWiz->PrevPage = IDD_ADDDEVICE_DETECTREBOOT; if (HardwareWiz->Reboot && HardwareWiz->PromptForReboot) { SetDlgText(hDlg, IDC_HDW_TEXT, IDS_HDW_REBOOTDET, IDS_HDW_REBOOTDET); } else { SetDlgText(hDlg, IDC_HDW_TEXT, IDS_HDW_NOREBOOTDET, IDS_HDW_NOREBOOTDET); } // // no back, no next! This page is just to confirm that the // user will continue detection after rebooting. // PropSheet_SetWizButtons(hwndParentDlg, PSWIZB_FINISH); EnableWindow(GetDlgItem(hwndParentDlg, IDCANCEL), FALSE); break; case PSN_WIZFINISH: DestroyDeviceDetection(HardwareWiz, FALSE); break; } break; default: return(FALSE); } return(TRUE); }