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

838 lines
22 KiB
C

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1998 - 1999
//
// File: pnpenum.c
//
//--------------------------------------------------------------------------
#include "hdwwiz.h"
INT_PTR CALLBACK HdwAskDetectDlgProc(
HWND hDlg,
UINT wMsg,
WPARAM wParam,
LPARAM lParam
)
{
PHARDWAREWIZ HardwareWiz = (PHARDWAREWIZ)GetWindowLongPtr(hDlg, DWLP_USER);
switch (wMsg) {
case WM_INITDIALOG: {
HWND hwndParentDlg;
HICON hIcon;
LPPROPSHEETPAGE lppsp = (LPPROPSHEETPAGE)lParam;
HardwareWiz = (PHARDWAREWIZ)lppsp->lParam;
SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)HardwareWiz);
break;
}
case WM_COMMAND:
break;
case WM_NOTIFY:
switch (((NMHDR FAR *)lParam)->code) {
case PSN_SETACTIVE:
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK | PSWIZB_NEXT);
HardwareWiz->PrevPage = IDD_ADDDEVICE_ASKDETECT;
//
// Set the Initial radio button state.
// default to do autodetection.
//
CheckRadioButton(hDlg,
IDC_ADDDEVICE_ASKDETECT_AUTO,
IDC_ADDDEVICE_ASKDETECT_SPECIFIC,
IDC_ADDDEVICE_ASKDETECT_AUTO
);
break;
case PSN_WIZBACK:
//
// If we are going back then this is effectively a Cancel
//
SetDlgMsgResult(hDlg, wMsg, IDD_ADDDEVICE_PROBLIST);
break;
case PSN_WIZNEXT:
if (IsDlgButtonChecked(hDlg, IDC_ADDDEVICE_ASKDETECT_AUTO)) {
SetDlgMsgResult(hDlg, wMsg, IDD_ADDDEVICE_DETECTION);
} else {
SetDlgMsgResult(hDlg, wMsg, IDD_ADDDEVICE_SELECTCLASS);
}
break;
case PSN_RESET:
HardwareWiz->Cancelled = TRUE;
break;
}
break;
default:
return(FALSE);
}
return(TRUE);
}
DWORD
PNPEnumerate(
PHARDWAREWIZ HardwareWiz
)
{
CONFIGRET ConfigRet;
DEVINST RootDevInst, ChildDevInst;
HDEVINFO hDeviceInfo;
if (HardwareWiz->ExitDetect) {
return 0;
}
//
// reenumerate from the root of the devnode tree
//
ConfigRet = CM_Locate_DevNode_Ex(&RootDevInst,
NULL,
CM_LOCATE_DEVNODE_NORMAL,
NULL
);
if (ConfigRet != CR_SUCCESS) {
return 0;
}
//
// Force install of ALL devices which still need installing.
// save reboot flags to pass back to main thread.
//
ConfigRet = CM_Get_Child_Ex(&ChildDevInst,
RootDevInst,
0,
NULL
);
if (ConfigRet == CR_SUCCESS) {
InstallSilentChildSiblings(NULL, HardwareWiz, ChildDevInst, TRUE);
}
if (HardwareWiz->Reboot) {
return 0;
}
Sleep(100); // give a chance for new devices to be noticed by PNP
//
// Ask PNP to look for newly arrived devices.
//
CM_Reenumerate_DevNode_Ex(
RootDevInst,
CM_REENUMERATE_SYNCHRONOUS | CM_REENUMERATE_RETRY_INSTALLATION,
NULL
);
Sleep(5000); // give a chance for new devices to be noticed by PNP
do {
if (HardwareWiz->ExitDetect) {
return 0;
}
} while (CMP_WaitNoPendingInstallEvents(1000) == WAIT_TIMEOUT);
return 0;
}
int
InsertDeviceNodeListView(
HWND hwndList,
PHARDWAREWIZ HardwareWiz,
HDEVINFO hDeviceInfo,
PSP_DEVINFO_DATA DeviceInfoData
)
{
INT lvIndex;
LV_ITEM lviItem;
PTCHAR DeviceName;
TCHAR Buffer[MAX_PATH];
ULONG Status = 0, Problem = 0;
lviItem.mask = LVIF_TEXT | LVIF_PARAM;
lviItem.iItem = -1;
lviItem.iSubItem = 0;
if (SetupDiGetClassImageIndex(&HardwareWiz->ClassImageList,
&DeviceInfoData->ClassGuid,
&lviItem.iImage
)) {
lviItem.mask |= LVIF_IMAGE;
}
DeviceName = BuildFriendlyName(DeviceInfoData->DevInst, NULL);
if (DeviceName) {
lviItem.pszText = DeviceName;
} else {
lviItem.pszText = szUnknown;
}
lviItem.mask |= LVIF_STATE;
if (CM_Get_DevNode_Status(&Status, &Problem, DeviceInfoData->DevInst, 0) == CR_SUCCESS) {
if (Problem) {
//
// Add the yellow ! or red X overlay to the devnode if it has a
// problem.
//
lviItem.state = (Problem == CM_PROB_DISABLED) ?
INDEXTOOVERLAYMASK(IDI_DISABLED_OVL - IDI_CLASSICON_OVERLAYFIRST + 1) :
INDEXTOOVERLAYMASK(IDI_PROBLEM_OVL - IDI_CLASSICON_OVERLAYFIRST + 1);
} else {
lviItem.state = INDEXTOOVERLAYMASK(0);
}
lviItem.stateMask = LVIS_OVERLAYMASK;
}
lviItem.lParam = (LPARAM)DeviceInfoData->DevInst;
lvIndex = ListView_InsertItem(hwndList, &lviItem);
if (DeviceName) {
LocalFree(DeviceName);
}
return lvIndex;
}
BOOL
AnyNewPnPDevicesFound(
HWND hDlg,
PHARDWAREWIZ HardwareWiz
)
{
HDEVINFO NewDeviceInfo, OldDeviceInfo;
BOOL NewDevicesFound;
BOOL NewDevice;
INT iNew, iOld;
SP_DEVINFO_DATA NewDeviceInfoData, OldDeviceInfoData;
OldDeviceInfo = HardwareWiz->PNPEnumDeviceInfo;
NewDeviceInfo = SetupDiGetClassDevs(NULL,
NULL,
GetParent(hDlg),
DIGCF_ALLCLASSES
);
if (!OldDeviceInfo || NewDeviceInfo == INVALID_HANDLE_VALUE) {
return FALSE;
}
NewDevicesFound = FALSE;
iNew = 0;
NewDeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
while (SetupDiEnumDeviceInfo(NewDeviceInfo, iNew++, &NewDeviceInfoData)) {
NewDevice = TRUE;
iOld = 0;
OldDeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
while (SetupDiEnumDeviceInfo(OldDeviceInfo, iOld++, &OldDeviceInfoData)) {
if (NewDeviceInfoData.DevInst == OldDeviceInfoData.DevInst) {
//
// If this DevInst exists in the Old DeviceInfo list then it is
// not a new device.
//
NewDevice = FALSE;
break;
}
}
//
// If we did not find this device in the original list then it is a new
// PnP device. Set the NewDevicesFound BOOL and break out of the loop.
//
if (NewDevice) {
NewDevicesFound = TRUE;
break;
}
}
SetupDiDestroyDeviceInfoList(NewDeviceInfo);
return NewDevicesFound;
}
INT_PTR CALLBACK
HdwPnpEnumDlgProc(
HWND hDlg,
UINT wMsg,
WPARAM wParam,
LPARAM lParam
)
{
PHARDWAREWIZ HardwareWiz = (PHARDWAREWIZ)GetWindowLongPtr(hDlg, DWLP_USER);
if (wMsg == WM_INITDIALOG) {
LPPROPSHEETPAGE lppsp = (LPPROPSHEETPAGE)lParam;
HardwareWiz = (PHARDWAREWIZ)lppsp->lParam;
SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)HardwareWiz);
return TRUE;
}
switch (wMsg) {
case WM_COMMAND:
break;
case WM_DESTROY:
if (HardwareWiz->PNPEnumDeviceInfo) {
SetupDiDestroyDeviceInfoList(HardwareWiz->PNPEnumDeviceInfo);
HardwareWiz->PNPEnumDeviceInfo = NULL;
}
break;
case WUM_PNPENUMERATE:
HardwareWiz->InstallPending = FALSE;
HardwareWiz->CurrCursor = NULL;
SetCursor(HardwareWiz->IdcArrow);
Animate_Stop(GetDlgItem(hDlg, IDC_ANIMATE_SEARCH));
if (HardwareWiz->ExitDetect) {
break;
}
HardwareWiz->FoundPnPDevices = AnyNewPnPDevicesFound(hDlg, HardwareWiz);
PropSheet_PressButton(GetParent(hDlg), PSBTN_NEXT);
break;
case WM_NOTIFY:
switch (((NMHDR FAR *)lParam)->code) {
case PSN_SETACTIVE: {
int PrevPage;
PrevPage = HardwareWiz->PrevPage;
HardwareWiz->PrevPage = IDD_ADDDEVICE_PNPENUM;
HardwareWiz->ExitDetect = FALSE;
//
// If moving forwards, kick off enumeration.
//
if (PrevPage != IDD_ADDDEVICE_ASKDETECT) {
EnableWindow(GetDlgItem(GetParent(hDlg), IDCANCEL), FALSE);
PropSheet_SetWizButtons(GetParent(hDlg), 0);
SetDlgText(hDlg, IDC_HDW_TEXT, IDS_ADDDEVICE_PNPENUMERATE, IDS_ADDDEVICE_PNPENUMERATE);
Animate_Open(GetDlgItem(hDlg, IDC_ANIMATE_SEARCH), MAKEINTRESOURCE(IDA_SEARCHING));
Animate_Play(GetDlgItem(hDlg, IDC_ANIMATE_SEARCH), 0, -1, -1);
//
// Create a list of all of the installed devices, which
// will be used after enumeration to build the list of
// newly installed.
//
HardwareWiz->PNPEnumDeviceInfo = SetupDiGetClassDevs(
NULL,
NULL,
GetParent(hDlg),
DIGCF_ALLCLASSES
);
if (HardwareWiz->PNPEnumDeviceInfo == INVALID_HANDLE_VALUE) {
HardwareWiz->PNPEnumDeviceInfo = NULL;
}
HardwareWiz->InstallPending = TRUE;
HardwareWiz->CurrCursor = HardwareWiz->IdcAppStarting;
SetCursor(HardwareWiz->CurrCursor);
if (!SearchThreadRequest(HardwareWiz->SearchThread,
hDlg,
SEARCH_PNPENUM,
0
)) {
EnableWindow(GetDlgItem(GetParent(hDlg), IDCANCEL), TRUE);
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK| PSWIZB_NEXT);
SetDlgText(hDlg, IDC_HDW_TEXT, IDS_ADDDEVICE_PNPENUMERROR, IDS_ADDDEVICE_PNPENUMERROR);
Animate_Stop(GetDlgItem(hDlg, IDC_ANIMATE_SEARCH));
}
}
}
break;
case PSN_QUERYCANCEL:
if (HardwareWiz->InstallPending) {
if (HardwareWiz->ExitDetect) {
SetDlgMsgResult(hDlg, wMsg, TRUE);
break;
}
HardwareWiz->ExitDetect = TRUE;
HardwareWiz->CurrCursor = HardwareWiz->IdcWait;
SetCursor(HardwareWiz->CurrCursor);
CancelSearchRequest(HardwareWiz);
HardwareWiz->CurrCursor = NULL;
}
SetDlgMsgResult(hDlg, wMsg, FALSE);
break;
case PSN_RESET:
HardwareWiz->Cancelled = TRUE;
Animate_Stop(GetDlgItem(hDlg, IDC_ANIMATE_SEARCH));
break;
case PSN_WIZBACK:
SetDlgMsgResult(hDlg, wMsg, IDD_ADDDEVICE_WELCOME);
break;
case PSN_WIZNEXT:
if (HardwareWiz->FoundPnPDevices) {
SetDlgMsgResult(hDlg, wMsg, IDD_ADDDEVICE_PNPFINISH);
} else {
EnableWindow(GetDlgItem(GetParent(hDlg), IDCANCEL), TRUE);
SetDlgMsgResult(hDlg, wMsg, IDD_ADDDEVICE_CONNECTED);
}
break;
}
break;
case WM_SETCURSOR:
if (HardwareWiz->CurrCursor) {
SetCursor(HardwareWiz->CurrCursor);
break;
}
// fall thru to return(FALSE);
default:
return(FALSE);
}
return(TRUE);
}
BOOL
FillInstalledDevicesList(
HWND hDlg,
PHARDWAREWIZ HardwareWiz
)
{
HDEVINFO NewDeviceInfo, OldDeviceInfo;
BOOL Installed;
BOOL NewDevice;
INT iNew, iOld;
SP_DEVINFO_DATA NewDeviceInfoData, OldDeviceInfoData;
HWND hwndList;
hwndList = GetDlgItem(hDlg, IDC_FOUNDPNP_LIST);
SendMessage(hwndList, WM_SETREDRAW, FALSE, 0L);
ListView_DeleteAllItems(hwndList);
OldDeviceInfo = HardwareWiz->PNPEnumDeviceInfo;
NewDeviceInfo = SetupDiGetClassDevs(NULL,
NULL,
GetParent(hDlg),
DIGCF_ALLCLASSES
);
if (!OldDeviceInfo || NewDeviceInfo == INVALID_HANDLE_VALUE) {
SendMessage(hwndList, WM_SETREDRAW, TRUE, 0L);
return FALSE;
}
//
// For each element in the new list check to see if its in the old list.
// If its not then it is a newly installed devnode so add it to the list box.
//
Installed = FALSE;
iNew = 0;
NewDeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
while (SetupDiEnumDeviceInfo(NewDeviceInfo, iNew++, &NewDeviceInfoData)) {
NewDevice = TRUE;
iOld = 0;
OldDeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
while (SetupDiEnumDeviceInfo(OldDeviceInfo, iOld++, &OldDeviceInfoData)) {
if (NewDeviceInfoData.DevInst == OldDeviceInfoData.DevInst) {
//
// If this DevInst exists in the Old DeviceInfo list then it is
// not a new device.
//
NewDevice = FALSE;
break;
}
}
//
// If this is a new device then add it to the list view and set
// the Installed boolean to TRUE.
//
if (NewDevice) {
InsertDeviceNodeListView(hwndList, HardwareWiz, NewDeviceInfo, &NewDeviceInfoData);
Installed = TRUE;
}
}
SetupDiDestroyDeviceInfoList(NewDeviceInfo);
if (!Installed) {
SendMessage(hwndList, WM_SETREDRAW, TRUE, 0L);
SetupDiDestroyDeviceInfoList(HardwareWiz->PNPEnumDeviceInfo);
HardwareWiz->PNPEnumDeviceInfo = NULL;
return FALSE;
}
ListView_SetItemState(hwndList,
0,
LVIS_SELECTED|LVIS_FOCUSED,
LVIS_SELECTED|LVIS_FOCUSED
);
//
// scroll the selected item into view.
//
ListView_EnsureVisible(hwndList, 0, FALSE);
ListView_SetColumnWidth(hwndList, 0, LVSCW_AUTOSIZE_USEHEADER);
SendMessage(hwndList, WM_SETREDRAW, TRUE, 0L);
return Installed;
}
BOOL
InitPnpFinishDlgProc(
HWND hDlg,
PHARDWAREWIZ HardwareWiz
)
{
HFONT hfont;
HICON hIcon;
int FontSize, PtsPixels;
HWND hwndParentDlg;
HWND hwndList;
LV_COLUMN lvcCol;
LOGFONT LogFont;
TCHAR Buffer[64];
//
// Insert columns for listview.
// 0 == device name
//
hwndList = GetDlgItem(hDlg, IDC_FOUNDPNP_LIST);
lvcCol.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
lvcCol.fmt = LVCFMT_LEFT;
lvcCol.pszText = Buffer;
lvcCol.iSubItem = 0;
LoadString(hHdwWiz, IDS_DEVINSTALLED, Buffer, SIZECHARS(Buffer));
ListView_InsertColumn(hwndList, 0, &lvcCol);
SendMessage(hwndList,
LVM_SETEXTENDEDLISTVIEWSTYLE,
LVS_EX_FULLROWSELECT,
LVS_EX_FULLROWSELECT
);
if (HardwareWiz->ClassImageList.cbSize) {
ListView_SetImageList(hwndList,
HardwareWiz->ClassImageList.ImageList,
LVSIL_SMALL
);
}
return TRUE;
}
INT_PTR CALLBACK
HdwPnpFinishDlgProc(
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);
if (!InitPnpFinishDlgProc(hDlg, HardwareWiz)) {
return FALSE;
}
break;
}
case WM_DESTROY:
break;
case WM_NOTIFY:
switch (((LPNMHDR)lParam)->code) {
case PSN_SETACTIVE:
PropSheet_SetWizButtons(hwndParentDlg, PSWIZB_FINISH);
EnableWindow(GetDlgItem(hwndParentDlg, IDCANCEL), FALSE);
FillInstalledDevicesList(hDlg, HardwareWiz);
break;
case PSN_WIZFINISH:
break;
case NM_DBLCLK:
if ((((LPNMHDR)lParam)->idFrom) == IDC_FOUNDPNP_LIST) {
LVITEM lvItem;
lvItem.mask = LVIF_PARAM;
lvItem.iSubItem = 0;
lvItem.iItem = ListView_GetNextItem(GetDlgItem(hDlg, IDC_FOUNDPNP_LIST),
-1,
LVNI_SELECTED);
if ((lvItem.iItem != -1) &&
ListView_GetItem(GetDlgItem(hDlg, IDC_FOUNDPNP_LIST), &lvItem) &&
(lvItem.lParam)) {
//
// Launch the properties for this device.
//
DeviceProperties(hDlg,
HardwareWiz->hMachine,
(LPCSTR)(HardwareWiz->hMachine ? HardwareWiz->MachineName : NULL),
(DEVNODE)lvItem.lParam,
0
);
}
}
}
break;
default:
return(FALSE);
}
return(TRUE);
}
INT_PTR CALLBACK
HdwConnectedDlgProc(
HWND hDlg,
UINT wMsg,
WPARAM wParam,
LPARAM lParam
)
{
PHARDWAREWIZ HardwareWiz = (PHARDWAREWIZ)GetWindowLongPtr(hDlg, DWLP_USER);
if (wMsg == WM_INITDIALOG) {
LPPROPSHEETPAGE lppsp = (LPPROPSHEETPAGE)lParam;
HardwareWiz = (PHARDWAREWIZ)lppsp->lParam;
SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)HardwareWiz);
return TRUE;
}
switch (wMsg) {
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDC_ADDDEVICE_CONNECTED_YES:
case IDC_ADDDEVICE_CONNECTED_NO:
//
// Only show the next button if one of the radio buttons are
// selected.
//
if (IsDlgButtonChecked(hDlg, IDC_ADDDEVICE_CONNECTED_YES) ||
IsDlgButtonChecked(hDlg, IDC_ADDDEVICE_CONNECTED_NO)) {
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK | PSWIZB_NEXT);
} else {
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK);
}
break;
}
break;
case WM_DESTROY:
break;
case WM_NOTIFY:
switch (((NMHDR FAR *)lParam)->code) {
case PSN_SETACTIVE:
HardwareWiz->PrevPage = IDD_ADDDEVICE_CONNECTED;
//
// Only show the next button if one of the radio buttons are
// selected.
//
if (IsDlgButtonChecked(hDlg, IDC_ADDDEVICE_CONNECTED_YES) ||
IsDlgButtonChecked(hDlg, IDC_ADDDEVICE_CONNECTED_NO)) {
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK | PSWIZB_NEXT);
} else {
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK);
}
break;
case PSN_WIZBACK:
SetDlgMsgResult(hDlg, wMsg, IDD_ADDDEVICE_WELCOME);
break;
case PSN_WIZNEXT:
if (IsDlgButtonChecked(hDlg, IDC_ADDDEVICE_CONNECTED_YES)) {
SetDlgMsgResult(hDlg, wMsg, IDD_ADDDEVICE_PROBLIST);
} else {
SetDlgMsgResult(hDlg, wMsg, IDD_ADDDEVICE_CONNECTED_FINISH);
}
break;
}
break;
default:
return(FALSE);
}
return(TRUE);
}
INT_PTR CALLBACK
HdwConnectedFinishDlgProc(
HWND hDlg,
UINT wMsg,
WPARAM wParam,
LPARAM lParam
)
{
PHARDWAREWIZ HardwareWiz = (PHARDWAREWIZ)GetWindowLongPtr(hDlg, DWLP_USER);
if (wMsg == 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);
return TRUE;
}
switch (wMsg) {
case WM_COMMAND:
break;
case WM_DESTROY:
break;
case WM_NOTIFY:
switch (((NMHDR FAR *)lParam)->code) {
case PSN_SETACTIVE:
PropSheet_SetWizButtons(GetParent(hDlg), PSWIZB_BACK | PSWIZB_FINISH);
break;
case PSN_WIZBACK:
SetDlgMsgResult(hDlg, wMsg, IDD_ADDDEVICE_CONNECTED);
break;
case PSN_WIZFINISH:
if (IsDlgButtonChecked(hDlg, IDC_NEED_SHUTDOWN)) {
//
// Rember that we need to shutdown.
//
HardwareWiz->Shutdown = TRUE;
}
break;
}
break;
default:
return(FALSE);
}
return(TRUE);
}