NT4/private/sdktools/winmeter/data.c
2020-09-30 17:12:29 +02:00

497 lines
15 KiB
C

/***************************************************************************\
* data.c
*
* Microsoft Confidential
* Copyright (c) 1991 Microsoft Corporation
*
* Module to query system data for WINMETER application. . . builds database
*
* History:
* Written by Hadi Partovi (t-hadip) summer 1991
*
* Re-written and adapted for NT by Fran Borda (v-franb) Nov.1991
* for Newman Consulting
* Took out all WIN-specific and bargraph code. Added 3 new
* linegraphs (Mem/Paging, Process/Threads/Handles, IO), and
* tailored info to that available under NT.
\***************************************************************************/
#include "winmeter.h"
SYSTEM_PERFORMANCE_INFORMATION PerfInfo,PreviousPerfInfo;
OBJECT_BASIC_INFORMATION ObjectInfo;
ULONG A_PageCount,C_PageCount,F_PageCount;
ULONG ProcessCount,ThreadCount,FileHandleCount;
HANDLE NullDeviceHandle = NULL;
// main global information structures
extern GLOBAL g;
// global variables for this module
static BOOL fFirstTime=TRUE; // set to FALSE after first query
int do_procs = FALSE;
int do_mem = FALSE;
int win_on_top = FALSE;
int do_io = FALSE;
// internal functions in this module
void FreeLGS(void);
// Frees memory for linegraphs
void InitializeLineGraph(void);
// Initializes g.plgList - the three default linegraphs
void QueryThreadData(void);
// functions for linegraph: return values to be plotted
// these simply return plottable values from the database
VALUE valGiveCPUUsage(void);
#if 1
VALUE valGiveProcesses(void);
VALUE valGiveThreads(void);
VALUE valGiveFiles(void);
VALUE valGiveMemoryA(void);
VALUE valGiveMemoryC(void);
VALUE valGiveMemoryF(void);
VALUE valGiveIORead(void);
VALUE valGiveIOWrite(void);
VALUE valGiveIOOther(void);
#endif
/***************************************************************************\
* AllocLGValues()
*
* Entry: None
* Exit: Allocates memory for the stored values of a linegraph.
* If the linegraph already had memory allocated, the function
* reallocates the memory, clearing stored values
* Finally, sets various indices in the lg structure
\***************************************************************************/
void AllocLGValues(void)
{
PLGDATA plgd; // pointer to linegraph data
for (plgd=g.plg->plgd; plgd; plgd=plgd->plgdNext)
{
if (plgd->pValues)
// clear values
MemFree(plgd->pValues);
plgd->pValues = MemAlloc(sizeof(VALUE)*g.plg->nMaxValues);
}
// reset the line graph indices without redrawing it
ClearLineGraph();
return;
}
/***************************************************************************\
* DoUpdate()
*
* Entry: Three values: the delta value, the old queried value and the new value
* Exit: Updates the old value and the delta
* This is a macro for updating delta counters and cOld counters,
* but should eventually be changed so that both are part of one
* COUNTER structure, or something
\***************************************************************************/
#define DoUpdate(dwDelta, dwOld, dwNew) { \
dwDelta = dwNew - dwOld; \
dwOld = dwNew; }
// if dwNew < dwOldV, counter has rolled over, dwDelta should really
// evaluate to (dwNew + ULONG_MAX-dwOld).
// However, the two's complement method of subtraction ensures that
// -dwOld= ULONG_MAX-dwOld. Ergo, all is well, as long as the delta
// is stored in a DWORD
/***************************************************************************\
* FreeDatabaseMemory()
*
* Entry: none
* Exit: frees all memory used for database (before exiting)
\***************************************************************************/
void FreeDatabaseMemory(void)
{
// Free up linegraph memory
FreeLGS();
return;
}
/***************************************************************************\
* FreeLGValues()
*
* Entry: Flag, set if should free entire PLGDATA structure
* Exit: Frees the LGDATA linked list of the current linegraph
* This is used if the History option is off (g.fRemember==FALSE),
* to free one linegraph's memory when switching to displaying another
\***************************************************************************/
void FreeLGValues(
BOOL fFreeAll) // flag specifying whether to free everything
{
PLGDATA plgd1, plgd2; // pointers into linked list
for (plgd1=g.plg->plgd; plgd1; plgd1=plgd2)
{
plgd2 = plgd1->plgdNext;
if (plgd1->pValues)
{
MemFree(plgd1->pValues);
plgd1->pValues = NULL; // set to null so it isn't "freed" again
}
if (fFreeAll)
{
MemFree(plgd1->lpszDescription);
MemFree(plgd1);
}
}
return;
}
/***************************************************************************\
* FreeLGS()
*
* Entry: None
* Exit: Frees up all the memory held by all the linegraphs in memory
\***************************************************************************/
void FreeLGS(void)
{
PLGRAPH plgNext; // temporary pointer to linegraph
// go through all linegraphs in list
for (g.plg = g.plgList; g.plg; g.plg=plgNext)
{
FreeLGValues(TRUE);
plgNext = g.plg->plgNext;
MemFree(g.plg->lpszTitle);
MemFree(g.plg);
}
return;
}
/***************************************************************************\
* InitializeDatabase()
*
* Entry: None
* Exit: Initializes thread and process database for querying
* Allocates memory asnd sets up the line graph linked list
\***************************************************************************/
void InitializeDatabase(void)
{
InitializeLineGraph();
QueryThreadData();
return;
}
/***************************************************************************\
* InitializeLineGraph()
*
* Entry: None
* Exit: Initializes the global linegraph linked list
* Creates a linked list pointed to by g.plgList, and sets g.plg
* to the starting current linegraph.
\***************************************************************************/
void InitializeLineGraph(void)
{
g.plgCPU = g.plgList = MemAlloc(sizeof(LGRAPH));
g.plgProcs = g.plgCPU->plgNext = MemAlloc(sizeof(LGRAPH));
g.plgMemory = g.plgProcs->plgNext = MemAlloc(sizeof(LGRAPH));
g.plgIO = g.plgMemory->plgNext = MemAlloc(sizeof(LGRAPH));
g.plgIO->plgNext = NULL;
g.plgCPU->nLines = 1;
g.plgMemory->nLines = g.plgIO->nLines = g.plgProcs->nLines = 3;
// INITIALIZE CPU USAGE LINEGRAPH
g.plg = g.plgCPU;
g.plg->nDisplayValues = NO_VALUES_YET;
// load title
MyLoadString(IDS_CPU_USAGE);
g.plg->lpszTitle = MemAlloc(1 + lstrlen(g.szBuf));
lstrcpy(g.plg->lpszTitle, g.szBuf);
LoadLineGraphSettings();
// do line
g.plg->plgd = MemAlloc(sizeof(LGDATA));
MyLoadString(IDS_CPU);
g.plg->plgd->lpszDescription = MemAlloc(1+lstrlen(g.szBuf));
lstrcpy(g.plg->plgd->lpszDescription, g.szBuf);
g.plg->plgd->iColor = BLUE_INDEX;
g.plg->plgd->valNext = &valGiveCPUUsage;
g.plg->plgd->plgdNext = NULL;
AllocLGValues();
// INITIALIZE ProcThreadFile USAGE LINEGRAPH
g.plg = g.plgProcs;
g.plg->nDisplayValues = NO_VALUES_YET;
// load title
MyLoadString(IDS_PROC_INFO);
g.plg->lpszTitle = MemAlloc(1 + lstrlen(g.szBuf));
lstrcpy(g.plg->lpszTitle, g.szBuf);
LoadLineGraphSettings();
// first line
g.plg->plgd = MemAlloc(sizeof(LGDATA));
MyLoadString(IDS_PROCESSES);
g.plg->plgd->lpszDescription = MemAlloc(1+lstrlen(g.szBuf));
lstrcpy(g.plg->plgd->lpszDescription, g.szBuf);
g.plg->plgd->iColor = RED_INDEX;
g.plg->plgd->valNext = &valGiveProcesses;
// second line
g.plg->plgd->plgdNext = MemAlloc(sizeof(LGDATA));
MyLoadString(IDS_THREADS);
g.plg->plgd->plgdNext->lpszDescription = MemAlloc(1+lstrlen(g.szBuf));
lstrcpy(g.plg->plgd->plgdNext->lpszDescription, g.szBuf);
g.plg->plgd->plgdNext->iColor = GREEN_INDEX;
g.plg->plgd->plgdNext->valNext = &valGiveThreads;
// third line
g.plg->plgd->plgdNext->plgdNext = MemAlloc(sizeof(LGDATA));
MyLoadString(IDS_FILES);
g.plg->plgd->plgdNext->plgdNext->lpszDescription =
MemAlloc(1+lstrlen(g.szBuf));
lstrcpy(g.plg->plgd->plgdNext->plgdNext->lpszDescription, g.szBuf);
g.plg->plgd->plgdNext->plgdNext->iColor = BLUE_INDEX;
g.plg->plgd->plgdNext->plgdNext->valNext = &valGiveFiles;
g.plg->plgd->plgdNext->plgdNext->plgdNext = NULL;
AllocLGValues();
// INITIALIZE MEMORY USAGE LINEGRAPH
g.plg = g.plgMemory;
g.plg->nDisplayValues = NO_VALUES_YET;
// load title
MyLoadString(IDS_MEMORY_USAGE);
g.plg->lpszTitle = MemAlloc(1 + lstrlen(g.szBuf));
lstrcpy(g.plg->lpszTitle, g.szBuf);
LoadLineGraphSettings();
// first line
g.plg->plgd = MemAlloc(sizeof(LGDATA));
MyLoadString(IDS_AVAILPAGES);
g.plg->plgd->lpszDescription = MemAlloc(1+lstrlen(g.szBuf));
lstrcpy(g.plg->plgd->lpszDescription, g.szBuf);
g.plg->plgd->iColor = RED_INDEX;
g.plg->plgd->valNext = &valGiveMemoryA;
// second line
g.plg->plgd->plgdNext = MemAlloc(sizeof(LGDATA));
MyLoadString(IDS_COMMITPAGES);
g.plg->plgd->plgdNext->lpszDescription = MemAlloc(1+lstrlen(g.szBuf));
lstrcpy(g.plg->plgd->plgdNext->lpszDescription, g.szBuf);
g.plg->plgd->plgdNext->iColor = GREEN_INDEX;
g.plg->plgd->plgdNext->valNext = &valGiveMemoryC;
// third line
g.plg->plgd->plgdNext->plgdNext = MemAlloc(sizeof(LGDATA));
MyLoadString(IDS_PAGEFAULTS);
g.plg->plgd->plgdNext->plgdNext->lpszDescription =
MemAlloc(1+lstrlen(g.szBuf));
lstrcpy(g.plg->plgd->plgdNext->plgdNext->lpszDescription, g.szBuf);
g.plg->plgd->plgdNext->plgdNext->iColor = BLUE_INDEX;
g.plg->plgd->plgdNext->plgdNext->valNext = &valGiveMemoryF;
g.plg->plgd->plgdNext->plgdNext->plgdNext = NULL;
AllocLGValues();
// INITIALIZE IO USAGE LINEGRAPH
g.plg = g.plgIO;
g.plg->nDisplayValues = NO_VALUES_YET;
// load title
MyLoadString(IDS_IO_USAGE);
g.plg->lpszTitle = MemAlloc(1 + lstrlen(g.szBuf));
lstrcpy(g.plg->lpszTitle, g.szBuf);
LoadLineGraphSettings();
// first line
g.plg->plgd = MemAlloc(sizeof(LGDATA));
MyLoadString(IDS_IO_READS);
g.plg->plgd->lpszDescription = MemAlloc(1+lstrlen(g.szBuf));
lstrcpy(g.plg->plgd->lpszDescription, g.szBuf);
g.plg->plgd->iColor = RED_INDEX;
g.plg->plgd->valNext = &valGiveIORead;
// second line
g.plg->plgd->plgdNext = MemAlloc(sizeof(LGDATA));
MyLoadString(IDS_IO_WRITES);
g.plg->plgd->plgdNext->lpszDescription = MemAlloc(1+lstrlen(g.szBuf));
lstrcpy(g.plg->plgd->plgdNext->lpszDescription, g.szBuf);
g.plg->plgd->plgdNext->iColor = GREEN_INDEX;
g.plg->plgd->plgdNext->valNext = &valGiveIOWrite;
// third line
g.plg->plgd->plgdNext->plgdNext = MemAlloc(sizeof(LGDATA));
MyLoadString(IDS_IO_OTHER);
g.plg->plgd->plgdNext->plgdNext->lpszDescription =
MemAlloc(1+lstrlen(g.szBuf));
lstrcpy(g.plg->plgd->plgdNext->plgdNext->lpszDescription, g.szBuf);
g.plg->plgd->plgdNext->plgdNext->iColor = BLUE_INDEX;
g.plg->plgd->plgdNext->plgdNext->valNext = &valGiveIOOther;
g.plg->plgd->plgdNext->plgdNext->plgdNext = NULL;
AllocLGValues();
return;
}
/***************************************************************************\
* QueryGlobalData()
*
* Entry: None
* Exit: Queries globabl data
\***************************************************************************/
void QueryGlobalData(void)
{
// Query System for global info
NtQuerySystemInformation(SystemPerformanceInformation,
&PerfInfo,
sizeof(PerfInfo),
NULL
);
return;
}
/***************************************************************************\
* QueryThreadData()
*
* Entry: None
* Exit: Queries thread data
*
\***************************************************************************/
void QueryThreadData(void)
{
// in case this was the first query, (from InitializeDatabase()),
// clear fFirstTime flag to signify that initialization query is over
fFirstTime = FALSE;
NtQueryObject(NtCurrentProcess(),ObjectBasicInformation,
&ObjectInfo,sizeof(ObjectInfo),NULL);
ProcessCount = ObjectInfo.NumberOfObjects;
NtQueryObject(NtCurrentThread(),ObjectBasicInformation,
&ObjectInfo,sizeof(ObjectInfo),NULL);
ThreadCount = ObjectInfo.NumberOfObjects;
NtQueryObject(NullDeviceHandle,ObjectBasicInformation,
&ObjectInfo,sizeof(ObjectInfo),NULL);
#if 0
// Currently, this always matches the ThreadCount, which seems odd,
// so we'll display the TotalHandleCount for now.
FileHandleCount = ObjectInfo.NumberOfObjects;
#else
FileHandleCount = ObjectInfo.TotalHandleCount;
#endif
return;
}
/***************************************************************************\
* valGiveCPUUsage()
*
* Entry: none
* Exit: Gives % value of CPU Tics that are not idle - linegraph fxn
\***************************************************************************/
VALUE valGiveCPUUsage(void)
{
LARGE_INTEGER EndTime,
BeginTime,
ElapsedTime,
PercentIdle,
DelayTimeTicks;
DelayTimeTicks = RtlExtendedIntegerMultiply(
RtlConvertUlongToLargeInteger(g.nTimerInterval),
(ULONG)10000);
EndTime = *(PLARGE_INTEGER)&PerfInfo.IdleProcessTime;
BeginTime = *(PLARGE_INTEGER)&PreviousPerfInfo.IdleProcessTime;
ElapsedTime = RtlLargeIntegerSubtract(EndTime,BeginTime);
PercentIdle = RtlLargeIntegerDivide(
// Multiply the elapsed time by 100 to retain some
// precision.
RtlExtendedIntegerMultiply(ElapsedTime,(ULONG)100),
// Then divide by the delay and ignore any remainder.
DelayTimeTicks, NULL);
if (PercentIdle.LowPart > 100)
PercentIdle.LowPart = 0;
return (100 - PercentIdle.LowPart) ;
}
VALUE valGiveProcesses(void)
{
return (ProcessCount);
}
VALUE valGiveThreads(void)
{
return(ThreadCount);
}
VALUE valGiveFiles(void)
{
return(FileHandleCount);
}
VALUE valGiveMemoryA(void)
{
return((PerfInfo.AvailablePages/10) > M_DEFAULT_DVAL_AXISHEIGHT ?
M_DEFAULT_DVAL_AXISHEIGHT : (PerfInfo.AvailablePages/10));
}
VALUE valGiveMemoryC(void)
{
return((PerfInfo.CommittedPages/10) > M_DEFAULT_DVAL_AXISHEIGHT ?
M_DEFAULT_DVAL_AXISHEIGHT : (PerfInfo.CommittedPages/10));
}
VALUE valGiveMemoryF(void)
{
return((PerfInfo.PageFaultCount - PreviousPerfInfo.PageFaultCount)
> M_DEFAULT_DVAL_AXISHEIGHT ? M_DEFAULT_DVAL_AXISHEIGHT :
(PerfInfo.PageFaultCount - PreviousPerfInfo.PageFaultCount));
}
VALUE valGiveIORead(void)
{
return((PerfInfo.IoReadOperationCount - PreviousPerfInfo.IoReadOperationCount)
> I_DEFAULT_DVAL_AXISHEIGHT ? I_DEFAULT_DVAL_AXISHEIGHT :
(PerfInfo.IoReadOperationCount - PreviousPerfInfo.IoReadOperationCount));
}
VALUE valGiveIOWrite(void)
{
return((PerfInfo.IoWriteOperationCount - PreviousPerfInfo.IoWriteOperationCount)
> I_DEFAULT_DVAL_AXISHEIGHT ? I_DEFAULT_DVAL_AXISHEIGHT :
(PerfInfo.IoWriteOperationCount - PreviousPerfInfo.IoWriteOperationCount));
}
VALUE valGiveIOOther(void)
{
return((PerfInfo.IoOtherOperationCount - PreviousPerfInfo.IoOtherOperationCount)
> I_DEFAULT_DVAL_AXISHEIGHT ? I_DEFAULT_DVAL_AXISHEIGHT :
(PerfInfo.IoOtherOperationCount - PreviousPerfInfo.IoOtherOperationCount));
}