mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
777 lines
22 KiB
777 lines
22 KiB
//==========================================================================//
|
|
// 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
|
|
)
|
|
{
|
|
return (PointerSeek (PlaybackLog.pHeader, lFileOffset)) ;
|
|
}
|
|
|
|
|
|
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.
|
|
*/
|
|
{
|
|
LOGPOSITION LP ;
|
|
PLOGINDEX pIndex ;
|
|
PBOOKMARK pBookmarkDisk, pBookmark ;
|
|
// LONG lFilePosition ;
|
|
|
|
pIndex = IndexFromPosition (pLogPosition) ;
|
|
|
|
LP = *pLogPosition ;
|
|
pBookmark = NULL ;
|
|
|
|
while (TRUE) {
|
|
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)) ;
|
|
if (pBookmark) {
|
|
*pBookmark = *pBookmarkDisk;
|
|
pBookmark->pBookmarkNext = NULL ;
|
|
}
|
|
else return (FALSE);
|
|
}
|
|
|
|
if (pIndex && IsDataIndex (pIndex)) {
|
|
LP.iPosition++ ;
|
|
*pLogPosition = LP ;
|
|
if (pBookmark) {
|
|
pBookmark->iTic = PlaybackLog.iTotalTics ;
|
|
BookmarkAppend (&PlaybackLog.pBookmarkFirst, pBookmark) ;
|
|
}
|
|
return (TRUE) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
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.
|
|
*/
|
|
{
|
|
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) ;
|
|
}
|
|
|
|
|
|
//==========================================================================//
|
|
// Exported Functions //
|
|
//==========================================================================//
|
|
void
|
|
PlaybackInitializeInstance (void)
|
|
{
|
|
PlaybackLog.iStatus = iPMStatusClosed ;
|
|
PlaybackLog.hFile = NULL ;
|
|
|
|
PlaybackLog.szFilePath = MemoryAllocate (FilePathLen * sizeof (TCHAR)) ;
|
|
if (PlaybackLog.szFilePath) {
|
|
lstrcpy (PlaybackLog.szFilePath, szDefaultLogFileName) ;
|
|
}
|
|
PlaybackLog.szFileTitle = MemoryAllocate (FilePathLen * sizeof (TCHAR)) ;
|
|
if (PlaybackLog.szFileTitle) {
|
|
lstrcpy (PlaybackLog.szFileTitle, szDefaultLogFileName) ;
|
|
}
|
|
}
|
|
|
|
|
|
INT
|
|
OpenPlayback (
|
|
LPTSTR lpszFilePath,
|
|
LPTSTR lpszFileTitle
|
|
)
|
|
{
|
|
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) ;
|
|
}
|
|
|
|
|
|
void
|
|
CloseInputLog (
|
|
HWND hWndParent
|
|
)
|
|
{
|
|
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
|
|
)
|
|
{
|
|
LOGPOSITION LP ;
|
|
int i ;
|
|
|
|
LP = PlaybackLog.BeginIndexPos ;
|
|
for (i = 0 ;
|
|
i < iIndex ;
|
|
i++) {
|
|
if (!NextIndexPosition (&LP, FALSE))
|
|
return (FALSE) ;
|
|
}
|
|
|
|
*pLP = LP ;
|
|
return (TRUE) ;
|
|
}
|
|
|
|
|
|
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
|
|
)
|
|
{
|
|
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) ;
|
|
}
|
|
|
|
|
|
PPERFDATA
|
|
LogDataFromPosition (
|
|
PPERFSYSTEM pSystem,
|
|
PLOGPOSITION pLogPosition
|
|
)
|
|
{
|
|
PLOGINDEX pLogIndex ;
|
|
|
|
|
|
if (!pLogPosition)
|
|
return (NULL) ;
|
|
|
|
pLogIndex = IndexFromPosition (pLogPosition) ;
|
|
if (!pLogIndex)
|
|
return (NULL) ;
|
|
|
|
return (DataFromIndex (pLogIndex, pSystem->sysName)) ;
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
LogPositionSystemTime (
|
|
PLOGPOSITION pLP,
|
|
SYSTEMTIME *pSystemTime
|
|
)
|
|
/*
|
|
Effect: Given a logposition, get the index entry for that position
|
|
and return the system time stored therein.
|
|
*/
|
|
{
|
|
PLOGINDEX pLogIndex ;
|
|
|
|
pLogIndex = IndexFromPosition (pLP) ;
|
|
if (!pLogIndex)
|
|
return (FALSE) ;
|
|
|
|
*pSystemTime = pLogIndex->SystemTime ;
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
int
|
|
LogPositionIntervalSeconds (
|
|
PLOGPOSITION pLPStart,
|
|
PLOGPOSITION pLPStop
|
|
)
|
|
/*
|
|
Effect: Return the time difference (in seconds) between the
|
|
system times of the two specified log positions.
|
|
*/
|
|
{
|
|
SYSTEMTIME SystemTimeStart ;
|
|
SYSTEMTIME SystemTimeStop ;
|
|
|
|
|
|
if (LogPositionSystemTime (pLPStart, &SystemTimeStart) &&
|
|
LogPositionSystemTime (pLPStop, &SystemTimeStop))
|
|
return (SystemTimeDifference (&SystemTimeStart,
|
|
&SystemTimeStop, TRUE)) ;
|
|
else
|
|
return (0) ;
|
|
}
|
|
|
|
|
|
|
|
int
|
|
PlaybackSelectedSeconds (void)
|
|
{
|
|
return (LogPositionIntervalSeconds (&PlaybackLog.StartIndexPos,
|
|
&PlaybackLog.StopIndexPos)) ;
|
|
}
|
|
|
|
void
|
|
BuildLogComputerList (
|
|
HWND hDlg,
|
|
int DlgID
|
|
)
|
|
{
|
|
PPERFDATA pPerfData;
|
|
int iNumSystem ;
|
|
HWND hListBox = GetDlgItem (hDlg, DlgID) ;
|
|
PLOGINDEX pLogIndex ;
|
|
TCHAR szLoggedComputerName[MAX_PATH + 3] ;
|
|
|
|
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) ;
|
|
if (LBFind (hListBox, szLoggedComputerName) != 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;
|
|
}
|
|
}
|
|
}
|
|
|
|
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) ;
|
|
}
|