/***************************************************************************** * * 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 // for sprintf #include // 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) ; } }