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.
263 lines
6.4 KiB
263 lines
6.4 KiB
/*++
|
|
|
|
Copyright (C) Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
devrmdlg.cpp
|
|
|
|
Abstract:
|
|
|
|
This module implements CRemoveDevDlg -- device removing dialog box
|
|
|
|
Author:
|
|
|
|
William Hsieh (williamh) created
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
#include "devmgr.h"
|
|
#include "hwprof.h"
|
|
#include "devrmdlg.h"
|
|
|
|
//
|
|
// help topic ids
|
|
//
|
|
const DWORD g_a210HelpIDs[]=
|
|
{
|
|
IDC_REMOVEDEV_ICON, IDH_DISABLEHELP, // Confirm Device Removal: "" (Static)
|
|
IDC_REMOVEDEV_DEVDESC, IDH_DISABLEHELP, // Confirm Device Removal: "" (Static)
|
|
IDC_REMOVEDEV_WARNING, IDH_DISABLEHELP, // Confirm Device Removal: "" (Static)
|
|
0, 0
|
|
};
|
|
|
|
//
|
|
// CRemoveDevDlg implementation
|
|
//
|
|
BOOL CRemoveDevDlg::OnInitDialog()
|
|
{
|
|
SetDlgItemText(m_hDlg, IDC_REMOVEDEV_DEVDESC, m_pDevice->GetDisplayName());
|
|
HICON hIconOld;
|
|
hIconOld = (HICON)SendDlgItemMessage(m_hDlg, IDC_REMOVEDEV_ICON,
|
|
STM_SETICON,
|
|
(WPARAM)(m_pDevice->LoadClassIcon()),
|
|
0
|
|
);
|
|
if (hIconOld)
|
|
DestroyIcon(hIconOld);
|
|
|
|
try
|
|
{
|
|
String str;
|
|
str.LoadString(g_hInstance, IDS_REMOVEDEV_WARN);
|
|
SetDlgItemText(m_hDlg, IDC_REMOVEDEV_WARNING, str);
|
|
}
|
|
catch (CMemoryException* e)
|
|
{
|
|
e->Delete();
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void
|
|
CRemoveDevDlg::OnCommand(
|
|
WPARAM wParam,
|
|
LPARAM lParam
|
|
)
|
|
{
|
|
UNREFERENCED_PARAMETER(lParam);
|
|
|
|
if (BN_CLICKED == HIWORD(wParam))
|
|
{
|
|
if (IDOK == LOWORD(wParam))
|
|
{
|
|
OnOk();
|
|
}
|
|
|
|
else if (IDCANCEL == LOWORD(wParam))
|
|
{
|
|
EndDialog(m_hDlg, IDCANCEL);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CRemoveDevDlg::OnOk()
|
|
{
|
|
SP_REMOVEDEVICE_PARAMS rmdParams;
|
|
|
|
rmdParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
|
|
rmdParams.ClassInstallHeader.InstallFunction = DIF_REMOVE;
|
|
|
|
HCURSOR hCursorOld;
|
|
hCursorOld = SetCursor(LoadCursor(NULL, MAKEINTRESOURCE(IDC_WAIT)));
|
|
|
|
//
|
|
// Uninstall does not apply to specific profiles -- it is global.
|
|
//
|
|
rmdParams.Scope = DI_REMOVEDEVICE_GLOBAL;
|
|
rmdParams.HwProfile = 0;
|
|
|
|
//
|
|
// walk down the tree and remove all of this device's children
|
|
//
|
|
if (m_pDevice->GetChild() &&
|
|
!IsRemoveSubtreeOk(m_pDevice->GetChild(), &rmdParams))
|
|
{
|
|
//
|
|
// Children refuse the removal. Cancel the removal.
|
|
//
|
|
MsgBoxParam(m_hDlg, IDS_DESCENDANTS_VETO, 0, MB_OK | MB_ICONINFORMATION);
|
|
EndDialog(m_hDlg, IDCANCEL);
|
|
return;
|
|
}
|
|
|
|
SP_DEVINSTALL_PARAMS dip;
|
|
dip.cbSize = sizeof(dip);
|
|
m_pDevice->m_pMachine->DiSetClassInstallParams(*m_pDevice,
|
|
&rmdParams.ClassInstallHeader,
|
|
sizeof(rmdParams));
|
|
|
|
BOOL RemovalOK;
|
|
|
|
//
|
|
// Either this device has no children or the children has no
|
|
// objection on removal. Remove it.
|
|
//
|
|
RemovalOK = m_pDevice->m_pMachine->DiCallClassInstaller(DIF_REMOVE, *m_pDevice);
|
|
|
|
if (hCursorOld)
|
|
{
|
|
SetCursor(hCursorOld);
|
|
}
|
|
|
|
m_pDevice->m_pMachine->DiSetClassInstallParams(*m_pDevice, NULL, 0);
|
|
|
|
if (RemovalOK)
|
|
{
|
|
EndDialog(m_hDlg, IDOK);
|
|
}
|
|
|
|
else
|
|
{
|
|
//
|
|
// Can not removed the device, return Cancel so that
|
|
// the caller know what is going on.
|
|
//
|
|
MsgBoxParam(m_hDlg, IDS_UNINSTALL_FAILED, 0, MB_OK | MB_ICONINFORMATION);
|
|
EndDialog(m_hDlg, IDCANCEL);
|
|
}
|
|
}
|
|
|
|
//
|
|
// This function walks the substree started with the given CDevice to
|
|
// see if it is ok to removed the CDevice.
|
|
// INPUT:
|
|
// pDevice -- the device
|
|
// prmdParams -- parameter used to call the setupapi
|
|
// OUTPUT:
|
|
// TRUE -- it is ok to remove
|
|
// FALSE -- it is NOT ok to remove
|
|
BOOL
|
|
CRemoveDevDlg::IsRemoveSubtreeOk(
|
|
CDevice* pDevice,
|
|
PSP_REMOVEDEVICE_PARAMS prmdParams
|
|
)
|
|
{
|
|
BOOL Result = TRUE;
|
|
|
|
|
|
HDEVINFO hDevInfo;
|
|
while (Result && pDevice)
|
|
{
|
|
//
|
|
// if the device has children, remove all of them.
|
|
//
|
|
if (Result && pDevice->GetChild())
|
|
{
|
|
Result = IsRemoveSubtreeOk(pDevice->GetChild(), prmdParams);
|
|
}
|
|
|
|
//
|
|
// create a new HDEVINFO just for this device -- we do not want
|
|
// to change anything in the main device tree maintained by CMachine
|
|
//
|
|
hDevInfo = pDevice->m_pMachine->DiCreateDeviceInfoList(NULL, m_hDlg);
|
|
|
|
if (INVALID_HANDLE_VALUE == hDevInfo)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
SP_DEVINFO_DATA DevData;
|
|
DevData.cbSize = sizeof(DevData);
|
|
CDevInfoList DevInfoList(hDevInfo, m_hDlg);
|
|
|
|
//
|
|
// include the device in the newly created hdevinfo
|
|
//
|
|
DevInfoList.DiOpenDeviceInfo(pDevice->GetDeviceID(), m_hDlg, 0,
|
|
&DevData);
|
|
|
|
DevInfoList.DiSetClassInstallParams(&DevData,
|
|
&prmdParams->ClassInstallHeader,
|
|
sizeof(SP_REMOVEDEVICE_PARAMS)
|
|
);
|
|
|
|
//
|
|
// remove this devnode.
|
|
//
|
|
Result = DevInfoList.DiCallClassInstaller(DIF_REMOVE, &DevData);
|
|
DevInfoList.DiSetClassInstallParams(&DevData, NULL, 0);
|
|
|
|
//
|
|
// continue the query on all the siblings
|
|
//
|
|
pDevice = pDevice->GetSibling();
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
|
|
BOOL
|
|
CRemoveDevDlg::OnDestroy()
|
|
{
|
|
HICON hIcon;
|
|
|
|
hIcon = (HICON)SendDlgItemMessage(m_hDlg, IDC_REMOVEDEV_ICON, STM_GETICON, 0, 0);
|
|
|
|
if (hIcon) {
|
|
DestroyIcon(hIcon);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL
|
|
CRemoveDevDlg::OnHelp(
|
|
LPHELPINFO pHelpInfo
|
|
)
|
|
{
|
|
WinHelp((HWND)pHelpInfo->hItemHandle, DEVMGR_HELP_FILE_NAME, HELP_WM_HELP,
|
|
(ULONG_PTR)g_a210HelpIDs);
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL
|
|
CRemoveDevDlg::OnContextMenu(
|
|
HWND hWnd,
|
|
WORD xPos,
|
|
WORD yPos
|
|
)
|
|
{
|
|
UNREFERENCED_PARAMETER(xPos);
|
|
UNREFERENCED_PARAMETER(yPos);
|
|
|
|
WinHelp(hWnd, DEVMGR_HELP_FILE_NAME, HELP_CONTEXTMENU,
|
|
(ULONG_PTR)g_a210HelpIDs);
|
|
return FALSE;
|
|
}
|