windows-nt/Source/XPSP1/NT/base/pnp/hdwwiz/detect.c
2020-09-26 16:20:57 +08:00

1288 lines
35 KiB
C

//+-------------------------------------------------------------------------
//
// 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);
}