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.
 
 
 
 
 
 

1292 lines
42 KiB

/*++
Copyright (C) Microsoft Corporation
Module Name:
devdrvpg.cpp
Abstract:
This module implements CDeviceDriverPage -- device driver property page
Author:
William Hsieh (williamh) created
Revision History:
--*/
// devdrvpg.cpp : implementation file
//
#include "devmgr.h"
#include "devdrvpg.h"
#include "cdriver.h"
#include "tswizard.h"
#include "devrmdlg.h"
//
// help topic ids
//
const DWORD g_a106HelpIDs[]=
{
IDC_DEVDRV_ICON, IDH_DISABLEHELP, // Driver: "" (Static)
IDC_DEVDRV_DESC, IDH_DISABLEHELP, // Driver: "" (Static)
IDC_DEVDRV_TITLE_DRIVERPROVIDER, idh_devmgr_driver_provider_main,
IDC_DEVDRV_DRIVERPROVIDER, idh_devmgr_driver_provider_main,
IDC_DEVDRV_TITLE_DRIVERDATE, idh_devmgr_driver_date_main,
IDC_DEVDRV_DRIVERDATE, idh_devmgr_driver_date_main,
IDC_DEVDRV_TITLE_DRIVERVERSION, idh_devmgr_driver_version_main,
IDC_DEVDRV_DRIVERVERSION, idh_devmgr_driver_version_main,
IDC_DEVDRV_TITLE_DRIVERSIGNER, idh_devmgr_digital_signer,
IDC_DEVDRV_DRIVERSIGNER, idh_devmgr_digital_signer,
IDC_DEVDRV_DETAILS, idh_devmgr_devdrv_details, // Driver: "Driver Details" (Button)
IDC_DEVDRV_DETAILS_TEXT, idh_devmgr_devdrv_details, // Driver: "Driver Details" (Button)
IDC_DEVDRV_UNINSTALL, idh_devmgr_devdrv_uninstall, // Driver: "Uninstall" (Button)
IDC_DEVDRV_UNINSTALL_TEXT, idh_devmgr_devdrv_uninstall, // Driver: "Uninstall" (Button)
IDC_DEVDRV_CHANGEDRIVER, idh_devmgr_driver_change_driver, // Driver: "&Change Driver..." (Button)
IDC_DEVDRV_CHANGEDRIVER_TEXT, idh_devmgr_driver_change_driver, // Driver: "&Change Driver..." (Button)
IDC_DEVDRV_ROLLBACK, idh_devmgr_rollback_button, // Driver: "Roll Back Driver..." (Button)
IDC_DEVDRV_ROLLBACK_TEXT, idh_devmgr_rollback_button, // Driver: "Roll Back Driver..." (Button)
0, 0
};
CDeviceDriverPage::~CDeviceDriverPage()
{
if (m_pDriver) {
delete m_pDriver;
}
}
BOOL
CDeviceDriverPage::OnCommand(
WPARAM wParam,
LPARAM lParam
)
{
UNREFERENCED_PARAMETER(lParam);
if (BN_CLICKED == HIWORD(wParam)) {
switch (LOWORD(wParam)) {
case IDC_DEVDRV_DETAILS:
{
//
// We first need to call CDriver::BuildDriverList to build up a list
// of drivers for this device. This can take some time so we will put
// up the busy cursor.
//
HCURSOR hCursorOld = SetCursor(LoadCursor(NULL, IDC_WAIT));
CDriver* pDriver;
pDriver = m_pDevice->CreateDriver();
if (pDriver) {
pDriver->BuildDriverList();
SetCursor(hCursorOld);
//
// Show driver file details
//
if (pDriver->GetCount() > 0) {
if (pDriver) {
CDriverFilesDlg DriverFilesDlg(m_pDevice, pDriver);
DriverFilesDlg.DoModal(m_hDlg, (LPARAM)&DriverFilesDlg);
}
} else {
//
// No driver files are loaded for this device
//
String strNoDrivers;
strNoDrivers.LoadString(g_hInstance, IDS_DEVDRV_NODRIVERFILE);
MessageBox(m_hDlg, strNoDrivers, m_pDevice->GetDisplayName(), MB_OK);
return FALSE;
}
delete pDriver;
pDriver = NULL;
}
break;
}
case IDC_DEVDRV_UNINSTALL:
{
BOOL Refresh = (m_pDevice->IsPhantom() ||
m_pDevice->HasProblem() ||
!m_pDevice->IsStarted());
if (UninstallDrivers(m_pDevice, m_hDlg)) {
//
// Enable refresh since we disabled it in the beginning.
//
// We only need to force a refresh here if the device that
// was removed was a Phantom device. This is because Phantom
// devices don't have kernel mode devnodes and so they won't
// generate a WM_DEVICECHANGE like live devnodes will.
//
if (Refresh) {
m_pDevice->m_pMachine->ScheduleRefresh();
}
::DestroyWindow(GetParent(m_hDlg));
}
break;
}
case IDC_DEVDRV_CHANGEDRIVER:
{
BOOL fChanged;
DWORD Reboot = 0;
if (UpdateDriver(m_pDevice, m_hDlg, &fChanged, &Reboot) && fChanged) {
//
// ISSUE: JasonC 2/7/00
//
// A refresh on m_pDevice->m_pMachine is necessary here.
// Since we are running on a different thread and each
// property page may have cached the HDEVINFO and the
// SP_DEVINFO_DATA, refresh on the CMachine object can not
// be done here. The problem is worsen by the fact that
// user can go back to the device tree and work on the tree
// while this property sheet is still up.
// It would be nice if MMC would support modal dialog boxes!
//
m_pDevice->PropertyChanged();
m_pDevice->GetClass()->PropertyChanged();
m_pDevice->m_pMachine->DiTurnOnDiFlags(*m_pDevice, DI_PROPERTIES_CHANGE);
UpdateControls();
PropSheet_SetTitle(GetParent(m_hDlg), PSH_PROPTITLE, m_pDevice->GetDisplayName());
PropSheet_CancelToClose(GetParent(m_hDlg));
if (Reboot & (DI_NEEDRESTART | DI_NEEDREBOOT)) {
m_pDevice->m_pMachine->DiTurnOnDiFlags(*m_pDevice, DI_NEEDREBOOT);
}
}
break;
}
case IDC_DEVDRV_ROLLBACK:
{
BOOL fChanged;
DWORD Reboot = 0;
if (RollbackDriver(m_pDevice, m_hDlg, &fChanged, &Reboot) && fChanged) {
//
// ISSUE: JasonC 2/7/00
//
// A refresh on m_pDevice->m_pMachine is necessary here.
// Since we are running on a different thread and each
// property page may have cached the HDEVINFO and the
// SP_DEVINFO_DATA, refresh on the CMachine object can not
// be done here. The problem is worsen by the fact that
// user can go back to the device tree and work on the tree
// while this property sheet is still up.
// It would be nice if MMC would support modal dialog boxes!
//
m_pDevice->PropertyChanged();
m_pDevice->GetClass()->PropertyChanged();
m_pDevice->m_pMachine->DiTurnOnDiFlags(*m_pDevice, DI_PROPERTIES_CHANGE);
UpdateControls();
PropSheet_SetTitle(GetParent(m_hDlg), PSH_PROPTITLE, m_pDevice->GetDisplayName());
PropSheet_CancelToClose(GetParent(m_hDlg));
if (Reboot & (DI_NEEDRESTART | DI_NEEDREBOOT)) {
m_pDevice->m_pMachine->DiTurnOnDiFlags(*m_pDevice, DI_NEEDREBOOT);
}
}
break;
}
default:
break;
}
}
return FALSE;
}
//
// This function uninstalls the drivers for the given device
// INPUT:
// pDevice -- the object represent the device
// hDlg -- the property page window handle
//
// OUTPUT:
// TRUE -- function succeeded.
// FALSE -- function failed.
//
BOOL
CDeviceDriverPage::UninstallDrivers(
CDevice* pDevice,
HWND hDlg
)
{
BOOL Return = FALSE;
CMachine *pMachine;
if (pDevice->m_pMachine->m_ParentMachine) {
pMachine = pDevice->m_pMachine->m_ParentMachine;
} else {
pMachine = pDevice->m_pMachine;
}
if(!pDevice->m_pMachine->IsLocal() || !g_IsAdmin) {
//
// Must be an admin and on the local machine to remove a device.
//
return FALSE;
}
BOOL Refresh = (pDevice->IsPhantom() ||
pDevice->HasProblem() ||
!pDevice->IsStarted());
pMachine->EnableRefresh(FALSE);
CRemoveDevDlg TheDlg(pDevice);
if (IDOK == TheDlg.DoModal(hDlg, (LPARAM) &TheDlg)) {
DWORD DiFlags;
DiFlags = pDevice->m_pMachine->DiGetFlags(*pDevice);
//
// First try and send a MMCPropertyChangeNotify message to our
// CComponent so that it can prompt for a reboot inside the
// device manager thread instead of our thread. If this is not
// done then the property sheet will hang around after device
// manager has gone away...which will cause a "hung app" dialog
// to appear.
//
// Note: In this case we pass NULL as the Window handle since
// uninstalling will cause the property sheet to go away.
//
CNotifyRebootRequest* pNRR = new CNotifyRebootRequest(NULL, DiFlags, IDS_REMOVEDEV_RESTART);
if (pNRR) {
if (!m_pDevice->m_psd.PropertyChangeNotify(reinterpret_cast<LONG_PTR>(pNRR))) {
//
// There isn't a CComponent around, so this is just a property
// sheet running outside of MMC.
//
pNRR->Release();
PromptForRestart(hDlg, DiFlags, IDS_REMOVEDEV_RESTART);
}
} else {
//
// We couldn't allocate memory to create our CNotifyRebootRequest
// instance, so just prompt for a reboot in this thread.
//
PromptForRestart(hDlg, DiFlags, IDS_REMOVEDEV_RESTART);
}
if (Refresh) {
pMachine->ScheduleRefresh();
}
Return = TRUE;
}
pMachine->EnableRefresh(TRUE);
return Return;
}
BOOL
CDeviceDriverPage::LaunchTroubleShooter(
CDevice* pDevice,
HWND hDlg,
BOOL *pfChanged
)
{
BOOL fChanged = FALSE;
DWORD Status, Problem = 0;
CProblemAgent* ProblemAgent;
if (pDevice->GetStatus(&Status, &Problem) || pDevice->IsPhantom())
{
//
// if the device is a phantom device, use the CM_PROB_DEVICE_NOT_THERE
//
if (pDevice->IsPhantom())
{
Problem = CM_PROB_DEVICE_NOT_THERE;
Status = DN_HAS_PROBLEM;
}
//
// if the device is not started and no problem is assigned to it
// fake the problem number to be failed start.
//
if (!(Status & DN_STARTED) && !Problem && pDevice->IsRAW())
{
Problem = CM_PROB_FAILED_START;
}
}
ProblemAgent = new CProblemAgent(pDevice, Problem, FALSE);
if (ProblemAgent) {
fChanged = ProblemAgent->FixIt(GetParent(hDlg));
delete ProblemAgent;
}
if (pfChanged) {
*pfChanged = fChanged;
}
return TRUE;
}
//
// This function updates drivers for the given device
// INPUT:
// pDevice -- the object represent the device
// hDlg -- the property page window handle
// pfChanged -- optional buffer to receive if driver changes
// have occured.
// OUTPUT:
// TRUE -- function succeeded.
// FALSE -- function failed.
//
BOOL
CDeviceDriverPage::RollbackDriver(
CDevice* pDevice,
HWND hDlg,
BOOL *pfChanged,
DWORD *pdwReboot
)
{
HCURSOR hCursorOld;
BOOL RollbackSuccessful = FALSE;
DWORD RollbackError = ERROR_CANCELLED;
DWORD Status = 0, Problem = 0;
//
// Verify that the process has Admin credentials and that we are running on the local
// machine.
//
if (!pDevice || !pDevice->m_pMachine->IsLocal() || !g_IsAdmin) {
ASSERT(FALSE);
return FALSE;
}
hCursorOld = SetCursor(LoadCursor(NULL, IDC_WAIT));
//
// If the device has the DN_WILL_BE_REMOVED flag set and the user is
// attempting to roll back the driver then we will prompt them for a
// reboot and include text in the prompt that explains this device
// is in the process of being removed.
//
if (pDevice->GetStatus(&Status, &Problem) &&
(Status & DN_WILL_BE_REMOVED)) {
//
// First try and send a MMCPropertyChangeNotify message to our
// CComponent so that it can prompt for a reboot inside the
// device manager thread instead of our thread. If this is not
// done then the property sheet will hang around after device
// manager has gone away...which will cause a "hung app" dialog
// to appear.
//
CNotifyRebootRequest* pNRR = new CNotifyRebootRequest(m_hDlg, DI_NEEDRESTART, IDS_WILL_BE_REMOVED_NO_ROLLBACK_DRIVER);
if (pNRR) {
if (!m_pDevice->m_psd.PropertyChangeNotify(reinterpret_cast<LONG_PTR>(pNRR))) {
//
// There isn't a CComponent around, so this is just a property
// sheet running outside of MMC.
//
pNRR->Release();
PromptForRestart(m_hDlg, DI_NEEDRESTART, IDS_WILL_BE_REMOVED_NO_ROLLBACK_DRIVER);
}
} else {
//
// We couldn't allocate memory to create our CNotifyRebootRequest
// instance, so just prompt for a reboot in this thread.
//
PromptForRestart(m_hDlg, DI_NEEDRESTART, IDS_WILL_BE_REMOVED_NO_ROLLBACK_DRIVER);
}
return FALSE;
}
//
// First check to see if there are any drivers to Rollback
//
CSafeRegistry regRollback;
TCHAR RollbackSubkeyName[MAX_PATH + 1];
TCHAR ReinstallString[MAX_PATH];
BOOL bFoundMatch = FALSE;
int index = 0;
ReinstallString[0] = TEXT('\0');
RollbackSubkeyName[0] = TEXT('\0');
if (regRollback.Open(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Reinstall"))) {
DWORD SubkeySize = ARRAYLEN(RollbackSubkeyName);
while (!bFoundMatch && regRollback.EnumerateSubkey(index, RollbackSubkeyName, &SubkeySize)) {
CSafeRegistry regRollbackSubkey;
if (regRollbackSubkey.Open(regRollback, RollbackSubkeyName)) {
DWORD regType, cbSize;
LPTSTR DeviceInstanceIds;
cbSize = 0;
if (regRollbackSubkey.GetValue(TEXT("DeviceInstanceIds"), &regType, NULL, &cbSize)) {
//
// Allocate memory to hold the DeviceInstanceIds
//
DeviceInstanceIds = (LPTSTR)LocalAlloc(LPTR, cbSize);
if (DeviceInstanceIds) {
ZeroMemory(DeviceInstanceIds, cbSize);
if (regRollbackSubkey.GetValue(TEXT("DeviceInstanceIds"), &regType,
(PBYTE)DeviceInstanceIds, &cbSize)) {
//
// Compare the list of DeviceInstanceIds in this registry key with this
// devices DeviceInstanceId
//
for (LPTSTR p = DeviceInstanceIds; *p; p += (lstrlen(p) + 1)) {
if (pDevice->GetDeviceID() && !lstrcmpi(p, pDevice->GetDeviceID())) {
bFoundMatch = TRUE;
cbSize = sizeof(ReinstallString);
regRollbackSubkey.GetValue(TEXT("ReinstallString"), &regType,
(PBYTE)ReinstallString, &cbSize);
break;
}
}
}
LocalFree(DeviceInstanceIds);
}
}
}
SubkeySize = ARRAYLEN(RollbackSubkeyName);
index++;
}
}
if (bFoundMatch) {
//
// Check the ReinstallString path to verify that a backup directory actually exists.
// We first need to strip the INF name off of the end of the path.
//
PTSTR p;
//
// Assume that the directory does NOT exist
//
bFoundMatch = FALSE;
if (ReinstallString[0] != TEXT('\0')) {
p = StrRChr(ReinstallString, NULL, TEXT('\\'));
if (p) {
*p = 0;
WIN32_FIND_DATA findData;
HANDLE FindHandle;
UINT OldMode;
OldMode = SetErrorMode(SEM_FAILCRITICALERRORS);
FindHandle = FindFirstFile(ReinstallString, &findData);
if(FindHandle != INVALID_HANDLE_VALUE) {
FindClose(FindHandle);
bFoundMatch = TRUE;
} else {
//
// The directory does not exist. Make sure we clean out the registry key
//
regRollback.DeleteSubkey(RollbackSubkeyName);
}
SetErrorMode(OldMode);
}
}
}
if (bFoundMatch) {
//
// We found a match, lets ask the user if they want to rollback the drivers
//
String strYesRollback;
strYesRollback.LoadString(g_hInstance, IDS_DEVDRV_YESROLLBACK);
if (MessageBox(hDlg, strYesRollback, pDevice->GetDisplayName(), MB_YESNO) == IDYES) {
RollbackSuccessful = pDevice->m_pMachine->RollbackDriver(hDlg, RollbackSubkeyName, 0x3, pdwReboot);
if (!RollbackSuccessful) {
RollbackError = GetLastError();
}
}
} else {
//
// We could not find a drivers backup for this device. Lets ask the user if they want
// to start the troubleshooter.
//
String strNoRollback;
strNoRollback.LoadString(g_hInstance, IDS_DEVDRV_NOROLLBACK);
if (MessageBox(hDlg, strNoRollback, pDevice->GetDisplayName(), MB_YESNO) == IDYES) {
LaunchTroubleShooter(pDevice, hDlg, pfChanged);
}
}
if (hCursorOld) {
SetCursor(hCursorOld);
}
//
// We will assume that something changed when we called InstallDevInst()
// unless it returned FALSE and GetLastError() == ERROR_CANCELLED
//
if (pfChanged) {
*pfChanged = TRUE;
if (!bFoundMatch || (!RollbackSuccessful && (ERROR_CANCELLED == RollbackError))) {
*pfChanged = FALSE;
}
}
return TRUE;
}
//
// This function updates drivers for the given device
// INPUT:
// pDevice -- the object represent the device
// hDlg -- the property page window handle
// pfChanged -- optional buffer to receive if driver changes
// have occured.
// OUTPUT:
// TRUE -- function succeeded.
// FALSE -- function failed.
//
BOOL
CDeviceDriverPage::UpdateDriver(
CDevice* pDevice,
HWND hDlg,
BOOL *pfChanged,
DWORD *pdwReboot
)
{
BOOL Installed = FALSE;
DWORD InstallError = ERROR_SUCCESS;
DWORD Status = 0, Problem = 0;
//
// Must be an admin and on the local machine to update a device.
//
if (!pDevice || !pDevice->m_pMachine->IsLocal() || !g_IsAdmin) {
ASSERT(FALSE);
return FALSE;
}
//
// If the device has the DN_WILL_BE_REMOVED flag set and the user is
// attempting to update the driver then we will prompt them for a
// reboot and include text in the prompt that explains this device
// is in the process of being removed.
//
if (pDevice->GetStatus(&Status, &Problem) &&
(Status & DN_WILL_BE_REMOVED)) {
//
// First try and send a MMCPropertyChangeNotify message to our
// CComponent so that it can prompt for a reboot inside the
// device manager thread instead of our thread. If this is not
// done then the property sheet will hang around after device
// manager has gone away...which will cause a "hung app" dialog
// to appear.
//
CNotifyRebootRequest* pNRR = new CNotifyRebootRequest(m_hDlg, DI_NEEDRESTART, IDS_WILL_BE_REMOVED_NO_UPDATE_DRIVER);
if (pNRR) {
if (!m_pDevice->m_psd.PropertyChangeNotify(reinterpret_cast<LONG_PTR>(pNRR))) {
//
// There isn't a CComponent around, so this is just a property
// sheet running outside of MMC.
//
pNRR->Release();
PromptForRestart(m_hDlg, DI_NEEDRESTART, IDS_WILL_BE_REMOVED_NO_UPDATE_DRIVER);
}
} else {
//
// We couldn't allocate memory to create our CNotifyRebootRequest
// instance, so just prompt for a reboot in this thread.
//
PromptForRestart(m_hDlg, DI_NEEDRESTART, IDS_WILL_BE_REMOVED_NO_UPDATE_DRIVER);
}
return FALSE;
}
Installed = pDevice->m_pMachine->InstallDevInst(hDlg, pDevice->GetDeviceID(), TRUE, pdwReboot);
if (!Installed) {
InstallError = GetLastError();
}
//
// We will assume that something changed when we called InstallDevInst()
// unless it returned FALSE and GetLastError() == ERROR_CANCELLED
//
if (pfChanged) {
*pfChanged = TRUE;
if (!Installed && (ERROR_CANCELLED == InstallError)) {
*pfChanged = FALSE;
}
}
return TRUE;
}
void
CDeviceDriverPage::InitializeDriver()
{
if (m_pDriver) {
delete m_pDriver;
m_pDriver = NULL;
}
m_pDriver = m_pDevice->CreateDriver();
}
void
CDeviceDriverPage::UpdateControls(
LPARAM lParam
)
{
if (lParam) {
m_pDevice = (CDevice*) lParam;
}
try {
//
// Calling PropertyChanged() will update the display name for the device. We need
// to do this in case a 3rd party property sheet did something that could change
// the device's display name.
//
m_pDevice->PropertyChanged();
//
// If we are not running locally then don't bother showing the driver
// details since we can't get a list of the drivers and we can't get
// any information about the driver.
//
if (!m_pDevice->m_pMachine->IsLocal()) {
::EnableWindow(GetControl(IDC_DEVDRV_DETAILS), FALSE);
::EnableWindow(GetControl(IDC_DEVDRV_DETAILS_TEXT), FALSE);
}
//
// can not change driver on remote machine or the user
// has no Administrator privilege.
//
if (!m_pDevice->m_pMachine->IsLocal() || !g_IsAdmin) {
::EnableWindow(GetControl(IDC_DEVDRV_CHANGEDRIVER), FALSE);
::EnableWindow(GetControl(IDC_DEVDRV_CHANGEDRIVER_TEXT), FALSE);
::EnableWindow(GetControl(IDC_DEVDRV_ROLLBACK), FALSE);
::EnableWindow(GetControl(IDC_DEVDRV_ROLLBACK_TEXT), FALSE);
::EnableWindow(GetControl(IDC_DEVDRV_UNINSTALL), FALSE);
::EnableWindow(GetControl(IDC_DEVDRV_UNINSTALL_TEXT), FALSE);
}
//
// Hide the uninstall button if the device cannot be uninstalled
//
else if (!m_pDevice->IsUninstallable()) {
::EnableWindow(GetControl(IDC_DEVDRV_UNINSTALL), FALSE);
::EnableWindow(GetControl(IDC_DEVDRV_UNINSTALL_TEXT), FALSE);
}
HICON hIconOld;
m_IDCicon = IDC_DEVDRV_ICON; // Save for cleanup in OnDestroy.
hIconOld = (HICON)SendDlgItemMessage(m_hDlg, IDC_DEVDRV_ICON, STM_SETICON,
(WPARAM)(m_pDevice->LoadClassIcon()),
0
);
if (hIconOld) {
DestroyIcon(hIconOld);
}
InitializeDriver();
SetDlgItemText(m_hDlg, IDC_DEVDRV_DESC, m_pDevice->GetDisplayName());
String strDriverProvider, strDriverDate, strDriverVersion, strDriverSigner;
m_pDevice->GetProviderString(strDriverProvider);
SetDlgItemText(m_hDlg, IDC_DEVDRV_DRIVERPROVIDER, strDriverProvider);
m_pDevice->GetDriverDateString(strDriverDate);
SetDlgItemText(m_hDlg, IDC_DEVDRV_DRIVERDATE, strDriverDate);
m_pDevice->GetDriverVersionString(strDriverVersion);
SetDlgItemText(m_hDlg, IDC_DEVDRV_DRIVERVERSION, strDriverVersion);
if (m_pDriver) {
m_pDriver->GetDriverSignerString(strDriverSigner);
}
//
// If we could not get a digital signature string or then just display
// Unknown for the Digital Signer.
//
if (strDriverSigner.IsEmpty()) {
strDriverSigner.LoadString(g_hInstance, IDS_UNKNOWN);
}
SetDlgItemText(m_hDlg, IDC_DEVDRV_DRIVERSIGNER, strDriverSigner);
AddToolTips(m_hDlg, IDC_DEVDRV_DRIVERSIGNER, (LPTSTR)strDriverSigner, &m_hwndDigitalSignerTip);
}
catch (CMemoryException* e) {
e->Delete();
// report memory error
MsgBoxParam(m_hDlg, 0, 0, 0);
}
}
BOOL
CDeviceDriverPage::OnHelp(
LPHELPINFO pHelpInfo
)
{
WinHelp((HWND)pHelpInfo->hItemHandle, DEVMGR_HELP_FILE_NAME, HELP_WM_HELP,
(ULONG_PTR)g_a106HelpIDs);
return FALSE;
}
BOOL
CDeviceDriverPage::OnContextMenu(
HWND hWnd,
WORD xPos,
WORD yPos
)
{
UNREFERENCED_PARAMETER(xPos);
UNREFERENCED_PARAMETER(yPos);
WinHelp(hWnd, DEVMGR_HELP_FILE_NAME, HELP_CONTEXTMENU,
(ULONG_PTR)g_a106HelpIDs);
return FALSE;
}
//////////////////////////////////////////////////////////////////////////////////////////
//
// Driver Files
//
const DWORD g_a110HelpIDs[]=
{
IDC_DRIVERFILES_ICON, IDH_DISABLEHELP, // Driver: "" (Icon)
IDC_DRIVERFILES_DESC, IDH_DISABLEHELP, // Driver: "" (Static)
IDC_DRIVERFILES_FILES, IDH_DISABLEHELP, // Driver: "Provider:" (Static)
IDC_DRIVERFILES_FILELIST, idh_devmgr_driver_driver_files, // Driver: "" (ListBox)
IDC_DRIVERFILES_TITLE_PROVIDER, idh_devmgr_driver_provider, // Driver: "Provider:" (Static)
IDC_DRIVERFILES_PROVIDER, idh_devmgr_driver_provider, // Driver: "" (Static)
IDC_DRIVERFILES_TITLE_COPYRIGHT,idh_devmgr_driver_copyright, // Driver: "Copyright:" (Static)
IDC_DRIVERFILES_COPYRIGHT, idh_devmgr_driver_copyright, // Driver: "" (Static)
IDC_DRIVERFILES_TITLE_DIGITALSIGNER, IDH_DISABLEHELP,
IDC_DRIVERFILES_DIGITALSIGNER, IDH_DISABLEHELP,
IDC_DRIVERFILES_TITLE_VERSION, idh_devmgr_driver_file_version, // Driver: "Version:" (Static)
IDC_DRIVERFILES_VERSION, idh_devmgr_driver_file_version, // Driver: "File Version:" (Static)
0, 0
};
BOOL CDriverFilesDlg::OnInitDialog()
{
int SignedIndex = 0, BlankIndex = 0, DriverBlockIndex = 0, CertIndex = 0;
try {
HICON hIcon;
hIcon = (HICON)SendDlgItemMessage(m_hDlg, IDC_DRIVERFILES_ICON, STM_SETICON,
(WPARAM)(m_pDevice->LoadClassIcon()), 0);
if (hIcon) {
DestroyIcon(hIcon);
}
SetDlgItemText(m_hDlg, IDC_DRIVERFILES_DESC, m_pDevice->GetDisplayName());
//
// Create the ImageList that contains the signed and blank images.
//
// NOTE: On BiDi builds we need to set the ILC_MIRROR flag so that the
// signed/unsigned icons are not mirrored.
//
m_ImageList = ImageList_Create(GetSystemMetrics(SM_CXSMICON),
GetSystemMetrics(SM_CYSMICON),
ILC_MASK |
((GetWindowLong(GetParent(m_hDlg), GWL_EXSTYLE) & WS_EX_LAYOUTRTL)
? ILC_MIRROR
: 0),
1,
1
);
if (m_ImageList) {
ImageList_SetBkColor(m_ImageList, GetSysColor(COLOR_WINDOW));
if ((hIcon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_BLANK))) != NULL) {
BlankIndex = ImageList_AddIcon(m_ImageList, hIcon);
DestroyIcon(hIcon);
}
if ((hIcon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_SIGNED))) != NULL) {
SignedIndex = ImageList_AddIcon(m_ImageList, hIcon);
DestroyIcon(hIcon);
}
if ((hIcon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_CERT))) != NULL) {
CertIndex = ImageList_AddIcon(m_ImageList, hIcon);
DestroyIcon(hIcon);
}
if ((hIcon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_DRIVERBLOCK))) != NULL) {
DriverBlockIndex = ImageList_AddIcon(m_ImageList, hIcon);
DestroyIcon(hIcon);
}
}
//
//Initialize the list of drivers
//
LV_COLUMN lvcCol;
LV_ITEM lviItem;
CDriverFile* pDrvFile;
PVOID Context;
HWND hwndFileList = GetDlgItem(m_hDlg, IDC_DRIVERFILES_FILELIST);
//
// Insert a single column for this list.
//
lvcCol.mask = LVCF_FMT | LVCF_WIDTH;
lvcCol.fmt = LVCFMT_LEFT;
lvcCol.iSubItem = 0;
ListView_InsertColumn(hwndFileList, 0, (LV_COLUMN FAR *)&lvcCol);
ListView_SetExtendedListViewStyle(hwndFileList, LVS_EX_FULLROWSELECT | LVS_EX_LABELTIP);
if (m_ImageList) {
ListView_SetImageList(hwndFileList, m_ImageList, LVSIL_SMALL);
}
ListView_DeleteAllItems(hwndFileList);
if (m_pDriver && m_pDriver->GetFirstDriverFile(&pDrvFile, Context)) {
do {
ASSERT(pDrvFile);
LPCTSTR pFullPathName;
pFullPathName = pDrvFile->GetFullPathName();
if (pFullPathName) {
lviItem.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
lviItem.iSubItem = 0;
lviItem.lParam = (LPARAM)pDrvFile;
lviItem.iItem = ListView_GetItemCount(hwndFileList);
lviItem.pszText = (LPTSTR)pFullPathName;
if (m_ImageList) {
if (pDrvFile->IsDriverBlocked()) {
//
// The driver is blocked
//
lviItem.iImage = DriverBlockIndex;
} else if (pDrvFile->GetWin32Error() == NO_ERROR) {
//
// The driver is WHQL signed.
//
lviItem.iImage = SignedIndex;
} else if ((pDrvFile->GetWin32Error() == ERROR_AUTHENTICODE_TRUSTED_PUBLISHER) ||
(pDrvFile->GetWin32Error() == ERROR_AUTHENTICODE_TRUST_NOT_ESTABLISHED)) {
//
// The driver is Authenticode signed.
//
lviItem.iImage = CertIndex;
} else {
//
// The driver is NOT blocked and NOT signed.
//
lviItem.iImage = BlankIndex;
}
}
ListView_InsertItem(hwndFileList, &lviItem);
}
} while (m_pDriver->GetNextDriverFile(&pDrvFile, Context));
if (ListView_GetItemCount(hwndFileList) >= 1) {
ListView_SetItemState(hwndFileList,
0,
LVIS_SELECTED | LVIS_FOCUSED,
LVIS_SELECTED | LVIS_FOCUSED
);
ListView_EnsureVisible(hwndFileList, 0, FALSE);
ListView_SetColumnWidth(hwndFileList, 0, LVSCW_AUTOSIZE_USEHEADER);
ShowCurDriverFileDetail();
} else {
//
// nothing on the driver file list, disable it
//
::EnableWindow(GetControl(IDC_DRIVERFILES_FILELIST), FALSE);
}
}
}
catch (CMemoryException* e) {
e->Delete();
return FALSE;
}
return TRUE;
}
void
CDriverFilesDlg::OnCommand(
WPARAM wParam,
LPARAM lParam
)
{
UNREFERENCED_PARAMETER(lParam);
if (BN_CLICKED == HIWORD(wParam)) {
if (IDOK == LOWORD(wParam)) {
EndDialog(m_hDlg, IDOK);
} else if (IDCANCEL == LOWORD(wParam)) {
EndDialog(m_hDlg, IDCANCEL);
}
}
}
BOOL
CDriverFilesDlg::OnNotify(
LPNMHDR pnmhdr
)
{
switch (pnmhdr->code) {
case LVN_ITEMCHANGED:
ShowCurDriverFileDetail();
break;
case NM_RETURN:
case NM_CLICK:
if (pnmhdr->idFrom == IDS_DRIVERFILES_BLOCKDRIVERLINK) {
LaunchHelpForBlockedDriver();
}
break;
}
return FALSE;
}
BOOL
CDriverFilesDlg::OnDestroy()
{
HICON hIcon;
hIcon = (HICON)SendDlgItemMessage(m_hDlg, IDC_DRIVERFILES_ICON, STM_GETICON, 0, 0);
if (hIcon) {
DestroyIcon(hIcon);
}
if (m_ImageList) {
ImageList_Destroy(m_ImageList);
}
return FALSE;
}
BOOL
CDriverFilesDlg::OnHelp(
LPHELPINFO pHelpInfo
)
{
WinHelp((HWND)pHelpInfo->hItemHandle, DEVMGR_HELP_FILE_NAME, HELP_WM_HELP,
(ULONG_PTR)g_a110HelpIDs);
return FALSE;
}
BOOL
CDriverFilesDlg::OnContextMenu(
HWND hWnd,
WORD xPos,
WORD yPos
)
{
UNREFERENCED_PARAMETER(xPos);
UNREFERENCED_PARAMETER(yPos);
WinHelp(hWnd, DEVMGR_HELP_FILE_NAME, HELP_CONTEXTMENU,
(ULONG_PTR)g_a110HelpIDs);
return FALSE;
}
void
CDriverFilesDlg::ShowCurDriverFileDetail()
{
HWND hwndFileList = GetDlgItem(m_hDlg, IDC_DRIVERFILES_FILELIST);
LVITEM lvItem;
LPCTSTR pString;
lvItem.mask = LVIF_PARAM;
lvItem.iSubItem = 0;
lvItem.iItem = ListView_GetNextItem(hwndFileList,
-1,
LVNI_SELECTED
);
if (lvItem.iItem != -1) {
try {
ListView_GetItem(hwndFileList, &lvItem);
CDriverFile* pDrvFile = (CDriverFile*)lvItem.lParam;
ASSERT(pDrvFile);
TCHAR TempString[LINE_LEN];
LPCTSTR pFullPathName;
pFullPathName = pDrvFile->GetFullPathName();
if (!pFullPathName || (pDrvFile->GetAttributes() == 0xFFFFFFFF)) {
//
// This is the case when the file is not present on the system
//
LoadResourceString(IDS_NOT_PRESENT, TempString, ARRAYLEN(TempString));
SetDlgItemText(m_hDlg, IDC_DRIVERFILES_VERSION, TempString);
SetDlgItemText(m_hDlg, IDC_DRIVERFILES_PROVIDER, TempString);
SetDlgItemText(m_hDlg, IDC_DRIVERFILES_COPYRIGHT, TempString);
SetDlgItemText(m_hDlg, IDC_DRIVERFILES_DIGITALSIGNER, TempString);
ShowWindow(GetControl(IDS_DRIVERFILES_BLOCKDRIVERLINK), FALSE);
} else {
if (!pDrvFile->HasVersionInfo()) {
//
// This is the case when the file is present but it does not have
// version information.
//
LoadResourceString(IDS_UNKNOWN, TempString, ARRAYLEN(TempString));
SetDlgItemText(m_hDlg, IDC_DRIVERFILES_VERSION, TempString);
SetDlgItemText(m_hDlg, IDC_DRIVERFILES_PROVIDER, TempString);
SetDlgItemText(m_hDlg, IDC_DRIVERFILES_COPYRIGHT, TempString);
} else {
//
// Show the file version information.
//
TempString[0] = _T('\0');
pString = pDrvFile->GetVersion();
if (!pString && _T('\0') == TempString[0]) {
LoadResourceString(IDS_NOT_AVAILABLE, TempString, ARRAYLEN(TempString));
pString = TempString;
}
SetDlgItemText(m_hDlg, IDC_DRIVERFILES_VERSION, (LPTSTR)pString);
pString = pDrvFile->GetProvider();
if (!pString && _T('\0') == TempString[0]) {
LoadResourceString(IDS_NOT_AVAILABLE, TempString, ARRAYLEN(TempString));
pString = TempString;
}
SetDlgItemText(m_hDlg, IDC_DRIVERFILES_PROVIDER, (LPTSTR)pString);
pString = pDrvFile->GetCopyright();
if (!pString && _T('\0') == TempString[0]) {
LoadResourceString(IDS_NOT_AVAILABLE, TempString, ARRAYLEN(TempString));
pString = TempString;
}
SetDlgItemText(m_hDlg, IDC_DRIVERFILES_COPYRIGHT, (LPTSTR)pString);
}
//
// Show the digital signer if the file is signed.
//
pString = pDrvFile->GetInfDigitalSigner();
if (!pString) {
TempString[0] = _T('\0');
LoadResourceString(((pDrvFile->GetWin32Error() != 0) &&
(pDrvFile->GetWin32Error() != 0xFFFFFFFF) &&
(pDrvFile->GetWin32Error() != ERROR_DRIVER_BLOCKED))
? IDS_NO_DIGITALSIGNATURE
: IDS_NOT_AVAILABLE,
TempString,
ARRAYLEN(TempString));
pString = TempString;
}
SetDlgItemText(m_hDlg, IDC_DRIVERFILES_DIGITALSIGNER, (LPTSTR)pString);
//
// Show the block driver link if this driver is blocked and it
// has a block driver html help ID.
//
ShowWindow(GetControl(IDS_DRIVERFILES_BLOCKDRIVERLINK),
pDrvFile->GetBlockedDriverHtmlHelpID()
? TRUE
: FALSE);
}
}
catch (CMemoryException* e) {
e->Delete();
// report memory error
MsgBoxParam(m_hDlg, 0, 0, 0);
}
} else {
// no selection
SetDlgItemText(m_hDlg, IDC_DRIVERFILES_VERSION, TEXT(""));
SetDlgItemText(m_hDlg, IDC_DRIVERFILES_PROVIDER, TEXT(""));
SetDlgItemText(m_hDlg, IDC_DRIVERFILES_COPYRIGHT, TEXT(""));
SetDlgItemText(m_hDlg, IDC_DRIVERFILES_DIGITALSIGNER, TEXT(""));
}
}
void
CDriverFilesDlg::LaunchHelpForBlockedDriver()
{
HWND hwndFileList = GetDlgItem(m_hDlg, IDC_DRIVERFILES_FILELIST);
LVITEM lvItem;
LPCTSTR pHtmlHelpID;
String strHcpLink;
lvItem.mask = LVIF_PARAM;
lvItem.iSubItem = 0;
lvItem.iItem = ListView_GetNextItem(hwndFileList,
-1,
LVNI_SELECTED
);
if (lvItem.iItem != -1) {
try {
ListView_GetItem(hwndFileList, &lvItem);
CDriverFile* pDrvFile = (CDriverFile*)lvItem.lParam;
ASSERT(pDrvFile);
if ((pHtmlHelpID = pDrvFile->GetBlockedDriverHtmlHelpID()) != NULL) {
strHcpLink.Format(TEXT("HELPCTR.EXE -url %s"), pHtmlHelpID);
ShellExecute(m_hDlg,
TEXT("open"),
TEXT("HELPCTR.EXE"),
(LPTSTR)strHcpLink,
NULL,
SW_SHOWNORMAL);
}
}
catch (CMemoryException* e) {
e->Delete();
// report memory error
MsgBoxParam(m_hDlg, 0, 0, 0);
}
}
}