Source code of Windows XP (NT5)
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.

425 lines
13 KiB

  1. /*******************************************************************************
  2. *
  3. * (C) COPYRIGHT MICROSOFT CORP., 1993-1995
  4. * TITLE: BANDPAGE.CPP
  5. * VERSION: 1.0
  6. * AUTHOR: jsenior
  7. * DATE: 10/28/1998
  8. *
  9. ********************************************************************************
  10. *
  11. * CHANGE LOG:
  12. *
  13. * DATE REV DESCRIPTION
  14. * ---------- ------- ----------------------------------------------------------
  15. * 10/28/1998 jsenior Original implementation.
  16. *
  17. *******************************************************************************/
  18. #include <assert.h>
  19. #include "resource.h"
  20. #include "BandPage.h"
  21. #include "ItemFind.h"
  22. #include "debug.h"
  23. #include "UsbItem.h"
  24. #include "usbutil.h"
  25. #include <shellapi.h>
  26. #include <systrayp.h>
  27. const DWORD BandHelpIds[] = {
  28. IDC_STATIC, IDH_NOHELP, //description text
  29. IDC_BANDWIDTH_BAR, idh_devmgr_usb_band_bar, //bandwidth bar
  30. IDC_LIST_DEVICES, idh_devmgr_usb_list_devices, //list box for devices
  31. IDC_REFRESH, idh_devmgr_usb_refresh_button,
  32. IDC_DISABLE_ERROR_DETECTION, idh_devmgr_disable_error_detection, //new radio button
  33. IDC_BAND_TEXT, IDH_NOHELP,
  34. IDC_BAND_TEXT2, IDH_NOHELP,
  35. 0, 0
  36. };
  37. static const TCHAR g_szUsbRegValue[] = TEXT("ErrorCheckingEnabled");
  38. static const TCHAR g_szWindowClassName[] = SYSTRAY_CLASSNAME;
  39. static const TCHAR g_szUsbRegPath[] =
  40. TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Usb");
  41. VOID
  42. BandwidthPage::Initialize()
  43. {
  44. hLstDevices = NULL;
  45. dlgResource = IDD_BANDWIDTH;
  46. HelpIds = (const DWORD *) BandHelpIds;
  47. newDisableErrorChecking = oldDisableErrorChecking = 0;
  48. }
  49. void BandwidthPage::Refresh()
  50. {
  51. LVITEM item;
  52. UINT interruptBW;
  53. int i = 0;
  54. UsbItem *usbItem, *controller;
  55. TCHAR buf[MAX_PATH];
  56. //
  57. // Clear all UI components, and then recreate the rootItem
  58. //
  59. fuelBar.ClearItems();
  60. ListView_DeleteAllItems(hLstDevices);
  61. if (rootItem) {
  62. DeleteChunk(rootItem);
  63. delete rootItem;
  64. }
  65. rootItem = new UsbItem;
  66. AddChunk(rootItem);
  67. //
  68. // Find out which mode we're being created in
  69. //
  70. if (preItem) {
  71. //
  72. // Control panel applet is creating the page
  73. //
  74. controller = preItem;
  75. } else {
  76. if (deviceName.empty()) {
  77. if (!GetDeviceName()) {
  78. return;
  79. }
  80. }
  81. controller = rootItem;
  82. if (deviceInfoData) {
  83. if (!controller->EnumerateController(0,
  84. deviceName,
  85. &imageList,
  86. deviceInfoData->DevInst)) {
  87. return;
  88. }
  89. } else {
  90. if (!controller->EnumerateController(0,
  91. deviceName,
  92. &imageList,
  93. NULL)) {
  94. return;
  95. }
  96. }
  97. }
  98. UsbItemActionFindIsoDevices find;
  99. controller->Walk(find);
  100. ZeroMemory(&item, sizeof(LVITEM));
  101. item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_IMAGE;
  102. //
  103. // Insert the devices using more than 5% of the bus bandwidth. In other
  104. // words, add the devices using Isochronous BW.
  105. //
  106. UsbItemList& isoDevices = find.GetIsoDevices();
  107. for (usbItem = isoDevices.begin() ? *isoDevices.Current() : NULL;
  108. usbItem;
  109. usbItem = isoDevices.next() ? *isoDevices.Current() : NULL,
  110. i++) {
  111. item.iItem = 0;
  112. item.iImage = usbItem->imageIndex;
  113. item.lParam = (LPARAM) usbItem;
  114. assert(usbItem->configInfo != NULL);
  115. item.pszText = (LPTSTR) usbItem->configInfo->deviceDesc.c_str();
  116. UsbSprintf(buf, TEXT("%d%%"), usbItem->bandwidth);
  117. fuelBar.AddItem(usbItem->bandwidth, usbItem, usbItem->imageIndex);
  118. ListView_InsertItem(hLstDevices, &item);
  119. ListView_SetItemText(hLstDevices, 0, 1, buf);
  120. }
  121. //
  122. // Add an item indicating that the system always uses 10%
  123. //
  124. item.iItem = 0;
  125. imageList.GetClassImageIndex(MyComputerClass, &item.iImage);
  126. item.lParam = (LPARAM) rootItem;
  127. LoadString(gHInst, IDS_BANDWIDTH_CONTROLLER_RSRVD, buf, MAX_PATH);
  128. item.pszText = buf;
  129. interruptBW = 10 + UsbItem::CalculateBWPercent(find.InterruptBW());
  130. fuelBar.AddItem(interruptBW, (LPVOID) rootItem, item.iImage);
  131. ListView_InsertItem(hLstDevices, &item);
  132. wsprintf(buf,_T("%d%%"),interruptBW);
  133. ListView_SetItemText(hLstDevices, 0, 1, buf);
  134. }
  135. BOOL BandwidthPage::OnInitDialog()
  136. {
  137. LV_COLUMN column;
  138. RECT rect;
  139. TCHAR buf[MAX_PATH];
  140. if (preItem) {
  141. SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~WS_CAPTION);
  142. //
  143. // Make the Refresh button go away
  144. //
  145. HWND hRefresh;
  146. if (NULL != (hRefresh = GetDlgItem(hwnd, IDC_REFRESH)) ) {
  147. SetWindowLong(hRefresh,
  148. GWL_STYLE,
  149. (GetWindowLong(hRefresh, GWL_STYLE) | WS_DISABLED) &
  150. ~WS_VISIBLE );
  151. }
  152. } else if (!deviceInfoSet && !deviceInfoData) {
  153. //
  154. // Make the Close button visible
  155. //
  156. HWND hButton;
  157. if (NULL != (hButton = GetDlgItem(hwnd, IDC_BANDWIDTH_CLOSE)) ) {
  158. SetWindowLong(hButton,
  159. GWL_STYLE,
  160. (GetWindowLong(hButton, GWL_STYLE) | WS_VISIBLE) &
  161. ~WS_DISABLED);
  162. }
  163. // RegisterForDeviceNotification(hwnd);
  164. } else {
  165. //
  166. // Move the refresh button to where the close button is
  167. //
  168. HWND hButtonClose, hButtonRefresh, hButtonDisable;
  169. RECT rectClose, rectParent;
  170. if (NULL != (hButtonClose = GetDlgItem(hwnd, IDC_BANDWIDTH_CLOSE)) &&
  171. GetWindowRect(hwnd, &rectParent)) {
  172. if (GetWindowRect(hButtonClose, &rectClose) &&
  173. NULL != (hButtonRefresh = GetDlgItem(hwnd, IDC_REFRESH)) ) {
  174. MoveWindow(hButtonRefresh,
  175. rectClose.left - rectParent.left,
  176. rectClose.top - rectParent.top,
  177. rectClose.right - rectClose.left,
  178. rectClose.bottom - rectClose.top,
  179. TRUE);
  180. }
  181. }
  182. #ifdef WINNT
  183. //
  184. // Set the disable error detection button appropriately.
  185. //
  186. if (IsErrorCheckingEnabled()) {
  187. newDisableErrorChecking = oldDisableErrorChecking = FALSE;
  188. } else {
  189. newDisableErrorChecking = oldDisableErrorChecking = TRUE;
  190. }
  191. CheckDlgButton(hwnd, IDC_DISABLE_ERROR_DETECTION, oldDisableErrorChecking);
  192. #endif // WINNT
  193. // RegisterForDeviceNotification(hwnd);
  194. }
  195. hLstDevices = GetDlgItem(hwnd, IDC_LIST_DEVICES);
  196. SetTextItem(hwnd, IDC_BAND_TEXT, IDS_BANDWIDTH_PAGEHELP);
  197. // UI change
  198. // SetTextItem(hwnd, IDC_BAND_TEXT2, IDS_BANDWIDTH_PAGEHELP2);
  199. fuelBar.SubclassDlgItem(IDC_BANDWIDTH_BAR, hwnd);
  200. ListView_SetImageList(hLstDevices, imageList.ImageList(), LVSIL_SMALL);
  201. fuelBar.SetImageList(imageList.ImageList());
  202. ZeroMemory(&column, sizeof(LV_COLUMN));
  203. column.mask = LVCF_FMT | LVCF_SUBITEM | LVCF_TEXT | LVCF_WIDTH;
  204. column.fmt = LVCFMT_LEFT;
  205. LoadString(gHInst, IDS_DEVICE_DESCRIPTION, buf, MAX_PATH);
  206. column.pszText = buf;
  207. GetClientRect(hLstDevices, &rect);
  208. column.cx = (int) (.65*(rect.right - rect.left));
  209. ListView_InsertColumn(hLstDevices, 0, &column);
  210. ZeroMemory(&column, sizeof(LV_COLUMN));
  211. column.mask = LVCF_FMT | LVCF_SUBITEM | LVCF_TEXT | LVCF_WIDTH;
  212. column.fmt = LVCFMT_LEFT;
  213. LoadString(gHInst, IDS_BANDWIDTH_CONSUMED, buf, MAX_PATH);
  214. column.pszText = buf;
  215. GetClientRect(hLstDevices, &rect);
  216. column.cx = (int) (.35*(rect.right - rect.left));
  217. ListView_InsertColumn(hLstDevices, 1, &column);
  218. Refresh();
  219. return TRUE;
  220. }
  221. BOOL BandwidthPage::OnCommand(INT wNotifyCode,
  222. INT wID,
  223. HWND hCtl)
  224. {
  225. if (wNotifyCode == BN_CLICKED) {
  226. switch (wID) {
  227. case IDC_REFRESH:
  228. Refresh();
  229. return 0;
  230. #ifdef WINNT
  231. case IDC_DISABLE_ERROR_DETECTION:
  232. newDisableErrorChecking = !newDisableErrorChecking;
  233. if (newDisableErrorChecking != oldDisableErrorChecking) {
  234. PropSheet_Changed(hwnd, hCtl);
  235. }
  236. return 0;
  237. #endif // WINNT
  238. case IDC_BANDWIDTH_CLOSE:
  239. // UnregisterDeviceNotification(hDevNotify);
  240. // UnregisterDeviceNotification(hHubNotify);
  241. EndDialog(hwnd, wID);
  242. }
  243. }
  244. return 1;
  245. }
  246. BOOL BandwidthPage::OnNotify(HWND hDlg, int nID, LPNMHDR pnmh)
  247. {
  248. switch (pnmh->code) {
  249. //
  250. // Sent when the user clicks on Apply OR OK !!
  251. //
  252. case PSN_APPLY:
  253. //
  254. // Do what ever action is necessary
  255. //
  256. UsbSetWindowLongPtr(hwnd, USBDWLP_MSGRESULT, PSNRET_NOERROR);
  257. SetErrorCheckingEnable(!newDisableErrorChecking);
  258. return 0;
  259. default:
  260. switch (nID) {
  261. case IDC_LIST_DEVICES:
  262. OnNotifyListDevices(hDlg, pnmh);
  263. return 0;
  264. }
  265. break;
  266. }
  267. return TRUE;
  268. }
  269. void
  270. BandwidthPage::OnNotifyListDevices(HWND hDlg, LPNMHDR pnmh)
  271. {
  272. if (pnmh->code == LVN_ITEMCHANGED) {
  273. LPNMLISTVIEW pnlv = (LPNMLISTVIEW) pnmh;
  274. // the check for lParam being non NULL is not really necessary b/c we
  275. // set it for each device we insert into the list...
  276. //
  277. // Check if the item has been selected. if not, then there is 2 possible
  278. // states. Either another item is selected (and LV_GetSelectedCount != 0)
  279. // or there is no selection (LV_GetSelectedCount == 0) and we need to clear
  280. // any selection in the fuelbar
  281. //
  282. if ((pnlv->uNewState & LVIS_SELECTED) && pnlv->lParam) {
  283. if (!fuelBar.HighlightItem((PVOID) pnlv->lParam)) {
  284. //
  285. // Must be one of the low consuumption devices
  286. //
  287. fuelBar.HighlightItem(0);
  288. }
  289. }
  290. else if (ListView_GetSelectedCount(hLstDevices) == 0) {
  291. fuelBar.HighlightItem(FuelBar::NoID);
  292. }
  293. } else if (pnmh->code == NM_DBLCLK) {
  294. //
  295. // Display properties on this specific device on double click
  296. //
  297. if (fuelBar.GetHighlightedItem() != rootItem) {
  298. DisplayPPSelectedListItem(hwnd, hLstDevices);
  299. }
  300. }
  301. }
  302. HPROPSHEETPAGE BandwidthPage::Create()
  303. {
  304. //
  305. // Make sure that this is indeed a controller
  306. //
  307. if (deviceName.empty()) {
  308. if (!GetDeviceName()) {
  309. return NULL;
  310. }
  311. }
  312. return UsbPropertyPage::Create();
  313. }
  314. BOOL
  315. BandwidthPage::IsErrorCheckingEnabled()
  316. {
  317. DWORD ErrorCheckingEnabled, type = REG_DWORD, size = sizeof(DWORD);
  318. HKEY hKey;
  319. if (ERROR_SUCCESS !=
  320. RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  321. g_szUsbRegPath,
  322. 0,
  323. KEY_READ,
  324. &hKey)) {
  325. return TRUE;
  326. }
  327. if (ERROR_SUCCESS !=
  328. RegQueryValueEx(hKey,
  329. g_szUsbRegValue,
  330. 0,
  331. &type,
  332. (LPBYTE) &ErrorCheckingEnabled,
  333. &size)) {
  334. return TRUE;
  335. }
  336. return (BOOL) ErrorCheckingEnabled;
  337. }
  338. UINT
  339. BandwidthPage::SetErrorCheckingEnable(BOOL ErrorCheckingEnabled)
  340. {
  341. DWORD disposition, size = sizeof(DWORD), type = REG_DWORD, error;
  342. HKEY hKey;
  343. if (ERROR_SUCCESS != (error =
  344. RegCreateKeyEx(HKEY_LOCAL_MACHINE,
  345. g_szUsbRegPath,
  346. 0,
  347. TEXT("REG_SZ"),
  348. REG_OPTION_NON_VOLATILE,
  349. KEY_ALL_ACCESS,
  350. NULL,
  351. &hKey,
  352. &disposition))) {
  353. return error;
  354. }
  355. error = RegSetValueEx(hKey,
  356. g_szUsbRegValue,
  357. 0,
  358. type,
  359. (LPBYTE) &ErrorCheckingEnabled,
  360. size);
  361. EnableSystray(ErrorCheckingEnabled);
  362. return error;
  363. }
  364. //
  365. // Enable or disable USB error checking
  366. //
  367. void
  368. BandwidthPage::EnableSystray(BOOL fEnable)
  369. {
  370. HWND hExistWnd = FindWindow(g_szWindowClassName, NULL);
  371. if (hExistWnd)
  372. {
  373. //
  374. // NOTE: Send an enable message even if the command line parameter
  375. // is 0 to force us to re-check for all enabled services.
  376. //
  377. PostMessage(hExistWnd, STWM_ENABLESERVICE, STSERVICE_USBUI, fEnable);
  378. }
  379. }