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.

1312 lines
36 KiB

  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. Module Name:
  4. diskmon.c
  5. Abstract:
  6. This module contians the code for the disk monitor utility.
  7. Author:
  8. Chuck Park (chuckp) 10-Feb-1994
  9. Mike Glass (mglass)
  10. Revision History:
  11. --*/
  12. #include "diskmon.h"
  13. #include "gauge.h"
  14. #include <stdlib.h>
  15. #include <stdio.h>
  16. #include <string.h>
  17. PCHAR
  18. *GetAttachedDrives(
  19. PINT NumberDrives
  20. );
  21. VOID
  22. CalcStats(
  23. PDISK list,
  24. BOOL initial
  25. );
  26. VOID
  27. ZeroList(
  28. PDISK list
  29. );
  30. VOID
  31. WriteStatText(
  32. VOID
  33. );
  34. VOID
  35. FormatTime(
  36. ULONG Time
  37. );
  38. DISK TotalDrives;
  39. PDISK DriveList = NULL,
  40. SelectedDrive = NULL;
  41. HINSTANCE hInst;
  42. HWND hDataDlg,
  43. hMainWnd;
  44. HMENU MenuHandle,Popup = NULL;
  45. UINT ActiveDrives = 0;
  46. CHAR AppName[] = "diskmon";
  47. CHAR Title[] = "Disk Performance Monitor";
  48. CHAR TimerText[] = "00:00:00:00";
  49. CHAR labels[9][17] = {"BPS Read",
  50. "BPS Write",
  51. "Ave. BPS Read",
  52. "Ave. BPS Write",
  53. "Ave. BPS Xfer",
  54. "Cur Queue",
  55. "Ave Queue",
  56. "Max Queue",
  57. "Requests / Sec"
  58. };
  59. HWND currentDrvHandle,
  60. totalDrvHandle,
  61. staticHandle[18],
  62. selectedDriveId,
  63. TimerTextId;
  64. INT cx,
  65. cy;
  66. INT Seconds,
  67. Minutes,
  68. Hours,
  69. Days;
  70. ULONG ElapsedTime = 0;
  71. int APIENTRY WinMain(
  72. HINSTANCE hInstance,
  73. HINSTANCE hPrevInstance,
  74. LPSTR lpCmdLine,
  75. int CmdShow
  76. )
  77. {
  78. MSG msg;
  79. HANDLE hAccelTable;
  80. if (!hPrevInstance) {
  81. if (!InitApplication(hInstance)) {
  82. return (FALSE);
  83. }
  84. }
  85. if (!InitInstance(hInstance, CmdShow)) {
  86. return (FALSE);
  87. }
  88. hAccelTable = LoadAccelerators (hInstance, AppName);
  89. while (GetMessage(&msg,NULL,0,0) ) {
  90. if (!TranslateAccelerator (msg.hwnd, hAccelTable, &msg)) {
  91. TranslateMessage(&msg);
  92. DispatchMessage(&msg);
  93. }
  94. }
  95. return (int)msg.wParam;
  96. lpCmdLine;
  97. }
  98. BOOL InitApplication(HINSTANCE hInstance)
  99. {
  100. WNDCLASS wc;
  101. wc.style = CS_HREDRAW | CS_VREDRAW;
  102. wc.lpfnWndProc = WndProc;
  103. wc.cbClsExtra = 0;
  104. wc.cbWndExtra = 0;
  105. wc.hInstance = hInstance;
  106. wc.hIcon = LoadIcon (hInstance, AppName);
  107. wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  108. wc.hbrBackground = (HBRUSH)GetStockObject(DKGRAY_BRUSH);
  109. wc.lpszMenuName = "DiskmonMenu";
  110. wc.lpszClassName = AppName;
  111. if (!RegisterClass(&wc))
  112. return FALSE;
  113. if(!RegisterGauge(hInstance))
  114. return FALSE;
  115. return TRUE;
  116. }
  117. BOOL InitInstance(
  118. HINSTANCE hInstance,
  119. int CmdShow
  120. )
  121. {
  122. CHAR buffer[80];
  123. DISK_PERFORMANCE perfbuf;
  124. DWORD BytesReturned;
  125. HANDLE handle;
  126. HWND hWnd;
  127. INT height,
  128. width;
  129. hInst = hInstance;
  130. cx = 70;
  131. cy = 70;
  132. width = 7;
  133. height = 7;
  134. //
  135. //Create the main window.
  136. //
  137. hWnd = CreateWindow(
  138. AppName,
  139. Title,
  140. WS_CAPTION | WS_SYSMENU,
  141. 20,20,
  142. cx * width,
  143. cy * height,
  144. NULL,
  145. NULL,
  146. hInstance,
  147. NULL
  148. );
  149. if (!hWnd) {
  150. return (FALSE);
  151. }
  152. //
  153. // If the IOCTL GET_DISK_PERF returns ERROR_INVALID_FUNCTION, let the user
  154. // know that Diskperf.sys is not started.
  155. //
  156. handle = CreateFile("\\\\.\\PhysicalDrive0",
  157. GENERIC_READ,
  158. FILE_SHARE_READ
  159. | FILE_SHARE_WRITE,
  160. NULL,
  161. OPEN_EXISTING,
  162. FILE_ATTRIBUTE_NORMAL,
  163. NULL);
  164. if (handle == INVALID_HANDLE_VALUE) {
  165. MessageBox(NULL,"Couldn't open a drive.","Error.",
  166. MB_ICONEXCLAMATION | MB_OK);
  167. return FALSE;
  168. }
  169. if (!DeviceIoControl (handle,
  170. IOCTL_DISK_PERFORMANCE,
  171. NULL,
  172. 0,
  173. &perfbuf,
  174. sizeof(DISK_PERFORMANCE),
  175. &BytesReturned,
  176. NULL
  177. )) {
  178. if (GetLastError() == ERROR_INVALID_FUNCTION) {
  179. sprintf(buffer,"Diskperf.sys is not started on your system.\n Start the driver and reboot.");
  180. MessageBox(NULL,buffer,"Error",MB_ICONEXCLAMATION | MB_OK);
  181. return FALSE;
  182. }
  183. }
  184. CloseHandle(handle);
  185. ShowWindow(hWnd, CmdShow);
  186. UpdateWindow(hWnd);
  187. hMainWnd = hWnd;
  188. return TRUE;
  189. }
  190. LRESULT CALLBACK
  191. WndProc(
  192. HWND hWnd,
  193. UINT message,
  194. WPARAM uParam,
  195. LPARAM lParam
  196. )
  197. {
  198. CHAR buffer[20];
  199. INT wmId,
  200. wmEvent,
  201. x,
  202. y,
  203. minValue,
  204. maxValue,
  205. menuIndex,
  206. i,
  207. j;
  208. static HBRUSH brush;
  209. HDC DC;
  210. PAINTSTRUCT ps;
  211. PDISK current;
  212. RECT childRect;
  213. POINT point;
  214. switch (message) {
  215. case WM_CREATE:
  216. MenuHandle = GetMenu(hWnd);
  217. brush = GetStockObject(DKGRAY_BRUSH);
  218. x = cx / 3;
  219. y = cy / 3;
  220. minValue = 0;
  221. maxValue = 5000;
  222. //
  223. //Create gauge windows
  224. //
  225. currentDrvHandle = CreateGauge (hWnd,hInst,
  226. x,y,cx*3,cy*2,
  227. minValue,maxValue);
  228. x = cx * 3 + ((cx * 2) / 3) ;
  229. totalDrvHandle = CreateGauge (hWnd,hInst,
  230. x,y,cx*3,cy*2,
  231. minValue,maxValue*8);
  232. if (!currentDrvHandle || !totalDrvHandle) {
  233. DestroyWindow(hWnd);
  234. }
  235. //
  236. //Allocate and zero mem for the totaldrive structs.
  237. //
  238. TotalDrives.start = (PDISK_PERFORMANCE)malloc(sizeof(DISK_PERFORMANCE));
  239. if (!TotalDrives.start){
  240. return 1;
  241. }
  242. TotalDrives.current = (PDISK_PERFORMANCE)malloc(sizeof(DISK_PERFORMANCE));
  243. if (!TotalDrives.current) {
  244. free(TotalDrives.start);
  245. return 1;
  246. }
  247. TotalDrives.previous = (PDISK_PERFORMANCE)malloc(sizeof(DISK_PERFORMANCE));
  248. if (!TotalDrives.previous) {
  249. free(TotalDrives.current);
  250. free(TotalDrives.start);
  251. return 1;
  252. }
  253. memset (TotalDrives.start, 0x0,sizeof(DISK_PERFORMANCE));
  254. memset (TotalDrives.current, 0x0,sizeof(DISK_PERFORMANCE));
  255. memset (TotalDrives.previous, 0x0,sizeof(DISK_PERFORMANCE));
  256. TotalDrives.MaxQDepth = 0;
  257. TotalDrives.QDepth = 0;
  258. InvalidateRect(currentDrvHandle,NULL,TRUE);
  259. InvalidateRect(totalDrvHandle,NULL,TRUE);
  260. UpdateWindow(currentDrvHandle);
  261. UpdateWindow(totalDrvHandle);
  262. //
  263. //Create static text controls.
  264. //
  265. for (j = 1;j < 3;j++ ) {
  266. for (i = 0; i < 9 ; i++ ) {
  267. CreateWindow("static",
  268. labels[i],
  269. WS_CHILD | WS_VISIBLE | SS_LEFT,
  270. (INT)( ((cx / 3) * j) + ((j - 1) * cx * 3)),
  271. (INT)(cy * 3 + 20 * i),
  272. (INT)(cx * 1.7),
  273. (INT)(cy / 3),
  274. hWnd,
  275. (HMENU)IntToPtr(i | j << 8),
  276. hInst,
  277. NULL);
  278. }
  279. }
  280. for (j = 1;j < 3 ; j++ ) {
  281. for (i = 0; i < 9 ; i++ ) {
  282. staticHandle[i + ((j-1) * 9)] =
  283. CreateWindow("static",
  284. "0",
  285. WS_CHILD | WS_VISIBLE | SS_RIGHT,
  286. (INT)( ((cx * 2)+cx/3*(j-1) ) + ((j - 1) * cx * 3)),
  287. (INT)(cy * 3 + 20 * i),
  288. (INT)(cx * 1.3),
  289. (INT)(cy / 3),
  290. hWnd,
  291. (HMENU)IntToPtr(i | j << 8),
  292. hInst,
  293. NULL);
  294. }
  295. }
  296. //
  297. //Create Selected drive id control and All drives control
  298. //
  299. selectedDriveId = CreateWindow("static",
  300. "",
  301. WS_CHILD | WS_VISIBLE | SS_LEFT,
  302. (INT)( cx * 1.3),
  303. (INT)(cy * 2.7),
  304. (INT)(cx * 1.5),
  305. (INT)(cy / 3),
  306. hWnd,
  307. (HMENU)(25),
  308. hInst,
  309. NULL);
  310. CreateWindow("static","All Active Drives",
  311. WS_CHILD | WS_VISIBLE | SS_LEFT,
  312. (INT)( cx * 4.6),
  313. (INT)(cy * 2.7),
  314. (INT)(cx * 2.0),
  315. (INT)(cy / 3),
  316. hWnd,
  317. (HMENU)(26),
  318. hInst,
  319. NULL);
  320. TimerTextId = CreateWindow("static","00:00:00:00",
  321. WS_CHILD | WS_VISIBLE | SS_LEFT,
  322. (INT)(cx * 3),
  323. (INT)(cy * .5),
  324. (INT)(cx * 1.5),
  325. (INT)(cy / 3),
  326. hWnd,
  327. (HMENU)(26),
  328. hInst,
  329. NULL);
  330. break;
  331. case WM_CTLCOLORSTATIC:
  332. SetStretchBltMode((HDC)uParam,HALFTONE);
  333. //
  334. // Get the original brush origins
  335. //
  336. GetBrushOrgEx((HDC)uParam,&point);
  337. //
  338. // Get the extents of the child window.
  339. //
  340. GetWindowRect((HWND)lParam,&childRect);
  341. //
  342. // Set new brush origin
  343. //
  344. SetBrushOrgEx((HDC)uParam,childRect.left,childRect.top,&point);
  345. //
  346. //Set the color of text and background for the static controls
  347. //
  348. SetBkMode ((HDC)uParam,TRANSPARENT);
  349. SetBkColor ((HDC)uParam,(COLORREF)PtrToUlong(brush));
  350. SetTextColor ((HDC)uParam, RGB(255,255,255));
  351. //
  352. // restore the original brush origin
  353. //
  354. return (LRESULT)brush;
  355. case WM_PAINT:
  356. DC = BeginPaint (hWnd,&ps);
  357. SetStretchBltMode(DC,BLACKONWHITE);
  358. //RealizePalette(DC);
  359. //
  360. // Force repaint of the gauges.
  361. //
  362. InvalidateRect (currentDrvHandle,NULL,TRUE);
  363. InvalidateRect (totalDrvHandle,NULL,TRUE);
  364. InvalidateRect (TimerTextId,NULL,TRUE);
  365. EndPaint (hWnd,&ps);
  366. break;
  367. case WM_TIMER:
  368. ++ElapsedTime;
  369. FormatTime (ElapsedTime);
  370. SetWindowText(TimerTextId,TimerText);
  371. CalcStats (DriveList,FALSE);
  372. //
  373. //Determine currently selected drive and update
  374. //the gauge.
  375. //
  376. UpdateGauge(currentDrvHandle,(INT)(SelectedDrive->AveBPS / 1000));
  377. //
  378. //Calc total stats and update active drives gauge.
  379. //
  380. UpdateGauge(totalDrvHandle,(INT)(TotalDrives.AveBPS / (1000)));
  381. WriteStatText();
  382. break;
  383. case WM_COMMAND:
  384. wmId = LOWORD(uParam);
  385. wmEvent = HIWORD(uParam);
  386. if (wmId >= ID_DRV0 && wmId <= ID_DRV0 + 32) {
  387. //
  388. //Uncheck currently selected drive.
  389. //
  390. CheckMenuItem (Popup,SelectedDrive->MenuId,
  391. MF_BYPOSITION | MF_UNCHECKED);
  392. //
  393. //Determine which drive, make it the selected drive,
  394. //and check it.
  395. //
  396. current = DriveList;
  397. while ( current && (current->MenuId != wmId - ID_DRV0)) {
  398. current = current->next;
  399. }
  400. SelectedDrive = current;
  401. CheckMenuItem (Popup,SelectedDrive->MenuId,
  402. MF_BYPOSITION | MF_CHECKED);
  403. //
  404. //Update the drive Id static control
  405. //
  406. SetWindowText (selectedDriveId,SelectedDrive->DrvString);
  407. break;
  408. }
  409. switch (wmId) {
  410. case IDM_VIEW:
  411. //
  412. // TODO: Not yet implemented.
  413. //
  414. break;
  415. case IDM_RESET:
  416. //
  417. // Zero all disk data
  418. //
  419. ZeroList (DriveList);
  420. //
  421. // Disable reset
  422. //
  423. EnableMenuItem (GetMenu(hWnd),IDM_RESET,MF_GRAYED);
  424. DrawMenuBar (hWnd);
  425. //
  426. // Show zero'ed info.
  427. //
  428. UpdateGauge(currentDrvHandle,0);
  429. UpdateGauge(totalDrvHandle,0);
  430. WriteStatText();
  431. break;
  432. case IDM_CHOOSE:
  433. DialogBox(hInst,
  434. "DISKDLG",
  435. hWnd,
  436. (DLGPROC)ConfigMonitor
  437. );
  438. //
  439. //If any drives were selected, set up the remaining
  440. //fields in the structures.
  441. //
  442. if (DriveList) {
  443. //
  444. //Delete the old "Drive" menu if it exists and
  445. //create a new one.
  446. //
  447. if (Popup) {
  448. DeleteMenu (GetMenu(hWnd),3,MF_BYPOSITION);
  449. DrawMenuBar (hWnd);
  450. }
  451. Popup = CreatePopupMenu ();
  452. menuIndex = 1;
  453. current = DriveList;
  454. while (current) {
  455. //
  456. //Open the drive
  457. //
  458. sprintf (buffer,"\\\\.\\");
  459. strcat (buffer,current->DrvString);
  460. current->handle = CreateFile(buffer,
  461. GENERIC_READ,
  462. FILE_SHARE_READ
  463. | FILE_SHARE_WRITE,
  464. NULL,
  465. OPEN_EXISTING,
  466. FILE_ATTRIBUTE_NORMAL,
  467. NULL);
  468. if (current->handle == INVALID_HANDLE_VALUE) {
  469. MessageBox(NULL,"Couldn't open a drive.","Error.",
  470. MB_ICONEXCLAMATION | MB_OK);
  471. DestroyWindow(hWnd);
  472. }
  473. //
  474. //Allocate memory for each of the DISK_PERFORMANCE
  475. //structures.
  476. //
  477. current->start =
  478. (PDISK_PERFORMANCE) malloc(sizeof(DISK_PERFORMANCE));
  479. current->current =
  480. (PDISK_PERFORMANCE) malloc(sizeof(DISK_PERFORMANCE));
  481. current->previous =
  482. (PDISK_PERFORMANCE) malloc(sizeof(DISK_PERFORMANCE));
  483. if (!(current->start && current->current
  484. && current->previous)) {
  485. MessageBox(NULL,"Couldn't allocate memory.","Error.",
  486. MB_ICONEXCLAMATION | MB_OK);
  487. DestroyWindow(hWnd);
  488. }
  489. //
  490. //Add to the Popup menu
  491. //
  492. if (menuIndex == 1) {
  493. AppendMenu (Popup,MF_STRING | MF_BYPOSITION,
  494. ID_DRV0 + ActiveDrives - menuIndex++,
  495. current->DrvString);
  496. } else {
  497. InsertMenu (Popup,0,
  498. MF_STRING | MF_BYPOSITION,
  499. ID_DRV0 + ActiveDrives - menuIndex++,
  500. current->DrvString);
  501. }
  502. current = current->next;
  503. }
  504. //
  505. //Start with first PhysicalDrive choosen being the currently
  506. //selected drive.
  507. //
  508. SelectedDrive = DriveList;
  509. while (SelectedDrive->next) {
  510. SelectedDrive = SelectedDrive->next;
  511. }
  512. AppendMenu (GetMenu(hWnd),MF_POPUP,(INT_PTR)Popup,"Dri&ve");
  513. //
  514. //Put check mark next to selected drive.
  515. //
  516. CheckMenuItem (Popup,SelectedDrive->MenuId,
  517. MF_BYPOSITION | MF_CHECKED);
  518. //
  519. //Set the drive id control
  520. //
  521. SetWindowText (selectedDriveId,SelectedDrive->DrvString);
  522. //
  523. //Enable the start menu item.
  524. //
  525. EnableMenuItem (GetMenu(hWnd),IDM_START,MF_ENABLED);
  526. DrawMenuBar (hWnd);
  527. }
  528. break;
  529. case IDM_START:
  530. SetTimer(hWnd,ID_TIMER,1000,(TIMERPROC)NULL);
  531. //
  532. //Get initial values for each drive.
  533. //
  534. CalcStats(DriveList,TRUE);
  535. ModifyMenu (GetMenu(hWnd),
  536. IDM_START,
  537. MF_BYCOMMAND,
  538. IDM_STOP,
  539. "Sto&p");
  540. EnableMenuItem (GetMenu(hWnd),IDM_CHOOSE,MF_GRAYED);
  541. DrawMenuBar(hWnd);
  542. break;
  543. case IDM_STOP:
  544. EnableMenuItem (GetMenu(hWnd),IDM_RESET,MF_ENABLED);
  545. KillTimer(hWnd, ID_TIMER);
  546. ModifyMenu (GetMenu(hWnd),
  547. IDM_STOP,
  548. MF_BYCOMMAND,
  549. IDM_START,
  550. "S&tart");
  551. EnableMenuItem (GetMenu(hWnd),IDM_CHOOSE,MF_ENABLED);
  552. DrawMenuBar(hWnd);
  553. break;
  554. case IDM_EXIT:
  555. DestroyWindow (hWnd);
  556. break;
  557. default:
  558. return (DefWindowProc(hWnd, message, uParam, lParam));
  559. }
  560. break;
  561. case WM_DESTROY:
  562. PostQuitMessage(0);
  563. break;
  564. default:
  565. return (DefWindowProc(hWnd, message, uParam, lParam));
  566. }
  567. return (0);
  568. }
  569. BOOL
  570. CALLBACK
  571. ConfigMonitor(
  572. HWND hDlg,
  573. UINT Msg,
  574. WPARAM wParam,
  575. LPARAM lParam
  576. )
  577. {
  578. BOOL Processed = TRUE;
  579. static INT NumberCurrentDrives = 0;
  580. INT selectedDrvBuf[32],
  581. i;
  582. CHAR (*drvs)[16],
  583. buffer[16];
  584. PDISK drive;
  585. switch (Msg) {
  586. case WM_INITDIALOG:
  587. //
  588. // Determine the currently installed PhysicalDrives
  589. //
  590. (char **)drvs = GetAttachedDrives(&NumberCurrentDrives);
  591. if (!drvs) {
  592. break;
  593. }
  594. //
  595. // Load the listbox with the installed drives.
  596. //
  597. for (i = 0;i < NumberCurrentDrives ;i++ ) {
  598. SendDlgItemMessage (hDlg,ID_LB,LB_ADDSTRING,
  599. 0,(LPARAM)(LPCTSTR)drvs[i]);
  600. }
  601. //
  602. // Release the strings allocated in GetAttachedDrives
  603. //
  604. free (drvs);
  605. break;
  606. case WM_COMMAND:
  607. switch (LOWORD(wParam)) {
  608. case ID_LB:
  609. //
  610. // Message for the drive list box.
  611. //
  612. if ( HIWORD(wParam) == LBN_DBLCLK || HIWORD(wParam) == LBN_SELCHANGE ) {
  613. if (!IsWindowEnabled(GetDlgItem(hDlg,IDOK))) {
  614. EnableWindow(GetDlgItem(hDlg,IDOK),TRUE);
  615. } else {
  616. if(!SendDlgItemMessage (hDlg,ID_LB,LB_GETSELCOUNT,0,0)) {
  617. EnableWindow(GetDlgItem(hDlg,IDOK),FALSE);
  618. }
  619. }
  620. }
  621. break;
  622. case IDOK:
  623. //
  624. //Poison the selection array
  625. //
  626. for (i = 0; i < 32; i++ ) {
  627. selectedDrvBuf[i] = -1;
  628. }
  629. //
  630. // If already configed free up all old stuff.
  631. //
  632. if (DriveList) {
  633. ActiveDrives = 0;
  634. drive = DriveList;
  635. while (drive) {
  636. if (drive->start) {
  637. free (drive->start);
  638. }
  639. if (drive->current) {
  640. free (drive->current);
  641. }
  642. if (drive->previous) {
  643. free (drive->previous);
  644. }
  645. CloseHandle (drive->handle);
  646. drive = drive->next;
  647. }
  648. free(DriveList);
  649. DriveList = NULL;
  650. }
  651. //
  652. //Determine which drives are selected.
  653. //
  654. ActiveDrives = (UINT)SendDlgItemMessage (hDlg,ID_LB,LB_GETSELITEMS,(WPARAM)NumberCurrentDrives,
  655. (LPARAM)(LPINT)selectedDrvBuf);
  656. for (i = 0;i < (INT)ActiveDrives ; i++ ) {
  657. if ( selectedDrvBuf[i] != -1 && selectedDrvBuf[i] < NumberCurrentDrives) {
  658. //
  659. // One more check because return from GETSELITEMS is
  660. // sometimes bogus.
  661. //
  662. if (!SendDlgItemMessage (hDlg,ID_LB,LB_GETSEL,(WPARAM)selectedDrvBuf[i],0)) {
  663. MessageBox(NULL,"Bogus val from GETSELITEMS","BUG",MB_OK);
  664. continue;
  665. }
  666. //
  667. //Allocate mem. and link into DISK list.
  668. //
  669. if ((drive = (PDISK) malloc(sizeof(DISK)))==NULL) {
  670. MessageBox(NULL,"Couldn't allocate memory.","Error",
  671. MB_ICONEXCLAMATION | MB_OK);
  672. EndDialog (hDlg,wParam);
  673. break;
  674. }
  675. //
  676. //pull out the string from the list box.
  677. //
  678. SendDlgItemMessage (hDlg,ID_LB,LB_GETTEXT,selectedDrvBuf[i],
  679. (LPARAM)(LPCTSTR)buffer);
  680. strcpy (drive->DrvString,buffer);
  681. //
  682. // Init rest of structure
  683. //
  684. drive->BytesRead = 0;
  685. drive->BytesWritten = 0;
  686. drive->QDepth = 0;
  687. drive->MaxQDepth = 0;
  688. drive->next = NULL;
  689. drive->MenuId = i;
  690. //
  691. // Link into the list of selected drives
  692. //
  693. if ( !DriveList ) {
  694. DriveList = drive;
  695. } else {
  696. drive->next = DriveList;
  697. DriveList = drive;
  698. }
  699. }
  700. }
  701. //
  702. //Fall through to EndDialog
  703. //
  704. case IDCANCEL:
  705. EndDialog(hDlg, wParam);
  706. break;
  707. default:
  708. Processed = FALSE;
  709. break;
  710. }
  711. default:
  712. Processed = FALSE;
  713. break;
  714. }
  715. return(Processed);
  716. }
  717. PCHAR
  718. *GetAttachedDrives(
  719. PINT NumberDrives
  720. )
  721. {
  722. BOOL ValidDrive = FALSE;
  723. CHAR (*drivestrings)[16];
  724. CHAR buffer[21];
  725. HANDLE handle;
  726. INT i = 0;
  727. *NumberDrives = 0;
  728. do {
  729. //
  730. // Try to open each disk starting with 0, if it is present,
  731. // continue. When last is found, exit the loop.
  732. //
  733. ValidDrive = FALSE;
  734. sprintf(buffer,"\\\\.\\PhysicalDrive%d",i);
  735. handle = CreateFile(buffer,
  736. GENERIC_READ,FILE_SHARE_READ | FILE_SHARE_WRITE,
  737. NULL,
  738. OPEN_EXISTING,
  739. FILE_ATTRIBUTE_NORMAL,
  740. NULL);
  741. if (handle != INVALID_HANDLE_VALUE) {
  742. ValidDrive = TRUE;
  743. ++(*NumberDrives);
  744. ++i;
  745. CloseHandle(handle);
  746. }
  747. } while (ValidDrive);
  748. //
  749. // Allocate mem for array of char strings and
  750. // copy "PhysicalDriveX" into each.
  751. //
  752. drivestrings = malloc ((16 * *NumberDrives));
  753. if (!drivestrings) {
  754. return NULL;
  755. }
  756. for (i = 0;i < *NumberDrives ; i++ ) {
  757. sprintf (drivestrings[i],"PhysicalDrive%d",i);
  758. }
  759. return (char **)drivestrings;
  760. }
  761. VOID
  762. CalcStats(
  763. PDISK list,
  764. BOOL initial
  765. )
  766. {
  767. BOOL retval = FALSE;
  768. CHAR errorbuf[25];
  769. DWORD BytesReturned;
  770. LARGE_INTEGER liVal,
  771. BytesRead,
  772. BytesWritten,
  773. curBytesRead,
  774. curBytesWritten;
  775. PDISK newvals = list,
  776. curdisk = list;
  777. UINT tmpQDepth = 0;
  778. BytesRead.QuadPart = 0;
  779. BytesWritten.QuadPart = 0;
  780. TotalDrives.current->QueueDepth = 0;
  781. TotalDrives.current->ReadCount = 0;
  782. TotalDrives.current->WriteCount = 0;
  783. TotalDrives.current->BytesRead.QuadPart = 0;
  784. TotalDrives.current->BytesWritten.QuadPart = 0;
  785. //
  786. //Issue disk perf IOCTL on each drive in list.
  787. //
  788. while (curdisk) {
  789. curBytesRead.QuadPart = 0;
  790. *(curdisk->previous) = *(curdisk->current);
  791. retval = DeviceIoControl (curdisk->handle,
  792. IOCTL_DISK_PERFORMANCE,
  793. NULL,
  794. 0,
  795. curdisk->current,
  796. sizeof(DISK_PERFORMANCE),
  797. &BytesReturned,
  798. NULL
  799. );
  800. if (!retval) {
  801. sprintf(errorbuf,"IOCTL returned error %x",GetLastError());
  802. MessageBox(NULL,errorbuf,"Error",MB_ICONEXCLAMATION | MB_OK);
  803. break;
  804. }
  805. if (initial) {
  806. *(curdisk->start) = *(curdisk->current);
  807. *(curdisk->previous) = *(curdisk->current);
  808. curdisk->AveBPS = 0;
  809. curdisk->MaxBPS = 0;
  810. } else {
  811. //
  812. //Calc the averages and per disk totals
  813. //
  814. curBytesRead.QuadPart = curdisk->current->BytesRead.QuadPart -
  815. curdisk->previous->BytesRead.QuadPart;
  816. curBytesWritten.QuadPart = curdisk->current->BytesWritten.QuadPart -
  817. curdisk->previous->BytesWritten.QuadPart;
  818. BytesRead.QuadPart = BytesRead.QuadPart + curBytesRead.QuadPart;
  819. BytesWritten.QuadPart = BytesWritten.QuadPart + curBytesWritten.QuadPart;
  820. liVal.QuadPart = curBytesRead.QuadPart + curBytesWritten.QuadPart;
  821. curdisk->AveBPS = (ULONG)liVal.QuadPart;
  822. curdisk->BytesRead += (ULONG)curBytesRead.QuadPart;
  823. curdisk->BytesWritten += (ULONG)curBytesWritten.QuadPart;
  824. curdisk->QDepth += curdisk->current->QueueDepth;
  825. curdisk->MaxQDepth = (curdisk->current->QueueDepth >
  826. curdisk->MaxQDepth) ?
  827. curdisk->current->QueueDepth :
  828. curdisk->MaxQDepth;
  829. TotalDrives.QDepth += curdisk->current->QueueDepth;
  830. TotalDrives.current->QueueDepth += curdisk->current->QueueDepth;
  831. tmpQDepth += curdisk->current->QueueDepth;
  832. TotalDrives.current->ReadCount += curdisk->current->ReadCount-curdisk->previous->ReadCount;
  833. TotalDrives.current->WriteCount += curdisk->current->WriteCount - curdisk->previous->WriteCount;
  834. TotalDrives.current->BytesRead.QuadPart = TotalDrives.current->BytesRead.QuadPart +
  835. curBytesRead.QuadPart;
  836. TotalDrives.current->BytesWritten.QuadPart = TotalDrives.current->BytesWritten.QuadPart +
  837. curBytesWritten.QuadPart;
  838. }
  839. curdisk = curdisk->next;
  840. }
  841. //
  842. // Calculate total active drive stats.
  843. //
  844. TotalDrives.AveBPS = (ULONG)(BytesRead.QuadPart + BytesWritten.QuadPart);
  845. TotalDrives.previous->BytesRead.QuadPart = TotalDrives.previous->BytesRead.QuadPart +
  846. BytesRead.QuadPart;
  847. TotalDrives.previous->BytesWritten.QuadPart =
  848. TotalDrives.previous->BytesWritten.QuadPart + BytesWritten.QuadPart;
  849. TotalDrives.MaxQDepth = (TotalDrives.MaxQDepth > tmpQDepth) ?
  850. TotalDrives.MaxQDepth : tmpQDepth;
  851. list = newvals;
  852. }
  853. VOID
  854. FormatTime(ULONG Time)
  855. {
  856. ++Seconds;
  857. if (Seconds % 60 == 0) {
  858. ++Minutes;
  859. Seconds = 0;
  860. if(Minutes % 60 == 0) {
  861. ++Hours;
  862. Minutes = 0;
  863. if(Hours % 24 == 0) {
  864. ++Days;
  865. Hours = 0;
  866. }
  867. }
  868. }
  869. sprintf(TimerText,"%02d:%02d:%02d:%02d",Days,Hours,Minutes,Seconds);
  870. }
  871. VOID
  872. ZeroList(
  873. PDISK list
  874. )
  875. {
  876. PDISK curdrive = list;
  877. memset (TotalDrives.start, 0x0,sizeof(DISK_PERFORMANCE));
  878. memset (TotalDrives.current, 0x0,sizeof(DISK_PERFORMANCE));
  879. memset (TotalDrives.previous, 0x0,sizeof(DISK_PERFORMANCE));
  880. TotalDrives.MaxQDepth = 0;
  881. TotalDrives.QDepth = 0;
  882. TotalDrives.AveBPS = 0;
  883. TotalDrives.MaxBPS = 0;
  884. TotalDrives.BytesRead = 0;
  885. TotalDrives.BytesWritten = 0;
  886. while (curdrive) {
  887. memset (curdrive->start,0x0,sizeof(DISK_PERFORMANCE));
  888. memset (curdrive->current,0x0,sizeof(DISK_PERFORMANCE));
  889. memset (curdrive->previous,0x0,sizeof(DISK_PERFORMANCE));
  890. curdrive->AveBPS = 0;
  891. curdrive->MaxBPS = 0;
  892. curdrive->BytesRead = 0;
  893. curdrive->BytesWritten = 0;
  894. curdrive->QDepth = 0;
  895. curdrive->MaxQDepth = 0;
  896. curdrive = curdrive->next;
  897. }
  898. CalcStats (list,TRUE);
  899. SelectedDrive->current->QueueDepth = 0;
  900. Seconds = 0;
  901. Minutes = 0;
  902. Hours = 0;
  903. Days = 0;
  904. ElapsedTime = 1;
  905. sprintf (TimerText,"00:00:00:00");
  906. }
  907. VOID
  908. WriteStatText(
  909. VOID
  910. )
  911. {
  912. LARGE_INTEGER Val,BytesRead,BytesWritten;
  913. CHAR buffer[20];
  914. //
  915. // BPS Read
  916. //
  917. BytesRead.QuadPart = SelectedDrive->current->BytesRead.QuadPart -
  918. SelectedDrive->previous->BytesRead.QuadPart;
  919. sprintf(buffer,"%.0Lu%Lu",BytesRead.HighPart,BytesRead.LowPart);
  920. SetWindowText(staticHandle[0],buffer);
  921. //
  922. // BPS Write
  923. //
  924. BytesWritten.QuadPart = SelectedDrive->current->BytesWritten.QuadPart -
  925. SelectedDrive->previous->BytesWritten.QuadPart;
  926. sprintf(buffer,"%.0Lu%Lu",BytesWritten.HighPart,BytesWritten.LowPart);
  927. SetWindowText(staticHandle[1],buffer);
  928. //
  929. // Ave. BPS Read
  930. //
  931. BytesRead.QuadPart = SelectedDrive->current->BytesRead.QuadPart +
  932. SelectedDrive->start->BytesRead.QuadPart;
  933. Val.QuadPart = BytesRead.QuadPart / ElapsedTime; // 1 10 BPS Write",
  934. sprintf (buffer,"%.0Lu%Lu",Val.HighPart,Val.LowPart); // 2 11 Ave. BPS Read",
  935. SetWindowText(staticHandle[2],buffer); // 3 12 Ave. BPS Write",
  936. // 4 13 Ave. BPS Xfer",
  937. // // 5 14 Cur Queue",
  938. // Ave. BPS Write // 6 15 Ave Queue",
  939. // // 7 16 Max Queue",
  940. // 8 17 Requests / Sec"
  941. BytesWritten.QuadPart = SelectedDrive->current->BytesWritten.QuadPart +
  942. SelectedDrive->start->BytesWritten.QuadPart;
  943. Val.QuadPart = BytesWritten.QuadPart / ElapsedTime;
  944. sprintf (buffer,"%.0Lu%Lu",Val.HighPart,Val.LowPart);
  945. SetWindowText(staticHandle[3],buffer);
  946. //
  947. // Ave. BPS Total
  948. //
  949. Val.QuadPart = (BytesRead.QuadPart + BytesWritten.QuadPart) / ElapsedTime;
  950. sprintf (buffer,"%.0Lu%Lu",Val.HighPart,Val.LowPart);
  951. SetWindowText (staticHandle[4],buffer);
  952. //
  953. // Current Queue depth
  954. //
  955. sprintf (buffer, "%Lu",SelectedDrive->current->QueueDepth);
  956. SetWindowText (staticHandle[5],buffer);
  957. //
  958. // Ave. Queue depth
  959. //
  960. sprintf (buffer, "%Lu",SelectedDrive->QDepth / ElapsedTime);
  961. SetWindowText (staticHandle[6],buffer);
  962. //
  963. // Max Q
  964. //
  965. sprintf (buffer, "%Lu",SelectedDrive->MaxQDepth);
  966. SetWindowText (staticHandle[7],buffer);
  967. //
  968. // Requests / Sec
  969. //
  970. sprintf (buffer, "%Lu",SelectedDrive->current->ReadCount-SelectedDrive->previous->ReadCount +
  971. SelectedDrive->current->WriteCount-SelectedDrive->previous->WriteCount);
  972. SetWindowText (staticHandle[8],buffer);
  973. //
  974. // Total drives Stats
  975. //
  976. //
  977. // BPS Read
  978. //
  979. sprintf(buffer,"%.0Lu%Lu",TotalDrives.current->BytesRead.HighPart,
  980. TotalDrives.current->BytesRead.LowPart);
  981. SetWindowText(staticHandle[9],buffer);
  982. sprintf(buffer,"%.0Lu%Lu",TotalDrives.current->BytesWritten.HighPart,
  983. TotalDrives.current->BytesWritten.LowPart);
  984. SetWindowText(staticHandle[10],buffer);
  985. Val.QuadPart = TotalDrives.previous->BytesRead.QuadPart / ElapsedTime;
  986. sprintf (buffer,"%.0Lu%Lu",Val.HighPart,Val.LowPart);
  987. SetWindowText(staticHandle[11],buffer);
  988. Val.QuadPart = TotalDrives.previous->BytesWritten.QuadPart / ElapsedTime;
  989. sprintf (buffer,"%.0Lu%Lu",Val.HighPart,Val.LowPart);
  990. SetWindowText(staticHandle[12],buffer);
  991. Val.QuadPart = (TotalDrives.previous->BytesWritten.QuadPart +
  992. TotalDrives.previous->BytesRead.QuadPart) / ElapsedTime;
  993. sprintf (buffer,"%.0Lu%Lu",Val.HighPart,Val.LowPart);
  994. SetWindowText (staticHandle[13],buffer);
  995. sprintf (buffer,"%Lu",TotalDrives.current->QueueDepth);
  996. SetWindowText (staticHandle[14],buffer);
  997. sprintf (buffer, "%Lu",TotalDrives.QDepth / ElapsedTime);
  998. SetWindowText (staticHandle[15],buffer);
  999. sprintf (buffer, "%Lu",TotalDrives.MaxQDepth);
  1000. SetWindowText (staticHandle[16],buffer);
  1001. sprintf (buffer, "%Lu",TotalDrives.current->ReadCount + TotalDrives.current->WriteCount);
  1002. SetWindowText (staticHandle[17],buffer);
  1003. }