mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2309 lines
61 KiB
2309 lines
61 KiB
/*****************************************************************************
|
|
*
|
|
* Report.c - This file contains the report window handler. Some of the
|
|
* support routines are in RptFct.c
|
|
*
|
|
* Microsoft Confidential
|
|
* Copyright (c) 1992-1993 Microsoft Corporation
|
|
*
|
|
* Author -
|
|
*
|
|
* Hon-Wah Chan
|
|
*
|
|
****************************************************************************/
|
|
|
|
#include "perfmon.h"
|
|
#include <stdio.h> // for sprintf
|
|
#include <string.h> // for strncpy
|
|
#include "report.h" // Exported declarations for this file
|
|
|
|
#include "addline.h" // for AddLine, EditLine
|
|
#include "perferr.h" // for PostError
|
|
#include "fileutil.h" // for FileHandleCreate
|
|
#include "line.h" // for LineAppend
|
|
#include "pmemory.h" // for MemoryXXX (mallloc-type) routines
|
|
#include "perfdata.h" // for UpdateLines
|
|
#include "perfmops.h" // for DoWindowDrag
|
|
#include "playback.h" // for PlaybackLines, PlayingBackLog
|
|
#include "system.h" // for SystemGet
|
|
#include "utils.h"
|
|
#include "menuids.h" // for IDM_VIEWREPORT
|
|
#include "fileopen.h" // for FileGetName
|
|
#include "counters.h" // for CounterEntry
|
|
|
|
|
|
//==========================================================================//
|
|
// Local Data //
|
|
//==========================================================================//
|
|
|
|
TCHAR szSystemFormat [ResourceStringLen] ;
|
|
TCHAR szObjectFormat [ResourceStringLen] ;
|
|
|
|
|
|
//=============================//
|
|
// Report Class //
|
|
//=============================//
|
|
|
|
TCHAR szReportWindowClass[] = TEXT("PerfRpt") ;
|
|
#define dwReportClassStyle (CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS)
|
|
#define iReportClassExtra (0)
|
|
#define iReportWindowExtra (0)
|
|
#define dwReportWindowStyle (WS_CHILD | WS_VSCROLL | WS_HSCROLL)
|
|
|
|
|
|
#define szValuePlaceholder TEXT("-999999999.999")
|
|
#define szValueLargeHexPlaceholder TEXT(" xBBBBBBBBDDDDDDDD")
|
|
|
|
#define szHexFormat TEXT("x%08lX")
|
|
#define szLargeHexFormat TEXT("x%08lX%08lX")
|
|
#define szLargeValueFormat TEXT("%12.0f")
|
|
#define eStatusLargeValueMax ((FLOAT) 999999999.0)
|
|
#define szValueFormat TEXT("%12.3f")
|
|
|
|
|
|
//==========================================================================//
|
|
// Local Functions //
|
|
//==========================================================================//
|
|
|
|
|
|
PREPORT
|
|
AllocateReportData (
|
|
HWND hWndReport
|
|
)
|
|
{
|
|
PREPORT pReport ;
|
|
|
|
pReport = ReportData (hWndReport) ;
|
|
|
|
pReport->hWnd = hWndReport ;
|
|
pReport->iStatus = iPMStatusClosed ;
|
|
pReport->bManualRefresh = FALSE ;
|
|
pReport->bModified = FALSE ;
|
|
|
|
pReport->Visual.iColorIndex = 0 ;
|
|
pReport->Visual.iWidthIndex = -1 ;
|
|
pReport->Visual.iStyleIndex = -1 ;
|
|
|
|
pReport->iIntervalMSecs = iDefaultReportIntervalSecs * 1000 ;
|
|
pReport->pSystemFirst = NULL ;
|
|
pReport->pLineFirst = NULL ;
|
|
pReport->pLineLast = NULL ;
|
|
|
|
pReport->CurrentItemType = REPORT_TYPE_NOTHING ;
|
|
pReport->CurrentItem.pLine = NULL ;
|
|
|
|
return (pReport) ;
|
|
}
|
|
|
|
|
|
void FreeReportData (PREPORT pReport) {}
|
|
|
|
void
|
|
ReportLineAppend (
|
|
PREPORT pReport,
|
|
PLINE pLineNew
|
|
)
|
|
{
|
|
if (pReport->pLineFirst == NULL) {
|
|
pReport->pLineLast =
|
|
pReport->pLineFirst = pLineNew ;
|
|
} else {
|
|
(pReport->pLineLast)->pLineNext = pLineNew ;
|
|
pReport->pLineLast = pLineNew;
|
|
}
|
|
}
|
|
|
|
|
|
BOOL
|
|
LineCounterRemove (
|
|
PCOUNTERGROUP pCGroup,
|
|
PLINE pLineRemove
|
|
)
|
|
{
|
|
PLINE pLine ;
|
|
|
|
if (pCGroup->pLineFirst == pLineRemove) {
|
|
pCGroup->pLineFirst = (pCGroup->pLineFirst)->pLineCounterNext ;
|
|
return (TRUE) ;
|
|
}
|
|
|
|
for (pLine = pCGroup->pLineFirst ;
|
|
pLine->pLineCounterNext ;
|
|
pLine = pLine->pLineCounterNext) { // for
|
|
if (pLine->pLineCounterNext == pLineRemove) {
|
|
pLine->pLineCounterNext = pLineRemove->pLineCounterNext ;
|
|
if (pLineRemove == pCGroup->pLineLast) {
|
|
pCGroup->pLineLast = pLine;
|
|
}
|
|
return (TRUE) ;
|
|
}
|
|
}
|
|
|
|
return (FALSE) ;
|
|
}
|
|
|
|
|
|
void
|
|
DrawCounter (
|
|
HDC hDC,
|
|
PREPORT pReport,
|
|
PCOUNTERGROUP pCounterGroup
|
|
)
|
|
{
|
|
RECT Rect ;
|
|
|
|
if (!pCounterGroup->pLineFirst)
|
|
return ;
|
|
|
|
SelectFont (hDC, pReport->hFont) ;
|
|
TextOut (hDC, xCounterMargin, pCounterGroup->yLine,
|
|
pCounterGroup->pLineFirst->lnCounterName,
|
|
lstrlen (pCounterGroup->pLineFirst->lnCounterName)) ;
|
|
|
|
if (pCounterGroup == pReport->CurrentItem.pCounter) {
|
|
ReportCounterRect (pReport, pCounterGroup, &Rect) ;
|
|
DrawFocusRect (hDC, &Rect) ;
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
DrawObject (
|
|
HDC hDC,
|
|
PREPORT pReport,
|
|
POBJECTGROUP pObjectGroup
|
|
)
|
|
{
|
|
TCHAR szLine [LongTextLen] ;
|
|
PCOUNTERGROUP pCounterGroup ;
|
|
PCOLUMNGROUP pColumnGroup ;
|
|
|
|
if (!pObjectGroup->pCounterGroupFirst) {
|
|
return ;
|
|
}
|
|
|
|
SelectFont (hDC, pReport->hFontHeaders) ;
|
|
|
|
SetTextAlign (hDC, TA_RIGHT) ;
|
|
|
|
for (pColumnGroup = pObjectGroup->pColumnGroupFirst ;
|
|
pColumnGroup ;
|
|
pColumnGroup = pColumnGroup->pColumnGroupNext) {
|
|
// Draw Parent
|
|
if (pColumnGroup->lpszParentName)
|
|
TextOut (hDC,
|
|
ValueMargin (pReport) +
|
|
pColumnGroup->xPos + pColumnGroup->xWidth,
|
|
pObjectGroup->yFirstLine - pReport->yLineHeight,
|
|
pColumnGroup->lpszParentName,
|
|
lstrlen (pColumnGroup->lpszParentName)) ;
|
|
|
|
// Draw Instance
|
|
if (pColumnGroup->lpszInstanceName) {
|
|
TextOut (hDC,
|
|
ValueMargin (pReport) +
|
|
pColumnGroup->xPos + pColumnGroup->xWidth,
|
|
pObjectGroup->yFirstLine,
|
|
pColumnGroup->lpszInstanceName,
|
|
lstrlen (pColumnGroup->lpszInstanceName)) ;
|
|
}
|
|
|
|
if (pColumnGroup == pReport->CurrentItem.pColumn) {
|
|
RECT Rect ;
|
|
|
|
ReportColumnRect (pReport, pColumnGroup, &Rect) ;
|
|
DrawFocusRect (hDC, &Rect) ;
|
|
}
|
|
|
|
}
|
|
SetTextAlign (hDC, TA_LEFT) ;
|
|
|
|
TSPRINTF (szLine, szObjectFormat, pObjectGroup->lpszObjectName) ;
|
|
TextOut (hDC,
|
|
xObjectMargin, pObjectGroup->yFirstLine,
|
|
szLine, lstrlen (szLine)) ;
|
|
|
|
if (pObjectGroup == pReport->CurrentItem.pObject) {
|
|
RECT Rect ;
|
|
|
|
ReportObjectRect (pReport, pObjectGroup, &Rect) ;
|
|
DrawFocusRect (hDC, &Rect) ;
|
|
}
|
|
|
|
SelectFont (hDC, pReport->hFont) ;
|
|
|
|
for (pCounterGroup = pObjectGroup->pCounterGroupFirst;
|
|
pCounterGroup;
|
|
pCounterGroup = pCounterGroup->pCounterGroupNext) {
|
|
DrawCounter (hDC, pReport, pCounterGroup) ;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void
|
|
DrawSystem (
|
|
HDC hDC,
|
|
PREPORT pReport,
|
|
PSYSTEMGROUP pSystemGroup
|
|
)
|
|
{
|
|
TCHAR szLine [LongTextLen] ;
|
|
POBJECTGROUP pObjectGroup ;
|
|
|
|
SelectFont (hDC, pReport->hFontHeaders) ;
|
|
|
|
if (!pSystemGroup->pObjectGroupFirst)
|
|
return ;
|
|
|
|
SetTextAlign (hDC, TA_LEFT) ;
|
|
TSPRINTF (szLine, szSystemFormat, pSystemGroup->lpszSystemName) ;
|
|
TextOut (hDC,
|
|
xSystemMargin, pSystemGroup->yFirstLine,
|
|
szLine, lstrlen (szLine)) ;
|
|
|
|
if (pSystemGroup == pReport->CurrentItem.pSystem) {
|
|
RECT Rect ;
|
|
|
|
ReportSystemRect (pReport, pSystemGroup, &Rect) ;
|
|
DrawFocusRect (hDC, &Rect) ;
|
|
}
|
|
|
|
for (pObjectGroup = pSystemGroup->pObjectGroupFirst ;
|
|
pObjectGroup ;
|
|
pObjectGroup = pObjectGroup->pObjectGroupNext) {
|
|
DrawObject (hDC, pReport, pObjectGroup) ;
|
|
}
|
|
}
|
|
|
|
void
|
|
DrawReportValue (
|
|
HDC hDC,
|
|
PREPORT pReport,
|
|
PLINE pLine
|
|
)
|
|
{
|
|
TCHAR szValue [20] ;
|
|
FLOAT eValue ;
|
|
RECT rectValue ;
|
|
|
|
// skip until we have collect enough samples for the first data
|
|
if (pLine->bFirstTime == 0) {
|
|
eValue = CounterEntry (pLine) ;
|
|
if (pLine->lnCounterType == PERF_COUNTER_RAWCOUNT_HEX ||
|
|
pLine->lnCounterType == PERF_COUNTER_LARGE_RAWCOUNT_HEX) {
|
|
if (pLine->lnCounterType == PERF_COUNTER_RAWCOUNT_HEX ||
|
|
pLine->lnaCounterValue[0].HighPart == 0) {
|
|
TSPRINTF (szValue,
|
|
szHexFormat,
|
|
pLine->lnaCounterValue[0].LowPart) ;
|
|
} else {
|
|
TSPRINTF (szValue,
|
|
szLargeHexFormat,
|
|
pLine->lnaCounterValue[0].HighPart,
|
|
pLine->lnaCounterValue[0].LowPart) ;
|
|
}
|
|
} else {
|
|
TSPRINTF (szValue,
|
|
(eValue > eStatusLargeValueMax) ?
|
|
szLargeValueFormat : szValueFormat,
|
|
eValue) ;
|
|
ConvertDecimalPoint (szValue) ;
|
|
}
|
|
} else {
|
|
// draw "- - - -"
|
|
lstrcpy(szValue, DashLine);
|
|
}
|
|
|
|
ReportLineValueRect (pReport, pLine, &rectValue) ;
|
|
|
|
ExtTextOut (hDC,
|
|
rectValue.right - 2, rectValue.top,
|
|
ETO_CLIPPED | ETO_OPAQUE,
|
|
&rectValue,
|
|
szValue, lstrlen (szValue), NULL) ;
|
|
|
|
if (pReport->CurrentItemType == REPORT_TYPE_LINE &&
|
|
pLine == pReport->CurrentItem.pLine) {
|
|
DrawFocusRect (hDC, &rectValue) ;
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
DrawReportValues (
|
|
HDC hDC,
|
|
PREPORT pReport
|
|
)
|
|
{
|
|
PSYSTEMGROUP pSystemGroup ;
|
|
POBJECTGROUP pObjectGroup ;
|
|
PCOUNTERGROUP pCounterGroup ;
|
|
PLINE pLine ;
|
|
|
|
SelectFont (hDC, pReport->hFont) ;
|
|
SetTextAlign (hDC, TA_RIGHT) ;
|
|
|
|
for (pSystemGroup = pReport->pSystemGroupFirst ;
|
|
pSystemGroup ;
|
|
pSystemGroup = pSystemGroup->pSystemGroupNext) {
|
|
for (pObjectGroup = pSystemGroup->pObjectGroupFirst ;
|
|
pObjectGroup ;
|
|
pObjectGroup = pObjectGroup->pObjectGroupNext) {
|
|
for (pCounterGroup = pObjectGroup->pCounterGroupFirst ;
|
|
pCounterGroup ;
|
|
pCounterGroup = pCounterGroup->pCounterGroupNext) {
|
|
for (pLine = pCounterGroup->pLineFirst ;
|
|
pLine ;
|
|
pLine = pLine->pLineCounterNext) {
|
|
DrawReportValue (hDC, pReport, pLine) ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void
|
|
DrawReportHeaders (
|
|
HDC hDC,
|
|
PREPORT pReport
|
|
)
|
|
{
|
|
PSYSTEMGROUP pSystemGroup ;
|
|
|
|
for (pSystemGroup = pReport->pSystemGroupFirst ;
|
|
pSystemGroup ;
|
|
pSystemGroup = pSystemGroup->pSystemGroupNext) {
|
|
DrawSystem (hDC, pReport, pSystemGroup) ;
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
DrawReport (
|
|
HDC hDC,
|
|
PREPORT pReport
|
|
)
|
|
{
|
|
SetBkColor (hDC, GetSysColor(COLOR_WINDOW)) ;
|
|
DrawReportHeaders (hDC, pReport) ;
|
|
//UpdateLines (&(pReport->pSystemFirst), pReport->pLineFirst) ;
|
|
DrawReportValues (hDC, pReport) ;
|
|
}
|
|
|
|
|
|
|
|
void
|
|
SetLinePosition (
|
|
HDC hDC,
|
|
PREPORT pReport,
|
|
POBJECTGROUP pObjectGroup,
|
|
PLINE pLine
|
|
)
|
|
{
|
|
PCOLUMNGROUP pColumnGroup ;
|
|
|
|
pColumnGroup = GetColumnGroup (pReport, pObjectGroup, pLine) ;
|
|
if (!pColumnGroup) {
|
|
pLine->xReportPos = 0 ;
|
|
pLine->iReportColumn = -1 ;
|
|
} else {
|
|
pLine->xReportPos = pColumnGroup->xPos ;
|
|
pLine->iReportColumn = pColumnGroup->ColumnNumber ;
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
SetCounterPositions (
|
|
HDC hDC,
|
|
PREPORT pReport,
|
|
POBJECTGROUP pObjectGroup,
|
|
PCOUNTERGROUP pCounterGroup,
|
|
int yLine
|
|
)
|
|
{
|
|
PLINE pLine ;
|
|
int yPos ;
|
|
|
|
|
|
if (!pCounterGroup->pLineFirst)
|
|
return ;
|
|
|
|
yPos = pCounterGroup->yLine ;
|
|
|
|
SelectFont (hDC, pReport->hFontHeaders) ;
|
|
|
|
for (pLine = pCounterGroup->pLineFirst ;
|
|
pLine ;
|
|
pLine = pLine->pLineCounterNext) {
|
|
SetLinePosition (hDC, pReport, pObjectGroup, pLine) ;
|
|
pLine->yReportPos = yPos ;
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
SetColumnPositions (
|
|
HDC hDC,
|
|
PREPORT pReport,
|
|
POBJECTGROUP pObjectGroup
|
|
)
|
|
{
|
|
int xPos ;
|
|
PCOLUMNGROUP pColumnGroup ;
|
|
|
|
xPos = 0 ;
|
|
for (pColumnGroup = pObjectGroup->pColumnGroupFirst ;
|
|
pColumnGroup ;
|
|
pColumnGroup = pColumnGroup->pColumnGroupNext) {
|
|
pColumnGroup->xWidth = max (max (pColumnGroup->ParentNameTextWidth,
|
|
pColumnGroup->InstanceNameTextWidth),
|
|
pReport->xValueWidth) ;
|
|
pColumnGroup->xPos = xPos ;
|
|
pColumnGroup->yFirstLine = pObjectGroup->yFirstLine ;
|
|
xPos += (pColumnGroup->xWidth + xColumnMargin) ;
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
SetObjectPositions (
|
|
HDC hDC,
|
|
PREPORT pReport,
|
|
POBJECTGROUP pObjectGroup,
|
|
int yLine
|
|
)
|
|
/*
|
|
Effect: Determine and set the logical coordinates for the
|
|
object pObject within the report pReport.
|
|
|
|
For each instance x counter, determine the appropriate
|
|
column, adding a column description to the object if
|
|
needed.
|
|
|
|
Called By: SetSystemPositions only.
|
|
|
|
See Also: SetSystemPositions, SetCounterPositions, ColumnGroup.
|
|
*/
|
|
{
|
|
PCOUNTERGROUP pCounterGroup ;
|
|
int yPos ;
|
|
PLINE pLine ;
|
|
|
|
// check if there is parent name for this object type
|
|
// if so, need to add extra space for the parent name
|
|
if (pObjectGroup->pCounterGroupFirst) {
|
|
pCounterGroup = pObjectGroup->pCounterGroupFirst ;
|
|
pLine = pCounterGroup->pLineFirst ;
|
|
if (pLine && LineParentName(pLine)) {
|
|
pObjectGroup->yFirstLine += yLine ;
|
|
}
|
|
}
|
|
|
|
SetColumnPositions (hDC, pReport, pObjectGroup) ;
|
|
|
|
yPos = pObjectGroup->yFirstLine + yLine ;
|
|
|
|
for (pCounterGroup = pObjectGroup->pCounterGroupFirst ;
|
|
pCounterGroup ;
|
|
pCounterGroup = pCounterGroup->pCounterGroupNext) {
|
|
pCounterGroup->yLine = yPos + yLine ;
|
|
|
|
SetCounterPositions (hDC, pReport, pObjectGroup, pCounterGroup, yLine) ;
|
|
|
|
yPos = pCounterGroup->yLine ;
|
|
}
|
|
|
|
pObjectGroup->yLastLine = yPos + yLine ;
|
|
}
|
|
|
|
|
|
void
|
|
SetSystemPositions (
|
|
HDC hDC,
|
|
PREPORT pReport,
|
|
PSYSTEMGROUP pSystemGroup,
|
|
int yLine
|
|
)
|
|
{
|
|
POBJECTGROUP pObjectGroup ;
|
|
int yPos ;
|
|
|
|
yPos = pSystemGroup->yFirstLine ;
|
|
|
|
for (pObjectGroup = pSystemGroup->pObjectGroupFirst ;
|
|
pObjectGroup ;
|
|
pObjectGroup = pObjectGroup->pObjectGroupNext) {
|
|
pObjectGroup->yFirstLine = yPos + yLine ;
|
|
|
|
SetObjectPositions (hDC, pReport, pObjectGroup, yLine) ;
|
|
|
|
yPos = pObjectGroup->yLastLine ;
|
|
}
|
|
|
|
pSystemGroup->yLastLine = yPos + yLine ;
|
|
}
|
|
|
|
|
|
void
|
|
static
|
|
SetScrollRanges (
|
|
HWND hWnd
|
|
)
|
|
{
|
|
PREPORT pReport ;
|
|
RECT rectClient ;
|
|
int xWidth, yHeight ;
|
|
|
|
GetClientRect (hWnd, &rectClient) ;
|
|
xWidth = rectClient.right - rectClient.left ;
|
|
yHeight = rectClient.bottom - rectClient.top ;
|
|
|
|
pReport = ReportData (hWnd) ;
|
|
|
|
SetScrollRange (hWnd, SB_VERT,
|
|
0, max (0, pReport->yHeight - yHeight),
|
|
TRUE) ;
|
|
SetScrollRange (hWnd, SB_HORZ,
|
|
0, max (0, pReport->xWidth - xWidth),
|
|
TRUE) ;
|
|
}
|
|
|
|
//==========================================================================//
|
|
// Message Handlers //
|
|
//==========================================================================//
|
|
|
|
|
|
void
|
|
static
|
|
OnCreate (
|
|
HWND hWnd
|
|
)
|
|
{
|
|
HDC hDC ;
|
|
PREPORT pReport ;
|
|
|
|
pReport = AllocateReportData (hWnd) ;
|
|
if (!pReport)
|
|
return ;
|
|
|
|
pReport->hFont = hFontScales ;
|
|
pReport->hFontHeaders = hFontScalesBold ;
|
|
|
|
pReport->pLineFirst = NULL ;
|
|
pReport->pSystemFirst = NULL ;
|
|
|
|
pReport->pSystemGroupFirst = NULL ;
|
|
|
|
hDC = GetDC (hWnd) ;
|
|
|
|
SelectFont (hDC, pReport->hFont) ;
|
|
|
|
|
|
pReport->yLineHeight = FontHeight (hDC, TRUE) ;
|
|
pReport->xValueWidth = TextWidth (hDC, szValuePlaceholder) ;
|
|
ReleaseDC (hWnd, hDC) ;
|
|
|
|
pReport->xWidth = 0 ;
|
|
pReport->yHeight = 0 ;
|
|
|
|
StringLoad (IDS_SYSTEMFORMAT, szSystemFormat) ;
|
|
StringLoad (IDS_OBJECTFORMAT, szObjectFormat) ;
|
|
}
|
|
|
|
|
|
void
|
|
static
|
|
OnPaint (
|
|
HWND hWnd
|
|
)
|
|
{
|
|
HDC hDC ;
|
|
PAINTSTRUCT ps ;
|
|
PREPORT pReport ;
|
|
|
|
|
|
|
|
pReport = ReportData (hWnd) ;
|
|
|
|
hDC = BeginPaint (hWnd, &ps) ;
|
|
//hDC = hReportDC ;
|
|
SetWindowOrgEx (hDC,
|
|
GetScrollPos (hWnd, SB_HORZ),
|
|
GetScrollPos (hWnd, SB_VERT),
|
|
NULL) ;
|
|
|
|
DrawReport (hDC, pReport) ;
|
|
|
|
EndPaint (hWnd, &ps) ;
|
|
}
|
|
|
|
|
|
void
|
|
static
|
|
UpdateReportValues (
|
|
PREPORT pReport
|
|
)
|
|
/*
|
|
Effect: Redraw all the visible report values of pReport.
|
|
Since drawing the values completely covers any
|
|
previous values, there is no need to erase (or flicker)
|
|
between updating values.
|
|
|
|
Called By: ReportTimer, OnVScroll, OnHScroll.
|
|
*/
|
|
{
|
|
HDC hDC ;
|
|
|
|
hDC = GetDC (pReport->hWnd) ;
|
|
|
|
if (!hDC)
|
|
return;
|
|
|
|
SetBkColor (hDC, GetSysColor(COLOR_WINDOW)) ;
|
|
SetWindowOrgEx (hDC,
|
|
GetScrollPos (pReport->hWnd, SB_HORZ),
|
|
GetScrollPos (pReport->hWnd, SB_VERT),
|
|
NULL) ;
|
|
|
|
DrawReportValues (hDC, pReport) ;
|
|
ReleaseDC (pReport->hWnd, hDC) ;
|
|
|
|
}
|
|
|
|
|
|
void
|
|
static
|
|
OnHScroll (
|
|
HWND hWnd,
|
|
int iScrollCode,
|
|
int iScrollNewPos
|
|
)
|
|
{
|
|
PREPORT pReport ;
|
|
int iScrollAmt, iScrollPos, iScrollRange ;
|
|
int iScrollLo ;
|
|
RECT rectClient ;
|
|
int xWidth ;
|
|
|
|
pReport = ReportData (hWnd) ;
|
|
|
|
GetClientRect (hWnd, &rectClient) ;
|
|
xWidth = rectClient.right - rectClient.left ;
|
|
|
|
if (pReport->xWidth <= xWidth) {
|
|
// no horz scroll bar, forget it
|
|
return ;
|
|
}
|
|
|
|
iScrollPos = GetScrollPos (hWnd, SB_HORZ) ;
|
|
|
|
GetScrollRange (hWnd, SB_HORZ, &iScrollLo, &iScrollRange) ;
|
|
|
|
|
|
switch (iScrollCode) {
|
|
case SB_LINEUP:
|
|
iScrollAmt = - Report.yLineHeight ;
|
|
break ;
|
|
|
|
case SB_LINEDOWN:
|
|
iScrollAmt = Report.yLineHeight ;
|
|
break ;
|
|
|
|
case SB_PAGEUP:
|
|
iScrollAmt = - (rectClient.right - rectClient.left) / 2 ;
|
|
break ;
|
|
|
|
case SB_PAGEDOWN:
|
|
iScrollAmt = (rectClient.right - rectClient.left) / 2 ;
|
|
break ;
|
|
|
|
case SB_THUMBPOSITION:
|
|
iScrollAmt = iScrollNewPos - iScrollPos ;
|
|
break ;
|
|
|
|
default:
|
|
iScrollAmt = 0 ;
|
|
}
|
|
|
|
iScrollAmt = PinInclusive (iScrollAmt,
|
|
-iScrollPos,
|
|
iScrollRange - iScrollPos) ;
|
|
if (iScrollAmt) {
|
|
iScrollPos += iScrollAmt ;
|
|
ScrollWindow (hWnd, -iScrollAmt, 0, NULL, NULL) ;
|
|
SetScrollPos (hWnd, SB_HORZ, iScrollPos, TRUE) ;
|
|
UpdateWindow (hWnd) ;
|
|
#if 0
|
|
UpdateReportValues (pReport) ;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
static
|
|
OnVScroll (
|
|
HWND hWnd,
|
|
int iScrollCode,
|
|
int iScrollNewPos
|
|
)
|
|
{
|
|
PREPORT pReport ;
|
|
int iScrollAmt, iScrollPos, iScrollRange ;
|
|
int iScrollLo ;
|
|
RECT rectClient ;
|
|
|
|
pReport = ReportData (hWnd) ;
|
|
|
|
iScrollPos = GetScrollPos (hWnd, SB_VERT) ;
|
|
GetScrollRange (hWnd, SB_VERT, &iScrollLo, &iScrollRange) ;
|
|
|
|
GetClientRect (hWnd, &rectClient) ;
|
|
|
|
switch (iScrollCode) {
|
|
case SB_LINEUP:
|
|
iScrollAmt = - Report.yLineHeight ;
|
|
break ;
|
|
|
|
case SB_LINEDOWN:
|
|
iScrollAmt = Report.yLineHeight ;
|
|
break ;
|
|
|
|
case SB_PAGEUP:
|
|
iScrollAmt = - (rectClient.bottom - rectClient.top) / 2 ;
|
|
break ;
|
|
|
|
case SB_PAGEDOWN:
|
|
iScrollAmt = (rectClient.bottom - rectClient.top) / 2 ;
|
|
break ;
|
|
|
|
case SB_THUMBPOSITION:
|
|
iScrollAmt = iScrollNewPos - iScrollPos ;
|
|
break ;
|
|
|
|
default:
|
|
iScrollAmt = 0 ;
|
|
}
|
|
|
|
iScrollAmt = PinInclusive (iScrollAmt,
|
|
-iScrollPos,
|
|
iScrollRange - iScrollPos) ;
|
|
if (iScrollAmt) {
|
|
iScrollPos += iScrollAmt ;
|
|
ScrollWindow (hWnd, 0, -iScrollAmt, NULL, NULL) ;
|
|
SetScrollPos (hWnd, SB_VERT, iScrollPos, TRUE) ;
|
|
|
|
// WindowInvalidate (hWnd) ;
|
|
UpdateWindow (hWnd) ;
|
|
#if 0
|
|
UpdateReportValues (pReport) ;
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void
|
|
static
|
|
OnKeyDown (
|
|
HWND hWnd,
|
|
WPARAM wParam
|
|
)
|
|
{
|
|
switch (wParam) {
|
|
case VK_UP:
|
|
OnVScroll (hWnd, SB_LINEUP, 0) ;
|
|
break ;
|
|
|
|
case VK_DOWN:
|
|
OnVScroll (hWnd, SB_LINEDOWN, 0) ;
|
|
break ;
|
|
|
|
case VK_LEFT:
|
|
OnHScroll (hWnd, SB_LINEUP, 0) ;
|
|
break ;
|
|
|
|
case VK_RIGHT:
|
|
OnHScroll (hWnd, SB_LINEDOWN, 0) ;
|
|
break ;
|
|
|
|
case VK_PRIOR:
|
|
OnVScroll (hWnd, SB_PAGEUP, 0) ;
|
|
break ;
|
|
|
|
case VK_NEXT:
|
|
OnVScroll (hWnd, SB_PAGEDOWN, 0) ;
|
|
break ;
|
|
}
|
|
}
|
|
|
|
|
|
LRESULT
|
|
APIENTRY
|
|
ReportWndProc (
|
|
HWND hWnd,
|
|
UINT wMsg,
|
|
WPARAM wParam,
|
|
LPARAM lParam
|
|
)
|
|
{
|
|
BOOL bCallDefProc ;
|
|
LRESULT lReturnValue ;
|
|
|
|
bCallDefProc = FALSE ;
|
|
lReturnValue = 0L ;
|
|
|
|
switch (wMsg) {
|
|
case WM_CREATE:
|
|
OnCreate (hWnd) ;
|
|
break ;
|
|
|
|
case WM_LBUTTONDOWN:
|
|
|
|
if (!OnReportLButtonDown (hWnd, LOWORD (lParam), HIWORD (lParam))) {
|
|
// mouse click do not hit on any entries, see if we
|
|
// need to drag Perfmon
|
|
if (!(Options.bMenubar)) {
|
|
DoWindowDrag (hWnd, lParam) ;
|
|
}
|
|
}
|
|
break ;
|
|
|
|
case WM_LBUTTONDBLCLK:
|
|
SendMessage (hWndMain, WM_LBUTTONDBLCLK, wParam, lParam) ;
|
|
break ;
|
|
|
|
case WM_PAINT:
|
|
OnPaint (hWnd) ;
|
|
break ;
|
|
|
|
case WM_SIZE:
|
|
SetScrollRanges (hWnd) ;
|
|
break ;
|
|
|
|
case WM_HSCROLL:
|
|
OnHScroll (hWnd, LOWORD (wParam), HIWORD (wParam)) ;
|
|
break ;
|
|
|
|
case WM_VSCROLL:
|
|
OnVScroll (hWnd, LOWORD (wParam), HIWORD (wParam)) ;
|
|
break ;
|
|
|
|
case WM_TIMER:
|
|
ReportTimer (hWnd, FALSE) ;
|
|
break ;
|
|
|
|
case WM_KEYDOWN:
|
|
OnKeyDown (hWnd, wParam) ;
|
|
break ;
|
|
|
|
case WM_DESTROY:
|
|
KillTimer (hWnd, ReportTimerID) ;
|
|
break ;
|
|
|
|
default:
|
|
bCallDefProc = TRUE ;
|
|
}
|
|
|
|
|
|
if (bCallDefProc)
|
|
lReturnValue = DefWindowProc (hWnd, wMsg, wParam, lParam) ;
|
|
|
|
return (lReturnValue);
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================//
|
|
// Exported Functions //
|
|
//==========================================================================//
|
|
|
|
void
|
|
SetReportTimer (
|
|
PREPORT pReport
|
|
)
|
|
{
|
|
if (pReport->iStatus == iPMStatusCollecting)
|
|
KillTimer (pReport->hWnd, ReportTimerID) ;
|
|
|
|
SetTimer (pReport->hWnd, ReportTimerID,
|
|
pReport->iIntervalMSecs , NULL) ;
|
|
pReport->iStatus = iPMStatusCollecting ;
|
|
}
|
|
|
|
|
|
void
|
|
ClearReportTimer (
|
|
PREPORT pReport
|
|
)
|
|
{
|
|
pReport->iStatus = iPMStatusClosed ;
|
|
KillTimer (pReport->hWnd, ReportTimerID) ;
|
|
}
|
|
|
|
|
|
BOOL
|
|
ReportInitializeApplication (void)
|
|
{
|
|
BOOL bSuccess ;
|
|
WNDCLASS wc ;
|
|
|
|
//=============================//
|
|
// Register ReportWindow class //
|
|
//=============================//
|
|
|
|
|
|
wc.style = dwReportClassStyle ;
|
|
wc.lpfnWndProc = ReportWndProc ;
|
|
wc.hInstance = hInstance ;
|
|
wc.cbClsExtra = iReportWindowExtra ;
|
|
wc.cbWndExtra = iReportClassExtra ;
|
|
wc.hIcon = NULL ;
|
|
wc.hCursor = LoadCursor(NULL, IDC_ARROW) ;
|
|
// wc.hbrBackground = GetStockObject (WHITE_BRUSH) ;
|
|
wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1) ;
|
|
wc.lpszMenuName = NULL ;
|
|
wc.lpszClassName = szReportWindowClass ;
|
|
|
|
bSuccess = RegisterClass (&wc) ;
|
|
|
|
|
|
//=============================//
|
|
// Register Child classes //
|
|
//=============================//
|
|
|
|
return (bSuccess) ;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HWND
|
|
CreateReportWindow (
|
|
HWND hWndParent
|
|
)
|
|
/*
|
|
Effect: Create the graph window. This window is a child of
|
|
hWndMain and is a container for the graph data,
|
|
graph label, graph legend, and graph status windows.
|
|
|
|
Note: We dont worry about the size here, as this window
|
|
will be resized whenever the main window is resized.
|
|
|
|
*/
|
|
{
|
|
return (CreateWindow (szReportWindowClass, // window class
|
|
NULL, // caption
|
|
dwReportWindowStyle, // style for window
|
|
0, 0, // initial position
|
|
0, 0, // initial size
|
|
hWndParent, // parent
|
|
NULL, // menu
|
|
hInstance, // program instance
|
|
NULL)) ; // user-supplied data
|
|
}
|
|
|
|
|
|
|
|
void
|
|
SetReportPositions (
|
|
HDC hDC,
|
|
PREPORT pReport
|
|
)
|
|
{
|
|
PSYSTEMGROUP pSystemGroup ;
|
|
int yLine ;
|
|
int yPos ;
|
|
|
|
|
|
// pReport->xMaxCounterWidth = 0 ;
|
|
|
|
yLine = pReport->yLineHeight ;
|
|
yPos = 2 * yLine ;
|
|
|
|
for (pSystemGroup = pReport->pSystemGroupFirst ;
|
|
pSystemGroup ;
|
|
pSystemGroup = pSystemGroup->pSystemGroupNext) {
|
|
pSystemGroup->yFirstLine = yPos + yLine ;
|
|
|
|
SetSystemPositions (hDC, pReport, pSystemGroup, yLine) ;
|
|
|
|
yPos = pSystemGroup->yLastLine ;
|
|
}
|
|
|
|
pReport->yHeight = yPos ;
|
|
|
|
SetScrollRanges (pReport->hWnd) ;
|
|
}
|
|
|
|
|
|
|
|
void
|
|
PlaybackReport (
|
|
HWND hWndReport
|
|
)
|
|
{
|
|
PREPORT pReport ;
|
|
|
|
pReport = ReportData (hWndReport) ;
|
|
|
|
PlaybackLines (pReport->pSystemFirst,
|
|
pReport->pLineFirst,
|
|
PlaybackLog.StartIndexPos.iPosition) ;
|
|
PlaybackLines (pReport->pSystemFirst,
|
|
pReport->pLineFirst,
|
|
PlaybackLog.StopIndexPos.iPosition) ;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CurrentReportItem (
|
|
HWND hWndReport
|
|
)
|
|
{
|
|
PREPORT pReport ;
|
|
|
|
pReport = ReportData (hWndReport) ;
|
|
if (!pReport)
|
|
return (FALSE) ;
|
|
|
|
return (pReport->CurrentItemType != REPORT_TYPE_NOTHING) ;
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
AddReport (
|
|
HWND hWndParent
|
|
)
|
|
{
|
|
PREPORT pReport ;
|
|
LPTSTR pCurrentSystem ;
|
|
POBJECTGROUP pParentObject ;
|
|
|
|
pReport = ReportData (hWndReport) ;
|
|
|
|
if (pReport->CurrentItemType == REPORT_TYPE_LINE) {
|
|
pCurrentSystem = pReport->CurrentItem.pLine->lnSystemName ;
|
|
} else if (pReport->CurrentItemType == REPORT_TYPE_SYSTEM) {
|
|
pCurrentSystem = pReport->CurrentItem.pSystem->lpszSystemName ;
|
|
} else if (pReport->CurrentItemType == REPORT_TYPE_OBJECT) {
|
|
pCurrentSystem = pReport->CurrentItem.pObject->pParentSystem->lpszSystemName ;
|
|
} else if (pReport->CurrentItemType == REPORT_TYPE_COLUMN) {
|
|
pParentObject = pReport->CurrentItem.pColumn->pParentObject ;
|
|
pCurrentSystem = pParentObject->pParentSystem->lpszSystemName ;
|
|
} else if (pReport->CurrentItemType == REPORT_TYPE_COUNTER) {
|
|
pParentObject = pReport->CurrentItem.pCounter->pParentObject ;
|
|
pCurrentSystem = pParentObject->pParentSystem->lpszSystemName ;
|
|
} else {
|
|
pCurrentSystem = NULL ;
|
|
}
|
|
|
|
|
|
return (AddLine (hWndParent,
|
|
&(pReport->pSystemFirst),
|
|
&(pReport->Visual),
|
|
pCurrentSystem,
|
|
LineTypeReport)) ;
|
|
}
|
|
|
|
|
|
BOOL
|
|
ToggleReportRefresh (
|
|
HWND hWnd
|
|
)
|
|
{
|
|
PREPORT pReport ;
|
|
|
|
pReport = ReportData (hWnd) ;
|
|
|
|
if (pReport->bManualRefresh)
|
|
SetReportTimer (pReport) ;
|
|
else
|
|
ClearReportTimer (pReport) ;
|
|
|
|
pReport->bManualRefresh = !pReport->bManualRefresh ;
|
|
return (pReport->bManualRefresh) ;
|
|
}
|
|
|
|
BOOL
|
|
ReportRefresh (
|
|
HWND hWnd
|
|
)
|
|
{
|
|
PREPORT pReport ;
|
|
|
|
pReport = ReportData (hWnd) ;
|
|
|
|
return (pReport->bManualRefresh) ;
|
|
}
|
|
|
|
|
|
|
|
void
|
|
ReportTimer (
|
|
HWND hWnd,
|
|
BOOL bForce
|
|
)
|
|
{
|
|
PREPORT pReport ;
|
|
|
|
pReport = ReportData (hWnd) ;
|
|
|
|
if (PlayingBackLog () || !pReport) {
|
|
return;
|
|
}
|
|
|
|
if (bForce || !pReport->bManualRefresh) {
|
|
UpdateLines (&(pReport->pSystemFirst), pReport->pLineFirst) ;
|
|
if (iPerfmonView == IDM_VIEWREPORT && !bPerfmonIconic) {
|
|
// only need to draw the data when we are viewing it...
|
|
UpdateReportValues (pReport) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
BOOL
|
|
SaveReport (
|
|
HWND hWndReport,
|
|
HANDLE hInputFile,
|
|
BOOL bGetFileName
|
|
)
|
|
{
|
|
PREPORT pReport ;
|
|
PLINE pLine ;
|
|
HANDLE hFile = NULL;
|
|
DISKREPORT DiskReport ;
|
|
PERFFILEHEADER FileHeader ;
|
|
TCHAR szFileName [256] ;
|
|
BOOL newFileName = FALSE ;
|
|
|
|
pReport = ReportData (hWndReport) ;
|
|
if (!pReport) {
|
|
return (FALSE) ;
|
|
}
|
|
|
|
if (hInputFile) {
|
|
// use the input file handle if it is available
|
|
// this is the case for saving workspace data
|
|
hFile = hInputFile ;
|
|
} else {
|
|
if (pReportFullFileName) {
|
|
lstrcpy (szFileName, pReportFullFileName) ;
|
|
}
|
|
if (bGetFileName || pReportFullFileName == NULL) {
|
|
if (!FileGetName (hWndReport, IDS_REPORTFILE, szFileName)) {
|
|
return (FALSE) ;
|
|
}
|
|
newFileName = TRUE ;
|
|
}
|
|
|
|
hFile = FileHandleCreate (szFileName) ;
|
|
|
|
if (hFile && newFileName) {
|
|
ChangeSaveFileName (szFileName, IDM_VIEWREPORT) ;
|
|
} else if (!hFile) {
|
|
DlgErrorBox (hWndReport, ERR_CANT_OPEN, szFileName) ;
|
|
}
|
|
}
|
|
|
|
|
|
if (!hFile || hFile == INVALID_HANDLE_VALUE)
|
|
return (FALSE) ;
|
|
|
|
|
|
if (!hInputFile) {
|
|
memset (&FileHeader, 0, sizeof (FileHeader)) ;
|
|
lstrcpy (FileHeader.szSignature, szPerfReportSignature) ;
|
|
FileHeader.dwMajorVersion = ReportMajorVersion ;
|
|
FileHeader.dwMinorVersion = ReportMinorVersion ;
|
|
|
|
if (!FileWrite (hFile, &FileHeader, sizeof (PERFFILEHEADER))) {
|
|
goto Exit0 ;
|
|
}
|
|
}
|
|
|
|
DiskReport.Visual = pReport->Visual ;
|
|
DiskReport.bManualRefresh = pReport->bManualRefresh ;
|
|
DiskReport.dwIntervalSecs = pReport->iIntervalMSecs ;
|
|
DiskReport.dwNumLines = NumLines (pReport->pLineFirst) ;
|
|
DiskReport.perfmonOptions = Options ;
|
|
|
|
if (!FileWrite (hFile, &DiskReport, sizeof (DISKREPORT))) {
|
|
goto Exit0 ;
|
|
}
|
|
|
|
for (pLine = pReport->pLineFirst ;
|
|
pLine ;
|
|
pLine = pLine->pLineNext) {
|
|
if (!WriteLine (pLine, hFile)) {
|
|
goto Exit0 ;
|
|
}
|
|
}
|
|
|
|
if (!hInputFile) {
|
|
CloseHandle (hFile) ;
|
|
}
|
|
|
|
return (TRUE) ;
|
|
|
|
Exit0:
|
|
if (!hInputFile) {
|
|
CloseHandle (hFile) ;
|
|
|
|
// only need to report error if not workspace
|
|
DlgErrorBox (hWndReport, ERR_SETTING_FILE, szFileName) ;
|
|
}
|
|
return (FALSE) ;
|
|
}
|
|
|
|
|
|
void
|
|
ReportAddAction (
|
|
PREPORT pReport
|
|
)
|
|
{
|
|
HDC hDC ;
|
|
|
|
//=============================//
|
|
// Calculate report positions //
|
|
//=============================//
|
|
|
|
hDC = GetDC (hWndReport) ;
|
|
if (hDC) {
|
|
SetReportPositions (hDC, pReport) ;
|
|
ReleaseDC (hWndReport, hDC) ;
|
|
}
|
|
|
|
}
|
|
|
|
void
|
|
UpdateReportData (
|
|
HWND hWndReport
|
|
)
|
|
{
|
|
PREPORT pReport ;
|
|
|
|
pReport = ReportData (hWndReport) ;
|
|
if (PlayingBackLog ()) {
|
|
PlaybackReport (hWndReport) ;
|
|
} else if (pReport->iStatus == iPMStatusClosed) {
|
|
SetReportTimer (pReport) ;
|
|
}
|
|
|
|
WindowInvalidate (hWndReport) ;
|
|
}
|
|
|
|
|
|
BOOL
|
|
OpenReportVer1 (
|
|
HANDLE hFile,
|
|
DISKREPORT *pDiskReport,
|
|
PREPORT pReport,
|
|
DWORD dwMinorVersion
|
|
)
|
|
{
|
|
HDC hDC ;
|
|
|
|
pReport->Visual = pDiskReport->Visual ;
|
|
pReport->iIntervalMSecs = pDiskReport->dwIntervalSecs ;
|
|
if (dwMinorVersion < 3) {
|
|
// convert this to msec
|
|
pReport->iIntervalMSecs *= 1000 ;
|
|
}
|
|
pReport->bManualRefresh = pDiskReport->bManualRefresh ;
|
|
|
|
bDelayAddAction = TRUE ;
|
|
ReadLines (hFile, pDiskReport->dwNumLines,
|
|
&(pReport->pSystemFirst), &(pReport->pLineFirst), IDM_VIEWREPORT) ;
|
|
|
|
if (pReport->pLineFirst) {
|
|
// set focus on the first line
|
|
pReport->CurrentItem.pLine = pReport->pLineFirst ;
|
|
pReport->CurrentItemType = REPORT_TYPE_LINE ;
|
|
}
|
|
bDelayAddAction = FALSE ;
|
|
|
|
//=============================//
|
|
// Calculate report positions //
|
|
//=============================//
|
|
|
|
hDC = GetDC (hWndReport) ;
|
|
if (hDC) {
|
|
SetReportPositions (hDC, pReport) ;
|
|
ReleaseDC (hWndReport, hDC) ;
|
|
}
|
|
|
|
if (PlayingBackLog ()) {
|
|
PlaybackReport (hWndReport) ;
|
|
} else if (pReport->iStatus == iPMStatusClosed) {
|
|
SetReportTimer (pReport) ;
|
|
}
|
|
|
|
WindowInvalidate (hWndReport) ;
|
|
|
|
return (TRUE) ;
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
OpenReport (
|
|
HWND hWndReport,
|
|
HANDLE hFile,
|
|
DWORD dwMajorVersion,
|
|
DWORD dwMinorVersion,
|
|
BOOL bReportFile
|
|
)
|
|
{
|
|
PREPORT pReport ;
|
|
DISKREPORT DiskReport ;
|
|
BOOL bSuccess = TRUE ;
|
|
|
|
pReport = ReportData (hWndReport) ;
|
|
if (!pReport) {
|
|
bSuccess = FALSE ;
|
|
goto Exit0 ;
|
|
}
|
|
|
|
if (!FileRead (hFile, &DiskReport, sizeof (DISKREPORT))) {
|
|
bSuccess = FALSE ;
|
|
goto Exit0 ;
|
|
}
|
|
|
|
|
|
switch (dwMajorVersion) {
|
|
case (1):
|
|
|
|
SetHourglassCursor() ;
|
|
|
|
ResetReportView (hWndReport) ;
|
|
|
|
OpenReportVer1 (hFile, &DiskReport, pReport, dwMinorVersion) ;
|
|
|
|
// change to report view if we are opening a
|
|
// report file
|
|
if (bReportFile && iPerfmonView != IDM_VIEWREPORT) {
|
|
SendMessage (hWndMain, WM_COMMAND, (LONG)IDM_VIEWREPORT, 0L) ;
|
|
}
|
|
|
|
if (iPerfmonView == IDM_VIEWREPORT) {
|
|
SetPerfmonOptions (&DiskReport.perfmonOptions) ;
|
|
}
|
|
|
|
SetArrowCursor() ;
|
|
|
|
break ;
|
|
}
|
|
|
|
Exit0:
|
|
|
|
if (bReportFile) {
|
|
CloseHandle (hFile) ;
|
|
}
|
|
|
|
return (bSuccess) ;
|
|
}
|
|
|
|
void
|
|
ResetReportView (
|
|
HWND hWndReport
|
|
)
|
|
{
|
|
PREPORT pReport ;
|
|
|
|
pReport = ReportData (hWndReport) ;
|
|
|
|
if (!pReport) {
|
|
return ;
|
|
}
|
|
|
|
ChangeSaveFileName (NULL, IDM_VIEWREPORT) ;
|
|
|
|
if (pReport->pSystemGroupFirst) {
|
|
ResetReport (hWndReport) ;
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
ResetReport (
|
|
HWND hWndReport
|
|
)
|
|
{
|
|
PREPORT pReport ;
|
|
PSYSTEMGROUP pSystemGroup, pSystemGroupDelete ;
|
|
POBJECTGROUP pObjectGroup, pObjectGroupDelete ;
|
|
PCOUNTERGROUP pCounterGroup, pCounterGroupDelete ;
|
|
HDC hDC ;
|
|
|
|
pReport = ReportData (hWndReport) ;
|
|
if (!pReport)
|
|
return ;
|
|
|
|
ClearReportTimer (pReport) ;
|
|
|
|
pSystemGroup = pReport->pSystemGroupFirst ;
|
|
while (pSystemGroup) {
|
|
pObjectGroup = pSystemGroup->pObjectGroupFirst ;
|
|
while (pObjectGroup) {
|
|
pCounterGroup = pObjectGroup->pCounterGroupFirst ;
|
|
while (pCounterGroup) {
|
|
pCounterGroupDelete = pCounterGroup ;
|
|
pCounterGroup = pCounterGroup->pCounterGroupNext ;
|
|
MemoryFree (pCounterGroupDelete) ;
|
|
}
|
|
|
|
pObjectGroupDelete = pObjectGroup ;
|
|
pObjectGroup = pObjectGroup->pObjectGroupNext ;
|
|
ColumnGroupRemove (pObjectGroupDelete->pColumnGroupFirst) ;
|
|
MemoryFree (pObjectGroupDelete->lpszObjectName) ;
|
|
MemoryFree (pObjectGroupDelete) ;
|
|
}
|
|
|
|
pSystemGroupDelete = pSystemGroup ;
|
|
pSystemGroup = pSystemGroup->pSystemGroupNext ;
|
|
MemoryFree (pSystemGroupDelete->lpszSystemName) ;
|
|
MemoryFree (pSystemGroupDelete) ;
|
|
}
|
|
|
|
FreeLines (pReport->pLineFirst) ;
|
|
pReport->pLineFirst = NULL ;
|
|
|
|
FreeSystems (pReport->pSystemFirst) ;
|
|
pReport->pSystemFirst = NULL ;
|
|
|
|
pReport->pSystemGroupFirst = NULL ;
|
|
pReport->CurrentItemType = REPORT_TYPE_NOTHING ;
|
|
pReport->CurrentItem.pLine = NULL ;
|
|
|
|
// reset scrolling ranges
|
|
pReport->xWidth = 0 ;
|
|
pReport->yHeight = 0 ;
|
|
pReport->xMaxCounterWidth = 0 ;
|
|
hDC = GetDC (hWndReport) ;
|
|
if (hDC) {
|
|
SetReportPositions (hDC, pReport) ;
|
|
|
|
SelectFont (hDC, pReport->hFont) ;
|
|
pReport->xValueWidth = TextWidth (hDC, szValuePlaceholder) ;
|
|
|
|
ReleaseDC (hWndReport, hDC) ;
|
|
}
|
|
|
|
WindowInvalidate (hWndReport) ;
|
|
}
|
|
|
|
void
|
|
ClearReportDisplay (
|
|
HWND hWndReport
|
|
)
|
|
{
|
|
PREPORT pReport ;
|
|
PLINE pLine;
|
|
|
|
if (PlayingBackLog()) {
|
|
return ;
|
|
}
|
|
|
|
pReport = ReportData (hWndReport) ;
|
|
if (!pReport || !pReport->pLineFirst)
|
|
return ;
|
|
|
|
for (pLine = pReport->pLineFirst ;
|
|
pLine ;
|
|
pLine = pLine->pLineNext) {
|
|
// reset the new data counts
|
|
pLine->bFirstTime = 2 ;
|
|
}
|
|
|
|
// re-draw the values
|
|
UpdateReportValues (pReport) ;
|
|
|
|
}
|
|
|
|
//=========================================
|
|
// we don't print. we just export
|
|
//
|
|
// if need printing, define KEEP_PRINT
|
|
//=========================================
|
|
#ifdef KEEP_PRINT
|
|
BOOL
|
|
PrintReportDisplay (
|
|
HDC hDC,
|
|
PREPORT pReport
|
|
)
|
|
{
|
|
SetReportPositions (hDC, pReport) ;
|
|
DrawReport (hDC, pReport) ;
|
|
return TRUE ;
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
PrintReport (
|
|
HWND hWndParent,
|
|
HWND hWndReport
|
|
)
|
|
{
|
|
PREPORT pReport ;
|
|
HDC hDC ;
|
|
int xPageWidth ;
|
|
int yPageHeight ;
|
|
int xValueWidth ;
|
|
|
|
HFONT hFont, hFontHeaders ;
|
|
int yLineHeight ;
|
|
|
|
pReport = ReportData (hWndReport) ;
|
|
if (!pReport)
|
|
return (FALSE) ;
|
|
|
|
hDC = PrintDC () ;
|
|
if (!hDC) {
|
|
PostError () ;
|
|
return (FALSE) ;
|
|
}
|
|
|
|
xPageWidth = GetDeviceCaps (hDC, HORZRES) ;
|
|
yPageHeight = GetDeviceCaps (hDC, VERTRES) ;
|
|
|
|
|
|
StartJob (hDC, TEXT("Performance Monitor Report")) ;
|
|
StartPage (hDC) ;
|
|
|
|
|
|
hFont = pReport->hFont ;
|
|
hFontHeaders = pReport->hFontHeaders ;
|
|
yLineHeight = pReport->yLineHeight ;
|
|
xValueWidth = pReport->xValueWidth ;
|
|
|
|
pReport->hFont = hFontPrinterScales ;
|
|
pReport->hFontHeaders = hFontPrinterScalesBold ;
|
|
|
|
SelectFont (hDC, pReport->hFont) ;
|
|
pReport->yLineHeight = FontHeight (hDC, TRUE) ;
|
|
|
|
pReport->xValueWidth = TextWidth (hDC, szValuePlaceholder) ;
|
|
|
|
PrintReportDisplay (hDC, pReport) ;
|
|
|
|
EndPage (hDC) ;
|
|
EndJob (hDC) ;
|
|
|
|
DeleteDC (hDC) ;
|
|
|
|
|
|
pReport->hFont = hFont ;
|
|
pReport->hFontHeaders = hFontHeaders ;
|
|
pReport->yLineHeight = yLineHeight ;
|
|
|
|
pReport->xValueWidth = xValueWidth ;
|
|
|
|
hDC = GetDC (hWndReport) ;
|
|
SetReportPositions (hDC, pReport) ;
|
|
ReleaseDC (hWndReport, hDC) ;
|
|
|
|
return (FALSE) ;
|
|
}
|
|
|
|
// we don't print. we just export
|
|
#endif
|
|
|
|
#if 0
|
|
/*
|
|
NOTE:
|
|
this function was attempted as a replacement for the
|
|
FindEquivalentLine function used to locate matching
|
|
report entries. It "Almost" works, but because of how
|
|
the new entries (lines) are added to the list. Since new
|
|
columns aren't added in a timely fashion for this test
|
|
to work, the list of counters still must be searched
|
|
sequentially. To make this indexed search work for "bulk"
|
|
additions, the column updating/addtion must take place
|
|
more "synchronously" with the counter addition.
|
|
|
|
-- bobw 2-Jan-97
|
|
|
|
*/
|
|
PLINE
|
|
FindEquivalentReportLine (
|
|
PLINE pLineToFind,
|
|
PREPORT pReport
|
|
)
|
|
{
|
|
PLINE pLine = NULL;
|
|
PLINE pLastEquivLine = NULL;
|
|
|
|
BOOL bNotUsed;
|
|
|
|
PSYSTEMGROUP pSystemGroup = NULL;
|
|
POBJECTGROUP pObjectGroup = NULL;
|
|
PCOUNTERGROUP pCounterGroup = NULL;
|
|
PCOLUMNGROUP pColumnGroup = NULL;
|
|
PCOLUMNGROUP pMatchingColumn = NULL;
|
|
int dwColumn;
|
|
|
|
// since the report data is organized hierarchically, we'll search
|
|
// that way instead of just looking at each lin
|
|
|
|
pSystemGroup = GetSystemGroup (pReport, pLineToFind->lnSystemName);
|
|
|
|
if (pSystemGroup != NULL) {
|
|
// found the system that this line belongs to so look up the
|
|
// object
|
|
pObjectGroup = GetObjectGroup (pSystemGroup, pLineToFind->lnObjectName) ;
|
|
if (pObjectGroup != NULL) {
|
|
// find matching instance column
|
|
for (pColumnGroup = pObjectGroup->pColumnGroupFirst;
|
|
pColumnGroup;
|
|
pColumnGroup = pColumnGroup->pColumnGroupNext) {
|
|
if (pstrsame (pLineToFind->lnInstanceName, pColumnGroup->lpszInstanceName) &&
|
|
pstrsame (pLineToFind->lnPINName, pColumnGroup->lpszParentName)) {
|
|
// this column has the same name as the one we're
|
|
// looking for so find the highest matching index value
|
|
if (pMatchingColumn == NULL) {
|
|
pMatchingColumn = pColumnGroup;
|
|
} else {
|
|
if (pColumnGroup->dwInstanceIndex > pMatchingColumn->dwInstanceIndex) {
|
|
pMatchingColumn = pColumnGroup;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (pMatchingColumn == NULL) {
|
|
dwColumn = 0;
|
|
} else {
|
|
dwColumn = (int)pMatchingColumn->ColumnNumber;
|
|
}
|
|
// then try to find the matching counter in this column
|
|
pCounterGroup = GetCounterGroup (pObjectGroup,
|
|
pLineToFind->lnCounterDef.CounterNameTitleIndex,
|
|
&bNotUsed,
|
|
pLineToFind->lnCounterName,
|
|
FALSE);
|
|
|
|
if (pCounterGroup != NULL) {
|
|
// search the instances of this counter group for a match
|
|
for (pLine = pCounterGroup->pLineFirst ;
|
|
pLine ;
|
|
pLine = pLine->pLineNext) {
|
|
if (pLine->iReportColumn == dwColumn) {
|
|
// match counter names to confir
|
|
if (pstrsame(pLine->lnCounterName,
|
|
pLineToFind->lnCounterName)) {
|
|
pLastEquivLine = pLine;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return (pLastEquivLine) ;
|
|
}
|
|
#endif
|
|
|
|
BOOL
|
|
ReportInsertLine (
|
|
HWND hWnd,
|
|
PLINE pLine
|
|
)
|
|
/*
|
|
Effect: Insert the line pLine into the data structures for the
|
|
Report of window hWnd. The line is added to the list of
|
|
lines, and also added to the report structure in the
|
|
appropriate System, Object, and Counter.
|
|
|
|
Returns: Whether the function was successful. If this function
|
|
returns FALSE, the line was not added.
|
|
*/
|
|
{
|
|
HDC hDC ;
|
|
PREPORT pReport ;
|
|
PSYSTEMGROUP pSystemGroup ;
|
|
POBJECTGROUP pObjectGroup ;
|
|
PCOUNTERGROUP pCounterGroup ;
|
|
PLINE pLineEquivalent ;
|
|
int OldCounterWidth ;
|
|
BOOL bNewCounterGroup ;
|
|
|
|
pReport = ReportData (hWnd) ;
|
|
pReport->bModified = TRUE ;
|
|
|
|
pLineEquivalent = FindEquivalentLine (pLine, pReport->pLineFirst);
|
|
if (pLineEquivalent) {
|
|
if (bMonitorDuplicateInstances) {
|
|
pLine->dwInstanceIndex = pLineEquivalent->dwInstanceIndex + 1;
|
|
} else {
|
|
return (FALSE) ;
|
|
}
|
|
}
|
|
//=============================//
|
|
// Add line, line's system //
|
|
//=============================//
|
|
|
|
ReportLineAppend (pReport, pLine) ;
|
|
|
|
|
|
//=============================//
|
|
// Find correct spot; add line //
|
|
//=============================//
|
|
|
|
pSystemGroup = GetSystemGroup (pReport, pLine->lnSystemName) ;
|
|
pObjectGroup = GetObjectGroup (pSystemGroup, pLine->lnObjectName) ;
|
|
pCounterGroup = GetCounterGroup (pObjectGroup,
|
|
pLine->lnCounterDef.CounterNameTitleIndex,
|
|
&bNewCounterGroup,
|
|
pLine->lnCounterName,
|
|
TRUE);
|
|
|
|
if (!pCounterGroup)
|
|
return (FALSE) ;
|
|
|
|
LineCounterAppend (pCounterGroup, pLine) ;
|
|
|
|
//=============================//
|
|
// Calculate report positions //
|
|
//=============================//
|
|
hDC = GetDC (hWnd) ;
|
|
SelectFont (hDC, pReport->hFontHeaders) ;
|
|
|
|
if (bNewCounterGroup) {
|
|
// re-calc. the max. counter group width
|
|
OldCounterWidth = pReport->xMaxCounterWidth ;
|
|
pReport->xMaxCounterWidth =
|
|
max (pReport->xMaxCounterWidth,
|
|
TextWidth (hDC, pLine->lnCounterName)) ;
|
|
if (OldCounterWidth < pReport->xMaxCounterWidth) {
|
|
// adjust the report width with the new counter width
|
|
pReport->xWidth +=
|
|
(pReport->xMaxCounterWidth - OldCounterWidth);
|
|
}
|
|
}
|
|
|
|
if (pLine->lnCounterType == PERF_COUNTER_LARGE_RAWCOUNT_HEX) {
|
|
SelectFont (hDC, pReport->hFont) ;
|
|
pReport->xValueWidth = TextWidth (hDC, szValueLargeHexPlaceholder) ;
|
|
}
|
|
|
|
if (!bDelayAddAction) {
|
|
SetReportPositions (hDC, pReport) ;
|
|
}
|
|
ReleaseDC (hWnd, hDC) ;
|
|
|
|
pReport->CurrentItem.pLine = pLine ;
|
|
pReport->CurrentItemType = REPORT_TYPE_LINE ;
|
|
|
|
if (!bDelayAddAction) {
|
|
if (PlayingBackLog ()) {
|
|
PlaybackReport (hWndReport) ;
|
|
} else if (pReport->iStatus == iPMStatusClosed) {
|
|
SetReportTimer (pReport) ;
|
|
}
|
|
|
|
WindowInvalidate (hWnd) ;
|
|
}
|
|
return (TRUE) ;
|
|
}
|
|
|
|
|
|
BOOL
|
|
ExportComputerName (
|
|
HANDLE hFile,
|
|
PSYSTEMGROUP pSystemGroup
|
|
)
|
|
{
|
|
int StringLen ;
|
|
BOOL bWriteSuccess = TRUE ;
|
|
CHAR TempBuff [LongTextLen] ;
|
|
TCHAR UnicodeBuff [LongTextLen] ;
|
|
|
|
// export computer name
|
|
strcpy (TempBuff, LineEndStr) ;
|
|
strcat (TempBuff, LineEndStr) ;
|
|
StringLen = strlen (TempBuff) ;
|
|
TSPRINTF (UnicodeBuff, szSystemFormat, pSystemGroup->lpszSystemName) ;
|
|
ConvertUnicodeStr (&TempBuff[StringLen], UnicodeBuff) ;
|
|
strcat (TempBuff, LineEndStr) ;
|
|
|
|
if (!FileWrite (hFile, TempBuff, strlen(TempBuff))) {
|
|
bWriteSuccess = FALSE ;
|
|
}
|
|
|
|
return (bWriteSuccess) ;
|
|
}
|
|
|
|
#define WRITE_FILE_TIME 2
|
|
BOOL
|
|
ExportObjectName (
|
|
HANDLE hFile,
|
|
POBJECTGROUP pObjectGroup,
|
|
int *pColNum
|
|
)
|
|
{
|
|
int StringLen ;
|
|
BOOL bNeedToExport ;
|
|
BOOL bWriteSuccess = TRUE ;
|
|
PCOLUMNGROUP pColumnGroup ;
|
|
int ParentNum, InstanceNum ;
|
|
int TimeToWrite ;
|
|
CHAR TempBuff [512] ;
|
|
TCHAR UnicodeBuff [512] ;
|
|
|
|
ParentNum = InstanceNum = 0 ;
|
|
|
|
if (pColNum) {
|
|
*pColNum = 0 ;
|
|
}
|
|
|
|
// export object name
|
|
strcpy (TempBuff, LineEndStr) ;
|
|
StringLen = strlen (TempBuff) ;
|
|
TSPRINTF (UnicodeBuff, szObjectFormat, pObjectGroup->lpszObjectName) ;
|
|
ConvertUnicodeStr (&TempBuff[StringLen], UnicodeBuff) ;
|
|
strcat (TempBuff, LineEndStr) ;
|
|
|
|
if (!FileWrite (hFile, TempBuff, strlen(TempBuff))) {
|
|
goto Exit0 ;
|
|
}
|
|
|
|
|
|
TimeToWrite = 0 ;
|
|
|
|
// export column group
|
|
if (pObjectGroup->pColumnGroupFirst) {
|
|
strcpy (TempBuff, pDelimiter) ;
|
|
strcat (TempBuff, pDelimiter) ;
|
|
StringLen = strlen (TempBuff) ;
|
|
|
|
bNeedToExport = FALSE ;
|
|
|
|
// export Parent Names
|
|
for (pColumnGroup = pObjectGroup->pColumnGroupFirst ;
|
|
pColumnGroup ;
|
|
pColumnGroup = pColumnGroup->pColumnGroupNext) {
|
|
|
|
if (pColumnGroup->lpszParentName) {
|
|
ParentNum++ ;
|
|
bNeedToExport = TRUE ;
|
|
ConvertUnicodeStr (&TempBuff[StringLen],
|
|
pColumnGroup->lpszParentName) ;
|
|
StringLen = strlen (TempBuff) ;
|
|
}
|
|
|
|
strcat (&TempBuff[StringLen], pDelimiter) ;
|
|
StringLen = strlen (TempBuff) ;
|
|
|
|
// check if we need to export this line before it is filled up
|
|
TimeToWrite++ ;
|
|
if (TimeToWrite > WRITE_FILE_TIME) {
|
|
if (!FileWrite (hFile, TempBuff, strlen(TempBuff))) {
|
|
goto Exit0 ;
|
|
}
|
|
TimeToWrite = 0 ;
|
|
StringLen = 0 ;
|
|
TempBuff[0] = TEXT('\0') ;
|
|
}
|
|
}
|
|
|
|
// write the line delimiter
|
|
strcpy (&TempBuff[StringLen], LineEndStr) ;
|
|
if (!FileWrite (hFile, TempBuff, strlen(TempBuff))) {
|
|
goto Exit0 ;
|
|
}
|
|
|
|
if (!bNeedToExport) {
|
|
ParentNum = 0 ;
|
|
}
|
|
|
|
|
|
// setup to export Instances
|
|
strcpy (TempBuff, pDelimiter) ;
|
|
strcat (TempBuff, pDelimiter) ;
|
|
StringLen = strlen (TempBuff) ;
|
|
bNeedToExport = FALSE ;
|
|
TimeToWrite = 0 ;
|
|
|
|
// export Instance Names
|
|
for (pColumnGroup = pObjectGroup->pColumnGroupFirst ;
|
|
pColumnGroup ;
|
|
pColumnGroup = pColumnGroup->pColumnGroupNext) {
|
|
|
|
if (pColumnGroup->lpszInstanceName) {
|
|
InstanceNum++ ;
|
|
bNeedToExport = TRUE ;
|
|
ConvertUnicodeStr (&TempBuff[StringLen],
|
|
pColumnGroup->lpszInstanceName) ;
|
|
StringLen = strlen (TempBuff) ;
|
|
}
|
|
|
|
strcat (&TempBuff[StringLen], pDelimiter) ;
|
|
StringLen = strlen (TempBuff) ;
|
|
|
|
// check if we need to export this line before it is filled up
|
|
TimeToWrite++ ;
|
|
if (TimeToWrite > WRITE_FILE_TIME) {
|
|
if (!FileWrite (hFile, TempBuff, strlen(TempBuff))) {
|
|
goto Exit0 ;
|
|
}
|
|
TimeToWrite = 0 ;
|
|
StringLen = 0 ;
|
|
TempBuff[0] = TEXT('\0') ;
|
|
}
|
|
}
|
|
|
|
// write the line delimiter
|
|
strcpy (&TempBuff[StringLen], LineEndStr) ;
|
|
if (!FileWrite (hFile, TempBuff, strlen(TempBuff))) {
|
|
goto Exit0 ;
|
|
}
|
|
|
|
if (!bNeedToExport) {
|
|
InstanceNum = 0 ;
|
|
}
|
|
}
|
|
|
|
if (pColNum) {
|
|
*pColNum = max (ParentNum, InstanceNum) ;
|
|
}
|
|
|
|
return (TRUE) ;
|
|
|
|
Exit0:
|
|
return (FALSE) ;
|
|
|
|
}
|
|
|
|
BOOL
|
|
ExportLineName (
|
|
HANDLE hFile,
|
|
PLINE pLine,
|
|
int *pExportCounterName
|
|
)
|
|
{
|
|
FLOAT eValue ;
|
|
int StringLen ;
|
|
BOOL bWriteSuccess = TRUE ;
|
|
CHAR TempBuff [LongTextLen] ;
|
|
TCHAR UnicodeBuff [LongTextLen] ;
|
|
|
|
|
|
strcpy (TempBuff, pDelimiter) ;
|
|
|
|
if (*pExportCounterName) {
|
|
StringLen = strlen (TempBuff) ;
|
|
ConvertUnicodeStr (&TempBuff[StringLen], pLine->lnCounterName) ;
|
|
strcat (TempBuff, pDelimiter) ;
|
|
*pExportCounterName = FALSE ;
|
|
}
|
|
StringLen = strlen (TempBuff) ;
|
|
|
|
if (pLine->bFirstTime == 0) {
|
|
eValue = CounterEntry (pLine) ;
|
|
|
|
if (pLine->lnCounterType == PERF_COUNTER_RAWCOUNT_HEX ||
|
|
pLine->lnCounterType == PERF_COUNTER_LARGE_RAWCOUNT_HEX) {
|
|
if (pLine->lnCounterType == PERF_COUNTER_RAWCOUNT_HEX ||
|
|
pLine->lnaCounterValue[0].HighPart == 0) {
|
|
TSPRINTF (UnicodeBuff,
|
|
szHexFormat,
|
|
pLine->lnaCounterValue[0].LowPart) ;
|
|
} else {
|
|
TSPRINTF (UnicodeBuff,
|
|
szLargeHexFormat,
|
|
pLine->lnaCounterValue[0].HighPart,
|
|
pLine->lnaCounterValue[0].LowPart) ;
|
|
}
|
|
} else {
|
|
TSPRINTF (UnicodeBuff,
|
|
(eValue > eStatusLargeValueMax) ?
|
|
szLargeValueFormat : szValueFormat,
|
|
eValue) ;
|
|
ConvertDecimalPoint (UnicodeBuff) ;
|
|
}
|
|
ConvertUnicodeStr (&TempBuff[StringLen], UnicodeBuff) ;
|
|
} else {
|
|
// export "----" for unstable values
|
|
strcat (&TempBuff[StringLen], "----");
|
|
}
|
|
|
|
// write the line value
|
|
if (!FileWrite (hFile, TempBuff, strlen(TempBuff))) {
|
|
goto Exit0 ;
|
|
}
|
|
|
|
return (TRUE) ;
|
|
|
|
|
|
Exit0:
|
|
return (FALSE) ;
|
|
}
|
|
|
|
|
|
// This routine is need to insert the line values into its
|
|
// column location. It is needed because not all the instances (columns)
|
|
// are available for the same line.
|
|
void
|
|
SaveColumnLineData (
|
|
PLINE pLine,
|
|
LPSTR pColumnLineData
|
|
)
|
|
{
|
|
FLOAT eValue ;
|
|
LPSTR pColumnLine ;
|
|
CHAR TempBuff [LongTextLen] ;
|
|
TCHAR UnicodeBuff [LongTextLen] ;
|
|
|
|
if (!pColumnLineData || pLine->iReportColumn < 0) {
|
|
return ;
|
|
}
|
|
|
|
// find the offset into the pColumnLineData buffer for current line
|
|
pColumnLine = pColumnLineData + pLine->iReportColumn * ShortTextLen ;
|
|
|
|
if (pLine->bFirstTime == 0) {
|
|
eValue = CounterEntry (pLine) ;
|
|
|
|
|
|
if (pLine->lnCounterType == PERF_COUNTER_RAWCOUNT_HEX ||
|
|
pLine->lnCounterType == PERF_COUNTER_LARGE_RAWCOUNT_HEX) {
|
|
if (pLine->lnCounterType == PERF_COUNTER_RAWCOUNT_HEX ||
|
|
pLine->lnaCounterValue[0].HighPart == 0) {
|
|
TSPRINTF (UnicodeBuff,
|
|
szHexFormat,
|
|
pLine->lnaCounterValue[0].LowPart) ;
|
|
} else {
|
|
TSPRINTF (UnicodeBuff,
|
|
szLargeHexFormat,
|
|
pLine->lnaCounterValue[0].HighPart,
|
|
pLine->lnaCounterValue[0].LowPart) ;
|
|
}
|
|
} else {
|
|
TSPRINTF (UnicodeBuff,
|
|
(eValue > eStatusLargeValueMax) ?
|
|
szLargeValueFormat : szValueFormat,
|
|
eValue) ;
|
|
ConvertDecimalPoint (UnicodeBuff) ;
|
|
}
|
|
ConvertUnicodeStr (TempBuff, UnicodeBuff) ;
|
|
strncpy (pColumnLine, TempBuff, ShortTextLen) ;
|
|
*(pColumnLine + ShortTextLen - 1) = '\0' ;
|
|
} else {
|
|
// export "----" for unstable values
|
|
strcpy (pColumnLine, "----");
|
|
}
|
|
}
|
|
|
|
BOOL
|
|
ExportColumnLineData (
|
|
HANDLE hFile,
|
|
int ColumnTotal,
|
|
PCOUNTERGROUP pCounterGroup,
|
|
LPSTR pColumnLineData
|
|
)
|
|
{
|
|
int iIndex ;
|
|
int StringLen ;
|
|
CHAR TempBuff [LongTextLen] ;
|
|
LPSTR pCurrentLineData ;
|
|
|
|
// export the counter name
|
|
strcpy (TempBuff, pDelimiter) ;
|
|
StringLen = strlen (TempBuff) ;
|
|
ConvertUnicodeStr (&TempBuff[StringLen], pCounterGroup->pLineFirst->lnCounterName) ;
|
|
strcat (TempBuff, pDelimiter) ;
|
|
if (!FileWrite (hFile, TempBuff, strlen(TempBuff))) {
|
|
goto Exit0 ;
|
|
}
|
|
|
|
// go thru each column and export the line value if it has been stored
|
|
for (iIndex = 0, pCurrentLineData = pColumnLineData ;
|
|
iIndex < ColumnTotal ;
|
|
iIndex++, pCurrentLineData += ShortTextLen ) {
|
|
if (*pCurrentLineData != 0) {
|
|
// data available for this column
|
|
if (!FileWrite (hFile, pCurrentLineData, strlen(pCurrentLineData))) {
|
|
goto Exit0 ;
|
|
}
|
|
}
|
|
|
|
if (!FileWrite (hFile, pDelimiter, strlen(pDelimiter))) {
|
|
goto Exit0 ;
|
|
}
|
|
}
|
|
|
|
if (!FileWrite (hFile, LineEndStr, strlen(LineEndStr))) {
|
|
goto Exit0 ;
|
|
}
|
|
|
|
return (TRUE) ;
|
|
|
|
|
|
Exit0:
|
|
return (FALSE) ;
|
|
|
|
}
|
|
|
|
void
|
|
ExportReport (void)
|
|
{
|
|
HANDLE hFile = 0 ;
|
|
PREPORT pReport ;
|
|
PSYSTEMGROUP pSystemGroup ;
|
|
POBJECTGROUP pObjectGroup ;
|
|
PCOUNTERGROUP pCounterGroup ;
|
|
PLINE pLine ;
|
|
BOOL bExportComputer ;
|
|
BOOL bExportObject ;
|
|
BOOL bExportCounterName ;
|
|
int ColumnTotal = 0 ;
|
|
LPSTR pColumnLineData = NULL ;
|
|
LPTSTR pFileName = NULL ;
|
|
INT ErrCode = 0 ;
|
|
|
|
if (!(pReport = ReportData (hWndReport))) {
|
|
return ;
|
|
}
|
|
|
|
// see if there is anything to export..
|
|
if (!(pReport->pSystemGroupFirst)) {
|
|
return ;
|
|
}
|
|
|
|
SetHourglassCursor() ;
|
|
|
|
if (ErrCode = ExportFileOpen (hWndReport, &hFile,
|
|
pReport->iIntervalMSecs, &pFileName)) {
|
|
goto Exit0 ;
|
|
}
|
|
|
|
if (!pFileName) {
|
|
// the case when user cancel
|
|
goto Exit0 ;
|
|
}
|
|
|
|
// export each system group
|
|
|
|
for (pSystemGroup = pReport->pSystemGroupFirst ;
|
|
pSystemGroup ;
|
|
pSystemGroup = pSystemGroup->pSystemGroupNext) {
|
|
|
|
bExportComputer = TRUE ;
|
|
|
|
for (pObjectGroup = pSystemGroup->pObjectGroupFirst ;
|
|
pObjectGroup ;
|
|
pObjectGroup = pObjectGroup->pObjectGroupNext) {
|
|
|
|
bExportObject = TRUE ;
|
|
|
|
for (pCounterGroup = pObjectGroup->pCounterGroupFirst ;
|
|
pCounterGroup ;
|
|
pCounterGroup = pCounterGroup->pCounterGroupNext) {
|
|
|
|
bExportCounterName = TRUE ;
|
|
|
|
// Column data buffer has been allocated for this object type,
|
|
// zero out the buffer and prepare for next round.
|
|
|
|
if (pColumnLineData) {
|
|
memset (pColumnLineData, 0, ColumnTotal * ShortTextLen) ;
|
|
}
|
|
|
|
for (pLine = pCounterGroup->pLineFirst ;
|
|
pLine ;
|
|
pLine = pLine->pLineCounterNext) {
|
|
|
|
if (bExportComputer) {
|
|
// only need to do this for the first object
|
|
bExportComputer = FALSE ;
|
|
if (!ExportComputerName (hFile, pSystemGroup)) {
|
|
ErrCode = ERR_EXPORT_FILE ;
|
|
goto Exit0 ;
|
|
}
|
|
}
|
|
|
|
if (bExportObject) {
|
|
// only need to do this for the first counter group
|
|
bExportObject = FALSE ;
|
|
if (!ExportObjectName (hFile, pObjectGroup, &ColumnTotal)) {
|
|
ErrCode = ERR_EXPORT_FILE ;
|
|
goto Exit0 ;
|
|
}
|
|
|
|
if (ColumnTotal > 1) {
|
|
// special case to setup a column array and export
|
|
// the line values later
|
|
pColumnLineData = MemoryAllocate (ColumnTotal * ShortTextLen) ;
|
|
if (!pColumnLineData) {
|
|
ErrCode = ERR_EXPORT_FILE ;
|
|
goto Exit0 ;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (ColumnTotal > 1) {
|
|
// save the line value into its column & export later
|
|
SaveColumnLineData (pLine, pColumnLineData) ;
|
|
} else {
|
|
// simple case, export the line now
|
|
if (!ExportLineName (hFile, pLine, &bExportCounterName)) {
|
|
ErrCode = ERR_EXPORT_FILE ;
|
|
goto Exit0 ;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!bExportCounterName) {
|
|
// export the line end
|
|
if (!FileWrite (hFile, LineEndStr, strlen(LineEndStr))) {
|
|
ErrCode = ERR_EXPORT_FILE ;
|
|
goto Exit0 ;
|
|
}
|
|
}
|
|
|
|
if (pColumnLineData) {
|
|
// now, do the actual export
|
|
if (!ExportColumnLineData (hFile,
|
|
ColumnTotal,
|
|
pCounterGroup,
|
|
pColumnLineData)) {
|
|
ErrCode = ERR_EXPORT_FILE ;
|
|
goto Exit0 ;
|
|
}
|
|
}
|
|
}
|
|
|
|
// done with the object, done with the buffer
|
|
if (pColumnLineData) {
|
|
MemoryFree (pColumnLineData) ;
|
|
ColumnTotal = 0 ;
|
|
pColumnLineData = NULL ;
|
|
}
|
|
}
|
|
}
|
|
|
|
Exit0:
|
|
|
|
SetArrowCursor() ;
|
|
|
|
if (pColumnLineData) {
|
|
MemoryFree (pColumnLineData) ;
|
|
}
|
|
|
|
if (hFile) {
|
|
CloseHandle (hFile) ;
|
|
}
|
|
|
|
if (pFileName) {
|
|
if (ErrCode) {
|
|
DlgErrorBox (hWndGraph, ErrCode, pFileName) ;
|
|
}
|
|
|
|
MemoryFree (pFileName) ;
|
|
}
|
|
}
|