793 lines
22 KiB
C
793 lines
22 KiB
C
//==========================================================================//
|
|
// Includes //
|
|
//==========================================================================//
|
|
|
|
|
|
#include "perfmon.h"
|
|
#include "playback.h" // external declarations for this module
|
|
|
|
#include "bookmark.h" // for BookmarkAppend
|
|
#include "grafdata.h" // for ResetGraph
|
|
#include "perfdata.h" // for UpdateLinesForSystem
|
|
#include "perfmops.h" // for SystemTimeDateString
|
|
#include "log.h"
|
|
#include "pmemory.h" // for MemoryAllocate
|
|
#include "fileutil.h"
|
|
#include "utils.h"
|
|
#include "alert.h" // for ResetAlert
|
|
#include "report.h" // for ResetReport
|
|
|
|
NTSTATUS AddNamesToArray (LPTSTR pNames,
|
|
DWORD dwLastID,
|
|
LPWSTR *lpCounterId) ;
|
|
|
|
|
|
void PlaybackAddCounterName (PLOGINDEX pIndex) ;
|
|
|
|
//==========================================================================//
|
|
// Macros //
|
|
//==========================================================================//
|
|
|
|
|
|
|
|
#define PointerSeek(pBase, lFileOffset) \
|
|
((PVOID) ((PBYTE) pBase + lFileOffset))
|
|
|
|
|
|
//==========================================================================//
|
|
// Local Functions //
|
|
//==========================================================================//
|
|
|
|
|
|
PVOID PlaybackSeek (long lFileOffset)
|
|
{ // PlaybackSeek
|
|
return (PointerSeek (PlaybackLog.pHeader, lFileOffset)) ;
|
|
} // PlaybackSeek
|
|
|
|
|
|
PLOGINDEXBLOCK FirstIndexBlock (PLOGHEADER pLogHeader)
|
|
{
|
|
return ((PLOGINDEXBLOCK) PointerSeek (pLogHeader, pLogHeader->iLength)) ;
|
|
}
|
|
|
|
|
|
PLOGINDEX IndexFromPosition (PLOGPOSITION pLogPosition)
|
|
{
|
|
return (&pLogPosition->pIndexBlock->aIndexes [pLogPosition->iIndex]) ;
|
|
}
|
|
|
|
|
|
PPERFDATA DataFromIndex (PLOGINDEX pLogIndex,
|
|
LPTSTR lpszSystemName)
|
|
{
|
|
PPERFDATA pPerfData;
|
|
TCHAR szLoggedComputerName[MAX_PATH + 3] ;
|
|
int iNumSystem ;
|
|
|
|
// Note: NULL lpszSystemName means return first logged system name
|
|
// at the specified index.
|
|
|
|
pPerfData = PlaybackSeek (pLogIndex->lDataOffset) ;
|
|
|
|
for (iNumSystem = 0;
|
|
iNumSystem < pLogIndex->iSystemsLogged;
|
|
iNumSystem++)
|
|
{
|
|
if ( pPerfData &&
|
|
pPerfData->Signature[0] == (WCHAR)'P' &&
|
|
pPerfData->Signature[1] == (WCHAR)'E' &&
|
|
pPerfData->Signature[2] == (WCHAR)'R' &&
|
|
pPerfData->Signature[3] == (WCHAR)'F' )
|
|
{
|
|
GetPerfComputerName(pPerfData, szLoggedComputerName) ;
|
|
if (!lpszSystemName || strsamei(lpszSystemName, szLoggedComputerName))
|
|
{
|
|
return pPerfData ;
|
|
}
|
|
pPerfData = (PPERFDATA)((PBYTE) pPerfData +
|
|
pPerfData->TotalByteLength) ;
|
|
}
|
|
else
|
|
{
|
|
break ;
|
|
}
|
|
}
|
|
return NULL ;
|
|
}
|
|
|
|
|
|
PPERFDATA DataFromIndexPosition (PLOGPOSITION pLogPosition,
|
|
LPTSTR lpszSystemName)
|
|
{
|
|
PLOGINDEX pLogIndex ;
|
|
// long lDataFileOffset ;
|
|
|
|
pLogIndex = IndexFromPosition (pLogPosition) ;
|
|
return (DataFromIndex (pLogIndex, lpszSystemName)) ;
|
|
}
|
|
|
|
|
|
BOOL NextLogPosition (IN OUT PLOGPOSITION pLogPosition)
|
|
{
|
|
PLOGINDEXBLOCK pIndexBlock ;
|
|
|
|
if (pLogPosition->pIndexBlock->iNumIndexes == 0)
|
|
{
|
|
// no data in this index block. This is most likely
|
|
// a corrupted log file caused by system failure...
|
|
return (FALSE) ;
|
|
}
|
|
|
|
if (pLogPosition->iIndex == pLogPosition->pIndexBlock->iNumIndexes - 1)
|
|
{
|
|
if (pLogPosition->pIndexBlock->lNextBlockOffset)
|
|
{
|
|
pIndexBlock =
|
|
PlaybackSeek (pLogPosition->pIndexBlock->lNextBlockOffset) ;
|
|
|
|
if (pIndexBlock->iNumIndexes == 0)
|
|
{
|
|
// no data in the next index block. This is most likely
|
|
// a corrupted log file caused by system failure...
|
|
return (FALSE) ;
|
|
}
|
|
else
|
|
{
|
|
pLogPosition->pIndexBlock = pIndexBlock ;
|
|
pLogPosition->iIndex = 0 ;
|
|
return (TRUE) ;
|
|
}
|
|
}
|
|
else
|
|
return (FALSE) ;
|
|
}
|
|
else
|
|
{
|
|
pLogPosition->iIndex++ ;
|
|
return (TRUE) ;
|
|
}
|
|
}
|
|
|
|
|
|
BOOL NextIndexPosition (IN OUT PLOGPOSITION pLogPosition,
|
|
BOOL bCheckForNonDataIndexes)
|
|
/*
|
|
Effect: Set pLogPosition to the next log position from
|
|
the current position of pLogPosition if there is one.
|
|
|
|
Returns: Whether there was a next log position.
|
|
*/
|
|
{ // NextIndexPosition
|
|
LOGPOSITION LP ;
|
|
PLOGINDEX pIndex ;
|
|
PBOOKMARK pBookmarkDisk, pBookmark ;
|
|
// LONG lFilePosition ;
|
|
|
|
pIndex = IndexFromPosition (pLogPosition) ;
|
|
|
|
LP = *pLogPosition ;
|
|
pBookmark = NULL ;
|
|
|
|
while (TRUE)
|
|
{ // while
|
|
if (!NextLogPosition (&LP))
|
|
return (FALSE) ;
|
|
pIndex = IndexFromPosition (&LP) ;
|
|
|
|
if (pIndex && bCheckForNonDataIndexes && IsCounterNameIndex (pIndex))
|
|
{
|
|
PlaybackAddCounterName (pIndex) ;
|
|
}
|
|
|
|
if (pIndex && bCheckForNonDataIndexes && IsBookmarkIndex (pIndex))
|
|
{
|
|
if (pBookmark)
|
|
{
|
|
// this is the case when several bookmarks are
|
|
// found before any data index...
|
|
pBookmark->iTic = PlaybackLog.iTotalTics ;
|
|
BookmarkAppend (&PlaybackLog.pBookmarkFirst, pBookmark) ;
|
|
}
|
|
|
|
pBookmarkDisk = PlaybackSeek (pIndex->lDataOffset) ;
|
|
pBookmark = MemoryAllocate (sizeof (BOOKMARK)) ;
|
|
*pBookmark = *pBookmarkDisk;
|
|
pBookmark->pBookmarkNext = NULL ;
|
|
}
|
|
|
|
if (pIndex && IsDataIndex (pIndex))
|
|
{
|
|
LP.iPosition++ ;
|
|
*pLogPosition = LP ;
|
|
if (pBookmark)
|
|
{
|
|
pBookmark->iTic = PlaybackLog.iTotalTics ;
|
|
BookmarkAppend (&PlaybackLog.pBookmarkFirst, pBookmark) ;
|
|
}
|
|
return (TRUE) ;
|
|
}
|
|
} // while
|
|
} // NextIndexPosition
|
|
|
|
|
|
BOOL NextReLogIndexPosition (IN OUT PLOGPOSITION pLogPosition)
|
|
/*
|
|
Effect: Set pLogPosition to the next log position from
|
|
the current position of pLogPosition if there is one.
|
|
Will return bookmarks, counternames, or data.
|
|
|
|
Returns: Whether there was a next relog position.
|
|
*/
|
|
{ // NextReLogIndexPosition
|
|
LOGPOSITION LP ;
|
|
PLOGINDEX pIndex ;
|
|
// LONG lFilePosition ;
|
|
|
|
pIndex = IndexFromPosition (pLogPosition) ;
|
|
|
|
LP = *pLogPosition ;
|
|
|
|
if (!NextLogPosition (&LP))
|
|
return (FALSE) ;
|
|
pIndex = IndexFromPosition (&LP) ;
|
|
|
|
if (pIndex && IsDataIndex (pIndex))
|
|
{
|
|
LP.iPosition++ ;
|
|
}
|
|
*pLogPosition = LP ;
|
|
return (TRUE) ;
|
|
} // NextReLogIndexPosition
|
|
|
|
|
|
|
|
|
|
|
|
//==========================================================================//
|
|
// Exported Functions //
|
|
//==========================================================================//
|
|
|
|
|
|
void PlaybackInitializeInstance (void)
|
|
{ // PlaybackInitializeInstance
|
|
PlaybackLog.iStatus = iPMStatusClosed ;
|
|
PlaybackLog.hFile = NULL ;
|
|
|
|
PlaybackLog.szFilePath = MemoryAllocate (FilePathLen * sizeof (TCHAR)) ;
|
|
PlaybackLog.szFileTitle = MemoryAllocate (FilePathLen * sizeof (TCHAR)) ;
|
|
lstrcpy (PlaybackLog.szFilePath, szDefaultLogFileName) ;
|
|
lstrcpy (PlaybackLog.szFileTitle, szDefaultLogFileName) ;
|
|
} // PlaybackInitializeInstance
|
|
|
|
|
|
INT OpenPlayback (LPTSTR lpszFilePath, LPTSTR lpszFileTitle)
|
|
{ // OpenPlayback
|
|
BOOL bFirstTime = TRUE ;
|
|
|
|
lstrcpy (PlaybackLog.szFilePath, lpszFilePath) ;
|
|
lstrcpy (PlaybackLog.szFileTitle, lpszFileTitle) ;
|
|
PlaybackLog.hFile = FileHandleReadOnly (lpszFilePath) ;
|
|
if (!PlaybackLog.hFile || PlaybackLog.hFile == INVALID_HANDLE_VALUE)
|
|
{
|
|
return (ERR_CANT_OPEN) ;
|
|
}
|
|
|
|
PlaybackLog.pHeader = (PLOGHEADER) FileMap (PlaybackLog.hFile,
|
|
&PlaybackLog.hMapHandle) ;
|
|
|
|
if (!PlaybackLog.pHeader)
|
|
{
|
|
if (PlaybackLog.hMapHandle)
|
|
{
|
|
CloseHandle (PlaybackLog.hMapHandle) ;
|
|
}
|
|
|
|
CloseHandle (PlaybackLog.hFile) ;
|
|
return (ERR_CANT_OPEN) ;
|
|
}
|
|
|
|
if (!strsame (PlaybackLog.pHeader->szSignature, LogFileSignature))
|
|
{
|
|
FileUnMap((LPVOID)PlaybackLog.pHeader, PlaybackLog.hMapHandle) ;
|
|
CloseHandle (PlaybackLog.hFile) ;
|
|
return (ERR_BAD_LOG_FILE) ;
|
|
}
|
|
|
|
PlaybackLog.BeginIndexPos.pIndexBlock = FirstIndexBlock (PlaybackLog.pHeader) ;
|
|
PlaybackLog.BeginIndexPos.iIndex = 0 ;
|
|
PlaybackLog.BeginIndexPos.iPosition = 0 ;
|
|
PlaybackLog.pBookmarkFirst = NULL ;
|
|
|
|
PlaybackLog.iTotalTics = 1 ;
|
|
PlaybackLog.EndIndexPos = PlaybackLog.BeginIndexPos ;
|
|
while (NextIndexPosition (&PlaybackLog.EndIndexPos, TRUE))
|
|
{
|
|
if (bFirstTime)
|
|
{
|
|
// set the begin index to the first data index
|
|
bFirstTime = FALSE ;
|
|
PlaybackLog.BeginIndexPos.iIndex =
|
|
PlaybackLog.EndIndexPos.iIndex ;
|
|
}
|
|
else
|
|
{
|
|
PlaybackLog.iTotalTics++ ;
|
|
}
|
|
}
|
|
|
|
if (PlaybackLog.iTotalTics == 1 )
|
|
{
|
|
// no data inside the log file. It must be a corrupted
|
|
// log file
|
|
FileUnMap((LPVOID)PlaybackLog.pHeader, PlaybackLog.hMapHandle) ;
|
|
CloseHandle (PlaybackLog.hFile) ;
|
|
return (ERR_CORRUPT_LOG) ;
|
|
}
|
|
|
|
// PlaybackLog.StartIndexPos = PlaybackLog.BeginIndexPos ;
|
|
|
|
// getthe first data index
|
|
if (!LogPositionN (1, &(PlaybackLog.StartIndexPos)))
|
|
{
|
|
PlaybackLog.StartIndexPos = PlaybackLog.BeginIndexPos ;
|
|
}
|
|
|
|
PlaybackLog.StopIndexPos = PlaybackLog.EndIndexPos ;
|
|
PlaybackLog.StopIndexPos.iPosition =
|
|
min (PlaybackLog.StopIndexPos.iPosition,
|
|
PlaybackLog.iTotalTics - 1 ) ;
|
|
|
|
|
|
PlaybackLog.iSelectedTics = PlaybackLog.iTotalTics ;
|
|
|
|
PlaybackLog.iStatus = iPMStatusPlaying ;
|
|
return (0) ;
|
|
} // OpenPlayback
|
|
|
|
|
|
void CloseInputLog (HWND hWndParent)
|
|
{ // CloseInputLog
|
|
PBOOKMARK pBookmark, pNextBookmark ;
|
|
BOOL retCode, retCode1 ;
|
|
PLOGCOUNTERNAME pLogCounterName, pNextCounterName ;
|
|
|
|
UNREFERENCED_PARAMETER (hWndParent) ;
|
|
|
|
// free the bookmark list
|
|
for (pBookmark = PlaybackLog.pBookmarkFirst ;
|
|
pBookmark ;
|
|
pBookmark = pNextBookmark )
|
|
{
|
|
// save next bookmark and free current bookmark
|
|
pNextBookmark = pBookmark->pBookmarkNext ;
|
|
MemoryFree (pBookmark) ;
|
|
}
|
|
PlaybackLog.pBookmarkFirst = NULL ;
|
|
|
|
// free all counter names stuff
|
|
if (PlaybackLog.pBaseCounterNames)
|
|
{
|
|
MemoryFree (PlaybackLog.pBaseCounterNames) ;
|
|
}
|
|
PlaybackLog.pBaseCounterNames = NULL ;
|
|
PlaybackLog.lBaseCounterNameSize = 0 ;
|
|
PlaybackLog.lBaseCounterNameOffset = 0 ;
|
|
|
|
for (pLogCounterName = PlaybackLog.pLogCounterNameFirst ;
|
|
pLogCounterName ;
|
|
pLogCounterName = pNextCounterName)
|
|
{
|
|
pNextCounterName = pLogCounterName->pCounterNameNext ;
|
|
MemoryFree (pLogCounterName->pRemainNames) ;
|
|
MemoryFree (pLogCounterName) ;
|
|
}
|
|
|
|
PlaybackLog.pLogCounterNameFirst = NULL ;
|
|
|
|
retCode1 = FileUnMap((LPVOID)PlaybackLog.pHeader, PlaybackLog.hMapHandle) ;
|
|
retCode = CloseHandle (PlaybackLog.hFile) ;
|
|
PlaybackLog.iStatus = iPMStatusClosed ;
|
|
|
|
ResetGraphView (hWndGraph) ;
|
|
ResetAlertView (hWndAlert) ;
|
|
ResetLogView (hWndLog) ;
|
|
ResetReportView (hWndReport) ;
|
|
}
|
|
|
|
|
|
|
|
BOOL LogPositionN (int iIndex, PLOGPOSITION pLP)
|
|
{ // LogPositionN
|
|
LOGPOSITION LP ;
|
|
int i ;
|
|
|
|
LP = PlaybackLog.BeginIndexPos ;
|
|
for (i = 0 ;
|
|
i < iIndex ;
|
|
i++)
|
|
{
|
|
if (!NextIndexPosition (&LP, FALSE))
|
|
return (FALSE) ;
|
|
}
|
|
|
|
*pLP = LP ;
|
|
return (TRUE) ;
|
|
} // LogPositionN
|
|
|
|
|
|
PLOGINDEX PlaybackIndexN (int iIndex)
|
|
{
|
|
LOGPOSITION LP ;
|
|
int i ;
|
|
|
|
LP = PlaybackLog.BeginIndexPos ;
|
|
for (i = 0 ;
|
|
i < iIndex ;
|
|
i++)
|
|
{
|
|
if (!NextIndexPosition (&LP, FALSE))
|
|
return (NULL) ;
|
|
}
|
|
|
|
return (IndexFromPosition (&LP)) ;
|
|
}
|
|
|
|
|
|
BOOL PlaybackLines (PPERFSYSTEM pSystemFirst,
|
|
PLINE pLineFirst,
|
|
int iLogTic)
|
|
{ // PlaybackLines
|
|
|
|
PLOGINDEX pLogIndex ;
|
|
PPERFDATA pPerfData ;
|
|
PPERFSYSTEM pSystem ;
|
|
BOOL bAnyFound ;
|
|
|
|
pLogIndex = PlaybackIndexN (iLogTic) ;
|
|
if (!pLogIndex)
|
|
return (FALSE) ;
|
|
|
|
bAnyFound = FALSE ;
|
|
for (pSystem = pSystemFirst ;
|
|
pSystem ;
|
|
pSystem = pSystem->pSystemNext)
|
|
{ // for
|
|
pPerfData = DataFromIndex (pLogIndex, pSystem->sysName) ;
|
|
if (pPerfData)
|
|
{
|
|
UpdateLinesForSystem (pSystem->sysName,
|
|
pPerfData,
|
|
pLineFirst,
|
|
NULL) ;
|
|
bAnyFound = TRUE ;
|
|
}
|
|
else
|
|
{
|
|
FailedLinesForSystem (pSystem->sysName,
|
|
pPerfData,
|
|
pLineFirst) ;
|
|
}
|
|
}
|
|
return (bAnyFound) ;
|
|
} // PlaybackLines
|
|
|
|
|
|
|
|
|
|
PPERFDATA LogDataFromPosition (PPERFSYSTEM pSystem,
|
|
PLOGPOSITION pLogPosition)
|
|
{ // LogDataFromPosition
|
|
PLOGINDEX pLogIndex ;
|
|
|
|
|
|
if (!pLogPosition)
|
|
return (NULL) ;
|
|
|
|
pLogIndex = IndexFromPosition (pLogPosition) ;
|
|
if (!pLogIndex)
|
|
return (NULL) ;
|
|
|
|
return (DataFromIndex (pLogIndex, pSystem->sysName)) ;
|
|
} // LogDataFromPosition
|
|
|
|
|
|
|
|
BOOL LogPositionSystemTime (PLOGPOSITION pLP, SYSTEMTIME *pSystemTime)
|
|
/*
|
|
Effect: Given a logposition, get the index entry for that position
|
|
and return the system time stored therein.
|
|
*/
|
|
{ // LogPositionSystemTime
|
|
PLOGINDEX pLogIndex ;
|
|
|
|
pLogIndex = IndexFromPosition (pLP) ;
|
|
if (!pLogIndex)
|
|
return (FALSE) ;
|
|
|
|
*pSystemTime = pLogIndex->SystemTime ;
|
|
return TRUE;
|
|
} // LogPositionSystemTime
|
|
|
|
|
|
int LogPositionIntervalSeconds (PLOGPOSITION pLPStart,
|
|
PLOGPOSITION pLPStop)
|
|
/*
|
|
Effect: Return the time difference (in seconds) between the
|
|
system times of the two specified log positions.
|
|
*/
|
|
{ // LogPositionIntervalSeconds
|
|
SYSTEMTIME SystemTimeStart ;
|
|
SYSTEMTIME SystemTimeStop ;
|
|
|
|
|
|
if (LogPositionSystemTime (pLPStart, &SystemTimeStart) &&
|
|
LogPositionSystemTime (pLPStop, &SystemTimeStop))
|
|
return (SystemTimeDifference (&SystemTimeStart,
|
|
&SystemTimeStop, TRUE)) ;
|
|
else
|
|
return (0) ;
|
|
} // LogPositionIntervalSeconds
|
|
|
|
|
|
|
|
int PlaybackSelectedSeconds (void)
|
|
{ // PlaybackSelectedSeconds
|
|
return (LogPositionIntervalSeconds (&PlaybackLog.StartIndexPos,
|
|
&PlaybackLog.StopIndexPos)) ;
|
|
} // PlaybackSelectedSeconds
|
|
|
|
void BuildLogComputerList (HWND hDlg, int DlgID)
|
|
{
|
|
PPERFDATA pPerfData;
|
|
int iNumSystem ;
|
|
HWND hListBox = GetDlgItem (hDlg, DlgID) ;
|
|
PLOGINDEX pLogIndex ;
|
|
TCHAR szLoggedComputerName[MAX_PATH + 3] ;
|
|
int Index ;
|
|
|
|
pLogIndex = IndexFromPosition (&(PlaybackLog.StartIndexPos)) ;
|
|
pPerfData = PlaybackSeek (pLogIndex->lDataOffset) ;
|
|
|
|
for (iNumSystem = 0;
|
|
iNumSystem < pLogIndex->iSystemsLogged;
|
|
iNumSystem++)
|
|
{
|
|
if ( pPerfData &&
|
|
pPerfData->Signature[0] == (WCHAR)'P' &&
|
|
pPerfData->Signature[1] == (WCHAR)'E' &&
|
|
pPerfData->Signature[2] == (WCHAR)'R' &&
|
|
pPerfData->Signature[3] == (WCHAR)'F' )
|
|
{
|
|
GetPerfComputerName(pPerfData, szLoggedComputerName) ;
|
|
Index = LBFind (hListBox, szLoggedComputerName) ;
|
|
if (Index != LB_ERR)
|
|
{
|
|
// computer name already exist, we must have reach the next
|
|
// block of perfdata
|
|
break ;
|
|
}
|
|
LBAdd (hListBox, szLoggedComputerName) ;
|
|
pPerfData = (PPERFDATA)((PBYTE) pPerfData +
|
|
pPerfData->TotalByteLength) ;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
} // BuildLogComputerList
|
|
|
|
void PlaybackAddCounterName (PLOGINDEX pIndex)
|
|
{
|
|
PLOGCOUNTERNAME pLogCounterName = NULL,
|
|
pListCounterName = NULL;
|
|
PLOGFILECOUNTERNAME pDiskCounterName ;
|
|
PVOID pCounterData ;
|
|
BOOL bExist = FALSE ;
|
|
|
|
pDiskCounterName = PlaybackSeek (pIndex->lDataOffset) ;
|
|
|
|
// check we have a record for this system
|
|
for (pListCounterName = PlaybackLog.pLogCounterNameFirst ;
|
|
pListCounterName ;
|
|
pListCounterName = pListCounterName->pCounterNameNext)
|
|
{
|
|
if (strsamei(pDiskCounterName->szComputer,
|
|
pListCounterName->CounterName.szComputer))
|
|
{
|
|
// found!
|
|
pLogCounterName = pListCounterName ;
|
|
bExist = TRUE ;
|
|
break ;
|
|
}
|
|
}
|
|
|
|
if (!bExist)
|
|
{
|
|
// new counter name record
|
|
if (!(pLogCounterName = MemoryAllocate (sizeof(LOGCOUNTERNAME))))
|
|
{
|
|
return ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// free old memory in previous counter name record.
|
|
if (pLogCounterName->pRemainNames)
|
|
{
|
|
MemoryFree (pLogCounterName->pRemainNames) ;
|
|
}
|
|
pLogCounterName->pRemainNames = NULL ;
|
|
}
|
|
|
|
pLogCounterName->CounterName = *pDiskCounterName ;
|
|
|
|
if (pDiskCounterName->lBaseCounterNameOffset == 0)
|
|
{
|
|
// this is the base counter names,
|
|
// get the master copy of the counter names
|
|
|
|
if (!(pCounterData =
|
|
MemoryAllocate (pDiskCounterName->lUnmatchCounterNames)))
|
|
{
|
|
MemoryFree (pLogCounterName) ;
|
|
return ;
|
|
}
|
|
|
|
// free the old one if it exists.
|
|
if (PlaybackLog.pBaseCounterNames)
|
|
{
|
|
MemoryFree (PlaybackLog.pBaseCounterNames) ;
|
|
}
|
|
|
|
PlaybackLog.pBaseCounterNames = pCounterData ;
|
|
|
|
pCounterData =
|
|
PlaybackSeek (pDiskCounterName->lCurrentCounterNameOffset) ;
|
|
|
|
memcpy (PlaybackLog.pBaseCounterNames,
|
|
pCounterData,
|
|
pDiskCounterName->lUnmatchCounterNames) ;
|
|
|
|
PlaybackLog.lBaseCounterNameSize =
|
|
pDiskCounterName->lUnmatchCounterNames ;
|
|
|
|
PlaybackLog.lBaseCounterNameOffset =
|
|
pDiskCounterName->lBaseCounterNameOffset ;
|
|
}
|
|
else if (pDiskCounterName->lUnmatchCounterNames)
|
|
{
|
|
// this is not a based system and it has extra counter names
|
|
// allocate a buffer to hold them
|
|
pLogCounterName->pRemainNames =
|
|
MemoryAllocate (pDiskCounterName->lUnmatchCounterNames) ;
|
|
|
|
if (pLogCounterName->pRemainNames)
|
|
{
|
|
pCounterData =
|
|
PlaybackSeek (pDiskCounterName->lCurrentCounterNameOffset) ;
|
|
|
|
memcpy(pLogCounterName->pRemainNames,
|
|
pCounterData,
|
|
pDiskCounterName->lUnmatchCounterNames) ;
|
|
}
|
|
}
|
|
|
|
if (!bExist)
|
|
{
|
|
// now add the new counter name record to the linked list
|
|
if (!PlaybackLog.pLogCounterNameFirst)
|
|
{
|
|
PlaybackLog.pLogCounterNameFirst = pLogCounterName ;
|
|
}
|
|
else
|
|
{
|
|
for (pListCounterName = PlaybackLog.pLogCounterNameFirst ;
|
|
pListCounterName->pCounterNameNext ;
|
|
pListCounterName = pListCounterName->pCounterNameNext)
|
|
{
|
|
// do nothing until we get to the end of the list
|
|
;
|
|
}
|
|
pListCounterName->pCounterNameNext = pLogCounterName ;
|
|
}
|
|
}
|
|
|
|
} // PlaybackAddCounterName
|
|
|
|
|
|
LPWSTR *LogBuildNameTable (PPERFSYSTEM pSysInfo)
|
|
{
|
|
|
|
DWORD dwArraySize ;
|
|
PLOGCOUNTERNAME pCounterName ;
|
|
LPWSTR *lpCounterId = NULL ;
|
|
LPWSTR lpCounterNames ;
|
|
NTSTATUS Status ;
|
|
|
|
for (pCounterName = PlaybackLog.pLogCounterNameFirst ;
|
|
pCounterName ;
|
|
pCounterName = pCounterName->pCounterNameNext)
|
|
{
|
|
if (strsamei (pSysInfo->sysName, pCounterName->CounterName.szComputer))
|
|
{
|
|
// found the right system
|
|
break ;
|
|
}
|
|
}
|
|
if (!pCounterName)
|
|
{
|
|
goto ERROR_EXIT ;
|
|
}
|
|
|
|
dwArraySize = (pCounterName->CounterName.dwLastCounterId + 1)
|
|
* sizeof (LPWSTR) ;
|
|
|
|
lpCounterId = MemoryAllocate (dwArraySize +
|
|
pCounterName->CounterName.lMatchLength +
|
|
pCounterName->CounterName.lUnmatchCounterNames ) ;
|
|
|
|
if (!lpCounterId)
|
|
{
|
|
goto ERROR_EXIT ;
|
|
}
|
|
|
|
// initialize pointers into buffer
|
|
|
|
lpCounterNames = (LPWSTR)((LPBYTE)lpCounterId + dwArraySize);
|
|
if (pCounterName->CounterName.lBaseCounterNameOffset == 0)
|
|
{
|
|
// this is the base system
|
|
memcpy(lpCounterNames,
|
|
PlaybackLog.pBaseCounterNames,
|
|
PlaybackLog.lBaseCounterNameSize) ;
|
|
}
|
|
else
|
|
{
|
|
// copy the matched portion from the base system
|
|
memcpy(lpCounterNames,
|
|
PlaybackLog.pBaseCounterNames,
|
|
pCounterName->CounterName.lMatchLength) ;
|
|
|
|
// copy the unmatched portion
|
|
if (pCounterName->CounterName.lUnmatchCounterNames)
|
|
{
|
|
memcpy(((PBYTE)lpCounterNames +
|
|
pCounterName->CounterName.lMatchLength),
|
|
pCounterName->pRemainNames,
|
|
pCounterName->CounterName.lUnmatchCounterNames) ;
|
|
}
|
|
}
|
|
|
|
Status = AddNamesToArray (lpCounterNames,
|
|
pCounterName->CounterName.dwLastCounterId,
|
|
lpCounterId) ;
|
|
|
|
if (Status != ERROR_SUCCESS)
|
|
{
|
|
goto ERROR_EXIT ;
|
|
}
|
|
|
|
pSysInfo->CounterInfo.dwLastId =
|
|
pCounterName->CounterName.dwLastCounterId ;
|
|
pSysInfo->CounterInfo.dwLangId =
|
|
pCounterName->CounterName.dwLangId ;
|
|
pSysInfo->CounterInfo.dwHelpSize = 0 ;
|
|
pSysInfo->CounterInfo.dwCounterSize =
|
|
pCounterName->CounterName.lMatchLength +
|
|
pCounterName->CounterName.lUnmatchCounterNames ;
|
|
|
|
return (lpCounterId) ;
|
|
|
|
ERROR_EXIT:
|
|
if (lpCounterId)
|
|
{
|
|
MemoryFree (lpCounterId) ;
|
|
}
|
|
return (NULL) ;
|
|
} // LogBuildNameTable
|
|
|
|
|
|
|
|
|