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 / playback.c < prev    next >
Text File  |  1994-10-13  |  23KB  |  789 lines

  1. //==========================================================================//
  2. //                                  Includes                                //
  3. //==========================================================================//
  4.  
  5.  
  6. #include "perfmon.h"
  7. #include "playback.h"   // external declarations for this module
  8.  
  9. #include "bookmark.h"   // for BookmarkAppend
  10. #include "grafdata.h"   // for ResetGraph
  11. #include "perfdata.h"   // for UpdateLinesForSystem
  12. #include "perfmops.h"   // for SystemTimeDateString
  13. #include "log.h"
  14. #include "pmemory.h"    // for MemoryAllocate
  15. #include "fileutil.h"
  16. #include "utils.h"
  17. #include "alert.h"      // for ResetAlert
  18. #include "report.h"     // for ResetReport
  19.  
  20. NTSTATUS  AddNamesToArray (LPTSTR pNames,
  21.    DWORD    dwLastID,
  22.    LPWSTR   *lpCounterId) ;
  23.  
  24.  
  25. void  PlaybackAddCounterName (PLOGINDEX pIndex) ;
  26.  
  27. //==========================================================================//
  28. //                                   Macros                                 //
  29. //==========================================================================//
  30.  
  31.  
  32.  
  33. #define PointerSeek(pBase, lFileOffset)         \
  34.    ((PVOID) ((PBYTE) pBase + lFileOffset))
  35.  
  36.  
  37. //==========================================================================//
  38. //                              Local Functions                             //
  39. //==========================================================================//
  40.  
  41.  
  42. PVOID PlaybackSeek (long lFileOffset)
  43.    {  // PlaybackSeek
  44.    return (PointerSeek (PlaybackLog.pHeader, lFileOffset)) ;
  45.    }  // PlaybackSeek
  46.  
  47.  
  48. PLOGINDEXBLOCK FirstIndexBlock (PLOGHEADER pLogHeader)
  49.    {
  50.    return ((PLOGINDEXBLOCK) PointerSeek (pLogHeader, pLogHeader->iLength)) ;
  51.    }
  52.  
  53.  
  54. PLOGINDEX IndexFromPosition (PLOGPOSITION pLogPosition)
  55.    {
  56.    return (&pLogPosition->pIndexBlock->aIndexes [pLogPosition->iIndex]) ;
  57.    }
  58.  
  59.  
  60. PPERFDATA DataFromIndex (PLOGINDEX pLogIndex,
  61.                          LPTSTR lpszSystemName)
  62.    {
  63.    PPERFDATA pPerfData;
  64.    TCHAR     szLoggedComputerName[MAX_COMPUTERNAME_LENGTH + 3] ;
  65.    int       iNumSystem ;
  66.  
  67.    // Note: NULL lpszSystemName means return first logged system name
  68.    //       at the specified index.
  69.  
  70.    pPerfData = PlaybackSeek (pLogIndex->lDataOffset) ;
  71.  
  72.    for (iNumSystem = 0;
  73.         iNumSystem < pLogIndex->iSystemsLogged;
  74.         iNumSystem++)
  75.       {
  76.       if ( pPerfData &&
  77.            pPerfData->Signature[0] == (WCHAR)'P' &&
  78.            pPerfData->Signature[1] == (WCHAR)'E' &&
  79.            pPerfData->Signature[2] == (WCHAR)'R' &&
  80.            pPerfData->Signature[3] == (WCHAR)'F' )
  81.           {
  82.           GetPerfComputerName(pPerfData, szLoggedComputerName) ;
  83.           if (!lpszSystemName || strsamei(lpszSystemName, szLoggedComputerName))
  84.               {
  85.               return pPerfData ;
  86.               }
  87.           pPerfData = (PPERFDATA)((PBYTE) pPerfData +
  88.                                   pPerfData->TotalByteLength) ;
  89.           }
  90.       else
  91.           { 
  92.           break ;
  93.           }
  94.        }
  95.    return NULL ;
  96.    }
  97.  
  98.  
  99. PPERFDATA DataFromIndexPosition (PLOGPOSITION pLogPosition,
  100.                                  LPTSTR lpszSystemName)
  101.    {
  102.    PLOGINDEX      pLogIndex ;
  103. //   long           lDataFileOffset ;
  104.  
  105.    pLogIndex = IndexFromPosition (pLogPosition) ;
  106.    return (DataFromIndex (pLogIndex, lpszSystemName)) ;
  107.    }
  108.  
  109.  
  110. BOOL NextLogPosition (IN OUT PLOGPOSITION pLogPosition)
  111.    {
  112.    PLOGINDEXBLOCK pIndexBlock ;
  113.  
  114.    if (pLogPosition->pIndexBlock->iNumIndexes == 0)
  115.       {
  116.       // no data in this index block.  This is most likely
  117.       // a corrupted log file caused by system failure...
  118.       return (FALSE) ;
  119.       }
  120.  
  121.    if (pLogPosition->iIndex == pLogPosition->pIndexBlock->iNumIndexes - 1)
  122.       {
  123.       if (pLogPosition->pIndexBlock->lNextBlockOffset)
  124.          {
  125.          pIndexBlock = 
  126.             PlaybackSeek (pLogPosition->pIndexBlock->lNextBlockOffset) ;
  127.  
  128.          if (pIndexBlock->iNumIndexes == 0)
  129.             {
  130.             // no data in the next index block.  This is most likely
  131.             // a corrupted log file caused by system failure...
  132.             return (FALSE) ;
  133.             }
  134.          else
  135.             {
  136.             pLogPosition->pIndexBlock = pIndexBlock ;
  137.             pLogPosition->iIndex = 0 ;
  138.             return (TRUE) ;
  139.             }
  140.          }
  141.       else
  142.          return (FALSE) ;   
  143.       }
  144.    else
  145.       {
  146.       pLogPosition->iIndex++ ;
  147.       return (TRUE) ;
  148.       } 
  149.    }
  150.  
  151.  
  152. BOOL NextIndexPosition (IN OUT PLOGPOSITION pLogPosition,
  153.                         BOOL bCheckForNonDataIndexes)
  154. /*
  155.    Effect:        Set pLogPosition to the next log position from 
  156.                   the current position of pLogPosition if there is one.
  157.  
  158.    Returns:       Whether there was a next log position.
  159. */
  160.    {  // NextIndexPosition
  161.    LOGPOSITION    LP ;
  162.    PLOGINDEX      pIndex ;
  163.    PBOOKMARK      pBookmarkDisk, pBookmark ;
  164. //   LONG           lFilePosition ;
  165.  
  166.    pIndex = IndexFromPosition (pLogPosition) ;
  167.    
  168.    LP = *pLogPosition ;
  169.    pBookmark = NULL ;
  170.  
  171.    while (TRUE)
  172.       {  // while
  173.       if (!NextLogPosition (&LP))
  174.          return (FALSE) ;
  175.       pIndex = IndexFromPosition (&LP) ;
  176.  
  177.       if (pIndex && bCheckForNonDataIndexes && IsCounterNameIndex (pIndex))
  178.          {
  179.          PlaybackAddCounterName (pIndex) ;
  180.          }
  181.  
  182.       if (pIndex && bCheckForNonDataIndexes && IsBookmarkIndex (pIndex))
  183.          {
  184.          if (pBookmark)
  185.             {
  186.             // this is the case when several bookmarks are
  187.             // found before any data index...
  188.             pBookmark->iTic = PlaybackLog.iTotalTics ;
  189.             BookmarkAppend (&PlaybackLog.pBookmarkFirst, pBookmark) ;
  190.             }
  191.  
  192.          pBookmarkDisk = PlaybackSeek (pIndex->lDataOffset) ;
  193.          pBookmark = MemoryAllocate (sizeof (BOOKMARK)) ;
  194.          *pBookmark = *pBookmarkDisk;
  195.          pBookmark->pBookmarkNext = NULL ;
  196.          }
  197.  
  198.       if (pIndex && IsDataIndex (pIndex))
  199.          {
  200.          LP.iPosition++ ;
  201.          *pLogPosition = LP ;
  202.          if (pBookmark)
  203.             {
  204.             pBookmark->iTic = PlaybackLog.iTotalTics ;
  205.             BookmarkAppend (&PlaybackLog.pBookmarkFirst, pBookmark) ;
  206.             }
  207.          return (TRUE) ;
  208.          }
  209.       }  // while
  210.    }  // NextIndexPosition
  211.  
  212.  
  213. BOOL NextReLogIndexPosition (IN OUT PLOGPOSITION pLogPosition)
  214. /*
  215.    Effect:        Set pLogPosition to the next log position from 
  216.                   the current position of pLogPosition if there is one.
  217.                   Will return bookmarks, counternames, or data.
  218.  
  219.    Returns:       Whether there was a next relog position.
  220. */
  221.    {  // NextReLogIndexPosition
  222.    LOGPOSITION    LP ;
  223.    PLOGINDEX      pIndex ;
  224. //   LONG           lFilePosition ;
  225.  
  226.    pIndex = IndexFromPosition (pLogPosition) ;
  227.    
  228.    LP = *pLogPosition ;
  229.  
  230.    if (!NextLogPosition (&LP))
  231.       return (FALSE) ;
  232.    pIndex = IndexFromPosition (&LP) ;
  233.  
  234.    if (pIndex && IsDataIndex (pIndex))
  235.       {
  236.       LP.iPosition++ ;
  237.       }
  238.    *pLogPosition = LP ;
  239.    return (TRUE) ;
  240.    }  // NextReLogIndexPosition
  241.  
  242.  
  243.  
  244.  
  245.    
  246. //==========================================================================//
  247. //                             Exported Functions                           //
  248. //==========================================================================//
  249.  
  250.  
  251. void PlaybackInitializeInstance (void)
  252.    {  // PlaybackInitializeInstance
  253.    PlaybackLog.iStatus = iPMStatusClosed ;
  254.    PlaybackLog.hFile = NULL ;
  255.  
  256.    PlaybackLog.szFilePath  = MemoryAllocate (FilePathLen * sizeof (TCHAR)) ;
  257.    PlaybackLog.szFileTitle = MemoryAllocate (FilePathLen * sizeof (TCHAR)) ;
  258.    lstrcpy (PlaybackLog.szFilePath,  szDefaultLogFileName) ;
  259.    lstrcpy (PlaybackLog.szFileTitle, szDefaultLogFileName) ;
  260.    }  // PlaybackInitializeInstance
  261.  
  262.  
  263. INT OpenPlayback (LPTSTR lpszFilePath, LPTSTR lpszFileTitle)
  264.    {  // OpenPlayback
  265.    BOOL     bFirstTime = TRUE ;
  266.  
  267.    lstrcpy  (PlaybackLog.szFilePath, lpszFilePath) ;
  268.    lstrcpy  (PlaybackLog.szFileTitle, lpszFileTitle) ;
  269.    PlaybackLog.hFile = FileHandleReadOnly (lpszFilePath) ;
  270.    if (!PlaybackLog.hFile || PlaybackLog.hFile == INVALID_HANDLE_VALUE)
  271.       {
  272.       return (ERR_CANT_OPEN) ;
  273.       }
  274.  
  275.    PlaybackLog.pHeader = (PLOGHEADER) FileMap (PlaybackLog.hFile,
  276.       &PlaybackLog.hMapHandle) ;
  277.    
  278.    if (!PlaybackLog.pHeader)
  279.       {
  280.       if (PlaybackLog.hMapHandle)
  281.          {
  282.          CloseHandle (PlaybackLog.hMapHandle) ;
  283.          }
  284.  
  285.       CloseHandle (PlaybackLog.hFile) ;
  286.       return (ERR_CANT_OPEN) ;
  287.       }
  288.  
  289.    if (!strsame (PlaybackLog.pHeader->szSignature, LogFileSignature))
  290.       {
  291.       FileUnMap((LPVOID)PlaybackLog.pHeader, PlaybackLog.hMapHandle) ;
  292.       CloseHandle (PlaybackLog.hFile) ;
  293.       return (ERR_BAD_LOG_FILE) ;
  294.       }
  295.  
  296.    PlaybackLog.BeginIndexPos.pIndexBlock = FirstIndexBlock (PlaybackLog.pHeader) ;
  297.    PlaybackLog.BeginIndexPos.iIndex = 0 ;
  298.    PlaybackLog.BeginIndexPos.iPosition = 0 ;
  299.    PlaybackLog.pBookmarkFirst = NULL ;
  300.  
  301.    PlaybackLog.iTotalTics = 1 ;
  302.    PlaybackLog.EndIndexPos = PlaybackLog.BeginIndexPos ;
  303.    while (NextIndexPosition (&PlaybackLog.EndIndexPos, TRUE))
  304.       {
  305.       if (bFirstTime)
  306.          {
  307.          // set the begin index to the first data index
  308.          bFirstTime = FALSE ;
  309.          PlaybackLog.BeginIndexPos.iIndex =
  310.             PlaybackLog.EndIndexPos.iIndex ;
  311.          }
  312.       else
  313.          {
  314.          PlaybackLog.iTotalTics++ ;
  315.          }
  316.       }
  317.  
  318.    if (PlaybackLog.iTotalTics == 1 )
  319.       {
  320.       // no data inside the log file.  It must be a corrupted
  321.       // log file
  322.       FileUnMap((LPVOID)PlaybackLog.pHeader, PlaybackLog.hMapHandle) ;
  323.       CloseHandle (PlaybackLog.hFile) ;
  324.       return (ERR_CORRUPT_LOG) ;
  325.       }
  326.  
  327. //   PlaybackLog.StartIndexPos = PlaybackLog.BeginIndexPos ;
  328.  
  329.    // getthe first data index
  330.    if (!LogPositionN (1, &(PlaybackLog.StartIndexPos)))
  331.       {
  332.       PlaybackLog.StartIndexPos = PlaybackLog.BeginIndexPos ;
  333.       }
  334.  
  335.    PlaybackLog.StopIndexPos = PlaybackLog.EndIndexPos ;
  336.    PlaybackLog.StopIndexPos.iPosition =
  337.       min (PlaybackLog.StopIndexPos.iPosition,
  338.            PlaybackLog.iTotalTics - 1 ) ;
  339.  
  340.  
  341.    PlaybackLog.iSelectedTics = PlaybackLog.iTotalTics ;
  342.  
  343.    PlaybackLog.iStatus = iPMStatusPlaying ;
  344.    return (0) ;   
  345.    }  // OpenPlayback
  346.  
  347.  
  348. void CloseInputLog (HWND hWndParent)
  349.    {  // CloseInputLog
  350.    PBOOKMARK      pBookmark, pNextBookmark ;
  351.    BOOL           retCode, retCode1 ;
  352.    PLOGCOUNTERNAME pLogCounterName, pNextCounterName ;
  353.  
  354.    UNREFERENCED_PARAMETER (hWndParent) ;
  355.  
  356.    // free the bookmark list
  357.    for (pBookmark = PlaybackLog.pBookmarkFirst ;
  358.       pBookmark ;
  359.       pBookmark = pNextBookmark )
  360.       {
  361.       // save next bookmark and free current bookmark
  362.       pNextBookmark = pBookmark->pBookmarkNext ;
  363.       MemoryFree (pBookmark) ;
  364.       }
  365.    PlaybackLog.pBookmarkFirst = NULL ;
  366.  
  367.    // free all counter names stuff
  368.    if (PlaybackLog.pBaseCounterNames)
  369.       {
  370.       MemoryFree (PlaybackLog.pBaseCounterNames) ;
  371.       }
  372.    PlaybackLog.pBaseCounterNames = NULL ;
  373.    PlaybackLog.lBaseCounterNameSize = 0 ;
  374.    PlaybackLog.lBaseCounterNameOffset = 0 ;
  375.  
  376.    for (pLogCounterName = PlaybackLog.pLogCounterNameFirst ;
  377.       pLogCounterName ;
  378.       pLogCounterName = pNextCounterName)
  379.       {
  380.       pNextCounterName = pLogCounterName->pCounterNameNext ;
  381.       MemoryFree (pLogCounterName->pRemainNames) ;
  382.       MemoryFree (pLogCounterName) ;
  383.       }
  384.  
  385.    PlaybackLog.pLogCounterNameFirst = NULL ;
  386.  
  387.    retCode1 = FileUnMap((LPVOID)PlaybackLog.pHeader, PlaybackLog.hMapHandle) ;
  388.    retCode = CloseHandle (PlaybackLog.hFile) ;
  389.    PlaybackLog.iStatus = iPMStatusClosed ;
  390.  
  391.    ResetGraphView (hWndGraph) ;
  392.    ResetAlertView (hWndAlert) ;
  393.    ResetLogView (hWndLog) ;
  394.    ResetReportView (hWndReport) ;
  395.    }
  396.  
  397.  
  398.  
  399. BOOL LogPositionN (int iIndex, PLOGPOSITION pLP)
  400.    {  // LogPositionN
  401.    LOGPOSITION    LP ;
  402.    int            i ;
  403.  
  404.    LP = PlaybackLog.BeginIndexPos ;
  405.    for (i = 0 ;
  406.         i < iIndex ;
  407.         i++)
  408.       {
  409.       if (!NextIndexPosition (&LP, FALSE))
  410.          return (FALSE) ;
  411.       }
  412.  
  413.    *pLP = LP ;
  414.    return (TRUE) ;
  415.    }  // LogPositionN
  416.  
  417.  
  418. PLOGINDEX PlaybackIndexN (int iIndex)
  419.    {
  420.    LOGPOSITION    LP ;
  421.    int            i ;
  422.  
  423.    LP = PlaybackLog.BeginIndexPos ;
  424.    for (i = 0 ;
  425.         i < iIndex ;
  426.         i++)
  427.       {
  428.       if (!NextIndexPosition (&LP, FALSE))
  429.          return (NULL) ;
  430.       }
  431.  
  432.    return (IndexFromPosition (&LP)) ;
  433.    }
  434.  
  435.  
  436. BOOL PlaybackLines (PPERFSYSTEM pSystemFirst,
  437.                     PLINE pLineFirst,
  438.                     int iLogTic)
  439.    {  // PlaybackLines
  440.  
  441.    PLOGINDEX      pLogIndex ;
  442.    PPERFDATA      pPerfData ;
  443.    PPERFSYSTEM       pSystem ;
  444.    BOOL           bAnyFound ;
  445.  
  446.    pLogIndex = PlaybackIndexN (iLogTic) ;
  447.    if (!pLogIndex)
  448.       return (FALSE) ;
  449.  
  450.    bAnyFound = FALSE ;
  451.    for (pSystem = pSystemFirst ;
  452.         pSystem ;
  453.         pSystem = pSystem->pSystemNext)
  454.       {  // for
  455.       pPerfData = DataFromIndex (pLogIndex, pSystem->sysName) ;
  456.       if (pPerfData)
  457.          {
  458.          UpdateLinesForSystem (pSystem->sysName,
  459.                                pPerfData,
  460.                                pLineFirst,
  461.                                NULL) ;
  462.          bAnyFound = TRUE ;
  463.          }
  464.       else
  465.          {
  466.          FailedLinesForSystem (pSystem->sysName,
  467.                                pPerfData,
  468.                                pLineFirst) ;
  469.          }
  470.       }
  471.    return (bAnyFound) ;
  472.    }  // PlaybackLines
  473.  
  474.  
  475.  
  476.  
  477. PPERFDATA LogDataFromPosition (PPERFSYSTEM pSystem, 
  478.                                PLOGPOSITION pLogPosition)
  479.    {  // LogDataFromPosition
  480.    PLOGINDEX      pLogIndex ;
  481.    
  482.  
  483.    if (!pLogPosition)
  484.       return (NULL) ;
  485.  
  486.    pLogIndex = IndexFromPosition (pLogPosition) ;
  487.    if (!pLogIndex)
  488.       return (NULL) ;
  489.    
  490.    return (DataFromIndex (pLogIndex, pSystem->sysName)) ;
  491.    }  // LogDataFromPosition
  492.  
  493.  
  494.  
  495. BOOL LogPositionSystemTime (PLOGPOSITION pLP, SYSTEMTIME *pSystemTime)
  496. /*
  497.    Effect:        Given a logposition, get the index entry for that position
  498.                   and return the system time stored therein.
  499. */
  500.    {  // LogPositionSystemTime
  501.    PLOGINDEX      pLogIndex ;
  502.  
  503.    pLogIndex = IndexFromPosition (pLP) ;
  504.    if (!pLogIndex)
  505.       return (FALSE) ;
  506.  
  507.    *pSystemTime = pLogIndex->SystemTime ;
  508.    }  // LogPositionSystemTime
  509.  
  510.  
  511. int LogPositionIntervalSeconds (PLOGPOSITION pLPStart, 
  512.                                 PLOGPOSITION pLPStop)
  513. /*
  514.    Effect:        Return the time difference (in seconds) between the
  515.                   system times of the two specified log positions.
  516. */
  517.    {  // LogPositionIntervalSeconds
  518.    SYSTEMTIME     SystemTimeStart ;
  519.    SYSTEMTIME     SystemTimeStop ;
  520.  
  521.  
  522.    if (LogPositionSystemTime (pLPStart, &SystemTimeStart) &&
  523.        LogPositionSystemTime (pLPStop, &SystemTimeStop))
  524.       return (SystemTimeDifference (&SystemTimeStart, &SystemTimeStop)) ;
  525.    else
  526.       return (0) ;
  527.    }  // LogPositionIntervalSeconds
  528.  
  529.  
  530.  
  531. int PlaybackSelectedSeconds (void)
  532.    {  // PlaybackSelectedSeconds
  533.    return (LogPositionIntervalSeconds (&PlaybackLog.StartIndexPos, 
  534.                                        &PlaybackLog.StopIndexPos)) ;
  535.    }  // PlaybackSelectedSeconds
  536.  
  537. void BuildLogComputerList (HWND hDlg, int DlgID)
  538.    {
  539.    PPERFDATA pPerfData;
  540.    int       iNumSystem ;
  541.    HWND      hListBox = GetDlgItem (hDlg, DlgID) ;
  542.    PLOGINDEX pLogIndex ;
  543.    TCHAR     szLoggedComputerName[MAX_COMPUTERNAME_LENGTH + 3] ;
  544.    int       Index ;
  545.  
  546.    pLogIndex = IndexFromPosition (&(PlaybackLog.StartIndexPos)) ;
  547.    pPerfData = PlaybackSeek (pLogIndex->lDataOffset) ;
  548.  
  549.    for (iNumSystem = 0;
  550.         iNumSystem < pLogIndex->iSystemsLogged;
  551.         iNumSystem++)
  552.       {
  553.       if ( pPerfData &&
  554.            pPerfData->Signature[0] == (WCHAR)'P' &&
  555.            pPerfData->Signature[1] == (WCHAR)'E' &&
  556.            pPerfData->Signature[2] == (WCHAR)'R' &&
  557.            pPerfData->Signature[3] == (WCHAR)'F' )
  558.           {
  559.           GetPerfComputerName(pPerfData, szLoggedComputerName) ;
  560.           Index = LBFind (hListBox, szLoggedComputerName) ;
  561.           if (Index != LB_ERR) 
  562.              {
  563.              // computer name already exist, we must have reach the next
  564.              // block of perfdata
  565.              break ;
  566.              }
  567.           LBAdd (hListBox, szLoggedComputerName) ;
  568.           pPerfData = (PPERFDATA)((PBYTE) pPerfData +
  569.                                   pPerfData->TotalByteLength) ;
  570.           }
  571.        else 
  572.           {
  573.           break;
  574.           }
  575.        }
  576.    }  // BuildLogComputerList
  577.  
  578. void  PlaybackAddCounterName (PLOGINDEX pIndex)
  579. {
  580.    PLOGCOUNTERNAME      pLogCounterName, pListCounterName ;
  581.    PLOGFILECOUNTERNAME  pDiskCounterName ;
  582.    PVOID                pCounterData ;
  583.    BOOL                 bExist = FALSE ;
  584.  
  585.    pDiskCounterName = PlaybackSeek (pIndex->lDataOffset) ;
  586.  
  587.    // check we have a record for this system
  588.    for (pListCounterName = PlaybackLog.pLogCounterNameFirst ;
  589.         pListCounterName ;
  590.         pListCounterName = pListCounterName->pCounterNameNext)
  591.       {
  592.       if (strsamei(pDiskCounterName->szComputer,
  593.          pListCounterName->CounterName.szComputer))
  594.          {
  595.          // found!
  596.          pLogCounterName = pListCounterName ;
  597.          bExist = TRUE ;
  598.          break ;
  599.          }
  600.       }
  601.  
  602.    if (!bExist)
  603.       {
  604.       // new counter name record
  605.       if (!(pLogCounterName = MemoryAllocate (sizeof(LOGCOUNTERNAME))))
  606.          {
  607.          return ;
  608.          }
  609.       }
  610.    else
  611.       {
  612.       // free old memory in previous counter name record.
  613.       if (pLogCounterName->pRemainNames)
  614.          {
  615.          MemoryFree (pLogCounterName->pRemainNames) ;
  616.          }
  617.       pLogCounterName->pRemainNames = NULL ;
  618.       }
  619.  
  620.    pLogCounterName->CounterName = *pDiskCounterName ;
  621.  
  622.    if (pDiskCounterName->lBaseCounterNameOffset == 0)
  623.       {
  624.       // this is the base counter names, 
  625.       // get the master copy of the counter names
  626.  
  627.       if (!(pCounterData =
  628.             MemoryAllocate (pDiskCounterName->lUnmatchCounterNames)))
  629.          {
  630.          MemoryFree (pLogCounterName) ;
  631.          return ;
  632.          }
  633.  
  634.       // free the old one if it exists.
  635.       if (PlaybackLog.pBaseCounterNames)
  636.          {
  637.          MemoryFree (PlaybackLog.pBaseCounterNames) ;
  638.          }
  639.    
  640.       PlaybackLog.pBaseCounterNames = pCounterData ;
  641.  
  642.       pCounterData =
  643.          PlaybackSeek (pDiskCounterName->lCurrentCounterNameOffset) ;
  644.  
  645.       memcpy (PlaybackLog.pBaseCounterNames,
  646.          pCounterData,
  647.          pDiskCounterName->lUnmatchCounterNames) ;
  648.  
  649.       PlaybackLog.lBaseCounterNameSize =
  650.          pDiskCounterName->lUnmatchCounterNames ;
  651.  
  652.       PlaybackLog.lBaseCounterNameOffset =
  653.          pDiskCounterName->lBaseCounterNameOffset ;
  654.       }
  655.    else if (pDiskCounterName->lUnmatchCounterNames)
  656.       {
  657.       // this is not a based system and it has extra counter names
  658.       // allocate a buffer to hold them
  659.       pLogCounterName->pRemainNames =
  660.          MemoryAllocate (pDiskCounterName->lUnmatchCounterNames) ;
  661.  
  662.       if (pLogCounterName->pRemainNames)
  663.          {
  664.          pCounterData =
  665.             PlaybackSeek (pDiskCounterName->lCurrentCounterNameOffset) ;
  666.  
  667.          memcpy(pLogCounterName->pRemainNames,
  668.             pCounterData,
  669.             pDiskCounterName->lUnmatchCounterNames) ;
  670.          }
  671.       }
  672.  
  673.    if (!bExist)
  674.       {
  675.       // now add the new counter name record to the linked list
  676.       if (!PlaybackLog.pLogCounterNameFirst)
  677.          {
  678.          PlaybackLog.pLogCounterNameFirst = pLogCounterName ;
  679.          }
  680.       else
  681.          {
  682.          for (pListCounterName = PlaybackLog.pLogCounterNameFirst ;
  683.             pListCounterName->pCounterNameNext ;
  684.             pListCounterName = pListCounterName->pCounterNameNext)
  685.             {
  686.             // do nothing until we get to the end of the list
  687.             ;
  688.             }
  689.          pListCounterName->pCounterNameNext = pLogCounterName ;
  690.          }
  691.       }
  692.  
  693. }  // PlaybackAddCounterName
  694.  
  695.  
  696. LPWSTR *LogBuildNameTable (PPERFSYSTEM pSysInfo)
  697. {
  698.  
  699.    DWORD             dwArraySize ;
  700.    PLOGCOUNTERNAME   pCounterName ;
  701.    LPWSTR            *lpCounterId = NULL ;
  702.    LPWSTR            lpCounterNames ;
  703.    NTSTATUS          Status ;
  704.  
  705.    for (pCounterName = PlaybackLog.pLogCounterNameFirst ;
  706.         pCounterName ;
  707.         pCounterName = pCounterName->pCounterNameNext)
  708.       {
  709.       if (strsamei (pSysInfo->sysName, pCounterName->CounterName.szComputer))
  710.          {
  711.          // found the right system
  712.          break ;
  713.          }
  714.       }
  715.    if (!pCounterName)
  716.       {
  717.       goto ERROR_EXIT ;
  718.       }
  719.  
  720.    dwArraySize = (pCounterName->CounterName.dwLastCounterId + 1)
  721.       * sizeof (LPWSTR) ;
  722.  
  723.    lpCounterId = MemoryAllocate (dwArraySize +
  724.       pCounterName->CounterName.lMatchLength +
  725.       pCounterName->CounterName.lUnmatchCounterNames ) ;
  726.  
  727.    if (!lpCounterId)
  728.       {
  729.       goto ERROR_EXIT ;
  730.       }
  731.  
  732.    // initialize pointers into buffer
  733.  
  734.    lpCounterNames = (LPWSTR)((LPBYTE)lpCounterId + dwArraySize);
  735.    if (pCounterName->CounterName.lBaseCounterNameOffset == 0)
  736.       {
  737.       // this is the base system
  738.       memcpy(lpCounterNames,
  739.          PlaybackLog.pBaseCounterNames,
  740.          PlaybackLog.lBaseCounterNameSize) ;
  741.       }
  742.    else
  743.       {
  744.       // copy the matched portion from the base system
  745.       memcpy(lpCounterNames,
  746.          PlaybackLog.pBaseCounterNames,
  747.          pCounterName->CounterName.lMatchLength) ;
  748.  
  749.       // copy the unmatched portion
  750.       if (pCounterName->CounterName.lUnmatchCounterNames)
  751.          {
  752.          memcpy(((PBYTE)lpCounterNames +
  753.             pCounterName->CounterName.lMatchLength),
  754.             pCounterName->pRemainNames,
  755.             pCounterName->CounterName.lUnmatchCounterNames) ;
  756.          }
  757.       }
  758.  
  759.    Status = AddNamesToArray (lpCounterNames,
  760.       pCounterName->CounterName.dwLastCounterId,
  761.       lpCounterId) ;
  762.  
  763.    if (Status != ERROR_SUCCESS)
  764.       {
  765.       goto ERROR_EXIT ;
  766.       }
  767.  
  768.    pSysInfo->CounterInfo.dwLastId =
  769.       pCounterName->CounterName.dwLastCounterId ;
  770.    pSysInfo->CounterInfo.dwLangId =
  771.       pCounterName->CounterName.dwLangId ;
  772.    pSysInfo->CounterInfo.dwHelpSize = 0 ;
  773.    pSysInfo->CounterInfo.dwCounterSize =
  774.       pCounterName->CounterName.lMatchLength +
  775.       pCounterName->CounterName.lUnmatchCounterNames ;
  776.    
  777.    return (lpCounterId) ;
  778.  
  779. ERROR_EXIT:
  780.    if (lpCounterId)
  781.       {
  782.       MemoryFree (lpCounterId) ;
  783.       }
  784.    return (NULL) ;
  785. } // LogBuildNameTable
  786.  
  787.     
  788. 
  789.