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 / line.c < prev    next >
Text File  |  1994-10-13  |  25KB  |  963 lines

  1.  
  2.  
  3. //==========================================================================//
  4. //                                  Includes                                //
  5. //==========================================================================//
  6.  
  7.  
  8. #include "perfmon.h"    // included by all source files
  9. #include "line.h"       // external declarations for this file
  10. //#include <tchar.h>      // for _tcsncpy
  11.  
  12. #include "fileutil.h"   // for FileRead, FileWrite
  13. #include "pmemory.h"     // for MemoryXXX (mallloc-type) routines
  14. #include "perfdata.h"   // for UpdateSystemData, et al
  15. #include "perfmops.h"   // for InsertLine
  16. #include "system.h"     // for SystemAdd
  17. #include "utils.h"
  18. #include "playback.h"   // for PlayingBackLog
  19. #include "counters.h"   // CounterEntry
  20.  
  21. #include <string.h>     // for strncpy
  22. #ifdef UNICODE
  23. #define _tcsncpy    wcsncpy
  24. #else
  25. #define _tcsncpy    strncpy
  26. #endif
  27.  
  28. TCHAR LOCAL_SYS_CODE_NAME[] = TEXT("....") ;
  29. #define  sizeofCodeName sizeof(LOCAL_SYS_CODE_NAME) / sizeof(TCHAR) - 1
  30.  
  31. // Local Function prototype
  32. PLINE ReadLine (PPERFSYSTEM *ppSystem,
  33.                 PPPERFSYSTEM ppSystemFirst,
  34.                 PPERFDATA *ppPerfData, 
  35.                 HANDLE hFile,
  36.                 int LineType,
  37.                 PDISKLINE  *ppDiskLine,
  38.                 DWORD *pSizeofDiskLine) ;
  39.  
  40.  
  41.  
  42. //==========================================================================//
  43. //                             Exported Functions                           //
  44. //==========================================================================//
  45.  
  46.  
  47. PLINE LineAllocate (void)
  48. /*
  49.    Effect:        Allocate and initialize a Line data structure. Lines
  50.                   are used as the primary elements of both charts and
  51.                   alerts.
  52.  
  53.                   Establish any representation invariants for the Line
  54.                   type.
  55.  
  56.                   Also alllocate another structure, an array of data
  57.                   elements, iNumDataValues long.
  58. */
  59.    {  // LineAllocate
  60.    PLINE          pLine ;
  61.  
  62.    pLine = MemoryAllocate (sizeof (LINESTRUCT)) ;
  63.  
  64.    if (pLine)
  65.       {
  66. //  don't need to zero these again since MemoryAllocate is using
  67. //  GMEM_ZEROPOINT
  68. //      pLine->pLineNext = NULL ;
  69. //      pLine->pLineCounterNext = NULL ;
  70.  
  71.       // do want to do this since (FLOAT)0.0 is not 0
  72.       pLine->lnMinValue =
  73.       pLine->lnMaxValue =
  74.       pLine->lnAveValue = (FLOAT) 0.0 ;
  75.  
  76.       if (PlayingBackLog())
  77.          {
  78.          pLine->bFirstTime = FALSE ;
  79.          }
  80.       else
  81.          {
  82. //         pLine->bFirstTime = TRUE ;
  83.          // we want to take 2 samples before plotting the first data
  84.          pLine->bFirstTime = 2 ;
  85.          }
  86.       }  // if
  87.  
  88.    return (pLine) ;
  89.    }  // LineAllocate
  90.  
  91.  
  92. void LineFree (PLINE pLine)
  93.    {  // LineFree
  94.    // free any memory allocated by this line
  95.    if (pLine->lnSystemName)
  96.       MemoryFree (pLine->lnSystemName) ;
  97.  
  98.    if (pLine->lnObjectName)
  99.       MemoryFree (pLine->lnObjectName) ;
  100.  
  101.    if (pLine->lnCounterName)
  102.       MemoryFree (pLine->lnCounterName) ;
  103.  
  104.    if (pLine->lnInstanceName)
  105.       MemoryFree (pLine->lnInstanceName) ;
  106.  
  107.    if (pLine->lnParentObjName)
  108.       MemoryFree (pLine->lnParentObjName) ;
  109.  
  110.    if (pLine->lnPINName)
  111.       MemoryFree (pLine->lnPINName) ;
  112.  
  113.    if (pLine->lpszAlertProgram)
  114.       MemoryFree (pLine->lpszAlertProgram) ;
  115.  
  116.    if (pLine->hPen)
  117.       DeletePen(pLine->hPen);
  118.  
  119.    if (pLine->hBrush)
  120.       DeletePen(pLine->hBrush);
  121.  
  122.    if (pLine->lnValues)
  123.       MemoryFree (pLine->lnValues) ;
  124.  
  125.    if (pLine->aiLogIndexes)
  126.       MemoryFree (pLine->aiLogIndexes) ;
  127.  
  128.    MemoryFree (pLine) ;
  129.    }  // LineFree
  130.  
  131.  
  132.  
  133. void LineAppend (PPLINE ppLineFirst, 
  134.                  PLINE pLineNew)
  135.    {
  136.    PLINE          pLine ;
  137.  
  138.    if (!*ppLineFirst)
  139.       *ppLineFirst = pLineNew ;
  140.    else  
  141.       {  // else
  142.       for (pLine = *ppLineFirst ;
  143.            pLine->pLineNext ;
  144.            pLine = pLine->pLineNext)
  145.          /* nothing */ ;
  146.       pLine->pLineNext = pLineNew ;
  147.       }  // else
  148.    }
  149.  
  150.  
  151.  
  152. BOOL LineRemove (PPLINE ppLineFirst,
  153.                  PLINE pLineRemove)
  154.    {
  155.    PLINE          pLine ;
  156.  
  157.    if (*ppLineFirst == pLineRemove)
  158.       {
  159.       *ppLineFirst = (*ppLineFirst)->pLineNext ;
  160.       return (TRUE) ;
  161.       }
  162.  
  163.    for (pLine = *ppLineFirst ;
  164.         pLine->pLineNext ;
  165.         pLine = pLine->pLineNext)
  166.       {   // for
  167.       if (pLine->pLineNext == pLineRemove)
  168.          {
  169.          pLine->pLineNext = pLineRemove->pLineNext ;
  170.          return (TRUE) ;
  171.          }  // if
  172.       }  // for
  173.  
  174.    return (FALSE) ;
  175.    }  // LineRemove
  176.  
  177.  
  178.  
  179. int NumLines (PLINE pLineFirst)
  180.    {  // NumLines
  181.    PLINE          pLine ;
  182.    int            iNumLines ;
  183.  
  184.    if (!pLineFirst)
  185.       return (0) ;
  186.  
  187.   
  188.    iNumLines = 0 ;
  189.    for (pLine = pLineFirst ;
  190.         pLine ;
  191.         pLine = pLine->pLineNext)
  192.       {  // for
  193.       iNumLines++ ;
  194.       }  // for
  195.  
  196.  
  197.    return (iNumLines) ;
  198.    }  // NumLines
  199.  
  200.  
  201.  
  202. LPTSTR LineInstanceName (PLINE pLine)
  203.    {
  204.    if (pLine->lnObject.NumInstances <= 0)
  205.       return (NULL) ;
  206.    else
  207.       return (pLine->lnInstanceName) ;
  208.    }
  209.  
  210.  
  211. LPTSTR LineParentName (PLINE pLine)
  212.    {
  213.    if (pLine->lnObject.NumInstances <= 0)
  214.       return (NULL) ;
  215.    else if (pLine->lnInstanceDef.ParentObjectTitleIndex)
  216.       return (pLine->lnPINName) ;
  217.    else
  218.       return (NULL) ;
  219.    }
  220.  
  221.  
  222.  
  223. void LineCounterAppend (PPLINE ppLineFirst, 
  224.                         PLINE pLineNew)
  225.    {
  226.    PLINE          pLine ;
  227.  
  228.    if (!*ppLineFirst)
  229.       *ppLineFirst = pLineNew ;
  230.    else  
  231.       {  // else
  232.       for (pLine = *ppLineFirst ;
  233.            pLine->pLineCounterNext ;
  234.            pLine = pLine->pLineCounterNext)
  235.          /* nothing */ ;
  236.       pLine->pLineCounterNext = pLineNew ;
  237.       }  // else
  238.    }
  239.  
  240.  
  241.  
  242. BOOL EquivalentLine (PLINE pLine1,
  243.                      PLINE pLine2)
  244.    {  // LineEquivalent
  245.    return (pstrsame (pLine1->lnCounterName, pLine2->lnCounterName) &&
  246.            pstrsame (pLine1->lnInstanceName, pLine2->lnInstanceName) &&
  247.            pstrsame (pLine1->lnPINName, pLine2->lnPINName) &&
  248.            pstrsame (pLine1->lnObjectName, pLine2->lnObjectName) &&
  249.            pstrsamei (pLine1->lnSystemName, pLine2->lnSystemName)) ;
  250.    }  // LineEquivalent
  251.  
  252.  
  253. PLINE FindEquivalentLine (PLINE pLineToFind,
  254.                           PLINE pLineFirst)
  255.    {
  256.    PLINE          pLine ;
  257.  
  258.    for (pLine = pLineFirst ;
  259.         pLine ;
  260.         pLine = pLine->pLineNext)
  261.       {  // for
  262.       if (EquivalentLine (pLine, pLineToFind))
  263.          return (pLine) ;
  264.       }  // for
  265.  
  266.    return (NULL) ;
  267.    }  // FindEquivalentLine
  268.  
  269. // This routine is used only to read the system name from a disk string
  270. // It is mainly for performance improvement.
  271. LPTSTR DiskStringReadSys (PDISKSTRING pDS)
  272.    {  // DiskStringReadSys
  273.    LPTSTR         lpszText ;
  274.    LPTSTR         pDiskSysName ;
  275.    int            iIndex ;
  276.    BOOL           bLocalSysName = FALSE ;
  277.  
  278.    if (pDS->dwLength == 0)
  279.       {
  280.       return (NULL) ;
  281.       }
  282.  
  283.    if (pDS->dwLength == sizeofCodeName)
  284.       {
  285.       // check for LOCAL_SYS_CODE_NAME
  286.       bLocalSysName = TRUE ;
  287.       pDiskSysName = (LPTSTR)((PBYTE) pDS + pDS->dwOffset) ;
  288.       for (iIndex = 0 ; iIndex < sizeofCodeName; iIndex++, pDiskSysName++)
  289.          {
  290.          if (*pDiskSysName != LOCAL_SYS_CODE_NAME[iIndex])
  291.             {
  292.             bLocalSysName = FALSE ;
  293.             break ;
  294.             }
  295.          }
  296.       }
  297.  
  298.    if (bLocalSysName)
  299.       {
  300.       lpszText =
  301.          MemoryAllocate ((lstrlen(LocalComputerName)+1) * sizeof(TCHAR)) ;
  302.       if (lpszText)
  303.          {
  304.          lstrcpy (lpszText, LocalComputerName) ;
  305.          }
  306.       }
  307.    else
  308.       {
  309.       lpszText = MemoryAllocate (sizeof (TCHAR) * (pDS->dwLength + 1)) ;
  310.       if (lpszText)
  311.          {
  312.          _tcsncpy ((WCHAR *)lpszText, (WCHAR *)((PBYTE) pDS + pDS->dwOffset),
  313.                   pDS->dwLength) ;
  314.          }
  315.       }
  316.  
  317.    return (lpszText) ;
  318.    }  // DiskStringReadSys
  319.  
  320.  
  321.  
  322. LPTSTR DiskStringRead (PDISKSTRING pDS)
  323.    {  // DiskStringRead
  324.    LPTSTR         lpszText ;
  325.  
  326.    if (pDS->dwLength == 0)
  327.       {
  328.       return (NULL) ;
  329.       }
  330.  
  331.    lpszText = MemoryAllocate (sizeof (TCHAR) * (pDS->dwLength + 1)) ;
  332.    if (!lpszText)
  333.       {
  334.       return (NULL) ;
  335.       }
  336.  
  337.    _tcsncpy ((WCHAR *)lpszText, (WCHAR *)((PBYTE) pDS + pDS->dwOffset),
  338.             pDS->dwLength) ;
  339.  
  340.    return (lpszText) ;
  341.    }  // DiskStringRead
  342.  
  343.  
  344. int DiskStringLength (LPTSTR lpszText)
  345.    {
  346.    if (!lpszText)
  347.       return (0) ;
  348.    else
  349.       return (lstrlen (lpszText)) ;
  350.    }
  351.  
  352. PBYTE DiskStringCopy (PDISKSTRING pDS, LPTSTR lpszText, PBYTE pNextFree)
  353.    {
  354.    if (!lpszText)
  355.       {
  356.       pDS->dwOffset = 0 ;
  357.       pDS->dwLength = 0 ;
  358.       return (pNextFree) ;
  359.       }
  360.    else
  361.       {
  362.       pDS->dwOffset = pNextFree - (PBYTE) pDS ;
  363.       pDS->dwLength = DiskStringLength (lpszText) ;
  364.       _tcsncpy ((WCHAR *)pNextFree, (WCHAR *)lpszText, pDS->dwLength) ;
  365.       return (pNextFree + pDS->dwLength * sizeof(TCHAR)) ;
  366.       }
  367.    }  // DiskStringCopy
  368.    
  369.  
  370. void CounterName (PPERFSYSTEM pSystem, 
  371.                   PPERFCOUNTERDEF pCounter, 
  372.                   LPTSTR lpszCounter)
  373.    {  // CounterName
  374. //!!   strclr (lpszCounter) ;
  375.    lpszCounter [0] = TEXT('\0') ;
  376.    QueryPerformanceName (pSystem, 
  377.                          pCounter->CounterNameTitleIndex, 
  378.                          0, 256,
  379.                          lpszCounter,
  380.                          FALSE) ;
  381.    }  // CounterName
  382.  
  383.  
  384.  
  385. PPERFOBJECT LineFindObject (PPERFSYSTEM pSystem,
  386.                             PPERFDATA pPerfData,
  387.                             PLINE pLine)
  388. /*
  389.    Effect:        Set the lnObject field of pLine to the object with the
  390.                   name of lnObjectName, and return TRUE. Return FALSE if
  391.                   there is no such object.
  392. */
  393.    {  // LineFindObject
  394.    PPERFOBJECT    pObject ;
  395.  
  396.    pObject = GetObjectDefByName (pSystem, pPerfData, pLine->lnObjectName) ;
  397.    
  398.    if (pObject)
  399.       {
  400.       pLine->lnObject = *pObject ;
  401.       return (pObject) ;
  402.       }
  403.    else
  404.       return (NULL) ;
  405.    }  // LineFindObject
  406.    
  407.  
  408.  
  409. PPERFCOUNTERDEF LineFindCounter (PPERFSYSTEM pSystem,
  410.                                  PPERFOBJECT pObject,
  411.                                  PPERFDATA pPerfData,
  412.                                  PLINE pLine)
  413.    {  // LineFindCounter
  414.    UINT               i ;
  415.    PPERFCOUNTERDEF   pCounter ;
  416.    TCHAR             szCounter [256] ;
  417.  
  418.    for (i = 0, pCounter = FirstCounter (pObject) ;
  419.         i < pObject->NumCounters ;
  420.         i++, pCounter = NextCounter (pCounter))
  421.       {  // for
  422.       CounterName (pSystem, pCounter, szCounter) ;
  423.       if (strsame (szCounter, pLine->lnCounterName))
  424.          {
  425.          pLine->lnCounterDef = *pCounter ;
  426.          return (pCounter) ;
  427.          }  // if
  428.       }  // for
  429.  
  430.    return (NULL) ;
  431.    }  // LineFindCounter
  432.  
  433.                       
  434. PPERFINSTANCEDEF LineFindInstance (PPERFDATA pPerfData,
  435.                                    PPERFOBJECT pObject,
  436.                                    PLINE pLine)
  437.    {  // LineFindInstance
  438.   
  439.                                    
  440.    PPERFINSTANCEDEF  pInstance = NULL ;
  441.  
  442.    if ((pObject->NumInstances > 0) && pLine->lnInstanceName)
  443.       {
  444.       // instances exist, find the right one
  445.       
  446.       if (pLine->lnUniqueID != PERF_NO_UNIQUE_ID)
  447.          {
  448.          pInstance = GetInstanceByUniqueID(pObject, pLine->lnUniqueID) ;
  449.          }
  450.       else
  451.          {
  452.          pInstance = GetInstanceByName(pPerfData, pObject,
  453.                         pLine->lnInstanceName, pLine->lnPINName) ;
  454.          }
  455.       }
  456.  
  457.    if (pInstance)
  458.       {
  459.       pLine->lnInstanceDef = *pInstance ;
  460.       }
  461.  
  462.    return (pInstance) ;
  463.    }  // LineFindInstance
  464.  
  465.  
  466.  
  467.  
  468. void ReadLines (HANDLE hFile,
  469.                 DWORD dwNumLines,
  470.                 PPPERFSYSTEM ppSystemFirst,
  471.                 PPLINE ppLineFirst,
  472.                 int LineType)
  473.    {
  474.    DWORD          i ;
  475.    PPERFDATA      pPerfData ;
  476.    PLINE          pLine ;
  477.    PPERFSYSTEM    pSystem ;
  478.    PDISKLINE      pDiskLine = NULL ;
  479.    DWORD          SizeofDiskLine = 0 ;  // bytes in pDiskLine
  480.  
  481.  
  482.    pPerfData = AllocatePerfData () ;
  483.    pSystem = *ppSystemFirst ;
  484.  
  485. #if 0
  486.    if (!pSystem)
  487.       {
  488.       pSystem = SystemAdd (ppSystemFirst, LocalComputerName) ;
  489.       pSystem = *ppSystemFirst ; //!!
  490.       }
  491.  
  492.    UpdateSystemData (pSystem, &pPerfData) ;
  493. #endif
  494.    pDiskLine = MemoryAllocate (FilePathLen) ;
  495.    if (!pDiskLine)
  496.       {
  497.       // no memory to begin with, forget it
  498.       DlgErrorBox (hWndMain, ERR_NO_MEMORY) ;
  499.       return ;
  500.       }
  501.    SizeofDiskLine = FilePathLen ;
  502.  
  503.    for (i = 0 ;
  504.         i < dwNumLines ;
  505.         i++)
  506.       {
  507.       pLine = ReadLine (&pSystem, ppSystemFirst, &pPerfData, hFile,
  508.             LineType, &pDiskLine, &SizeofDiskLine) ;
  509.       if (pLine)
  510.          {
  511.          if (InsertLine (pLine) == FALSE)
  512.             {
  513.             // no inert occurred due to either line already existed
  514.             // or error detected.
  515.             LineFree (pLine) ;
  516.             }
  517.          }
  518.       }
  519.    
  520.    if (pDiskLine)
  521.       {
  522.       MemoryFree (pDiskLine);
  523.       }
  524.  
  525.    BuildValueListForSystems (*ppSystemFirst, *ppLineFirst) ;
  526.  
  527.    MemoryFree (pPerfData) ;
  528.    }  // ReadLines
  529.  
  530.  
  531.  
  532. PLINE ReadLine (PPERFSYSTEM *ppSystem,
  533.                 PPPERFSYSTEM ppSystemFirst,
  534.                 PPERFDATA *ppPerfData,
  535.                 HANDLE hFile,
  536.                 int LineType,
  537.                 PDISKLINE  *ppDiskLine,
  538.                 DWORD *pSizeofDiskLine)
  539.  
  540.  
  541. /*
  542.    Effect:        Read in a line from the file hFile, at the current file
  543.                   position.
  544.  
  545.    Internals:     The very first characters are a line signature, then a 
  546.                   length integer. If the signature is correct, then allocate
  547.                   the length amount, and work with that.
  548. */
  549.    {  // ReadLine
  550.    PLINE             pLine ;
  551.  
  552.    struct
  553.       {
  554.       DWORD             dwSignature ;
  555.       DWORD             dwLength ;
  556.       } LineHeader ;
  557.  
  558.    PPERFOBJECT       pObject ;
  559.    PPERFCOUNTERDEF   pCounter ;
  560.    PDISKLINE         pDiskLine ;    // Local copy of the pointer
  561.    PPERFINSTANCEDEF  pInstance ;
  562.  
  563.    pLine = NULL ;
  564.  
  565.    //=============================//
  566.    // read and compare signature  //
  567.    //=============================//
  568.  
  569.    if (!FileRead (hFile, &LineHeader, sizeof (LineHeader)))
  570.       return (NULL) ;
  571.  
  572.  
  573.    if (LineHeader.dwSignature != dwLineSignature ||
  574.        LineHeader.dwLength == 0)
  575.       {
  576.       SetLastError (ERROR_BAD_FORMAT) ;
  577.       return (NULL) ;
  578.       }
  579.  
  580.  
  581.    //=============================//
  582.    // read and allocate length    //
  583.    //=============================//
  584.  
  585.  
  586. //   if (!FileRead (hFile, &dwLength, sizeof (dwLength)) || dwLength == 0)
  587. //      return (NULL) ;
  588.  
  589.  
  590.    // check if we need a bigger buffer, 
  591.    // normally, it should be the same except the first time...
  592.    if (LineHeader.dwLength > *pSizeofDiskLine)
  593.       {
  594.       if (*ppDiskLine)
  595.          {
  596.          // free the previous buffer
  597.          MemoryFree (*ppDiskLine);
  598.          *pSizeofDiskLine = 0 ;
  599.          }
  600.  
  601.       // re-allocate a new buffer
  602.       *ppDiskLine = (PDISKLINE) MemoryAllocate (LineHeader.dwLength) ;
  603.       if (!(*ppDiskLine))
  604.          {
  605.          // no memory, should flag an error...
  606.          return (NULL) ;
  607.          }
  608.       *pSizeofDiskLine = LineHeader.dwLength ;
  609.       }
  610.       
  611.    pDiskLine = *ppDiskLine ;
  612.  
  613.  
  614.    //=============================//
  615.    // copy diskline, alloc line   //
  616.    //=============================//
  617.  
  618.    if (!FileRead (hFile, pDiskLine, LineHeader.dwLength))
  619.       return (NULL) ;
  620.  
  621.  
  622.    pLine = LineAllocate () ;
  623.    if (!pLine)
  624.       {
  625.       return (NULL) ;
  626.       }
  627.  
  628.    pLine->iLineType = pDiskLine->iLineType ;
  629.  
  630.  
  631.    //=============================//
  632.    // convert system information  //
  633.    //=============================//
  634.  
  635.    pLine->lnSystemName = DiskStringReadSys (&(pDiskLine->dsSystemName)) ;
  636.    if (!pLine->lnSystemName)
  637.       goto ErrorBadLine ;
  638.  
  639.    if (!*ppSystem || !strsamei (pLine->lnSystemName, (*ppSystem)->sysName))
  640.       {
  641.       *ppSystem = SystemAdd (ppSystemFirst, pLine->lnSystemName) ;
  642.       if (!*ppSystem)
  643.          {
  644.          SetLastError (ERROR_BAD_FORMAT) ;
  645.          goto ErrorBadLine ;
  646.          }
  647.       UpdateSystemData (*ppSystem, ppPerfData) ;
  648.       }  // if
  649.  
  650.    //=============================//
  651.    // convert object information  //
  652.    //=============================//
  653.  
  654.    pLine->lnObjectName = DiskStringRead (&(pDiskLine->dsObjectName)) ;
  655.    if (!pLine->lnObjectName)
  656.       goto ErrorBadLine ;
  657.  
  658.    pObject = LineFindObject (*ppSystem, *ppPerfData, pLine) ;
  659.  
  660.    //=============================//
  661.    // convert counter information //
  662.    //=============================//
  663.  
  664.    pLine->lnCounterName = DiskStringRead (&(pDiskLine->dsCounterName)) ;
  665.    if (!pLine->lnCounterName)
  666.       goto ErrorBadLine ;
  667.  
  668.    if (pObject)
  669.       {
  670.       pCounter = LineFindCounter (*ppSystem, pObject, *ppPerfData, pLine) ;
  671.       if (!pCounter)
  672.          {
  673.          SetLastError (ERROR_BAD_FORMAT) ;
  674.          goto ErrorBadLine ;
  675.          }
  676.       }
  677.  
  678.    //=============================//
  679.    // convert instance info       //
  680.    //=============================//
  681.  
  682.    pLine->lnUniqueID = pDiskLine->dwUniqueID ;
  683.    pLine->lnInstanceName = DiskStringRead (&(pDiskLine->dsInstanceName)) ;
  684.    pLine->lnPINName = DiskStringRead (&(pDiskLine->dsPINName)) ;
  685.  
  686.    if (pObject &&
  687.        pLine->lnObject.NumInstances > 0 &&
  688.        pLine->lnInstanceName == NULL)
  689.       {
  690.       goto ErrorBadLine ;
  691.       }
  692.  
  693.    if (pObject) {
  694.       pInstance = LineFindInstance (*ppPerfData, pObject, pLine) ;
  695.  
  696.       if (pInstance)
  697.          {
  698.          pLine->lnParentObjName = DiskStringRead (&(pDiskLine->dsParentObjName)) ;
  699.          }
  700.       }
  701.    else {
  702.       pLine->lnParentObjName = DiskStringRead (&(pDiskLine->dsParentObjName)) ;
  703.    }
  704.  
  705.  
  706.    //=============================//
  707.    // convert chart information   //
  708.    //=============================//
  709.  
  710.    if (LineType == IDM_VIEWCHART)
  711.       {
  712.       pLine->Visual = pDiskLine->Visual ;
  713.       pLine->hPen = CreatePen (pLine->Visual.iStyle,
  714.                                pLine->Visual.iWidth, 
  715.                                pLine->Visual.crColor) ;
  716.       pLine->iScaleIndex = pDiskLine->iScaleIndex ;
  717.       pLine->eScale = pDiskLine->eScale ;
  718.       }
  719.  
  720.  
  721.    //=============================//
  722.    // convert alert information   //
  723.    //=============================//
  724.  
  725.    if (LineType == IDM_VIEWALERT)
  726.       {
  727.       pLine->Visual = pDiskLine->Visual ;
  728.       pLine->hBrush = CreateSolidBrush (pLine->Visual.crColor) ;
  729.       pLine->bAlertOver = pDiskLine->bAlertOver ;
  730.       pLine->eAlertValue = pDiskLine->eAlertValue ;
  731.       pLine->lpszAlertProgram = DiskStringRead (&(pDiskLine->dsAlertProgram)) ;
  732.       pLine->bEveryTime = pDiskLine->bEveryTime ;
  733.       pLine->bAlerted = FALSE ;
  734.       }
  735.  
  736.  
  737.    //=============================//
  738.    // Convert the nasty stuff     //
  739.    //=============================//
  740.  
  741.  
  742.    if (pObject) {
  743.       pLine->lnCounterType = pCounter->CounterType;
  744.       pLine->lnCounterLength = pCounter->CounterSize;
  745.       }
  746.  
  747.    return (pLine) ;
  748.  
  749.  
  750. ErrorBadLine:
  751.    if (!pLine)
  752.       {
  753.       LineFree (pLine) ;
  754.       }
  755.    return (NULL) ;
  756.    }  // ReadLine
  757.  
  758.  
  759.  
  760.  
  761. BOOL WriteLine (PLINE pLine,
  762.                 HANDLE hFile)
  763.    {  // WriteLine
  764.    PDISKLINE      pDiskLine ;
  765.    DWORD          dwSignature ;
  766.    DWORD          dwLength ;
  767.    PBYTE          pNextFree ;
  768.    BOOL           bConvertName ;
  769.  
  770.    //=============================//
  771.    // write signature             //
  772.    //=============================//
  773.  
  774.    dwSignature = dwLineSignature ;
  775.    if (!FileWrite (hFile, &dwSignature, sizeof (dwSignature)))
  776.       return (FALSE) ;
  777.  
  778.    if (IsLocalComputer(pLine->lnSystemName))
  779.       {
  780.       bConvertName = TRUE ;
  781.       }
  782.    else
  783.       {
  784.       bConvertName = FALSE ;
  785.       }
  786.  
  787.    //=============================//
  788.    // compute and allocate length //
  789.    //=============================//
  790.  
  791.  
  792.    dwLength = sizeof (DISKLINE) ;
  793.    if (bConvertName)
  794.       {
  795.       dwLength += DiskStringLength (LOCAL_SYS_CODE_NAME) * sizeof (TCHAR) ;
  796.       }
  797.    else
  798.       {
  799.       dwLength += DiskStringLength (pLine->lnSystemName) * sizeof (TCHAR) ;
  800.       }
  801.    dwLength += DiskStringLength (pLine->lnObjectName) * sizeof (TCHAR) ;
  802.    dwLength += DiskStringLength (pLine->lnCounterName) * sizeof (TCHAR) ;
  803.    dwLength += DiskStringLength (pLine->lnInstanceName) * sizeof (TCHAR) ;
  804.    dwLength += DiskStringLength (pLine->lnPINName) * sizeof (TCHAR) ;
  805.    dwLength += DiskStringLength (pLine->lnParentObjName) * sizeof (TCHAR) ;
  806.    dwLength += DiskStringLength (pLine->lpszAlertProgram) * sizeof (TCHAR) ;
  807.  
  808.  
  809.    if (!FileWrite (hFile, &dwLength, sizeof (dwLength)))
  810.       return (FALSE) ;
  811.  
  812.    pDiskLine = (PDISKLINE) MemoryAllocate (dwLength) ;
  813.    if (!pDiskLine)
  814.       return (FALSE) ;
  815.  
  816.    pNextFree = (PBYTE) pDiskLine + sizeof (DISKLINE) ;
  817.  
  818.  
  819.    //=============================//
  820.    // convert fixed size fields   //
  821.    //=============================//
  822.  
  823.    pDiskLine->iLineType = pLine->iLineType ;
  824.    pDiskLine->dwUniqueID = pLine->lnUniqueID ;
  825.    pDiskLine->Visual = pLine->Visual ;
  826.    pDiskLine->iScaleIndex = pLine->iScaleIndex ;
  827.    pDiskLine->eScale = pLine->eScale ;
  828.    pDiskLine->bAlertOver = pLine->bAlertOver ;
  829.    pDiskLine->eAlertValue = pLine->eAlertValue ;
  830.    pDiskLine->bEveryTime = pLine->bEveryTime ;
  831.  
  832.  
  833.    //=============================//
  834.    // copy disk string fields     //
  835.    //=============================//
  836.  
  837.    if (bConvertName)
  838.       {
  839.       pNextFree = DiskStringCopy (&pDiskLine->dsSystemName, 
  840.                                   LOCAL_SYS_CODE_NAME,
  841.                                   pNextFree) ;
  842.       }
  843.    else
  844.       {
  845.       pNextFree = DiskStringCopy (&pDiskLine->dsSystemName, 
  846.                                   pLine->lnSystemName,
  847.                                   pNextFree) ;
  848.       }
  849.  
  850.    pNextFree = DiskStringCopy (&pDiskLine->dsObjectName, 
  851.                                pLine->lnObjectName,
  852.                                pNextFree) ;
  853.  
  854.    pNextFree = DiskStringCopy (&pDiskLine->dsCounterName, 
  855.                                pLine->lnCounterName,
  856.                                pNextFree) ;
  857.  
  858.    pNextFree = DiskStringCopy (&pDiskLine->dsParentObjName, 
  859.                                pLine->lnParentObjName,
  860.                                pNextFree) ;
  861.  
  862.    pNextFree = DiskStringCopy (&pDiskLine->dsInstanceName, 
  863.                                pLine->lnInstanceName,
  864.                                pNextFree) ;
  865.  
  866.    pNextFree = DiskStringCopy (&pDiskLine->dsPINName, 
  867.                                pLine->lnPINName,
  868.                                pNextFree) ;
  869.  
  870.    pNextFree = DiskStringCopy (&pDiskLine->dsAlertProgram, 
  871.                                pLine->lpszAlertProgram,
  872.                                pNextFree) ;
  873.  
  874.  
  875.  
  876.    FileWrite (hFile, pDiskLine, dwLength) ;
  877.    MemoryFree (pDiskLine) ;
  878.    return (TRUE) ;
  879.  
  880. //ErrorBadLine:
  881.    MemoryFree (pDiskLine) ;
  882.    return (FALSE) ;
  883.    }  // WriteLine
  884.  
  885.  
  886. // we are not doing printing.  In case we need this
  887. // later, then define DO_PRINTING
  888. #ifdef DO_PRINTING
  889. int aiPrinterLineStyles [] = 
  890.    {
  891.    PS_SOLID,
  892.    PS_DASH,
  893.    PS_DOT,
  894.    PS_DASHDOT,
  895.    PS_DASHDOTDOT
  896.    } ;
  897. #define NumPrinterLineStyles()   \
  898.    (sizeof (aiPrinterLineStyles) / sizeof (aiPrinterLineStyles [0]))
  899.  
  900.  
  901. COLORREF acrPrinterLineColors [] =
  902.    {
  903.    RGB (192, 192, 192),
  904.    RGB (128, 128, 128), 
  905.    RGB (64, 64, 64),
  906.    RGB (0, 0, 0)
  907.    }  ;
  908.  
  909.  
  910. #define NumPrinterLineColors()   \
  911.    (sizeof (acrPrinterLineColors) / sizeof (acrPrinterLineColors [0]))
  912. #endif      // DO_PRINTING
  913.  
  914.  
  915. HPEN LineCreatePen (HDC hDC,
  916.                     PLINEVISUAL pVisual,
  917.                     BOOL bForPrint)
  918.    {  // LineCreatePen
  919.    HPEN        hPen ;
  920. #ifdef DO_PRINTING
  921.    LOGBRUSH    logBrush ;
  922.  
  923.    if (bForPrint)
  924.       {
  925.       logBrush.lbStyle = PS_SOLID ;
  926. //!!         aiPrinterLineStyles [pVisual->iColorIndex % NumPrinterLineStyles ()] ;
  927.       logBrush.lbColor = 
  928.          acrPrinterLineColors [pVisual->iColorIndex % NumPrinterLineColors ()] ;
  929.       logBrush.lbHatch = 0 ;
  930.  
  931.       hPen = ExtCreatePen (logBrush.lbStyle | 
  932.                            PS_GEOMETRIC | 
  933.                            PS_ENDCAP_SQUARE | 
  934.                            PS_JOIN_BEVEL,
  935.                            VertInchPixels (hDC, pVisual->iWidth, 20),
  936.                            &logBrush,
  937.                            0, NULL) ;
  938.       }
  939.    else
  940. #endif
  941.       hPen = CreatePen (pVisual->iStyle,
  942.                         pVisual->iWidth, 
  943.                         pVisual->crColor) ;
  944.  
  945.    return (hPen) ;
  946.    }  // LineCreatePen
  947.  
  948.  
  949.  
  950. VOID FreeLines (PLINESTRUCT pLineFirst)
  951.    {  // FreeLines
  952.    PLINESTRUCT    pLine,next_line;
  953.  
  954.  
  955.    for (pLine = pLineFirst; pLine; pLine = next_line)
  956.       {
  957.       next_line = pLine->pLineNext;
  958.       LineFree (pLine) ;
  959.       }
  960.    }  // FreeLines
  961.  
  962. 
  963.