1104 lines
42 KiB
C
1104 lines
42 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1998 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
ReLog.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
Program to test relogging to a log file
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Bob Watson (bobw) 2-apr-97
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
#include <windows.h>
|
|||
|
#include <tchar.h>
|
|||
|
#include <stdio.h>
|
|||
|
#include <stdlib.h>
|
|||
|
#include <string.h>
|
|||
|
#include <pdh.h>
|
|||
|
#include <pdhmsg.h>
|
|||
|
#include "resource.h"
|
|||
|
#include "varg.c"
|
|||
|
#include "relog.h"
|
|||
|
/*
|
|||
|
LPCTSTR cszInputSwitch = (LPCTSTR)TEXT("/input:");
|
|||
|
LPCTSTR cszOutputSwitch = (LPCTSTR)TEXT("/output:");
|
|||
|
LPCTSTR cszSettingsSwitch = (LPCTSTR)TEXT("/settings:");
|
|||
|
LPCTSTR cszLogtypeSwitch = (LPCTSTR)TEXT("/logtype:");
|
|||
|
LPCTSTR cszFilterSwitch = (LPCTSTR)TEXT("/filter:");
|
|||
|
LPCTSTR cszStartTime = (LPCTSTR)TEXT("/starttime:");
|
|||
|
LPCTSTR cszEndTime = (LPCTSTR)TEXT("/endtime:");
|
|||
|
LPCTSTR cszListSwitch = (LPCTSTR)TEXT("/list");
|
|||
|
LPCTSTR cszAppendSwitch = (LPCTSTR)TEXT("/append");
|
|||
|
*/
|
|||
|
VARG_RECORD Commands[] = {
|
|||
|
|
|||
|
VARG_HELP( VARG_FLAG_OPTIONAL )
|
|||
|
VARG_BOOL( IDS_PARAM_APPEND, VARG_FLAG_OPTIONAL, FALSE )
|
|||
|
VARG_STR ( IDS_PARAM_COUNTERFILE, VARG_FLAG_OPTIONAL, _T("") )
|
|||
|
VARG_STR ( IDS_PARAM_FORMAT,VARG_FLAG_OPTIONAL,_T("BLG") )
|
|||
|
VARG_MSZ ( IDS_PARAM_INPUT, VARG_FLAG_REQUIRED|VARG_FLAG_NOFLAG, _T("") )
|
|||
|
VARG_INT ( IDS_PARAM_INTERVAL, VARG_FLAG_OPTIONAL, 0 )
|
|||
|
VARG_TIME( IDS_PARAM_BEGIN, VARG_FLAG_OPTIONAL|VARG_FLAG_ARG_TIME )
|
|||
|
VARG_TIME( IDS_PARAM_END, VARG_FLAG_OPTIONAL|VARG_FLAG_ARG_TIME )
|
|||
|
VARG_STR ( IDS_PARAM_OUTPUT, VARG_FLAG_OPTIONAL, _T("") )
|
|||
|
VARG_BOOL( IDS_PARAM_QUERY, VARG_FLAG_OPTIONAL, FALSE )
|
|||
|
|
|||
|
VARG_TERMINATOR
|
|||
|
};
|
|||
|
|
|||
|
enum _Commands {
|
|||
|
eHelp,
|
|||
|
eAppend,
|
|||
|
eCounters,
|
|||
|
eFormat,
|
|||
|
eInput,
|
|||
|
eInterval,
|
|||
|
eBegin,
|
|||
|
eEnd,
|
|||
|
eOutput,
|
|||
|
eQuery
|
|||
|
};
|
|||
|
|
|||
|
LPCTSTR cszBinType = (LPCTSTR)TEXT("bin");
|
|||
|
LPCTSTR cszBlgType = (LPCTSTR)TEXT("blg");
|
|||
|
LPCTSTR cszCsvType = (LPCTSTR)TEXT("csv");
|
|||
|
LPCTSTR cszTsvType = (LPCTSTR)TEXT("tsv");
|
|||
|
LPCSTR cszBinLogFileHeader = "\"(PDH-BIN 4.0)\"\n";
|
|||
|
LPCSTR cszTextRecordTerminator = "\n";
|
|||
|
|
|||
|
//LPCTSTR cszRelogVersionStr = (LPCWSTR)TEXT(RELOG_VERSION_ID);
|
|||
|
|
|||
|
#define TextRecordTerminatorSize 1 // size of the string above
|
|||
|
FILE *fSettingsFile = NULL;
|
|||
|
|
|||
|
#define DBG_SHOW_STATUS_PRINTS 1
|
|||
|
#define DBG_NO_STATUS_PRINTS 0
|
|||
|
|
|||
|
DWORD dwDbgPrintLevel = DBG_NO_STATUS_PRINTS;
|
|||
|
|
|||
|
#define ALLOW_REOPEN_OF_SETTINGS_FILE FALSE
|
|||
|
|
|||
|
// assume string format of YYYY-MM-DD-hh:mm:ss
|
|||
|
// 0123456789012345678
|
|||
|
// value is index of the first char of that field
|
|||
|
#define DATE_STRING_LENGTH 19
|
|||
|
#define DATE_SECONDS_OFFSET 17
|
|||
|
#define DATE_MINUTES_OFFSET 14
|
|||
|
#define DATE_HOURS_OFFSET 11
|
|||
|
#define DATE_DAYS_OFFSET 8
|
|||
|
#define DATE_MONTH_OFFSET 5
|
|||
|
|
|||
|
#define NORMAL_MODE 1
|
|||
|
#define LIST_MODE 2
|
|||
|
#define SUMMARY_MODE 3
|
|||
|
#define APPEND_MODE 4
|
|||
|
#define HEADER_MODE 5
|
|||
|
|
|||
|
// structures lifted from pdh\log_bin.h
|
|||
|
|
|||
|
typedef struct _PDHI_BINARY_LOG_RECORD_HEADER {
|
|||
|
DWORD dwType;
|
|||
|
DWORD dwLength;
|
|||
|
} PDHI_BINARY_LOG_RECORD_HEADER, *PPDHI_BINARY_LOG_RECORD_HEADER;
|
|||
|
|
|||
|
//
|
|||
|
// the first data record after the log file type record is
|
|||
|
// an information record followed by the list of counters contained in this
|
|||
|
// log file. the record length is the size of the info header record and
|
|||
|
// all the counter info blocks in bytes.
|
|||
|
// note that this record can occur later in the log file if the query
|
|||
|
// is changed or the log file is appended.
|
|||
|
//
|
|||
|
typedef struct _PDHI_BINARY_LOG_INFO {
|
|||
|
LONGLONG FileLength; // file space allocated (optional)
|
|||
|
DWORD dwLogVersion; // version stamp
|
|||
|
DWORD dwFlags; // option flags
|
|||
|
LONGLONG StartTime;
|
|||
|
LONGLONG EndTime;
|
|||
|
LONGLONG CatalogOffset; // offset in file to wild card catalog
|
|||
|
LONGLONG CatalogChecksum; // checksum of catalog header
|
|||
|
LONGLONG CatalogDate; // date/time catalog was updated
|
|||
|
LONGLONG FirstRecordOffset; // pointer to first record [to read] in log
|
|||
|
LONGLONG LastRecordOffset; // pointer to last record [to read] in log
|
|||
|
LONGLONG NextRecordOffset; // pointer to where next one goes
|
|||
|
LONGLONG WrapOffset; // pointer to last byte used in file
|
|||
|
LONGLONG LastUpdateTime; // date/time last record was written
|
|||
|
LONGLONG FirstDataRecordOffset; // location of first data record in file
|
|||
|
// makes the info struct 256 bytes
|
|||
|
// and leaves room for future information
|
|||
|
DWORD dwReserved[38];
|
|||
|
} PDHI_BINARY_LOG_INFO, *PPDHI_BINARY_LOG_INFO;
|
|||
|
|
|||
|
typedef struct _PDHI_BINARY_LOG_HEADER_RECORD {
|
|||
|
PDHI_BINARY_LOG_RECORD_HEADER RecHeader;
|
|||
|
PDHI_BINARY_LOG_INFO Info;
|
|||
|
} PDHI_BINARY_LOG_HEADER_RECORD, *PPDHI_BINARY_LOG_HEADER_RECORD;
|
|||
|
|
|||
|
|
|||
|
// new but unexported pdh functions
|
|||
|
// these will need to be moved to the PDH.H file
|
|||
|
// in the final shipped version
|
|||
|
|
|||
|
#ifdef UNICODE
|
|||
|
PDH_FUNCTION
|
|||
|
PdhListLogFileHeaderW (
|
|||
|
IN LPCWSTR szFileName,
|
|||
|
IN LPWSTR mszHeaderList,
|
|||
|
IN LPDWORD pcchHeaderListSize
|
|||
|
);
|
|||
|
#define PdhListLogFileHeader PdhListLogFileHeaderW
|
|||
|
#else //ANSI
|
|||
|
|
|||
|
PDH_FUNCTION
|
|||
|
PdhListLogFileHeaderA (
|
|||
|
IN LPCSTR szFileName,
|
|||
|
IN LPSTR mszHeaderList,
|
|||
|
IN LPDWORD pcchHeaderListSize
|
|||
|
);
|
|||
|
#define PdhListLogFileHeader PdhListLogFileHeaderA
|
|||
|
#endif
|
|||
|
|
|||
|
DWORD
|
|||
|
GetOutputLogType( LPTSTR str )
|
|||
|
{
|
|||
|
DWORD dwLogType = PDH_LOG_TYPE_CSV;
|
|||
|
|
|||
|
if (_tcscmp(str, cszBinType) == 0) {
|
|||
|
dwLogType = PDH_LOG_TYPE_BINARY;
|
|||
|
} else if (_tcscmp(str, cszBlgType) == 0) {
|
|||
|
dwLogType = PDH_LOG_TYPE_BINARY;
|
|||
|
} else if (_tcscmp(str, cszCsvType) == 0) {
|
|||
|
dwLogType = PDH_LOG_TYPE_CSV;
|
|||
|
} else if (_tcscmp(str, cszTsvType) == 0) {
|
|||
|
dwLogType = PDH_LOG_TYPE_TSV;
|
|||
|
} else {
|
|||
|
// return unknown
|
|||
|
dwLogType = PDH_LOG_TYPE_UNDEFINED;
|
|||
|
}
|
|||
|
return dwLogType;
|
|||
|
}
|
|||
|
|
|||
|
DWORD
|
|||
|
DoListMode (
|
|||
|
LPCTSTR szInputFile,
|
|||
|
LPCTSTR szOutputFile
|
|||
|
)
|
|||
|
{
|
|||
|
// BUGBUG: note these should be dynamically allocated
|
|||
|
LPTSTR szReturnBuffer;
|
|||
|
TCHAR szMachineList[32768];
|
|||
|
TCHAR szWildPath[32768];
|
|||
|
// end bugbug
|
|||
|
PDH_STATUS pdhStatus;
|
|||
|
DWORD dwBufSize;
|
|||
|
DWORD dwMlSize;
|
|||
|
LPTSTR szThisString;
|
|||
|
LPTSTR szThisMachine;
|
|||
|
FILE *fOut = NULL;
|
|||
|
DWORD dwNumEntries;
|
|||
|
PDH_TIME_INFO pInfo[2];
|
|||
|
DWORD dwBufferSize = (sizeof(pInfo));
|
|||
|
SYSTEMTIME stLogTime;
|
|||
|
|
|||
|
dwMlSize = sizeof(szMachineList) / sizeof(szMachineList[0]);
|
|||
|
pdhStatus = PdhEnumMachines (
|
|||
|
szInputFile,
|
|||
|
szMachineList,
|
|||
|
&dwMlSize);
|
|||
|
|
|||
|
if ((pdhStatus == ERROR_SUCCESS) && (dwMlSize > 0)) {
|
|||
|
if (*szOutputFile == 0) {
|
|||
|
fOut = stdout;
|
|||
|
} else {
|
|||
|
fOut = _tfopen (szOutputFile, (LPCTSTR)TEXT("wt"));
|
|||
|
}
|
|||
|
pdhStatus = PdhGetDataSourceTimeRange (
|
|||
|
szInputFile,
|
|||
|
&dwNumEntries,
|
|||
|
&pInfo[0],
|
|||
|
&dwBufferSize);
|
|||
|
|
|||
|
if (pdhStatus == ERROR_SUCCESS) {
|
|||
|
_ftprintf(fOut, (LPCTSTR)TEXT("\nLogfile: \"%s\" contains %d Records."), szInputFile, pInfo[0].SampleCount);
|
|||
|
// write time range out to file
|
|||
|
FileTimeToSystemTime ((FILETIME *)(&pInfo[0].StartTime), &stLogTime);
|
|||
|
_ftprintf(fOut, (LPCTSTR)TEXT("\n Start Time: %4.4d-%2.2d-%2.2d-%2.2d:%2.2d:%2.2d"),
|
|||
|
stLogTime.wYear, stLogTime.wMonth, stLogTime.wDay,
|
|||
|
stLogTime.wHour, stLogTime.wMinute, stLogTime.wSecond);
|
|||
|
FileTimeToSystemTime ((FILETIME *)(&pInfo[0].EndTime), &stLogTime);
|
|||
|
_ftprintf(fOut, (LPCTSTR)TEXT("\n End Time: %4.4d-%2.2d-%2.2d-%2.2d:%2.2d:%2.2d"),
|
|||
|
stLogTime.wYear, stLogTime.wMonth, stLogTime.wDay,
|
|||
|
stLogTime.wHour, stLogTime.wMinute, stLogTime.wSecond);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
for (szThisMachine = szMachineList;
|
|||
|
*szThisMachine != 0;
|
|||
|
szThisMachine += _tcsclen(szThisMachine)) {
|
|||
|
|
|||
|
if (*szThisMachine != _T('\\')) {
|
|||
|
_tcscpy (szWildPath, (LPCTSTR)TEXT("\\\\"));
|
|||
|
_tcscat (szWildPath, szThisMachine);
|
|||
|
_tcscat (szWildPath, (LPCTSTR)TEXT("\\*(*)\\*"));
|
|||
|
} else {
|
|||
|
_tcscpy (szWildPath, szThisMachine);
|
|||
|
_tcscat (szWildPath, (LPCTSTR)TEXT("\\*(*)\\*"));
|
|||
|
}
|
|||
|
|
|||
|
dwBufSize = 512000;
|
|||
|
szReturnBuffer = HeapAlloc (GetProcessHeap(),
|
|||
|
HEAP_ZERO_MEMORY,
|
|||
|
dwBufSize * sizeof(TCHAR));
|
|||
|
|
|||
|
if (szReturnBuffer != NULL) {
|
|||
|
|
|||
|
pdhStatus = PdhExpandWildCardPath (
|
|||
|
szInputFile,
|
|||
|
szWildPath,
|
|||
|
szReturnBuffer,
|
|||
|
&dwBufSize,
|
|||
|
0);
|
|||
|
|
|||
|
if (dwBufSize != 0) {
|
|||
|
if (fOut == stdout) {
|
|||
|
_ftprintf (fOut, (LPCTSTR)TEXT("\nCounters contained in \"%s\":\n"), szInputFile);
|
|||
|
}
|
|||
|
|
|||
|
for (szThisString = szReturnBuffer;
|
|||
|
*szThisString != 0;
|
|||
|
szThisString += _tcsclen(szThisString) + 1) {
|
|||
|
_ftprintf (fOut, (LPCTSTR)TEXT("%s\n"), szThisString);
|
|||
|
}
|
|||
|
} else {
|
|||
|
_tprintf ((LPCTSTR)TEXT("\nError 0x%8.8x (%d) returned from enumeration of machine %s in %s"),
|
|||
|
pdhStatus, (DWORD)(pdhStatus & 0x0000FFFF),
|
|||
|
szThisMachine,
|
|||
|
szInputFile);
|
|||
|
}
|
|||
|
|
|||
|
HeapFree (GetProcessHeap(), 0, szReturnBuffer);
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
} else {
|
|||
|
// unable to list log file contents
|
|||
|
_tprintf ((LPCTSTR)TEXT("\nError 0x%8.8x (%d) returned from enumeration of %s"),
|
|||
|
pdhStatus, (DWORD)(pdhStatus & 0x0000FFFF),
|
|||
|
szInputFile);
|
|||
|
}
|
|||
|
|
|||
|
return ERROR_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
DWORD
|
|||
|
DoHeaderListMode (
|
|||
|
LPCTSTR szInputFile,
|
|||
|
LPCTSTR szOutputFile
|
|||
|
)
|
|||
|
{
|
|||
|
// end bugbug
|
|||
|
PDH_STATUS pdhStatus;
|
|||
|
LPTSTR szThisString;
|
|||
|
FILE *fOut = NULL;
|
|||
|
DWORD dwType = 0L;
|
|||
|
HLOG hLog = NULL;
|
|||
|
LPTSTR mszHeaderList;
|
|||
|
DWORD cchHeaderListSize = 0x80000; // 512K
|
|||
|
DWORD dwNumEntries;
|
|||
|
PDH_TIME_INFO pInfo[2];
|
|||
|
DWORD dwBufferSize = (sizeof(pInfo));
|
|||
|
SYSTEMTIME stLogTime;
|
|||
|
|
|||
|
mszHeaderList = (LPTSTR)HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, cchHeaderListSize * sizeof(TCHAR));
|
|||
|
if (mszHeaderList != NULL) {
|
|||
|
pdhStatus = PdhListLogFileHeader (
|
|||
|
szInputFile,
|
|||
|
mszHeaderList,
|
|||
|
&cchHeaderListSize);
|
|||
|
|
|||
|
if (pdhStatus == ERROR_SUCCESS) {
|
|||
|
if (*szOutputFile == 0) {
|
|||
|
fOut = stdout;
|
|||
|
} else {
|
|||
|
fOut = _tfopen (szOutputFile, (LPCTSTR)TEXT("wt"));
|
|||
|
}
|
|||
|
|
|||
|
pdhStatus = PdhGetDataSourceTimeRange (
|
|||
|
szInputFile,
|
|||
|
&dwNumEntries,
|
|||
|
&pInfo[0],
|
|||
|
&dwBufferSize);
|
|||
|
|
|||
|
if (pdhStatus == ERROR_SUCCESS) {
|
|||
|
_ftprintf(fOut, (LPCTSTR)TEXT("\nLogfile: \"%s\" contains %d Records."), szInputFile, pInfo[0].SampleCount);
|
|||
|
// write time range out to file
|
|||
|
FileTimeToSystemTime ((FILETIME *)(&pInfo[0].StartTime), &stLogTime);
|
|||
|
_ftprintf(fOut, (LPCTSTR)TEXT("\n Start Time: %4.4d-%2.2d-%2.2d-%2.2d:%2.2d:%2.2d"),
|
|||
|
stLogTime.wYear, stLogTime.wMonth, stLogTime.wDay,
|
|||
|
stLogTime.wHour, stLogTime.wMinute, stLogTime.wSecond);
|
|||
|
FileTimeToSystemTime ((FILETIME *)(&pInfo[0].EndTime), &stLogTime);
|
|||
|
_ftprintf(fOut, (LPCTSTR)TEXT("\n End Time: %4.4d-%2.2d-%2.2d-%2.2d:%2.2d:%2.2d"),
|
|||
|
stLogTime.wYear, stLogTime.wMonth, stLogTime.wDay,
|
|||
|
stLogTime.wHour, stLogTime.wMinute, stLogTime.wSecond);
|
|||
|
}
|
|||
|
|
|||
|
if (fOut == stdout) {
|
|||
|
_ftprintf (fOut, (LPCTSTR)TEXT("\nCounters contained in %s\n"), szInputFile);
|
|||
|
}
|
|||
|
|
|||
|
for (szThisString = mszHeaderList;
|
|||
|
*szThisString != 0;
|
|||
|
szThisString += _tcsclen(szThisString) + 1) {
|
|||
|
_ftprintf (fOut, (LPCTSTR)TEXT("%s\n"), szThisString);
|
|||
|
}
|
|||
|
} else {
|
|||
|
// unable to list log file contents
|
|||
|
_tprintf ((LPCTSTR)TEXT("\nError 0x%8.8x (%d) returned from enumeration of %s"),
|
|||
|
pdhStatus, (DWORD)(pdhStatus & 0x0000FFFF),
|
|||
|
szInputFile);
|
|||
|
}
|
|||
|
|
|||
|
HeapFree (GetProcessHeap(), HEAP_ZERO_MEMORY, mszHeaderList);
|
|||
|
}
|
|||
|
|
|||
|
return ERROR_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
HRESULT GetCountersFromFile( HQUERY hQuery )
|
|||
|
{
|
|||
|
TCHAR buffer[MAXSTR];
|
|||
|
HCOUNTER pCounter;
|
|||
|
HRESULT hr;
|
|||
|
LPTSTR strCounter = NULL;
|
|||
|
|
|||
|
FILE* f = _tfopen( Commands[eCounters].strValue, _T("r") );
|
|||
|
|
|||
|
if( !f ){
|
|||
|
return GetLastError();
|
|||
|
}
|
|||
|
|
|||
|
while( NULL != _fgetts( buffer, MAXSTR, f ) ){
|
|||
|
|
|||
|
if( buffer[0] == ';' || // comments
|
|||
|
buffer[0] == '#' ){
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
Chomp(buffer);
|
|||
|
|
|||
|
strCounter = _tcstok( buffer, _T("\"\n") );
|
|||
|
if( strCounter != NULL ){
|
|||
|
hr = PdhAddCounter(
|
|||
|
hQuery,
|
|||
|
buffer,
|
|||
|
0,
|
|||
|
&pCounter
|
|||
|
);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
fclose( f );
|
|||
|
|
|||
|
return ERROR_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
DWORD
|
|||
|
DoNormalMode (
|
|||
|
LPCTSTR szInputFile,
|
|||
|
LPCTSTR szOutputFile,
|
|||
|
LPCTSTR szSettingsFile,
|
|||
|
DWORD dwOutputLogType,
|
|||
|
PDH_TIME_INFO pdhTimeInfo,
|
|||
|
DWORD dwFilterCount
|
|||
|
)
|
|||
|
{
|
|||
|
DWORD dwNumOutputCounters = 0;
|
|||
|
DWORD dwRecCount = 0;
|
|||
|
DWORD dwFiltered;
|
|||
|
LONG Status = ERROR_SUCCESS;
|
|||
|
PDH_STATUS PdhStatus;
|
|||
|
PDH_RAW_COUNTER RawValue;
|
|||
|
|
|||
|
LPTSTR szCounterPath = NULL;
|
|||
|
|
|||
|
HQUERY hQuery = NULL;
|
|||
|
HLOG hOutLog = NULL;
|
|||
|
HLOG hInLog = NULL;
|
|||
|
HCOUNTER hCounter = NULL;
|
|||
|
HCOUNTER hLastGoodCounter = NULL;
|
|||
|
DWORD dwType;
|
|||
|
DWORD dwOpenMode;
|
|||
|
|
|||
|
LPTSTR szReturnBuffer;
|
|||
|
TCHAR szMachineList[32768];
|
|||
|
TCHAR szWildPath[32768];
|
|||
|
// end bugbug
|
|||
|
PDH_STATUS pdhStatus;
|
|||
|
DWORD dwBufSize;
|
|||
|
DWORD dwMlSize;
|
|||
|
LPTSTR szThisString;
|
|||
|
LPTSTR szThisMachine;
|
|||
|
FILE *fOut = NULL;
|
|||
|
|
|||
|
if (Status == ERROR_SUCCESS) {
|
|||
|
_tprintf ((LPCTSTR)TEXT("\nRelogging: \"%s\" to \"%s\""), szInputFile, szOutputFile);
|
|||
|
|
|||
|
PdhStatus = PdhOpenQuery (szInputFile, 0L, &hQuery);
|
|||
|
if (PdhStatus != ERROR_SUCCESS) {
|
|||
|
Status = PdhStatus;
|
|||
|
_tprintf ((LPCTSTR)TEXT("\nPdhOpenQuery returned: 0x%8.8x (%d)"), PdhStatus, PdhStatus);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (Status == ERROR_SUCCESS) {
|
|||
|
if (*szSettingsFile == 0) {
|
|||
|
if (dwOutputLogType == PDH_LOG_TYPE_BINARY) {
|
|||
|
// load all counters from input file into query
|
|||
|
LPTSTR mszHeaderList;
|
|||
|
DWORD cchHeaderListSize = 0x80000; // 512K
|
|||
|
|
|||
|
mszHeaderList = (LPTSTR)HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, cchHeaderListSize * sizeof(TCHAR));
|
|||
|
if (mszHeaderList != NULL) {
|
|||
|
PdhStatus = PdhListLogFileHeader (
|
|||
|
szInputFile,
|
|||
|
mszHeaderList,
|
|||
|
&cchHeaderListSize);
|
|||
|
|
|||
|
if (PdhStatus == ERROR_SUCCESS) {
|
|||
|
// we can recycle the hCounter value since we don't need it for anything after this.
|
|||
|
for (szCounterPath = mszHeaderList;
|
|||
|
*szCounterPath != 0;
|
|||
|
szCounterPath += _tcsclen(szCounterPath) + 1) {
|
|||
|
PdhStatus = PdhAddCounter (hQuery, szCounterPath, 0L, &hCounter);
|
|||
|
if (PdhStatus != ERROR_SUCCESS) {
|
|||
|
_tprintf ((LPCTSTR)TEXT("\nUnable to add \"%s\", error: 0x%8.8x (%d)"), szCounterPath, PdhStatus, PdhStatus);
|
|||
|
} else {
|
|||
|
hLastGoodCounter = hCounter;
|
|||
|
dwNumOutputCounters++;
|
|||
|
if (dwDbgPrintLevel == DBG_SHOW_STATUS_PRINTS) {
|
|||
|
_tprintf ((LPCTSTR)TEXT("\nRelogging \"%s\""), szCounterPath);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
HeapFree (GetProcessHeap(), 0, mszHeaderList);
|
|||
|
}
|
|||
|
} else {
|
|||
|
// enumerate each counter for all non-binary log types
|
|||
|
dwMlSize = sizeof(szMachineList) / sizeof(szMachineList[0]);
|
|||
|
pdhStatus = PdhEnumMachines (
|
|||
|
szInputFile,
|
|||
|
szMachineList,
|
|||
|
&dwMlSize);
|
|||
|
|
|||
|
if ((pdhStatus == ERROR_SUCCESS) && (dwMlSize > 0)) {
|
|||
|
|
|||
|
for (szThisMachine = szMachineList;
|
|||
|
*szThisMachine != 0;
|
|||
|
szThisMachine += _tcsclen(szThisMachine)) {
|
|||
|
|
|||
|
if (*szThisMachine != _T('\\')) {
|
|||
|
_tcscpy (szWildPath, (LPCTSTR)TEXT("\\\\"));
|
|||
|
_tcscat (szWildPath, szThisMachine);
|
|||
|
_tcscat (szWildPath, (LPCTSTR)TEXT("\\*(*)\\*"));
|
|||
|
} else {
|
|||
|
_tcscpy (szWildPath, szThisMachine);
|
|||
|
_tcscat (szWildPath, (LPCTSTR)TEXT("\\*(*)\\*"));
|
|||
|
}
|
|||
|
|
|||
|
dwBufSize = 512000;
|
|||
|
szReturnBuffer = HeapAlloc (GetProcessHeap(),
|
|||
|
HEAP_ZERO_MEMORY,
|
|||
|
dwBufSize * sizeof(TCHAR));
|
|||
|
|
|||
|
if (szReturnBuffer != NULL) {
|
|||
|
|
|||
|
pdhStatus = PdhExpandWildCardPath (
|
|||
|
szInputFile,
|
|||
|
szWildPath,
|
|||
|
szReturnBuffer,
|
|||
|
&dwBufSize,
|
|||
|
0);
|
|||
|
|
|||
|
if (dwBufSize != 0) {
|
|||
|
for (szThisString = szReturnBuffer;
|
|||
|
*szThisString != 0;
|
|||
|
szThisString += _tcsclen(szThisString) + 1) {
|
|||
|
PdhStatus = PdhAddCounter (hQuery, szThisString, 0L, &hCounter);
|
|||
|
if (PdhStatus != ERROR_SUCCESS) {
|
|||
|
_tprintf ((LPCTSTR)TEXT("\nUnable to add \"%s\", error: 0x%8.8x (%d)"), szThisString, PdhStatus, PdhStatus);
|
|||
|
} else {
|
|||
|
hLastGoodCounter = hCounter;
|
|||
|
dwNumOutputCounters++;
|
|||
|
if (dwDbgPrintLevel == DBG_SHOW_STATUS_PRINTS) {
|
|||
|
_tprintf ((LPCTSTR)TEXT("\nAdded \"%s\", error: 0x%8.8x (%d)"), szThisString, PdhStatus, PdhStatus);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
HeapFree (GetProcessHeap(), 0, szReturnBuffer);
|
|||
|
} else {
|
|||
|
// unable to allocate memory
|
|||
|
PdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
|
|||
|
}
|
|||
|
} // end for each machine in the log file
|
|||
|
} else {
|
|||
|
// unable to list machines
|
|||
|
// return PDH status
|
|||
|
}
|
|||
|
}
|
|||
|
} else {
|
|||
|
// we can recycle the hCounter value since we don't need it for anything after this.
|
|||
|
GetCountersFromFile( hQuery );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if ((Status == ERROR_SUCCESS) && (dwNumOutputCounters > 0)) {
|
|||
|
dwOpenMode = PDH_LOG_WRITE_ACCESS | PDH_LOG_CREATE_ALWAYS;
|
|||
|
|
|||
|
PdhStatus = PdhOpenLog (szOutputFile,
|
|||
|
dwOpenMode,
|
|||
|
&dwOutputLogType,
|
|||
|
hQuery,
|
|||
|
0L,
|
|||
|
NULL,
|
|||
|
&hOutLog);
|
|||
|
|
|||
|
if (PdhStatus != ERROR_SUCCESS) {
|
|||
|
Status = PdhStatus;
|
|||
|
_tprintf ((LPCTSTR)TEXT("\nUnable to open \"%s\" for output, error: 0x%8.8x (%d)"), szOutputFile, PdhStatus, PdhStatus);
|
|||
|
} else {
|
|||
|
// set query range
|
|||
|
PdhStatus = PdhSetQueryTimeRange (hQuery, &pdhTimeInfo);
|
|||
|
// copy log data to output log
|
|||
|
PdhStatus = PdhUpdateLog (hOutLog, NULL);
|
|||
|
while (PdhStatus == ERROR_SUCCESS) {
|
|||
|
dwRecCount++;
|
|||
|
dwFiltered = 1;
|
|||
|
while ((dwFiltered < dwFilterCount) && (PdhStatus == ERROR_SUCCESS)) {
|
|||
|
PdhStatus = PdhCollectQueryData(hQuery);
|
|||
|
if (PdhStatus == ERROR_SUCCESS) {
|
|||
|
PdhStatus = PdhGetRawCounterValue (
|
|||
|
hLastGoodCounter,
|
|||
|
&dwType,
|
|||
|
&RawValue);
|
|||
|
if (PdhStatus == ERROR_SUCCESS) {
|
|||
|
// check for bogus timestamps as an inidcation we ran off the end of the file
|
|||
|
if ((*(LONGLONG *)&RawValue.TimeStamp == 0) ||
|
|||
|
(*(LONGLONG *)&RawValue.TimeStamp >= pdhTimeInfo.EndTime)){
|
|||
|
PdhStatus = PDH_END_OF_LOG_FILE;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
dwFiltered++;
|
|||
|
}
|
|||
|
if (PdhStatus == ERROR_SUCCESS) {
|
|||
|
PdhStatus = PdhUpdateLog (hOutLog, NULL);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// PdhStatus should be either PDH_END_OF_LOG_FILE or PDH_NO_MORE_DATA when
|
|||
|
// the loop above exits, if that's the case then reset status to SUCCESS
|
|||
|
// otherwise display the error
|
|||
|
if ((PdhStatus == PDH_END_OF_LOG_FILE) || (PdhStatus == PDH_NO_MORE_DATA)) {
|
|||
|
PdhStatus = ERROR_SUCCESS;
|
|||
|
} else {
|
|||
|
printf ("\nPdhUpdateLog returned: 0x%8.8x (%d)", PdhStatus, PdhStatus);
|
|||
|
}
|
|||
|
|
|||
|
// update log catalog while we're at it
|
|||
|
//
|
|||
|
// BUGBUG: For now this isn't working very well so this step
|
|||
|
// will be skipped until it works better (5.1 maybe?)
|
|||
|
/*
|
|||
|
if (dwOutputLogType == PDH_LOG_TYPE_BINARY) {
|
|||
|
PdhStatus = PdhUpdateLogFileCatalog (hOutLog);
|
|||
|
if (PdhStatus != ERROR_SUCCESS) {
|
|||
|
Status = PdhStatus;
|
|||
|
_tprintf ((LPCTSTR)TEXT("\nPdhUpdateLogFileCatalog returned: 0x%8.8x (%d)"), PdhStatus, PdhStatus);
|
|||
|
}
|
|||
|
}
|
|||
|
*/
|
|||
|
|
|||
|
PdhStatus = PdhCloseLog (hOutLog, 0L);
|
|||
|
if (PdhStatus != ERROR_SUCCESS) {
|
|||
|
Status = PdhStatus;
|
|||
|
printf ("\nPdhCloseLog returned: 0x%8.8x (%d)", PdhStatus, PdhStatus);
|
|||
|
} else {
|
|||
|
hOutLog = NULL;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (hQuery != NULL) {
|
|||
|
PdhStatus = PdhCloseQuery (hQuery);
|
|||
|
if (PdhStatus != ERROR_SUCCESS) {
|
|||
|
Status = PdhStatus;
|
|||
|
printf ("\nPdhCloseLog returned: 0x%8.8x (%d)", PdhStatus, PdhStatus);
|
|||
|
} else {
|
|||
|
hQuery = NULL;
|
|||
|
hCounter = NULL;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (Status == ERROR_SUCCESS) {
|
|||
|
_tprintf ((LPCTSTR)TEXT("\n%d records from %s have been relogged to %s"), dwRecCount, szInputFile, szOutputFile);
|
|||
|
}
|
|||
|
|
|||
|
return Status;
|
|||
|
}
|
|||
|
|
|||
|
DWORD
|
|||
|
DoAppendFiles (
|
|||
|
IN LPCTSTR szAppendFile,
|
|||
|
IN LPCTSTR szBaseFile,
|
|||
|
IN DWORD dwFilterCount
|
|||
|
|
|||
|
)
|
|||
|
/*
|
|||
|
append data records from Append file to base file if they
|
|||
|
contain the same counter data
|
|||
|
(and hopefully append file starts after base file)
|
|||
|
*/
|
|||
|
{
|
|||
|
HANDLE hTempFile;
|
|||
|
TCHAR szTempFileName[MAX_PATH];
|
|||
|
TCHAR szTempDirPath[MAX_PATH];
|
|||
|
|
|||
|
DWORD dwReturn = ERROR_SUCCESS;
|
|||
|
PDH_STATUS pdhStatus;
|
|||
|
DWORD dwFiltered;
|
|||
|
|
|||
|
DWORD dwAppendLogType;
|
|||
|
DWORD dwBaseLogType;
|
|||
|
|
|||
|
HLOG hAppendLogFile;
|
|||
|
HLOG hBaseLogFile;
|
|||
|
|
|||
|
LPTSTR mszBaseFileHeader;
|
|||
|
DWORD cchBaseFileHeaderSize;
|
|||
|
LPTSTR mszAppendFileHeader;
|
|||
|
DWORD cchAppendFileHeaderSize;
|
|||
|
|
|||
|
PPDH_RAW_LOG_RECORD pRawRecord;
|
|||
|
DWORD dwRecordBuffSize;
|
|||
|
DWORD dwRecordSize;
|
|||
|
DWORD dwRecordIdx;
|
|||
|
|
|||
|
BOOL bStatus;
|
|||
|
DWORD dwBytesWritten;
|
|||
|
|
|||
|
PPDHI_BINARY_LOG_HEADER_RECORD pBinLogHead;
|
|||
|
|
|||
|
FILETIME ftValue;
|
|||
|
|
|||
|
DWORD dwLogRecType;
|
|||
|
BOOL bIsDataRecord;
|
|||
|
|
|||
|
// see if the file headers match
|
|||
|
// read headers of log files
|
|||
|
cchBaseFileHeaderSize = 0x80000;
|
|||
|
mszBaseFileHeader = (LPTSTR)HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, cchBaseFileHeaderSize * sizeof(TCHAR));
|
|||
|
if (mszBaseFileHeader != NULL) {
|
|||
|
pdhStatus = PdhListLogFileHeader (
|
|||
|
szBaseFile,
|
|||
|
mszBaseFileHeader,
|
|||
|
&cchBaseFileHeaderSize);
|
|||
|
|
|||
|
if (pdhStatus == ERROR_SUCCESS) {
|
|||
|
cchAppendFileHeaderSize = 0x80000;
|
|||
|
mszAppendFileHeader = (LPTSTR)HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, cchAppendFileHeaderSize * sizeof(TCHAR));
|
|||
|
if (mszAppendFileHeader != NULL) {
|
|||
|
pdhStatus = PdhListLogFileHeader (
|
|||
|
szAppendFile,
|
|||
|
mszAppendFileHeader,
|
|||
|
&cchAppendFileHeaderSize);
|
|||
|
if (pdhStatus == ERROR_SUCCESS) {
|
|||
|
// compare buffers
|
|||
|
if (cchAppendFileHeaderSize == cchBaseFileHeaderSize) {
|
|||
|
if (memcmp(mszAppendFileHeader, mszBaseFileHeader, cchBaseFileHeaderSize) == 0) {
|
|||
|
// same
|
|||
|
pdhStatus = ERROR_SUCCESS;
|
|||
|
} else {
|
|||
|
// different
|
|||
|
_tprintf ((LPCTSTR)TEXT("\nInput file counter list is different from that of the output file."));
|
|||
|
pdhStatus = ERROR_DATATYPE_MISMATCH;
|
|||
|
}
|
|||
|
} else {
|
|||
|
_tprintf ((LPCTSTR)TEXT("\nInput file counter list is different from that of the output file."));
|
|||
|
// different sizes
|
|||
|
pdhStatus = ERROR_DATATYPE_MISMATCH;
|
|||
|
}
|
|||
|
} else {
|
|||
|
// unable to read append file
|
|||
|
_tprintf ((LPCTSTR)TEXT("\nUnable to read the input file header."));
|
|||
|
}
|
|||
|
HeapFree (GetProcessHeap(), HEAP_ZERO_MEMORY, mszAppendFileHeader);
|
|||
|
} else {
|
|||
|
_tprintf ((LPCTSTR)TEXT("\nUnable to allocate an internal memory buffer."));
|
|||
|
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
|
|||
|
}
|
|||
|
} else {
|
|||
|
// unable to read base file header
|
|||
|
_tprintf ((LPCTSTR)TEXT("\nUnable to read the output file header."));
|
|||
|
}
|
|||
|
HeapFree (GetProcessHeap(), HEAP_ZERO_MEMORY, mszBaseFileHeader);
|
|||
|
} else {
|
|||
|
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
|
|||
|
}
|
|||
|
|
|||
|
if (pdhStatus == ERROR_SUCCESS) {
|
|||
|
// the files have matching headers so get ready to copy them
|
|||
|
|
|||
|
// create temporary output file name
|
|||
|
GetTempPath (MAX_PATH, szTempDirPath);
|
|||
|
GetTempFileName (szTempDirPath, (LPCTSTR)TEXT("PDH"), 0, szTempFileName);
|
|||
|
|
|||
|
hTempFile = CreateFile (
|
|||
|
szTempFileName,
|
|||
|
GENERIC_READ | GENERIC_WRITE,
|
|||
|
0,
|
|||
|
NULL,
|
|||
|
OPEN_EXISTING, // the file is created by GetTempFileName above (go figure)
|
|||
|
FILE_ATTRIBUTE_NORMAL,
|
|||
|
NULL);
|
|||
|
|
|||
|
if (hTempFile != INVALID_HANDLE_VALUE) {
|
|||
|
|
|||
|
// open log files
|
|||
|
pdhStatus = PdhOpenLog (
|
|||
|
szBaseFile,
|
|||
|
PDH_LOG_READ_ACCESS | PDH_LOG_OPEN_EXISTING,
|
|||
|
&dwBaseLogType,
|
|||
|
NULL,
|
|||
|
0,
|
|||
|
NULL,
|
|||
|
&hBaseLogFile);
|
|||
|
|
|||
|
if (pdhStatus == ERROR_SUCCESS) {
|
|||
|
pdhStatus = PdhOpenLog (
|
|||
|
szAppendFile,
|
|||
|
PDH_LOG_READ_ACCESS | PDH_LOG_OPEN_EXISTING,
|
|||
|
&dwAppendLogType,
|
|||
|
NULL,
|
|||
|
0,
|
|||
|
NULL,
|
|||
|
&hAppendLogFile);
|
|||
|
|
|||
|
if (pdhStatus == ERROR_SUCCESS) {
|
|||
|
dwRecordIdx = 1;
|
|||
|
ftValue.dwHighDateTime = 0xFFFFFFFF;
|
|||
|
ftValue.dwLowDateTime = dwRecordIdx;
|
|||
|
|
|||
|
dwRecordBuffSize = 0x80000;
|
|||
|
pRawRecord = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, dwRecordBuffSize);
|
|||
|
|
|||
|
if (pRawRecord != NULL) {
|
|||
|
dwFiltered = 1;
|
|||
|
// write headers from first file to temp file
|
|||
|
while (pdhStatus == ERROR_SUCCESS) {
|
|||
|
ftValue.dwHighDateTime = 0xFFFFFFFF;
|
|||
|
ftValue.dwLowDateTime = dwRecordIdx;
|
|||
|
dwRecordSize = dwRecordBuffSize;
|
|||
|
pdhStatus = PdhReadRawLogRecord (
|
|||
|
hBaseLogFile,
|
|||
|
ftValue,
|
|||
|
pRawRecord,
|
|||
|
&dwRecordSize);
|
|||
|
|
|||
|
if (pdhStatus == ERROR_SUCCESS) {
|
|||
|
bIsDataRecord = TRUE;
|
|||
|
if (dwRecordIdx == 1) {
|
|||
|
bIsDataRecord = FALSE;
|
|||
|
} else if ((dwRecordIdx == 2) && (pRawRecord->dwRecordType == PDH_LOG_TYPE_BINARY)) {
|
|||
|
pBinLogHead = (PPDHI_BINARY_LOG_HEADER_RECORD)&pRawRecord->RawBytes[0];
|
|||
|
// only linear files can be appended
|
|||
|
if (pBinLogHead->Info.WrapOffset == 0) {
|
|||
|
// now fix up the fields in the header so they'll work
|
|||
|
// with the new combined file
|
|||
|
pBinLogHead->Info.FileLength = 0; // file space allocated (optional)
|
|||
|
pBinLogHead->Info.CatalogOffset = 0; // the catalog is removed
|
|||
|
pBinLogHead->Info.CatalogChecksum = 0;
|
|||
|
pBinLogHead->Info.CatalogDate = 0; // date/time catalog was updated
|
|||
|
//pBinLogHead->Info.FirstRecordOffset = 0; // pointer to first record [to read] in log
|
|||
|
pBinLogHead->Info.LastRecordOffset = 0; // pointer to last record [to read] in log
|
|||
|
pBinLogHead->Info.NextRecordOffset = 0; // pointer to where next one goes
|
|||
|
pBinLogHead->Info.WrapOffset = 0; // pointer to last byte used in file
|
|||
|
pBinLogHead->Info.LastUpdateTime = 0; // date/time last record was written
|
|||
|
pBinLogHead->Info.FirstDataRecordOffset = 0; // location of first data record in file
|
|||
|
} else {
|
|||
|
// file is circular so bail
|
|||
|
pdhStatus = PDH_UNKNOWN_LOG_FORMAT;
|
|||
|
}
|
|||
|
bIsDataRecord = FALSE;
|
|||
|
}
|
|||
|
|
|||
|
if (pdhStatus == ERROR_SUCCESS) {
|
|||
|
// write the first 2 records of the base file
|
|||
|
// then only the data records after that
|
|||
|
if ((dwRecordIdx > 2) && (pRawRecord->dwRecordType == PDH_LOG_TYPE_BINARY)) {
|
|||
|
// it must be a data record or else skip it
|
|||
|
dwLogRecType = *((LPDWORD)&pRawRecord->RawBytes[0]);
|
|||
|
if ((dwLogRecType & 0x00FF0000) != 0x00030000) {
|
|||
|
// then this is not a data record
|
|||
|
// so skip it and get next record
|
|||
|
dwRecordIdx++;
|
|||
|
continue;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if ((!bIsDataRecord) || (dwFiltered == dwFilterCount)) {
|
|||
|
// write the record to the output file
|
|||
|
bStatus = WriteFile (
|
|||
|
hTempFile,
|
|||
|
&pRawRecord->RawBytes[0],
|
|||
|
pRawRecord->dwItems,
|
|||
|
&dwBytesWritten,
|
|||
|
NULL);
|
|||
|
if (!bStatus || (dwBytesWritten != pRawRecord->dwItems)) {
|
|||
|
pdhStatus = GetLastError();
|
|||
|
} else {
|
|||
|
// reset the count
|
|||
|
dwFiltered = 1;
|
|||
|
}
|
|||
|
} else {
|
|||
|
// skip this one
|
|||
|
if (bIsDataRecord) dwFiltered += 1;
|
|||
|
}
|
|||
|
|
|||
|
// get next record
|
|||
|
dwRecordIdx++;
|
|||
|
}
|
|||
|
} else if (pdhStatus == PDH_INSUFFICIENT_BUFFER) {
|
|||
|
// BUGBUG: expand and retry
|
|||
|
} else {
|
|||
|
if ((pdhStatus == PDH_END_OF_LOG_FILE) || (pdhStatus == PDH_ENTRY_NOT_IN_LOG_FILE)) {
|
|||
|
// fix up return codes to continue
|
|||
|
pdhStatus = ERROR_SUCCESS;
|
|||
|
} else {
|
|||
|
_tprintf ((LPCTSTR)TEXT("\n ReadRaw returned %d (0x%8.8x)"), pdhStatus, pdhStatus);
|
|||
|
}
|
|||
|
// bail
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// add records from new file
|
|||
|
if (pdhStatus == ERROR_SUCCESS) {
|
|||
|
dwRecordIdx = 1;
|
|||
|
ftValue.dwHighDateTime = 0xFFFFFFFF;
|
|||
|
ftValue.dwLowDateTime = dwRecordIdx;
|
|||
|
|
|||
|
if (pRawRecord != NULL) {
|
|||
|
// write headers from first file to temp file
|
|||
|
while (pdhStatus == ERROR_SUCCESS) {
|
|||
|
ftValue.dwHighDateTime = 0xFFFFFFFF;
|
|||
|
ftValue.dwLowDateTime = dwRecordIdx;
|
|||
|
dwRecordSize = dwRecordBuffSize;
|
|||
|
pdhStatus = PdhReadRawLogRecord (
|
|||
|
hAppendLogFile,
|
|||
|
ftValue,
|
|||
|
pRawRecord,
|
|||
|
&dwRecordSize);
|
|||
|
|
|||
|
if (pdhStatus == ERROR_SUCCESS) {
|
|||
|
bIsDataRecord = TRUE;
|
|||
|
if (dwRecordIdx == 1) {
|
|||
|
bIsDataRecord = FALSE;
|
|||
|
} else if ((dwRecordIdx == 2) && (pRawRecord->dwRecordType == PDH_LOG_TYPE_BINARY)) {
|
|||
|
// write only the data records to the output file
|
|||
|
// if this isn't the first record, then it must be a data record or
|
|||
|
// or else skip it
|
|||
|
dwLogRecType = *((LPDWORD)&pRawRecord->RawBytes[0]);
|
|||
|
if ((pRawRecord->dwRecordType == PDH_LOG_TYPE_BINARY) &&
|
|||
|
((dwLogRecType & 0x00FF0000) != 0x00030000)) {
|
|||
|
// then this is not a data record
|
|||
|
// so skip it and get next record
|
|||
|
dwRecordIdx++;
|
|||
|
continue;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if ((!bIsDataRecord) || (dwFiltered == dwFilterCount)) {
|
|||
|
bStatus = WriteFile (
|
|||
|
hTempFile,
|
|||
|
&pRawRecord->RawBytes[0],
|
|||
|
pRawRecord->dwItems,
|
|||
|
&dwBytesWritten,
|
|||
|
NULL);
|
|||
|
if (!bStatus || (dwBytesWritten != pRawRecord->dwItems)) {
|
|||
|
pdhStatus = GetLastError();
|
|||
|
} else {
|
|||
|
// reset the count
|
|||
|
dwFiltered = 1;
|
|||
|
}
|
|||
|
} else {
|
|||
|
// skip this one
|
|||
|
if (bIsDataRecord) dwFiltered += 1;
|
|||
|
}
|
|||
|
|
|||
|
// get next record
|
|||
|
dwRecordIdx++;
|
|||
|
} else if (pdhStatus == PDH_INSUFFICIENT_BUFFER) {
|
|||
|
// BUGBUG: expand and retry
|
|||
|
} else {
|
|||
|
if ((pdhStatus == PDH_END_OF_LOG_FILE) || (pdhStatus == PDH_ENTRY_NOT_IN_LOG_FILE)) {
|
|||
|
// fix up return codes to continue
|
|||
|
pdhStatus = ERROR_SUCCESS;
|
|||
|
} else {
|
|||
|
_tprintf ((LPCTSTR)TEXT("\n ReadRaw returned %d (0x%8.8x)"), pdhStatus, pdhStatus);
|
|||
|
}
|
|||
|
// bail
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
} else {
|
|||
|
// no buffer
|
|||
|
}
|
|||
|
}
|
|||
|
// clean up
|
|||
|
PdhCloseLog (hAppendLogFile,0);
|
|||
|
PdhCloseLog (hBaseLogFile,0);
|
|||
|
CloseHandle (hTempFile);
|
|||
|
// shuffle the files around to make it look like it was appended
|
|||
|
if (pdhStatus == ERROR_SUCCESS) {
|
|||
|
if (CopyFile (szTempFileName, szBaseFile, FALSE)) {
|
|||
|
DeleteFile (szTempFileName);
|
|||
|
}
|
|||
|
}
|
|||
|
} else {
|
|||
|
// alloc fail
|
|||
|
_tprintf ((LPCTSTR)TEXT("\nUnable to allocate temporary memory buffer."));
|
|||
|
}
|
|||
|
} else {
|
|||
|
//unable to open new file for reading
|
|||
|
_tprintf ((LPCTSTR)TEXT("\nUnable to open input file for reading."));
|
|||
|
dwReturn = pdhStatus;
|
|||
|
PdhCloseLog (hBaseLogFile,0);
|
|||
|
CloseHandle (hTempFile);
|
|||
|
DeleteFile (szTempFileName);
|
|||
|
}
|
|||
|
} else {
|
|||
|
//unable to open base file for reading
|
|||
|
_tprintf ((LPCTSTR)TEXT("\nUnable to open output file for reading."));
|
|||
|
dwReturn = pdhStatus;
|
|||
|
CloseHandle (hTempFile);
|
|||
|
DeleteFile (szTempFileName);
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
// unable to create temp file
|
|||
|
_tprintf ((LPCTSTR)TEXT("\nUnable to create temporary file in temp dir."));
|
|||
|
dwReturn = GetLastError();
|
|||
|
}
|
|||
|
} else {
|
|||
|
dwReturn = pdhStatus;
|
|||
|
}
|
|||
|
|
|||
|
return dwReturn;
|
|||
|
}
|
|||
|
|
|||
|
int
|
|||
|
__cdecl
|
|||
|
wmain(
|
|||
|
int argc,
|
|||
|
_TCHAR *argv[]
|
|||
|
)
|
|||
|
/*
|
|||
|
|
|||
|
relog
|
|||
|
/Input:<filename>
|
|||
|
/Output:<filename>
|
|||
|
/Settings:<settings filename>
|
|||
|
/Logtype:[BIN|BLG|TSV|CSV]
|
|||
|
/StartTime:yyyy-mm-dd-hh:mm:ss
|
|||
|
/EndTime;yyyy-mm-dd-hh:mm:ss
|
|||
|
/Filter:n
|
|||
|
*/
|
|||
|
{
|
|||
|
LONG Status = ERROR_SUCCESS;
|
|||
|
|
|||
|
DWORD dwOutputLogType = PDH_LOG_TYPE_UNDEFINED;
|
|||
|
|
|||
|
DWORD dwFilterCount = 1;
|
|||
|
|
|||
|
DWORD dwMode = NORMAL_MODE;
|
|||
|
|
|||
|
PDH_TIME_INFO pdhTimeInfo;
|
|||
|
|
|||
|
DWORD dwPdhVersion = 0;
|
|||
|
|
|||
|
ParseCmd( argc, argv );
|
|||
|
|
|||
|
Status = PdhGetDllVersion (&dwPdhVersion);
|
|||
|
|
|||
|
dwOutputLogType = GetOutputLogType( Commands[eFormat].strValue );
|
|||
|
|
|||
|
pdhTimeInfo.StartTime = 0;
|
|||
|
pdhTimeInfo.EndTime = 0;
|
|||
|
if( Commands[eBegin].bDefined ){
|
|||
|
FILETIME ft;
|
|||
|
SystemTimeToFileTime( &Commands[eBegin].stValue, &ft );
|
|||
|
pdhTimeInfo.StartTime = *(LONGLONG *)&ft;
|
|||
|
}
|
|||
|
|
|||
|
if( Commands[eEnd].bDefined ){
|
|||
|
FILETIME ft;
|
|||
|
SystemTimeToFileTime( &Commands[eEnd].stValue, &ft );
|
|||
|
pdhTimeInfo.EndTime = *(LONGLONG *)&ft;
|
|||
|
}
|
|||
|
pdhTimeInfo.SampleCount = 0;
|
|||
|
// szXXXFile cannot be NULL at this point!
|
|||
|
if ( Commands[eQuery].bValue ) {
|
|||
|
dwMode = LIST_MODE;
|
|||
|
} else if (Commands[eAppend].bValue ) {
|
|||
|
dwMode = APPEND_MODE;
|
|||
|
}
|
|||
|
|
|||
|
if (Status == ERROR_SUCCESS) {
|
|||
|
switch (dwMode) {
|
|||
|
case HEADER_MODE:
|
|||
|
Status = DoHeaderListMode (
|
|||
|
Commands[eInput].strValue,
|
|||
|
Commands[eOutput].strValue);
|
|||
|
break;
|
|||
|
|
|||
|
case LIST_MODE:
|
|||
|
Status = DoListMode (
|
|||
|
Commands[eInput].strValue,
|
|||
|
Commands[eOutput].strValue);
|
|||
|
break;
|
|||
|
|
|||
|
case APPEND_MODE:
|
|||
|
Status = DoAppendFiles (
|
|||
|
Commands[eInput].strValue,
|
|||
|
Commands[eOutput].strValue,
|
|||
|
Commands[eInterval].nValue );
|
|||
|
break;
|
|||
|
|
|||
|
case NORMAL_MODE:
|
|||
|
default:
|
|||
|
Status = DoNormalMode (
|
|||
|
Commands[eInput].strValue,
|
|||
|
Commands[eOutput].strValue,
|
|||
|
Commands[eCounters].strValue,
|
|||
|
dwOutputLogType,
|
|||
|
pdhTimeInfo,
|
|||
|
Commands[eInterval].nValue);
|
|||
|
break;
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return Status;
|
|||
|
}
|