|
|
/*++
Copyright (C) Microsoft Corporation
Module Name:
devpopg.cpp
Abstract:
This module implements CDevicePowerMgmtPage -- device power management property page
Author:
William Hsieh (williamh) created
Revision History:
--*/ // devdrvpg.cpp : implementation file
//
#include "devmgr.h"
#include "devpopg.h"
extern "C" { #include <initguid.h>
#include <wdmguid.h>
#include <devguid.h>
}
//
// help topic ids
//
const DWORD g_a15HelpIDs[]= { IDC_DEVPOWER_DESC, IDH_DISABLEHELP, IDC_DEVPOWER_ICON, IDH_DISABLEHELP, IDC_DEVPOWER_WAKEENABLE, IDH_DEVMGR_PWRMGR_WAKEENABLE, IDC_DEVPOWER_MGMT_WAKEENABLE, IDH_DEVMGR_PWRMGR_MGMT_WAKEENABLE, IDC_DEVPOWER_DEVICEENABLE, IDH_DEVMGR_PWRMGR_DEVICEENABLE, IDC_DEVPOWER_MESSAGE, IDH_DISABLEHELP, 0,0
};
BOOL CDevicePowerMgmtPage::OnInitDialog( LPPROPSHEETPAGE ppsp ) { //
// Notify CPropSheetData about the page creation
// the controls will be initialize in UpdateControls virtual function.
//
m_pDevice->m_psd.PageCreateNotify(m_hDlg);
BOOLEAN Enabled;
//
// First see if the device is able to wake the system
//
if (m_poWakeEnable.Open(m_pDevice->GetDeviceID())) { m_poWakeEnable.Get(Enabled); ::SendMessage(GetControl(IDC_DEVPOWER_WAKEENABLE), BM_SETCHECK, Enabled ? BST_CHECKED : BST_UNCHECKED, 0);
EnableWindow(GetControl(IDC_DEVPOWER_MGMT_WAKEENABLE), Enabled); } else { EnableWindow(GetControl(IDC_DEVPOWER_WAKEENABLE), FALSE); ShowWindow(GetControl(IDC_DEVPOWER_MGMT_WAKEENABLE), FALSE); }
//
// See if the device can be turned off to save power
//
if (m_poShutdownEnable.Open(m_pDevice->GetDeviceID())) { m_poShutdownEnable.Get(Enabled); ::SendMessage(GetControl(IDC_DEVPOWER_DEVICEENABLE), BM_SETCHECK, Enabled ? BST_CHECKED : BST_UNCHECKED, 0); } else { EnableWindow(GetControl(IDC_DEVPOWER_DEVICEENABLE), FALSE); }
//
// Special network card code.
//
GUID ClassGuid; m_pDevice->ClassGuid(ClassGuid); if (IsEqualGUID(ClassGuid, GUID_DEVCLASS_NET)) {
if (m_poWakeMgmtEnable.Open(m_pDevice->GetDeviceID())) { m_poWakeMgmtEnable.Get(Enabled); ::SendMessage(GetControl(IDC_DEVPOWER_MGMT_WAKEENABLE), BM_SETCHECK, Enabled ? BST_CHECKED : BST_UNCHECKED, 0); }
//
// This is a special case for network class devices. Wake on Lan will
// only work if the device is enabled for power management. So, if the
// user unchecks the 'power manage this device' then we need to disable
// the WOL and management stations controls.
//
if (BST_CHECKED == ::SendMessage(GetControl(IDC_DEVPOWER_DEVICEENABLE), BM_GETCHECK, 0, 0) ) {
if (m_poWakeEnable.IsOpened()) { ::EnableWindow(GetControl(IDC_DEVPOWER_WAKEENABLE), TRUE); }
if (m_poWakeMgmtEnable.IsOpened()) { //
// The 'allow management stations to bring the computer out of standby'
// option is only allowed if the 'Allow this device to bring the computer
// out of standby' option is checked.
//
if (m_poWakeEnable.IsOpened() && (BST_CHECKED == ::SendMessage(GetControl(IDC_DEVPOWER_WAKEENABLE), BM_GETCHECK, 0, 0))) { ::EnableWindow(GetControl(IDC_DEVPOWER_MGMT_WAKEENABLE), TRUE); } else { ::EnableWindow(GetControl(IDC_DEVPOWER_MGMT_WAKEENABLE), FALSE); } } } else {
::EnableWindow(GetControl(IDC_DEVPOWER_WAKEENABLE), FALSE); ::EnableWindow(GetControl(IDC_DEVPOWER_MGMT_WAKEENABLE), FALSE); } } else {
ShowWindow(GetControl(IDC_DEVPOWER_MGMT_WAKEENABLE), FALSE); EnableWindow(GetControl(IDC_DEVPOWER_MGMT_WAKEENABLE), FALSE); }
return CPropSheetPage::OnInitDialog(ppsp); }
BOOL CDevicePowerMgmtPage::OnCommand( WPARAM wParam, LPARAM lParam ) { UNREFERENCED_PARAMETER(lParam);
switch (LOWORD(wParam)) { case IDC_DEVPOWER_WAKEENABLE: if (BST_CHECKED == ::SendMessage(GetControl(IDC_DEVPOWER_WAKEENABLE), BM_GETCHECK, 0, 0) ) {
::EnableWindow(GetControl(IDC_DEVPOWER_MGMT_WAKEENABLE), TRUE); } else {
::EnableWindow(GetControl(IDC_DEVPOWER_MGMT_WAKEENABLE), FALSE); } break;
case IDC_DEVPOWER_DEVICEENABLE: //
// This is a special case for network class devices. Wake on Lan will
// only work if the device is enabled for power management. So, if the
// user unchecks the 'power manage this device' then we need to disable
// the WOL and management stations controls.
//
GUID ClassGuid; m_pDevice->ClassGuid(ClassGuid); if (IsEqualGUID(ClassGuid, GUID_DEVCLASS_NET)) { if (BST_CHECKED == ::SendMessage(GetControl(IDC_DEVPOWER_DEVICEENABLE), BM_GETCHECK, 0, 0) ) { if (m_poWakeEnable.IsOpened()) { ::EnableWindow(GetControl(IDC_DEVPOWER_WAKEENABLE), TRUE); }
if (m_poWakeMgmtEnable.IsOpened()) { //
// The 'allow management stations to bring the computer out of standby'
// option is only allowed if the 'Allow this device to bring the computer
// out of standby' option is checked.
//
if (m_poWakeEnable.IsOpened() && (BST_CHECKED == ::SendMessage(GetControl(IDC_DEVPOWER_WAKEENABLE), BM_GETCHECK, 0, 0))) { ::EnableWindow(GetControl(IDC_DEVPOWER_MGMT_WAKEENABLE), TRUE); } else { ::EnableWindow(GetControl(IDC_DEVPOWER_MGMT_WAKEENABLE), FALSE); } } } else { ::EnableWindow(GetControl(IDC_DEVPOWER_WAKEENABLE), FALSE); ::EnableWindow(GetControl(IDC_DEVPOWER_MGMT_WAKEENABLE), FALSE); } } break; }
return FALSE; }
//
// This function saves the settings(if any)
//
BOOL CDevicePowerMgmtPage::OnApply() { BOOLEAN Enabled;
if (m_poWakeEnable.IsOpened() && IsWindowEnabled(GetControl(IDC_DEVPOWER_WAKEENABLE))) { Enabled = BST_CHECKED == ::SendMessage(GetControl(IDC_DEVPOWER_WAKEENABLE), BM_GETCHECK, 0, 0); m_poWakeEnable.Set(Enabled); }
if (m_poWakeMgmtEnable.IsOpened() && IsWindowEnabled(GetControl(IDC_DEVPOWER_MGMT_WAKEENABLE))) { Enabled = BST_CHECKED == ::SendMessage(GetControl(IDC_DEVPOWER_MGMT_WAKEENABLE), BM_GETCHECK, 0, 0); m_poWakeMgmtEnable.Set(Enabled); }
if (m_poShutdownEnable.IsOpened() && IsWindowEnabled(GetControl(IDC_DEVPOWER_DEVICEENABLE))) { Enabled = BST_CHECKED == ::SendMessage(GetControl(IDC_DEVPOWER_DEVICEENABLE), BM_GETCHECK, 0, 0); m_poShutdownEnable.Set(Enabled); } return FALSE; }
//
// This function refreshes every control in the dialog. It may be called
// when the dialog is being initialized
//
void CDevicePowerMgmtPage::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();
HICON hIconOld; m_IDCicon = IDC_DEVPOWER_ICON; // Save for cleanup in OnDestroy.
hIconOld = (HICON)SendDlgItemMessage(m_hDlg, IDC_DEVPOWER_ICON, STM_SETICON, (WPARAM)(m_pDevice->LoadClassIcon()), 0 ); if (hIconOld) { DestroyIcon(hIconOld); }
SetDlgItemText(m_hDlg, IDC_DEVPOWER_DESC, m_pDevice->GetDisplayName());
//
// Get any power message that the class installer might want to display
//
SP_POWERMESSAGEWAKE_PARAMS pmp; DWORD RequiredSize;
pmp.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER); pmp.ClassInstallHeader.InstallFunction = DIF_POWERMESSAGEWAKE; pmp.PowerMessageWake[0] = TEXT('\0');
m_pDevice->m_pMachine->DiSetClassInstallParams(*m_pDevice, &pmp.ClassInstallHeader, sizeof(pmp) );
//
// If the class installer returns NO_ERROR and there is text to display in the
// PowerMessageWake field of the SP_POWERMESSAGEWAKE_PARAMS structure then display
// the text.
//
if ((m_pDevice->m_pMachine->DiCallClassInstaller(DIF_POWERMESSAGEWAKE, *m_pDevice)) && (m_pDevice->m_pMachine->DiGetClassInstallParams(*m_pDevice, &pmp.ClassInstallHeader, sizeof(pmp), &RequiredSize)) && (pmp.PowerMessageWake[0] != TEXT('\0'))) {
SetDlgItemText(m_hDlg, IDC_DEVPOWER_MESSAGE, pmp.PowerMessageWake); } } catch (CMemoryException* e) { e->Delete(); // report memory error
MsgBoxParam(m_hDlg, 0, 0, 0); } }
BOOL CDevicePowerMgmtPage::OnHelp( LPHELPINFO pHelpInfo ) { WinHelp((HWND)pHelpInfo->hItemHandle, DEVMGR_HELP_FILE_NAME, HELP_WM_HELP, (ULONG_PTR)g_a15HelpIDs);
return FALSE; }
BOOL CDevicePowerMgmtPage::OnContextMenu( HWND hWnd, WORD xPos, WORD yPos ) { UNREFERENCED_PARAMETER(xPos); UNREFERENCED_PARAMETER(yPos); WinHelp(hWnd, DEVMGR_HELP_FILE_NAME, HELP_CONTEXTMENU, (ULONG_PTR)g_a15HelpIDs);
return FALSE; }
//
// This function enables/disables the device power capability
// INPUT:
// fEnable -- TRUE to enable
// -- FALSE to disable
// OUTPUT:
// TRUE if the state is set
// FALSE if the state is not set.
BOOL CPowerEnable::Set( BOOLEAN fEnable ) { if (IsOpened()) { DWORD Error; BOOLEAN fNewValue = fEnable; Error = WmiSetSingleInstance(m_hWmiBlock, m_DevInstId, m_Version, sizeof(fNewValue), &fNewValue);
//
// Get the value back to see if the change is really succeeded.
//
if (ERROR_SUCCESS == Error && Get(fNewValue) && fNewValue == fEnable) { return TRUE; } }
return FALSE; }
BOOL CPowerEnable::Get( BOOLEAN& fEnable ) { fEnable = FALSE;
if (IsOpened()) { ULONG Size = m_WmiInstDataSize; DWORD Error;
Error = WmiQuerySingleInstance(m_hWmiBlock, m_DevInstId, &Size, m_pWmiInstData);
if (ERROR_SUCCESS == Error && Size == m_WmiInstDataSize && m_DataBlockSize == ((PWNODE_SINGLE_INSTANCE)m_pWmiInstData)->SizeDataBlock && m_Version == ((PWNODE_SINGLE_INSTANCE)m_pWmiInstData)->WnodeHeader.Version) { fEnable = *((BOOLEAN*)(m_pWmiInstData + ((PWNODE_SINGLE_INSTANCE)m_pWmiInstData)->DataBlockOffset)); return TRUE; } }
return FALSE; }
//
// Function to open the wmi block.
// INPUT:
// DeviceId -- the device id
// OUTPUT:
// TRUE if the device can be turned off
// FALSE if the device can not be turned off.
BOOL CPowerEnable::Open( LPCTSTR DeviceId ) { if (!DeviceId) { return FALSE; }
//
// Do nothing if already opened
//
if (IsOpened()) { return TRUE; }
if (lstrlen(DeviceId) >= ARRAYLEN(m_DevInstId) - 2) { return FALSE; }
WmiDevInstToInstanceName(m_DevInstId, ARRAYLEN(m_DevInstId), (PTCHAR)DeviceId, 0);
ULONG Error; Error = WmiOpenBlock(&m_wmiGuid, 0, &m_hWmiBlock); if (ERROR_SUCCESS == Error) { //
// Get the required block size.
//
ULONG BufferSize = 0; Error = WmiQuerySingleInstance(m_hWmiBlock, m_DevInstId, &BufferSize, NULL); if (BufferSize && Error == ERROR_INSUFFICIENT_BUFFER) { //
// The device does support the GUID, remember the size
// and allocate a buffer to the data block.
//
m_WmiInstDataSize = BufferSize; m_pWmiInstData = new BYTE[BufferSize];
if (m_pWmiInstData) { Error = WmiQuerySingleInstance(m_hWmiBlock, m_DevInstId, &BufferSize, m_pWmiInstData); } else { Error = ERROR_NOT_ENOUGH_MEMORY; }
if (ERROR_SUCCESS == Error && m_DataBlockSize == ((PWNODE_SINGLE_INSTANCE)m_pWmiInstData)->SizeDataBlock) { //
// Remember the version
//
m_Version = ((PWNODE_SINGLE_INSTANCE)m_pWmiInstData)->WnodeHeader.Version; return TRUE; } }
Close(); }
SetLastError(Error);
return FALSE; }
|