2142 lines
47 KiB
C
2142 lines
47 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1995 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
perfhist.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This Module contains the code for the histogram monitoring utility
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Stephane Plante (t-stephp) (28-Feb-1995)
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "perfhist.h"
|
|||
|
#include <commdlg.h>
|
|||
|
|
|||
|
TEXTFORMAT labels[] = {
|
|||
|
{ { 15,379, 55,396 }, TEXT("Drive:"), ( 6), { 0 }, DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER | DT_LEFT },
|
|||
|
{ { 15,396, 55,413 }, TEXT("Type:"), ( 5), { 0 }, DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER | DT_LEFT },
|
|||
|
{ { 195,379,275,396 }, TEXT("Average:"), ( 8), { 0 }, DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER | DT_LEFT },
|
|||
|
{ { 195,396,275,413 }, TEXT("Avg. Read:"), (10), { 0 }, DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER | DT_LEFT },
|
|||
|
{ { 195,413,275,430 }, TEXT("Avg. Write:"), (11), { 0 }, DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER | DT_LEFT },
|
|||
|
{ { 405,379,525,396 }, TEXT("Total Average:"), (14), { 0 }, DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER | DT_LEFT },
|
|||
|
{ { 405,396,525,413 }, TEXT("Total Avg. Read:"), (16), { 0 }, DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER | DT_LEFT },
|
|||
|
{ { 405,413,525,430 }, TEXT("Total Avg. Write:"), (17), { 0 }, DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER | DT_LEFT },
|
|||
|
{ { 15,413, 75,430 }, TEXT("Buckets:"), ( 8), { 0 }, DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER | DT_LEFT },
|
|||
|
{ { 1, 1,640, 17 }, TEXT("DISK HOTSPOTS"), (13), { 0 }, DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER | DT_CENTER },
|
|||
|
{ { 1, 45,640, 62 }, TEXT("Interval Disk Access"), (20), { 0 }, DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER | DT_CENTER },
|
|||
|
{ { 5, 45, 34, 62 }, TEXT("Hits"), ( 4), { 0 }, DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER | DT_LEFT },
|
|||
|
{ { 5,355,115,372 }, TEXT("Disk Location"), (13), { 0 }, DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER | DT_LEFT },
|
|||
|
{ { 280,355,320,372 }, TEXT("Key:"), ( 4), { 0 }, DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER | DT_LEFT },
|
|||
|
{ { 350,355,380,372 }, TEXT("20%"), ( 3), { 0 }, DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER | DT_RIGHT },
|
|||
|
{ { 410,355,440,372 }, TEXT("40%"), ( 3), { 0 }, DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER | DT_RIGHT },
|
|||
|
{ { 470,355,500,372 }, TEXT("60%"), ( 3), { 0 }, DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER | DT_RIGHT },
|
|||
|
{ { 530,355,560,372 }, TEXT("80%"), ( 3), { 0 }, DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER | DT_RIGHT },
|
|||
|
{ { 590,355,630,372 }, TEXT("100%"), ( 3), { 0 }, DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER | DT_RIGHT }, };
|
|||
|
|
|||
|
TEXTFORMAT variables[] = {
|
|||
|
{ { 65,379,175,396 }, TEXT(""), ( 0), { 0 }, DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER | DT_RIGHT },
|
|||
|
{ { 65,396,175,413 }, TEXT(""), ( 0), { 0 }, DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER | DT_RIGHT },
|
|||
|
{ { 285,379,385,396 }, TEXT("0"), ( 1), { 0 }, DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER | DT_RIGHT },
|
|||
|
{ { 285,396,385,413 }, TEXT("0"), ( 1), { 0 }, DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER | DT_RIGHT },
|
|||
|
{ { 285,413,385,430 }, TEXT("0"), ( 1), { 0 }, DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER | DT_RIGHT },
|
|||
|
{ { 530,379,625,396 }, TEXT("0"), ( 1), { 0 }, DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER | DT_RIGHT },
|
|||
|
{ { 530,396,625,413 }, TEXT("0"), ( 1), { 0 }, DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER | DT_RIGHT },
|
|||
|
{ { 530,413,625,430 }, TEXT("0"), ( 1), { 0 }, DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER | DT_RIGHT },
|
|||
|
{ { 85,413,175,430 }, TEXT("0"), ( 1), { 0 }, DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER | DT_RIGHT }, };
|
|||
|
|
|||
|
|
|||
|
TEXTFORMAT xaxis[] = {
|
|||
|
{ { 0,338, 30,355 }, TEXT("0"), ( 1), { 0 }, DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER | DT_RIGHT },
|
|||
|
{ { 40,338, 97,355 }, TEXT("10"), ( 2), { 0 }, DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER | DT_RIGHT },
|
|||
|
{ { 107,338,164,355 }, TEXT("20"), ( 2), { 0 }, DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER | DT_RIGHT },
|
|||
|
{ { 172,338,228,355 }, TEXT("30"), ( 2), { 0 }, DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER | DT_RIGHT },
|
|||
|
{ { 240,338,297,355 }, TEXT("40"), ( 2), { 0 }, DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER | DT_RIGHT },
|
|||
|
{ { 307,338,364,355 }, TEXT("50"), ( 2), { 0 }, DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER | DT_RIGHT },
|
|||
|
{ { 374,338,430,355 }, TEXT("60"), ( 2), { 0 }, DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER | DT_RIGHT },
|
|||
|
{ { 440,338,497,355 }, TEXT("70"), ( 2), { 0 }, DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER | DT_RIGHT },
|
|||
|
{ { 507,338,564,355 }, TEXT("80"), ( 2), { 0 }, DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER | DT_RIGHT },
|
|||
|
{ { 574,338,630,355 }, TEXT("90"), ( 2), { 0 }, DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER | DT_RIGHT } };
|
|||
|
|
|||
|
TEXTFORMAT yaxis[] = {
|
|||
|
{ { 5,318, 28,335 }, TEXT("0"), ( 1), { 0 }, DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER | DT_RIGHT },
|
|||
|
{ { 5,286, 28,303 }, TEXT("1"), ( 1), { 0 }, DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER | DT_RIGHT },
|
|||
|
{ { 5,254, 28,271 }, TEXT("2"), ( 1), { 0 }, DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER | DT_RIGHT },
|
|||
|
{ { 5,222, 28,239 }, TEXT("3"), ( 1), { 0 }, DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER | DT_RIGHT },
|
|||
|
{ { 5,190, 28,207 }, TEXT("4"), ( 1), { 0 }, DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER | DT_RIGHT },
|
|||
|
{ { 5,158, 28,175 }, TEXT("5"), ( 1), { 0 }, DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER | DT_RIGHT },
|
|||
|
{ { 5,126, 28,143 }, TEXT("6"), ( 1), { 0 }, DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER | DT_RIGHT },
|
|||
|
{ { 5, 94, 28,111 }, TEXT("7"), ( 1), { 0 }, DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER | DT_RIGHT },
|
|||
|
{ { 5, 62, 28, 79 }, TEXT("8"), ( 1), { 0 }, DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER | DT_RIGHT } };
|
|||
|
|
|||
|
COLOREDBOX boxes[] = {
|
|||
|
{330,355, 17, 17, RGB(0,0,255) },
|
|||
|
{390,355, 17, 17, RGB(255,255,0) },
|
|||
|
{450,355, 17, 17, RGB(255,0,255) },
|
|||
|
{510,355, 17, 17, RGB(0,255,0) },
|
|||
|
{570,355, 17, 17, RGB(255,0,0) } };
|
|||
|
|
|||
|
IOCTL_MAPPING type[] = {
|
|||
|
{ TEXT("Location"), IOCTL_DISK_HISTOGRAM, PROCESS_READ | PROCESS_WRITE },
|
|||
|
{ TEXT("Read Location"), IOCTL_DISK_HISTOGRAM, PROCESS_READ },
|
|||
|
{ TEXT("Read Req. Size"), IOCTL_DISK_REQUEST, PROCESS_READ },
|
|||
|
{ TEXT("Req. Size"), IOCTL_DISK_REQUEST, PROCESS_READ | PROCESS_WRITE },
|
|||
|
{ TEXT("Write Location"), IOCTL_DISK_HISTOGRAM, PROCESS_WRITE },
|
|||
|
{ TEXT("Write Req. Size"), IOCTL_DISK_REQUEST, PROCESS_WRITE }, };
|
|||
|
|
|||
|
HINSTANCE hInst;
|
|||
|
HWND hMainWnd;
|
|||
|
HFONT hMainFont;
|
|||
|
HMENU hMenuHandle;
|
|||
|
HBRUSH hBrush;
|
|||
|
HBRUSH hBrush1;
|
|||
|
HBRUSH hBrush2;
|
|||
|
HBRUSH hBrush3;
|
|||
|
HBRUSH hBrush4;
|
|||
|
HBRUSH hBrush5;
|
|||
|
CHAR szAppName[] = "perfhist";
|
|||
|
CHAR szTitle[] = "Disk Histogram Monitor";
|
|||
|
BOOLEAN timerOn = FALSE;
|
|||
|
ULONG cMax = 9;
|
|||
|
UINT activeDrives = 0;
|
|||
|
INFORMATION current;
|
|||
|
INFORMATION total;
|
|||
|
PULONG pHist = NULL;
|
|||
|
PULONG pCurr = NULL;
|
|||
|
LARGE_INTEGER CurrentWrite;
|
|||
|
LARGE_INTEGER CurrentRead;
|
|||
|
LARGE_INTEGER CurrentAvg;
|
|||
|
LARGE_INTEGER TotalWrite;
|
|||
|
LARGE_INTEGER TotalRead;
|
|||
|
LARGE_INTEGER TotalAvg;
|
|||
|
RECT rCoordRect;
|
|||
|
PERFHISTSTRUCT PerfHist = { IDW_FULL, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL, NULL, NULL };
|
|||
|
|
|||
|
int APIENTRY
|
|||
|
WinMain(
|
|||
|
HINSTANCE hInstance,
|
|||
|
HINSTANCE hPrevInstance,
|
|||
|
LPSTR lpCmdList,
|
|||
|
int CmdShow)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine initializes the appropriate windows classes and then serves
|
|||
|
as a message pump for the system.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hInstance: Handle to this instance
|
|||
|
hPrevInstance: Handle to the Previous Instance
|
|||
|
lpCmdList: What the user typed on the command line
|
|||
|
CmdShow: Wether the user wants us visible or invisible at the start
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
What the result of the program is. TRUE for successful run and normal
|
|||
|
termination. FALSE otherwise.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
MSG msg;
|
|||
|
HANDLE hAccelTable;
|
|||
|
|
|||
|
if (!hPrevInstance) {
|
|||
|
if (!InitApplication(hInstance)) {
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (!InitInstance(hInstance,CmdShow)) {
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
hAccelTable = LoadAccelerators(hInstance,szAppName);
|
|||
|
|
|||
|
while (GetMessage(&msg,NULL,0,0) ) {
|
|||
|
if (!TranslateAccelerator(msg.hwnd,hAccelTable,&msg) ) {
|
|||
|
TranslateMessage(&msg);
|
|||
|
DispatchMessage(&msg);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return msg.wParam;
|
|||
|
|
|||
|
} // End of WinMain
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
InitApplication(
|
|||
|
HINSTANCE hInstance)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This Routine actually initializes the main application class and registers it.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hInstance Handle to this instance
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Wether the registration was successful.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
WNDCLASS wc;
|
|||
|
|
|||
|
wc.style = CS_HREDRAW | CS_VREDRAW;
|
|||
|
wc.lpfnWndProc = (WNDPROC)WndProc;
|
|||
|
wc.cbClsExtra = 0;
|
|||
|
wc.cbWndExtra = 0;
|
|||
|
wc.hInstance = hInstance;
|
|||
|
wc.hIcon = (HICON)NULL;
|
|||
|
wc.hCursor = LoadCursor(NULL,IDC_ARROW);
|
|||
|
wc.hbrBackground = CreateSolidBrush(RGB(64,64,64));
|
|||
|
wc.lpszMenuName = MAKEINTRESOURCE(PERF_MENU);
|
|||
|
wc.lpszClassName = szAppName;
|
|||
|
|
|||
|
if (!RegisterClass(&wc)) {
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
return TRUE;
|
|||
|
|
|||
|
} // End InitApplications;
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
InitInstance(
|
|||
|
HINSTANCE hInstance,
|
|||
|
int CmdShow)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This build the screen and determines the number of physical drivers
|
|||
|
currently on the system.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hInstance Handle to this instance
|
|||
|
CmdShow Wether the user wants us to come out visible
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Wether the creation succeeded
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
HWND hWnd;
|
|||
|
HANDLE handle;
|
|||
|
HMENU hMenu;
|
|||
|
HFONT temp = NULL;
|
|||
|
DISK_HISTOGRAM histgram;
|
|||
|
DWORD numBytes;
|
|||
|
TCHAR szTopMost[] = TEXT("Always on &Top");
|
|||
|
|
|||
|
hInst = hInstance;
|
|||
|
|
|||
|
hWnd = CreateWindowEx(
|
|||
|
0,
|
|||
|
szAppName,
|
|||
|
szTitle,
|
|||
|
WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
|
|||
|
0,
|
|||
|
0,
|
|||
|
640,
|
|||
|
480,
|
|||
|
NULL,
|
|||
|
NULL,
|
|||
|
hInstance,
|
|||
|
NULL);
|
|||
|
|
|||
|
if (!hWnd) {
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Add the Always on Top string to the System menu
|
|||
|
//
|
|||
|
|
|||
|
hMenu = GetSystemMenu(hWnd,FALSE);
|
|||
|
AppendMenu(hMenu,MF_SEPARATOR,0,NULL);
|
|||
|
AppendMenu(hMenu,MF_ENABLED | MF_UNCHECKED | MF_STRING, IDM_TOPMOST, szTopMost);
|
|||
|
|
|||
|
//
|
|||
|
// Setup all the entries in the Main Data Structure
|
|||
|
//
|
|||
|
|
|||
|
PerfHist.hdcMain = GetDC(hWnd);
|
|||
|
PerfHist.hdcMem = CreateCompatibleDC(PerfHist.hdcMain);
|
|||
|
PerfHist.hBitMap = CreateCompatibleBitmap(PerfHist.hdcMain,640,480);
|
|||
|
PerfHist.bCantHide = FALSE;
|
|||
|
PerfHist.bTmpHide = FALSE;
|
|||
|
PerfHist.fDisplay = FALSE;
|
|||
|
PerfHist.wFormat = IDW_FULL;
|
|||
|
PerfHist.bIconic = FALSE;
|
|||
|
PerfHist.bNoTitle = FALSE;
|
|||
|
PerfHist.bTopMost = FALSE;
|
|||
|
|
|||
|
//
|
|||
|
// Initialize the Main DC (Memory DC)
|
|||
|
//
|
|||
|
|
|||
|
hMainFont = SelectObject(PerfHist.hdcMain,temp);
|
|||
|
SelectObject(PerfHist.hdcMain,hMainFont);
|
|||
|
SelectObject(PerfHist.hdcMem, hMainFont);
|
|||
|
SelectObject(PerfHist.hdcMem,hBrush);
|
|||
|
SelectObject(PerfHist.hdcMem,PerfHist.hBitMap);
|
|||
|
SetStretchBltMode(PerfHist.hdcMem,BLACKONWHITE);
|
|||
|
SetBkColor(PerfHist.hdcMem,RGB(64,64,64));
|
|||
|
SetBkMode(PerfHist.hdcMem,TRANSPARENT);
|
|||
|
SetTextColor(PerfHist.hdcMem,RGB(255,255,255));
|
|||
|
PatBlt(PerfHist.hdcMem,0,0,640,480, PATCOPY);
|
|||
|
|
|||
|
handle = CreateFile(TEXT("\\\\.\\PhysicalDrive0"),
|
|||
|
GENERIC_READ,
|
|||
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|||
|
NULL,
|
|||
|
OPEN_EXISTING,
|
|||
|
FILE_ATTRIBUTE_NORMAL,
|
|||
|
NULL);
|
|||
|
|
|||
|
if (handle == INVALID_HANDLE_VALUE) {
|
|||
|
MessageBox(NULL,
|
|||
|
TEXT("Could not open a drive."),
|
|||
|
TEXT("Error"),
|
|||
|
MB_ICONEXCLAMATION | MB_OK);
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
if (!DeviceIoControl (handle,
|
|||
|
IOCTL_DISK_REQUEST,
|
|||
|
NULL,
|
|||
|
0,
|
|||
|
&histgram,
|
|||
|
sizeof(DISK_HISTOGRAM),
|
|||
|
&numBytes,
|
|||
|
NULL)) {
|
|||
|
|
|||
|
if (GetLastError() == ERROR_INVALID_FUNCTION) {
|
|||
|
MessageBox(NULL,
|
|||
|
TEXT("Histgram.sys is not started on your system.\n"
|
|||
|
"Start the driver and reboot."),
|
|||
|
TEXT("Error"),
|
|||
|
MB_ICONEXCLAMATION | MB_OK);
|
|||
|
|
|||
|
CloseHandle(handle);
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
CloseHandle(handle);
|
|||
|
|
|||
|
ShowWindow(hWnd,CmdShow);
|
|||
|
UpdateWindow(hWnd);
|
|||
|
hMainWnd = hWnd;
|
|||
|
|
|||
|
return TRUE;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
TCHAR
|
|||
|
**GetAttachedDrives(
|
|||
|
PINT NumberDrives)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine builds an array of string which contains the name
|
|||
|
of each physicaldrive present on the system.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
NumberDrives Pointer to where to return the number of drives
|
|||
|
|
|||
|
Returns:
|
|||
|
|
|||
|
An array of strings
|
|||
|
|
|||
|
Credit:
|
|||
|
|
|||
|
Chuck Park, that GOD of a Programmer, wrote this and was kind enough to
|
|||
|
let me use it!
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
BOOL ValidDrive;
|
|||
|
TCHAR (*drivestrings)[16];
|
|||
|
TCHAR buffer[21];
|
|||
|
HANDLE handle;
|
|||
|
INT i = 0;
|
|||
|
|
|||
|
*NumberDrives = 0;
|
|||
|
|
|||
|
do {
|
|||
|
ValidDrive = FALSE;
|
|||
|
|
|||
|
_stprintf(buffer,TEXT("\\\\.\\PhysicalDrive%d"),i);
|
|||
|
|
|||
|
handle = CreateFile(buffer,
|
|||
|
GENERIC_READ,
|
|||
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|||
|
NULL,
|
|||
|
OPEN_EXISTING,
|
|||
|
FILE_ATTRIBUTE_NORMAL,
|
|||
|
NULL);
|
|||
|
|
|||
|
if (handle != INVALID_HANDLE_VALUE) {
|
|||
|
ValidDrive = TRUE;
|
|||
|
++(*NumberDrives);
|
|||
|
++i;
|
|||
|
CloseHandle(handle);
|
|||
|
}
|
|||
|
|
|||
|
} while (ValidDrive);
|
|||
|
|
|||
|
drivestrings = malloc ((16 * *NumberDrives * sizeof(TCHAR)));
|
|||
|
|
|||
|
if (!drivestrings) {
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
for (i = 0; i < *NumberDrives; i++) {
|
|||
|
_stprintf(drivestrings[i],"PhysicalDrive%d",i);
|
|||
|
}
|
|||
|
|
|||
|
return (TCHAR **)drivestrings;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
SetMenuBar(
|
|||
|
HWND hwnd)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function adds or removes the window title and the
|
|||
|
Menu bar based on the current flags.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hwnd Which window we wand to update
|
|||
|
|
|||
|
returns:
|
|||
|
|
|||
|
nada
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
|
|||
|
static DWORD wID;
|
|||
|
DWORD dwStyle;
|
|||
|
int cy;
|
|||
|
int cx;
|
|||
|
|
|||
|
dwStyle = GetWindowLong(hwnd,GWL_STYLE);
|
|||
|
if (PerfHist.bNoTitle) {
|
|||
|
//
|
|||
|
// Remove the caption && menu bar, etc
|
|||
|
//
|
|||
|
dwStyle &= ~ (WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX | WS_MAXIMIZEBOX);
|
|||
|
wID = SetWindowLong(hwnd, GWL_ID,0);
|
|||
|
|
|||
|
//
|
|||
|
// Uncheck the NO_TITLE option in the file menu
|
|||
|
//
|
|||
|
|
|||
|
CheckMenuItem(hMenuHandle, IDM_FILE_NO_TITLEBAR, MF_BYCOMMAND | MF_CHECKED);
|
|||
|
|
|||
|
//
|
|||
|
// Change the height to better reflect the space we are using
|
|||
|
//
|
|||
|
|
|||
|
if (PerfHist.wFormat == IDW_FULL) {
|
|||
|
cy = 440;
|
|||
|
cx = 640;
|
|||
|
} else {
|
|||
|
cx = 600;
|
|||
|
cy = 45;
|
|||
|
}
|
|||
|
} else {
|
|||
|
dwStyle |= (WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX);
|
|||
|
|
|||
|
//
|
|||
|
// Let's only reset the ID if the current wID is NULL
|
|||
|
//
|
|||
|
|
|||
|
if (!GetWindowLong(hwnd,GWL_ID)) {
|
|||
|
SetWindowLong(hwnd,GWL_ID,wID);
|
|||
|
SetWindowRgn(hwnd,NULL,TRUE);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Check the NO_TITLE option in the file menu
|
|||
|
//
|
|||
|
|
|||
|
CheckMenuItem(hMenuHandle, IDM_FILE_NO_TITLEBAR, MF_BYCOMMAND | MF_UNCHECKED);
|
|||
|
|
|||
|
//
|
|||
|
// Change the height to better reflect the space we are using
|
|||
|
//
|
|||
|
|
|||
|
if (PerfHist.wFormat == IDW_FULL) {
|
|||
|
cx = 640;
|
|||
|
cy = 480;
|
|||
|
} else {
|
|||
|
cx = 600;
|
|||
|
cy = 95;
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (PerfHist.wFormat == IDW_FULL) {
|
|||
|
|
|||
|
//
|
|||
|
// UnCheck the SMALL_DISPLAY menu setting
|
|||
|
//
|
|||
|
|
|||
|
CheckMenuItem(hMenuHandle, IDM_FILE_SMALL_DISPLAY, MF_BYCOMMAND | MF_UNCHECKED);
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// Check the SMALL_DISPLAY menu setting
|
|||
|
//
|
|||
|
|
|||
|
CheckMenuItem(hMenuHandle, IDM_FILE_SMALL_DISPLAY, MF_BYCOMMAND | MF_CHECKED);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Set the new style to the window
|
|||
|
//
|
|||
|
|
|||
|
SetWindowLong(hwnd,GWL_STYLE,dwStyle);
|
|||
|
|
|||
|
//
|
|||
|
// Set the new size of the window.
|
|||
|
// Make sure that we don't make it noticable to the user
|
|||
|
//
|
|||
|
|
|||
|
SetWindowPos(hwnd,NULL,0,0,cx,cy,SWP_NOMOVE | SWP_NOZORDER | SWP_FRAMECHANGED);
|
|||
|
|
|||
|
//
|
|||
|
// Force a Repaint
|
|||
|
//
|
|||
|
|
|||
|
InvalidateRgn(hwnd,NULL,TRUE);
|
|||
|
|
|||
|
//
|
|||
|
// Show the window
|
|||
|
//
|
|||
|
|
|||
|
ShowWindow(hwnd,SW_SHOW);
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
DrawColoredBox(
|
|||
|
int iWhich)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function displays one of the coloured boxes which servers as a key
|
|||
|
for the histogram
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
iWhich which coloured box to draw on the screen
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Nothing
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
HDC hdcMem;
|
|||
|
HBITMAP hBitMap;
|
|||
|
HBRUSH hBrush;
|
|||
|
|
|||
|
if (iWhich < 0 || iWhich >= boxesSize)
|
|||
|
return;
|
|||
|
|
|||
|
hdcMem = CreateCompatibleDC(PerfHist.hdcMain);
|
|||
|
hBitMap = CreateCompatibleBitmap(PerfHist.hdcMain,boxes[iWhich].width ,boxes[iWhich].height);
|
|||
|
SelectObject(hdcMem,hBitMap);
|
|||
|
hBrush = CreateSolidBrush(boxes[iWhich].colour);
|
|||
|
SelectObject(hdcMem,hBrush);
|
|||
|
|
|||
|
PatBlt(hdcMem,
|
|||
|
0,
|
|||
|
0,
|
|||
|
boxes[iWhich].width,
|
|||
|
boxes[iWhich].height,
|
|||
|
PATCOPY);
|
|||
|
|
|||
|
BitBlt(PerfHist.hdcMem,
|
|||
|
boxes[iWhich].x,
|
|||
|
boxes[iWhich].y,
|
|||
|
boxes[iWhich].width,
|
|||
|
boxes[iWhich].height,
|
|||
|
hdcMem,
|
|||
|
0,
|
|||
|
0,
|
|||
|
SRCCOPY);
|
|||
|
|
|||
|
DeleteObject(hBitMap);
|
|||
|
DeleteObject(hBrush);
|
|||
|
DeleteDC(hdcMem);
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
DrawString(
|
|||
|
TEXTFORMAT *string)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This functions displays the contents of the TEXTFORMAT record to the
|
|||
|
screen
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
The address of the record to print to the screen
|
|||
|
|
|||
|
Returns:
|
|||
|
|
|||
|
Nothing
|
|||
|
--*/
|
|||
|
{
|
|||
|
FillRect(PerfHist.hdcMem,&string->rect,hBrush);
|
|||
|
DrawText(PerfHist.hdcMem,string->text,string->length,&string->rect,string->style);
|
|||
|
// InvalidateRect(hMainWnd,string->rect,TRUE);
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
DrawXaxis(
|
|||
|
ULONG uMax)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function displays the number and draws the line for the xaxis
|
|||
|
portion of the histogram
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
uMax The largest number to display
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Nothing
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
ULONG i,j;
|
|||
|
ULONGLONG size;
|
|||
|
ULONG index;
|
|||
|
|
|||
|
for (i = 0; i < xaxisSize; i++) {
|
|||
|
index = uMax * i / ( xaxisSize - 1);
|
|||
|
|
|||
|
if (xaxis[i].value.QuadPart != (LONGLONG) index) {
|
|||
|
xaxis[i].value.QuadPart = (LONGLONG) index;
|
|||
|
if (current.ioctl == IOCTL_DISK_REQUEST) {
|
|||
|
for (j = 0, size = 1;j < index; j++)
|
|||
|
size *= 2;
|
|||
|
} else {
|
|||
|
size = current.histogram->Granularity * index;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Lets try to figure out what kind of units we should tack
|
|||
|
// onto the end of each numbers. The best way to do that
|
|||
|
// is to work our way up the scale...
|
|||
|
//
|
|||
|
|
|||
|
if (size < 1024) {
|
|||
|
|
|||
|
//
|
|||
|
// It's less then 1K, so don't use anything
|
|||
|
//
|
|||
|
|
|||
|
_stprintf(xaxis[i].text,"%ld",size);
|
|||
|
|
|||
|
} else if (size < (1024 * 1024)) {
|
|||
|
|
|||
|
//
|
|||
|
// It's in the 1kb-999kB range, so call it that
|
|||
|
//
|
|||
|
|
|||
|
_stprintf(xaxis[i].text,"%ldKb",(size / 1024) );
|
|||
|
} else if (size < (1024 * 1024 * 1024)) {
|
|||
|
|
|||
|
//
|
|||
|
// It's in the 1Mb-999Mb Range, so call it that
|
|||
|
//
|
|||
|
|
|||
|
_stprintf(xaxis[i].text,"%ldMb",(size / (1024 * 1024) ) );
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// Its in the 1Gb+ range
|
|||
|
//
|
|||
|
|
|||
|
_stprintf(xaxis[i].text,"%ldGb",(size / (1024 * 1024 * 1024) ) );
|
|||
|
}
|
|||
|
xaxis[i].length = _tcslen(xaxis[i].text);
|
|||
|
DrawString(&xaxis[i]);
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// We had better choose our title according to what we are displaying!
|
|||
|
//
|
|||
|
|
|||
|
if (current.ioctl == IOCTL_DISK_REQUEST) {
|
|||
|
_stprintf(labels[12].text,"IO Request Size");
|
|||
|
} else {
|
|||
|
_stprintf(labels[12].text,"Disk Location");
|
|||
|
}
|
|||
|
labels[12].length = _tcslen(labels[12].text);
|
|||
|
DrawString(&labels[12]);
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
DrawYaxis(
|
|||
|
ULONG uMax)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function displays the number and draws the line for the yaxis
|
|||
|
portion of the histogram
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
uMax The largest number to display
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Nothing
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
ULONG i;
|
|||
|
ULONG index;
|
|||
|
|
|||
|
if (uMax == 0)
|
|||
|
return;
|
|||
|
|
|||
|
for (i = 0; i < yaxisSize; i++) {
|
|||
|
index = i * uMax / (yaxisSize - 1);
|
|||
|
|
|||
|
if (yaxis[i].value.QuadPart != (LONGLONG) index) {
|
|||
|
yaxis[i].value.QuadPart = (LONGLONG) index;
|
|||
|
|
|||
|
_stprintf(yaxis[i].text,"%ld",yaxis[i].value.QuadPart);
|
|||
|
yaxis[i].length = _tcslen(yaxis[i].text);
|
|||
|
DrawString(&yaxis[i]);
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
DrawFont()
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function selects the proper font into the current DC
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Nothing
|
|||
|
|
|||
|
Returns:
|
|||
|
|
|||
|
Nothing
|
|||
|
--*/
|
|||
|
{
|
|||
|
CHOOSEFONT cf;
|
|||
|
LOGFONT lf;
|
|||
|
HFONT hFont = NULL;
|
|||
|
HDC hDC;
|
|||
|
|
|||
|
cf.lStructSize = sizeof(CHOOSEFONT);
|
|||
|
cf.hwndOwner = (HWND) NULL;
|
|||
|
cf.hDC = (HDC) NULL;
|
|||
|
cf.lpLogFont = &lf;
|
|||
|
cf.iPointSize = 0;
|
|||
|
cf.Flags = CF_SCREENFONTS;
|
|||
|
cf.rgbColors = RGB(0,0,0);
|
|||
|
cf.lCustData = 0L;
|
|||
|
cf.lpfnHook = (LPCFHOOKPROC) NULL;
|
|||
|
cf.lpTemplateName = (LPSTR) NULL;
|
|||
|
cf.hInstance = (HINSTANCE) NULL;
|
|||
|
cf.lpszStyle = (LPSTR) NULL;
|
|||
|
cf.nFontType = SCREEN_FONTTYPE;
|
|||
|
cf.nSizeMin = 0;
|
|||
|
cf.nSizeMax = 0;
|
|||
|
|
|||
|
ChooseFont(&cf);
|
|||
|
|
|||
|
hFont = CreateFontIndirect(cf.lpLogFont);
|
|||
|
if (hFont) {
|
|||
|
hMainFont = hFont;
|
|||
|
hFont = SelectObject(PerfHist.hdcMain,hMainFont);
|
|||
|
if (hFont) {
|
|||
|
DeleteObject(hFont);
|
|||
|
}
|
|||
|
hFont = SelectObject(PerfHist.hdcMem,hMainFont);
|
|||
|
if (hFont) {
|
|||
|
DeleteObject(hFont);
|
|||
|
}
|
|||
|
} else {
|
|||
|
hDC = GetDC(hMainWnd);
|
|||
|
|
|||
|
//
|
|||
|
// Do a quick double select to remember what the main font is!
|
|||
|
//
|
|||
|
|
|||
|
hMainFont = SelectObject(hDC,hFont);
|
|||
|
SelectObject(hDC,hMainFont);
|
|||
|
|
|||
|
ReleaseDC(hMainWnd,hDC);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void
|
|||
|
DrawHistogram()
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function draws both bitmaps to the screen
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
none
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Nothing
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
HDC hdcMem;
|
|||
|
HBITMAP hBitMap;
|
|||
|
ULONG i;
|
|||
|
ULONG tMax;
|
|||
|
BOOL status = FALSE;
|
|||
|
ULONGLONG lCurRead = 0;
|
|||
|
ULONGLONG lCurWrite = 0;
|
|||
|
ULONGLONG lTotRead = 0;
|
|||
|
ULONGLONG lTotWrite = 0;
|
|||
|
ULONG write;
|
|||
|
ULONG read;
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Calculate the highest area of activity
|
|||
|
//
|
|||
|
|
|||
|
memset(pHist,0, (total.histogram->Size * sizeof(ULONG) ) );
|
|||
|
memset(pCurr,0, (total.histogram->Size * sizeof(ULONG) ) );
|
|||
|
|
|||
|
total.histogram->ReadCount += current.histogram->ReadCount;
|
|||
|
total.histogram->WriteCount += current.histogram->WriteCount;
|
|||
|
|
|||
|
for (i = tMax = 0; i < total.histogram->Size; i++) {
|
|||
|
|
|||
|
write = current.histogram->Histogram[i].Writes;
|
|||
|
total.histogram->Histogram[i].Writes += write;
|
|||
|
lCurWrite += (write * (i+1));
|
|||
|
lTotWrite += (total.histogram->Histogram[i].Writes * (i+1));
|
|||
|
|
|||
|
if (total.flags & PROCESS_WRITE) {
|
|||
|
pHist[i] += total.histogram->Histogram[i].Writes;
|
|||
|
pCurr[i] += write;
|
|||
|
}
|
|||
|
|
|||
|
read = current.histogram->Histogram[i].Reads;
|
|||
|
total.histogram->Histogram[i].Reads += read;
|
|||
|
lCurRead += (read * (i+1));
|
|||
|
lTotRead += (total.histogram->Histogram[i].Reads * (i+1));
|
|||
|
|
|||
|
if (total.flags & PROCESS_READ) {
|
|||
|
pHist[i] += total.histogram->Histogram[i].Reads;
|
|||
|
pCurr[i] += read;
|
|||
|
}
|
|||
|
|
|||
|
if (pHist[i] > tMax) {
|
|||
|
tMax = pHist[i];
|
|||
|
}
|
|||
|
if (pCurr[i] > cMax) {
|
|||
|
status = TRUE;
|
|||
|
cMax = pCurr[i];
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Create a compatible DC
|
|||
|
//
|
|||
|
|
|||
|
hdcMem = CreateCompatibleDC(PerfHist.hdcMain);
|
|||
|
|
|||
|
//
|
|||
|
// Create a bitmap compatible with the current dc
|
|||
|
//
|
|||
|
|
|||
|
hBitMap = CreateCompatibleBitmap(PerfHist.hdcMain, total.histogram->Size, cMax);
|
|||
|
|
|||
|
//
|
|||
|
// Load the Bitmap into the temp memory we have allocated
|
|||
|
//
|
|||
|
|
|||
|
SelectObject(hdcMem,hBitMap);
|
|||
|
//
|
|||
|
// Color the background grey in the bitmap
|
|||
|
//
|
|||
|
|
|||
|
SelectObject(hdcMem, GetStockObject(LTGRAY_BRUSH));
|
|||
|
|
|||
|
//
|
|||
|
// Reset the background grey in the bitmap
|
|||
|
//
|
|||
|
|
|||
|
status = PatBlt(hdcMem,0,0,total.histogram->Size,cMax,PATCOPY);
|
|||
|
|
|||
|
//
|
|||
|
// Draw the Histogram, using different colored brushes where
|
|||
|
// possible
|
|||
|
//
|
|||
|
|
|||
|
for (i = 0; i < current.histogram->Size; i++) {
|
|||
|
if (pCurr[i] <= 0)
|
|||
|
continue;
|
|||
|
else if (pCurr[i] < (cMax * 1 / 5))
|
|||
|
SelectObject(hdcMem,hBrush1);
|
|||
|
else if (pCurr[i] < (cMax * 2 / 5))
|
|||
|
SelectObject(hdcMem,hBrush2);
|
|||
|
else if (pCurr[i] < (cMax * 3 / 5))
|
|||
|
SelectObject(hdcMem,hBrush3);
|
|||
|
else if (pCurr[i] < (cMax * 4 / 5))
|
|||
|
SelectObject(hdcMem,hBrush4);
|
|||
|
else
|
|||
|
SelectObject(hdcMem,hBrush5);
|
|||
|
|
|||
|
//
|
|||
|
// Draw the line, of the appropriate height,
|
|||
|
// remember that the bottom of the BM is the
|
|||
|
// x-axis!
|
|||
|
//
|
|||
|
|
|||
|
PatBlt(hdcMem,
|
|||
|
i,
|
|||
|
(cMax - pCurr[i]),
|
|||
|
1,
|
|||
|
pCurr[i],
|
|||
|
PATCOPY);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Perform the stretch that will dispay the bitmap insides
|
|||
|
// its proper window
|
|||
|
//
|
|||
|
|
|||
|
status = StretchBlt(PerfHist.hdcMem,
|
|||
|
30,
|
|||
|
62,
|
|||
|
600,
|
|||
|
273,
|
|||
|
hdcMem,
|
|||
|
0,
|
|||
|
0,
|
|||
|
total.histogram->Size,
|
|||
|
cMax,
|
|||
|
SRCCOPY);
|
|||
|
|
|||
|
//
|
|||
|
// Test to see if the window is currently minized
|
|||
|
// If it is, then we had better do something about it.
|
|||
|
//
|
|||
|
|
|||
|
if (PerfHist.bIconic) {
|
|||
|
|
|||
|
DeleteDC(hdcMem);
|
|||
|
DeleteObject(hBitMap);
|
|||
|
|
|||
|
//
|
|||
|
// We don't need to do any more work, so stop here!
|
|||
|
//
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Recalculate the various averages
|
|||
|
//
|
|||
|
|
|||
|
|
|||
|
read = current.histogram->Granularity; // using read as a scratch var
|
|||
|
|
|||
|
if (current.histogram->ReadCount) {
|
|||
|
|
|||
|
CurrentRead.QuadPart = (lCurRead * read / current.histogram->ReadCount);
|
|||
|
TotalRead.QuadPart = (lTotRead * read / total.histogram->ReadCount);
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
CurrentRead.QuadPart = 0;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
if (current.histogram->WriteCount) {
|
|||
|
|
|||
|
CurrentWrite.QuadPart = (lCurWrite * read / current.histogram->WriteCount);
|
|||
|
TotalWrite.QuadPart = (lTotWrite * read / total.histogram->WriteCount);
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
CurrentWrite.QuadPart = 0;
|
|||
|
}
|
|||
|
|
|||
|
if (current.histogram->WriteCount || current.histogram->ReadCount) {
|
|||
|
|
|||
|
CurrentAvg.QuadPart = (lCurRead + lCurWrite) * read /
|
|||
|
(current.histogram->ReadCount + current.histogram->WriteCount);
|
|||
|
|
|||
|
TotalAvg.QuadPart = (lTotRead + lTotWrite) * read /
|
|||
|
(total.histogram->ReadCount + total.histogram->WriteCount);
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
CurrentAvg.QuadPart = 0;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Oops, we changed the size of the Yaxis. Better redraw it
|
|||
|
//
|
|||
|
|
|||
|
if (status)
|
|||
|
DrawYaxis(cMax);
|
|||
|
|
|||
|
SelectObject(hdcMem, GetStockObject(LTGRAY_BRUSH));
|
|||
|
PatBlt(hdcMem,0,0,total.histogram->Size,1,PATCOPY);
|
|||
|
|
|||
|
for (i = 0; i < total.histogram->Size; i++) {
|
|||
|
if (pHist[i] <= 0)
|
|||
|
continue;
|
|||
|
else if (pHist[i] < (tMax * 1 / 5))
|
|||
|
SetPixelV(hdcMem,i,0,RGB(0,0,255));
|
|||
|
else if (pHist[i] < (tMax * 2 / 5))
|
|||
|
SetPixelV(hdcMem,i,0,RGB(0,255,0));
|
|||
|
else if (pHist[i] < (tMax * 3 / 5))
|
|||
|
SetPixelV(hdcMem,i,0,RGB(255,255,0));
|
|||
|
else if (pHist[i] < (tMax * 4 / 5))
|
|||
|
SetPixelV(hdcMem,i,0,RGB(255,0,255));
|
|||
|
else
|
|||
|
SetPixelV(hdcMem,i,0,RGB(255,0,0));
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Display the bitmap in the disk usage window
|
|||
|
// making sure to only strech the appropriate space
|
|||
|
//
|
|||
|
|
|||
|
StretchBlt(PerfHist.hdcMem,
|
|||
|
30,
|
|||
|
20,
|
|||
|
600,
|
|||
|
20,
|
|||
|
hdcMem,
|
|||
|
0,
|
|||
|
0,
|
|||
|
total.histogram->Size,
|
|||
|
1,
|
|||
|
SRCCOPY);
|
|||
|
|
|||
|
//
|
|||
|
// Release all used resources
|
|||
|
//
|
|||
|
|
|||
|
DeleteDC(hdcMem);
|
|||
|
DeleteObject(hBitMap);
|
|||
|
}
|
|||
|
|
|||
|
BOOL
|
|||
|
ProcessCreate(
|
|||
|
HWND hWnd,
|
|||
|
LPCREATESTRUCT lpCreateStruct)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine process the WM_CREATE message send to the WndProc function.
|
|||
|
It is responsible for creating all the initial objects on the screen.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hwnd The window which is affected by the message
|
|||
|
lpCreateStruct (lParam)
|
|||
|
|
|||
|
Returns:
|
|||
|
|
|||
|
TRUE or FALSE
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
int i;
|
|||
|
|
|||
|
hBrush = CreateSolidBrush(RGB(64,64,64));
|
|||
|
hBrush1 = CreateSolidBrush(RGB(0,0,255));
|
|||
|
hBrush2 = CreateSolidBrush(RGB(255,255,0));
|
|||
|
hBrush3 = CreateSolidBrush(RGB(255,0,255));
|
|||
|
hBrush4 = CreateSolidBrush(RGB(0,255,0));
|
|||
|
hBrush5 = CreateSolidBrush(RGB(255,0,0));
|
|||
|
hMenuHandle = GetMenu(hWnd);
|
|||
|
|
|||
|
//
|
|||
|
// Create static text controls
|
|||
|
//
|
|||
|
|
|||
|
for (i = 0; i < labelsSize; i++) {
|
|||
|
labels[i].length = _tcslen(labels[i].text);
|
|||
|
}
|
|||
|
|
|||
|
for (i = 0; i < variablesSize; i++) {
|
|||
|
variables[i].length = _tcslen(variables[i].text);
|
|||
|
}
|
|||
|
|
|||
|
for (i = 0; i < xaxisSize; i++) {
|
|||
|
xaxis[i].length = _tcslen(xaxis[i].text);
|
|||
|
xaxis[i].value.QuadPart = -1;
|
|||
|
}
|
|||
|
|
|||
|
for (i = 0; i < yaxisSize; i++) {
|
|||
|
yaxis[i].length = _tcslen(yaxis[i].text);
|
|||
|
yaxis[i].value.QuadPart = -1;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// These menu items should not be allowed right now
|
|||
|
//
|
|||
|
|
|||
|
EnableMenuItem (hMenuHandle,IDM_OPTIONS_START,MF_GRAYED);
|
|||
|
EnableMenuItem (hMenuHandle,IDM_OPTIONS_STOP, MF_GRAYED);
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
void
|
|||
|
ProcessPaint(
|
|||
|
HWND hWnd)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine handles all window paint messages.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hWnd window to redraw
|
|||
|
|
|||
|
Returns:
|
|||
|
|
|||
|
void
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
PAINTSTRUCT ps;
|
|||
|
TEXTFORMAT *tf;
|
|||
|
RECT *rc;
|
|||
|
ULONG num;
|
|||
|
ULONG i,j;
|
|||
|
|
|||
|
BeginPaint(hMainWnd,&ps);
|
|||
|
|
|||
|
//
|
|||
|
// Are we an icon? Gee, if so, then many we should just dump
|
|||
|
// the HISTOGRAM to the top-left corner of the screen? That
|
|||
|
// would be very smart!
|
|||
|
//
|
|||
|
|
|||
|
if (PerfHist.bIconic) {
|
|||
|
|
|||
|
//
|
|||
|
// We need to do a very nasty stretch-move-blit here, but hey? what
|
|||
|
// the heck? we are gods anyways!
|
|||
|
//
|
|||
|
|
|||
|
StretchBlt(PerfHist.hdcMain,
|
|||
|
0,
|
|||
|
0,
|
|||
|
36,
|
|||
|
36,
|
|||
|
PerfHist.hdcMem,
|
|||
|
30,
|
|||
|
62,
|
|||
|
600,
|
|||
|
273,
|
|||
|
SRCCOPY);
|
|||
|
|
|||
|
//
|
|||
|
// If we don't do an EndPaint, we will continually get WM_PAINT
|
|||
|
// messages, which is really bad, so might as well do one.
|
|||
|
//
|
|||
|
|
|||
|
EndPaint(hMainWnd,&ps);
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if (PerfHist.wFormat != IDW_FULL) {
|
|||
|
|
|||
|
//
|
|||
|
// Here we are simply gonna display the main total bar in the
|
|||
|
// window, then we are gonna exit
|
|||
|
//
|
|||
|
|
|||
|
BitBlt(PerfHist.hdcMain,
|
|||
|
0,
|
|||
|
0,
|
|||
|
600,
|
|||
|
20,
|
|||
|
PerfHist.hdcMem,
|
|||
|
30,
|
|||
|
20,
|
|||
|
SRCCOPY);
|
|||
|
|
|||
|
//
|
|||
|
// Let's also display the current bar in the window, to give the user
|
|||
|
// a better idea of what is going on.
|
|||
|
//
|
|||
|
|
|||
|
StretchBlt(PerfHist.hdcMain,
|
|||
|
0,
|
|||
|
25,
|
|||
|
600,
|
|||
|
20,
|
|||
|
PerfHist.hdcMem,
|
|||
|
30,
|
|||
|
334,
|
|||
|
600,
|
|||
|
1,
|
|||
|
SRCCOPY);
|
|||
|
|
|||
|
|
|||
|
EndPaint(hMainWnd,&ps);
|
|||
|
|
|||
|
return;
|
|||
|
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// The easiest way to do this is to check to see which regions have
|
|||
|
// changed and to update them.
|
|||
|
//
|
|||
|
// If I really analyze this code, I might discover that alot of it
|
|||
|
// is very redundant because the data is painted on the memory map
|
|||
|
// so we don't need to redraw it!!!
|
|||
|
//
|
|||
|
// However, removing this requires that other portions of the program
|
|||
|
// be updated to display the screen properly
|
|||
|
//
|
|||
|
|
|||
|
for (i = 0; i < 4; i++) {
|
|||
|
if (i == 0) {
|
|||
|
tf = &labels[0];
|
|||
|
num = labelsSize;
|
|||
|
} else if (i == 1) {
|
|||
|
tf = &variables[0];
|
|||
|
num = variablesSize;
|
|||
|
} else if (i == 2) {
|
|||
|
tf = &xaxis[0];
|
|||
|
num = xaxisSize;
|
|||
|
} else {
|
|||
|
tf = &yaxis[0];
|
|||
|
num = yaxisSize;
|
|||
|
}
|
|||
|
|
|||
|
for (j = 0; j < num ; j++) {
|
|||
|
|
|||
|
rc = &tf->rect;
|
|||
|
|
|||
|
if ( ( (rc->top > ps.rcPaint.top &&
|
|||
|
rc->top < ps.rcPaint.bottom) ||
|
|||
|
( (rc->bottom) > ps.rcPaint.top &&
|
|||
|
(rc->bottom) < ps.rcPaint.bottom) ) &&
|
|||
|
( (rc->left > ps.rcPaint.left &&
|
|||
|
rc->left < ps.rcPaint.right) ||
|
|||
|
( (rc->right) > ps.rcPaint.left &&
|
|||
|
(rc->right) < ps.rcPaint.right) ) ) {
|
|||
|
|
|||
|
DrawString(tf);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
tf++;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
for (i = 0; i < boxesSize; i++) {
|
|||
|
if ( ( (boxes[i].y > ps.rcPaint.top &&
|
|||
|
boxes[i].y < ps.rcPaint.bottom) ||
|
|||
|
( (boxes[i].y + boxes[i].height) > ps.rcPaint.top &&
|
|||
|
(boxes[i].y + boxes[i].height) < ps.rcPaint.bottom) ) &&
|
|||
|
( (boxes[i].x > ps.rcPaint.left &&
|
|||
|
boxes[i].x < ps.rcPaint.right) ||
|
|||
|
( (boxes[i].x + boxes[i].width) > ps.rcPaint.left &&
|
|||
|
(boxes[i].x + boxes[i].width) < ps.rcPaint.right) ) ) {
|
|||
|
|
|||
|
DrawColoredBox(i);
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
BitBlt(PerfHist.hdcMain,
|
|||
|
0,
|
|||
|
0,
|
|||
|
640,
|
|||
|
480,
|
|||
|
PerfHist.hdcMem,
|
|||
|
0,
|
|||
|
0,
|
|||
|
SRCCOPY);
|
|||
|
|
|||
|
EndPaint(hMainWnd,&ps);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
void
|
|||
|
ProcessCommand(
|
|||
|
HWND hWnd,
|
|||
|
int id,
|
|||
|
HWND hWndCtl,
|
|||
|
UINT codeNotify)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This rouinte handles all window commands
|
|||
|
|
|||
|
Arugments:
|
|||
|
|
|||
|
hWnd window that sent command
|
|||
|
id command sent
|
|||
|
hWndCtl not used
|
|||
|
codeNotify not used
|
|||
|
|
|||
|
Returns:
|
|||
|
|
|||
|
void
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
|
|||
|
DISK_HISTOGRAM tempHist;
|
|||
|
DWORD numBytes;
|
|||
|
|
|||
|
switch(id) {
|
|||
|
case IDM_FILE_EXIT:
|
|||
|
DestroyWindow(hWnd);
|
|||
|
break;
|
|||
|
case IDM_FILE_NO_TITLEBAR:
|
|||
|
PerfHist.fDisplay = FALSE;
|
|||
|
PerfHist.bNoTitle = (PerfHist.bNoTitle ? FALSE : TRUE);
|
|||
|
SetMenuBar(hWnd); // This is the function that does the work
|
|||
|
break;
|
|||
|
case IDM_FILE_SMALL_DISPLAY:
|
|||
|
PerfHist.fDisplay = FALSE;
|
|||
|
PerfHist.wFormat = (PerfHist.wFormat == IDW_FULL ? IDW_TOTAL : IDW_FULL);
|
|||
|
SetMenuBar(hWnd); // This is the function that does the work
|
|||
|
InvalidateRgn(hMainWnd,NULL,TRUE);
|
|||
|
break;
|
|||
|
case IDM_OPTIONS_CONFIGURATION:
|
|||
|
DialogBox(hInst,
|
|||
|
MAKEINTRESOURCE(IDD_PERF_CONFIGURATION),
|
|||
|
hWnd,
|
|||
|
(DLGPROC)ConfigProc);
|
|||
|
break;
|
|||
|
case IDM_OPTIONS_CHANGEFONT:
|
|||
|
DrawFont();
|
|||
|
InvalidateRgn(hMainWnd,NULL,TRUE);
|
|||
|
break;
|
|||
|
case IDM_OPTIONS_START:
|
|||
|
|
|||
|
EnableMenuItem(hMenuHandle,IDM_OPTIONS_STOP, MF_ENABLED);
|
|||
|
EnableMenuItem(hMenuHandle,IDM_OPTIONS_START,MF_GRAYED);
|
|||
|
DrawMenuBar(hWnd);
|
|||
|
|
|||
|
//
|
|||
|
// Flush the Current Values
|
|||
|
//
|
|||
|
|
|||
|
DeviceIoControl(current.handle,
|
|||
|
current.ioctl,
|
|||
|
NULL,
|
|||
|
0,
|
|||
|
&tempHist,
|
|||
|
DISK_HISTOGRAM_SIZE,
|
|||
|
&numBytes,
|
|||
|
NULL);
|
|||
|
|
|||
|
SetTimer(hWnd,ID_TIMER,1000,(TIMERPROC)NULL);
|
|||
|
break;
|
|||
|
|
|||
|
case IDM_OPTIONS_STOP:
|
|||
|
|
|||
|
KillTimer(hWnd,ID_TIMER);
|
|||
|
|
|||
|
EnableMenuItem(hMenuHandle,IDM_OPTIONS_STOP, MF_GRAYED);
|
|||
|
EnableMenuItem(hMenuHandle,IDM_OPTIONS_START,MF_ENABLED);
|
|||
|
DrawMenuBar(hWnd);
|
|||
|
|
|||
|
break;
|
|||
|
default:
|
|||
|
FORWARD_WM_COMMAND(hWnd,id,hWndCtl,codeNotify,DefWindowProc);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
void
|
|||
|
ProcessDestroy(
|
|||
|
HWND hWnd)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This is the routine that process the destroy window message
|
|||
|
|
|||
|
Arugments:
|
|||
|
|
|||
|
hWnd The window that is to be destroyed
|
|||
|
|
|||
|
Returns:
|
|||
|
|
|||
|
Nothing
|
|||
|
--*/
|
|||
|
{
|
|||
|
DeleteObject(hMainFont);
|
|||
|
DeleteObject(hBrush);
|
|||
|
DeleteObject(hBrush1);
|
|||
|
DeleteObject(hBrush2);
|
|||
|
DeleteObject(hBrush3);
|
|||
|
DeleteObject(hBrush4);
|
|||
|
DeleteObject(hBrush5);
|
|||
|
PostQuitMessage(0);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
ProcessTimer(
|
|||
|
HWND hWnd,
|
|||
|
UINT id)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This is the routine that process each timer tick. It calls a
|
|||
|
DeviceIoControl to get the latest and greatest information
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hWnd The current window
|
|||
|
id not used
|
|||
|
|
|||
|
Returns
|
|||
|
|
|||
|
Void
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD numBytes;
|
|||
|
|
|||
|
if (!DeviceIoControl(current.handle,
|
|||
|
current.ioctl,
|
|||
|
NULL,
|
|||
|
0,
|
|||
|
current.histogram,
|
|||
|
(DISK_HISTOGRAM_SIZE + (current.histogram->Size * HISTOGRAM_BUCKET_SIZE )),
|
|||
|
&numBytes,
|
|||
|
NULL) &&
|
|||
|
GetLastError() == ERROR_INVALID_FUNCTION) {
|
|||
|
|
|||
|
KillTimer(hWnd,ID_TIMER);
|
|||
|
MessageBox(NULL,
|
|||
|
TEXT("Error obtaining histogram data."),
|
|||
|
TEXT("Error"),
|
|||
|
MB_ICONEXCLAMATION | MB_OK);
|
|||
|
return;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Reset the pointer to the histogram to the 'correct location'
|
|||
|
//
|
|||
|
|
|||
|
current.histogram->Histogram = (HISTOGRAM_BUCKET *) ( (char *) current.histogram + DISK_HISTOGRAM_SIZE );
|
|||
|
|
|||
|
//
|
|||
|
// Draw the Histogram
|
|||
|
//
|
|||
|
|
|||
|
DrawHistogram();
|
|||
|
|
|||
|
numBytes = (numBytes - DISK_HISTOGRAM_SIZE) / HISTOGRAM_BUCKET_SIZE;
|
|||
|
|
|||
|
if (variables[8].value.QuadPart != (LONGLONG) numBytes) {
|
|||
|
|
|||
|
variables[8].value.QuadPart = (LONGLONG) numBytes;
|
|||
|
_stprintf(variables[8].text,"%ld", variables[8].value.QuadPart);
|
|||
|
variables[8].length = _tcslen(variables[8].text);
|
|||
|
DrawString(&variables[8]);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Update the 'current' selections
|
|||
|
//
|
|||
|
|
|||
|
if (variables[2].value.QuadPart != CurrentAvg.QuadPart) {
|
|||
|
|
|||
|
variables[2].value.QuadPart = CurrentAvg.QuadPart;
|
|||
|
_stprintf(variables[2].text,"%ld",variables[2].value.QuadPart);
|
|||
|
variables[2].length = _tcslen(variables[2].text);
|
|||
|
DrawString(&variables[2]);
|
|||
|
}
|
|||
|
|
|||
|
if (variables[3].value.QuadPart != CurrentRead.QuadPart) {
|
|||
|
|
|||
|
variables[3].value.QuadPart = CurrentRead.QuadPart;
|
|||
|
_stprintf(variables[3].text,"%ld",variables[3].value.QuadPart);
|
|||
|
variables[3].length = _tcslen(variables[3].text);
|
|||
|
DrawString(&variables[3]);
|
|||
|
}
|
|||
|
|
|||
|
if (variables[4].value.QuadPart != CurrentWrite.QuadPart) {
|
|||
|
|
|||
|
variables[4].value.QuadPart = CurrentWrite.QuadPart;
|
|||
|
_stprintf(variables[4].text,"%ld",variables[4].value.QuadPart);
|
|||
|
variables[4].length = _tcslen(variables[4].text);
|
|||
|
DrawString(&variables[4]);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Update the 'total' selections
|
|||
|
//
|
|||
|
|
|||
|
if (variables[5].value.QuadPart != TotalAvg.QuadPart) {
|
|||
|
|
|||
|
variables[5].value.QuadPart = TotalAvg.QuadPart;
|
|||
|
_stprintf(variables[5].text,"%ld",variables[5].value.QuadPart);
|
|||
|
variables[5].length = _tcslen(variables[5].text);
|
|||
|
DrawString(&variables[5]);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
if (variables[6].value.QuadPart != TotalRead.QuadPart) {
|
|||
|
variables[6].value.QuadPart = TotalRead.QuadPart;
|
|||
|
_stprintf(variables[6].text,"%ld",variables[6].value.QuadPart);
|
|||
|
variables[6].length = _tcslen(variables[6].text);
|
|||
|
DrawString(&variables[6]);
|
|||
|
}
|
|||
|
|
|||
|
if (variables[7].value.QuadPart != TotalWrite.QuadPart) {
|
|||
|
|
|||
|
variables[7].value.QuadPart = TotalWrite.QuadPart;
|
|||
|
_stprintf(variables[7].text,"%ld",variables[7].value.QuadPart);
|
|||
|
variables[7].length = _tcslen(variables[7].text);
|
|||
|
DrawString(&variables[7]);
|
|||
|
}
|
|||
|
|
|||
|
ProcessPaint(hMainWnd);
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
BOOL APIENTRY
|
|||
|
ConfigProc(
|
|||
|
HWND hDlg,
|
|||
|
UINT uMsg,
|
|||
|
WPARAM wParam,
|
|||
|
LPARAM lParam)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This is the callback routine for the configuration dialog box.
|
|||
|
|
|||
|
Arugments:
|
|||
|
|
|||
|
hDlg The Dialog Box
|
|||
|
uMsg The message which has been sent to the window
|
|||
|
wParam
|
|||
|
lParam
|
|||
|
|
|||
|
Returns
|
|||
|
|
|||
|
0
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
BOOL processed = TRUE;
|
|||
|
static int NumberOfCurrentDrives = 0;
|
|||
|
DISK_HISTOGRAM tempHist;
|
|||
|
INT noActive;
|
|||
|
INT errNum;
|
|||
|
INT i;
|
|||
|
TCHAR (*drvs)[16];
|
|||
|
TCHAR buffer[16];
|
|||
|
TCHAR fileName[20];
|
|||
|
TCHAR errorBuf[64];
|
|||
|
HDC hdc;
|
|||
|
|
|||
|
switch(uMsg) {
|
|||
|
case WM_INITDIALOG:
|
|||
|
|
|||
|
(char **)drvs = GetAttachedDrives(&NumberOfCurrentDrives);
|
|||
|
|
|||
|
if (!drvs) {
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
for (i = 0; i < NumberOfCurrentDrives; i++) {
|
|||
|
SendDlgItemMessage(hDlg,
|
|||
|
IDC_PHYSICAL_DRIVE,
|
|||
|
LB_ADDSTRING,
|
|||
|
0,
|
|||
|
(LPARAM) (LPCTSTR)drvs[i]);
|
|||
|
}
|
|||
|
|
|||
|
free (drvs);
|
|||
|
|
|||
|
for (i = 0; i < typeSize; i++) {
|
|||
|
SendDlgItemMessage(hDlg,
|
|||
|
IDC_SOURCE_DATA,
|
|||
|
LB_ADDSTRING,
|
|||
|
0,
|
|||
|
(LPARAM) (LPCTSTR)type[i].name);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Diasable the OK button for now
|
|||
|
//
|
|||
|
|
|||
|
EnableWindow(GetDlgItem(hDlg,IDOK),FALSE);
|
|||
|
|
|||
|
processed = FALSE;
|
|||
|
break;
|
|||
|
case WM_COMMAND:
|
|||
|
switch(LOWORD(wParam)) {
|
|||
|
case IDC_SOURCE_DATA:
|
|||
|
case IDC_PHYSICAL_DRIVE:
|
|||
|
|
|||
|
if (HIWORD(wParam) == LBN_DBLCLK ||
|
|||
|
HIWORD(wParam) == LBN_SELCHANGE) {
|
|||
|
|
|||
|
if (SendDlgItemMessage(hDlg,IDC_PHYSICAL_DRIVE,LB_GETCURSEL,0,0) != LB_ERR &&
|
|||
|
SendDlgItemMessage(hDlg,IDC_SOURCE_DATA, LB_GETCURSEL,0,0) != LB_ERR) {
|
|||
|
|
|||
|
if (!IsWindowEnabled(GetDlgItem(hDlg,IDOK))) {
|
|||
|
EnableWindow(GetDlgItem(hDlg,IDOK),TRUE);
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
if (IsWindowEnabled(GetDlgItem(hDlg,IDOK))) {
|
|||
|
EnableWindow(GetDlgItem(hDlg,IDOK),FALSE);
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case IDOK:
|
|||
|
|
|||
|
if (timerOn) {
|
|||
|
KillTimer(hMainWnd,ID_TIMER);
|
|||
|
}
|
|||
|
|
|||
|
EnableMenuItem (hMenuHandle,IDM_OPTIONS_START,MF_ENABLED);
|
|||
|
EnableMenuItem (hMenuHandle,IDM_OPTIONS_STOP, MF_GRAYED);
|
|||
|
DrawMenuBar(hMainWnd);
|
|||
|
|
|||
|
if (current.handle != INVALID_HANDLE_VALUE) {
|
|||
|
CloseHandle(current.handle);
|
|||
|
current.handle = INVALID_HANDLE_VALUE;
|
|||
|
}
|
|||
|
|
|||
|
if (current.histogram != NULL) {
|
|||
|
free (current.histogram);
|
|||
|
current.histogram = NULL;
|
|||
|
}
|
|||
|
|
|||
|
if (total.histogram != NULL) {
|
|||
|
free(total.histogram);
|
|||
|
total.histogram = NULL;
|
|||
|
}
|
|||
|
if (pHist != NULL) {
|
|||
|
free(pHist);
|
|||
|
pHist = NULL;
|
|||
|
}
|
|||
|
if (pCurr != NULL) {
|
|||
|
free(pCurr);
|
|||
|
pCurr = NULL;
|
|||
|
}
|
|||
|
|
|||
|
noActive = SendDlgItemMessage(hDlg,
|
|||
|
IDC_PHYSICAL_DRIVE,
|
|||
|
LB_GETCURSEL,
|
|||
|
0,
|
|||
|
0);
|
|||
|
|
|||
|
errNum = SendDlgItemMessage(hDlg,
|
|||
|
IDC_PHYSICAL_DRIVE,
|
|||
|
LB_GETTEXT,
|
|||
|
(WPARAM)noActive,
|
|||
|
(LPARAM)(LPCTSTR)buffer);
|
|||
|
|
|||
|
if (errNum == LB_ERR) {
|
|||
|
|
|||
|
_tcscpy(variables[0].text,TEXT(""));
|
|||
|
_tcscpy(variables[1].text,TEXT(""));
|
|||
|
|
|||
|
variables[0].length = _tcslen(variables[0].text);
|
|||
|
variables[1].length = _tcslen(variables[1].text);
|
|||
|
DrawString(&variables[0]);
|
|||
|
DrawString(&variables[1]);
|
|||
|
|
|||
|
MessageBox(NULL,
|
|||
|
TEXT("Could not retrieve text selection from dialog"),
|
|||
|
TEXT("Error"),
|
|||
|
MB_ICONEXCLAMATION | MB_OK);
|
|||
|
|
|||
|
processed = TRUE;
|
|||
|
break;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
_stprintf(fileName,TEXT("\\\\.\\"));
|
|||
|
_tcscat(fileName,buffer);
|
|||
|
|
|||
|
current.handle = CreateFile(fileName,
|
|||
|
GENERIC_READ,
|
|||
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|||
|
NULL,
|
|||
|
OPEN_EXISTING,
|
|||
|
FILE_ATTRIBUTE_NORMAL,
|
|||
|
NULL);
|
|||
|
|
|||
|
if (current.handle == INVALID_HANDLE_VALUE) {
|
|||
|
_stprintf(errorBuf,
|
|||
|
TEXT("Could not open drive: %s\n"),
|
|||
|
fileName);
|
|||
|
|
|||
|
_tcscpy(variables[0].text,TEXT(""));
|
|||
|
_tcscpy(variables[1].text,TEXT(""));
|
|||
|
|
|||
|
variables[0].length = _tcslen(variables[0].text);
|
|||
|
variables[1].length = _tcslen(variables[1].text);
|
|||
|
DrawString(&variables[0]);
|
|||
|
DrawString(&variables[1]);
|
|||
|
|
|||
|
MessageBox(NULL,
|
|||
|
errorBuf,
|
|||
|
TEXT("Error"),
|
|||
|
MB_ICONEXCLAMATION | MB_OK);
|
|||
|
|
|||
|
processed = TRUE;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Updates the displayed current drive
|
|||
|
//
|
|||
|
|
|||
|
_tcscpy(variables[0].text,&buffer[8]);
|
|||
|
variables[0].length = _tcslen(&buffer[8]);
|
|||
|
DrawString(&variables[0]);
|
|||
|
|
|||
|
noActive = SendDlgItemMessage(hDlg,
|
|||
|
IDC_SOURCE_DATA,
|
|||
|
LB_GETCURSEL,
|
|||
|
0,
|
|||
|
0);
|
|||
|
|
|||
|
errNum = SendDlgItemMessage(hDlg,
|
|||
|
IDC_SOURCE_DATA,
|
|||
|
LB_GETTEXT,
|
|||
|
noActive,
|
|||
|
(LPARAM) (LPCTSTR) buffer);
|
|||
|
|
|||
|
if (errNum == LB_ERR) {
|
|||
|
|
|||
|
_tcscpy(variables[0].text,TEXT(""));
|
|||
|
_tcscpy(variables[1].text,TEXT(""));
|
|||
|
|
|||
|
variables[0].length = _tcslen(variables[0].text);
|
|||
|
variables[1].length = _tcslen(variables[1].text);
|
|||
|
|
|||
|
DrawString(&variables[0]);
|
|||
|
DrawString(&variables[1]);
|
|||
|
|
|||
|
MessageBox(NULL,
|
|||
|
TEXT("Could not retrieve text selection from dialog"),
|
|||
|
TEXT("Error"),
|
|||
|
MB_ICONEXCLAMATION | MB_OK);
|
|||
|
|
|||
|
processed = TRUE;
|
|||
|
break;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
current.flags = type[noActive].flags;
|
|||
|
current.ioctl = type[noActive].ioctl;
|
|||
|
total.flags = type[noActive].flags;
|
|||
|
total.ioctl = type[noActive].ioctl;
|
|||
|
|
|||
|
if (!DeviceIoControl(current.handle,
|
|||
|
current.ioctl,
|
|||
|
NULL,
|
|||
|
0,
|
|||
|
&tempHist,
|
|||
|
sizeof(DISK_HISTOGRAM),
|
|||
|
&noActive,
|
|||
|
NULL)) {
|
|||
|
|
|||
|
if (GetLastError() == ERROR_INVALID_FUNCTION) {
|
|||
|
|
|||
|
MessageBox(NULL,
|
|||
|
TEXT("DeviceIoControl Request Failed"),
|
|||
|
TEXT("Error"),
|
|||
|
MB_ICONEXCLAMATION | MB_OK);
|
|||
|
|
|||
|
_tcscpy(variables[0].text,TEXT(""));
|
|||
|
_tcscpy(variables[1].text,TEXT(""));
|
|||
|
|
|||
|
variables[0].length = _tcslen(variables[0].text);
|
|||
|
variables[1].length = _tcslen(variables[1].text);
|
|||
|
|
|||
|
DrawString(&variables[0]);
|
|||
|
DrawString(&variables[1]);
|
|||
|
|
|||
|
CloseHandle(current.handle);
|
|||
|
EnableMenuItem (hMenuHandle,IDM_OPTIONS_START,MF_GRAYED);
|
|||
|
DrawMenuBar(hMainWnd);
|
|||
|
processed = TRUE;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
current.histogram = malloc( tempHist.Size * HISTOGRAM_BUCKET_SIZE + DISK_HISTOGRAM_SIZE);
|
|||
|
total.histogram = malloc( tempHist.Size * HISTOGRAM_BUCKET_SIZE + DISK_HISTOGRAM_SIZE);
|
|||
|
pHist = malloc( tempHist.Size * sizeof(ULONG) );
|
|||
|
pCurr = malloc( tempHist.Size * sizeof(ULONG) );
|
|||
|
|
|||
|
if (current.histogram == NULL || total.histogram == NULL || pHist == NULL || pCurr == NULL) {
|
|||
|
|
|||
|
MessageBox(NULL,
|
|||
|
TEXT("Could not allocate memory"),
|
|||
|
TEXT("Error"),
|
|||
|
MB_ICONEXCLAMATION | MB_OK);
|
|||
|
|
|||
|
_tcscpy(variables[0].text,TEXT(""));
|
|||
|
_tcscpy(variables[1].text,TEXT(""));
|
|||
|
|
|||
|
variables[0].length = _tcslen(variables[0].text);
|
|||
|
variables[1].length = _tcslen(variables[1].text);
|
|||
|
|
|||
|
DrawString(&variables[0]);
|
|||
|
DrawString(&variables[1]);
|
|||
|
|
|||
|
CloseHandle(current.handle);
|
|||
|
if (current.histogram) {
|
|||
|
free(current.histogram);
|
|||
|
}
|
|||
|
if (total.histogram) {
|
|||
|
free(total.histogram);
|
|||
|
}
|
|||
|
if (pHist) {
|
|||
|
free(pHist);
|
|||
|
}
|
|||
|
EnableMenuItem (hMenuHandle,IDM_OPTIONS_START,MF_GRAYED);
|
|||
|
DrawMenuBar(hMainWnd);
|
|||
|
processed = TRUE;
|
|||
|
break;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
memset(current.histogram,0, ( (tempHist.Size * HISTOGRAM_BUCKET_SIZE) + DISK_HISTOGRAM_SIZE) );
|
|||
|
memset(total.histogram, 0, ( (tempHist.Size * HISTOGRAM_BUCKET_SIZE) + DISK_HISTOGRAM_SIZE) );
|
|||
|
|
|||
|
current.histogram->Histogram = (PHISTOGRAM_BUCKET) ( ( char *) current.histogram + DISK_HISTOGRAM_SIZE);
|
|||
|
total.histogram->Histogram = (PHISTOGRAM_BUCKET) ( ( char *) total.histogram + DISK_HISTOGRAM_SIZE );
|
|||
|
total.histogram->Size = tempHist.Size;
|
|||
|
current.histogram->Size = tempHist.Size;
|
|||
|
total.histogram->Granularity = tempHist.Granularity;
|
|||
|
current.histogram->Granularity = tempHist.Granularity;
|
|||
|
total.histogram->DiskSize = tempHist.DiskSize;
|
|||
|
TotalWrite.QuadPart = TotalRead.QuadPart = TotalAvg.QuadPart = 0;
|
|||
|
CurrentWrite.QuadPart = CurrentRead.QuadPart = CurrentAvg.QuadPart = 0;
|
|||
|
|
|||
|
//
|
|||
|
// Reset the Max value in the histogram
|
|||
|
//
|
|||
|
|
|||
|
cMax = yaxisSize;
|
|||
|
|
|||
|
//
|
|||
|
// Display the new Xaxis
|
|||
|
//
|
|||
|
|
|||
|
DrawXaxis(total.histogram->Size);
|
|||
|
|
|||
|
//
|
|||
|
// Sets the Drive type text in the type window
|
|||
|
//
|
|||
|
|
|||
|
_tcscpy(variables[1].text,buffer);
|
|||
|
variables[1].length = _tcslen(buffer);
|
|||
|
DrawString(&variables[1]);
|
|||
|
|
|||
|
//
|
|||
|
// Reset all the other text windows
|
|||
|
//
|
|||
|
|
|||
|
for (i = 2; i < variablesSize; i++) {
|
|||
|
_tcscpy(variables[i].text,TEXT("0"));
|
|||
|
variables[i].length = _tcslen(variables[i].text);
|
|||
|
DrawString(&variables[i]);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Deliberate Fall-Through -- We want to get rid of the
|
|||
|
// dialog box
|
|||
|
//
|
|||
|
|
|||
|
case IDCANCEL:
|
|||
|
EndDialog(hDlg,TRUE);
|
|||
|
break;
|
|||
|
default:
|
|||
|
processed = FALSE;
|
|||
|
break;
|
|||
|
}
|
|||
|
default:
|
|||
|
processed = FALSE;
|
|||
|
break;
|
|||
|
}
|
|||
|
UpdateWindow(hMainWnd);
|
|||
|
return (processed);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
LRESULT WINAPI
|
|||
|
WndProc(
|
|||
|
HWND hwnd,
|
|||
|
UINT uMsg,
|
|||
|
WPARAM wParam,
|
|||
|
LPARAM lParam)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This is the main callback routine for the application. All API messages
|
|||
|
are processed by this routine.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hWnd The window which is affected by the message
|
|||
|
uMsg The message which has been sent to the window
|
|||
|
wParam Not Used
|
|||
|
lParam Not Used
|
|||
|
|
|||
|
Returns
|
|||
|
|
|||
|
0
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
switch(uMsg) {
|
|||
|
HANDLE_MSG(hwnd,WM_COMMAND, ProcessCommand);
|
|||
|
HANDLE_MSG(hwnd,WM_CREATE, ProcessCreate);
|
|||
|
HANDLE_MSG(hwnd,WM_PAINT, ProcessPaint);
|
|||
|
HANDLE_MSG(hwnd,WM_TIMER, ProcessTimer);
|
|||
|
HANDLE_MSG(hwnd,WM_DESTROY, ProcessDestroy);
|
|||
|
case WM_MOUSEACTIVATE:
|
|||
|
//
|
|||
|
// The right button temp. hides the window if topmost is
|
|||
|
// enabled. The window re-appears when right button is
|
|||
|
// released. When this happens, we don't want to activate
|
|||
|
// the window just before hiding it because it looks really
|
|||
|
// bad, so we intercept, the activate message.
|
|||
|
//
|
|||
|
if (GetAsyncKeyState(VK_RBUTTON) & 0x8000) {
|
|||
|
return (MA_NOACTIVATE);
|
|||
|
} else {
|
|||
|
goto DEFPROC;
|
|||
|
}
|
|||
|
break;
|
|||
|
case WM_INITMENU:
|
|||
|
PerfHist.bCantHide = TRUE;
|
|||
|
goto DEFPROC;
|
|||
|
case WM_MENUSELECT:
|
|||
|
if (LOWORD(lParam) == -1 && HIWORD(lParam) == 0) {
|
|||
|
PerfHist.bCantHide = FALSE;
|
|||
|
}
|
|||
|
goto DEFPROC;
|
|||
|
case WM_RBUTTONDOWN:
|
|||
|
case WM_NCRBUTTONDOWN:
|
|||
|
//
|
|||
|
// The right button temporarily hides the window, if the
|
|||
|
// window is topmost, and if no menu is currently 'active'.
|
|||
|
//
|
|||
|
|
|||
|
if (!PerfHist.bTmpHide && PerfHist.bTopMost && !PerfHist.bCantHide) {
|
|||
|
ShowWindow(hwnd,SW_HIDE);
|
|||
|
SetCapture(hwnd);
|
|||
|
PerfHist.bTmpHide = TRUE;
|
|||
|
}
|
|||
|
break;
|
|||
|
case WM_RBUTTONUP:
|
|||
|
case WM_NCRBUTTONUP:
|
|||
|
//
|
|||
|
// If the window is currently hidden, right button up brings it
|
|||
|
// back. We must make sure we show it in its previous state, ie:
|
|||
|
// minized, or normal.
|
|||
|
//
|
|||
|
if (PerfHist.bTmpHide) {
|
|||
|
ReleaseCapture();
|
|||
|
if (PerfHist.bIconic) {
|
|||
|
ShowWindow(hwnd,SW_SHOWMINNOACTIVE);
|
|||
|
} else {
|
|||
|
ShowWindow(hwnd,SW_SHOWNOACTIVATE);
|
|||
|
}
|
|||
|
PerfHist.bTmpHide = FALSE;
|
|||
|
}
|
|||
|
break;
|
|||
|
case WM_SIZE:
|
|||
|
//
|
|||
|
// If we are minimizing the window, then we should remember that.
|
|||
|
// Also, if we resize the window, we should remember that we are
|
|||
|
// no longer minized.
|
|||
|
//
|
|||
|
if (wParam == SIZE_MINIMIZED) {
|
|||
|
PerfHist.bIconic = TRUE;
|
|||
|
UpdateWindow(hwnd);
|
|||
|
} else if (PerfHist.bIconic) {
|
|||
|
InvalidateRect(hMainWnd,NULL,TRUE);
|
|||
|
PerfHist.bIconic = FALSE;
|
|||
|
UpdateWindow(hwnd);
|
|||
|
}
|
|||
|
break;
|
|||
|
case WM_KEYDOWN:
|
|||
|
//
|
|||
|
// ESC key toggles the menu/title bar (just like a double click
|
|||
|
// on the cline area of the window
|
|||
|
//
|
|||
|
if ( (wParam = VK_ESCAPE) && !(HIWORD(lParam) & 0x4000)) {
|
|||
|
goto TOGGLE_TITLE;
|
|||
|
}
|
|||
|
break;
|
|||
|
case WM_NCLBUTTONDBLCLK:
|
|||
|
if (!PerfHist.bNoTitle) {
|
|||
|
//
|
|||
|
// If we have title bars, etc, etc, let the normal stuff
|
|||
|
// take place.
|
|||
|
//
|
|||
|
goto DEFPROC;
|
|||
|
}
|
|||
|
//
|
|||
|
// Else: we don't have any title bars, etc, then this is
|
|||
|
// actually a request to bring the title bars back...
|
|||
|
//
|
|||
|
|
|||
|
/* Fall Through */
|
|||
|
case WM_LBUTTONDBLCLK:
|
|||
|
TOGGLE_TITLE:
|
|||
|
PerfHist.fDisplay = FALSE;
|
|||
|
PerfHist.bNoTitle = (PerfHist.bNoTitle ? FALSE : TRUE);
|
|||
|
SetMenuBar(hwnd); // This is the function that does the work
|
|||
|
break;
|
|||
|
case WM_NCHITTEST:
|
|||
|
//
|
|||
|
// If we have no title/menu bar, clicking and dragging the
|
|||
|
// client ara move sthe window. To do this, return HTCAPTION.
|
|||
|
// Note: dragging is not allowed if window maximized, or if
|
|||
|
// the caption bar is present.
|
|||
|
|
|||
|
wParam = DefWindowProc(hwnd,uMsg,wParam,lParam);
|
|||
|
if (PerfHist.bNoTitle && (wParam == HTCLIENT) && !IsZoomed(hwnd)) {
|
|||
|
return HTCAPTION;
|
|||
|
}
|
|||
|
return wParam;
|
|||
|
case WM_SYSCOMMAND:
|
|||
|
switch (wParam) {
|
|||
|
case SC_MINIMIZE:
|
|||
|
if (!IsZoomed(hwnd)) {
|
|||
|
GetWindowRect(hwnd,&rCoordRect);
|
|||
|
}
|
|||
|
if (PerfHist.bTopMost) {
|
|||
|
PerfHist.bTopMost = FALSE;
|
|||
|
PostMessage(hwnd,WM_SYSCOMMAND, IDM_TOPMOST, 0L);
|
|||
|
}
|
|||
|
break;
|
|||
|
case SC_MAXIMIZE:
|
|||
|
if (!IsIconic(hwnd)) {
|
|||
|
GetWindowRect(hwnd,&rCoordRect);
|
|||
|
}
|
|||
|
break;
|
|||
|
case IDM_TOPMOST: {
|
|||
|
HMENU hMenu;
|
|||
|
|
|||
|
hMenu = GetSystemMenu(hwnd,FALSE);
|
|||
|
if (PerfHist.bTopMost) {
|
|||
|
CheckMenuItem(hMenu,IDM_TOPMOST,MF_BYCOMMAND | MF_UNCHECKED);
|
|||
|
SetWindowPos(hwnd,HWND_NOTOPMOST,0,0,0,0,
|
|||
|
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
|
|||
|
PerfHist.bTopMost = FALSE;
|
|||
|
} else {
|
|||
|
CheckMenuItem(hMenu,IDM_TOPMOST,MF_BYCOMMAND | MF_CHECKED);
|
|||
|
SetWindowPos(hwnd,HWND_TOPMOST,0,0,0,0,
|
|||
|
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
|
|||
|
PerfHist.bTopMost = TRUE;
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
default:
|
|||
|
goto DEFPROC;
|
|||
|
}
|
|||
|
goto DEFPROC;
|
|||
|
default:
|
|||
|
DEFPROC:
|
|||
|
return (DefWindowProc(hwnd,uMsg,wParam,lParam));
|
|||
|
}
|
|||
|
|
|||
|
return 0;
|
|||
|
}
|