home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / sdktools / winnt / perfmon / report.c < prev    next >
C/C++ Source or Header  |  1997-10-05  |  61KB  |  2,240 lines

  1. /*****************************************************************************
  2.  *
  3.  *  Report.c - This file contains the report window handler.  Some of the
  4.  *       support routines are in RptFct.c
  5.  *
  6.  *  Microsoft Confidential
  7.  *  Copyright (c) 1992-1997 Microsoft Corporation
  8.  *
  9.  *  Author -
  10.  *
  11.  *       Hon-Wah Chan
  12.  *
  13.  ****************************************************************************/
  14.  
  15. #include "perfmon.h"
  16. #include <stdio.h>      // for sprintf
  17. #include <string.h>     // for strncpy
  18. #include "report.h"     // Exported declarations for this file
  19.  
  20. #include "addline.h"    // for AddLine, EditLine
  21. #include "perferr.h"    // for PostError
  22. #include "fileutil.h"   // for FileHandleCreate
  23. #include "line.h"       // for LineAppend
  24. #include "pmemory.h"    // for MemoryXXX (mallloc-type) routines
  25. #include "perfdata.h"   // for UpdateLines
  26. #include "perfmops.h"   // for DoWindowDrag
  27. #include "playback.h"   // for PlaybackLines, PlayingBackLog
  28. #include "system.h"     // for SystemGet
  29. #include "utils.h"
  30. #include "menuids.h"    // for IDM_VIEWREPORT
  31. #include "fileopen.h"   // for FileGetName
  32. #include "counters.h"   // for CounterEntry
  33.  
  34.  
  35. //==========================================================================//
  36. //                                Local Data                                //
  37. //==========================================================================//
  38.  
  39. TCHAR          szSystemFormat [ResourceStringLen] ;
  40. TCHAR          szObjectFormat [ResourceStringLen] ;
  41.  
  42.  
  43. //=============================//
  44. // Report Class                //
  45. //=============================//
  46.  
  47.  
  48. TCHAR   szReportWindowClass[] = TEXT("PerfRpt") ;
  49. #define dwReportClassStyle           (CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS)
  50. #define iReportClassExtra            (0)
  51. #define iReportWindowExtra           (0)
  52. #define dwReportWindowStyle          (WS_CHILD | WS_VSCROLL | WS_HSCROLL)
  53.  
  54.  
  55. #define szValuePlaceholder          TEXT("-999999999.999")
  56. #define szValueLargeHexPlaceholder  TEXT(" xBBBBBBBBDDDDDDDD")
  57.  
  58. #define szHexFormat                 TEXT("x%08lX")
  59. #define szLargeHexFormat            TEXT("x%08lX%08lX")
  60. #define szLargeValueFormat          TEXT("%12.0f")
  61. #define eStatusLargeValueMax        ((FLOAT) 999999999.0)
  62. #define szValueFormat               TEXT("%12.3f")
  63.  
  64.  
  65. //==========================================================================//
  66. //                              Local Functions                             //
  67. //==========================================================================//
  68.  
  69.  
  70. PREPORT AllocateReportData (HWND hWndReport)
  71.    {
  72.    PREPORT        pReport ;
  73.  
  74.    pReport = ReportData (hWndReport) ;
  75.  
  76.    pReport->hWnd = hWndReport ;
  77.    pReport->iStatus = iPMStatusClosed ;
  78.    pReport->bManualRefresh = FALSE ;
  79.    pReport->bModified = FALSE ;
  80.  
  81.    pReport->Visual.iColorIndex = 0 ;
  82.    pReport->Visual.iWidthIndex = -1 ;
  83.    pReport->Visual.iStyleIndex = -1 ;
  84.  
  85.    pReport->iIntervalMSecs = iDefaultReportIntervalSecs * 1000 ;
  86.    pReport->pSystemFirst = NULL ;
  87.    pReport->pLineFirst = NULL ;
  88.  
  89.    pReport->CurrentItemType = REPORT_TYPE_NOTHING ;
  90.    pReport->CurrentItem.pLine = NULL ;
  91.  
  92.    return (pReport) ;
  93.    }  // AllocateReportData
  94.  
  95.  
  96. void FreeReportData (PREPORT pReport)
  97.    {  // FreeReportData
  98.    }  // FreeReportData
  99.  
  100.  
  101.  
  102. BOOL LineCounterRemove (PPLINE ppLineFirst,
  103.                         PLINE pLineRemove)
  104.    {
  105.    PLINE          pLine ;
  106.  
  107.    if (*ppLineFirst == pLineRemove)
  108.       {
  109.       *ppLineFirst = (*ppLineFirst)->pLineCounterNext ;
  110.       return (TRUE) ;
  111.       }
  112.  
  113.    for (pLine = *ppLineFirst ;
  114.         pLine->pLineCounterNext ;
  115.         pLine = pLine->pLineCounterNext)
  116.       {   // for
  117.       if (pLine->pLineCounterNext == pLineRemove)
  118.          {
  119.          pLine->pLineCounterNext = pLineRemove->pLineCounterNext ;
  120.          return (TRUE) ;
  121.          }  // if
  122.       }  // for
  123.  
  124.    return (FALSE) ;
  125.    }  // LineCounterRemove
  126.  
  127.  
  128.  
  129. void DrawCounter (HDC hDC, PREPORT pReport,
  130.                   PCOUNTERGROUP pCounterGroup)
  131.    {  // DrawCounter
  132.      
  133.    RECT  Rect ;
  134.  
  135.  
  136.    if (!pCounterGroup->pLineFirst)
  137.       return ;
  138.  
  139.    SelectFont (hDC, pReport->hFont) ;
  140.    TextOut (hDC, xCounterMargin, pCounterGroup->yLine,
  141.             pCounterGroup->pLineFirst->lnCounterName,
  142.             lstrlen (pCounterGroup->pLineFirst->lnCounterName)) ;
  143.  
  144.    if (pCounterGroup == pReport->CurrentItem.pCounter)
  145.       {
  146.       ReportCounterRect (pReport, pCounterGroup, &Rect) ;
  147.       DrawFocusRect (hDC, &Rect) ;
  148.       }
  149.  
  150.    }  // DrawCounter
  151.  
  152.  
  153. void DrawObject (HDC hDC, PREPORT pReport,
  154.                  POBJECTGROUP pObjectGroup)
  155.    {  // DrawObject
  156.    TCHAR          szLine [LongTextLen] ;
  157.    PCOUNTERGROUP  pCounterGroup ;
  158.    PCOLUMNGROUP   pColumnGroup ;
  159.  
  160.    if (!pObjectGroup->pCounterGroupFirst)
  161.       {
  162.       return ;
  163.       }
  164.  
  165.    SelectFont (hDC, pReport->hFontHeaders) ;
  166.  
  167.    SetTextAlign (hDC, TA_RIGHT) ;
  168.  
  169.    for (pColumnGroup = pObjectGroup->pColumnGroupFirst ;
  170.         pColumnGroup ;
  171.         pColumnGroup = pColumnGroup->pColumnGroupNext)
  172.       {  // for
  173.       // Draw Parent
  174.       if (pColumnGroup->lpszParentName)
  175.          TextOut (hDC, 
  176.                   ValueMargin (pReport) + 
  177.                   pColumnGroup->xPos + pColumnGroup->xWidth,
  178.                   pObjectGroup->yFirstLine - pReport->yLineHeight,
  179.                   pColumnGroup->lpszParentName,
  180.                   lstrlen (pColumnGroup->lpszParentName)) ;
  181.  
  182.       // Draw Instance
  183.       if (pColumnGroup->lpszInstanceName)
  184.          {
  185.          TextOut (hDC, 
  186.                   ValueMargin (pReport) + 
  187.                   pColumnGroup->xPos + pColumnGroup->xWidth,
  188.                   pObjectGroup->yFirstLine,
  189.                   pColumnGroup->lpszInstanceName,
  190.                   lstrlen (pColumnGroup->lpszInstanceName)) ;
  191.          }
  192.  
  193.       if (pColumnGroup == pReport->CurrentItem.pColumn)
  194.          {
  195.          RECT  Rect ;
  196.  
  197.          ReportColumnRect (pReport, pColumnGroup, &Rect) ;
  198.          DrawFocusRect (hDC, &Rect) ;
  199.          }
  200.  
  201.       }  // for
  202.    SetTextAlign (hDC, TA_LEFT) ;
  203.  
  204.    TSPRINTF (szLine, szObjectFormat, pObjectGroup->lpszObjectName) ;
  205.    TextOut (hDC, 
  206.             xObjectMargin, pObjectGroup->yFirstLine,
  207.             szLine, lstrlen (szLine)) ;
  208.  
  209.    if (pObjectGroup == pReport->CurrentItem.pObject)
  210.       {
  211.       RECT  Rect ;
  212.  
  213.       ReportObjectRect (pReport, pObjectGroup, &Rect) ;
  214.       DrawFocusRect (hDC, &Rect) ;
  215.       }
  216.  
  217.    SelectFont (hDC, pReport->hFont) ;
  218.  
  219.    for (pCounterGroup = pObjectGroup->pCounterGroupFirst ;
  220.         pCounterGroup ;
  221.         pCounterGroup = pCounterGroup->pCounterGroupNext)
  222.       {  // for
  223.       DrawCounter (hDC, pReport, pCounterGroup) ;
  224.       }  // for
  225.  
  226.    }  // DrawObject
  227.  
  228.  
  229. void DrawSystem (HDC hDC, PREPORT pReport, PSYSTEMGROUP pSystemGroup)
  230.    {  // DrawSystem
  231.    TCHAR          szLine [LongTextLen] ;
  232.    POBJECTGROUP   pObjectGroup ;
  233.  
  234.    SelectFont (hDC, pReport->hFontHeaders) ;
  235.  
  236.    if (!pSystemGroup->pObjectGroupFirst)
  237.       return ;
  238.  
  239.    SetTextAlign (hDC, TA_LEFT) ;
  240.    TSPRINTF (szLine, szSystemFormat, pSystemGroup->lpszSystemName) ;
  241.    TextOut (hDC, 
  242.             xSystemMargin, pSystemGroup->yFirstLine,
  243.             szLine, lstrlen (szLine)) ;
  244.  
  245.    if (pSystemGroup == pReport->CurrentItem.pSystem)
  246.       {
  247.       RECT  Rect ;
  248.  
  249.       ReportSystemRect (pReport, pSystemGroup, &Rect) ;
  250.       DrawFocusRect (hDC, &Rect) ;
  251.       }
  252.  
  253.    for (pObjectGroup = pSystemGroup->pObjectGroupFirst ;
  254.         pObjectGroup ;
  255.         pObjectGroup = pObjectGroup->pObjectGroupNext)
  256.       {  // for
  257.       DrawObject (hDC, pReport, pObjectGroup) ;
  258.       }  // for
  259.    }  // DrawSystem
  260.  
  261. void DrawReportValue (HDC hDC, PREPORT pReport, PLINE pLine)
  262.    {  // DrawReportValue
  263.    TCHAR          szValue [20] ;
  264.    FLOAT          eValue ;
  265.    RECT           rectValue ;
  266.  
  267.    // skip until we have collect enough samples for the first data
  268.    if (pLine->bFirstTime == 0)
  269.       {
  270.       eValue = CounterEntry (pLine) ;
  271.       if (pLine->lnCounterType == PERF_COUNTER_RAWCOUNT_HEX ||
  272.           pLine->lnCounterType == PERF_COUNTER_LARGE_RAWCOUNT_HEX)
  273.          {
  274.          DWORD LowValue  ;
  275.          DWORD HighValue ;
  276.  
  277.          LowValue  = (DWORD) (pLine->lnaCounterValue[0]) ;
  278.          HighValue = (DWORD) (pLine->lnaCounterValue[0] >> 32);
  279.  
  280.          if (pLine->lnCounterType == PERF_COUNTER_RAWCOUNT_HEX ||
  281.              HighValue == 0)
  282.             {
  283.             TSPRINTF (szValue,
  284.                       szHexFormat,
  285.                       LowValue) ;
  286.             }
  287.          else
  288.             {
  289.  
  290.             TSPRINTF (szValue,
  291.                       szLargeHexFormat,
  292.                       HighValue,
  293.                       LowValue) ;
  294.             }
  295.          }
  296.       else
  297.          {
  298.          TSPRINTF (szValue,
  299.                    (eValue > eStatusLargeValueMax) ?
  300.                        szLargeValueFormat : szValueFormat,
  301.                    eValue) ;
  302.          ConvertDecimalPoint (szValue) ;
  303.          }
  304.       }
  305.    else
  306.       {
  307.       // draw "- - - -"
  308.       lstrcpy(szValue, DashLine);
  309.       }
  310.  
  311.    ReportLineValueRect (pReport, pLine, &rectValue) ;
  312.    
  313.    ExtTextOut (hDC, 
  314.                rectValue.right - 2, rectValue.top,
  315.                ETO_CLIPPED | ETO_OPAQUE,
  316.                &rectValue,
  317.                szValue, lstrlen (szValue), NULL) ;
  318.  
  319.    if (pReport->CurrentItemType == REPORT_TYPE_LINE &&
  320.        pLine == pReport->CurrentItem.pLine)
  321.       {
  322.       DrawFocusRect (hDC, &rectValue) ;
  323.       }
  324.    }  // DrawReportValue
  325.  
  326.  
  327. void DrawReportValues (HDC hDC, PREPORT pReport)
  328.    {
  329.    PSYSTEMGROUP   pSystemGroup ;
  330.    POBJECTGROUP   pObjectGroup ;
  331.    PCOUNTERGROUP  pCounterGroup ;
  332.    PLINE          pLine ;
  333.  
  334.    SelectFont (hDC, pReport->hFont) ;
  335.    SetTextAlign (hDC, TA_RIGHT) ;
  336.  
  337.    for (pSystemGroup = pReport->pSystemGroupFirst ;
  338.         pSystemGroup ;
  339.         pSystemGroup = pSystemGroup->pSystemGroupNext)
  340.       {  // for System...
  341.       for (pObjectGroup = pSystemGroup->pObjectGroupFirst ;
  342.            pObjectGroup ;
  343.            pObjectGroup = pObjectGroup->pObjectGroupNext)
  344.          {  // for Object...
  345.          for (pCounterGroup = pObjectGroup->pCounterGroupFirst ;
  346.               pCounterGroup ;
  347.               pCounterGroup = pCounterGroup->pCounterGroupNext)
  348.             {  // for Counter...
  349.             for (pLine = pCounterGroup->pLineFirst ;
  350.                  pLine ;
  351.                  pLine = pLine->pLineCounterNext)
  352.                {  // for Line...
  353.                DrawReportValue (hDC, pReport, pLine) ;
  354.                }  // for Line...
  355.             }  // for Counter...
  356.          }  // for Object      
  357.       }  // for System...
  358.  
  359.    }
  360.  
  361.  
  362. void DrawReportHeaders (HDC hDC, PREPORT pReport)
  363.    {  // DrawReportHeaders
  364.    PSYSTEMGROUP   pSystemGroup ;
  365.  
  366.    for (pSystemGroup = pReport->pSystemGroupFirst ;
  367.         pSystemGroup ;
  368.         pSystemGroup = pSystemGroup->pSystemGroupNext)
  369.       {  // for
  370.       DrawSystem (hDC, pReport, pSystemGroup) ;
  371.       }  // for         
  372.    }  // DrawReportHeaders
  373.  
  374.  
  375. void DrawReport (HDC hDC, PREPORT pReport)
  376.    {
  377.    SetBkColor (hDC, GetSysColor(COLOR_WINDOW)) ;
  378.    DrawReportHeaders (hDC, pReport) ;
  379.    //UpdateLines (&(pReport->pSystemFirst), pReport->pLineFirst) ;
  380.    DrawReportValues (hDC, pReport) ;
  381.    }
  382.  
  383.  
  384.  
  385. void SetLinePosition (HDC hDC,
  386.                       PREPORT pReport, 
  387.                       POBJECTGROUP pObjectGroup,
  388.                       PLINE pLine)
  389.    {  // SetLinePositions
  390.    PCOLUMNGROUP   pColumnGroup ;
  391.  
  392.    pColumnGroup = GetColumnGroup (pReport, pObjectGroup, pLine) ;
  393.    if (!pColumnGroup)
  394.       {
  395.       pLine->xReportPos = 0 ;
  396.       pLine->iReportColumn = -1 ;
  397.       }
  398.    else
  399.       {
  400.       pLine->xReportPos = pColumnGroup->xPos ;
  401.       pLine->iReportColumn = pColumnGroup->ColumnNumber ;
  402.       }
  403.    }  // SetLinePosition
  404.  
  405.  
  406. void SetCounterPositions (HDC hDC,
  407.                           PREPORT pReport,
  408.                           POBJECTGROUP pObjectGroup,
  409.                           PCOUNTERGROUP pCounterGroup,
  410.                           int yLine)
  411.    {  // SetCounterPositions
  412.    PLINE          pLine ;
  413.    int            yPos ;
  414.  
  415.  
  416.    if (!pCounterGroup->pLineFirst)
  417.       return ;
  418.  
  419.    yPos = pCounterGroup->yLine ;
  420.  
  421.    SelectFont (hDC, pReport->hFontHeaders) ;
  422.  
  423.    for (pLine = pCounterGroup->pLineFirst ;
  424.         pLine ;
  425.         pLine = pLine->pLineCounterNext)
  426.       {  // for
  427.       SetLinePosition (hDC, pReport, pObjectGroup, pLine) ;
  428.       pLine->yReportPos = yPos ;
  429.       }  // for
  430.    }  // SetCounterPositions
  431.  
  432.  
  433. void SetColumnPositions (HDC hDC,
  434.                          PREPORT pReport,
  435.                          POBJECTGROUP pObjectGroup)
  436.    {  // SetColumnPositions
  437.    int            xPos ;
  438.    PCOLUMNGROUP   pColumnGroup ;
  439.  
  440.    xPos = 0 ;
  441.    for (pColumnGroup = pObjectGroup->pColumnGroupFirst ;
  442.         pColumnGroup ;
  443.         pColumnGroup = pColumnGroup->pColumnGroupNext)
  444.       {  // for
  445.       pColumnGroup->xWidth = max (max (pColumnGroup->ParentNameTextWidth,
  446.                                        pColumnGroup->InstanceNameTextWidth),
  447.                                   pReport->xValueWidth) ;
  448.       pColumnGroup->xPos = xPos ;
  449.       pColumnGroup->yFirstLine = pObjectGroup->yFirstLine ;
  450.       xPos += (pColumnGroup->xWidth + xColumnMargin) ;
  451.       }  // for
  452.    }  // SetColumnPositions
  453.  
  454.  
  455. void SetObjectPositions (HDC hDC,
  456.                          PREPORT pReport,
  457.                          POBJECTGROUP pObjectGroup,
  458.                          int yLine)
  459. /*
  460.    Effect:        Determine and set the logical coordinates for the
  461.                   object pObject within the report pReport.
  462.  
  463.                   For each instance x counter, determine the appropriate
  464.                   column, adding a column description to the object if
  465.                   needed.
  466.  
  467.    Called By:     SetSystemPositions only.
  468.  
  469.    See Also:      SetSystemPositions, SetCounterPositions, ColumnGroup.
  470. */
  471.    {  // SetObjectPositions
  472.    PCOUNTERGROUP  pCounterGroup ;
  473.    int            yPos ;
  474.    PLINE          pLine ;
  475.  
  476.    // check if there is parnet name for this object type
  477.    // if so, need to add extra space for the parent name
  478.    if (pObjectGroup->pCounterGroupFirst)
  479.       {
  480.       pCounterGroup = pObjectGroup->pCounterGroupFirst ;
  481.       pLine = pCounterGroup->pLineFirst ;
  482.       if (pLine && LineParentName(pLine))
  483.          {
  484.          pObjectGroup->yFirstLine += yLine ;
  485.          }
  486.       }
  487.  
  488.    SetColumnPositions (hDC, pReport, pObjectGroup) ;
  489.  
  490.    yPos = pObjectGroup->yFirstLine + yLine ;
  491.  
  492.    for (pCounterGroup = pObjectGroup->pCounterGroupFirst ;
  493.         pCounterGroup ;
  494.         pCounterGroup = pCounterGroup->pCounterGroupNext)
  495.       {  // for
  496.       pCounterGroup->yLine = yPos + yLine ;
  497.    
  498.       SetCounterPositions (hDC, pReport, pObjectGroup, pCounterGroup, yLine) ;
  499.  
  500.       yPos = pCounterGroup->yLine ;
  501.       }  // for
  502.  
  503.    pObjectGroup->yLastLine = yPos + yLine ;
  504.    }  // SetObjectPositions
  505.  
  506.  
  507. void SetSystemPositions (HDC hDC,
  508.                          PREPORT pReport, 
  509.                          PSYSTEMGROUP pSystemGroup,
  510.                          int yLine)
  511.    {  // SetSystemPositions
  512.    POBJECTGROUP   pObjectGroup ;
  513.    int            yPos ;
  514.  
  515.    yPos = pSystemGroup->yFirstLine ;
  516.  
  517.    for (pObjectGroup = pSystemGroup->pObjectGroupFirst ;
  518.         pObjectGroup ;
  519.         pObjectGroup = pObjectGroup->pObjectGroupNext)
  520.       {  // for
  521.       pObjectGroup->yFirstLine = yPos + yLine ;
  522.    
  523.       SetObjectPositions (hDC, pReport, pObjectGroup, yLine) ;
  524.  
  525.       yPos = pObjectGroup->yLastLine ;
  526.       }  // for
  527.  
  528.    pSystemGroup->yLastLine = yPos + yLine ;
  529.    }  // SetSystemPositions
  530.  
  531.  
  532. void static SetScrollRanges (HWND hWnd)
  533.    {  // SetScrollRanges
  534.    PREPORT        pReport ;
  535.    RECT           rectClient ;
  536.    int            xWidth, yHeight ;
  537.  
  538.    GetClientRect (hWnd, &rectClient) ;
  539.    xWidth = rectClient.right - rectClient.left ;
  540.    yHeight = rectClient.bottom - rectClient.top ;
  541.  
  542.    pReport = ReportData (hWnd) ;
  543.  
  544.    SetScrollRange (hWnd, SB_VERT, 
  545.                    0, max (0, pReport->yHeight - yHeight), 
  546.                    TRUE) ;
  547.    SetScrollRange (hWnd, SB_HORZ,
  548.                    0, max (0, pReport->xWidth - xWidth),
  549.                    TRUE) ;
  550.    }  // SetScrollRanges
  551.  
  552. //==========================================================================//
  553. //                              Message Handlers                            //
  554. //==========================================================================//
  555.  
  556.  
  557. void static OnCreate (HWND hWnd)
  558.    {  // OnCreate
  559.    HDC            hDC ;
  560.    PREPORT        pReport ;
  561.  
  562.    pReport = AllocateReportData (hWnd) ;
  563.    if (!pReport)
  564.       return ;
  565.  
  566.    pReport->hFont = hFontScales ;
  567.    pReport->hFontHeaders = hFontScalesBold ;
  568.  
  569.    pReport->pLineFirst = NULL ;
  570.    pReport->pSystemFirst = NULL ;
  571.  
  572.    pReport->pSystemGroupFirst = NULL ;
  573.  
  574.    hDC = GetDC (hWnd) ;
  575.  
  576.    SelectFont (hDC, pReport->hFont) ;
  577.  
  578.  
  579.    pReport->yLineHeight = FontHeight (hDC, TRUE) ;
  580.    pReport->xValueWidth = TextWidth (hDC, szValuePlaceholder) ;
  581.    ReleaseDC (hWnd, hDC) ;
  582.  
  583.    pReport->xWidth = 0 ;
  584.    pReport->yHeight = 0 ;
  585.  
  586.    StringLoad (IDS_SYSTEMFORMAT, szSystemFormat) ;
  587.    StringLoad (IDS_OBJECTFORMAT, szObjectFormat) ;
  588.    }  // OnCreate
  589.  
  590.  
  591. void static OnPaint (HWND hWnd)
  592.    {
  593.    HDC            hDC ;
  594.    PAINTSTRUCT    ps ;
  595.    PREPORT        pReport ;
  596.  
  597.  
  598.  
  599.    pReport = ReportData (hWnd) ;
  600.  
  601.    hDC = BeginPaint (hWnd, &ps) ;
  602.    //hDC = hReportDC ;
  603.    SetWindowOrgEx (hDC, 
  604.                    GetScrollPos (hWnd, SB_HORZ), 
  605.                    GetScrollPos (hWnd, SB_VERT),
  606.                    NULL) ;
  607.  
  608.    DrawReport (hDC, pReport) ;
  609.  
  610.    EndPaint (hWnd, &ps) ;
  611.    }
  612.  
  613.  
  614. void static UpdateReportValues (PREPORT pReport)
  615. /*
  616.    Effect:        Redraw all the visible report values of pReport.
  617.                   Since drawing the values completely covers any 
  618.                   previous values, there is no need to erase (or flicker)
  619.                   between updating values.
  620.  
  621.    Called By:     ReportTimer, OnVScroll, OnHScroll.
  622. */
  623.    {  // UpdateReportValues
  624.    HDC            hDC ;
  625.  
  626.    hDC = GetDC (pReport->hWnd) ;
  627.  
  628.    SetBkColor (hDC, GetSysColor(COLOR_WINDOW)) ;
  629.    SetWindowOrgEx (hDC, 
  630.                    GetScrollPos (pReport->hWnd, SB_HORZ), 
  631.                    GetScrollPos (pReport->hWnd, SB_VERT),
  632.                    NULL) ;
  633.  
  634.    DrawReportValues (hDC, pReport) ;
  635.    ReleaseDC (pReport->hWnd, hDC) ;
  636.  
  637.    }  // UpdateReportValues
  638.  
  639.  
  640.  
  641. void static OnHScroll (HWND hWnd,
  642.                        int iScrollCode,
  643.                        int iScrollNewPos)
  644.    {  // OnHScroll
  645.    PREPORT        pReport ;
  646.    int            iScrollAmt, iScrollPos, iScrollRange ;
  647.    int            iScrollLo ;
  648.    RECT           rectClient ;
  649.    int            xWidth ;
  650.  
  651.    pReport = ReportData (hWnd) ;
  652.  
  653.    GetClientRect (hWnd, &rectClient) ;
  654.    xWidth = rectClient.right - rectClient.left ;
  655.  
  656.    if (pReport->xWidth <= xWidth)
  657.       {
  658.       // no horz scroll bar, forget it
  659.       return ;
  660.       }
  661.  
  662.    iScrollPos = GetScrollPos (hWnd, SB_HORZ) ;
  663.  
  664.    GetScrollRange (hWnd, SB_HORZ, &iScrollLo, &iScrollRange) ;
  665.  
  666.  
  667.    switch (iScrollCode)
  668.       {
  669.       case SB_LINEUP:
  670.            iScrollAmt = - Report.yLineHeight ;
  671.            break ;
  672.  
  673.       case SB_LINEDOWN:
  674.            iScrollAmt = Report.yLineHeight ;
  675.            break ;
  676.  
  677.       case SB_PAGEUP:
  678.            iScrollAmt = - (rectClient.right - rectClient.left) / 2 ;
  679.            break ;
  680.  
  681.       case SB_PAGEDOWN:
  682.            iScrollAmt = (rectClient.right - rectClient.left) / 2 ;
  683.            break ;
  684.  
  685.       case SB_THUMBPOSITION:
  686.            iScrollAmt = iScrollNewPos - iScrollPos ;
  687.            break ;
  688.  
  689.       default:
  690.            iScrollAmt = 0 ;
  691.       }  // switch
  692.  
  693.      iScrollAmt = PinInclusive (iScrollAmt,
  694.                                 -iScrollPos,
  695.                                 iScrollRange - iScrollPos) ;
  696.      if (iScrollAmt)
  697.         {
  698.         iScrollPos += iScrollAmt ;
  699.         ScrollWindow (hWnd, -iScrollAmt, 0, NULL, NULL) ;
  700.         SetScrollPos (hWnd, SB_HORZ, iScrollPos, TRUE) ;
  701.         UpdateWindow (hWnd) ;
  702. #if 0
  703.         UpdateReportValues (pReport) ;
  704. #endif
  705.         }
  706.    }  // OnHScroll
  707.  
  708.  
  709.  
  710. void static OnVScroll (HWND hWnd,
  711.                        int iScrollCode,
  712.                        int iScrollNewPos)
  713.    {  // OnVScroll
  714.    PREPORT        pReport ;
  715.    int            iScrollAmt, iScrollPos, iScrollRange ;
  716.    int            iScrollLo ;
  717.    RECT           rectClient ;
  718.  
  719.    pReport = ReportData (hWnd) ;
  720.  
  721.    iScrollPos = GetScrollPos (hWnd, SB_VERT) ;
  722.    GetScrollRange (hWnd, SB_VERT, &iScrollLo, &iScrollRange) ;
  723.  
  724.    GetClientRect (hWnd, &rectClient) ;
  725.  
  726.    switch (iScrollCode)
  727.       {
  728.       case SB_LINEUP:
  729.            iScrollAmt = - Report.yLineHeight ;
  730.            break ;
  731.  
  732.       case SB_LINEDOWN:
  733.            iScrollAmt = Report.yLineHeight ;
  734.            break ;
  735.  
  736.       case SB_PAGEUP:
  737.            iScrollAmt = - (rectClient.bottom - rectClient.top) / 2 ;
  738.            break ;
  739.  
  740.       case SB_PAGEDOWN:
  741.            iScrollAmt = (rectClient.bottom - rectClient.top) / 2 ;
  742.            break ;
  743.  
  744.       case SB_THUMBPOSITION:
  745.            iScrollAmt = iScrollNewPos - iScrollPos ;
  746.            break ;
  747.  
  748.       default:
  749.            iScrollAmt = 0 ;
  750.       }  // switch
  751.  
  752.      iScrollAmt = PinInclusive (iScrollAmt,
  753.                                 -iScrollPos,
  754.                                 iScrollRange - iScrollPos) ;
  755.      if (iScrollAmt)
  756.         {
  757.         iScrollPos += iScrollAmt ;
  758.         ScrollWindow (hWnd, 0, -iScrollAmt, NULL, NULL) ;
  759.         SetScrollPos (hWnd, SB_VERT, iScrollPos, TRUE) ;
  760.  
  761. //        WindowInvalidate (hWnd) ;
  762.         UpdateWindow (hWnd) ;
  763. #if 0
  764.         UpdateReportValues (pReport) ;        
  765. #endif
  766.         }
  767.    }  // OnVScroll
  768.  
  769. void static OnKeyDown (HWND hWnd, DWORD wParam)
  770.    {
  771.    switch (wParam)
  772.       {
  773.       case VK_UP:
  774.          OnVScroll (hWnd, SB_LINEUP, 0) ;
  775.          break ;
  776.  
  777.       case VK_DOWN:
  778.          OnVScroll (hWnd, SB_LINEDOWN, 0) ;
  779.          break ;
  780.  
  781.       case VK_LEFT:
  782.          OnHScroll (hWnd, SB_LINEUP, 0) ;
  783.          break ;
  784.  
  785.       case VK_RIGHT:
  786.          OnHScroll (hWnd, SB_LINEDOWN, 0) ;
  787.          break ;
  788.  
  789.       case VK_PRIOR:
  790.          OnVScroll (hWnd, SB_PAGEUP, 0) ;
  791.          break ;
  792.  
  793.       case VK_NEXT:
  794.          OnVScroll (hWnd, SB_PAGEDOWN, 0) ;
  795.          break ;
  796.       }
  797.    }  // OnKeyDown
  798.        
  799.          
  800. LRESULT APIENTRY ReportWndProc (HWND hWnd,
  801.                                WORD wMsg,
  802.                                DWORD wParam,
  803.                                LONG lParam)
  804.    {  // ReportWndProc
  805.    BOOL           bCallDefProc ;
  806.    LRESULT        lReturnValue ;
  807.  
  808.    bCallDefProc = FALSE ;
  809.    lReturnValue = 0L ;
  810.  
  811.    switch (wMsg)
  812.       {  // switch
  813.       case WM_CREATE:
  814.          OnCreate (hWnd) ;
  815.          break ;
  816.  
  817.       case WM_LBUTTONDOWN:
  818.  
  819.          if (!OnReportLButtonDown (hWnd, LOWORD (lParam), HIWORD (lParam)))
  820.             {
  821.             // mouse click do not hit on any entries, see if we 
  822.             // need to drag Perfmon
  823.             if (!(Options.bMenubar))
  824.                {
  825.                DoWindowDrag (hWnd, lParam) ;
  826.                }
  827.             }
  828.          break ;
  829.  
  830.       case WM_LBUTTONDBLCLK:
  831.          SendMessage (hWndMain, WM_LBUTTONDBLCLK, wParam, lParam) ;
  832.          break ;
  833.  
  834.       case WM_PAINT:
  835.          OnPaint (hWnd) ;
  836.          break ;
  837.  
  838.       case WM_SIZE:
  839.          SetScrollRanges (hWnd) ;
  840.          break ;
  841.  
  842.       case WM_HSCROLL:
  843.          OnHScroll (hWnd, LOWORD (wParam), HIWORD (wParam)) ;
  844.          break ;
  845.  
  846.       case WM_VSCROLL:
  847.          OnVScroll (hWnd, LOWORD (wParam), HIWORD (wParam)) ;
  848.          break ;
  849.  
  850.       case WM_TIMER:
  851.          ReportTimer (hWnd, FALSE) ;
  852.          break ;
  853.  
  854.       case WM_KEYDOWN:
  855.          OnKeyDown (hWnd, wParam) ;
  856.          break ;
  857.  
  858.       case WM_DESTROY:
  859.          KillTimer (hWnd, ReportTimerID) ;
  860.          break ;
  861.  
  862.       default:
  863.          bCallDefProc = TRUE ;
  864.       }  // switch
  865.  
  866.  
  867.    if (bCallDefProc)
  868.       lReturnValue = DefWindowProc (hWnd, wMsg, wParam, lParam) ;
  869.  
  870.    return (lReturnValue);
  871.    }  // ReportWndProc
  872.  
  873.  
  874.  
  875. //==========================================================================//
  876. //                             Exported Functions                           //
  877. //==========================================================================//
  878.  
  879. #if 0
  880. PREPORT ReportData (HWND hWndReport)
  881.    {
  882.    return (&Report) ;
  883.    }
  884. #endif
  885.  
  886. void SetReportTimer (PREPORT pReport)
  887.    {  
  888.    if (pReport->iStatus == iPMStatusCollecting)
  889.       KillTimer (pReport->hWnd, ReportTimerID) ;
  890.  
  891.    SetTimer (pReport->hWnd, ReportTimerID, 
  892.              pReport->iIntervalMSecs , NULL) ;
  893.    pReport->iStatus = iPMStatusCollecting ;
  894.    }
  895.  
  896.  
  897. void ClearReportTimer (PREPORT pReport)
  898.    {
  899.    pReport->iStatus = iPMStatusClosed ;
  900.    KillTimer (pReport->hWnd, ReportTimerID) ;
  901.    }
  902.  
  903.  
  904. BOOL ReportInitializeApplication (void)
  905.    {  // ReportInitializeApplication
  906.    BOOL           bSuccess ;
  907.    WNDCLASS       wc ;
  908.  
  909.    //=============================//
  910.    // Register ReportWindow class  //
  911.    //=============================//
  912.  
  913.  
  914.    wc.style         = dwReportClassStyle ;
  915.    wc.lpfnWndProc   = (WNDPROC) ReportWndProc ;
  916.    wc.hInstance     = hInstance ;
  917.    wc.cbClsExtra    = iReportWindowExtra ;
  918.    wc.cbWndExtra    = iReportClassExtra ;
  919.    wc.hIcon         = NULL ;
  920.    wc.hCursor       = LoadCursor(NULL, IDC_ARROW) ;
  921. //   wc.hbrBackground = GetStockObject (WHITE_BRUSH) ;
  922.    wc.hbrBackground =   (HBRUSH) (COLOR_WINDOW + 1) ;
  923.    wc.lpszMenuName  = NULL ;
  924.    wc.lpszClassName = szReportWindowClass ;
  925.  
  926.    bSuccess = RegisterClass (&wc) ;
  927.  
  928.  
  929.    //=============================//
  930.    // Register Child classes      //
  931.    //=============================//
  932.  
  933.    return (bSuccess) ;
  934.    }  // ReportInitializeApplication
  935.  
  936.  
  937.  
  938.  
  939.  
  940. HWND CreateReportWindow (HWND hWndParent)
  941. /*
  942.    Effect:        Create the graph window. This window is a child of 
  943.                   hWndMain and is a container for the graph data,
  944.                   graph label, graph legend, and graph status windows.
  945.  
  946.    Note:          We dont worry about the size here, as this window
  947.                   will be resized whenever the main window is resized.
  948.  
  949. */
  950.    {
  951.    return (CreateWindow (szReportWindowClass,       // window class
  952.                          NULL,                     // caption
  953.                          dwReportWindowStyle,       // style for window
  954.                          0, 0,                     // initial position
  955.                          0, 0,                     // initial size
  956.                          hWndParent,               // parent
  957.                          NULL,                     // menu
  958.                          hInstance,               // program instance
  959.                          NULL)) ;                  // user-supplied data                                              
  960.    }  // CreateReportWindow
  961.  
  962.  
  963.  
  964. void SetReportPositions (HDC hDC,
  965.                          PREPORT pReport)
  966.    {
  967.    PSYSTEMGROUP   pSystemGroup ;
  968.    int            yLine ;
  969.    int            yPos ;
  970.  
  971.   
  972. //   pReport->xMaxCounterWidth = 0 ;
  973.  
  974.    yLine = pReport->yLineHeight ;
  975.    yPos = 2 * yLine ;
  976.  
  977.    for (pSystemGroup = pReport->pSystemGroupFirst ;
  978.         pSystemGroup ;
  979.         pSystemGroup = pSystemGroup->pSystemGroupNext)
  980.       {  // for
  981.       pSystemGroup->yFirstLine = yPos + yLine ;
  982.  
  983.       SetSystemPositions (hDC, pReport, pSystemGroup, yLine) ;
  984.  
  985.       yPos = pSystemGroup->yLastLine ;
  986.       }  // for 
  987.  
  988.    pReport->yHeight = yPos ;
  989.  
  990.    SetScrollRanges (pReport->hWnd) ;
  991.    }  // SetReportPositions
  992.  
  993.  
  994.  
  995. void PlaybackReport (HWND hWndReport)
  996.    {  // PlaybackReport
  997.    PREPORT        pReport ;
  998.  
  999.    pReport = ReportData (hWndReport) ;
  1000.  
  1001.    PlaybackLines (pReport->pSystemFirst, 
  1002.                   pReport->pLineFirst, 
  1003.                   PlaybackLog.StartIndexPos.iPosition) ;
  1004.    PlaybackLines (pReport->pSystemFirst, 
  1005.                   pReport->pLineFirst, 
  1006.                   PlaybackLog.StopIndexPos.iPosition) ;
  1007.    }  // PlaybackReport
  1008.  
  1009.  
  1010. BOOL CurrentReportItem (HWND hWndReport)
  1011.    {  // CurrentReportItem
  1012.    PREPORT        pReport ;
  1013.  
  1014.    pReport = ReportData (hWndReport) ;
  1015.    if (!pReport)
  1016.       return (FALSE) ;
  1017.  
  1018.    return (pReport->CurrentItemType != REPORT_TYPE_NOTHING) ;
  1019.    }  // CurrentReportItem
  1020.  
  1021.  
  1022.  
  1023. BOOL AddReport (HWND hWndParent)
  1024.    {
  1025.    PREPORT        pReport ;
  1026.    LPTSTR         pCurrentSystem ;
  1027.    POBJECTGROUP  pParentObject ;
  1028.  
  1029.    pReport = ReportData (hWndReport) ;
  1030.  
  1031.    if (pReport->CurrentItemType == REPORT_TYPE_LINE)
  1032.       {
  1033.       pCurrentSystem = pReport->CurrentItem.pLine->lnSystemName ;
  1034.       }
  1035.    else if (pReport->CurrentItemType == REPORT_TYPE_SYSTEM)
  1036.       {
  1037.       pCurrentSystem = pReport->CurrentItem.pSystem->lpszSystemName ;
  1038.       }
  1039.    else if (pReport->CurrentItemType == REPORT_TYPE_OBJECT)
  1040.       {
  1041.       pCurrentSystem = pReport->CurrentItem.pObject->pParentSystem->lpszSystemName ;
  1042.       }
  1043.    else if (pReport->CurrentItemType == REPORT_TYPE_COLUMN)
  1044.       {
  1045.       pParentObject =  pReport->CurrentItem.pColumn->pParentObject ;
  1046.       pCurrentSystem =  pParentObject->pParentSystem->lpszSystemName ;
  1047.       }
  1048.    else if (pReport->CurrentItemType == REPORT_TYPE_COUNTER)
  1049.       {
  1050.       pParentObject =  pReport->CurrentItem.pCounter->pParentObject ;
  1051.       pCurrentSystem =  pParentObject->pParentSystem->lpszSystemName ;
  1052.       }
  1053.    else
  1054.       {
  1055.       pCurrentSystem = NULL ;
  1056.       }
  1057.  
  1058.  
  1059.    return (AddLine (hWndParent, 
  1060.                     &(pReport->pSystemFirst), 
  1061.                     &(pReport->Visual),
  1062.                     pCurrentSystem,
  1063.                     LineTypeReport)) ;
  1064.    }
  1065.  
  1066.  
  1067. BOOL ToggleReportRefresh (HWND hWnd)
  1068.    {  // ToggleReportRefresh
  1069.    PREPORT        pReport ;
  1070.  
  1071.    pReport = ReportData (hWnd) ;
  1072.  
  1073.    if (pReport->bManualRefresh)
  1074.       SetReportTimer (pReport) ;
  1075.    else
  1076.       ClearReportTimer (pReport) ;
  1077.  
  1078.    pReport->bManualRefresh = !pReport->bManualRefresh ;
  1079.    return (pReport->bManualRefresh) ;
  1080.    }  // ToggleReportRefresh
  1081.  
  1082. BOOL ReportRefresh (HWND hWnd)
  1083.    {  // ReportRefresh
  1084.    PREPORT        pReport ;
  1085.  
  1086.    pReport = ReportData (hWnd) ;
  1087.  
  1088.    return (pReport->bManualRefresh) ;
  1089.    }  // ReportRefresh
  1090.  
  1091.  
  1092.  
  1093. void ReportTimer (HWND hWnd, BOOL bForce)
  1094.    {
  1095.    PREPORT        pReport ;
  1096.  
  1097.    pReport = ReportData (hWnd) ;
  1098.  
  1099.    if (PlayingBackLog () || !pReport)
  1100.       {
  1101.       return;
  1102.       }
  1103.  
  1104.    if (bForce || !pReport->bManualRefresh)
  1105.       {  // if
  1106.       UpdateLines (&(pReport->pSystemFirst), pReport->pLineFirst) ;
  1107.       if (iPerfmonView == IDM_VIEWREPORT && !bPerfmonIconic)
  1108.          {
  1109.          // only need to draw the data when we are viewing it...
  1110.          UpdateReportValues (pReport) ;
  1111.          }
  1112.       }  // if
  1113.    }  // ReportTimer
  1114.  
  1115. BOOL SaveReport (HWND hWndReport, HANDLE hInputFile, BOOL bGetFileName)
  1116.    {
  1117.    PREPORT        pReport ;
  1118.    PLINE          pLine ;
  1119.    HANDLE         hFile ;
  1120.    DISKREPORT     DiskReport ;
  1121.    PERFFILEHEADER FileHeader ;
  1122.    TCHAR          szFileName [256] ;
  1123.    BOOL           newFileName = FALSE ;
  1124.  
  1125.    pReport = ReportData (hWndReport) ;
  1126.    if (!pReport)
  1127.       {
  1128.       return (FALSE) ;
  1129.       }
  1130.  
  1131.    if (hInputFile)
  1132.       {
  1133.       // use the input file handle if it is available
  1134.       // this is the case for saving workspace data
  1135.       hFile = hInputFile ;
  1136.       }
  1137.    else
  1138.       {
  1139.       if (pReportFullFileName)
  1140.          {
  1141.          lstrcpy (szFileName, pReportFullFileName) ;
  1142.          }
  1143.       if (bGetFileName || pReportFullFileName == NULL)
  1144.          {
  1145.          if (!FileGetName (hWndReport, IDS_REPORTFILE, szFileName))
  1146.             {
  1147.             return (FALSE) ;
  1148.             }
  1149.          newFileName = TRUE ;
  1150.          }
  1151.  
  1152.       hFile = FileHandleCreate (szFileName) ;
  1153.  
  1154.       if (hFile && newFileName)
  1155.          {
  1156.          ChangeSaveFileName (szFileName, IDM_VIEWREPORT) ;
  1157.          }
  1158.       else if (!hFile)
  1159.          {
  1160.          DlgErrorBox (hWndReport, ERR_CANT_OPEN, szFileName) ;
  1161.          }
  1162.       }
  1163.  
  1164.  
  1165.    if (!hFile)
  1166.       return (FALSE) ;
  1167.  
  1168.  
  1169.    if (!hInputFile)
  1170.       {
  1171.       memset (&FileHeader, 0, sizeof (FileHeader)) ;
  1172.       lstrcpy (FileHeader.szSignature, szPerfReportSignature) ;
  1173.       FileHeader.dwMajorVersion = ReportMajorVersion ;
  1174.       FileHeader.dwMinorVersion = ReportMinorVersion ;
  1175.    
  1176.       if (!FileWrite (hFile, &FileHeader, sizeof (PERFFILEHEADER)))
  1177.          {
  1178.          goto Exit0 ;
  1179.          }
  1180.       }
  1181.  
  1182.    DiskReport.Visual = pReport->Visual ;
  1183.    DiskReport.bManualRefresh = pReport->bManualRefresh ;
  1184.    DiskReport.dwIntervalSecs = pReport->iIntervalMSecs ;
  1185.    DiskReport.dwNumLines = NumLines (pReport->pLineFirst) ;
  1186.    DiskReport.perfmonOptions = Options ;
  1187.  
  1188.    if (!FileWrite (hFile, &DiskReport, sizeof (DISKREPORT)))
  1189.       {
  1190.       goto Exit0 ;
  1191.       }
  1192.  
  1193.    for (pLine = pReport->pLineFirst ;
  1194.         pLine ;
  1195.         pLine = pLine->pLineNext)
  1196.       {  // for
  1197.       if (!WriteLine (pLine, hFile))
  1198.          {
  1199.          goto Exit0 ;
  1200.          }
  1201.       }  // for
  1202.  
  1203.    if (!hInputFile)
  1204.       {
  1205.       CloseHandle (hFile) ;
  1206.       }
  1207.  
  1208.    return (TRUE) ;
  1209.  
  1210. Exit0:
  1211.    if (!hInputFile)
  1212.       {
  1213.       CloseHandle (hFile) ;
  1214.  
  1215.       // only need to report error if not workspace 
  1216.       DlgErrorBox (hWndReport, ERR_SETTING_FILE, szFileName) ;
  1217.       }
  1218.    return (FALSE) ;
  1219.    }  // SaveReport  
  1220.  
  1221.  
  1222. void ReportAddAction (PREPORT pReport)
  1223.    {
  1224.    HDC      hDC ;
  1225.  
  1226.    //=============================//
  1227.    // Calculate report positions  //
  1228.    //=============================//
  1229.  
  1230.    hDC = GetDC (hWndReport) ;
  1231.    SetReportPositions (hDC, pReport) ;
  1232.    ReleaseDC (hWndReport, hDC) ;
  1233.    
  1234.    if (PlayingBackLog ())
  1235.       {
  1236.       PlaybackReport (hWndReport) ;
  1237.       }
  1238.    else if (pReport->iStatus == iPMStatusClosed)
  1239.       {
  1240.       SetReportTimer (pReport) ;
  1241.       }
  1242.  
  1243.    WindowInvalidate (hWndReport) ;
  1244.    }
  1245.  
  1246.  
  1247. BOOL OpenReportVer1 (HANDLE hFile,
  1248.                      DISKREPORT *pDiskReport,
  1249.                      PREPORT pReport,
  1250.                      DWORD dwMinorVersion)
  1251.    {
  1252.    HDC   hDC ;
  1253.  
  1254.    pReport->Visual = pDiskReport->Visual ;
  1255.    pReport->iIntervalMSecs = pDiskReport->dwIntervalSecs ;
  1256.    if (dwMinorVersion < 3)
  1257.       {
  1258.       // convert this to msec
  1259.       pReport->iIntervalMSecs *= 1000 ;
  1260.       }
  1261.    pReport->bManualRefresh = pDiskReport->bManualRefresh ;
  1262.  
  1263.    bDelayAddAction = TRUE ;
  1264.    ReadLines (hFile, pDiskReport->dwNumLines,
  1265.              &(pReport->pSystemFirst), &(pReport->pLineFirst), IDM_VIEWREPORT) ;
  1266.  
  1267.    if (pReport->pLineFirst)
  1268.       {
  1269.       // set focus on the first line
  1270.       pReport->CurrentItem.pLine = pReport->pLineFirst ;
  1271.       pReport->CurrentItemType = REPORT_TYPE_LINE ;
  1272.       }
  1273.    bDelayAddAction = FALSE ;
  1274.  
  1275.    //=============================//
  1276.    // Calculate report positions  //
  1277.    //=============================//
  1278.  
  1279.    hDC = GetDC (hWndReport) ;
  1280.    SetReportPositions (hDC, pReport) ;
  1281.    ReleaseDC (hWndReport, hDC) ;
  1282.  
  1283.    if (PlayingBackLog ())
  1284.  
  1285.       {
  1286.       PlaybackReport (hWndReport) ;
  1287.       }
  1288.    else if (pReport->iStatus == iPMStatusClosed)
  1289.       {
  1290.       SetReportTimer (pReport) ;
  1291.       }
  1292.  
  1293.    WindowInvalidate (hWndReport) ;
  1294.  
  1295.    return (TRUE) ;
  1296.    }  // OpenReportVer1
  1297.  
  1298.  
  1299.  
  1300. BOOL OpenReport (HWND hWndReport, 
  1301.                  HANDLE hFile, 
  1302.                  DWORD dwMajorVersion,
  1303.                  DWORD dwMinorVersion,
  1304.                  BOOL bReportFile)
  1305.    {
  1306.    PREPORT        pReport ;
  1307.    DISKREPORT     DiskReport ;
  1308.    BOOL           bSuccess = TRUE ;
  1309.  
  1310.    pReport = ReportData (hWndReport) ;
  1311.    if (!pReport)
  1312.       {
  1313.       bSuccess = FALSE ;
  1314.       goto Exit0 ;
  1315.       }
  1316.  
  1317.    if (!FileRead (hFile, &DiskReport, sizeof (DISKREPORT)))
  1318.       {
  1319.       bSuccess = FALSE ;
  1320.       goto Exit0 ;
  1321.       }
  1322.  
  1323.  
  1324.    switch (dwMajorVersion)
  1325.       {
  1326.       case (1):
  1327.          
  1328.          SetHourglassCursor() ;
  1329.      
  1330.          ResetReportView (hWndReport) ;
  1331.  
  1332.          OpenReportVer1 (hFile, &DiskReport, pReport, dwMinorVersion) ;
  1333.  
  1334.          // change to report view if we are opening a 
  1335.          // report file
  1336.          if (bReportFile && iPerfmonView != IDM_VIEWREPORT)
  1337.             {
  1338.             SendMessage (hWndMain, WM_COMMAND, (LONG)IDM_VIEWREPORT, 0L) ;
  1339.             }
  1340.  
  1341.          if (iPerfmonView == IDM_VIEWREPORT)
  1342.             {
  1343.             SetPerfmonOptions (&DiskReport.perfmonOptions) ;
  1344.             }
  1345.  
  1346.          SetArrowCursor() ;
  1347.  
  1348.          break ;
  1349.       }  // switch
  1350.  
  1351. Exit0:
  1352.       
  1353.    if (bReportFile)
  1354.       {
  1355.       CloseHandle (hFile) ;
  1356.       }
  1357.  
  1358.    return (bSuccess) ;
  1359.    }  // OpenReport
  1360.  
  1361. void ResetReportView (HWND hWndReport)
  1362.    {  // ResetReportView
  1363.    PREPORT        pReport ;
  1364.  
  1365.    pReport = ReportData (hWndReport) ;
  1366.    
  1367.    if (!pReport)
  1368.       {
  1369.       return ;
  1370.       }
  1371.    
  1372.    ChangeSaveFileName (NULL, IDM_VIEWREPORT) ;
  1373.  
  1374.    if (pReport->pSystemGroupFirst)
  1375.       {
  1376.       ResetReport (hWndReport) ;
  1377.       }
  1378.    }  // ResetReportView
  1379.  
  1380.  
  1381. void ResetReport (HWND hWndReport)
  1382.    {  // ResetReport
  1383.    PREPORT        pReport ;
  1384.    PSYSTEMGROUP   pSystemGroup, pSystemGroupDelete ;
  1385.    POBJECTGROUP   pObjectGroup, pObjectGroupDelete ;
  1386.    PCOUNTERGROUP  pCounterGroup, pCounterGroupDelete ;
  1387.    HDC            hDC ;
  1388.  
  1389.    pReport = ReportData (hWndReport) ;
  1390.    if (!pReport)
  1391.       return ;
  1392.  
  1393.    ClearReportTimer (pReport) ;
  1394.  
  1395.    pSystemGroup = pReport->pSystemGroupFirst ;
  1396.    while (pSystemGroup)
  1397.       { 
  1398.       pObjectGroup = pSystemGroup->pObjectGroupFirst ;
  1399.       while (pObjectGroup)
  1400.          {
  1401.          pCounterGroup = pObjectGroup->pCounterGroupFirst ;
  1402.          while (pCounterGroup)
  1403.             {
  1404.             pCounterGroupDelete = pCounterGroup ;
  1405.             pCounterGroup = pCounterGroup->pCounterGroupNext ;
  1406.             MemoryFree (pCounterGroupDelete) ;
  1407.             }  // while pCounter...
  1408.          
  1409.          pObjectGroupDelete = pObjectGroup ;
  1410.          pObjectGroup = pObjectGroup->pObjectGroupNext ;
  1411.          ColumnGroupRemove (pObjectGroupDelete->pColumnGroupFirst) ;
  1412.          MemoryFree (pObjectGroupDelete->lpszObjectName) ;
  1413.          MemoryFree (pObjectGroupDelete) ;
  1414.          }  // while pObject
  1415.  
  1416.       pSystemGroupDelete = pSystemGroup ;
  1417.       pSystemGroup = pSystemGroup->pSystemGroupNext ;
  1418.       MemoryFree (pSystemGroupDelete->lpszSystemName) ;
  1419.       MemoryFree (pSystemGroupDelete) ;
  1420.       }  // while pSystem...
  1421.  
  1422.    FreeLines (pReport->pLineFirst) ;
  1423.    pReport->pLineFirst = NULL ;
  1424.  
  1425.    FreeSystems (pReport->pSystemFirst) ;
  1426.    pReport->pSystemFirst = NULL ;
  1427.  
  1428.    pReport->pSystemGroupFirst = NULL ;
  1429.    pReport->CurrentItemType   = REPORT_TYPE_NOTHING ;
  1430.    pReport->CurrentItem.pLine = NULL ;
  1431.  
  1432.    // reset scrolling ranges
  1433.    pReport->xWidth = 0 ;
  1434.    pReport->yHeight = 0 ;
  1435.    pReport->xMaxCounterWidth = 0 ;
  1436.    hDC = GetDC (hWndReport) ;
  1437.    SetReportPositions (hDC, pReport) ;
  1438.  
  1439.    SelectFont (hDC, pReport->hFont) ;
  1440.    pReport->xValueWidth = TextWidth (hDC, szValuePlaceholder) ;
  1441.  
  1442.    ReleaseDC (hWndReport, hDC) ;
  1443.  
  1444.    WindowInvalidate (hWndReport) ;
  1445.    }  // ResetReport
  1446.    
  1447. void ClearReportDisplay (HWND hWndReport)
  1448.    {  // ResetReport
  1449.    PREPORT        pReport ;
  1450.    PLINE          pLine;
  1451.  
  1452.    if (PlayingBackLog())
  1453.       {
  1454.       return ;
  1455.       }
  1456.  
  1457.    pReport = ReportData (hWndReport) ;
  1458.    if (!pReport || !pReport->pLineFirst)
  1459.       return ;
  1460.  
  1461.    for (pLine = pReport->pLineFirst ;
  1462.         pLine ;
  1463.         pLine = pLine->pLineNext)
  1464.       {
  1465.       // reset the new data counts
  1466.       pLine->bFirstTime = 2 ;
  1467.       }
  1468.  
  1469.    // re-draw the values
  1470.    UpdateReportValues (pReport) ;
  1471.  
  1472.    }  // ClearReportDisplay
  1473.  
  1474. //=========================================
  1475. // we don't print. we just export
  1476. //
  1477. // if need printing, define KEEP_PRINT
  1478. //=========================================
  1479. #ifdef KEEP_PRINT
  1480. BOOL PrintReportDisplay (HDC hDC,
  1481.                          PREPORT pReport)
  1482.    {
  1483.    SetReportPositions (hDC, pReport) ;
  1484.    DrawReport (hDC, pReport) ;
  1485.    return TRUE ;
  1486.    }  // PrintReportDisplay
  1487.  
  1488.  
  1489.  
  1490. BOOL PrintReport (HWND hWndParent,
  1491.                   HWND hWndReport)
  1492.    {
  1493.    PREPORT        pReport ;
  1494.    HDC            hDC ;
  1495.    int            xPageWidth ;
  1496.    int            yPageHeight ;
  1497.    int            xValueWidth ;
  1498.  
  1499.    HFONT          hFont, hFontHeaders ;
  1500.    int            yLineHeight ;
  1501.  
  1502.    pReport = ReportData (hWndReport) ;
  1503.    if (!pReport)
  1504.       return (FALSE) ;
  1505.  
  1506.    hDC = PrintDC () ;
  1507.    if (!hDC)
  1508.       {
  1509.       PostError () ;
  1510.       return (FALSE) ;
  1511.       }
  1512.       
  1513.    xPageWidth = GetDeviceCaps (hDC, HORZRES) ;
  1514.    yPageHeight = GetDeviceCaps (hDC, VERTRES) ;
  1515.  
  1516.    
  1517.    StartJob (hDC, TEXT("Performance Monitor Report")) ;
  1518.    StartPage (hDC) ;   
  1519.  
  1520.  
  1521.    hFont = pReport->hFont ;
  1522.    hFontHeaders = pReport->hFontHeaders ;
  1523.    yLineHeight = pReport->yLineHeight ;
  1524.    xValueWidth = pReport->xValueWidth ;
  1525.  
  1526.    pReport->hFont = hFontPrinterScales ;
  1527.    pReport->hFontHeaders = hFontPrinterScalesBold ;
  1528.  
  1529.    SelectFont (hDC, pReport->hFont) ;
  1530.    pReport->yLineHeight = FontHeight (hDC, TRUE) ;
  1531.  
  1532.    pReport->xValueWidth = TextWidth (hDC, szValuePlaceholder) ;
  1533.  
  1534.    PrintReportDisplay (hDC, pReport) ;
  1535.  
  1536.    EndPage (hDC) ;
  1537.    EndJob (hDC) ;
  1538.    
  1539.    DeleteDC (hDC) ;
  1540.  
  1541.  
  1542.    pReport->hFont = hFont ;
  1543.    pReport->hFontHeaders = hFontHeaders ;
  1544.    pReport->yLineHeight = yLineHeight ;
  1545.  
  1546.    pReport->xValueWidth = xValueWidth ;
  1547.  
  1548.    hDC = GetDC (hWndReport) ;
  1549.    SetReportPositions (hDC, pReport) ;
  1550.    ReleaseDC (hWndReport, hDC) ;
  1551.  
  1552.    return (FALSE) ;
  1553.    }  // PrintReport
  1554.  
  1555. // we don't print. we just export
  1556. #endif
  1557.  
  1558.  
  1559.  
  1560. BOOL ReportInsertLine (HWND hWnd, PLINE pLine)
  1561. /*
  1562.    Effect:        Insert the line pLine into the data structures for the
  1563.                   Report of window hWnd. The line is added to the list of
  1564.                   lines, and also added to the report structure in the 
  1565.                   appropriate System, Object, and Counter.
  1566.  
  1567.    Returns:       Whether the function was successful. If this function 
  1568.                   returns FALSE, the line was not added.
  1569. */
  1570.    {  // ReportInsertLine
  1571.    HDC            hDC ;
  1572.    PREPORT        pReport ;
  1573.    PSYSTEMGROUP   pSystemGroup ;
  1574.    POBJECTGROUP   pObjectGroup ;
  1575.    PCOUNTERGROUP  pCounterGroup ;
  1576.    PLINE          pLineEquivalent ;
  1577.    int            OldCounterWidth ;
  1578.    BOOL           bNewCounterGroup ;
  1579.  
  1580.    pReport = ReportData (hWnd) ;
  1581.    pReport->bModified = TRUE ;
  1582.  
  1583.    pLineEquivalent = FindEquivalentLine (pLine, pReport->pLineFirst) ;
  1584.    if (pLineEquivalent) 
  1585.       {
  1586.       return (FALSE) ; 
  1587.       }
  1588.    else
  1589.       {
  1590.       //=============================//
  1591.       // Add line, line's system     //
  1592.       //=============================//
  1593.  
  1594.       LineAppend (&pReport->pLineFirst, pLine) ;
  1595.       SystemAdd (&pReport->pSystemFirst, pLine->lnSystemName) ;
  1596.  
  1597.  
  1598.       //=============================//
  1599.       // Find correct spot; add line //
  1600.       //=============================//
  1601.  
  1602.       pSystemGroup = GetSystemGroup (pReport, pLine->lnSystemName) ;
  1603.       pObjectGroup = GetObjectGroup (pSystemGroup, pLine->lnObjectName) ;
  1604.       pCounterGroup = GetCounterGroup (pObjectGroup, 
  1605.                                  pLine->lnCounterDef.CounterNameTitleIndex,
  1606.                                  &bNewCounterGroup,
  1607.                                  pLine->lnCounterName) ;
  1608.  
  1609.       if (!pCounterGroup)
  1610.          return (FALSE) ;
  1611.  
  1612.       LineCounterAppend (&pCounterGroup->pLineFirst, pLine) ;
  1613.    
  1614.       //=============================//
  1615.       // Calculate report positions  //
  1616.       //=============================//
  1617.       hDC = GetDC (hWnd) ;
  1618.       SelectFont (hDC, pReport->hFontHeaders) ;
  1619.  
  1620.       if (bNewCounterGroup)
  1621.          {
  1622.          // re-calc. the max. counter group width 
  1623.          OldCounterWidth = pReport->xMaxCounterWidth ;
  1624.          pReport->xMaxCounterWidth = 
  1625.             max (pReport->xMaxCounterWidth,
  1626.                  TextWidth (hDC, pLine->lnCounterName)) ;
  1627.          if (OldCounterWidth < pReport->xMaxCounterWidth)
  1628.             {
  1629.             // adjust the report width with the new counter width
  1630.             pReport->xWidth +=
  1631.                (pReport->xMaxCounterWidth - OldCounterWidth);
  1632.             }
  1633.          }
  1634.  
  1635.       if (pLine->lnCounterType == PERF_COUNTER_LARGE_RAWCOUNT_HEX)
  1636.          {
  1637.          SelectFont (hDC, pReport->hFont) ;
  1638.          pReport->xValueWidth = TextWidth (hDC, szValueLargeHexPlaceholder) ;
  1639.          }
  1640.  
  1641.       if (!bDelayAddAction)
  1642.          {
  1643.          SetReportPositions (hDC, pReport) ;
  1644.          }
  1645.       ReleaseDC (hWnd, hDC) ;
  1646.  
  1647.       pReport->CurrentItem.pLine = pLine ;
  1648.       pReport->CurrentItemType = REPORT_TYPE_LINE ;
  1649.       
  1650.       if (!bDelayAddAction)
  1651.          {
  1652.          if (PlayingBackLog ())
  1653.             {
  1654.             PlaybackReport (hWndReport) ;
  1655.             }
  1656.          else if (pReport->iStatus == iPMStatusClosed)
  1657.             {
  1658.             SetReportTimer (pReport) ;
  1659.             }
  1660.          
  1661.          WindowInvalidate (hWnd) ;
  1662.          }
  1663.       }  // else
  1664.  
  1665.       return (TRUE) ;
  1666.    }  // ReportInsertLine
  1667.  
  1668.  
  1669. BOOL ExportComputerName (HANDLE hFile, PSYSTEMGROUP pSystemGroup)
  1670. {
  1671.    int            StringLen ;
  1672.    BOOL           bWriteSuccess = TRUE ;
  1673.  
  1674.    CHAR           TempBuff [LongTextLen * 2] ;
  1675.  
  1676.    TCHAR          UnicodeBuff [LongTextLen] ;
  1677.  
  1678.    // export computer name
  1679.    strcpy (TempBuff, LineEndStr) ;
  1680.    strcat (TempBuff, LineEndStr) ;
  1681.    StringLen = strlen (TempBuff) ;
  1682.    TSPRINTF (UnicodeBuff, szSystemFormat, pSystemGroup->lpszSystemName) ;
  1683.    ConvertUnicodeStr (&TempBuff[StringLen], UnicodeBuff) ;
  1684.    strcat (TempBuff, LineEndStr) ;
  1685.  
  1686.    if (!FileWrite (hFile, TempBuff, strlen(TempBuff)))
  1687.       {
  1688.       bWriteSuccess = FALSE ; 
  1689.       }
  1690.  
  1691.    return (bWriteSuccess) ;
  1692. }  // ExportComputerName
  1693.  
  1694. #define WRITE_FILE_TIME 2
  1695. BOOL ExportObjectName (HANDLE hFile, POBJECTGROUP pObjectGroup, int *pColNum)
  1696. {
  1697.    int            StringLen ;
  1698.    BOOL           bNeedToExport ;
  1699.    BOOL           bWriteSuccess = TRUE ;
  1700.    PCOLUMNGROUP   pColumnGroup ;
  1701.    int            ParentNum, InstanceNum ;
  1702.    int            TimeToWrite ;
  1703.  
  1704.    CHAR           TempBuff [512 * 2] ;
  1705.  
  1706.    TCHAR          UnicodeBuff [512] ;
  1707.  
  1708.    ParentNum = InstanceNum = 0 ;
  1709.  
  1710.    if (pColNum)
  1711.       {
  1712.       *pColNum = 0 ;
  1713.       }
  1714.  
  1715.    // export object name
  1716.    strcpy (TempBuff, LineEndStr) ;
  1717.    StringLen = strlen (TempBuff) ;
  1718.    TSPRINTF (UnicodeBuff, szObjectFormat, pObjectGroup->lpszObjectName) ;
  1719.    ConvertUnicodeStr (&TempBuff[StringLen], UnicodeBuff) ;
  1720.    strcat (TempBuff, LineEndStr) ;
  1721.  
  1722.    if (!FileWrite (hFile, TempBuff, strlen(TempBuff)))
  1723.       {
  1724.       goto Exit0 ;
  1725.       }
  1726.    
  1727.  
  1728.    TimeToWrite = 0 ;
  1729.  
  1730.    // export column group
  1731.    if (pObjectGroup->pColumnGroupFirst)
  1732.       {
  1733.       strcpy (TempBuff, pDelimiter) ;
  1734.       strcat (TempBuff, pDelimiter) ;
  1735.       StringLen = strlen (TempBuff) ;
  1736.  
  1737.       bNeedToExport = FALSE ;
  1738.  
  1739.       // export Parent Names
  1740.       for (pColumnGroup = pObjectGroup->pColumnGroupFirst ;
  1741.            pColumnGroup ;
  1742.            pColumnGroup = pColumnGroup->pColumnGroupNext)
  1743.          {  // for
  1744.  
  1745.          if (pColumnGroup->lpszParentName)
  1746.             {
  1747.             ParentNum++ ;
  1748.             bNeedToExport = TRUE ;
  1749.             ConvertUnicodeStr (&TempBuff[StringLen],
  1750.                                pColumnGroup->lpszParentName) ;
  1751.             StringLen = strlen (TempBuff) ;
  1752.             }
  1753.                         
  1754.          strcat (&TempBuff[StringLen], pDelimiter) ;
  1755.          StringLen = strlen (TempBuff) ;
  1756.  
  1757.          // check if we need to export this line before it is filled up
  1758.          TimeToWrite++ ;
  1759.          if (TimeToWrite > WRITE_FILE_TIME)
  1760.             {
  1761.             if (!FileWrite (hFile, TempBuff, strlen(TempBuff)))
  1762.                {
  1763.                goto Exit0 ;
  1764.                }
  1765.             TimeToWrite = 0 ;
  1766.             StringLen = 0 ;
  1767.             TempBuff[0] = TEXT('\0') ;
  1768.             }
  1769.          }
  1770.  
  1771.       // write the line delimiter
  1772.       strcpy (&TempBuff[StringLen], LineEndStr) ;
  1773.       if (!FileWrite (hFile, TempBuff, strlen(TempBuff)))
  1774.          {
  1775.          goto Exit0 ;
  1776.          }
  1777.           
  1778.       if (!bNeedToExport)
  1779.          {
  1780.          ParentNum = 0 ;
  1781.          }
  1782.  
  1783.  
  1784.       // setup to export Instances
  1785.       strcpy (TempBuff, pDelimiter) ;
  1786.       strcat (TempBuff, pDelimiter) ;
  1787.       StringLen = strlen (TempBuff) ;
  1788.       bNeedToExport = FALSE ;
  1789.       TimeToWrite = 0 ;
  1790.  
  1791.       // export Instance Names
  1792.       for (pColumnGroup = pObjectGroup->pColumnGroupFirst ;
  1793.            pColumnGroup ;
  1794.            pColumnGroup = pColumnGroup->pColumnGroupNext)
  1795.          {  // for
  1796.  
  1797.          if (pColumnGroup->lpszInstanceName)
  1798.             {
  1799.             InstanceNum++ ;
  1800.             bNeedToExport = TRUE ;
  1801.             ConvertUnicodeStr (&TempBuff[StringLen],
  1802.                                pColumnGroup->lpszInstanceName) ;
  1803.             StringLen = strlen (TempBuff) ;
  1804.             }
  1805.                
  1806.          strcat (&TempBuff[StringLen], pDelimiter) ;
  1807.          StringLen = strlen (TempBuff) ;
  1808.  
  1809.          // check if we need to export this line before it is filled up
  1810.          TimeToWrite++ ;
  1811.          if (TimeToWrite > WRITE_FILE_TIME)
  1812.             {
  1813.             if (!FileWrite (hFile, TempBuff, strlen(TempBuff)))
  1814.                {
  1815.                goto Exit0 ;
  1816.                }
  1817.             TimeToWrite = 0 ;
  1818.             StringLen = 0 ;
  1819.             TempBuff[0] = TEXT('\0') ;
  1820.             }
  1821.          }
  1822.  
  1823.       // write the line delimiter
  1824.       strcpy (&TempBuff[StringLen], LineEndStr) ;
  1825.       if (!FileWrite (hFile, TempBuff, strlen(TempBuff)))
  1826.          {
  1827.          goto Exit0 ;
  1828.          }
  1829.  
  1830.       if (!bNeedToExport)
  1831.          {
  1832.          InstanceNum = 0 ;
  1833.          }
  1834.       }
  1835.  
  1836.    if (pColNum)
  1837.       {
  1838.       *pColNum = max (ParentNum, InstanceNum) ;
  1839.       }
  1840.  
  1841.    return (TRUE) ;
  1842.  
  1843. Exit0:
  1844.    return (FALSE) ;
  1845.  
  1846. }  // ExportObjectName
  1847.  
  1848. BOOL ExportLineName (HANDLE hFile, PLINE pLine, int *pExportCounterName)
  1849. {
  1850.    FLOAT          eValue ;
  1851.    int            StringLen ;
  1852.    BOOL           bWriteSuccess = TRUE ;
  1853.  
  1854.    CHAR           TempBuff [LongTextLen * 2] ;
  1855.  
  1856.    TCHAR          UnicodeBuff [LongTextLen] ;
  1857.  
  1858.  
  1859.    strcpy (TempBuff, pDelimiter) ;
  1860.    
  1861.    if (*pExportCounterName)
  1862.       {
  1863.       StringLen = strlen (TempBuff) ;
  1864.       ConvertUnicodeStr (&TempBuff[StringLen], pLine->lnCounterName) ;
  1865.       strcat (TempBuff, pDelimiter) ;
  1866.       *pExportCounterName = FALSE ;
  1867.       }
  1868.    StringLen = strlen (TempBuff) ;
  1869.  
  1870.    if (pLine->bFirstTime == 0)
  1871.       {
  1872.       eValue = CounterEntry (pLine) ;
  1873.  
  1874.       if (pLine->lnCounterType == PERF_COUNTER_RAWCOUNT_HEX ||
  1875.           pLine->lnCounterType == PERF_COUNTER_LARGE_RAWCOUNT_HEX)
  1876.          {
  1877.          DWORD LowValue  ;
  1878.          DWORD HighValue ;
  1879.  
  1880.          LowValue  = (DWORD) (pLine->lnaCounterValue[0]) ;
  1881.          HighValue = (DWORD) (pLine->lnaCounterValue[0] >> 32);
  1882.  
  1883.          if (pLine->lnCounterType == PERF_COUNTER_RAWCOUNT_HEX ||
  1884.              HighValue == 0)
  1885.             {
  1886.             TSPRINTF (UnicodeBuff,
  1887.                       szHexFormat,
  1888.                       LowValue) ;
  1889.             }
  1890.          else
  1891.             {
  1892.             TSPRINTF (UnicodeBuff,
  1893.                       szLargeHexFormat,
  1894.                       HighValue,
  1895.                       LowValue) ;
  1896.             }
  1897.          }
  1898.       else
  1899.          {
  1900.          TSPRINTF (UnicodeBuff,
  1901.                    (eValue > eStatusLargeValueMax) ?
  1902.                        szLargeValueFormat : szValueFormat,
  1903.                    eValue) ;
  1904.          ConvertDecimalPoint (UnicodeBuff) ;
  1905.          }
  1906.       ConvertUnicodeStr (&TempBuff[StringLen], UnicodeBuff) ;
  1907.       }
  1908.    else
  1909.       {
  1910.       // export "----" for unstable values
  1911.       strcat (&TempBuff[StringLen], "----");
  1912.       }
  1913.  
  1914.    // write the line value
  1915.    if (!FileWrite (hFile, TempBuff, strlen(TempBuff)))
  1916.       {
  1917.       goto Exit0 ;
  1918.       }
  1919.  
  1920.    return (TRUE) ;
  1921.  
  1922.  
  1923. Exit0:
  1924.    return (FALSE) ;
  1925. }  // ExportLineName
  1926.  
  1927.  
  1928. // This routine is need to insert the line values into its
  1929. // column location.  It is needed because not all the instances (columns)
  1930. // are available for the same line.
  1931. void SaveColumnLineData (PLINE pLine, LPSTR pColumnLineData)
  1932. {
  1933.    FLOAT          eValue ;
  1934.    LPSTR          pColumnLine ;
  1935.  
  1936.    CHAR           TempBuff [LongTextLen * 2] ;
  1937.  
  1938.    TCHAR          UnicodeBuff [LongTextLen] ;
  1939.  
  1940.    if (!pColumnLineData || pLine->iReportColumn < 0)
  1941.       {
  1942.       return ;
  1943.       }
  1944.  
  1945.    // find the offset into the pColumnLineData buffer for current line
  1946.    pColumnLine = pColumnLineData + pLine->iReportColumn * ShortTextLen ;
  1947.  
  1948.    if (pLine->bFirstTime == 0)
  1949.       {
  1950.  
  1951.       eValue = CounterEntry (pLine) ;
  1952.  
  1953.  
  1954.       if (pLine->lnCounterType == PERF_COUNTER_RAWCOUNT_HEX ||
  1955.           pLine->lnCounterType == PERF_COUNTER_LARGE_RAWCOUNT_HEX)
  1956.          {
  1957.          DWORD LowValue  ;
  1958.          DWORD HighValue ;
  1959.  
  1960.          LowValue  = (DWORD) (pLine->lnaCounterValue[0]) ;
  1961.          HighValue = (DWORD) (pLine->lnaCounterValue[0] >> 32);
  1962.  
  1963.          if (pLine->lnCounterType == PERF_COUNTER_RAWCOUNT_HEX ||
  1964.              HighValue == 0)
  1965.             {
  1966.             TSPRINTF (UnicodeBuff,
  1967.                       szHexFormat,
  1968.                       LowValue) ;
  1969.             }
  1970.          else
  1971.             {
  1972.             TSPRINTF (UnicodeBuff,
  1973.                       szLargeHexFormat,
  1974.                       HighValue,
  1975.                       LowValue) ;
  1976.             }
  1977.          }
  1978.       else
  1979.          {
  1980.          TSPRINTF (UnicodeBuff,
  1981.                    (eValue > eStatusLargeValueMax) ?
  1982.                        szLargeValueFormat : szValueFormat,
  1983.                    eValue) ;
  1984.          ConvertDecimalPoint (UnicodeBuff) ;
  1985.          }
  1986.       ConvertUnicodeStr (TempBuff, UnicodeBuff) ;
  1987.       strncpy (pColumnLine, TempBuff, ShortTextLen) ;
  1988.       *(pColumnLine + ShortTextLen - 1) = '\0' ;
  1989.       }
  1990.    else
  1991.       {
  1992.       // export "----" for unstable values
  1993.       strcpy (pColumnLine, "----");
  1994.       }
  1995. }  // SaveColumnLineData
  1996.  
  1997. BOOL ExportColumnLineData (HANDLE hFile,
  1998.                            int ColumnTotal,
  1999.                            PCOUNTERGROUP pCounterGroup,
  2000.                            LPSTR pColumnLineData)
  2001. {
  2002.    int            iIndex ;
  2003.    int            StringLen ;
  2004.    CHAR           TempBuff [LongTextLen] ;
  2005.    LPSTR          pCurrentLineData ;
  2006.  
  2007.    // export the counter name
  2008.    strcpy (TempBuff, pDelimiter) ;
  2009.    StringLen = strlen (TempBuff) ;
  2010.    ConvertUnicodeStr (&TempBuff[StringLen], pCounterGroup->pLineFirst->lnCounterName) ;
  2011.    strcat (TempBuff, pDelimiter) ;
  2012.    if (!FileWrite (hFile, TempBuff, strlen(TempBuff)))
  2013.       {
  2014.       goto Exit0 ;
  2015.       }
  2016.  
  2017.    // go thru each column and export the line value if it has been stored   
  2018.    for (iIndex = 0, pCurrentLineData = pColumnLineData ;
  2019.       iIndex < ColumnTotal ;
  2020.       iIndex++, pCurrentLineData += ShortTextLen )
  2021.       {
  2022.       if (*pCurrentLineData != 0)
  2023.          {
  2024.          // data available for this column
  2025.          if (!FileWrite (hFile, pCurrentLineData, strlen(pCurrentLineData)))
  2026.             {
  2027.             goto Exit0 ;
  2028.             }
  2029.          }
  2030.  
  2031.       if (!FileWrite (hFile, pDelimiter, strlen(pDelimiter)))
  2032.          {
  2033.          goto Exit0 ;
  2034.          }
  2035.       }
  2036.  
  2037.    if (!FileWrite (hFile, LineEndStr, strlen(LineEndStr)))
  2038.       {
  2039.       goto Exit0 ;
  2040.       }
  2041.  
  2042.    return (TRUE) ;
  2043.  
  2044.  
  2045. Exit0:
  2046.    return (FALSE) ;
  2047.  
  2048. }  // ExportColumnLineData
  2049.  
  2050. void ExportReport (void)
  2051. {
  2052.    HANDLE         hFile = 0 ;
  2053.    PREPORT        pReport ;
  2054.    PSYSTEMGROUP   pSystemGroup ;
  2055.    POBJECTGROUP   pObjectGroup ;
  2056.    PCOUNTERGROUP  pCounterGroup ;
  2057.    PLINE          pLine ;
  2058.    BOOL           bExportComputer ;
  2059.    BOOL           bExportObject ;
  2060.    BOOL           bExportCounterName ;
  2061.    int            ColumnTotal = 0 ;
  2062.    LPSTR          pColumnLineData = NULL ;
  2063.    LPTSTR         pFileName = NULL ;
  2064.    INT            ErrCode = 0 ;
  2065.  
  2066.    if (!(pReport = ReportData (hWndReport)))
  2067.       {
  2068.       return ;
  2069.       }
  2070.  
  2071.    // see if there is anything to export..
  2072.    if (!(pReport->pSystemGroupFirst))
  2073.       {
  2074.       return ;
  2075.       }
  2076.  
  2077.    SetHourglassCursor() ;
  2078.    
  2079.    if (ErrCode = ExportFileOpen (hWndReport, &hFile,
  2080.        pReport->iIntervalMSecs, &pFileName))
  2081.       {
  2082.       goto Exit0 ;
  2083.       }
  2084.  
  2085.    if (!pFileName)
  2086.       {
  2087.       // the case when user cancel
  2088.       goto Exit0 ;
  2089.       }
  2090.  
  2091.    // export each system group
  2092.  
  2093.    for (pSystemGroup = pReport->pSystemGroupFirst ;
  2094.         pSystemGroup ;
  2095.         pSystemGroup = pSystemGroup->pSystemGroupNext)
  2096.       {  // for System...
  2097.  
  2098.       bExportComputer = TRUE ;
  2099.  
  2100.       for (pObjectGroup = pSystemGroup->pObjectGroupFirst ;
  2101.            pObjectGroup ;
  2102.            pObjectGroup = pObjectGroup->pObjectGroupNext)
  2103.          {  // for Object...
  2104.  
  2105.          bExportObject = TRUE ;
  2106.  
  2107.          for (pCounterGroup = pObjectGroup->pCounterGroupFirst ;
  2108.               pCounterGroup ;
  2109.               pCounterGroup = pCounterGroup->pCounterGroupNext)
  2110.             {  // for Counter...
  2111.  
  2112.             bExportCounterName = TRUE ;
  2113.  
  2114.             // Column data buffer has been allocated for this object type, 
  2115.             // zero out the buffer and prepare for next round.
  2116.          
  2117.             if (pColumnLineData)
  2118.                {
  2119.                memset (pColumnLineData, 0, ColumnTotal * ShortTextLen) ;
  2120.                }
  2121.  
  2122.             for (pLine = pCounterGroup->pLineFirst ;
  2123.                  pLine ;
  2124.                  pLine = pLine->pLineCounterNext)
  2125.                {  // for Line...
  2126.  
  2127.                if (bExportComputer)
  2128.                   {
  2129.                   // only need to do this for the first object
  2130.                   bExportComputer = FALSE ;
  2131.                   if (!ExportComputerName (hFile, pSystemGroup))
  2132.                      {
  2133.                      ErrCode = ERR_EXPORT_FILE ;
  2134.                      goto Exit0 ;
  2135.                      }
  2136.                   }
  2137.  
  2138.                if (bExportObject)
  2139.                   {
  2140.                   // only need to do this for the first counter group
  2141.                   bExportObject = FALSE ;
  2142.                   if (!ExportObjectName (hFile, pObjectGroup, &ColumnTotal))
  2143.                      {
  2144.                      ErrCode = ERR_EXPORT_FILE ;
  2145.                      goto Exit0 ;
  2146.                      }
  2147.  
  2148.                   if (ColumnTotal > 1)
  2149.                      {
  2150.                      // special case to setup a column array and export
  2151.                      // the line values later
  2152.                      pColumnLineData = MemoryAllocate (ColumnTotal * ShortTextLen) ;
  2153.                      if (!pColumnLineData)
  2154.                         {
  2155.                         ErrCode = ERR_EXPORT_FILE ;
  2156.                         goto Exit0 ;
  2157.                         }
  2158.                      }
  2159.                   }
  2160.  
  2161.                if (ColumnTotal > 1)
  2162.                   {
  2163.                   // save the line value into its column & export later
  2164.                   SaveColumnLineData (pLine, pColumnLineData) ;
  2165.                   }
  2166.                else
  2167.                   {
  2168.                   // simple case, export the line now
  2169.                   if (!ExportLineName (hFile, pLine, &bExportCounterName))
  2170.                      {
  2171.                      ErrCode = ERR_EXPORT_FILE ;
  2172.                      goto Exit0 ;
  2173.                      }
  2174.                   }
  2175.                }  // for Line...
  2176.  
  2177.             if (!bExportCounterName)
  2178.                {
  2179.                // export the line end
  2180.                if (!FileWrite (hFile, LineEndStr, strlen(LineEndStr)))
  2181.                   {
  2182.                   ErrCode = ERR_EXPORT_FILE ;
  2183.                   goto Exit0 ;
  2184.                   }
  2185.                }
  2186.  
  2187.             if (pColumnLineData)
  2188.                {
  2189.                // now, do the actual export
  2190.                if (!ExportColumnLineData (hFile,
  2191.                   ColumnTotal,
  2192.                   pCounterGroup,
  2193.                   pColumnLineData))
  2194.                   {
  2195.                   ErrCode = ERR_EXPORT_FILE ;
  2196.                   goto Exit0 ;
  2197.                   }
  2198.                }
  2199.             }  // for Counter...
  2200.  
  2201.          // done with the object, done with the buffer
  2202.          if (pColumnLineData)
  2203.             {
  2204.             MemoryFree (pColumnLineData) ;
  2205.             ColumnTotal = 0 ;
  2206.             pColumnLineData = NULL ;
  2207.             }
  2208.          }  // for Object
  2209.  
  2210.  
  2211.       }  // for System...
  2212.  
  2213. Exit0:
  2214.  
  2215.    SetArrowCursor() ;
  2216.  
  2217.    if (pColumnLineData)
  2218.       {
  2219.       MemoryFree (pColumnLineData) ;
  2220.       }
  2221.  
  2222.    if (hFile)
  2223.       {
  2224.       CloseHandle (hFile) ;
  2225.       }
  2226.  
  2227.    if (pFileName)
  2228.       {
  2229.       if (ErrCode)
  2230.          {
  2231.          DlgErrorBox (hWndGraph, ErrCode, pFileName) ;
  2232.          }
  2233.  
  2234.       MemoryFree (pFileName) ;
  2235.       }
  2236.  
  2237. }  // ExportReport
  2238.  
  2239.  
  2240.