windows-nt/Source/XPSP1/NT/shell/osshell/cpls/usb/bandpage.cpp
2020-09-26 16:20:57 +08:00

426 lines
13 KiB
C++

/*******************************************************************************
*
* (C) COPYRIGHT MICROSOFT CORP., 1993-1995
* TITLE: BANDPAGE.CPP
* VERSION: 1.0
* AUTHOR: jsenior
* DATE: 10/28/1998
*
********************************************************************************
*
* CHANGE LOG:
*
* DATE REV DESCRIPTION
* ---------- ------- ----------------------------------------------------------
* 10/28/1998 jsenior Original implementation.
*
*******************************************************************************/
#include <assert.h>
#include "resource.h"
#include "BandPage.h"
#include "ItemFind.h"
#include "debug.h"
#include "UsbItem.h"
#include "usbutil.h"
#include <shellapi.h>
#include <systrayp.h>
const DWORD BandHelpIds[] = {
IDC_STATIC, IDH_NOHELP, //description text
IDC_BANDWIDTH_BAR, idh_devmgr_usb_band_bar, //bandwidth bar
IDC_LIST_DEVICES, idh_devmgr_usb_list_devices, //list box for devices
IDC_REFRESH, idh_devmgr_usb_refresh_button,
IDC_DISABLE_ERROR_DETECTION, idh_devmgr_disable_error_detection, //new radio button
IDC_BAND_TEXT, IDH_NOHELP,
IDC_BAND_TEXT2, IDH_NOHELP,
0, 0
};
static const TCHAR g_szUsbRegValue[] = TEXT("ErrorCheckingEnabled");
static const TCHAR g_szWindowClassName[] = SYSTRAY_CLASSNAME;
static const TCHAR g_szUsbRegPath[] =
TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Usb");
VOID
BandwidthPage::Initialize()
{
hLstDevices = NULL;
dlgResource = IDD_BANDWIDTH;
HelpIds = (const DWORD *) BandHelpIds;
newDisableErrorChecking = oldDisableErrorChecking = 0;
}
void BandwidthPage::Refresh()
{
LVITEM item;
UINT interruptBW;
int i = 0;
UsbItem *usbItem, *controller;
TCHAR buf[MAX_PATH];
//
// Clear all UI components, and then recreate the rootItem
//
fuelBar.ClearItems();
ListView_DeleteAllItems(hLstDevices);
if (rootItem) {
DeleteChunk(rootItem);
delete rootItem;
}
rootItem = new UsbItem;
AddChunk(rootItem);
//
// Find out which mode we're being created in
//
if (preItem) {
//
// Control panel applet is creating the page
//
controller = preItem;
} else {
if (deviceName.empty()) {
if (!GetDeviceName()) {
return;
}
}
controller = rootItem;
if (deviceInfoData) {
if (!controller->EnumerateController(0,
deviceName,
&imageList,
deviceInfoData->DevInst)) {
return;
}
} else {
if (!controller->EnumerateController(0,
deviceName,
&imageList,
NULL)) {
return;
}
}
}
UsbItemActionFindIsoDevices find;
controller->Walk(find);
ZeroMemory(&item, sizeof(LVITEM));
item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
//
// Insert the devices using more than 5% of the bus bandwidth. In other
// words, add the devices using Isochronous BW.
//
UsbItemList& isoDevices = find.GetIsoDevices();
for (usbItem = isoDevices.begin() ? *isoDevices.Current() : NULL;
usbItem;
usbItem = isoDevices.next() ? *isoDevices.Current() : NULL,
i++) {
item.iItem = 0;
item.iImage = usbItem->imageIndex;
item.lParam = (LPARAM) usbItem;
assert(usbItem->configInfo != NULL);
item.pszText = (LPTSTR) usbItem->configInfo->deviceDesc.c_str();
UsbSprintf(buf, TEXT("%d%%"), usbItem->bandwidth);
fuelBar.AddItem(usbItem->bandwidth, usbItem, usbItem->imageIndex);
ListView_InsertItem(hLstDevices, &item);
ListView_SetItemText(hLstDevices, 0, 1, buf);
}
//
// Add an item indicating that the system always uses 10%
//
item.iItem = 0;
imageList.GetClassImageIndex(MyComputerClass, &item.iImage);
item.lParam = (LPARAM) rootItem;
LoadString(gHInst, IDS_BANDWIDTH_CONTROLLER_RSRVD, buf, MAX_PATH);
item.pszText = buf;
interruptBW = 10 + UsbItem::CalculateBWPercent(find.InterruptBW());
fuelBar.AddItem(interruptBW, (LPVOID) rootItem, item.iImage);
ListView_InsertItem(hLstDevices, &item);
wsprintf(buf,_T("%d%%"),interruptBW);
ListView_SetItemText(hLstDevices, 0, 1, buf);
}
BOOL BandwidthPage::OnInitDialog()
{
LV_COLUMN column;
RECT rect;
TCHAR buf[MAX_PATH];
if (preItem) {
SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~WS_CAPTION);
//
// Make the Refresh button go away
//
HWND hRefresh;
if (NULL != (hRefresh = GetDlgItem(hwnd, IDC_REFRESH)) ) {
SetWindowLong(hRefresh,
GWL_STYLE,
(GetWindowLong(hRefresh, GWL_STYLE) | WS_DISABLED) &
~WS_VISIBLE );
}
} else if (!deviceInfoSet && !deviceInfoData) {
//
// Make the Close button visible
//
HWND hButton;
if (NULL != (hButton = GetDlgItem(hwnd, IDC_BANDWIDTH_CLOSE)) ) {
SetWindowLong(hButton,
GWL_STYLE,
(GetWindowLong(hButton, GWL_STYLE) | WS_VISIBLE) &
~WS_DISABLED);
}
// RegisterForDeviceNotification(hwnd);
} else {
//
// Move the refresh button to where the close button is
//
HWND hButtonClose, hButtonRefresh, hButtonDisable;
RECT rectClose, rectParent;
if (NULL != (hButtonClose = GetDlgItem(hwnd, IDC_BANDWIDTH_CLOSE)) &&
GetWindowRect(hwnd, &rectParent)) {
if (GetWindowRect(hButtonClose, &rectClose) &&
NULL != (hButtonRefresh = GetDlgItem(hwnd, IDC_REFRESH)) ) {
MoveWindow(hButtonRefresh,
rectClose.left - rectParent.left,
rectClose.top - rectParent.top,
rectClose.right - rectClose.left,
rectClose.bottom - rectClose.top,
TRUE);
}
}
#ifdef WINNT
//
// Set the disable error detection button appropriately.
//
if (IsErrorCheckingEnabled()) {
newDisableErrorChecking = oldDisableErrorChecking = FALSE;
} else {
newDisableErrorChecking = oldDisableErrorChecking = TRUE;
}
CheckDlgButton(hwnd, IDC_DISABLE_ERROR_DETECTION, oldDisableErrorChecking);
#endif // WINNT
// RegisterForDeviceNotification(hwnd);
}
hLstDevices = GetDlgItem(hwnd, IDC_LIST_DEVICES);
SetTextItem(hwnd, IDC_BAND_TEXT, IDS_BANDWIDTH_PAGEHELP);
// UI change
// SetTextItem(hwnd, IDC_BAND_TEXT2, IDS_BANDWIDTH_PAGEHELP2);
fuelBar.SubclassDlgItem(IDC_BANDWIDTH_BAR, hwnd);
ListView_SetImageList(hLstDevices, imageList.ImageList(), LVSIL_SMALL);
fuelBar.SetImageList(imageList.ImageList());
ZeroMemory(&column, sizeof(LV_COLUMN));
column.mask = LVCF_FMT | LVCF_SUBITEM | LVCF_TEXT | LVCF_WIDTH;
column.fmt = LVCFMT_LEFT;
LoadString(gHInst, IDS_DEVICE_DESCRIPTION, buf, MAX_PATH);
column.pszText = buf;
GetClientRect(hLstDevices, &rect);
column.cx = (int) (.65*(rect.right - rect.left));
ListView_InsertColumn(hLstDevices, 0, &column);
ZeroMemory(&column, sizeof(LV_COLUMN));
column.mask = LVCF_FMT | LVCF_SUBITEM | LVCF_TEXT | LVCF_WIDTH;
column.fmt = LVCFMT_LEFT;
LoadString(gHInst, IDS_BANDWIDTH_CONSUMED, buf, MAX_PATH);
column.pszText = buf;
GetClientRect(hLstDevices, &rect);
column.cx = (int) (.35*(rect.right - rect.left));
ListView_InsertColumn(hLstDevices, 1, &column);
Refresh();
return TRUE;
}
BOOL BandwidthPage::OnCommand(INT wNotifyCode,
INT wID,
HWND hCtl)
{
if (wNotifyCode == BN_CLICKED) {
switch (wID) {
case IDC_REFRESH:
Refresh();
return 0;
#ifdef WINNT
case IDC_DISABLE_ERROR_DETECTION:
newDisableErrorChecking = !newDisableErrorChecking;
if (newDisableErrorChecking != oldDisableErrorChecking) {
PropSheet_Changed(hwnd, hCtl);
}
return 0;
#endif // WINNT
case IDC_BANDWIDTH_CLOSE:
// UnregisterDeviceNotification(hDevNotify);
// UnregisterDeviceNotification(hHubNotify);
EndDialog(hwnd, wID);
}
}
return 1;
}
BOOL BandwidthPage::OnNotify(HWND hDlg, int nID, LPNMHDR pnmh)
{
switch (pnmh->code) {
//
// Sent when the user clicks on Apply OR OK !!
//
case PSN_APPLY:
//
// Do what ever action is necessary
//
UsbSetWindowLongPtr(hwnd, USBDWLP_MSGRESULT, PSNRET_NOERROR);
SetErrorCheckingEnable(!newDisableErrorChecking);
return 0;
default:
switch (nID) {
case IDC_LIST_DEVICES:
OnNotifyListDevices(hDlg, pnmh);
return 0;
}
break;
}
return TRUE;
}
void
BandwidthPage::OnNotifyListDevices(HWND hDlg, LPNMHDR pnmh)
{
if (pnmh->code == LVN_ITEMCHANGED) {
LPNMLISTVIEW pnlv = (LPNMLISTVIEW) pnmh;
// the check for lParam being non NULL is not really necessary b/c we
// set it for each device we insert into the list...
//
// Check if the item has been selected. if not, then there is 2 possible
// states. Either another item is selected (and LV_GetSelectedCount != 0)
// or there is no selection (LV_GetSelectedCount == 0) and we need to clear
// any selection in the fuelbar
//
if ((pnlv->uNewState & LVIS_SELECTED) && pnlv->lParam) {
if (!fuelBar.HighlightItem((PVOID) pnlv->lParam)) {
//
// Must be one of the low consuumption devices
//
fuelBar.HighlightItem(0);
}
}
else if (ListView_GetSelectedCount(hLstDevices) == 0) {
fuelBar.HighlightItem(FuelBar::NoID);
}
} else if (pnmh->code == NM_DBLCLK) {
//
// Display properties on this specific device on double click
//
if (fuelBar.GetHighlightedItem() != rootItem) {
DisplayPPSelectedListItem(hwnd, hLstDevices);
}
}
}
HPROPSHEETPAGE BandwidthPage::Create()
{
//
// Make sure that this is indeed a controller
//
if (deviceName.empty()) {
if (!GetDeviceName()) {
return NULL;
}
}
return UsbPropertyPage::Create();
}
BOOL
BandwidthPage::IsErrorCheckingEnabled()
{
DWORD ErrorCheckingEnabled, type = REG_DWORD, size = sizeof(DWORD);
HKEY hKey;
if (ERROR_SUCCESS !=
RegOpenKeyEx(HKEY_LOCAL_MACHINE,
g_szUsbRegPath,
0,
KEY_READ,
&hKey)) {
return TRUE;
}
if (ERROR_SUCCESS !=
RegQueryValueEx(hKey,
g_szUsbRegValue,
0,
&type,
(LPBYTE) &ErrorCheckingEnabled,
&size)) {
return TRUE;
}
return (BOOL) ErrorCheckingEnabled;
}
UINT
BandwidthPage::SetErrorCheckingEnable(BOOL ErrorCheckingEnabled)
{
DWORD disposition, size = sizeof(DWORD), type = REG_DWORD, error;
HKEY hKey;
if (ERROR_SUCCESS != (error =
RegCreateKeyEx(HKEY_LOCAL_MACHINE,
g_szUsbRegPath,
0,
TEXT("REG_SZ"),
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hKey,
&disposition))) {
return error;
}
error = RegSetValueEx(hKey,
g_szUsbRegValue,
0,
type,
(LPBYTE) &ErrorCheckingEnabled,
size);
EnableSystray(ErrorCheckingEnabled);
return error;
}
//
// Enable or disable USB error checking
//
void
BandwidthPage::EnableSystray(BOOL fEnable)
{
HWND hExistWnd = FindWindow(g_szWindowClassName, NULL);
if (hExistWnd)
{
//
// NOTE: Send an enable message even if the command line parameter
// is 0 to force us to re-check for all enabled services.
//
PostMessage(hExistWnd, STWM_ENABLESERVICE, STSERVICE_USBUI, fEnable);
}
}