NT4/private/ntos/dd/histgram/cmd/perfhist/perfhist.c

2142 lines
47 KiB
C
Raw Normal View History

2001-01-01 00:00:00 +01:00
/*++
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;
}