windows-nt/Source/XPSP1/NT/sdktools/pdh/pdhlog/log_wmi.c
2020-09-26 16:20:57 +08:00

4104 lines
148 KiB
C

/*++
Copyright (C) 1996-1999 Microsoft Corporation
Module Name:
log_wmi.c
Abstract:
<abstract>
--*/
#include <stdio.h>
#include <stdlib.h>
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <assert.h>
#include <pdh.h>
#include "pdhidef.h"
#include "perfdata.h"
#include "log_bin.h"
#include "log_wmi.h"
#include "strings.h"
#include "pdhmsg.h"
#pragma warning ( disable : 4201 )
#include <initguid.h>
#include <wmistr.h>
#include <ntwmi.h>
#pragma warning ( default : 4201 )
GUID PdhTransactionGuid = // 933f3bb3-943e-490d-9ced-3cbb14c14479
{ 0x933f3bb3, 0x943e, 0x490d, 0x9c, 0xed, 0x3c, 0xbb, 0x14, 0xc1, 0x44, 0x79 };
PDHI_BINARY_LOG_RECORD_HEADER PdhNullCounterHeader = {
BINLOG_TYPE_DATA_PSEUDO, 48 };
PDH_RAW_COUNTER PdhNullCounter = {
0, // CStatus
{ 0, 0 }, // TimeStamp
0, // FirstValue
0, // SecondValue
0 // MultiCount
};
#define PDH_MAX_LOGFILES 32
#define PDH_MAX_PATH 1024
#define PDH_BLOCK_BUFFER_SIZE 8000
#define PDH_WMI_BUFFER_SIZE 64
#define PDH_WMI_BUFFER_SIZE_BYTE 64 * 1024
#define PDH_LOG_HEADER_EVENT 0x20
#define PDH_LOG_DATA_BLOCK_EVENT 0x22
#define PDH_LOG_CATALOG_LIST_EVENT 0x23
#define PDH_LOG_COUNTER_STRING_EVENT 0x24
#define PDH_EVENT_VERSION 60
#define PDH_WMI_MAX_BUFFERS 512
#define PDH_WMI_DEFAULT_BUFFERS 32
#define PDH_WMI_BUFFER_INCREMENT 16
#define PDH_RESOURCE_NAME L"MofResource"
#define TIME_DELTA 100000
TRACEHANDLE PdhTraceRegistrationHandle = (TRACEHANDLE) 0;
// For PDH WMI event trace logfile output
//
typedef struct _PDH_WMI_LOG_INFO {
DWORD dwLogVersion; // version stamp
DWORD dwFlags; // option flags
} PDH_WMI_LOG_INFO, *PPDH_WMI_LOG_INFO;
typedef struct _PDH_EVENT_TRACE_PROPERTIES {
EVENT_TRACE_PROPERTIES LoggerInfo;
WCHAR LoggerName[PDH_MAX_PATH];
WCHAR LogFileName[PDH_MAX_PATH];
GUID LogFileGuid;
LONGLONG TimeStamp;
LPWSTR MachineList;
DWORD MachineListSize;
BOOLEAN bHeaderEvent;
} PDH_EVENT_TRACE_PROPERTIES, * PPDH_EVENT_TRACE_PROPERTIES;
typedef struct _PDH_WMI_EVENT_TRACE {
EVENT_TRACE_HEADER EventHeader;
MOF_FIELD MofFields[4];
} PDH_WMI_EVENT_TRACE, * PPDH_WMI_EVENT_TRACE;
// For PDH WMI event trace logfile input
//
typedef enum _PDH_PROCESS_TRACE_STATE {
PdhProcessTraceNormal,
PdhProcessTraceRewind,
PdhProcessTraceComplete,
PdhProcessTraceEnd,
PdhProcessTraceExit
} PDH_PROCESS_TRACE_STATE;
typedef struct _PDH_WMI_PERF_MACHINE {
LIST_ENTRY Entry;
LIST_ENTRY LogObjectList;
LPWSTR pszBuffer;
DWORD dwLastId;
DWORD dwBufSize;
LPWSTR * ptrStrAry;
} PDH_WMI_PERF_MACHINE, * PPDH_WMI_PERF_MACHINE;
typedef struct _PDH_WMI_PERF_OBJECT {
LIST_ENTRY Entry;
DWORD dwObjectId;
LPWSTR szObjectName;
PVOID ptrBuffer;
} PDH_WMI_PERF_OBJECT, * PPDH_WMI_PERF_OBJECT;
typedef struct _PDH_COUNTER_PATH {
LIST_ENTRY Entry;
ULONGLONG TimeStamp;
PVOID CounterPathBuffer;
ULONG CounterPathSize;
ULONG CounterCount;
} PDH_COUNTER_PATH, * PPDH_COUNTER_PATH;
typedef struct _PDH_WMI_LOGFILE_INFO {
GUID LogFileGuid;
LIST_ENTRY CounterPathList;
LIST_ENTRY PerfMachineList;
ULONGLONG TimeStart;
ULONGLONG TimeEnd;
ULONGLONG TimeFreq;
ULONGLONG TimePrev;
PVOID DataBlock;
ULONG ValidEntries;
ULONG DataBlockSize;
ULONG DataBlockAlloc;
ULONG ulNumDataBlocks;
ULONG ulDataBlocksCopied;
ULONG ulCounters;
} PDH_WMI_LOGFILE_INFO, * PPDH_WMI_LOGFILE_INFO;
typedef struct _PDH_LOGGER_CONTEXT {
PDH_WMI_LOGFILE_INFO LogInfo[PDH_MAX_LOGFILES];
TRACEHANDLE LogFileHandle[PDH_MAX_LOGFILES];
LPWSTR LogFileName[PDH_MAX_LOGFILES];
ULONGLONG TimeFreq;
HANDLE hThreadWork;
HANDLE hSyncPDH;
HANDLE hSyncWMI;
PVOID CounterPathBuffer;
PVOID tmpBuffer;
PDH_PROCESS_TRACE_STATE LoggerState;
ULONG LogFileCount;
ULONG LoggerCount;
ULONG RefCount;
DWORD dwThread;
BOOLEAN bCounterPathChanged;
BOOLEAN bFirstDataBlockRead;
BOOLEAN bDataBlockProcessed;
BOOLEAN bFirstRun;
} PDH_LOGGER_CONTEXT, * PPDH_LOGGER_CONTEXT;
PPDH_LOGGER_CONTEXT ContextTable[PDH_MAX_LOGFILES];
DWORD ContextCount = 0;
HANDLE hPdhContextMutex;
typedef struct _PDH_DATA_BLOCK_TRANSFER {
ULONGLONG CurrentTime;
PVOID pRecord;
DWORD dwCurrentSize;
PDH_STATUS Status;
} PDH_DATA_BLOCK_TRANSFER, * PPDH_DATA_BLOCK_TRANSFER;
PDH_DATA_BLOCK_TRANSFER DataBlockInfo = { 0, NULL, 0, ERROR_SUCCESS };
void
GuidToString(PWCHAR s, LPGUID piid)
{
swprintf(s, L"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
piid->Data1,
piid->Data2,
piid->Data3,
piid->Data4[0],
piid->Data4[1],
piid->Data4[2],
piid->Data4[3],
piid->Data4[4],
piid->Data4[5],
piid->Data4[6],
piid->Data4[7]);
}
PPDH_LOGGER_CONTEXT
PdhWmiGetCurrentContext(
IN DWORD dwLine)
{
PPDH_LOGGER_CONTEXT CurrentContext = NULL;
DWORD dwThread = GetCurrentThreadId();
DWORD i;
if (WAIT_FOR_AND_LOCK_MUTEX(hPdhContextMutex) == ERROR_SUCCESS) {
for (i = 0; i < ContextCount; i ++) {
if (ContextTable[i]->dwThread == dwThread) {
CurrentContext = ContextTable[i];
break;
}
}
RELEASE_MUTEX(hPdhContextMutex);
}
return CurrentContext;
}
DWORD
PdhWmiGetLoggerContext(
IN DWORD dwLine,
IN PPDH_LOGGER_CONTEXT pLoggerContext)
{
DWORD i = ContextCount;
if (pLoggerContext != NULL) {
if (WAIT_FOR_AND_LOCK_MUTEX(hPdhContextMutex) == ERROR_SUCCESS) {
for (i = 0; i < ContextCount; i ++) {
if (ContextTable[i] == pLoggerContext) {
break;
}
}
RELEASE_MUTEX(hPdhContextMutex);
}
}
return i;
}
#define GetCurrentContext() PdhWmiGetCurrentContext(__LINE__)
#define GetLoggerContext(X) PdhWmiGetLoggerContext(__LINE__,X)
#if 0
PDH_FUNCTION
PdhiBuildEmptyBlock(
IN PPDHI_LOG pLog,
IN LONGLONG TimeStamp,
OUT ULONG * lenMofData,
OUT PVOID * ptrMofData)
{
PDH_STATUS pdhStatus = ERROR_SUCCESS;
PPDHI_COUNTER pThisCounter;
PPDHI_BINARY_LOG_RECORD_HEADER pLogCounterBuffer = NULL;
PPDHI_BINARY_LOG_RECORD_HEADER pThisLogCounter = NULL;
PPDH_RAW_COUNTER pSingleCounter;
PPDHI_RAW_COUNTER_ITEM_BLOCK pMultiCounter;
PPERF_DATA_BLOCK pObjectCounter;
DWORD dwBufSize = 0;
if (pLog->pQuery == NULL || pLog->pQuery->pCounterListHead == NULL) {
pdhStatus = PDH_NO_DATA;
goto Cleanup;
}
pThisCounter = pLog->pQuery->pCounterListHead;
do {
DWORD dwType = (pThisCounter->dwFlags & PDHIC_COUNTER_OBJECT)
? (PDHIC_COUNTER_OBJECT)
: ( (pThisCounter->dwFlags & PDHIC_MULTI_INSTANCE)
? (PDHIC_MULTI_INSTANCE) : (0));
DWORD dwCtrBufSize = sizeof(PDHI_BINARY_LOG_RECORD_HEADER);
DWORD dwNewSize;
int nItem;
switch (dwType) {
case PDHIC_MULTI_INSTANCE:
dwCtrBufSize += sizeof(PDHI_RAW_COUNTER_ITEM_BLOCK);
break;
case PDHIC_COUNTER_OBJECT:
dwCtrBufSize += sizeof(PERF_DATA_BLOCK);
break;
default:
dwCtrBufSize += sizeof(PDH_RAW_COUNTER);
break;
}
if (pLogCounterBuffer == NULL) {
dwBufSize = (dwCtrBufSize + sizeof(PDHI_BINARY_LOG_RECORD_HEADER));
pLogCounterBuffer = G_ALLOC(dwBufSize);
if (pLogCounterBuffer == NULL) {
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
break;
}
pThisLogCounter = (PPDHI_BINARY_LOG_RECORD_HEADER)
( ((PUCHAR) pLogCounterBuffer)
+ sizeof(PDHI_BINARY_LOG_RECORD_HEADER));
}
else {
PPDHI_BINARY_LOG_RECORD_HEADER ptrTemp = pLogCounterBuffer;
dwNewSize = (dwBufSize + dwCtrBufSize);
pLogCounterBuffer = G_REALLOC(ptrTemp, dwNewSize);
if (pLogCounterBuffer == NULL) {
G_FREE(ptrTemp);
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
break;
}
pThisLogCounter = (PPDHI_BINARY_LOG_RECORD_HEADER)
((LPBYTE) pLogCounterBuffer + dwBufSize);
dwBufSize += (USHORT) dwCtrBufSize;
}
assert (dwCtrBufSize < 0x00010000);
pThisLogCounter->dwLength = LOWORD(dwCtrBufSize);
if (dwType == PDHIC_COUNTER_OBJECT) {
FILETIME tmpFileTime;
pThisLogCounter->dwType = BINLOG_TYPE_DATA_LOC_OBJECT;
pObjectCounter = (PPERF_DATA_BLOCK)
((LPBYTE) pThisLogCounter +
sizeof(PDHI_BINARY_LOG_RECORD_HEADER));
pObjectCounter->Signature[0] = L'P';
pObjectCounter->Signature[1] = L'E';
pObjectCounter->Signature[2] = L'R';
pObjectCounter->Signature[3] = L'F';
pObjectCounter->LittleEndian = TRUE;
pObjectCounter->Version = PERF_DATA_VERSION;
pObjectCounter->Revision = PERF_DATA_REVISION;
pObjectCounter->TotalByteLength = sizeof(PERF_DATA_BLOCK);
pObjectCounter->NumObjectTypes = 1;
pObjectCounter->DefaultObject = pThisCounter->plCounterInfo.dwObjectId;
pObjectCounter->SystemNameLength = 0;
pObjectCounter->SystemNameOffset = 0;
pObjectCounter->HeaderLength = sizeof(PERF_DATA_BLOCK);
pObjectCounter->PerfTime.QuadPart = 0;
pObjectCounter->PerfFreq.QuadPart = 0;
pObjectCounter->PerfTime100nSec.QuadPart = 0;
tmpFileTime.dwLowDateTime = LODWORD(TimeStamp);
tmpFileTime.dwHighDateTime = HIDWORD(TimeStamp);
FileTimeToSystemTime(& tmpFileTime, & pObjectCounter->SystemTime);
}
else if (dwType == PDHIC_MULTI_INSTANCE) {
pThisLogCounter->dwType = BINLOG_TYPE_DATA_MULTI;
pMultiCounter = (PPDHI_RAW_COUNTER_ITEM_BLOCK)
((LPBYTE) pThisLogCounter +
sizeof(PDHI_BINARY_LOG_RECORD_HEADER));
ZeroMemory(pMultiCounter, sizeof(PDHI_RAW_COUNTER_ITEM_BLOCK));
pMultiCounter->CStatus = ERROR_SUCCESS;
pMultiCounter->TimeStamp.dwLowDateTime = LODWORD(TimeStamp);
pMultiCounter->TimeStamp.dwHighDateTime = HIDWORD(TimeStamp);
}
else {
pThisLogCounter->dwType = BINLOG_TYPE_DATA_SINGLE;
pSingleCounter = (PPDH_RAW_COUNTER)
((LPBYTE) pThisLogCounter +
sizeof(PDHI_BINARY_LOG_RECORD_HEADER));
ZeroMemory(pSingleCounter, sizeof(PDH_RAW_COUNTER));
pSingleCounter->CStatus = ERROR_SUCCESS;
pSingleCounter->TimeStamp.dwLowDateTime = LODWORD(TimeStamp);
pSingleCounter->TimeStamp.dwHighDateTime = HIDWORD(TimeStamp);
}
pThisCounter = pThisCounter->next.flink; // go to next in list
} while (pThisCounter != pLog->pQuery->pCounterListHead);
if (pLogCounterBuffer) {
pLogCounterBuffer->dwType = BINLOG_TYPE_DATA;
pLogCounterBuffer->dwLength = dwBufSize;
}
Cleanup:
* lenMofData = dwBufSize;
* ptrMofData = pLogCounterBuffer;
return pdhStatus;
}
#endif
PDH_FUNCTION
PdhWmiTraceEvent(
IN PPDHI_LOG pLog,
IN ULONG PdhEventType,
IN ULONGLONG TimeStamp,
IN ULONG lenMofData,
IN PVOID ptrMofData);
PDH_FUNCTION
PdhiBuildPerfCounterList(
IN PPDHI_LOG pLog,
IN PPDH_EVENT_TRACE_PROPERTIES LoggerInfo,
IN PPDHI_COUNTER pCounter)
{
PDH_STATUS Status = ERROR_SUCCESS;
PPERF_MACHINE pMachine = pCounter->pQMachine->pMachine;
LPWSTR * pString = pMachine->szPerfStrings;
BYTE * pType = pMachine->typePerfStrings;
DWORD dwLastId = pMachine->dwLastPerfString;
DWORD i;
DWORD dwBufSize = 0;
LPWSTR pszBuffer = NULL;
LPWSTR pszCurrent;
BOOLEAN bNewEvent = TRUE;
if (LoggerInfo->MachineList != NULL) {
pszCurrent = LoggerInfo->MachineList;
while (* pszCurrent != L'\0') {
if (lstrcmpiW(pszCurrent, pMachine->szName) == 0) {
// Machine Perf Counter List already there, bail out.
//
goto Cleanup;
}
pszCurrent += (lstrlenW(pszCurrent) + 1);
}
}
if (LoggerInfo->MachineList != NULL) {
LPWSTR pszTemp = LoggerInfo->MachineList;
LoggerInfo->MachineList = G_REALLOC( pszTemp,
sizeof(WCHAR) * (LoggerInfo->MachineListSize + (lstrlenW(pMachine->szName) + 1)));
if (LoggerInfo->MachineList != NULL) {
pszCurrent = LoggerInfo->MachineList
+ (LoggerInfo->MachineListSize - 1);
LoggerInfo->MachineListSize += (lstrlenW(pMachine->szName) + 1);
}
else {
G_FREE(pszTemp);
}
}
else {
LoggerInfo->MachineListSize = (lstrlenW(pMachine->szName) + 2);
LoggerInfo->MachineList =
G_ALLOC(sizeof(WCHAR) * LoggerInfo->MachineListSize);
if (LoggerInfo->MachineList != NULL) {
pszCurrent = LoggerInfo->MachineList;
}
}
if (LoggerInfo->MachineList == NULL) {
Status = PDH_MEMORY_ALLOCATION_FAILURE;
goto Cleanup;
}
lstrcpyW(pszCurrent, pMachine->szName);
dwBufSize = sizeof(WCHAR) * (lstrlenW(pMachine->szName) + 1);
pszBuffer = (LPWSTR) G_ALLOC(PDH_BLOCK_BUFFER_SIZE);
if (pszBuffer == NULL) {
Status = PDH_MEMORY_ALLOCATION_FAILURE;
goto Cleanup;
}
__try {
WCHAR szIndex[10];
DWORD dwNewSize = 0;
for (i = 0; i < dwLastId; i ++) {
if (pString[i] == NULL || pType[i] != STR_COUNTER) continue;
ZeroMemory(szIndex, sizeof(WCHAR) * 10);
_ltow(i, szIndex, 10);
dwNewSize = sizeof(WCHAR) * ( lstrlenW(szIndex) + 1
+ lstrlenW(pString[i]) + 1);
if (dwBufSize + dwNewSize >= PDH_BLOCK_BUFFER_SIZE) {
Status = PdhWmiTraceEvent(pLog,
PDH_LOG_COUNTER_STRING_EVENT,
LoggerInfo->TimeStamp - 1,
dwBufSize,
pszBuffer);
bNewEvent = TRUE;
}
if (bNewEvent) {
ZeroMemory(pszBuffer, PDH_BLOCK_BUFFER_SIZE);
lstrcpyW(pszBuffer, pMachine->szName);
pszCurrent = pszBuffer + (lstrlenW(pszBuffer) + 1);
dwBufSize = sizeof(WCHAR) * (lstrlenW(pMachine->szName) + 1);
bNewEvent = FALSE;
}
lstrcpyW(pszCurrent, szIndex);
pszCurrent += (lstrlenW(pszCurrent) + 1);
lstrcpyW(pszCurrent, pString[i]);
pszCurrent += (lstrlenW(pszCurrent) + 1);
dwBufSize += dwNewSize;
}
Status = PdhWmiTraceEvent(pLog,
PDH_LOG_COUNTER_STRING_EVENT,
LoggerInfo->TimeStamp - 1,
dwBufSize,
pszBuffer);
}
__except (EXCEPTION_EXECUTE_HANDLER) {
Status = GetExceptionCode();
}
Cleanup:
if (pszBuffer != NULL) {
G_FREE(pszBuffer);
}
return Status;
}
PDH_FUNCTION
PdhiBuildLogHeaderBlock(
IN PPDHI_LOG pLog,
IN PPDH_EVENT_TRACE_PROPERTIES LoggerInfo)
{
PDH_STATUS Status = ERROR_SUCCESS;
PVOID ptrOutBuffer = NULL;
PVOID ptrTemp;
PPDH_WMI_LOG_INFO pLogInfo = NULL;
DWORD SizeAlloc = sizeof(PDH_WMI_LOG_INFO);
DWORD NewSizeAlloc;
PPDHI_COUNTER pThisCounter;
PPDHI_COUNTER pThisCounterHead;
DWORD dwPathBufSize;
PPDHI_LOG_COUNTER_PATH pLogCounter;
LONG lBufOffset;
PWCHAR pBufferBase;
ptrOutBuffer = G_ALLOC(sizeof(PDH_WMI_LOG_INFO));
if (ptrOutBuffer == NULL) {
Status = PDH_MEMORY_ALLOCATION_FAILURE;
goto Cleanup;
}
pLogInfo = (PPDH_WMI_LOG_INFO) ptrOutBuffer;
pLogInfo->dwLogVersion = WMILOG_VERSION;
pLogInfo->dwFlags = pLog->dwLogFormat;
pThisCounter = pThisCounterHead = (pLog->pQuery)
? (pLog->pQuery->pCounterListHead)
: (NULL);
if (pThisCounter != NULL) {
do {
dwPathBufSize = sizeof(PDHI_LOG_COUNTER_PATH) + sizeof(DWORD);
if (pThisCounter->pCounterPath->szMachineName != NULL) {
dwPathBufSize += sizeof(WCHAR) * (1 +
lstrlenW(pThisCounter->pCounterPath->szMachineName));
}
if (pThisCounter->pCounterPath->szObjectName != NULL) {
dwPathBufSize += sizeof(WCHAR) * (1 +
lstrlenW(pThisCounter->pCounterPath->szObjectName));
}
if (pThisCounter->dwFlags & PDHIC_COUNTER_OBJECT) {
Status = PdhiBuildPerfCounterList(
pLog, LoggerInfo, pThisCounter);
if (Status != ERROR_SUCCESS) {
goto Cleanup;
}
}
if (pThisCounter->pCounterPath->szInstanceName != NULL) {
dwPathBufSize += sizeof(WCHAR) * (1 +
lstrlenW(pThisCounter->pCounterPath->szInstanceName));
}
if (pThisCounter->pCounterPath->szParentName != NULL) {
dwPathBufSize += sizeof(WCHAR) * (1 +
lstrlenW(pThisCounter->pCounterPath->szParentName));
}
if (pThisCounter->pCounterPath->szCounterName != NULL) {
dwPathBufSize += sizeof(WCHAR) * (1 +
lstrlenW(pThisCounter->pCounterPath->szCounterName));
}
dwPathBufSize = QWORD_MULTIPLE(dwPathBufSize);
NewSizeAlloc = SizeAlloc + dwPathBufSize;
ptrTemp = ptrOutBuffer;
ptrOutBuffer = G_REALLOC(ptrTemp, NewSizeAlloc);
if (ptrOutBuffer == NULL) {
G_FREE(ptrTemp);
Status = PDH_MEMORY_ALLOCATION_FAILURE;
goto Cleanup;
}
pLogCounter = (PPDHI_LOG_COUNTER_PATH)
(((LPBYTE) ptrOutBuffer) + SizeAlloc);
SizeAlloc = NewSizeAlloc;
RtlZeroMemory(pLogCounter, dwPathBufSize);
pLogCounter->dwLength = dwPathBufSize;
pLogCounter->dwFlags = pThisCounter->dwFlags;
pLogCounter->dwUserData = pThisCounter->dwUserData;
if (pThisCounter->dwFlags & PDHIC_COUNTER_OBJECT) {
pLogCounter->dwCounterType = PDHIC_COUNTER_OBJECT;
pLogCounter->lDefaultScale = 0;
pLogCounter->dwIndex = 0;
}
else {
pLogCounter->dwCounterType =
pThisCounter->plCounterInfo.dwCounterType;
pLogCounter->lDefaultScale =
pThisCounter->plCounterInfo.lDefaultScale;
pLogCounter->dwIndex =
pThisCounter->pCounterPath->dwIndex;
}
pLogCounter->llTimeBase = pThisCounter->TimeBase;
// if this is a wild card path, then move the strings up
// 1 dword in the buffer allowing the first DWORD of the
// the buffer to contain the offset into the catalog
// of the instances found in this log file. This list
// will be built after the log is closed.
lBufOffset = 0; // in WORDS (not bytes)
if (pThisCounter->pCounterPath->szInstanceName != NULL) {
if (* pThisCounter->pCounterPath->szInstanceName == SPLAT_L) {
lBufOffset = sizeof(DWORD);
}
}
#if DBG
if (lBufOffset > 0)
* (LPDWORD) (& pLogCounter->Buffer[0]) = 0x12345678;
#endif
if (pThisCounter->pCounterPath->szMachineName != NULL) {
pLogCounter->lMachineNameOffset = lBufOffset;
pBufferBase = (PWCHAR)
((LPBYTE) & pLogCounter->Buffer[0] + lBufOffset);
lstrcpyW(pBufferBase,
pThisCounter->pCounterPath->szMachineName);
lBufOffset += sizeof(WCHAR) * (1 +
lstrlenW(pThisCounter->pCounterPath->szMachineName));
}
else {
pLogCounter->lMachineNameOffset = (LONG) -1;
}
if (pThisCounter->pCounterPath->szObjectName != NULL) {
pLogCounter->lObjectNameOffset = lBufOffset;
pBufferBase = (PWCHAR)
((LPBYTE) & pLogCounter->Buffer[0] + lBufOffset);
lstrcpyW(pBufferBase,
pThisCounter->pCounterPath->szObjectName);
lBufOffset += sizeof(WCHAR) * (1 +
lstrlenW(pThisCounter->pCounterPath->szObjectName));
}
else {
pLogCounter->lObjectNameOffset = (LONG) -1;
}
if (pThisCounter->pCounterPath->szInstanceName != NULL) {
pLogCounter->lInstanceOffset = lBufOffset;
pBufferBase = (PWCHAR)
((LPBYTE) & pLogCounter->Buffer[0] + lBufOffset);
lstrcpyW(pBufferBase,
pThisCounter->pCounterPath->szInstanceName);
lBufOffset += sizeof(WCHAR) * (1 +
lstrlenW(pThisCounter->pCounterPath->szInstanceName));
}
else {
pLogCounter->lInstanceOffset = (LONG) -1;
}
if (pThisCounter->pCounterPath->szParentName != NULL) {
pLogCounter->lParentOffset = lBufOffset;
pBufferBase = (PWCHAR)
((LPBYTE) & pLogCounter->Buffer[0] + lBufOffset);
lstrcpyW(pBufferBase,
pThisCounter->pCounterPath->szParentName);
lBufOffset += sizeof(WCHAR) * (1 +
lstrlenW(pThisCounter->pCounterPath->szParentName));
}
else {
pLogCounter->lParentOffset = (LONG) -1;
}
if (pThisCounter->pCounterPath->szCounterName != NULL) {
pLogCounter->lCounterOffset = lBufOffset;
pBufferBase = (PWCHAR)
((LPBYTE) & pLogCounter->Buffer[0] + lBufOffset);
lstrcpyW(pBufferBase,
pThisCounter->pCounterPath->szCounterName);
lBufOffset += sizeof(WCHAR) * (1 +
lstrlenW(pThisCounter->pCounterPath->szCounterName));
}
else {
pLogCounter->lCounterOffset = (LONG) -1;
}
pThisCounter = pThisCounter->next.flink;
} while (pThisCounter != pThisCounterHead);
}
if (Status == ERROR_SUCCESS) {
Status = PdhWmiTraceEvent(pLog,
PDH_LOG_HEADER_EVENT,
LoggerInfo->TimeStamp - 1,
SizeAlloc,
ptrOutBuffer);
}
Cleanup:
if (ptrOutBuffer) {
G_FREE(ptrOutBuffer);
}
return Status;
}
PDH_FUNCTION
PdhWmiTraceEvent(
IN PPDHI_LOG pLog,
IN ULONG PdhEventType,
IN ULONGLONG TimeStamp,
IN ULONG lenMofData,
IN PVOID ptrMofData)
{
PDH_STATUS Status = PDH_INVALID_HANDLE;
if ( (pLog->dwLogFormat & PDH_LOG_WRITE_ACCESS)
&& ((TRACEHANDLE) pLog->hLogFileHandle != (TRACEHANDLE) 0)) {
PDH_WMI_EVENT_TRACE Wnode;
PPDH_EVENT_TRACE_PROPERTIES LoggerInfo =
(PPDH_EVENT_TRACE_PROPERTIES) pLog->lpMappedFileBase;
DWORD dwNumEvents = (lenMofData / PDH_BLOCK_BUFFER_SIZE);
DWORD dwCurrentEvent = 1;
PVOID ptrCurrentMof = ptrMofData;
BOOL bIncreaseBuffer = TRUE;
if (lenMofData > PDH_BLOCK_BUFFER_SIZE * dwNumEvents) {
dwNumEvents ++;
}
for (Status = ERROR_SUCCESS, dwCurrentEvent = 1;
(Status == ERROR_SUCCESS) && (dwCurrentEvent <= dwNumEvents);
dwCurrentEvent ++) {
USHORT sMofLen = (lenMofData > PDH_BLOCK_BUFFER_SIZE)
? (PDH_BLOCK_BUFFER_SIZE) : ((USHORT) lenMofData);
RtlZeroMemory(& Wnode, sizeof(PDH_WMI_EVENT_TRACE));
Wnode.EventHeader.Size = sizeof(PDH_WMI_EVENT_TRACE);
Wnode.EventHeader.Class.Type = (UCHAR) PdhEventType;
Wnode.EventHeader.Class.Version = PDH_EVENT_VERSION;
Wnode.EventHeader.GuidPtr = (ULONGLONG) & PdhTransactionGuid;
Wnode.EventHeader.Flags = WNODE_FLAG_TRACED_GUID
| WNODE_FLAG_USE_GUID_PTR
| WNODE_FLAG_USE_MOF_PTR
| WNODE_FLAG_USE_TIMESTAMP;
if ( PdhEventType == PDH_LOG_HEADER_EVENT
|| PdhEventType == PDH_LOG_COUNTER_STRING_EVENT) {
Wnode.EventHeader.Flags |= WNODE_FLAG_PERSIST_EVENT;
}
Wnode.EventHeader.TimeStamp.QuadPart = TimeStamp;
Wnode.MofFields[0].Length = sizeof(GUID);
Wnode.MofFields[0].DataPtr = (ULONGLONG) & LoggerInfo->LogFileGuid;
Wnode.MofFields[1].Length = sizeof(DWORD);
Wnode.MofFields[1].DataPtr = (ULONGLONG) & dwCurrentEvent;
Wnode.MofFields[2].Length = sizeof(DWORD);
Wnode.MofFields[2].DataPtr = (ULONGLONG) & dwNumEvents;
Wnode.MofFields[3].Length = sMofLen;
Wnode.MofFields[3].DataPtr = (ULONGLONG) ptrCurrentMof;
bIncreaseBuffer = TRUE;
while (bIncreaseBuffer == TRUE) {
Status = TraceEvent((TRACEHANDLE) pLog->hLogFileHandle,
(PEVENT_TRACE_HEADER) & Wnode);
if (Status == ERROR_NOT_ENOUGH_MEMORY) {
if (LoggerInfo->LoggerInfo.MaximumBuffers >= PDH_WMI_MAX_BUFFERS) {
bIncreaseBuffer = FALSE;
}
else {
EVENT_TRACE_PROPERTIES tmpLoggerInfo;
LoggerInfo->LoggerInfo.MaximumBuffers += PDH_WMI_BUFFER_INCREMENT;
RtlCopyMemory(& tmpLoggerInfo,
& LoggerInfo->LoggerInfo,
sizeof(EVENT_TRACE_PROPERTIES));
tmpLoggerInfo.Wnode.BufferSize = sizeof(EVENT_TRACE_PROPERTIES);
tmpLoggerInfo.LoggerNameOffset = 0;
tmpLoggerInfo.LogFileNameOffset = 0;
Status = ControlTraceW((TRACEHANDLE) pLog->hLogFileHandle,
LoggerInfo->LoggerName,
(PEVENT_TRACE_PROPERTIES) & tmpLoggerInfo,
EVENT_TRACE_CONTROL_UPDATE);
DebugPrint((1, "UpdateTrace(0x%08X,%d)(%d,0x%08X)\n",
pLog->hLogFileHandle,
LoggerInfo->LoggerInfo.MaximumBuffers,
Status,
Status));
bIncreaseBuffer = (Status == ERROR_SUCCESS || Status == ERROR_MORE_DATA) ? (TRUE) : (FALSE);
}
}
else {
bIncreaseBuffer = FALSE;
}
}
if (Status != ERROR_SUCCESS) {
DebugPrint((1, "PdhWmiTraceEvent(0x%08X,%d,%d/%d,%d,0x%08X,%I64d) fails (%d,0x%08X)\n",
pLog->hLogFileHandle,
PdhEventType,
dwCurrentEvent,
dwNumEvents,
sMofLen,
Wnode.EventHeader.Flags,
Wnode.EventHeader.TimeStamp.QuadPart,
Status,
Status));
}
if (Status == ERROR_SUCCESS) {
lenMofData -= sMofLen;
ptrCurrentMof = (PVOID) (((LPBYTE) ptrCurrentMof) + sMofLen);
}
}
}
return Status;
}
ULONG whextoi(WCHAR *s)
{
long len;
ULONG num, base, hex;
if (s == NULL || s[0] == L'\0') {
return 0;
}
len = (long) wcslen(s); // we expect all strings to be less than MAXSTR
if (len == 0) {
return 0;
}
hex = 0;
base = 1;
num = 0;
while (-- len >= 0) {
if (s[len] >= L'0' && s[len] <= L'9')
num = s[len] - L'0';
else if (s[len] >= L'a' && s[len] <= L'f')
num = (s[len] - L'a') + 10;
else if (s[len] >= L'A' && s[len] <= L'F')
num = (s[len] - L'A') + 10;
else
continue;
hex += num * base;
base = base * 16;
}
return hex;
}
PDH_FUNCTION
PdhiCheckWmiLogFileType(
IN LPCWSTR LogFileName,
IN LPDWORD LogFileType)
{
PDH_STATUS pdhStatus = ERROR_SUCCESS;
HANDLE hFile = NULL;
hFile = CreateFileW(LogFileName,
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile == NULL || hFile == INVALID_HANDLE_VALUE) {
pdhStatus = PDH_LOG_FILE_OPEN_ERROR;
}
else {
BYTE TraceBuffer[PDH_WMI_BUFFER_SIZE_BYTE];
ULONG ByteRead = 0;
INT bResult = ReadFile(hFile,
(LPVOID) TraceBuffer,
PDH_WMI_BUFFER_SIZE_BYTE,
& ByteRead,
NULL);
if (bResult > 0 && ByteRead == PDH_WMI_BUFFER_SIZE_BYTE) {
PWMI_BUFFER_HEADER BufferHeader;
PTRACE_LOGFILE_HEADER LogFileHeader;
BufferHeader = (PWMI_BUFFER_HEADER) TraceBuffer;
LogFileHeader = (PTRACE_LOGFILE_HEADER)
(TraceBuffer + sizeof(WMI_BUFFER_HEADER)
+ sizeof(SYSTEM_TRACE_HEADER));
if ( BufferHeader->Wnode.BufferSize == PDH_WMI_BUFFER_SIZE_BYTE
&& LogFileHeader->BufferSize == PDH_WMI_BUFFER_SIZE_BYTE) {
// preassume that this is PDH event trace counter logfile
//
* LogFileType = PDH_LOG_TYPE_BINARY;
}
else {
* LogFileType = PDH_LOG_TYPE_UNDEFINED;
}
}
}
return pdhStatus;
}
PDH_FUNCTION
PdhWmiGetLoggerName(
IN PPDHI_LOG pLog,
IN PPDH_EVENT_TRACE_PROPERTIES LoggerInfo)
{
PDH_STATUS Status = ERROR_SUCCESS;
BYTE TraceBuffer[PDH_WMI_BUFFER_SIZE_BYTE]; // read in the first trace buffer
HANDLE hFile;
ULONG ByteRead = 0;
hFile = CreateFileW(LoggerInfo->LogFileName,
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile == NULL || hFile == INVALID_HANDLE_VALUE) {
Status = PDH_LOG_FILE_OPEN_ERROR;
}
else {
INT bResult =
ReadFile(hFile, (LPVOID) TraceBuffer, PDH_WMI_BUFFER_SIZE_BYTE, & ByteRead, NULL);
if (bResult == 0 || ByteRead != PDH_WMI_BUFFER_SIZE_BYTE) {
Status = PDH_LOG_FILE_OPEN_ERROR;
}
CloseHandle(hFile);
}
if (Status == ERROR_SUCCESS) {
PTRACE_LOGFILE_HEADER pHeader = (PTRACE_LOGFILE_HEADER)
(TraceBuffer + sizeof(WMI_BUFFER_HEADER) + sizeof(SYSTEM_TRACE_HEADER));
if (pHeader->BuffersWritten > 1) {
UINT i;
WCHAR strTmp[PDH_MAX_PATH];
LPWSTR LoggerName = (LPWSTR) (((LPBYTE) pHeader) + sizeof(TRACE_LOGFILE_HEADER));
lstrcpynW(LoggerInfo->LoggerName, LoggerName, PDH_MAX_PATH);
wcsncpy(strTmp, LoggerName, 8);
strTmp[8] = L'\0';
LoggerInfo->LogFileGuid.Data1 = whextoi(strTmp);
wcsncpy(strTmp, & LoggerName[9], 4);
strTmp[4] = L'\0';
LoggerInfo->LogFileGuid.Data2 = (USHORT) whextoi(strTmp);
wcsncpy(strTmp, & LoggerName[14], 4);
strTmp[4] = L'\0';
LoggerInfo->LogFileGuid.Data3 = (USHORT) whextoi(strTmp);
for (i = 0; i < 2; i ++) {
wcsncpy(strTmp, & LoggerName[19 + (i * 2)], 2);
strTmp[2] = L'\0';
LoggerInfo->LogFileGuid.Data4[i] = (UCHAR) whextoi(strTmp);
}
for (i = 2; i < 8; i ++) {
wcsncpy(strTmp, & LoggerName[20 + (i * 2)], 2);
strTmp[2] = L'\0';
LoggerInfo->LogFileGuid.Data4[i] = (UCHAR) whextoi(strTmp);
}
}
else {
// Only 1 trace buffer written, no PDH events yet.
// It is safe to discard this one and create a new one.
//
Status = PDH_LOG_FILE_OPEN_ERROR;
DebugPrint((1,"PdhWmiGetLoggerName(0x%08X,0x%08X,0x%08X,\"%ws\")\n",
Status, pLog, LoggerInfo, LoggerInfo->LogFileName));
}
}
return Status;
}
PDH_FUNCTION
PdhiOpenOutputWmiLog(
IN PPDHI_LOG pLog)
{
PDH_STATUS Status = PDH_LOG_FILE_CREATE_ERROR;
PPDH_EVENT_TRACE_PROPERTIES LoggerInfo;
pLog->lpMappedFileBase = G_ALLOC(sizeof(PDH_EVENT_TRACE_PROPERTIES));
if (pLog->lpMappedFileBase == NULL) {
Status = PDH_MEMORY_ALLOCATION_FAILURE;
goto Cleanup;
}
LoggerInfo = (PPDH_EVENT_TRACE_PROPERTIES) pLog->lpMappedFileBase;
RtlZeroMemory(LoggerInfo, sizeof(PDH_EVENT_TRACE_PROPERTIES));
// Start PDH kernel logger
//
LoggerInfo->LoggerInfo.Wnode.BufferSize =
sizeof(PDH_EVENT_TRACE_PROPERTIES);
LoggerInfo->LoggerInfo.Wnode.Flags = WNODE_FLAG_TRACED_GUID;
LoggerInfo->LoggerInfo.Wnode.ClientContext = EVENT_TRACE_CLOCK_SYSTEMTIME;
LoggerInfo->LoggerInfo.BufferSize = PDH_WMI_BUFFER_SIZE;
LoggerInfo->LoggerInfo.LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
LoggerInfo->LoggerInfo.LogFileNameOffset = sizeof(EVENT_TRACE_PROPERTIES)
+ sizeof(WCHAR) * PDH_MAX_PATH;
_wfullpath(LoggerInfo->LogFileName, pLog->szLogFileName, PDH_MAX_PATH);
if ( !(pLog->dwLogFormat & PDH_LOG_OPT_CIRCULAR)
&& (pLog->dwLogFormat & PDH_LOG_OPT_APPEND)) {
Status = PdhWmiGetLoggerName(pLog, LoggerInfo);
if (Status != ERROR_SUCCESS) {
// if cannot get LogFileGuid from logfile, erase the old one
// and create new one
//
RPC_STATUS rpcStatus = UuidCreate(& LoggerInfo->LogFileGuid);
GuidToString(LoggerInfo->LoggerName, & LoggerInfo->LogFileGuid);
}
else {
LoggerInfo->LoggerInfo.LogFileMode |= EVENT_TRACE_FILE_MODE_APPEND;
}
}
else {
RPC_STATUS rpcStatus = UuidCreate(& LoggerInfo->LogFileGuid);
GuidToString(LoggerInfo->LoggerName, & LoggerInfo->LogFileGuid);
}
if (pLog->dwLogFormat & PDH_LOG_OPT_CIRCULAR) {
LoggerInfo->LoggerInfo.LogFileMode |= EVENT_TRACE_FILE_MODE_CIRCULAR;
}
else {
LoggerInfo->LoggerInfo.LogFileMode |= EVENT_TRACE_FILE_MODE_SEQUENTIAL;
}
LoggerInfo->LoggerInfo.LogFileMode |= EVENT_TRACE_USE_PAGED_MEMORY;
if (pLog->llMaxSize == 0) {
LoggerInfo->LoggerInfo.MaximumFileSize = 0;
}
else {
LoggerInfo->LoggerInfo.MaximumFileSize =
(ULONG) ((pLog->llMaxSize / 1024) / 1024);
}
LoggerInfo->LoggerInfo.MaximumBuffers = PDH_WMI_DEFAULT_BUFFERS;
LoggerInfo->bHeaderEvent = FALSE;
Status = StartTraceW((PTRACEHANDLE) & pLog->hLogFileHandle,
LoggerInfo->LoggerName,
(PEVENT_TRACE_PROPERTIES) LoggerInfo);
if (Status != ERROR_SUCCESS) {
DebugPrint((1, "StartTraceW(%ws,%ws,0x%08X,%I64d) fails (0x%08X,%c)\n",
LoggerInfo->LoggerName,
LoggerInfo->LogFileName,
LoggerInfo->LoggerInfo.LogFileMode,
pLog->llMaxSize,
Status,
LoggerInfo->bHeaderEvent ? 'T' : 'F'));
}
Cleanup:
if (Status != ERROR_SUCCESS) {
if (pLog->lpMappedFileBase) {
G_FREE(pLog->lpMappedFileBase);
pLog->lpMappedFileBase = NULL;
}
Status = PDH_LOG_FILE_CREATE_ERROR;
}
return Status;
}
PDH_FUNCTION
PdhiWriteWmiLogRecord (
IN PPDHI_LOG pLog,
IN SYSTEMTIME * stTimeStamp,
IN LPCWSTR szUserString
)
{
PDH_STATUS pdhStatus = ERROR_SUCCESS;
PPDHI_BINARY_LOG_RECORD_HEADER pLogCounterBuffer = NULL;
PPDHI_BINARY_LOG_RECORD_HEADER pThisLogCounter = NULL;
PPDH_RAW_COUNTER pSingleCounter;
PPDHI_RAW_COUNTER_ITEM_BLOCK pMultiCounter;
PPDHI_COUNTER pThisCounter;
PPERF_DATA_BLOCK pObjectCounter;
DWORD dwBufSize = 0;
ULONGLONG TimeStamp = 0;
FILETIME tFileTime;
PPDH_EVENT_TRACE_PROPERTIES LoggerInfo =
(PPDH_EVENT_TRACE_PROPERTIES) pLog->lpMappedFileBase;
DBG_UNREFERENCED_PARAMETER(szUserString);
SystemTimeToFileTime(stTimeStamp, & tFileTime);
pThisCounter = pLog->pQuery ? pLog->pQuery->pCounterListHead : NULL;
if (pThisCounter == NULL) {
return PDH_NO_DATA;
}
do {
DWORD dwType = (pThisCounter->dwFlags & PDHIC_COUNTER_OBJECT)
? (PDHIC_COUNTER_OBJECT)
: ( (pThisCounter->dwFlags & PDHIC_MULTI_INSTANCE)
? (PDHIC_MULTI_INSTANCE) : (0));
DWORD dwCtrBufSize = sizeof(PDHI_BINARY_LOG_RECORD_HEADER);
DWORD dwNewSize;
int nItem;
switch (dwType) {
case PDHIC_MULTI_INSTANCE:
if (pThisCounter->pThisRawItemList) {
dwCtrBufSize += pThisCounter->pThisRawItemList->dwLength;
}
else {
dwCtrBufSize += sizeof(PDHI_RAW_COUNTER_ITEM_BLOCK);
}
break;
case PDHIC_COUNTER_OBJECT:
if (pThisCounter->pThisObject) {
dwCtrBufSize += pThisCounter->pThisObject->TotalByteLength;
}
else {
dwCtrBufSize += sizeof(PERF_DATA_BLOCK);
}
break;
default:
dwCtrBufSize += sizeof(PDH_RAW_COUNTER);
break;
}
if (dwCtrBufSize > 0) {
// extend buffer to accomodate this new counter
//
if (pLogCounterBuffer == NULL) {
// add in room for the master record header
// then allocate the first one
//
dwBufSize = (dwCtrBufSize + sizeof(PDHI_BINARY_LOG_RECORD_HEADER));
pLogCounterBuffer = G_ALLOC(dwBufSize);
// set counter data pointer to just after the master
// record header
//
if (pLogCounterBuffer == NULL) {
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
break;
}
pThisLogCounter = (PPDHI_BINARY_LOG_RECORD_HEADER)
( ((PUCHAR) pLogCounterBuffer)
+ sizeof(PDHI_BINARY_LOG_RECORD_HEADER));
assert (dwCtrBufSize < 0x00010000);
pThisLogCounter->dwLength = LOWORD(dwCtrBufSize);
}
else {
PPDHI_BINARY_LOG_RECORD_HEADER ptrTemp = pLogCounterBuffer;
dwNewSize = (dwBufSize + dwCtrBufSize);
pLogCounterBuffer = G_REALLOC(ptrTemp, dwNewSize);
if (pLogCounterBuffer == NULL) {
G_FREE(ptrTemp);
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
break;
}
pThisLogCounter = (PPDHI_BINARY_LOG_RECORD_HEADER)
((LPBYTE) pLogCounterBuffer + dwBufSize);
dwBufSize += dwCtrBufSize;
assert (dwCtrBufSize < 0x00010000);
pThisLogCounter->dwLength = LOWORD(dwCtrBufSize);
}
}
if (dwType == PDHIC_COUNTER_OBJECT) {
FILETIME LocFileTime;
pThisLogCounter->dwType = BINLOG_TYPE_DATA_LOC_OBJECT;
pObjectCounter = (PPERF_DATA_BLOCK)
((LPBYTE) pThisLogCounter +
sizeof(PDHI_BINARY_LOG_RECORD_HEADER));
if (pThisCounter->pThisObject) {
RtlCopyMemory(pObjectCounter,
pThisCounter->pThisObject,
pThisCounter->pThisObject->TotalByteLength);
SystemTimeToFileTime(& pThisCounter->pThisObject->SystemTime,
& LocFileTime);
}
else {
if (TimeStamp != 0) {
LocFileTime.dwLowDateTime = LODWORD(TimeStamp);
LocFileTime.dwHighDateTime = HIDWORD(TimeStamp);
}
else {
LocFileTime = tFileTime;
}
pObjectCounter->Signature[0] = L'P';
pObjectCounter->Signature[1] = L'E';
pObjectCounter->Signature[2] = L'R';
pObjectCounter->Signature[3] = L'F';
pObjectCounter->LittleEndian = TRUE;
pObjectCounter->Version = PERF_DATA_VERSION;
pObjectCounter->Revision = PERF_DATA_REVISION;
pObjectCounter->TotalByteLength = sizeof(PERF_DATA_BLOCK);
pObjectCounter->NumObjectTypes = 1;
pObjectCounter->DefaultObject = pThisCounter->plCounterInfo.dwObjectId;
pObjectCounter->SystemNameLength = 0;
pObjectCounter->SystemNameOffset = 0;
pObjectCounter->HeaderLength = sizeof(PERF_DATA_BLOCK);
pObjectCounter->PerfTime.QuadPart = 0;
pObjectCounter->PerfFreq.QuadPart = 0;
pObjectCounter->PerfTime100nSec.QuadPart = 0;
FileTimeToSystemTime(& LocFileTime,
& pObjectCounter->SystemTime);
}
TimeStamp = MAKELONGLONG(LocFileTime.dwLowDateTime,
LocFileTime.dwHighDateTime);
}
else if (dwType == PDHIC_MULTI_INSTANCE) {
// multiple counter
//
pThisLogCounter->dwType = BINLOG_TYPE_DATA_MULTI;
pMultiCounter = (PPDHI_RAW_COUNTER_ITEM_BLOCK)
((LPBYTE) pThisLogCounter +
sizeof(PDHI_BINARY_LOG_RECORD_HEADER));
if (pThisCounter->pThisRawItemList) {
RtlCopyMemory(pMultiCounter,
pThisCounter->pThisRawItemList,
pThisCounter->pThisRawItemList->dwLength);
}
else {
FILETIME LocFileTime;
if (TimeStamp != 0) {
LocFileTime.dwLowDateTime = LODWORD(TimeStamp);
LocFileTime.dwHighDateTime = HIDWORD(TimeStamp);
}
else {
LocFileTime = tFileTime;
}
ZeroMemory(pMultiCounter,
sizeof(PDHI_RAW_COUNTER_ITEM_BLOCK));
pMultiCounter->CStatus = PDH_CSTATUS_INVALID_DATA;
pMultiCounter->TimeStamp.dwLowDateTime =
LocFileTime.dwLowDateTime;
pMultiCounter->TimeStamp.dwHighDateTime =
LocFileTime.dwHighDateTime;
}
TimeStamp = MAKELONGLONG(pMultiCounter->TimeStamp.dwLowDateTime,
pMultiCounter->TimeStamp.dwHighDateTime);
}
else {
pThisLogCounter->dwType = BINLOG_TYPE_DATA_SINGLE;
pSingleCounter = (PPDH_RAW_COUNTER)
((LPBYTE) pThisLogCounter +
sizeof(PDHI_BINARY_LOG_RECORD_HEADER));
RtlCopyMemory( pSingleCounter,
& pThisCounter->ThisValue,
sizeof(PDH_RAW_COUNTER));
if (pSingleCounter->CStatus != ERROR_SUCCESS) {
if (TimeStamp != 0) {
pSingleCounter->TimeStamp.dwLowDateTime =
LODWORD(TimeStamp);
pSingleCounter->TimeStamp.dwHighDateTime =
HIDWORD(TimeStamp);
}
else {
pSingleCounter->TimeStamp.dwLowDateTime =
tFileTime.dwLowDateTime;
pSingleCounter->TimeStamp.dwHighDateTime =
tFileTime.dwHighDateTime;
}
}
TimeStamp = (ULONGLONG) MAKELONGLONG(
pSingleCounter->TimeStamp.dwLowDateTime,
pSingleCounter->TimeStamp.dwHighDateTime);
}
pThisCounter = pThisCounter->next.flink; // go to next in list
} while (pThisCounter != pLog->pQuery->pCounterListHead);
if (TimeStamp == 0) {
TimeStamp = MAKELONGLONG(tFileTime.dwLowDateTime,
tFileTime.dwHighDateTime);
}
if (pdhStatus == ERROR_SUCCESS && pLogCounterBuffer) {
pLogCounterBuffer->dwType = BINLOG_TYPE_DATA;
pLogCounterBuffer->dwLength = dwBufSize;
LoggerInfo->TimeStamp = TimeStamp;
if (! LoggerInfo->bHeaderEvent) {
ULONG HeaderMofLength = 0;
PVOID HeaderMofData = NULL;
ULONG EventType;
if (LoggerInfo->LoggerInfo.LogFileMode
& EVENT_TRACE_FILE_MODE_APPEND) {
#if 0
pdhStatus = PdhiBuildEmptyBlock(pLog,
LoggerInfo->TimeStamp - 1,
& HeaderMofLength,
& HeaderMofData);
if (pdhStatus == ERROR_SUCCESS) {
pdhStatus = PdhWmiTraceEvent(pLog,
PDH_LOG_DATA_BLOCK_EVENT,
LoggerInfo->TimeStamp - 1,
HeaderMofLength,
HeaderMofData);
}
if (HeaderMofData) {
G_FREE(HeaderMofData);
}
#endif
}
else {
pdhStatus = PdhiBuildLogHeaderBlock(pLog, LoggerInfo);
}
LoggerInfo->bHeaderEvent = TRUE;
}
}
if (pdhStatus == ERROR_SUCCESS && pLogCounterBuffer) {
pdhStatus = PdhWmiTraceEvent(pLog,
PDH_LOG_DATA_BLOCK_EVENT,
TimeStamp,
dwBufSize,
(PVOID) pLogCounterBuffer);
}
if (pLogCounterBuffer != NULL) {
G_FREE(pLogCounterBuffer);
}
return pdhStatus;
}
PDH_FUNCTION
PdhiWriteWmiLogHeader (
IN PPDHI_LOG pLog,
IN LPCWSTR szUserCaption)
{
UNREFERENCED_PARAMETER (pLog);
UNREFERENCED_PARAMETER (szUserCaption);
return ERROR_SUCCESS;
}
PDH_FUNCTION
PdhiCloseWmiLog(
IN PPDHI_LOG pLog,
IN DWORD dwFlags)
{
PDH_STATUS Status = PDH_INVALID_ARGUMENT;
UNREFERENCED_PARAMETER (pLog);
UNREFERENCED_PARAMETER (dwFlags);
if (pLog->dwLogFormat & PDH_LOG_WRITE_ACCESS) {
if ((TRACEHANDLE) pLog->hLogFileHandle != (TRACEHANDLE) 0) {
PPDH_EVENT_TRACE_PROPERTIES LoggerInfo =
(PPDH_EVENT_TRACE_PROPERTIES) pLog->lpMappedFileBase;
if (LoggerInfo == NULL) {
Status = PDH_INVALID_HANDLE;
}
else {
ULONG HeaderMofLength = 0;
PVOID HeaderMofData = NULL;
#if 0
Status = PdhiBuildEmptyBlock(pLog,
LoggerInfo->TimeStamp,
& HeaderMofLength,
& HeaderMofData);
if (Status == ERROR_SUCCESS) {
Status = PdhWmiTraceEvent(pLog,
PDH_LOG_DATA_BLOCK_EVENT,
LoggerInfo->TimeStamp + 1,
HeaderMofLength,
HeaderMofData);
}
if (HeaderMofData) {
G_FREE(HeaderMofData);
}
#endif
Status = ControlTraceW((TRACEHANDLE) pLog->hLogFileHandle,
LoggerInfo->LoggerName,
(PEVENT_TRACE_PROPERTIES) LoggerInfo,
EVENT_TRACE_CONTROL_STOP);
if (Status != ERROR_SUCCESS) {
DebugPrint((1, "StopTrace(0x%08X,%ws,%ws) fails (%d)\n",
pLog->hLogFileHandle,
LoggerInfo->LoggerName,
LoggerInfo->LogFileName,
Status,
Status));
}
if (LoggerInfo->MachineList != NULL) {
G_FREE(LoggerInfo->MachineList);
}
G_FREE(pLog->lpMappedFileBase);
pLog->lpMappedFileBase = NULL;
}
pLog->hLogFileHandle = INVALID_HANDLE_VALUE;
if (PdhTraceRegistrationHandle != (TRACEHANDLE) 0) {
Status = UnregisterTraceGuids(PdhTraceRegistrationHandle);
if (Status != ERROR_SUCCESS) {
DebugPrint((4,
"UnregisterTraceGuid(0x%08X) fails (%d,0x%08X)\n",
PdhTraceRegistrationHandle,
Status,
Status));
}
}
}
else {
Status = PDH_INVALID_HANDLE;
}
}
else if (pLog->dwLogFormat & PDH_LOG_READ_ACCESS) {
ULONG i;
DWORD dwExitCode;
PPDH_LOGGER_CONTEXT CurrentContext =
(PPDH_LOGGER_CONTEXT) pLog->lpMappedFileBase;
DWORD dwContext = GetLoggerContext(CurrentContext);
if (dwContext < ContextCount) {
Status = WAIT_FOR_AND_LOCK_MUTEX(hPdhContextMutex);
if (Status == ERROR_SUCCESS) {
CurrentContext->RefCount --;
if (CurrentContext->RefCount > 0) {
RELEASE_MUTEX(hPdhContextMutex);
return ERROR_SUCCESS;
}
}
else {
return Status;
}
if (dwContext != ContextCount - 1) {
ContextTable[dwContext] = ContextTable[ContextCount - 1];
}
ContextCount --;
ContextTable[ContextCount] = NULL;
RELEASE_MUTEX(hPdhContextMutex);
if (CurrentContext->hThreadWork != NULL
&& CurrentContext->hThreadWork != INVALID_HANDLE_VALUE) {
if (GetExitCodeThread(CurrentContext->hThreadWork, & dwExitCode)
&& dwExitCode == STILL_ACTIVE) {
CurrentContext->LoggerState = PdhProcessTraceEnd;
SetEvent(CurrentContext->hSyncWMI);
while (CurrentContext->LoggerState != PdhProcessTraceExit) {
_sleep(1);
}
if (TerminateThread(CurrentContext->hThreadWork, 0)) {
WaitForSingleObject(CurrentContext->hThreadWork, INFINITE);
}
}
}
if (CurrentContext->hSyncWMI != NULL) {
CloseHandle(CurrentContext->hSyncWMI);
}
if (CurrentContext->hSyncPDH != NULL) {
CloseHandle(CurrentContext->hSyncPDH);
}
for (i = 0; i < CurrentContext->LoggerCount; i ++) {
if (! IsListEmpty(& CurrentContext->LogInfo[i].CounterPathList)) {
PLIST_ENTRY PathHead =
& CurrentContext->LogInfo[i].CounterPathList;
PLIST_ENTRY PathNext = PathHead->Flink;
PPDH_COUNTER_PATH pCounterPath;
while (PathHead != PathNext) {
pCounterPath = CONTAINING_RECORD(PathNext,
PDH_COUNTER_PATH,
Entry);
PathNext = PathNext->Flink;
RemoveEntryList(& pCounterPath->Entry);
G_FREE(pCounterPath->CounterPathBuffer);
G_FREE(pCounterPath);
}
}
if (! IsListEmpty(& CurrentContext->LogInfo[i].PerfMachineList)) {
PLIST_ENTRY PathHead =
& CurrentContext->LogInfo[i].PerfMachineList;
PLIST_ENTRY PathNext = PathHead->Flink;
PPDH_WMI_PERF_MACHINE pPerfMachine;
while (PathHead != PathNext) {
pPerfMachine = CONTAINING_RECORD(PathNext,
PDH_WMI_PERF_MACHINE,
Entry);
PathNext = PathNext->Flink;
RemoveEntryList(& pPerfMachine->Entry);
if (! IsListEmpty(& pPerfMachine->LogObjectList)) {
PLIST_ENTRY pHead =
& pPerfMachine->LogObjectList;
PLIST_ENTRY pNext = pHead->Flink;
PPDH_WMI_PERF_OBJECT pPerfObject;
while (pHead != pNext) {
pPerfObject = CONTAINING_RECORD(
pNext, PDH_WMI_PERF_OBJECT, Entry);
pNext = pNext->Flink;
RemoveEntryList(& pPerfObject->Entry);
G_FREE(pPerfObject->ptrBuffer);
G_FREE(pPerfObject);
}
}
G_FREE(pPerfMachine->pszBuffer);
G_FREE(pPerfMachine->ptrStrAry);
G_FREE(pPerfMachine);
}
}
if (CurrentContext->LogInfo[i].DataBlock) {
G_FREE(CurrentContext->LogInfo[i].DataBlock);
}
}
if (CurrentContext->tmpBuffer) {
G_FREE(CurrentContext->tmpBuffer);
}
if (CurrentContext->CounterPathBuffer) {
G_FREE(CurrentContext->CounterPathBuffer);
}
G_FREE(pLog->lpMappedFileBase);
pLog->lpMappedFileBase = NULL;
pLog->pLastRecordRead = NULL;
Status = ERROR_SUCCESS;
}
else {
Status = PDH_INVALID_HANDLE;
}
}
return Status;
}
PDH_FUNCTION
PdhiAddWmiLogFileGuid(
PPDH_LOGGER_CONTEXT CurrentContext,
LPGUID pGuid)
{
PDH_STATUS Status = ERROR_SUCCESS;
ULONG i;
for (i = 0; i < CurrentContext->LoggerCount; i ++) {
if (IsEqualGUID(pGuid, & CurrentContext->LogInfo[i].LogFileGuid))
break;
}
if (i == CurrentContext->LoggerCount) {
CurrentContext->LogInfo[i].LogFileGuid = * pGuid;
CurrentContext->LoggerCount ++;
if (CurrentContext->LoggerCount > CurrentContext->LogFileCount) {
DebugPrint((4, "LogFileCount(%d) LoggerCount(%d) mismatch\n",
CurrentContext->LoggerCount,
CurrentContext->LogFileCount));
}
}
return Status;
}
ULONG
PdhiFindLogFileGuid(
PPDH_LOGGER_CONTEXT CurrentContext,
LPGUID pGuid)
{
ULONG i;
for (i = 0; i < CurrentContext->LoggerCount; i ++) {
if (IsEqualGUID(pGuid, & CurrentContext->LogInfo[i].LogFileGuid))
break;
}
return i;
}
ULONGLONG
PdhWmiGetDataBlockTimeStamp(
PPDH_LOGGER_CONTEXT CurrentContext,
PEVENT_TRACE pEvent,
BOOLEAN bFirstRun)
{
PVOID pDataBlock = pEvent->MofData;
ULONGLONG TimeStamp = pEvent->Header.TimeStamp.QuadPart;
if (TimeStamp > 0) {
LPGUID pLogFileGuid = (LPGUID) pDataBlock;
ULONG i;
for (i = 0; i < CurrentContext->LoggerCount; i ++) {
if (IsEqualGUID( pLogFileGuid,
& CurrentContext->LogInfo[i].LogFileGuid)) {
break;
}
}
if (i < CurrentContext->LoggerCount) {
if (bFirstRun) {
if ( pEvent->Header.Class.Version < PDH_EVENT_VERSION
|| CurrentContext->LogInfo[i].TimePrev < TimeStamp) {
CurrentContext->LogInfo[i].ValidEntries ++;
}
if (CurrentContext->LogInfo[i].TimeStart == 0) {
CurrentContext->LogInfo[i].TimeStart = TimeStamp;
CurrentContext->LogInfo[i].TimePrev = TimeStamp;
}
else {
// no need to update StartTime.
// Always assume the first trace event has the StartTime.
//
if (CurrentContext->LogInfo[i].TimeEnd < TimeStamp) {
CurrentContext->LogInfo[i].TimeEnd = TimeStamp;
}
if ( (TimeStamp - CurrentContext->LogInfo[i].TimePrev)
< (CurrentContext->LogInfo[i].TimeFreq)) {
CurrentContext->LogInfo[i].TimeFreq =
TimeStamp - CurrentContext->LogInfo[i].TimePrev;
}
CurrentContext->LogInfo[i].TimePrev = TimeStamp;
}
}
else {
assert(CurrentContext->LogInfo[i].TimePrev <= TimeStamp);
assert(CurrentContext->LogInfo[i].TimeStart <= TimeStamp);
assert(CurrentContext->LogInfo[i].TimeEnd >= TimeStamp);
CurrentContext->LogInfo[i].TimePrev = TimeStamp;
}
}
}
return TimeStamp;
}
PDH_FUNCTION
PdhiWmiComputeCounterBlocks(
PPDH_LOGGER_CONTEXT CurrentContext,
PEVENT_TRACE pEvent)
{
LPGUID pLogFileGuid;
PDH_STATUS Status = ERROR_SUCCESS;
PVOID pDataBlock;
ULONG i;
ULONG ulNumDataBlocks;
ULONG ulDataBlocksCopied;
ULONG ulBufferSize;
ULONG ulBlockIndex;
BOOLEAN bOldEvent;
if (CurrentContext == NULL || pEvent == NULL) {
return PDH_INVALID_DATA;
}
bOldEvent = (pEvent->Header.Class.Version < PDH_EVENT_VERSION);
pLogFileGuid = (LPGUID) pEvent->MofData;
if (pLogFileGuid == NULL) {
return PDH_INVALID_DATA;
}
for (i = 0; i < CurrentContext->LoggerCount; i ++) {
if (IsEqualGUID(pLogFileGuid,
& CurrentContext->LogInfo[i].LogFileGuid)) {
break;
}
}
if (i == CurrentContext->LoggerCount) {
return PDH_INVALID_DATA;
}
ulNumDataBlocks = CurrentContext->LogInfo[i].ulNumDataBlocks;
ulDataBlocksCopied = CurrentContext->LogInfo[i].ulDataBlocksCopied;
if (ulNumDataBlocks > 0 && ulNumDataBlocks == ulDataBlocksCopied) {
if (CurrentContext->LogInfo[i].DataBlock != NULL) {
G_FREE(CurrentContext->LogInfo[i].DataBlock);
CurrentContext->LogInfo[i].DataBlock = NULL;
}
goto Cleanup;
}
if (ulNumDataBlocks == 0) {
if (bOldEvent) {
ulNumDataBlocks = 1;
ulBufferSize = pEvent->MofLength;
}
else {
ulNumDataBlocks = * (DWORD *) ( ((LPBYTE) pEvent->MofData)
+ sizeof(GUID) + sizeof(DWORD));
ulBufferSize = ulNumDataBlocks * PDH_BLOCK_BUFFER_SIZE
+ sizeof(GUID);
}
if (CurrentContext->LogInfo[i].DataBlock != NULL) {
G_FREE(CurrentContext->LogInfo[i].DataBlock);
CurrentContext->LogInfo[i].DataBlock = NULL;
}
CurrentContext->LogInfo[i].DataBlock = G_ALLOC(ulBufferSize);
if (CurrentContext->LogInfo[i].DataBlock == NULL) {
Status = PDH_MEMORY_ALLOCATION_FAILURE;
goto Cleanup;
}
CurrentContext->LogInfo[i].ulNumDataBlocks = ulNumDataBlocks;
CurrentContext->LogInfo[i].ulDataBlocksCopied = 0;
CurrentContext->LogInfo[i].DataBlockAlloc = ulBufferSize;
}
if (bOldEvent) {
RtlCopyMemory(CurrentContext->LogInfo[i].DataBlock,
pEvent->MofData,
pEvent->MofLength);
}
else {
ulBlockIndex = * (DWORD *) (((LPBYTE) pEvent->MofData) + sizeof(GUID));
pDataBlock = (PVOID)
( ((LPBYTE) CurrentContext->LogInfo[i].DataBlock)
+ sizeof(GUID)
+ PDH_BLOCK_BUFFER_SIZE * (ulBlockIndex - 1));
RtlCopyMemory(pDataBlock,
(PVOID) (((LPBYTE) pEvent->MofData)
+ sizeof(GUID) + sizeof(DWORD) + sizeof(DWORD)),
pEvent->MofLength - sizeof(GUID)
- sizeof(DWORD) - sizeof(DWORD));
}
CurrentContext->LogInfo[i].ulDataBlocksCopied ++;
if (CurrentContext->LogInfo[i].ulDataBlocksCopied >=
CurrentContext->LogInfo[i].ulNumDataBlocks) {
DWORD dwTotal;
DWORD dwCurrent;
DWORD dwCounters = 0;
BOOLEAN bValidBlock = TRUE;
PPDHI_BINARY_LOG_RECORD_HEADER pCurrent;
PPDHI_BINARY_LOG_RECORD_HEADER pMasterRec;
pDataBlock = CurrentContext->LogInfo[i].DataBlock;
pMasterRec = (PPDHI_BINARY_LOG_RECORD_HEADER)
((LPBYTE) pDataBlock + sizeof(GUID));
dwTotal = pMasterRec->dwLength;
pCurrent = pMasterRec;
dwCurrent = sizeof(PDHI_BINARY_LOG_RECORD_HEADER);
while (bValidBlock && dwCurrent < dwTotal) {
pCurrent = (PPDHI_BINARY_LOG_RECORD_HEADER)
((LPBYTE) pMasterRec + dwCurrent);
if (LOWORD(pCurrent->dwType) != BINLOG_START_WORD) {
bValidBlock = FALSE;
}
else {
dwCurrent += pCurrent->dwLength;
dwCounters ++;
}
}
if (bValidBlock) {
CurrentContext->LogInfo[i].ulCounters += dwCounters;
}
}
Cleanup:
return Status;
}
PDH_FUNCTION
PdhiAddCounterPathRecord(
PPDH_LOGGER_CONTEXT CurrentContext,
PEVENT_TRACE pEvent,
LPGUID pLogFileGuid,
ULONG BufferSize,
PVOID pBuffer,
ULONGLONG TimeStamp,
DWORD dwIndex,
DWORD dwCount,
BOOLEAN * pNeedUpdate)
{
PPDH_COUNTER_PATH pNewCounter;
ULONG i;
PVOID pCounterPath;
i = PdhiFindLogFileGuid(CurrentContext, pLogFileGuid);
if (i == CurrentContext->LoggerCount) {
return PDH_INVALID_DATA;
}
if (pEvent->Header.Class.Version >= PDH_EVENT_VERSION) {
if ( CurrentContext->LogInfo[i].DataBlock
&& CurrentContext->LogInfo[i].ulNumDataBlocks != dwCount) {
G_FREE(CurrentContext->LogInfo[i].DataBlock);
CurrentContext->LogInfo[i].DataBlock = NULL;
}
if (CurrentContext->LogInfo[i].DataBlock == NULL) {
CurrentContext->LogInfo[i].DataBlock =
G_ALLOC(PDH_BLOCK_BUFFER_SIZE * dwCount);
if (CurrentContext->LogInfo[i].DataBlock == NULL) {
return PDH_MEMORY_ALLOCATION_FAILURE;
}
CurrentContext->LogInfo[i].DataBlockAlloc = PDH_BLOCK_BUFFER_SIZE * dwCount;
CurrentContext->LogInfo[i].DataBlockSize = 0;
CurrentContext->LogInfo[i].ulNumDataBlocks = dwCount;
CurrentContext->LogInfo[i].ulDataBlocksCopied = 0;
}
pCounterPath = (PVOID) ( ((LPBYTE) CurrentContext->LogInfo[i].DataBlock)
+ (dwIndex - 1) * PDH_BLOCK_BUFFER_SIZE);
if (BufferSize > PDH_BLOCK_BUFFER_SIZE) {
BufferSize = PDH_BLOCK_BUFFER_SIZE;
}
RtlCopyMemory(pCounterPath, pBuffer, BufferSize);
CurrentContext->LogInfo[i].ulDataBlocksCopied ++;
CurrentContext->LogInfo[i].DataBlockSize += BufferSize;
if ( CurrentContext->LogInfo[i].ulDataBlocksCopied
< CurrentContext->LogInfo[i].ulNumDataBlocks) {
return ERROR_SUCCESS;
}
pCounterPath = (PVOID) (((LPBYTE) CurrentContext->LogInfo[i].DataBlock)
+ sizeof(PDH_WMI_LOG_INFO));
BufferSize = CurrentContext->LogInfo[i].DataBlockSize
- sizeof(PDH_WMI_LOG_INFO);
}
if (! IsListEmpty(& CurrentContext->LogInfo[i].CounterPathList)) {
PLIST_ENTRY PathHead = & CurrentContext->LogInfo[i].CounterPathList;
PLIST_ENTRY PathNext = PathHead->Flink;
while (PathHead != PathNext) {
pNewCounter = CONTAINING_RECORD(PathNext,
PDH_COUNTER_PATH,
Entry);
PathNext = PathNext->Flink;
if (TimeStamp == pNewCounter->TimeStamp) {
// CounterPath record is already in the list
//
return ERROR_SUCCESS;
}
}
}
pNewCounter = G_ALLOC(sizeof(PDH_COUNTER_PATH));
if (pNewCounter == NULL) {
return PDH_MEMORY_ALLOCATION_FAILURE;
}
pNewCounter->TimeStamp = TimeStamp;
pNewCounter->CounterPathBuffer = G_ALLOC(BufferSize);
if (pNewCounter->CounterPathBuffer == NULL) {
G_FREE(pNewCounter);
return PDH_MEMORY_ALLOCATION_FAILURE;
}
pNewCounter->CounterPathSize = BufferSize;
if (pEvent->Header.Class.Version >= PDH_EVENT_VERSION) {
RtlCopyMemory(pNewCounter->CounterPathBuffer, pCounterPath, BufferSize);
}
else {
RtlCopyMemory(pNewCounter->CounterPathBuffer, pBuffer, BufferSize);
}
pNewCounter->CounterCount = 0;
{
PPDHI_LOG_COUNTER_PATH pPath = pNewCounter->CounterPathBuffer;
ULONG dwProcessed = 0;
while (dwProcessed < BufferSize) {
pNewCounter->CounterCount ++;
dwProcessed += pPath->dwLength;
pPath = (PPDHI_LOG_COUNTER_PATH)
(((LPBYTE) pPath) + pPath->dwLength);
}
}
InsertTailList(& CurrentContext->LogInfo[i].CounterPathList,
& pNewCounter->Entry);
* pNeedUpdate = TRUE;
if (pEvent->Header.Class.Version >= PDH_EVENT_VERSION) {
G_FREE(CurrentContext->LogInfo[i].DataBlock);
CurrentContext->LogInfo[i].DataBlock = NULL;
CurrentContext->LogInfo[i].DataBlockAlloc = 0;
CurrentContext->LogInfo[i].DataBlockSize = 0;
CurrentContext->LogInfo[i].ulNumDataBlocks = 0;
CurrentContext->LogInfo[i].ulDataBlocksCopied = 0;
}
return ERROR_SUCCESS;
}
PDH_FUNCTION
PdhiAddPerfMachine(
IN PPDH_LOGGER_CONTEXT CurrentContext,
IN PVOID pMofDataBlock,
IN DWORD dwMofLength)
{
PDH_STATUS Status = ERROR_SUCCESS;
LPGUID pLogFileGuid = (LPGUID) pMofDataBlock;
LPWSTR pszMachineName = (LPWSTR) (((LPBYTE) pMofDataBlock)
+ sizeof(GUID) + sizeof(DWORD) + sizeof(DWORD));
DWORD dwBufSize = dwMofLength
- sizeof(GUID) - sizeof(DWORD) - sizeof(DWORD);
ULONG i;
LPWSTR pszTmpBuffer;
DWORD dwThisId;
DWORD dwBufUsed;
PPDH_WMI_PERF_MACHINE pCurrentMachine = NULL;
BOOLEAN bNewMachine = TRUE;
i = PdhiFindLogFileGuid(CurrentContext, pLogFileGuid);
if (i == CurrentContext->LoggerCount) {
Status = PDH_INVALID_DATA;
goto Cleanup;
}
if (! IsListEmpty(& CurrentContext->LogInfo[i].PerfMachineList)) {
PLIST_ENTRY pHead = & CurrentContext->LogInfo[i].PerfMachineList;
PLIST_ENTRY pNext = pHead->Flink;
while (pNext != pHead) {
PPDH_WMI_PERF_MACHINE pMachine =
CONTAINING_RECORD(pNext, PDH_WMI_PERF_MACHINE, Entry);
if (lstrcmpiW(pMachine->pszBuffer, pszMachineName) == 0) {
pCurrentMachine = pMachine;
bNewMachine = FALSE;
break;
}
pNext = pNext->Flink;
}
}
if (bNewMachine) {
pCurrentMachine = G_ALLOC(sizeof(PDH_WMI_PERF_MACHINE));
if (pCurrentMachine == NULL) {
Status = PDH_MEMORY_ALLOCATION_FAILURE;
goto Cleanup;
}
InsertTailList(& CurrentContext->LogInfo[i].PerfMachineList,
& pCurrentMachine->Entry);
pCurrentMachine->pszBuffer = G_ALLOC(dwBufSize);
if (pCurrentMachine->pszBuffer == NULL) {
Status = PDH_MEMORY_ALLOCATION_FAILURE;
goto Cleanup;
}
RtlCopyMemory(pCurrentMachine->pszBuffer, pszMachineName, dwBufSize);
pCurrentMachine->dwBufSize = dwBufSize;
InitializeListHead(& pCurrentMachine->LogObjectList);
}
else {
pszTmpBuffer = pCurrentMachine->pszBuffer;
dwBufSize -= (sizeof(WCHAR) * (lstrlenW(pszMachineName) + 1));
pszMachineName += (lstrlenW(pszMachineName) + 1);
pCurrentMachine->pszBuffer = G_ALLOC(
pCurrentMachine->dwBufSize + dwBufSize);
if (pCurrentMachine->pszBuffer == NULL) {
pCurrentMachine->pszBuffer = pszTmpBuffer;
Status = PDH_MEMORY_ALLOCATION_FAILURE;
goto Cleanup;
}
RtlCopyMemory(pCurrentMachine->pszBuffer,
pszTmpBuffer,
pCurrentMachine->dwBufSize);
G_FREE(pszTmpBuffer);
pszTmpBuffer = (LPWSTR)
( ((LPBYTE) pCurrentMachine->pszBuffer)
+ pCurrentMachine->dwBufSize);
RtlCopyMemory(pszTmpBuffer, pszMachineName, dwBufSize);
pCurrentMachine->dwBufSize += dwBufSize;
}
dwBufSize = pCurrentMachine->dwBufSize;
pCurrentMachine->dwLastId = 0;
i = lstrlenW(pCurrentMachine->pszBuffer) + 1;
pszTmpBuffer = pCurrentMachine->pszBuffer + i;
dwBufUsed = sizeof(WCHAR) * i;
while ((dwBufUsed < dwBufSize) && (* pszTmpBuffer)) {
do {
dwThisId = wcstoul(pszTmpBuffer, NULL, 10);
if (dwThisId > pCurrentMachine->dwLastId) {
pCurrentMachine->dwLastId = dwThisId;
}
i = lstrlenW(pszTmpBuffer) + 1;
dwBufUsed += (sizeof(WCHAR) * i);
if (dwBufUsed < dwBufSize) {
pszTmpBuffer += i;
}
}
while ((dwThisId == 0) && (* pszTmpBuffer)
&& dwBufUsed < dwBufSize);
i = lstrlenW(pszTmpBuffer) + 1;
dwBufUsed += (sizeof(WCHAR) * i);
if ((* pszTmpBuffer) && (dwBufUsed < dwBufSize)) {
pszTmpBuffer += i;
}
}
if (pCurrentMachine->dwLastId == 0) {
Status = PDH_CANNOT_READ_NAME_STRINGS;
goto Cleanup;
}
if (! bNewMachine) {
G_FREE(pCurrentMachine->ptrStrAry);
pCurrentMachine->ptrStrAry = NULL;
}
pCurrentMachine->ptrStrAry =
G_ALLOC(sizeof(LPWSTR) * (pCurrentMachine->dwLastId + 1));
if (pCurrentMachine->ptrStrAry == NULL) {
Status = PDH_CANNOT_READ_NAME_STRINGS;
goto Cleanup;
}
i = lstrlenW(pCurrentMachine->pszBuffer) + 1;
pszTmpBuffer = pCurrentMachine->pszBuffer + i;
dwBufUsed = sizeof(WCHAR) * i;
while ((dwBufUsed < dwBufSize) && (* pszTmpBuffer)) {
do {
dwThisId = wcstoul(pszTmpBuffer, NULL, 10);
i = lstrlenW(pszTmpBuffer) + 1;
dwBufUsed += (sizeof(WCHAR) * i);
if (dwBufUsed < dwBufSize) {
pszTmpBuffer += i;
}
}
while ((dwThisId == 0) && (* pszTmpBuffer)
&& dwBufUsed < dwBufSize);
if (dwThisId > 0 && dwThisId <= pCurrentMachine->dwLastId) {
pCurrentMachine->ptrStrAry[dwThisId] = pszTmpBuffer;
}
i = lstrlenW(pszTmpBuffer) + 1;
dwBufUsed += (sizeof(WCHAR) * i);
if ((* pszTmpBuffer) && (dwBufUsed < dwBufSize)) {
pszTmpBuffer += i;
}
}
Cleanup:
if (Status != ERROR_SUCCESS) {
if (bNewMachine) {
if (pCurrentMachine != NULL) {
if (pCurrentMachine->pszBuffer != NULL) {
G_FREE(pCurrentMachine->pszBuffer);
}
RemoveEntryList(& pCurrentMachine->Entry);
G_FREE(pCurrentMachine);
}
}
else if (pCurrentMachine != NULL) {
if (pCurrentMachine->pszBuffer != NULL) {
G_FREE(pCurrentMachine->pszBuffer);
}
RemoveEntryList(& pCurrentMachine->Entry);
G_FREE(pCurrentMachine);
}
}
return Status;
}
PDH_FUNCTION
PdhiGetCounterPathRecord(
IN PPDH_LOGGER_CONTEXT CurrentContext,
IN PVOID pRecord,
IN ULONG dwMaxSize)
{
PDH_STATUS Status = ERROR_SUCCESS;
DWORD CurrentSize = sizeof(PDHI_BINARY_LOG_HEADER_RECORD);
if (CurrentContext->bCounterPathChanged) {
PPDHI_BINARY_LOG_HEADER_RECORD pBinLogHeader = NULL;
PVOID pCounterPath;
ULONG i;
if (CurrentContext->CounterPathBuffer) {
G_FREE(CurrentContext->CounterPathBuffer);
}
CurrentContext->CounterPathBuffer = G_ALLOC(CurrentSize);
if (CurrentContext->CounterPathBuffer == NULL) {
Status = PDH_MEMORY_ALLOCATION_FAILURE;
goto Cleanup;
}
for (i = 0; i < CurrentContext->LoggerCount; i ++) {
if (! IsListEmpty(& CurrentContext->LogInfo[i].CounterPathList)) {
PLIST_ENTRY PathHead =
& CurrentContext->LogInfo[i].CounterPathList;
PLIST_ENTRY PathNext = PathHead->Flink;
PPDH_COUNTER_PATH pCurrentPath;
while (Status == ERROR_SUCCESS && PathNext != PathHead) {
PVOID ptrTemp;
pCurrentPath = CONTAINING_RECORD(PathNext,
PDH_COUNTER_PATH,
Entry);
PathNext = PathNext->Flink;
ptrTemp = CurrentContext->CounterPathBuffer;
CurrentContext->CounterPathBuffer = G_REALLOC(
ptrTemp, CurrentSize + pCurrentPath->CounterPathSize);
if (CurrentContext->CounterPathBuffer == NULL) {
G_FREE(ptrTemp);
Status = PDH_MEMORY_ALLOCATION_FAILURE;
goto Cleanup;
}
pCounterPath = (PVOID) (((PUCHAR)
CurrentContext->CounterPathBuffer) + CurrentSize);
RtlCopyMemory(pCounterPath,
pCurrentPath->CounterPathBuffer,
pCurrentPath->CounterPathSize);
CurrentSize += pCurrentPath->CounterPathSize;
}
}
}
pBinLogHeader = (PPDHI_BINARY_LOG_HEADER_RECORD)
CurrentContext->CounterPathBuffer;
RtlZeroMemory(pBinLogHeader, sizeof(PDHI_BINARY_LOG_HEADER_RECORD));
pBinLogHeader->RecHeader.dwType = BINLOG_TYPE_CATALOG_LIST;
pBinLogHeader->Info.dwLogVersion = BINLOG_VERSION;
pBinLogHeader->RecHeader.dwLength = CurrentSize;
CurrentContext->bCounterPathChanged = FALSE;
}
else if (CurrentContext->CounterPathBuffer == NULL) {
return PDH_ENTRY_NOT_IN_LOG_FILE;
}
else {
CurrentSize = ((PPDHI_BINARY_LOG_HEADER_RECORD)
CurrentContext->CounterPathBuffer)->RecHeader.dwLength;
}
if (pRecord != NULL) {
if (dwMaxSize < CurrentSize) {
CurrentSize = dwMaxSize;
Status = PDH_MORE_DATA;
}
RtlCopyMemory(pRecord, CurrentContext->CounterPathBuffer, CurrentSize);
}
Cleanup:
return Status;
}
ULONG
WINAPI
PdhWmiFirstBufferCallback(
PEVENT_TRACE_LOGFILEW LogFile)
{
UNREFERENCED_PARAMETER(LogFile);
return TRUE;
}
ULONG
WINAPI
PdhWmiBufferCallback(
PEVENT_TRACE_LOGFILEW LogFile)
{
ULONG bResult;
PPDH_LOGGER_CONTEXT CurrentContext;
UNREFERENCED_PARAMETER(LogFile);
CurrentContext = GetCurrentContext();
bResult = (CurrentContext && CurrentContext->LoggerState == PdhProcessTraceNormal)
? (TRUE) : (FALSE);
return bResult;
}
void
WINAPI
PdhWmiFirstEventCallback(
PEVENT_TRACE pEvent)
{
DWORD dwMofHeader;
DWORD dwCurrentBlock;
DWORD dwTotalBlocks;
PPDH_LOGGER_CONTEXT CurrentContext;
CurrentContext = GetCurrentContext();
if (pEvent == NULL) {
goto Cleanup;
}
else if (IsEqualGUID(& pEvent->Header.Guid, & EventTraceGuid)) {
goto Cleanup;
}
else if (! IsEqualGUID(& pEvent->Header.Guid, & PdhTransactionGuid)) {
goto Cleanup;
}
else if (CurrentContext == NULL) {
goto Cleanup;
}
dwMofHeader = (pEvent->Header.Class.Version >= PDH_EVENT_VERSION)
? (sizeof(GUID) + sizeof(DWORD) + sizeof(DWORD))
: (sizeof(GUID));
switch (pEvent->Header.Class.Type) {
case PDH_LOG_HEADER_EVENT:
assert(pEvent->MofLength >= sizeof(PDH_WMI_LOG_INFO) + sizeof(GUID));
PdhiAddWmiLogFileGuid(CurrentContext, (LPGUID) pEvent->MofData);
if (pEvent->Header.Class.Version >= PDH_EVENT_VERSION) {
dwCurrentBlock = * (DWORD *)
(((LPBYTE) pEvent->MofData) + sizeof(GUID));
dwTotalBlocks = * (DWORD *)
(((LPBYTE) pEvent->MofData) + sizeof(GUID) + sizeof(DWORD));
PdhiAddCounterPathRecord(
CurrentContext,
pEvent,
(LPGUID) pEvent->MofData,
pEvent->MofLength - dwMofHeader,
(PVOID) (((PUCHAR) pEvent->MofData) + dwMofHeader),
pEvent->Header.TimeStamp.QuadPart,
dwCurrentBlock,
dwTotalBlocks,
& CurrentContext->bCounterPathChanged);
}
else {
dwCurrentBlock = dwTotalBlocks = 1;
PdhiAddCounterPathRecord(
CurrentContext,
pEvent,
(LPGUID) pEvent->MofData,
pEvent->MofLength - sizeof(GUID) - sizeof(PDH_WMI_LOG_INFO),
(PVOID) (((PUCHAR) pEvent->MofData)
+ sizeof(GUID) + sizeof(PDH_WMI_LOG_INFO)),
pEvent->Header.TimeStamp.QuadPart,
dwCurrentBlock,
dwTotalBlocks,
& CurrentContext->bCounterPathChanged);
}
break;
case PDH_LOG_DATA_BLOCK_EVENT:
PdhWmiGetDataBlockTimeStamp(CurrentContext, pEvent, TRUE);
PdhiWmiComputeCounterBlocks(CurrentContext, pEvent);
break;
case PDH_LOG_COUNTER_STRING_EVENT:
PdhiAddWmiLogFileGuid(CurrentContext, (LPGUID) pEvent->MofData);
PdhiAddPerfMachine(CurrentContext, pEvent->MofData, pEvent->MofLength);
break;
default:
DebugPrint((4, "PdhWmiFirstEventCallback(), unknown EventType %d\n",
pEvent->Header.Class.Type));
break;
}
Cleanup:
return;
}
void
WINAPI
PdhWmiEventCallback(
PEVENT_TRACE pEvent)
{
LPGUID pLogFileGuid;
ULONG iLogFile;
BOOLEAN bNotifyPDH = FALSE;
ULONGLONG EventTime = 0;
ULONGLONG EventTimePrev = 0;
DWORD dwNumDataBlocks = 0;
DWORD dwBlockIndex = 0;
DWORD dwBufferSize = 0;
PPDH_LOGGER_CONTEXT CurrentContext = GetCurrentContext();
if (CurrentContext == NULL) {
goto Cleanup;
}
if (pEvent == NULL) {
DebugPrint((4, "PdhWmiEventCallback() with NULL PEVENT_TRACE\n"));
goto Cleanup;
}
else if (IsEqualGUID(& pEvent->Header.Guid, & EventTraceGuid)) {
goto Cleanup;
}
else if ((CurrentContext->LoggerState != PdhProcessTraceNormal) ||
(! IsEqualGUID(& pEvent->Header.Guid, & PdhTransactionGuid))) {
goto Cleanup;
}
switch (pEvent->Header.Class.Type) {
case PDH_LOG_HEADER_EVENT:
case PDH_LOG_COUNTER_STRING_EVENT:
// counter path information has been collected during the first run
//
break;
case PDH_LOG_DATA_BLOCK_EVENT:
pLogFileGuid = (LPGUID) pEvent->MofData;
iLogFile = PdhiFindLogFileGuid(CurrentContext, pLogFileGuid);
if (iLogFile >= CurrentContext->LoggerCount) {
break;
}
EventTimePrev = CurrentContext->LogInfo[iLogFile].TimePrev;
EventTime = PdhWmiGetDataBlockTimeStamp(CurrentContext, pEvent, FALSE);
if (EventTime == 0 || EventTimePrev > EventTime) {
break;
}
if ( pEvent->Header.Class.Version < PDH_EVENT_VERSION
|| EventTimePrev < EventTime) {
dwNumDataBlocks = * (DWORD *) ( ((LPBYTE) pEvent->MofData)
+ sizeof(GUID) + sizeof(DWORD));
dwBufferSize = (pEvent->Header.Class.Version >= PDH_EVENT_VERSION)
? (dwNumDataBlocks * PDH_BLOCK_BUFFER_SIZE + sizeof(GUID))
: (pEvent->MofLength);
if (CurrentContext->LogInfo[iLogFile].DataBlock == NULL) {
CurrentContext->LogInfo[iLogFile].DataBlock = G_ALLOC(dwBufferSize);
}
else if ( CurrentContext->LogInfo[iLogFile].DataBlockAlloc
< dwBufferSize) {
PVOID ptrTemp = CurrentContext->LogInfo[iLogFile].DataBlock;
CurrentContext->LogInfo[iLogFile].DataBlock = G_REALLOC(ptrTemp, dwBufferSize);
if (CurrentContext->LogInfo[iLogFile].DataBlock == NULL) {
G_FREE(ptrTemp);
}
}
if ( (CurrentContext->LogInfo[iLogFile].DataBlock != NULL)
&& (pEvent->Header.Class.Version >= PDH_EVENT_VERSION)) {
RtlCopyMemory(CurrentContext->LogInfo[iLogFile].DataBlock,
pLogFileGuid,
sizeof(GUID));
CurrentContext->LogInfo[iLogFile].DataBlockSize = sizeof(GUID);
CurrentContext->LogInfo[iLogFile].DataBlockAlloc = dwBufferSize;
CurrentContext->LogInfo[iLogFile].ulNumDataBlocks = dwNumDataBlocks;
CurrentContext->LogInfo[iLogFile].ulDataBlocksCopied = 0;
}
}
dwBlockIndex = * (DWORD *) (((LPBYTE) pEvent->MofData) + sizeof(GUID));
if (CurrentContext->LogInfo[iLogFile].DataBlock != NULL) {
if (pEvent->Header.Class.Version >= PDH_EVENT_VERSION) {
PVOID ptrDataBlock = (PVOID)
( ((LPBYTE) CurrentContext->LogInfo[iLogFile].DataBlock)
+ sizeof(GUID)
+ PDH_BLOCK_BUFFER_SIZE * (dwBlockIndex - 1));
RtlCopyMemory(ptrDataBlock,
(PVOID) (((LPBYTE) pEvent->MofData)
+ sizeof(GUID) + sizeof(DWORD) + sizeof(DWORD)),
pEvent->MofLength - sizeof(GUID)
- sizeof(DWORD) - sizeof(DWORD));
CurrentContext->LogInfo[iLogFile].ulDataBlocksCopied ++;
CurrentContext->LogInfo[iLogFile].DataBlockSize +=
pEvent->MofLength - sizeof(GUID)
- sizeof(DWORD) - sizeof(DWORD);
}
else {
RtlCopyMemory(CurrentContext->LogInfo[iLogFile].DataBlock,
pEvent->MofData,
pEvent->MofLength);
CurrentContext->LogInfo[iLogFile].DataBlockSize = pEvent->MofLength;
}
}
if (pEvent->Header.Class.Version < PDH_EVENT_VERSION) {
if (DataBlockInfo.CurrentTime == (ULONGLONG) 0) {
// no CurrentTime comparison, just get the data block
//
DataBlockInfo.CurrentTime = EventTime;
}
if (DataBlockInfo.CurrentTime <= EventTime) {
DataBlockInfo.pRecord =
CurrentContext->LogInfo[iLogFile].DataBlock;
DataBlockInfo.dwCurrentSize = pEvent->MofLength;
DataBlockInfo.Status = ERROR_SUCCESS;
bNotifyPDH = TRUE;
CurrentContext->bDataBlockProcessed = FALSE;
}
}
else if ( CurrentContext->LogInfo[iLogFile].ulDataBlocksCopied
>= CurrentContext->LogInfo[iLogFile].ulNumDataBlocks) {
if (DataBlockInfo.CurrentTime == (ULONGLONG) 0) {
// no CurrentTime comparison, just get the data block
//
DataBlockInfo.CurrentTime = EventTime;
}
if (DataBlockInfo.CurrentTime <= EventTime) {
DataBlockInfo.pRecord =
CurrentContext->LogInfo[iLogFile].DataBlock;
DataBlockInfo.dwCurrentSize =
CurrentContext->LogInfo[iLogFile].DataBlockSize;
DataBlockInfo.Status = ERROR_SUCCESS;
bNotifyPDH = TRUE;
CurrentContext->bDataBlockProcessed = FALSE;
}
}
break;
default:
DebugPrint((4, "PdhWmiEventCallback(), unknown EventType %d\n",
pEvent->Header.Class.Type));
break;
}
Cleanup:
if (bNotifyPDH) {
// Signal that we get the current DataBlock event, then wait for next
// DataBlock requests.
//
SetEvent(CurrentContext->hSyncPDH);
WaitForSingleObject(CurrentContext->hSyncWMI, INFINITE);
}
}
PDH_FUNCTION
PdhProcessLog(
PPDH_LOGGER_CONTEXT CurrentContext)
{
PDH_STATUS Status = ERROR_SUCCESS;
LONG i;
if (GetLoggerContext(CurrentContext) >= ContextCount) {
return PDH_INVALID_HANDLE;
}
CurrentContext->bFirstRun = TRUE;
CurrentContext->dwThread = GetCurrentThreadId();
do {
CurrentContext->LoggerState = PdhProcessTraceNormal;
CurrentContext->bFirstDataBlockRead = FALSE;
CurrentContext->bDataBlockProcessed = FALSE;
for (i = 0; i < (LONG) CurrentContext->LoggerCount; i ++) {
CurrentContext->LogInfo[i].TimePrev = 0;
if (CurrentContext->LogInfo[i].DataBlock) {
G_FREE(CurrentContext->LogInfo[i].DataBlock);
CurrentContext->LogInfo[i].DataBlock = NULL;
}
CurrentContext->LogInfo[i].DataBlockSize = 0;
}
RtlZeroMemory(& DataBlockInfo, sizeof(PDH_DATA_BLOCK_TRANSFER));
Status = ProcessTrace(CurrentContext->LogFileHandle,
CurrentContext->LogFileCount,
NULL,
NULL);
if (Status != ERROR_SUCCESS && Status != ERROR_CANCELLED) {
DebugPrint((4, "ProcessTrace(0x%08X,%d) fails (%d,0x%08X)\n",
CurrentContext,
CurrentContext->LogFileCount,
Status,
Status));
}
if (CurrentContext->bFirstRun) {
CurrentContext->bFirstRun = FALSE;
CurrentContext->LoggerState = PdhProcessTraceRewind;
CurrentContext->TimeFreq = CurrentContext->LogInfo[0].TimeFreq;
for (i = 1; i < (LONG) CurrentContext->LogFileCount; i ++) {
if ( CurrentContext->TimeFreq
> CurrentContext->LogInfo[i].TimeFreq) {
CurrentContext->TimeFreq =
CurrentContext->LogInfo[i].TimeFreq;
}
}
}
else if (CurrentContext->LoggerState == PdhProcessTraceNormal) {
CurrentContext->LoggerState = PdhProcessTraceComplete;
DataBlockInfo.Status = PDH_END_OF_LOG_FILE;
// Wake up PDH main thread so that PdhiReadNextWmiRecord() will
// notice END_OF_LOG_FILE condition. Wait PDH main thread to wake
// me up and rewind logger. After wake up, LoggerState should
// be reset to PdhProcessTraceNormal.
//
SetEvent(CurrentContext->hSyncPDH);
Status = WaitForSingleObject(CurrentContext->hSyncWMI,
INFINITE);
assert(CurrentContext->LoggerState == PdhProcessTraceRewind);
}
for (i = 0; i < (LONG) CurrentContext->LogFileCount; i ++) {
Status = CloseTrace(CurrentContext->LogFileHandle[i]);
if (Status != ERROR_SUCCESS) {
DebugPrint((4, "CloseTrace(%d,%ws) fails (%d,0x%08X)\n",
CurrentContext->LogFileHandle[i],
CurrentContext->LogFileName[i],
Status,
Status));
}
}
if (CurrentContext->LoggerState == PdhProcessTraceRewind) {
EVENT_TRACE_LOGFILEW EvmFile;
for (i = 0; i < (LONG) CurrentContext->LogFileCount; i ++) {
RtlZeroMemory(& EvmFile, sizeof(EVENT_TRACE_LOGFILE));
EvmFile.BufferCallback = PdhWmiBufferCallback;
EvmFile.EventCallback = PdhWmiEventCallback;
EvmFile.LogFileName = CurrentContext->LogFileName[i];
CurrentContext->LogFileHandle[i] = OpenTraceW(& EvmFile);
if ( CurrentContext->LogFileHandle[i] == 0
|| CurrentContext->LogFileHandle[i] ==
(TRACEHANDLE) INVALID_HANDLE_VALUE) {
DebugPrint((4,"OpenTraceW(%d,%ws) fails\n",
i,
CurrentContext->LogFileName[i]));
while (--i >= 0) {
CloseTrace(CurrentContext->LogFileHandle[i]);
}
Status = PDH_LOG_FILE_OPEN_ERROR;
DataBlockInfo.Status = PDH_LOG_FILE_OPEN_ERROR;
SetEvent(CurrentContext->hSyncPDH);
goto Cleanup;
}
}
}
} while (CurrentContext->LoggerState == PdhProcessTraceRewind);
Cleanup:
CurrentContext->LoggerState = PdhProcessTraceExit;
return Status;
}
PDH_FUNCTION
PdhiOpenInputWmiLog(
IN PPDHI_LOG pLog)
{
PDH_STATUS Status = ERROR_SUCCESS;
PPDHI_LOG pLogCurrent = pLog;
PPDH_LOGGER_CONTEXT CurrentContext;
EVENT_TRACE_LOGFILEW EvmFile;
WCHAR LogFileName[PDH_MAX_PATH];
LONG i;
DWORD ThreadId;
CurrentContext = (PPDH_LOGGER_CONTEXT) pLog->lpMappedFileBase;
if (CurrentContext != NULL) {
if (GetLoggerContext(CurrentContext) < ContextCount) {
CurrentContext->RefCount ++;
pLog->lpMappedFileBase = (PVOID) CurrentContext;
return ERROR_SUCCESS;
}
else {
DebugPrint((4, "PdhiOpenInputWmiLog(0x%08X,0x%08X,0x%08X)\n",
pLog,
pLog->lpMappedFileBase,
CurrentContext));
return PDH_INVALID_ARGUMENT;
}
}
CurrentContext = (PPDH_LOGGER_CONTEXT) G_ALLOC(sizeof(PDH_LOGGER_CONTEXT));
if (CurrentContext == NULL) {
Status = PDH_MEMORY_ALLOCATION_FAILURE;
goto Cleanup;
}
pLog->lpMappedFileBase = (PVOID) CurrentContext;
RtlZeroMemory(CurrentContext, sizeof(PDH_LOGGER_CONTEXT));
for (i = 0; i < PDH_MAX_LOGFILES && pLogCurrent; i ++) {
CurrentContext->LogFileName[i] = pLogCurrent->szLogFileName;
pLogCurrent = pLogCurrent->NextLog;
}
CurrentContext->LogFileCount = i;
CurrentContext->LoggerCount = 0;
for (i = 0; i < (LONG) CurrentContext->LogFileCount; i ++) {
InitializeListHead(& CurrentContext->LogInfo[i].CounterPathList);
InitializeListHead(& CurrentContext->LogInfo[i].PerfMachineList);
}
CurrentContext->RefCount = 1;
CurrentContext->hSyncWMI = CreateEvent(NULL, FALSE, FALSE, NULL);
CurrentContext->hSyncPDH = CreateEvent(NULL, FALSE, FALSE, NULL);
if (CurrentContext->hSyncWMI == NULL || CurrentContext->hSyncPDH == NULL) {
Status = PDH_INVALID_HANDLE;
goto Cleanup;
}
Status = WAIT_FOR_AND_LOCK_MUTEX(hPdhContextMutex);
if (Status == ERROR_SUCCESS) {
if (ContextCount < PDH_MAX_LOGFILES) {
ContextTable[ContextCount] = CurrentContext;
ContextCount ++;
}
else {
Status = PDH_MEMORY_ALLOCATION_FAILURE;
}
RELEASE_MUTEX(hPdhContextMutex);
}
if (Status != ERROR_SUCCESS) {
goto Cleanup;
}
for (i = 0; i < (LONG) CurrentContext->LogFileCount; i ++) {
RtlZeroMemory(& EvmFile, sizeof(EVENT_TRACE_LOGFILE));
EvmFile.BufferCallback = PdhWmiFirstBufferCallback;
EvmFile.EventCallback = PdhWmiFirstEventCallback;
EvmFile.LogFileName = LogFileName;
_wfullpath(EvmFile.LogFileName,
CurrentContext->LogFileName[i],
PDH_MAX_PATH);
CurrentContext->LogFileHandle[i] = OpenTraceW(& EvmFile);
if ( CurrentContext->LogFileHandle[i] == 0
|| CurrentContext->LogFileHandle[i] ==
(TRACEHANDLE) INVALID_HANDLE_VALUE) {
DebugPrint((4,"OpenTraceW(%d,%ws) fails\n",
i,
CurrentContext->LogFileName[i]));
while (--i >= 0) {
CloseTrace(CurrentContext->LogFileHandle[i]);
}
Status = PDH_LOG_FILE_OPEN_ERROR;
goto Cleanup;
}
}
CurrentContext->hThreadWork = CreateThread(
NULL,
0,
(LPTHREAD_START_ROUTINE) PdhProcessLog,
CurrentContext,
0,
(LPDWORD) & ThreadId);
if (CurrentContext->hThreadWork == NULL) {
Status = GetLastError();
DebugPrint((4, "CreateThread() fails (%d,0x%08X)\n",
Status, Status));
for (i = 0; i < (LONG) CurrentContext->LogFileCount; i ++) {
Status = CloseTrace(CurrentContext->LogFileHandle[i]);
if (Status != ERROR_SUCCESS) {
DebugPrint((4, "CloseTrace(0x%08X,%ws) fails (%d,0x%08X)\n",
CurrentContext->LogFileHandle[i],
CurrentContext->LogFileName[i],
Status,
Status));
}
}
goto Cleanup;
}
WaitForSingleObject(CurrentContext->hSyncPDH, INFINITE);
Cleanup:
if (Status != ERROR_SUCCESS) {
if (CurrentContext != NULL) {
DWORD dwContext = GetLoggerContext(CurrentContext);
if (dwContext < ContextCount) {
if ( WAIT_FOR_AND_LOCK_MUTEX(hPdhContextMutex)
== ERROR_SUCCESS) {
if (dwContext != ContextCount - 1) {
ContextTable[dwContext] = ContextTable[ContextCount - 1];
}
ContextTable[ContextCount - 1] = NULL;
ContextCount --;
RELEASE_MUTEX(hPdhContextMutex);
}
else {
ContextTable[dwContext] = NULL;
}
}
if (CurrentContext->hSyncWMI) {
CloseHandle(CurrentContext->hSyncWMI);
}
if (CurrentContext->hSyncPDH) {
CloseHandle(CurrentContext->hSyncPDH);
}
G_FREE(CurrentContext);
CurrentContext = NULL;
}
pLog->lpMappedFileBase = NULL;
}
return Status;
}
PDH_FUNCTION
PdhiRewindWmiLog(
IN PPDHI_LOG pLog)
{
PDH_STATUS Status = PDH_INVALID_HANDLE;
PPDH_LOGGER_CONTEXT CurrentContext;
CurrentContext = (PPDH_LOGGER_CONTEXT) pLog->lpMappedFileBase;
if (GetLoggerContext(CurrentContext) < ContextCount) {
CurrentContext->LoggerState = PdhProcessTraceRewind;
SetEvent(CurrentContext->hSyncWMI);
WaitForSingleObject(CurrentContext->hSyncPDH, INFINITE);
Status = ERROR_SUCCESS;
}
return Status;
}
PDH_FUNCTION
PdhiReadWmiHeaderRecord(
IN PPDHI_LOG pLog,
IN LPVOID pRecord,
IN DWORD dwMaxSize)
{
PDH_STATUS Status = ERROR_SUCCESS;
PPDH_LOGGER_CONTEXT CurrentContext = (PPDH_LOGGER_CONTEXT) pLog->lpMappedFileBase;
if (GetLoggerContext(CurrentContext) >= ContextCount) {
return PDH_INVALID_HANDLE;
}
// Wait until logfiles are scaned first to collect
// 1) Counter Path information
// 2) Time Range information
//
while (CurrentContext->bFirstRun) {
_sleep(1);
}
Status = PdhiGetCounterPathRecord(CurrentContext, pRecord, dwMaxSize);
pLog->pLastRecordRead = CurrentContext->CounterPathBuffer;
return Status;
}
PDH_FUNCTION
PdhiBuildDataBlock(
IN PPDHI_LOG pLog,
IN ULONGLONG TimeStamp)
{
PDH_STATUS pdhStatus = ERROR_SUCCESS;
LONG Offset = sizeof(PDHI_BINARY_LOG_RECORD_HEADER);
LONG CopySize;
LONG CheckSize;
ULONG i;
LONG CurrentSize = PDH_WMI_BUFFER_SIZE_BYTE;
PPDH_LOGGER_CONTEXT CurrentContext;
PPDHI_BINARY_LOG_RECORD_HEADER pHeader;
PVOID pBlock;
PPDHI_BINARY_LOG_RECORD_HEADER pCounterHeader;
PPDH_RAW_COUNTER pSingleCounter;
PPDHI_LOG_COUNTER_PATH pCounterPath;
BOOLEAN bValidBlock;
CurrentContext = (PPDH_LOGGER_CONTEXT) pLog->lpMappedFileBase;
if (GetLoggerContext(CurrentContext) >= ContextCount) {
return PDH_INVALID_HANDLE;
}
if (CurrentContext->tmpBuffer != NULL) {
G_FREE(CurrentContext->tmpBuffer);
CurrentContext->tmpBuffer = NULL;
}
pHeader = (PPDHI_BINARY_LOG_RECORD_HEADER)
G_ALLOC(PDH_WMI_BUFFER_SIZE_BYTE);
if (pHeader == NULL) {
return PDH_MEMORY_ALLOCATION_FAILURE;
}
pHeader->dwType = BINLOG_TYPE_DATA;
for (i = 0; i < CurrentContext->LoggerCount; i ++) {
CopySize = CurrentContext->LogInfo[i].DataBlockSize
- sizeof(GUID) - sizeof(PDHI_BINARY_LOG_RECORD_HEADER);
bValidBlock = TRUE;
if (Offset + CopySize > CurrentSize) {
while (Offset + CopySize > CurrentSize) {
CurrentSize += PDH_WMI_BUFFER_SIZE_BYTE;
}
CurrentContext->tmpBuffer = pHeader;
pHeader = G_REALLOC(CurrentContext->tmpBuffer, CurrentSize);
if (pHeader == NULL) {
G_FREE(CurrentContext->tmpBuffer);
CurrentContext->tmpBuffer = NULL;
return PDH_MEMORY_ALLOCATION_FAILURE;
}
CurrentContext->tmpBuffer = NULL;
}
pBlock = (PVOID) (((PUCHAR) pHeader) + Offset);
if ( (CurrentContext->LogInfo[i].DataBlock)
&& (CopySize > 0)
&& ( DataBlockInfo.CurrentTime
<= CurrentContext->LogInfo[i].TimeEnd)) {
CheckSize = sizeof(GUID);
while (bValidBlock && CheckSize < CopySize) {
pCounterHeader = (PPDHI_BINARY_LOG_RECORD_HEADER)
(((PUCHAR) CurrentContext->LogInfo[i].DataBlock) + CheckSize);
if (LOWORD(pCounterHeader->dwType) == BINLOG_START_WORD) {
CheckSize += pCounterHeader->dwLength;
}
else {
bValidBlock = FALSE;
}
}
}
else {
bValidBlock = FALSE;
}
if (bValidBlock == TRUE) {
RtlCopyMemory(
pBlock,
(PVOID) ( ((PUCHAR) CurrentContext->LogInfo[i].DataBlock)
+ sizeof(GUID)
+ sizeof(PDHI_BINARY_LOG_RECORD_HEADER)),
CopySize);
Offset += CopySize;
}
else {
// need to sneak in pseudo counter block
//
PVOID pCounterBlock;
ULONG BlockSize = 0;
ULONG j;
for (j = 0; j < CurrentContext->LogInfo[i].ulCounters; j ++) {
pBlock = (PVOID) (((PUCHAR) pHeader) + Offset);
RtlCopyMemory(pBlock,
& PdhNullCounterHeader,
sizeof(PDHI_BINARY_LOG_RECORD_HEADER));
pSingleCounter = (PPDH_RAW_COUNTER) (((PUCHAR) pBlock)
+ sizeof(PDHI_BINARY_LOG_RECORD_HEADER));
RtlCopyMemory(pSingleCounter,
& PdhNullCounter,
sizeof(PDH_RAW_COUNTER));
pSingleCounter->TimeStamp.dwLowDateTime = LODWORD(TimeStamp);
pSingleCounter->TimeStamp.dwHighDateTime = HIDWORD(TimeStamp);
Offset = Offset + sizeof(PDH_RAW_COUNTER)
+ sizeof(PDHI_BINARY_LOG_RECORD_HEADER);
}
}
}
pHeader->dwLength = Offset;
CurrentContext->tmpBuffer = pHeader;
return pdhStatus;
}
PDH_FUNCTION
PdhiReadNextWmiRecord(
IN PPDHI_LOG pLog,
IN LPVOID pRecord,
IN DWORD dwMaxSize,
IN BOOLEAN bAllCounter)
{
PDH_STATUS Status = ERROR_SUCCESS;
PPDH_LOGGER_CONTEXT CurrentContext;
ULONGLONG CurrentTime;
CurrentContext = (PPDH_LOGGER_CONTEXT) pLog->lpMappedFileBase;
if (GetLoggerContext(CurrentContext) >= ContextCount) {
Status = PDH_INVALID_HANDLE;
goto Cleanup;
}
// Wait until logfiles are scaned first to collect
// 1) Counter Path information
// 2) Time Range information
//
while (CurrentContext->bFirstRun) {
_sleep(1);
}
if (CurrentContext->LoggerState == PdhProcessTraceComplete) {
CurrentContext->LoggerState = PdhProcessTraceRewind;
SetEvent(CurrentContext->hSyncWMI);
WaitForSingleObject(CurrentContext->hSyncPDH, INFINITE);
Status = PDH_END_OF_LOG_FILE;
goto Cleanup;
}
if (! CurrentContext->bFirstDataBlockRead) {
CurrentContext->bFirstDataBlockRead = TRUE;
CurrentContext->bDataBlockProcessed = TRUE;
}
else if (! CurrentContext->bDataBlockProcessed) {
CurrentContext->bDataBlockProcessed = TRUE;
}
else {
DataBlockInfo.CurrentTime = (ULONGLONG) 0;
SetEvent(CurrentContext->hSyncWMI);
WaitForSingleObject(CurrentContext->hSyncPDH, INFINITE);
}
if (CurrentContext->LoggerState == PdhProcessTraceComplete) {
CurrentContext->LoggerState = PdhProcessTraceRewind;
SetEvent(CurrentContext->hSyncWMI);
WaitForSingleObject(CurrentContext->hSyncPDH, INFINITE);
Status = PDH_END_OF_LOG_FILE;
goto Cleanup;
}
if (bAllCounter && CurrentContext->LogFileCount > 1) {
CurrentTime = DataBlockInfo.CurrentTime;
while ( (CurrentContext->LoggerState != PdhProcessTraceComplete)
&& (DataBlockInfo.CurrentTime - CurrentTime <= TIME_DELTA)) {
DataBlockInfo.CurrentTime = (ULONGLONG) 0;
SetEvent(CurrentContext->hSyncWMI);
WaitForSingleObject(CurrentContext->hSyncPDH, INFINITE);
}
CurrentContext->bDataBlockProcessed = FALSE;
Status = DataBlockInfo.Status;
if (Status == ERROR_SUCCESS) {
Status = PdhiBuildDataBlock(pLog, CurrentTime);
}
if (Status == ERROR_SUCCESS) {
pLog->pLastRecordRead = CurrentContext->tmpBuffer;
}
}
else {
if (bAllCounter) {
pLog->pLastRecordRead =
(((PUCHAR) DataBlockInfo.pRecord) + sizeof(GUID));
}
else {
pLog->pLastRecordRead = ((PUCHAR) DataBlockInfo.pRecord);
}
CurrentContext->bDataBlockProcessed = TRUE;
Status = DataBlockInfo.Status;
}
if (Status == ERROR_SUCCESS) {
if (dwMaxSize < DataBlockInfo.dwCurrentSize - sizeof(GUID)) {
Status = PDH_MORE_DATA;
}
if (pRecord) {
RtlCopyMemory(pRecord,
pLog->pLastRecordRead,
(Status == ERROR_SUCCESS) ? (DataBlockInfo.dwCurrentSize)
: (dwMaxSize));
}
}
Cleanup:
return Status;
}
PDH_FUNCTION
PdhiReadTimeWmiRecord(
IN PPDHI_LOG pLog,
IN ULONGLONG TimeStamp,
IN LPVOID pRecord,
IN DWORD dwMaxSize)
{
PDH_STATUS Status = ERROR_SUCCESS;
PPDH_LOGGER_CONTEXT CurrentContext;
BOOLEAN TimeInRange = FALSE;
BOOLEAN bRewind = TRUE;
ULONG i;
CurrentContext = (PPDH_LOGGER_CONTEXT) pLog->lpMappedFileBase;
if (GetLoggerContext(CurrentContext) >= ContextCount) {
Status = PDH_INVALID_HANDLE;
goto Cleanup;
}
if (TimeStamp == MIN_TIME_VALUE) {
TimeStamp = CurrentContext->LogInfo[0].TimeStart;
}
if (TimeStamp == MAX_TIME_VALUE) {
TimeStamp = CurrentContext->LogInfo[0].TimeEnd;
}
for (i = 0; i < (ULONG) CurrentContext->LoggerCount; i ++) {
if ( TimeStamp >= CurrentContext->LogInfo[i].TimeStart
&& TimeStamp <= CurrentContext->LogInfo[i].TimeEnd) {
TimeInRange = TRUE;
break;
}
}
if (! TimeInRange) {
Status = PDH_INVALID_ARGUMENT;
goto Cleanup;
}
// Wait until logfiles are scaned first to collect
// 1) Counter Path information
// 2) Time Range information
//
while (CurrentContext->bFirstRun) {
_sleep(1);
}
if (CurrentContext->LoggerState == PdhProcessTraceComplete) {
CurrentContext->LoggerState = PdhProcessTraceRewind;
SetEvent(CurrentContext->hSyncWMI);
WaitForSingleObject(CurrentContext->hSyncPDH, INFINITE);
Status = PDH_END_OF_LOG_FILE;
goto Cleanup;
}
ReScan:
if (! CurrentContext->bFirstDataBlockRead) {
CurrentContext->bFirstDataBlockRead = TRUE;
CurrentContext->bDataBlockProcessed = TRUE;
}
else if (! CurrentContext->bDataBlockProcessed) {
CurrentContext->bDataBlockProcessed = TRUE;
}
else {
DataBlockInfo.CurrentTime = 0;
SetEvent(CurrentContext->hSyncWMI);
WaitForSingleObject(CurrentContext->hSyncPDH, INFINITE);
}
if (CurrentContext->LoggerState == PdhProcessTraceComplete) {
CurrentContext->LoggerState = PdhProcessTraceRewind;
SetEvent(CurrentContext->hSyncWMI);
WaitForSingleObject(CurrentContext->hSyncPDH, INFINITE);
Status = PDH_END_OF_LOG_FILE;
goto Cleanup;
}
else if (DataBlockInfo.CurrentTime > TimeStamp) {
if (bRewind) {
bRewind = FALSE;
CurrentContext->LoggerState = PdhProcessTraceRewind;
SetEvent(CurrentContext->hSyncWMI);
WaitForSingleObject(CurrentContext->hSyncPDH, INFINITE);
goto ReScan;
}
}
while ( (CurrentContext->LoggerState != PdhProcessTraceComplete)
&& (( ((LONGLONG) TimeStamp)
- ((LONGLONG) DataBlockInfo.CurrentTime))
> TIME_DELTA)) {
DataBlockInfo.CurrentTime = (ULONGLONG) 0;
SetEvent(CurrentContext->hSyncWMI);
WaitForSingleObject(CurrentContext->hSyncPDH, INFINITE);
}
CurrentContext->bDataBlockProcessed = TRUE;
Status = DataBlockInfo.Status;
if (Status == ERROR_SUCCESS) {
Status = PdhiBuildDataBlock(pLog, TimeStamp);
}
if (Status == ERROR_SUCCESS) {
pLog->pLastRecordRead = CurrentContext->tmpBuffer;
}
if (Status == ERROR_SUCCESS) {
if (dwMaxSize < DataBlockInfo.dwCurrentSize - sizeof(GUID)) {
Status = PDH_MORE_DATA;
}
if (pRecord) {
RtlCopyMemory(pRecord,
(((PUCHAR) DataBlockInfo.pRecord) + sizeof(GUID)),
(Status == ERROR_SUCCESS) ? (DataBlockInfo.dwCurrentSize)
: (dwMaxSize));
}
}
Cleanup:
return Status;
}
PDH_FUNCTION
PdhiGetTimeRangeFromWmiLog (
IN PPDHI_LOG pLog,
IN LPDWORD pdwNumEntries,
IN PPDH_TIME_INFO pInfo,
IN LPDWORD pdwBufferSize)
{
PDH_STATUS Status = ERROR_SUCCESS;
PPDH_LOGGER_CONTEXT CurrentContext;
ULONG i;
ULONGLONG StartTime;
ULONGLONG EndTime;
ULONG EntryCount;
CurrentContext = (PPDH_LOGGER_CONTEXT) pLog->lpMappedFileBase;
if (GetLoggerContext(CurrentContext) >= ContextCount) {
return PDH_INVALID_HANDLE;
}
// Wait until logfiles are scaned first to collect
// 1) Counter Path information
// 2) Time Range information
//
while (CurrentContext->bFirstRun) {
_sleep(1);
}
for (StartTime = CurrentContext->LogInfo[0].TimeStart,
EndTime = CurrentContext->LogInfo[0].TimeEnd,
EntryCount = CurrentContext->LogInfo[0].ValidEntries,
i = 1;
i < CurrentContext->LoggerCount;
i ++) {
if ( StartTime == 0
|| ( CurrentContext->LogInfo[i].TimeStart != 0
&& StartTime > CurrentContext->LogInfo[i].TimeStart)) {
StartTime = CurrentContext->LogInfo[i].TimeStart;
}
if (EndTime < CurrentContext->LogInfo[i].TimeEnd)
EndTime = CurrentContext->LogInfo[i].TimeEnd;
EntryCount += CurrentContext->LogInfo[i].ValidEntries;
}
if (* pdwBufferSize >= sizeof(PDH_TIME_INFO)) {
* (LONGLONG *) (& pInfo->StartTime) = StartTime;
* (LONGLONG *) (& pInfo->EndTime) = EndTime;
pInfo->SampleCount = EntryCount;
* pdwBufferSize = sizeof(PDH_TIME_INFO);
* pdwNumEntries = 1;
}
else {
Status = PDH_MORE_DATA;
}
return Status;
}
PPDH_WMI_PERF_MACHINE
PdhWmiGetLogNameTable(
IN PPDHI_LOG pLog,
IN LPCWSTR szMachineName,
IN DWORD dwLangId
)
{
PPDH_WMI_PERF_MACHINE pReturnMachine = NULL;
PPDH_LOGGER_CONTEXT CurrentContext;
DWORD i;
CurrentContext = (PPDH_LOGGER_CONTEXT) pLog->lpMappedFileBase;
if (GetLoggerContext(CurrentContext) >= ContextCount) {
return NULL;
}
for (i = 0;
pReturnMachine == NULL && i < CurrentContext->LoggerCount;
i ++) {
if (! IsListEmpty(& CurrentContext->LogInfo[i].PerfMachineList)) {
PLIST_ENTRY pHead = & CurrentContext->LogInfo[i].PerfMachineList;
PLIST_ENTRY pNext = pHead->Flink;
while (pNext != pHead) {
PPDH_WMI_PERF_MACHINE pMachine =
CONTAINING_RECORD(pNext, PDH_WMI_PERF_MACHINE, Entry);
if (lstrcmpiW(pMachine->pszBuffer, szMachineName) == 0) {
pReturnMachine = pMachine;
break;
}
pNext = pNext->Flink;
}
}
}
return pReturnMachine;
}
PPDH_WMI_PERF_OBJECT
PdhWmiAddPerfObject(
IN PPDHI_LOG pLog,
IN LPCWSTR szMachineName,
IN DWORD dwLangId,
IN LPCWSTR szObjectName,
IN DWORD dwObjectId,
IN PPERF_DATA_BLOCK pDataBlock
)
{
PPDH_WMI_PERF_OBJECT pPerfObject = NULL;
PPDH_WMI_PERF_MACHINE pPerfMachine =
PdhWmiGetLogNameTable(pLog, szMachineName, dwLangId);
PLIST_ENTRY pHead;
PLIST_ENTRY pNext;
PPDH_WMI_PERF_OBJECT pCurrentObj;
if (pPerfMachine == NULL) {
SetLastError(PDH_ENTRY_NOT_IN_LOG_FILE);
goto Cleanup;
}
pHead = & pPerfMachine->LogObjectList;
pNext = pHead->Flink;
while (pNext != pHead) {
pCurrentObj = CONTAINING_RECORD(pNext, PDH_WMI_PERF_OBJECT, Entry);
if (lstrcmpiW(pCurrentObj->szObjectName, szObjectName) == 0) {
pPerfObject = pCurrentObj;
break;
}
pNext = pNext->Flink;
}
if (pPerfObject != NULL) {
goto Cleanup;
}
pPerfObject = G_ALLOC(sizeof(PDH_WMI_PERF_OBJECT));
if (pPerfObject == NULL) {
SetLastError(PDH_MEMORY_ALLOCATION_FAILURE);
goto Cleanup;
}
pPerfObject->ptrBuffer = G_ALLOC(pDataBlock->TotalByteLength
+ sizeof(WCHAR) * (lstrlenW(szObjectName) + 1));
if (pPerfObject->ptrBuffer == NULL) {
G_FREE(pPerfObject);
SetLastError(PDH_MEMORY_ALLOCATION_FAILURE);
goto Cleanup;
}
pPerfObject->dwObjectId = dwObjectId;
RtlCopyMemory(pPerfObject->ptrBuffer,
pDataBlock,
pDataBlock->TotalByteLength);
pPerfObject->szObjectName = (LPWSTR)
(((LPBYTE) pPerfObject->ptrBuffer) + pDataBlock->TotalByteLength);
lstrcpyW(pPerfObject->szObjectName, szObjectName);
InsertTailList(& pPerfMachine->LogObjectList, & pPerfObject->Entry);
Cleanup:
return pPerfObject;
}
DWORD
PdhWmiGetLogPerfIndexByName(
IN PPDHI_LOG pLog,
IN LPCWSTR szMachineName,
IN DWORD dwLangId,
IN LPCWSTR szNameBuffer
)
{
PPDH_WMI_PERF_MACHINE pMachine;
DWORD dwLastIndex;
LPWSTR * pNameArray;
DWORD dwIndex;
SetLastError(ERROR_SUCCESS);
pMachine = PdhWmiGetLogNameTable(pLog, szMachineName, dwLangId);
if (pMachine != NULL && pMachine->ptrStrAry != NULL) {
dwLastIndex = pMachine->dwLastId;
pNameArray = pMachine->ptrStrAry;
for (dwIndex = 1; dwIndex <= dwLastIndex; dwIndex ++) {
if (lstrcmpiW(szNameBuffer, pNameArray[dwIndex]) == 0) {
if ((dwIndex & 0x00000001) == 0) {
// counter name index should be even integer
//
break;
}
}
}
if (dwIndex > dwLastIndex) {
SetLastError(PDH_STRING_NOT_FOUND);
dwIndex = 0;
}
}
else {
SetLastError(PDH_ENTRY_NOT_IN_LOG_FILE);
dwIndex = 0;
}
return dwIndex;
}
LPWSTR
PdhWmiGetLogPerfNameByIndex (
IN PPDHI_LOG pLog,
IN LPCWSTR szMachineName,
IN DWORD dwLangId,
IN DWORD dwIndex
)
{
PPDH_WMI_PERF_MACHINE pMachine;
LPWSTR pszReturnName = NULL;
LPWSTR * pNameArray;
static WCHAR szNumber[16];
pMachine = PdhWmiGetLogNameTable(pLog, szMachineName, dwLangId);
if (pMachine != NULL && pMachine->ptrStrAry != NULL
&& dwIndex < pMachine->dwLastId) {
pNameArray = pMachine->ptrStrAry;
pszReturnName = pNameArray[dwIndex];
}
if (pszReturnName == NULL) {
// unable to find name string, return numeric index string
//
memset(szNumber, 0, sizeof (szNumber));
_ltow(dwIndex, szNumber, 10);
pszReturnName = szNumber;
}
return pszReturnName;
}
PPDHI_BINARY_LOG_RECORD_HEADER
PdhiGetWmiSubRecord(
IN PPDHI_LOG pLog,
IN PPDHI_BINARY_LOG_RECORD_HEADER pRecord,
IN DWORD dwRecordId,
IN LPGUID LogFileGuid)
{
PPDHI_BINARY_LOG_RECORD_HEADER pThisRecord;
PPDH_LOGGER_CONTEXT CurrentContext;
DWORD dwRecordType;
DWORD dwRecordLength;
DWORD dwBytesProcessed;
DWORD dwThisSubRecordId;
DWORD dwLocalIndex;
ULONG i;
CurrentContext = (PPDH_LOGGER_CONTEXT) pLog->lpMappedFileBase;
if (GetLoggerContext(CurrentContext) >= ContextCount) {
return (NULL);
}
dwLocalIndex = dwRecordId;
for (i = 0; i < CurrentContext->LoggerCount; i ++) {
PLIST_ENTRY pHead = & CurrentContext->LogInfo[i].CounterPathList;
if (! IsListEmpty(pHead)) {
PLIST_ENTRY pNext = pHead->Flink;
PPDH_COUNTER_PATH pCounterPath =
CONTAINING_RECORD(pNext, PDH_COUNTER_PATH, Entry);
if (dwLocalIndex <= pCounterPath->CounterCount) {
break;
}
dwLocalIndex -= pCounterPath->CounterCount;
}
}
assert(i < CurrentContext->LoggerCount);
__try {
if ( (i >= CurrentContext->LoggerCount)
|| (! IsEqualGUID( LogFileGuid,
& CurrentContext->LogInfo[i].LogFileGuid))) {
// binary log record does not contain intended object's counter
//
return NULL;
}
}
__except(EXCEPTION_EXECUTE_HANDLER) {
return NULL;
}
dwRecordType = ((PPDHI_BINARY_LOG_RECORD_HEADER) pRecord)->dwType;
dwRecordLength = ((PPDHI_BINARY_LOG_RECORD_HEADER) pRecord)->dwLength;
pThisRecord = (PPDHI_BINARY_LOG_RECORD_HEADER)
(((LPBYTE) pRecord) + sizeof(PDHI_BINARY_LOG_RECORD_HEADER));
dwBytesProcessed = sizeof(PDHI_BINARY_LOG_RECORD_HEADER);
if (dwBytesProcessed < dwRecordLength) {
dwThisSubRecordId = 1;
while (dwThisSubRecordId < dwLocalIndex) {
if ((WORD)(pThisRecord->dwType & 0x0000FFFF) == BINLOG_START_WORD) {
dwBytesProcessed += pThisRecord->dwLength;
pThisRecord = (PPDHI_BINARY_LOG_RECORD_HEADER)
(((LPBYTE)pThisRecord) + pThisRecord->dwLength);
if (dwBytesProcessed >= dwRecordLength) {
break;
}
else {
dwThisSubRecordId ++;
}
}
else {
break;
}
}
}
else {
dwThisSubRecordId = 0;
}
if (dwThisSubRecordId == dwLocalIndex) {
if ((WORD)(pThisRecord->dwType & 0x0000FFFF) != BINLOG_START_WORD) {
pThisRecord = NULL;
}
}
else {
pThisRecord = NULL;
}
return pThisRecord;
}
PDH_FUNCTION
PdhWmiEnumObjectItemsFromDataBlock(
IN PPDHI_LOG pLog,
IN PPERF_DATA_BLOCK pDataBlock,
IN LPCWSTR szMachineName,
IN LPCWSTR szObjectName,
IN DWORD dwObjectId,
IN DWORD dwLangId,
IN PDHI_COUNTER_TABLE CounterTable
)
{
PDH_STATUS Status = ERROR_SUCCESS;
PERF_OBJECT_TYPE * pObjectDef = GetObjectDefByTitleIndex(pDataBlock, dwObjectId);
PERF_COUNTER_DEFINITION * pCountDef;
PERF_INSTANCE_DEFINITION * pInstDef;
DWORD dwItems;
LPWSTR szItemName;
DWORD dwItemLen;
WCHAR szInstanceName[1024];
PPDHI_INST_LIST pInstList = NULL;
PPDHI_INSTANCE pInstance = NULL;
PPDHI_INST_LIST pFirstInstList = NULL;
PPDH_WMI_PERF_OBJECT pPerfObj;
if (pObjectDef == NULL) {
Status = PDH_ENTRY_NOT_IN_LOG_FILE;
goto Cleanup;
}
pPerfObj = PdhWmiAddPerfObject(pLog,
szMachineName,
9,
szObjectName,
dwObjectId,
pDataBlock);
if (pPerfObj == NULL) {
Status = GetLastError();
goto Cleanup;
}
dwItems = 0;
pCountDef = FirstCounter(pObjectDef);
while (dwItems < (DWORD) pObjectDef->NumCounters) {
szItemName = PdhWmiGetLogPerfNameByIndex(
pLog,
szMachineName,
dwLangId,
pCountDef->CounterNameTitleIndex);
Status = PdhiFindCounterInstList(
CounterTable, szItemName, & pInstList);
if (Status == ERROR_SUCCESS && pFirstInstList == NULL
&& pInstList != NULL) {
pFirstInstList = pInstList;
}
dwItems ++;
pCountDef = NextCounter(pCountDef);
}
if (pFirstInstList == NULL) {
Status = PDH_NO_COUNTERS;
goto Cleanup;
}
if (pObjectDef->NumInstances != PERF_NO_INSTANCES) {
dwItems = 0;
pInstDef = FirstInstance(pObjectDef);
while (dwItems < (DWORD) pObjectDef->NumInstances) {
ZeroMemory(szInstanceName, sizeof(WCHAR) * 1024);
dwItemLen = GetFullInstanceNameStr(
pDataBlock,
pObjectDef,
pInstDef,
szInstanceName);
if (dwItemLen > 0) {
Status = PdhiFindInstance(
& pFirstInstList->InstList,
szInstanceName,
(lstrcmpiW(szInstanceName, L"_Total") == 0) ? FALSE : TRUE,
& pInstance);
}
dwItems ++;
pInstDef = NextInstance(pInstDef);
}
}
Cleanup:
return Status;
}
PDH_FUNCTION
PdhiEnumObjectItemsFromWmiLog (
IN PPDHI_LOG pLog,
IN LPCWSTR szMachineName,
IN LPCWSTR szObjectName,
IN PDHI_COUNTER_TABLE CounterTable,
IN DWORD dwDetailLevel,
IN DWORD dwFlags
)
{
DWORD dwTempBufferSize;
LPVOID pTempBuffer = NULL;
LPVOID ptrTemp;
PDH_STATUS pdhStatus = ERROR_SUCCESS;
PPDHI_BINARY_LOG_HEADER_RECORD pHeader;
PPDHI_LOG_COUNTER_PATH pPath;
PPDHI_BINARY_LOG_RECORD_HEADER pThisMasterRecord;
PPDHI_BINARY_LOG_RECORD_HEADER pThisSubRecord;
PPDHI_RAW_COUNTER_ITEM_BLOCK pDataBlock;
PPDHI_RAW_COUNTER_ITEM pDataItem;
DWORD dwBytesProcessed;
LONG nItemCount = 0;
LPBYTE pFirstChar;
LPWSTR szThisMachineName = NULL;
LPWSTR szThisObjectName = NULL;
LPWSTR szThisCounterName = NULL;
LPWSTR szThisInstanceName = NULL;
LPWSTR szThisParentName;
WCHAR szCompositeInstance[1024];
DWORD dwRecordLength;
BOOL bCopyThisObject;
BOOL bMachineDataBlockScaned = FALSE;
BOOL bInstanceListScanned = FALSE;
DWORD dwIndex;
DWORD dwDataItemIndex;
DWORD dwObjectId;
PPERF_DATA_BLOCK pPerfBlock;
PPDHI_INST_LIST pInstList = NULL;
PPDHI_INSTANCE pInstance = NULL;
PPDH_LOGGER_CONTEXT CurrentContext;
UNREFERENCED_PARAMETER (dwDetailLevel);
UNREFERENCED_PARAMETER (dwFlags);
CurrentContext = (PPDH_LOGGER_CONTEXT) pLog->lpMappedFileBase;
if (GetLoggerContext(CurrentContext) >= ContextCount) {
pdhStatus = PDH_INVALID_ARGUMENT;
goto Cleanup;
}
if (pLog->dwMaxRecordSize == 0) {
// no size is defined so start with 64K
pLog->dwMaxRecordSize = 0x010000;
}
dwTempBufferSize = pLog->dwMaxRecordSize;
pTempBuffer = G_ALLOC(dwTempBufferSize);
if (pTempBuffer == NULL) {
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
goto Cleanup;
}
// read in the catalog record
pdhStatus = PdhiReadWmiHeaderRecord(pLog, pTempBuffer, dwTempBufferSize);
while (pdhStatus == PDH_MORE_DATA) {
if (* (WORD *) pTempBuffer == BINLOG_START_WORD) {
dwTempBufferSize = ((DWORD *) pTempBuffer)[1];
if (dwTempBufferSize < pLog->dwMaxRecordSize) {
pdhStatus = PDH_ENTRY_NOT_IN_LOG_FILE;
}
else {
pLog->dwMaxRecordSize = dwTempBufferSize;
}
}
else {
pdhStatus = PDH_ENTRY_NOT_IN_LOG_FILE;
}
ptrTemp = pTempBuffer;
pTempBuffer = G_REALLOC(ptrTemp, dwTempBufferSize);
if (pTempBuffer == NULL) {
G_FREE(ptrTemp);
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
}
if (pdhStatus == PDH_MORE_DATA) {
pdhStatus = PdhiReadWmiHeaderRecord(
pLog, pTempBuffer, dwTempBufferSize);
}
}
if (pdhStatus != ERROR_SUCCESS) {
goto Cleanup;
}
pHeader = (PPDHI_BINARY_LOG_HEADER_RECORD) pTempBuffer;
dwRecordLength = ((PPDHI_BINARY_LOG_RECORD_HEADER) pTempBuffer)->dwLength;
pPath = (PPDHI_LOG_COUNTER_PATH)
((LPBYTE) pTempBuffer + sizeof(PDHI_BINARY_LOG_HEADER_RECORD));
dwBytesProcessed = sizeof(PDHI_BINARY_LOG_HEADER_RECORD);
dwIndex = 0;
while (dwBytesProcessed < dwRecordLength) {
bCopyThisObject = FALSE;
szThisObjectName = NULL;
dwIndex ++;
pFirstChar = (LPBYTE) & pPath->Buffer[0];
if (pPath->lMachineNameOffset >= 0L) {
szThisMachineName = (LPWSTR) ( (LPBYTE) pFirstChar
+ pPath->lMachineNameOffset);
if (lstrcmpiW(szThisMachineName, szMachineName) == 0) {
if (pPath->dwFlags & PDHIC_COUNTER_BLOCK) {
if (bMachineDataBlockScaned == FALSE) {
bCopyThisObject = TRUE;
bMachineDataBlockScaned = TRUE;
}
}
else if (pPath->lObjectNameOffset >= 0) {
szThisObjectName = (LPWSTR) ( (LPBYTE) pFirstChar
+ pPath->lObjectNameOffset);
if (lstrcmpiW(szThisObjectName, szObjectName) == 0) {
bCopyThisObject = TRUE;
}
}
}
}
else if (pPath->lObjectNameOffset >= 0) {
szThisObjectName = (LPWSTR) ( (LPBYTE) pFirstChar
+ pPath->lObjectNameOffset);
if (lstrcmpiW(szThisObjectName, szObjectName) == 0) {
bCopyThisObject = TRUE;
}
}
dwObjectId = 0;
if (bCopyThisObject) {
if ( (pPath->dwFlags & PDHIC_COUNTER_OBJECT)
|| (pPath->dwFlags & PDHIC_COUNTER_BLOCK)) {
dwObjectId = PdhWmiGetLogPerfIndexByName(
pLog, szMachineName, 9, szObjectName);
if (dwObjectId == 0) {
dwObjectId = wcstoul(szObjectName, NULL, 10);
if (dwObjectId == 0) {
szThisCounterName = NULL;
bCopyThisObject = FALSE;
}
}
}
else if (pPath->lCounterOffset > 0) {
szThisCounterName = (LPWSTR) ( (LPBYTE)pFirstChar
+ pPath->lCounterOffset);
}
else {
szThisCounterName = NULL;
bCopyThisObject = FALSE;
}
}
if (bCopyThisObject) {
if (dwObjectId == 0) {
pdhStatus = PdhiFindCounterInstList(
CounterTable,
szThisCounterName,
& pInstList);
if (pdhStatus == ERROR_SUCCESS && pInstList != NULL) {
nItemCount ++;
}
}
if (pPath->lInstanceOffset >= 0) {
szThisInstanceName = (LPWSTR) ( (LPBYTE) pFirstChar
+ pPath->lInstanceOffset);
}
if ( dwObjectId > 0
|| (pInstList != NULL && szThisInstanceName != NULL)) {
if (szThisInstanceName && * szThisInstanceName != SPLAT_L) {
if (pPath->lParentOffset >= 0) {
szThisParentName = (LPWSTR)
((LPBYTE) pFirstChar + pPath->lParentOffset);
lstrcpyW(szCompositeInstance, szThisParentName);
lstrcatW(szCompositeInstance, cszSlash);
lstrcatW(szCompositeInstance, szThisInstanceName);
}
else {
lstrcpyW(szCompositeInstance, szThisInstanceName);
}
if (pPath->dwIndex > 0 && pPath->dwIndex != PERF_NO_UNIQUE_ID) {
lstrcatW(szCompositeInstance, L"#");
_ltow(pPath->dwIndex,
(LPWSTR)( szCompositeInstance
+ lstrlenW(szCompositeInstance)),
10L);
}
pdhStatus = PdhiFindInstance(
& pInstList->InstList,
szCompositeInstance,
(lstrcmpiW(szCompositeInstance, L"_Total") == 0)
? FALSE : TRUE,
& pInstance);
if (pdhStatus == ERROR_SUCCESS && pInstance != NULL) {
nItemCount ++;
}
}
else if (dwObjectId > 0 || !bInstanceListScanned) {
pdhStatus = PdhiRewindWmiLog(pLog);
if (pdhStatus == ERROR_SUCCESS) {
pdhStatus = PdhiReadNextWmiRecord(
pLog, NULL, 0, FALSE);
while ( pdhStatus == ERROR_SUCCESS
|| pdhStatus == PDH_MORE_DATA) {
PdhiResetInstanceCount(CounterTable);
pdhStatus = ERROR_SUCCESS;
pThisMasterRecord =
(PPDHI_BINARY_LOG_RECORD_HEADER)
( ((PUCHAR) pLog->pLastRecordRead)
+ sizeof(GUID));
pThisSubRecord = PdhiGetWmiSubRecord(
pLog,
pThisMasterRecord,
dwIndex,
(LPGUID)(pLog->pLastRecordRead));
if (pThisSubRecord == NULL) {
// this data record does not contain
// counter record for selected object,
// skip to next one.
//
pdhStatus = PdhiReadNextWmiRecord(
pLog, NULL, 0, FALSE);
continue;
}
if (pThisSubRecord->dwType == BINLOG_TYPE_DATA_OBJECT
|| pThisSubRecord->dwType == BINLOG_TYPE_DATA_LOC_OBJECT) {
pPerfBlock = (PPERF_DATA_BLOCK)
((LPBYTE)pThisSubRecord +
sizeof (PDHI_BINARY_LOG_RECORD_HEADER));
pdhStatus = PdhWmiEnumObjectItemsFromDataBlock(
pLog,
pPerfBlock,
szMachineName,
szObjectName,
dwObjectId,
9,
CounterTable);
if (pdhStatus == PDH_ENTRY_NOT_IN_LOG_FILE) {
pdhStatus = ERROR_SUCCESS;
}
}
else {
pDataBlock = (PPDHI_RAW_COUNTER_ITEM_BLOCK)
((LPBYTE)pThisSubRecord +
sizeof (PDHI_BINARY_LOG_RECORD_HEADER));
if (pDataBlock->dwLength > 0) {
for (dwDataItemIndex = 0;
dwDataItemIndex < pDataBlock->dwItemCount;
dwDataItemIndex++) {
pDataItem = & pDataBlock->pItemArray[dwDataItemIndex];
szThisInstanceName = (LPWSTR)
(((LPBYTE) pDataBlock) + pDataItem->szName);
pdhStatus = PdhiFindInstance(
& pInstList->InstList,
szThisInstanceName,
(lstrcmpiW(szThisInstanceName, L"_Total") == 0)
? FALSE : TRUE,
& pInstance);
if (pdhStatus == ERROR_SUCCESS) {
nItemCount++;
}
}
}
}
if (pdhStatus != ERROR_SUCCESS) {
break;
}
else {
pdhStatus = PdhiReadNextWmiRecord(pLog, NULL, 0, FALSE);
}
}
if (pdhStatus == PDH_END_OF_LOG_FILE) {
pdhStatus = ERROR_SUCCESS;
}
if (pdhStatus == ERROR_SUCCESS) {
bInstanceListScanned = TRUE;
}
}
}
}
}
ZeroMemory(szCompositeInstance, sizeof(szCompositeInstance));
dwBytesProcessed += pPath->dwLength;
pPath = (PPDHI_LOG_COUNTER_PATH) ( (LPBYTE) pPath
+ pPath->dwLength);
}
if ((nItemCount > 0) && (pdhStatus != PDH_INSUFFICIENT_BUFFER)
&& (pdhStatus != PDH_MORE_DATA)) {
pdhStatus = ERROR_SUCCESS;
}
Cleanup:
if (pTempBuffer != NULL)
G_FREE(pTempBuffer);
return pdhStatus;
}
PDH_FUNCTION
PdhiGetWmiLogCounterInfo(
IN PPDHI_LOG pLog,
IN PPDHI_COUNTER pCounter)
{
PDH_STATUS Status = ERROR_SUCCESS;
DWORD dwObjectId = PdhWmiGetLogPerfIndexByName(
pLog,
pCounter->pCounterPath->szMachineName,
9,
pCounter->pCounterPath->szObjectName);
DWORD dwCounterId = wcstoul(pCounter->pCounterPath->szCounterName,
NULL, 10);
PPDH_WMI_PERF_MACHINE pMachine = NULL;
PPDH_WMI_PERF_OBJECT pObject = NULL;
PLIST_ENTRY pHead;
PLIST_ENTRY pNext;
PPERF_DATA_BLOCK pDataBlock = NULL;
PERF_OBJECT_TYPE * pPerfObject = NULL;
DWORD dwItems = 0;
PERF_COUNTER_DEFINITION * pPerfCounter;
PERF_INSTANCE_DEFINITION * pPerfInstance;
PPDH_LOGGER_CONTEXT CurrentContext;
BOOL bNeedEnumerate = TRUE;
CurrentContext = (PPDH_LOGGER_CONTEXT) pLog->lpMappedFileBase;
if (GetLoggerContext(CurrentContext) < ContextCount) {
pMachine = PdhWmiGetLogNameTable(pLog,
pCounter->pCounterPath->szMachineName,
9);
if (pMachine == NULL) {
Status = PDH_ENTRY_NOT_IN_LOG_FILE;
goto Cleanup;
}
pHead = & pMachine->LogObjectList;
pNext = pHead->Flink;
while (pNext != pHead) {
pObject = CONTAINING_RECORD(pNext, PDH_WMI_PERF_OBJECT, Entry);
if (pObject->dwObjectId == dwObjectId) {
bNeedEnumerate = FALSE;
break;
}
pNext = pNext->Flink;
}
if (bNeedEnumerate) {
DWORD dwCounterSize = 0;
DWORD dwInstanceSize = 0;
Status = PdhiEnumLoggedObjectItems(
(HLOG) pLog,
pCounter->pCounterPath->szMachineName,
pCounter->pCounterPath->szObjectName,
NULL,
& dwCounterSize,
NULL,
& dwInstanceSize,
0,
0,
TRUE);
if (Status != ERROR_SUCCESS && Status != PDH_MORE_DATA
&& Status != PDH_INSUFFICIENT_BUFFER) {
goto Cleanup;
}
Status = ERROR_SUCCESS;
}
}
else {
Status = PDH_INVALID_ARGUMENT;
goto Cleanup;
}
if (dwObjectId == 0) {
dwObjectId = wcstoul(pCounter->pCounterPath->szObjectName, NULL, 10);
if (dwObjectId != 0) {
Status = ERROR_SUCCESS;
}
else {
Status = PDH_ENTRY_NOT_IN_LOG_FILE;
}
}
else {
Status = ERROR_SUCCESS;
}
if (Status != ERROR_SUCCESS) {
goto Cleanup;
}
pMachine = PdhWmiGetLogNameTable(pLog,
pCounter->pCounterPath->szMachineName,
9);
if (pMachine == NULL) {
Status = PDH_ENTRY_NOT_IN_LOG_FILE;
goto Cleanup;
}
pHead = & pMachine->LogObjectList;
pNext = pHead->Flink;
while (pNext != pHead) {
PPDH_WMI_PERF_OBJECT pThisObject = CONTAINING_RECORD(
pNext, PDH_WMI_PERF_OBJECT, Entry);
if (pThisObject->dwObjectId == dwObjectId) {
pObject = pThisObject;
break;
}
pNext = pNext->Flink;
}
if (pObject == NULL) {
Status = PDH_ENTRY_NOT_IN_LOG_FILE;
goto Cleanup;
}
pDataBlock = (PPERF_DATA_BLOCK) pObject->ptrBuffer;
if (pDataBlock == NULL) {
Status = PDH_ENTRY_NOT_IN_LOG_FILE;
goto Cleanup;
}
pPerfObject = GetObjectDefByTitleIndex(pDataBlock, dwObjectId);
if (pPerfObject == NULL) {
Status = PDH_CSTATUS_NO_OBJECT;
goto Cleanup;
}
dwItems = 0;
pPerfCounter = FirstCounter(pPerfObject);
while (dwItems < pPerfObject->NumCounters) {
if ( pPerfCounter->CounterNameTitleIndex > 0
&& pPerfCounter->CounterNameTitleIndex <= pMachine->dwLastId) {
if (lstrcmpiW(pCounter->pCounterPath->szCounterName,
pMachine->ptrStrAry[pPerfCounter->CounterNameTitleIndex])
== 0) {
break;
}
if ( dwCounterId != 0
&& dwCounterId == pPerfCounter->CounterNameTitleIndex) {
break;
}
}
dwItems ++;
if (dwItems < pPerfObject->NumCounters) {
pPerfCounter = NextCounter(pPerfCounter);
if (pPerfCounter == NULL) {
break;
}
}
else {
pPerfCounter = NULL;
}
}
if (dwItems == pPerfObject->NumCounters) {
pPerfCounter = NULL;
}
if (pPerfCounter == NULL) {
Status = PDH_CSTATUS_NO_OBJECT;
goto Cleanup;
}
pCounter->plCounterInfo.dwObjectId = dwObjectId;
pCounter->plCounterInfo.dwCounterId = pPerfCounter->CounterNameTitleIndex;
pCounter->plCounterInfo.dwCounterType = pPerfCounter->CounterType;
pCounter->plCounterInfo.dwCounterSize = pPerfCounter->CounterSize;
pCounter->plCounterInfo.lDefaultScale = pPerfCounter->DefaultScale;
if (pCounter->plCounterInfo.dwCounterType & PERF_TIMER_100NS) {
pCounter->TimeBase = (LONGLONG) 10000000;
}
else if (pCounter->plCounterInfo.dwCounterType & PERF_OBJECT_TIMER) {
pCounter->TimeBase = pPerfObject->PerfFreq.QuadPart;
}
else {
pCounter->TimeBase = pDataBlock->PerfFreq.QuadPart;
}
if (pPerfObject->NumInstances == PERF_NO_INSTANCES) {
pCounter->plCounterInfo.lInstanceId = 0;
pCounter->plCounterInfo.szInstanceName = NULL;
pCounter->plCounterInfo.dwParentObjectId = 0;
pCounter->plCounterInfo.szParentInstanceName = NULL;
}
else {
pPerfInstance = FirstInstance(pPerfObject);
if (pPerfInstance->UniqueID == PERF_NO_UNIQUE_ID) {
pCounter->plCounterInfo.lInstanceId = PERF_NO_UNIQUE_ID;
pCounter->plCounterInfo.szInstanceName = pCounter->pCounterPath->szInstanceName;
pCounter->plCounterInfo.dwParentObjectId = (DWORD)PERF_NO_UNIQUE_ID;
pCounter->plCounterInfo.szParentInstanceName = pCounter->pCounterPath->szParentName;
}
else {
LONG lTempId;
if (pCounter->pCounterPath->szInstanceName != NULL) {
lTempId = wcstoul(pCounter->pCounterPath->szInstanceName,
NULL,
10);
}
else {
lTempId = 0;
}
pCounter->plCounterInfo.lInstanceId = lTempId;
pCounter->plCounterInfo.szInstanceName = NULL;
if (pCounter->pCounterPath->szParentName != NULL) {
lTempId = wcstoul(pCounter->pCounterPath->szParentName,
NULL,
10);
}
else {
lTempId = 0;
}
pCounter->plCounterInfo.dwParentObjectId = lTempId;
pCounter->plCounterInfo.szParentInstanceName = NULL;
}
}
Cleanup:
return Status;
}
PDH_FUNCTION
PdhiGetWmiLogFileSize(
IN PPDHI_LOG pLog,
IN LONGLONG * llSize)
{
PDH_STATUS pdhStatus = ERROR_SUCCESS;
LONGLONG SizeSum = 0;
DWORD dwFileSizeLow;
DWORD dwFileSizeHigh;
DWORD dwError;
HANDLE hFile;
if (pLog->dwLogFormat & PDH_LOG_WRITE_ACCESS) {
PPDH_EVENT_TRACE_PROPERTIES LoggerInfo =
(PPDH_EVENT_TRACE_PROPERTIES) pLog->lpMappedFileBase;
if (LoggerInfo != NULL && LoggerInfo->LogFileName != NULL
&& LoggerInfo->LogFileName[0] != L'\0') {
hFile = CreateFileW(
LoggerInfo->LogFileName,
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile == NULL || hFile == INVALID_HANDLE_VALUE) {
DWORD Win32Error = GetLastError();
switch (Win32Error) {
case ERROR_FILE_NOT_FOUND:
pdhStatus = PDH_FILE_NOT_FOUND;
break;
case ERROR_ALREADY_EXISTS:
pdhStatus = PDH_FILE_ALREADY_EXISTS;
break;
default:
pdhStatus = PDH_LOG_FILE_OPEN_ERROR;
break;
}
}
else {
dwFileSizeLow = GetFileSize(hFile, & dwFileSizeHigh);
if ( (dwFileSizeLow == 0xFFFFFFFF)
&& ((dwError = GetLastError()) != NO_ERROR)) {
pdhStatus = PDH_LOG_FILE_OPEN_ERROR;
}
else {
if (dwFileSizeHigh != 0) {
SizeSum += (dwFileSizeHigh << (sizeof(DWORD) * 8));
}
SizeSum += dwFileSizeLow;
}
CloseHandle(hFile);
}
}
else {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
else {
PPDH_LOGGER_CONTEXT CurrentContext =
(PPDH_LOGGER_CONTEXT) pLog->lpMappedFileBase;
if (GetLoggerContext(CurrentContext) < ContextCount) {
LONG i;
for (i = 0, hFile = NULL, dwFileSizeLow = 0, dwFileSizeHigh = 0;
(pdhStatus == ERROR_SUCCESS)
&& (i < (LONG) CurrentContext->LogFileCount);
i ++, hFile = NULL, dwFileSizeLow = 0, dwFileSizeHigh = 0) {
hFile = CreateFileW(
CurrentContext->LogFileName[i],
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile == NULL || hFile == INVALID_HANDLE_VALUE) {
DWORD Win32Error = GetLastError();
switch (Win32Error) {
case ERROR_FILE_NOT_FOUND:
pdhStatus = PDH_FILE_NOT_FOUND;
break;
case ERROR_ALREADY_EXISTS:
pdhStatus = PDH_FILE_ALREADY_EXISTS;
break;
default:
pdhStatus = PDH_LOG_FILE_OPEN_ERROR;
break;
}
break;
}
dwFileSizeLow = GetFileSize(hFile, & dwFileSizeHigh);
if ( (dwFileSizeLow == 0xFFFFFFFF)
&& ((dwError = GetLastError()) != NO_ERROR)) {
pdhStatus = PDH_LOG_FILE_OPEN_ERROR;
}
else {
if (dwFileSizeHigh != 0) {
SizeSum = SizeSum + (dwFileSizeHigh << (sizeof(DWORD) * 8));
}
SizeSum += dwFileSizeLow;
}
CloseHandle(hFile);
}
}
else {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
if (pdhStatus == ERROR_SUCCESS) {
__try {
* llSize = SizeSum;
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
return pdhStatus;
}