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;
|
||
}
|