305 lines
9 KiB
C++
305 lines
9 KiB
C++
|
/*******************************************************************************
|
||
|
*
|
||
|
* (C) COPYRIGHT MICROSOFT CORP., 1993-1995
|
||
|
* TITLE: BNDWIDTH.CPP
|
||
|
* VERSION: 1.0
|
||
|
* AUTHOR: jsenior
|
||
|
* DATE: 10/28/1998
|
||
|
*
|
||
|
********************************************************************************
|
||
|
*
|
||
|
* CHANGE LOG:
|
||
|
*
|
||
|
* DATE REV DESCRIPTION
|
||
|
* ---------- ------- ----------------------------------------------------------
|
||
|
* 10/28/1998 jsenior Original implementation.
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
#include "UsbPopup.h"
|
||
|
#include "PropPage.h"
|
||
|
#include "itemfind.h"
|
||
|
#include "debug.h"
|
||
|
#include "usbutil.h"
|
||
|
|
||
|
void
|
||
|
UsbBandwidthPopup::AddIsoDevicesToListView(UsbItem *controller,
|
||
|
int iIndent) {
|
||
|
UINT interruptBW;
|
||
|
LVITEM item;
|
||
|
TCHAR buf[MAX_PATH];
|
||
|
UsbItem *usbItem;
|
||
|
|
||
|
ZeroMemory(&item, sizeof(LVITEM));
|
||
|
item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE | LVIF_INDENT;
|
||
|
item.iIndent = iIndent;
|
||
|
|
||
|
UsbItemActionFindIsoDevices find;
|
||
|
controller->child->Walk(find);
|
||
|
|
||
|
//
|
||
|
// Put the devices in that use very little bandwidth first so that they
|
||
|
// will be shuffled to the bottom when the high consumption devices are
|
||
|
// added.
|
||
|
//
|
||
|
UsbItemList& isoDevices = find.GetIsoDevices();
|
||
|
for (usbItem = isoDevices.begin() ? *isoDevices.Current() : NULL;
|
||
|
usbItem;
|
||
|
usbItem = isoDevices.next() ? *isoDevices.Current() : NULL) {
|
||
|
|
||
|
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);
|
||
|
|
||
|
ListView_InsertItem(hListDevices, &item);
|
||
|
ListView_SetItemText(hListDevices, 0, 1, buf);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Add an item indicating that the system always uses 10%
|
||
|
//
|
||
|
item.iItem = 0;
|
||
|
ImageList.GetClassImageIndex(MyComputerClass, &item.iImage);
|
||
|
item.lParam = (LPARAM) controller;
|
||
|
LoadString(gHInst,
|
||
|
IDS_BANDWIDTH_CONTROLLER_RSRVD,
|
||
|
buf,
|
||
|
MAX_PATH);
|
||
|
item.pszText = buf;
|
||
|
ListView_InsertItem(hListDevices, &item);
|
||
|
|
||
|
interruptBW = 10 + UsbItem::CalculateBWPercent(find.InterruptBW());
|
||
|
wsprintf(buf,_T("%d%%"),interruptBW);
|
||
|
ListView_SetItemText(hListDevices, 0, 1, buf);
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
UsbBandwidthPopup::Refresh()
|
||
|
{
|
||
|
PUSB_ACQUIRE_INFO acquireInfo = 0;
|
||
|
UsbItem *controller;
|
||
|
LVITEM item;
|
||
|
TCHAR buf[MAX_PATH];
|
||
|
TCHAR formatString[MAX_PATH];
|
||
|
|
||
|
// CWaitCursor wait;
|
||
|
|
||
|
//
|
||
|
// Clear all UI components, and then recreate the rootItem
|
||
|
//
|
||
|
ListView_DeleteAllItems(hListDevices);
|
||
|
if (rootItem) {
|
||
|
DeleteChunk(rootItem);
|
||
|
delete rootItem;
|
||
|
}
|
||
|
rootItem = new UsbItem;
|
||
|
AddChunk(rootItem);
|
||
|
|
||
|
acquireInfo = GetControllerName(WmiHandle,
|
||
|
InstanceName.c_str());
|
||
|
if (!acquireInfo) {
|
||
|
goto BandwidthRefreshError;
|
||
|
}
|
||
|
if (!rootItem->EnumerateAll(&ImageList)) {
|
||
|
goto BandwidthRefreshError;
|
||
|
}
|
||
|
acquireInfo = (PUSB_ACQUIRE_INFO) LocalFree(acquireInfo);
|
||
|
|
||
|
//
|
||
|
// Set the notification using the name of the offending device
|
||
|
//
|
||
|
LoadString(gHInst,
|
||
|
IDS_BANDWIDTH_NOTIFICATION,
|
||
|
formatString,
|
||
|
MAX_PATH);
|
||
|
UsbSprintf(buf,
|
||
|
formatString,
|
||
|
deviceItem.configInfo->deviceDesc.c_str(),
|
||
|
UsbItem::CalculateBWPercent(ConnectionNotification->RequestedBandwidth));
|
||
|
if (!SetTextItem(hWnd, IDC_BANDWIDTH_NOTIFICATION, buf)) {
|
||
|
goto BandwidthRefreshError;
|
||
|
}
|
||
|
|
||
|
ZeroMemory(&item, sizeof(LVITEM));
|
||
|
item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
|
||
|
|
||
|
if (rootItem->NumChildren() == 1) {
|
||
|
//
|
||
|
// Computer only has one controller installed
|
||
|
//
|
||
|
if (!SetTextItem(hWnd, IDC_BANDWIDTH_EXPLANATION, IDS_BW_EXPLANATION) ||
|
||
|
!SetTextItem(hWnd, IDC_BANDWIDTH_RECOMMENDATION, IDS_BW_RECOMMENDATION)) {
|
||
|
goto BandwidthRefreshError;
|
||
|
}
|
||
|
|
||
|
AddIsoDevicesToListView(rootItem->child, 0);
|
||
|
} else if (rootItem->NumChildren() > 1) {
|
||
|
//
|
||
|
// Computer has multiple controllers on board. Yeehaw!
|
||
|
//
|
||
|
LoadString(gHInst,
|
||
|
IDS_BANDWIDTH_RECOMMENDATION,
|
||
|
formatString,
|
||
|
MAX_PATH);
|
||
|
UsbSprintf(buf,
|
||
|
formatString,
|
||
|
deviceItem.configInfo->deviceDesc.c_str());
|
||
|
if (!SetTextItem(hWnd, IDC_BANDWIDTH_RECOMMENDATION, buf) ||
|
||
|
!SetTextItem(hWnd, IDC_BANDWIDTH_EXPLANATION, IDS_BW_EXPLANATION)) {
|
||
|
goto BandwidthRefreshError;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Change the column text from "Device" to "Controller"
|
||
|
//
|
||
|
LV_COLUMN column;
|
||
|
ZeroMemory(&column, sizeof(LV_COLUMN));
|
||
|
column.mask = LVCF_TEXT;
|
||
|
LoadString(gHInst, IDS_CONTROLLER, buf, MAX_PATH);
|
||
|
column.pszText = buf;
|
||
|
ListView_SetColumn(hListDevices, 0, &column);
|
||
|
|
||
|
//
|
||
|
// Iterate through the controllers and find out how much bandwidth is
|
||
|
// being used on each. Display this in a list view control.
|
||
|
//
|
||
|
for (controller = rootItem->child;
|
||
|
controller != NULL;
|
||
|
controller = controller->sibling) {
|
||
|
|
||
|
AddIsoDevicesToListView(controller, 1);
|
||
|
|
||
|
item.iItem = 0;
|
||
|
item.iImage = controller->imageIndex;
|
||
|
item.lParam = (LPARAM) controller;
|
||
|
item.pszText = (LPTSTR) controller->configInfo->deviceDesc.c_str();
|
||
|
ListView_InsertItem(hListDevices, &item);
|
||
|
}
|
||
|
}
|
||
|
return TRUE;
|
||
|
BandwidthRefreshError:
|
||
|
if (acquireInfo) {
|
||
|
LocalFree(acquireInfo);
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
UsbBandwidthPopup::OnInitDialog(HWND HWnd)
|
||
|
{
|
||
|
hWnd = HWnd;
|
||
|
LV_COLUMN column;
|
||
|
RECT rect;
|
||
|
HANDLE hExclamation;
|
||
|
HICON hIcon;
|
||
|
TCHAR buf[MAX_PATH];
|
||
|
|
||
|
//
|
||
|
// Set the Icon to an exclamation mark
|
||
|
//
|
||
|
if (NULL == (hIcon = LoadIcon(NULL, (LPTSTR) IDI_EXCLAMATION)) ||
|
||
|
NULL == (hExclamation = GetDlgItem(hWnd, IDC_ICON_BANDWIDTH))) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
SendMessage((HWND) hExclamation, STM_SETICON, (WPARAM) hIcon, NULL);
|
||
|
|
||
|
hListDevices = GetDlgItem(HWnd, IDC_LIST_CONTROLLERS);
|
||
|
|
||
|
ListView_SetImageList(hListDevices, ImageList.ImageList(), LVSIL_SMALL);
|
||
|
|
||
|
//
|
||
|
// Add columns to the list box
|
||
|
//
|
||
|
ZeroMemory(&column, sizeof(LV_COLUMN));
|
||
|
column.mask = LVCF_FMT | LVCF_SUBITEM | LVCF_TEXT | LVCF_WIDTH;
|
||
|
column.fmt = LVCFMT_LEFT;
|
||
|
LoadString(gHInst, IDS_DEVICE, buf, MAX_PATH);
|
||
|
column.pszText = buf;
|
||
|
GetClientRect(hListDevices, &rect);
|
||
|
column.cx = (int) (.65*(rect.right - rect.left));
|
||
|
ListView_InsertColumn(hListDevices, 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(hListDevices, &rect);
|
||
|
column.cx = (int) (.35*(rect.right - rect.left));
|
||
|
ListView_InsertColumn(hListDevices, 1, &column);
|
||
|
|
||
|
return Refresh();
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
UsbBandwidthPopup::OnCommand(INT wNotifyCode,
|
||
|
INT wID,
|
||
|
HWND hCtl)
|
||
|
{
|
||
|
switch (wID) {
|
||
|
case IDOK:
|
||
|
EndDialog(hWnd, wID);
|
||
|
return TRUE;
|
||
|
case IDC_BW_REFRESH:
|
||
|
Refresh();
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
UsbBandwidthPopup::IsPopupStillValid() {
|
||
|
USB_BUS_NOTIFICATION busNotification;
|
||
|
|
||
|
USBINFO((_T("Names %s, %s!\n"),
|
||
|
deviceItem.configInfo->deviceDesc.c_str(),
|
||
|
LastDeviceName.c_str()));
|
||
|
|
||
|
if (!GetBusNotification(WmiHandle, &busNotification)) {
|
||
|
USBERROR((_T("Failed to get bus notification!\n")));
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Is this the same scenario?
|
||
|
//
|
||
|
if (deviceItem.configInfo->deviceDesc == LastDeviceName &&
|
||
|
busNotification.ConsumedBandwidth == LastBandwidthConsumed &&
|
||
|
ConnectionNotification->RequestedBandwidth == LastBandwidthRequested) {
|
||
|
USBWARN((_T("Same scenario!!!")));
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Change the scenario.
|
||
|
//
|
||
|
LastDeviceName = deviceItem.configInfo->deviceDesc;
|
||
|
LastBandwidthConsumed = busNotification.ConsumedBandwidth;
|
||
|
LastBandwidthRequested = ConnectionNotification->RequestedBandwidth;
|
||
|
|
||
|
//
|
||
|
// Is this notification still relevant?
|
||
|
//
|
||
|
USBINFO((_T("Bandwidth consumed %x, requested %x, total %x!\n"),
|
||
|
busNotification.ConsumedBandwidth,
|
||
|
ConnectionNotification->RequestedBandwidth,
|
||
|
busNotification.TotalBandwidth));
|
||
|
if (busNotification.ConsumedBandwidth +
|
||
|
ConnectionNotification->RequestedBandwidth <
|
||
|
busNotification.TotalBandwidth) {
|
||
|
USBWARN((_T("Got BW notification when there was no need!\n")));
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
UsbString UsbBandwidthPopup::LastDeviceName = _T("");
|
||
|
ULONG UsbBandwidthPopup::LastBandwidthRequested = 0;
|
||
|
ULONG UsbBandwidthPopup::LastBandwidthConsumed = 0;
|
||
|
|
||
|
|