You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
4195 lines
165 KiB
4195 lines
165 KiB
/*++
|
|
Copyright (C) 1996-1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
log_wmi.c
|
|
|
|
Abstract:
|
|
<abstract>
|
|
--*/
|
|
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
#include <windows.h>
|
|
#include <strsafe.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 <wmiguid.h>
|
|
#include <wmium.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;
|
|
LPCWSTR gszTotal = L"_Total";
|
|
|
|
// 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;
|
|
BOOLEAN bDisable;
|
|
} PDH_EVENT_TRACE_PROPERTIES, * PPDH_EVENT_TRACE_PROPERTIES;
|
|
|
|
PPDHI_LOG lpPdhBlgLog[PDH_MAX_LOGFILES];
|
|
DWORD dwPdhBlgLog = 0;
|
|
|
|
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 {
|
|
PdhProcessTraceStart,
|
|
PdhProcessTraceFirstPath,
|
|
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 TimePrev;
|
|
PVOID DataBlock;
|
|
PPDHI_LOG_MACHINE MachineList;
|
|
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];
|
|
HANDLE hThreadWork;
|
|
HANDLE hSyncPDH;
|
|
HANDLE hSyncWMI;
|
|
PVOID CounterPathBuffer;
|
|
PVOID tmpBuffer;
|
|
PDH_PROCESS_TRACE_STATE LoggerState;
|
|
ULONG LogFileCount;
|
|
ULONG LoggerCount;
|
|
ULONG RefCount;
|
|
DWORD dwThread;
|
|
DWORD dwBuffers;
|
|
DWORD dwEvents;
|
|
BOOLEAN bCounterPathChanged;
|
|
BOOLEAN bFirstDataBlockRead;
|
|
BOOLEAN bDataBlockProcessed;
|
|
BOOLEAN bFirstRun;
|
|
BOOLEAN bBulkProcess;
|
|
} 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 };
|
|
|
|
ULONG
|
|
PdhTraceNotificationCallback(
|
|
PWNODE_HEADER pWnode,
|
|
UINT_PTR LogFileIndex
|
|
)
|
|
{
|
|
LPGUID lpErrorGuid;
|
|
DWORD i;
|
|
ULONG lStatus = ERROR_SUCCESS;
|
|
|
|
if (pWnode == NULL) {
|
|
lStatus = ERROR_INVALID_PARAMETER;
|
|
}
|
|
else {
|
|
__try {
|
|
lpErrorGuid = & pWnode->Guid;
|
|
i = pWnode->BufferSize;
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER) {
|
|
lStatus = ERROR_INVALID_PARAMETER;
|
|
}
|
|
if (lStatus == ERROR_SUCCESS) {
|
|
if ((IsEqualGUID(lpErrorGuid, & TraceErrorGuid)) && (i >= (sizeof(WNODE_HEADER) + sizeof(ULONG)))) {
|
|
ULONGLONG LoggerId = pWnode->HistoricalContext;
|
|
ULONG ulStatus = * ((ULONG *) (((PUCHAR) pWnode) + sizeof(WNODE_HEADER)));
|
|
|
|
if (ulStatus == STATUS_LOG_FILE_FULL) {
|
|
if (WAIT_FOR_AND_LOCK_MUTEX(hPdhContextMutex) == ERROR_SUCCESS) {
|
|
PPDH_EVENT_TRACE_PROPERTIES LoggerInfo;
|
|
|
|
for (i = 0; i < dwPdhBlgLog; i ++) {
|
|
LoggerInfo = (PPDH_EVENT_TRACE_PROPERTIES) lpPdhBlgLog[i]->lpMappedFileBase;
|
|
if (LoggerInfo->LoggerInfo.Wnode.HistoricalContext == LoggerId) {
|
|
LoggerInfo->bDisable = TRUE;
|
|
}
|
|
}
|
|
RELEASE_MUTEX(hPdhContextMutex);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return lStatus;
|
|
}
|
|
|
|
void
|
|
GuidToString(
|
|
LPWSTR s,
|
|
DWORD dwSize,
|
|
LPGUID piid
|
|
)
|
|
{
|
|
StringCchPrintfW(s, dwSize, 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(
|
|
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(
|
|
DWORD dwLine,
|
|
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)
|
|
|
|
PDH_FUNCTION
|
|
PdhWmiTraceEvent(
|
|
PPDHI_LOG pLog,
|
|
ULONG PdhEventType,
|
|
ULONGLONG TimeStamp,
|
|
ULONG lenMofData,
|
|
PVOID ptrMofData
|
|
);
|
|
|
|
PDH_FUNCTION
|
|
PdhiBuildPerfCounterList(
|
|
PPDHI_LOG pLog,
|
|
PPDH_EVENT_TRACE_PROPERTIES LoggerInfo,
|
|
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;
|
|
dwBufSize = lstrlenW(pMachine->szName) + 1;
|
|
LoggerInfo->MachineList = G_REALLOC(pszTemp, sizeof(WCHAR) * (LoggerInfo->MachineListSize + dwBufSize));
|
|
if (LoggerInfo->MachineList != NULL) {
|
|
pszCurrent = LoggerInfo->MachineList + (LoggerInfo->MachineListSize - 1);
|
|
LoggerInfo->MachineListSize += dwBufSize;
|
|
}
|
|
else {
|
|
G_FREE(pszTemp);
|
|
}
|
|
}
|
|
else {
|
|
dwBufSize = lstrlenW(pMachine->szName) + 2;
|
|
LoggerInfo->MachineListSize = dwBufSize;
|
|
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;
|
|
}
|
|
|
|
StringCchCopyW(pszCurrent, dwBufSize, 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);
|
|
StringCbCopyW(pszBuffer, PDH_BLOCK_BUFFER_SIZE, pMachine->szName);
|
|
pszCurrent = pszBuffer + (lstrlenW(pszBuffer) + 1);
|
|
dwBufSize = sizeof(WCHAR) * (lstrlenW(pMachine->szName) + 1);
|
|
bNewEvent = FALSE;
|
|
}
|
|
StringCbCopyW(pszCurrent, PDH_BLOCK_BUFFER_SIZE - dwBufSize, szIndex);
|
|
pszCurrent += (lstrlenW(pszCurrent) + 1);
|
|
dwBufSize += sizeof(WCHAR) * (lstrlenW(szIndex) + 1);
|
|
StringCchCopyW(pszCurrent, PDH_BLOCK_BUFFER_SIZE - dwBufSize, pString[i]);
|
|
pszCurrent += (lstrlenW(pszCurrent) + 1);
|
|
dwBufSize += sizeof(WCHAR) * (lstrlenW(pString[i]) + 1);
|
|
}
|
|
Status = PdhWmiTraceEvent(pLog, PDH_LOG_COUNTER_STRING_EVENT, LoggerInfo->TimeStamp - 1, dwBufSize, pszBuffer);
|
|
}
|
|
__except (EXCEPTION_EXECUTE_HANDLER) {
|
|
Status = GetExceptionCode();
|
|
}
|
|
|
|
Cleanup:
|
|
G_FREE(pszBuffer);
|
|
return Status;
|
|
}
|
|
|
|
PDH_FUNCTION
|
|
PdhiBuildLogHeaderBlock(
|
|
PPDHI_LOG pLog,
|
|
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);
|
|
StringCchCopyW(pBufferBase,
|
|
lstrlenW(pThisCounter->pCounterPath->szMachineName) + 1,
|
|
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);
|
|
StringCchCopyW(pBufferBase,
|
|
lstrlenW(pThisCounter->pCounterPath->szObjectName) + 1,
|
|
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);
|
|
StringCchCopyW(pBufferBase,
|
|
lstrlenW(pThisCounter->pCounterPath->szInstanceName) + 1,
|
|
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);
|
|
StringCchCopyW(pBufferBase,
|
|
lstrlenW(pThisCounter->pCounterPath->szParentName) + 1,
|
|
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);
|
|
StringCchCopyW(pBufferBase,
|
|
lstrlenW(pThisCounter->pCounterPath->szCounterName) + 1,
|
|
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:
|
|
G_FREE(ptrOutBuffer);
|
|
return Status;
|
|
}
|
|
|
|
PDH_FUNCTION
|
|
PdhWmiTraceEvent(
|
|
PPDHI_LOG pLog,
|
|
ULONG PdhEventType,
|
|
ULONGLONG TimeStamp,
|
|
ULONG lenMofData,
|
|
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 (LoggerInfo->bDisable) {
|
|
return ERROR_DISK_FULL;
|
|
}
|
|
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);
|
|
TRACE((PDH_DBG_TRACE_INFO),
|
|
(__LINE__,
|
|
PDH_LOGWMI,
|
|
ARG_DEF(ARG_TYPE_PTR, 1),
|
|
Status,
|
|
TRACE_PTR(pLog->hLogFileHandle),
|
|
TRACE_DWORD(LoggerInfo->LoggerInfo.MaximumBuffers),
|
|
NULL));
|
|
bIncreaseBuffer = (Status == ERROR_SUCCESS || Status == ERROR_MORE_DATA) ? (TRUE) : (FALSE);
|
|
}
|
|
}
|
|
else {
|
|
bIncreaseBuffer = FALSE;
|
|
}
|
|
}
|
|
if (Status != ERROR_SUCCESS) {
|
|
DWORD dwMofLen = sMofLen;
|
|
TRACE((PDH_DBG_TRACE_ERROR),
|
|
(__LINE__,
|
|
PDH_LOGWMI,
|
|
ARG_DEF(ARG_TYPE_PTR, 1) | ARG_DEF(ARG_TYPE_ULONGX, 6) | ARG_DEF(ARG_TYPE_ULONG64, 7),
|
|
Status,
|
|
TRACE_PTR(pLog->hLogFileHandle),
|
|
TRACE_DWORD(PdhEventType),
|
|
TRACE_DWORD(dwCurrentEvent),
|
|
TRACE_DWORD(dwNumEvents),
|
|
TRACE_DWORD(dwMofLen),
|
|
TRACE_DWORD(Wnode.EventHeader.Flags),
|
|
TRACE_LONG64(Wnode.EventHeader.TimeStamp.QuadPart),
|
|
NULL));
|
|
}
|
|
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(
|
|
LPCWSTR LogFileName,
|
|
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 {
|
|
LPBYTE TraceBuffer = NULL;
|
|
|
|
TraceBuffer = G_ALLOC(sizeof(BYTE) * PDH_WMI_BUFFER_SIZE_BYTE);
|
|
if (TraceBuffer != NULL) {
|
|
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;
|
|
}
|
|
}
|
|
G_FREE(TraceBuffer);
|
|
}
|
|
else {
|
|
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
|
|
}
|
|
CloseHandle(hFile);
|
|
}
|
|
return pdhStatus;
|
|
}
|
|
|
|
PDH_FUNCTION
|
|
PdhWmiGetLoggerName(
|
|
PPDHI_LOG pLog,
|
|
PPDH_EVENT_TRACE_PROPERTIES LoggerInfo
|
|
)
|
|
{
|
|
PDH_STATUS Status = ERROR_SUCCESS;
|
|
LPBYTE TraceBuffer = NULL;
|
|
|
|
TraceBuffer = G_ALLOC(sizeof(BYTE) * PDH_WMI_BUFFER_SIZE_BYTE);
|
|
if (TraceBuffer != NULL) {
|
|
HANDLE hFile;
|
|
ULONG ByteRead = 0;
|
|
|
|
// read in the first trace buffer
|
|
|
|
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);
|
|
}
|
|
}
|
|
else {
|
|
Status = PDH_MEMORY_ALLOCATION_FAILURE;
|
|
}
|
|
|
|
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));
|
|
StringCchCopyW(LoggerInfo->LoggerName, PDH_MAX_PATH, LoggerName);
|
|
|
|
StringCchCopyW(strTmp, 9, LoggerName);
|
|
strTmp[8] = L'\0';
|
|
LoggerInfo->LogFileGuid.Data1 = whextoi(strTmp);
|
|
|
|
StringCchCopyW(strTmp, 5, & LoggerName[9]);
|
|
strTmp[4] = L'\0';
|
|
LoggerInfo->LogFileGuid.Data2 = (USHORT) whextoi(strTmp);
|
|
|
|
StringCchCopyW(strTmp, 5, & LoggerName[14]);
|
|
strTmp[4] = L'\0';
|
|
LoggerInfo->LogFileGuid.Data3 = (USHORT) whextoi(strTmp);
|
|
|
|
for (i = 0; i < 2; i ++) {
|
|
StringCchCopyW(strTmp, 3, & LoggerName[19 + (i * 2)]);
|
|
strTmp[2] = L'\0';
|
|
LoggerInfo->LogFileGuid.Data4[i] = (UCHAR) whextoi(strTmp);
|
|
}
|
|
|
|
for (i = 2; i < 8; i ++) {
|
|
StringCchCopyW(strTmp, 3, & LoggerName[20 + (i * 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;
|
|
TRACE((PDH_DBG_TRACE_ERROR),
|
|
(__LINE__,
|
|
PDH_LOGWMI,
|
|
ARG_DEF(ARG_TYPE_PTR, 1) | ARG_DEF(ARG_TYPE_PTR, 2)
|
|
| ARG_DEF(ARG_TYPE_WSTR, 3),
|
|
Status,
|
|
TRACE_PTR(pLog),
|
|
TRACE_PTR(LoggerInfo),
|
|
TRACE_WSTR(LoggerInfo->LogFileName),
|
|
NULL));
|
|
}
|
|
}
|
|
G_FREE(TraceBuffer);
|
|
return Status;
|
|
}
|
|
|
|
PDH_FUNCTION
|
|
PdhiOpenOutputWmiLog(
|
|
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, PDH_MAX_PATH, & LoggerInfo->LogFileGuid);
|
|
}
|
|
else {
|
|
LoggerInfo->LoggerInfo.LogFileMode |= EVENT_TRACE_FILE_MODE_APPEND;
|
|
}
|
|
}
|
|
else {
|
|
RPC_STATUS rpcStatus = UuidCreate(& LoggerInfo->LogFileGuid);
|
|
GuidToString(LoggerInfo->LoggerName, PDH_MAX_PATH, & LoggerInfo->LogFileGuid);
|
|
}
|
|
if (pLog->dwLogFormat & PDH_LOG_OPT_CIRCULAR) {
|
|
LoggerInfo->LoggerInfo.LogFileMode |= EVENT_TRACE_FILE_MODE_CIRCULAR_PERSIST;
|
|
|
|
}
|
|
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;
|
|
LoggerInfo->bDisable = FALSE;
|
|
Status = StartTraceW((PTRACEHANDLE) & pLog->hLogFileHandle,
|
|
LoggerInfo->LoggerName,
|
|
(PEVENT_TRACE_PROPERTIES) LoggerInfo);
|
|
if (Status != ERROR_SUCCESS) {
|
|
TRACE((PDH_DBG_TRACE_ERROR),
|
|
(__LINE__,
|
|
PDH_LOGWMI,
|
|
ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2) | ARG_DEF(ARG_TYPE_ULONGX, 3)
|
|
| ARG_DEF(ARG_TYPE_ULONG64, 4),
|
|
Status,
|
|
TRACE_WSTR(LoggerInfo->LoggerName),
|
|
TRACE_WSTR(LoggerInfo->LogFileName),
|
|
TRACE_DWORD(LoggerInfo->LoggerInfo.LogFileMode),
|
|
TRACE_LONG64(pLog->llMaxSize),
|
|
NULL));
|
|
}
|
|
|
|
Cleanup:
|
|
if (Status != ERROR_SUCCESS) {
|
|
G_FREE(pLog->lpMappedFileBase);
|
|
pLog->lpMappedFileBase = NULL;
|
|
Status = PDH_LOG_FILE_CREATE_ERROR;
|
|
}
|
|
else if (WAIT_FOR_AND_LOCK_MUTEX(hPdhContextMutex) == ERROR_SUCCESS) {
|
|
if (dwPdhBlgLog == 0) {
|
|
#if _MSC_VER >= 1200
|
|
#pragma warning(push)
|
|
#endif
|
|
#pragma warning(disable:4152)
|
|
WmiNotificationRegistration((const LPGUID) & TraceErrorGuid,
|
|
TRUE,
|
|
PdhTraceNotificationCallback,
|
|
0,
|
|
NOTIFICATION_CALLBACK_DIRECT);
|
|
#if _MSC_VER >= 1200
|
|
#pragma warning(pop)
|
|
#endif
|
|
}
|
|
lpPdhBlgLog[dwPdhBlgLog] = pLog;
|
|
dwPdhBlgLog ++;
|
|
RELEASE_MUTEX(hPdhContextMutex);
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
PDH_FUNCTION
|
|
PdhiWriteWmiLogRecord(
|
|
PPDHI_LOG pLog,
|
|
SYSTEMTIME * stTimeStamp,
|
|
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);
|
|
|
|
tFileTime.dwLowDateTime = tFileTime.dwHighDateTime = 0;
|
|
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));
|
|
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;
|
|
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 != NULL && pThisCounter->pThisObject != pThisCounter->pLastObject) {
|
|
ZeroMemory(& LocFileTime, sizeof(FILETIME));
|
|
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)) {
|
|
pdhStatus = PdhiBuildLogHeaderBlock(pLog, LoggerInfo);
|
|
}
|
|
LoggerInfo->bHeaderEvent = TRUE;
|
|
}
|
|
}
|
|
|
|
if (pdhStatus == ERROR_SUCCESS && pLogCounterBuffer) {
|
|
pdhStatus = PdhWmiTraceEvent(pLog, PDH_LOG_DATA_BLOCK_EVENT, TimeStamp, dwBufSize, (PVOID) pLogCounterBuffer);
|
|
}
|
|
G_FREE(pLogCounterBuffer);
|
|
return pdhStatus;
|
|
}
|
|
|
|
PDH_FUNCTION
|
|
PdhiWriteWmiLogHeader(
|
|
PPDHI_LOG pLog,
|
|
LPCWSTR szUserCaption
|
|
)
|
|
{
|
|
UNREFERENCED_PARAMETER(pLog);
|
|
UNREFERENCED_PARAMETER(szUserCaption);
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
PDH_FUNCTION
|
|
PdhiCloseWmiLog(
|
|
PPDHI_LOG pLog,
|
|
DWORD dwFlags
|
|
)
|
|
{
|
|
PDH_STATUS Status = PDH_INVALID_ARGUMENT;
|
|
ULONG i;
|
|
|
|
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;
|
|
Status = ControlTraceW((TRACEHANDLE) pLog->hLogFileHandle,
|
|
LoggerInfo->LoggerName,
|
|
(PEVENT_TRACE_PROPERTIES) LoggerInfo,
|
|
EVENT_TRACE_CONTROL_STOP);
|
|
if (Status != ERROR_SUCCESS) {
|
|
TRACE((PDH_DBG_TRACE_ERROR),
|
|
(__LINE__,
|
|
PDH_LOGWMI,
|
|
ARG_DEF(ARG_TYPE_PTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2)
|
|
| ARG_DEF(ARG_TYPE_WSTR, 3),
|
|
Status,
|
|
TRACE_PTR(pLog->hLogFileHandle),
|
|
TRACE_WSTR(LoggerInfo->LoggerName),
|
|
TRACE_WSTR(LoggerInfo->LogFileName),
|
|
NULL));
|
|
}
|
|
if (WAIT_FOR_AND_LOCK_MUTEX(hPdhContextMutex) == ERROR_SUCCESS) {
|
|
for (i = 0; i < dwPdhBlgLog; i ++) {
|
|
if (lpPdhBlgLog[i] == pLog) {
|
|
dwPdhBlgLog --;
|
|
if (i < dwPdhBlgLog) {
|
|
lpPdhBlgLog[i] = lpPdhBlgLog[dwPdhBlgLog];
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
if (dwPdhBlgLog == 0) {
|
|
#if _MSC_VER >= 1200
|
|
#pragma warning(push)
|
|
#endif
|
|
#pragma warning ( disable : 4152 )
|
|
WmiNotificationRegistration((const LPGUID) & TraceErrorGuid,
|
|
FALSE,
|
|
PdhTraceNotificationCallback,
|
|
0,
|
|
NOTIFICATION_CALLBACK_DIRECT);
|
|
#if _MSC_VER >= 1200
|
|
#pragma warning(pop)
|
|
#endif
|
|
}
|
|
RELEASE_MUTEX(hPdhContextMutex);
|
|
}
|
|
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) {
|
|
TRACE((PDH_DBG_TRACE_ERROR),
|
|
(__LINE__,
|
|
PDH_LOGWMI,
|
|
ARG_DEF(ARG_TYPE_PTR,1),
|
|
Status,
|
|
TRACE_PTR(PdhTraceRegistrationHandle),
|
|
NULL));
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
Status = PDH_INVALID_HANDLE;
|
|
}
|
|
}
|
|
else if (pLog->dwLogFormat & PDH_LOG_READ_ACCESS) {
|
|
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 (WaitForSingleObject(CurrentContext->hThreadWork, 5000) == WAIT_TIMEOUT) {
|
|
// wait too long, call TerminateThread() to foce working thread ends.
|
|
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 ++) {
|
|
PdhiFreeLogMachineTable(& CurrentContext->LogInfo[i].MachineList);
|
|
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);
|
|
}
|
|
}
|
|
G_FREE(CurrentContext->LogInfo[i].DataBlock);
|
|
}
|
|
G_FREE(CurrentContext->tmpBuffer);
|
|
G_FREE(CurrentContext->CounterPathBuffer);
|
|
G_FREE(pLog->pPerfmonInfo);
|
|
G_FREE(pLog->lpMappedFileBase);
|
|
pLog->pPerfmonInfo = NULL;
|
|
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) {
|
|
TRACE((PDH_DBG_TRACE_ERROR),
|
|
(__LINE__,
|
|
PDH_LOGWMI,
|
|
ARG_DEF(ARG_TYPE_PTR, 1),
|
|
Status,
|
|
TRACE_PTR(CurrentContext),
|
|
TRACE_DWORD(CurrentContext->LoggerCount),
|
|
TRACE_DWORD(CurrentContext->LogFileCount),
|
|
NULL));
|
|
}
|
|
}
|
|
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 (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;
|
|
}
|
|
CurrentContext->LogInfo[i].TimePrev = TimeStamp;
|
|
}
|
|
}
|
|
else {
|
|
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;
|
|
|
|
if (CurrentContext == NULL || pEvent == NULL) {
|
|
return PDH_INVALID_DATA;
|
|
}
|
|
|
|
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) {
|
|
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;
|
|
}
|
|
|
|
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 ( 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;
|
|
RtlCopyMemory(pNewCounter->CounterPathBuffer, pCounterPath, 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;
|
|
|
|
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(
|
|
PPDH_LOGGER_CONTEXT CurrentContext,
|
|
PVOID pMofDataBlock,
|
|
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) {
|
|
G_FREE(pCurrentMachine->pszBuffer);
|
|
RemoveEntryList(& pCurrentMachine->Entry);
|
|
G_FREE(pCurrentMachine);
|
|
}
|
|
}
|
|
else if (pCurrentMachine != NULL) {
|
|
G_FREE(pCurrentMachine->pszBuffer);
|
|
RemoveEntryList(& pCurrentMachine->Entry);
|
|
G_FREE(pCurrentMachine);
|
|
}
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
PDH_FUNCTION
|
|
PdhiGetCounterPathRecord(
|
|
PPDH_LOGGER_CONTEXT CurrentContext,
|
|
PVOID pRecord,
|
|
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;
|
|
}
|
|
|
|
PDH_FUNCTION
|
|
PdhWmiEnsureFirstRun(
|
|
PPDH_LOGGER_CONTEXT CurrentContext
|
|
)
|
|
{
|
|
PDH_STATUS Status = ERROR_SUCCESS;
|
|
LONG i;
|
|
|
|
if (CurrentContext->LoggerState == PdhProcessTraceStart) {
|
|
CurrentContext->LoggerState = PdhProcessTraceFirstPath;
|
|
SetEvent(CurrentContext->hSyncWMI);
|
|
}
|
|
while (CurrentContext->LoggerState == PdhProcessTraceFirstPath) {
|
|
Sleep(1);
|
|
}
|
|
|
|
for (i = 0; Status == ERROR_SUCCESS && i < (LONG) CurrentContext->LoggerCount; i ++) {
|
|
if (IsListEmpty(& CurrentContext->LogInfo[i].CounterPathList)) {
|
|
Status = PDH_BINARY_LOG_CORRUPT;
|
|
}
|
|
else if (CurrentContext->LogInfo[i].ValidEntries < 2) {
|
|
Status = PDH_LOG_SAMPLE_TOO_SMALL;
|
|
}
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
ULONG
|
|
WINAPI
|
|
PdhWmiBufferCallback(
|
|
PEVENT_TRACE_LOGFILEW LogFile
|
|
)
|
|
{
|
|
ULONG bResult = TRUE;
|
|
PPDH_LOGGER_CONTEXT CurrentContext;
|
|
|
|
UNREFERENCED_PARAMETER(LogFile);
|
|
CurrentContext = GetCurrentContext();
|
|
if (CurrentContext != NULL) {
|
|
CurrentContext->dwBuffers ++;
|
|
bResult = (CurrentContext->LoggerState != PdhProcessTraceNormal
|
|
&& CurrentContext->LoggerState != PdhProcessTraceFirstPath)
|
|
? (FALSE) : (TRUE);
|
|
}
|
|
return bResult;
|
|
}
|
|
|
|
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 (pEvent == NULL || CurrentContext == NULL) {
|
|
goto Cleanup;
|
|
}
|
|
else if (CurrentContext->LoggerState == PdhProcessTraceEnd
|
|
|| CurrentContext->LoggerState == PdhProcessTraceExit
|
|
|| CurrentContext->LoggerState == PdhProcessTraceRewind) {
|
|
goto Cleanup;
|
|
}
|
|
else if (CurrentContext->LoggerState == PdhProcessTraceStart) {
|
|
SetEvent(CurrentContext->hSyncPDH);
|
|
WaitForSingleObject(CurrentContext->hSyncWMI, INFINITE);
|
|
|
|
if (CurrentContext->LoggerState != PdhProcessTraceFirstPath) {
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
|
|
if ((! IsEqualGUID(& pEvent->Header.Guid, & PdhTransactionGuid))) {
|
|
goto Cleanup;
|
|
}
|
|
else if (CurrentContext->LoggerState != PdhProcessTraceFirstPath
|
|
&& CurrentContext->LoggerState != PdhProcessTraceNormal) {
|
|
goto Cleanup;
|
|
}
|
|
|
|
CurrentContext->dwEvents ++;
|
|
|
|
switch (pEvent->Header.Class.Type) {
|
|
case PDH_LOG_HEADER_EVENT:
|
|
if (CurrentContext->LoggerState == PdhProcessTraceFirstPath) {
|
|
DWORD dwCurrentBlock;
|
|
DWORD dwTotalBlocks;
|
|
DWORD dwMofHeader = sizeof(GUID) + sizeof(DWORD) + sizeof(DWORD);
|
|
|
|
PdhiAddWmiLogFileGuid(CurrentContext, (LPGUID) pEvent->MofData);
|
|
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);
|
|
}
|
|
break;
|
|
|
|
case PDH_LOG_COUNTER_STRING_EVENT:
|
|
if (CurrentContext->LoggerState == PdhProcessTraceFirstPath) {
|
|
PdhiAddWmiLogFileGuid(CurrentContext, (LPGUID) pEvent->MofData);
|
|
PdhiAddPerfMachine(CurrentContext, pEvent->MofData, pEvent->MofLength);
|
|
}
|
|
break;
|
|
|
|
case PDH_LOG_DATA_BLOCK_EVENT:
|
|
if (CurrentContext->LoggerState == PdhProcessTraceFirstPath) {
|
|
PdhiAddWmiLogFileGuid(CurrentContext, (LPGUID) pEvent->MofData);
|
|
PdhWmiGetDataBlockTimeStamp(CurrentContext, pEvent, TRUE);
|
|
PdhiWmiComputeCounterBlocks(CurrentContext, pEvent);
|
|
}
|
|
else {
|
|
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 (EventTimePrev < EventTime) {
|
|
dwNumDataBlocks = * (DWORD *) (((LPBYTE) pEvent->MofData) + sizeof(GUID) + sizeof(DWORD));
|
|
dwBufferSize = dwNumDataBlocks * PDH_BLOCK_BUFFER_SIZE + sizeof(GUID);
|
|
|
|
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) {
|
|
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) {
|
|
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);
|
|
}
|
|
|
|
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:
|
|
TRACE((PDH_DBG_TRACE_WARNING),
|
|
(__LINE__,
|
|
PDH_LOGWMI,
|
|
0,
|
|
ERROR_SUCCESS,
|
|
TRACE_DWORD(pEvent->Header.Class.Type),
|
|
NULL));
|
|
break;
|
|
}
|
|
|
|
Cleanup:
|
|
if (bNotifyPDH) {
|
|
if (CurrentContext->bFirstRun) {
|
|
CurrentContext->bFirstRun = FALSE;
|
|
}
|
|
else {
|
|
// Signal that we get the current DataBlock event, then wait for next
|
|
// DataBlock requests.
|
|
//
|
|
SetEvent(CurrentContext->hSyncPDH);
|
|
}
|
|
WaitForSingleObject(CurrentContext->hSyncWMI, INFINITE);
|
|
}
|
|
}
|
|
|
|
PDH_FUNCTION
|
|
PdhiCacheWmiHeaderEvent(
|
|
PPDH_LOGGER_CONTEXT pContext
|
|
)
|
|
{
|
|
PDH_STATUS Status = ERROR_SUCCESS;
|
|
DWORD dwIndex = 0;
|
|
DWORD dwSize;
|
|
DWORD dwProcess;
|
|
PPDHI_LOG_COUNTER_PATH pPath;
|
|
LPBYTE pString;
|
|
LPWSTR szMachine;
|
|
LPWSTR szObject;
|
|
LPWSTR szCounter;
|
|
LPWSTR szInstance;
|
|
LPWSTR szParent;
|
|
PPDHI_LOG_MACHINE pMachine;
|
|
PPDHI_LOG_OBJECT pObject;
|
|
PPDHI_LOG_COUNTER pCounter;
|
|
DWORD i;
|
|
PLIST_ENTRY pHead;
|
|
PLIST_ENTRY pNext;
|
|
PPDH_COUNTER_PATH pCtrPath;
|
|
|
|
for (i = 0; i < pContext->LoggerCount; i ++) {
|
|
if (! IsListEmpty(& pContext->LogInfo[i].CounterPathList)) {
|
|
pHead = & pContext->LogInfo[i].CounterPathList;
|
|
pNext = pHead->Flink;
|
|
while (Status == ERROR_SUCCESS && pNext != pHead) {
|
|
pCtrPath = CONTAINING_RECORD(pNext, PDH_COUNTER_PATH, Entry);
|
|
pNext = pNext->Flink;
|
|
|
|
if (pCtrPath == NULL) continue;
|
|
|
|
pPath = (PPDHI_LOG_COUNTER_PATH) pCtrPath->CounterPathBuffer;
|
|
dwSize = pCtrPath->CounterPathSize;
|
|
dwProcess = 0;
|
|
|
|
while (pPath != NULL && dwProcess < dwSize) {
|
|
dwIndex ++;
|
|
pString = (LPBYTE) & pPath->Buffer[0];
|
|
szMachine = (pPath->lMachineNameOffset >= 0)
|
|
? (LPWSTR) (pString + pPath->lMachineNameOffset) : NULL;
|
|
szObject = (pPath->lObjectNameOffset >= 0)
|
|
? (LPWSTR) (pString + pPath->lObjectNameOffset) : NULL;
|
|
|
|
if (szMachine != NULL && szMachine[0] != L'\0' && szObject != NULL && szObject[0] != L'\0') {
|
|
if (pPath->dwFlags & PDHIC_COUNTER_OBJECT) {
|
|
pMachine = PdhiFindLogMachine(& pContext->LogInfo[i].MachineList, szMachine, TRUE);
|
|
if (pMachine != NULL) {
|
|
pObject = PdhiFindLogObject(pMachine, & pMachine->ObjTable, szObject, TRUE);
|
|
if (pObject != NULL) {
|
|
pObject->bNeedExpand = TRUE;
|
|
if (pObject->pObjData == NULL) {
|
|
pObject->pObjData = (PPERF_OBJECT_TYPE)
|
|
G_ALLOC(sizeof(DWORD) * pContext->LoggerCount);
|
|
pObject->dwIndex = 0;
|
|
}
|
|
if (pObject->pObjData != NULL) {
|
|
LPDWORD pdwCounter = (LPDWORD) pObject->pObjData;
|
|
pObject->dwIndex = i;
|
|
pdwCounter[i] = dwIndex;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (pPath->dwFlags & PDHIC_MULTI_INSTANCE) {
|
|
szCounter = (pPath->lCounterOffset >= 0)
|
|
? (LPWSTR) (pString + pPath->lCounterOffset) : NULL;
|
|
if (szCounter != NULL && szCounter[0] != L'\0') {
|
|
pCounter = PdhiFindLogCounter(NULL,
|
|
& pContext->LogInfo[i].MachineList,
|
|
szMachine,
|
|
szObject,
|
|
szCounter,
|
|
pPath->dwCounterType,
|
|
pPath->lDefaultScale,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
0,
|
|
& dwIndex,
|
|
TRUE);
|
|
if (pCounter != NULL) {
|
|
pCounter->bMultiInstance = TRUE;
|
|
if (pCounter->pCtrData == NULL) {
|
|
pCounter->pCtrData = (LPDWORD)
|
|
G_ALLOC(sizeof(DWORD) * pContext->LoggerCount);
|
|
pCounter->dwCounterID = 0;
|
|
}
|
|
if (pCounter->pCtrData != NULL) {
|
|
pCounter->dwCounterID = i;
|
|
pCounter->pCtrData[i] = dwIndex;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
szCounter = (pPath->lCounterOffset >= 0)
|
|
? (LPWSTR) (pString + pPath->lCounterOffset) : NULL;
|
|
szInstance = (pPath->lInstanceOffset >= 0)
|
|
? (LPWSTR) (pString + pPath->lInstanceOffset) : NULL;
|
|
szParent = (pPath->lParentOffset >= 0)
|
|
? (LPWSTR) (pString + pPath->lParentOffset) : NULL;
|
|
if (szCounter != NULL && szCounter[0] != L'\0') {
|
|
pCounter = PdhiFindLogCounter(NULL,
|
|
& pContext->LogInfo[i].MachineList,
|
|
szMachine,
|
|
szObject,
|
|
szCounter,
|
|
pPath->dwCounterType,
|
|
pPath->lDefaultScale,
|
|
szInstance,
|
|
pPath->dwIndex,
|
|
szParent,
|
|
0,
|
|
& dwIndex,
|
|
TRUE);
|
|
if (pCounter != NULL) {
|
|
if (pCounter->pCtrData == NULL) {
|
|
pCounter->pCtrData = (LPDWORD)
|
|
G_ALLOC(sizeof(DWORD) * pContext->LoggerCount);
|
|
pCounter->dwCounterID = 0;
|
|
}
|
|
if (pCounter->pCtrData != NULL) {
|
|
pCounter->dwCounterID = i;
|
|
pCounter->pCtrData[i] = dwIndex;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
dwProcess += pPath->dwLength;
|
|
pPath = (dwProcess < dwSize)
|
|
? (PPDHI_LOG_COUNTER_PATH) (((LPBYTE) pPath) + pPath->dwLength) : NULL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
PDH_FUNCTION
|
|
PdhProcessLog(
|
|
PPDH_LOGGER_CONTEXT CurrentContext
|
|
)
|
|
{
|
|
PDH_STATUS Status = ERROR_SUCCESS;
|
|
LONG i;
|
|
|
|
if (GetLoggerContext(CurrentContext) >= ContextCount) {
|
|
return PDH_INVALID_HANDLE;
|
|
}
|
|
CurrentContext->LoggerState = PdhProcessTraceStart;
|
|
CurrentContext->bFirstRun = TRUE;
|
|
CurrentContext->dwThread = GetCurrentThreadId();
|
|
|
|
do {
|
|
if (CurrentContext->LoggerState != PdhProcessTraceStart) {
|
|
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));
|
|
CurrentContext->dwBuffers = CurrentContext->dwEvents = 0;
|
|
Status = ProcessTrace(CurrentContext->LogFileHandle, CurrentContext->LogFileCount, NULL, NULL);
|
|
if (Status != ERROR_SUCCESS && Status != ERROR_CANCELLED) {
|
|
TRACE((PDH_DBG_TRACE_ERROR),
|
|
(__LINE__,
|
|
PDH_LOGWMI,
|
|
ARG_DEF(ARG_TYPE_PTR, 1),
|
|
Status,
|
|
TRACE_PTR(CurrentContext),
|
|
TRACE_DWORD(CurrentContext->LogFileCount),
|
|
NULL));
|
|
}
|
|
|
|
if (CurrentContext->LoggerState == PdhProcessTraceFirstPath) {
|
|
Status = PdhiCacheWmiHeaderEvent(CurrentContext);
|
|
CurrentContext->LoggerState = PdhProcessTraceRewind;
|
|
}
|
|
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);
|
|
}
|
|
}
|
|
while (CurrentContext->LoggerState == PdhProcessTraceRewind);
|
|
|
|
for (i = 0; i < (LONG) CurrentContext->LogFileCount; i ++) {
|
|
Status = CloseTrace(CurrentContext->LogFileHandle[i]);
|
|
if (Status != ERROR_SUCCESS) {
|
|
TRACE((PDH_DBG_TRACE_ERROR),
|
|
(__LINE__,
|
|
PDH_LOGWMI,
|
|
ARG_DEF(ARG_TYPE_ULONG64, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
|
|
Status,
|
|
TRACE_LONG64(CurrentContext->LogFileHandle[i]),
|
|
TRACE_WSTR(CurrentContext->LogFileName[i]),
|
|
NULL));
|
|
}
|
|
}
|
|
|
|
CurrentContext->LoggerState = PdhProcessTraceExit;
|
|
return Status;
|
|
}
|
|
|
|
PDH_FUNCTION
|
|
PdhiOpenInputWmiLog(
|
|
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 {
|
|
TRACE((PDH_DBG_TRACE_ERROR),
|
|
(__LINE__,
|
|
PDH_LOGWMI,
|
|
ARG_DEF(ARG_TYPE_PTR, 1) | ARG_DEF(ARG_TYPE_PTR, 2)
|
|
| ARG_DEF(ARG_TYPE_PTR, 3),
|
|
PDH_INVALID_ARGUMENT,
|
|
TRACE_PTR(pLog),
|
|
TRACE_PTR(pLog->lpMappedFileBase),
|
|
TRACE_PTR(CurrentContext),
|
|
NULL));
|
|
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));
|
|
|
|
CurrentContext->bBulkProcess = (pLog->iRunidSQL != 0) ? TRUE : FALSE;
|
|
|
|
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 = PdhWmiBufferCallback;
|
|
EvmFile.EventCallback = PdhWmiEventCallback;
|
|
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) {
|
|
TRACE((PDH_DBG_TRACE_ERROR),
|
|
(__LINE__,
|
|
PDH_LOGWMI,
|
|
ARG_DEF(ARG_TYPE_WSTR, 1),
|
|
Status,
|
|
TRACE_WSTR(CurrentContext->LogFileName[i]),
|
|
TRACE_DWORD(i),
|
|
NULL));
|
|
|
|
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();
|
|
TRACE((PDH_DBG_TRACE_ERROR), (__LINE__, PDH_LOGWMI, 0, Status, NULL));
|
|
for (i = 0; i < (LONG) CurrentContext->LogFileCount; i ++) {
|
|
Status = CloseTrace(CurrentContext->LogFileHandle[i]);
|
|
if (Status != ERROR_SUCCESS) {
|
|
TRACE((PDH_DBG_TRACE_ERROR),
|
|
(__LINE__,
|
|
PDH_LOGWMI,
|
|
ARG_DEF(ARG_TYPE_ULONG64, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
|
|
Status,
|
|
TRACE_LONG64(CurrentContext->LogFileHandle[i]),
|
|
TRACE_WSTR(CurrentContext->LogFileName[i]),
|
|
NULL));
|
|
}
|
|
}
|
|
goto Cleanup;
|
|
}
|
|
WaitForSingleObject(CurrentContext->hSyncPDH, INFINITE);
|
|
|
|
Cleanup:
|
|
if (Status != ERROR_SUCCESS) {
|
|
if (pLog->lpMappedFileBase != NULL) {
|
|
DWORD dwTmpLogFormat = pLog->dwLogFormat;
|
|
pLog->dwLogFormat |= PDH_LOG_READ_ACCESS;
|
|
PdhiCloseWmiLog(pLog, 0);
|
|
pLog->dwLogFormat = dwTmpLogFormat;
|
|
}
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
PDH_FUNCTION
|
|
PdhiRewindWmiLog(
|
|
PPDHI_LOG pLog
|
|
)
|
|
{
|
|
PDH_STATUS Status = PDH_INVALID_HANDLE;
|
|
PPDH_LOGGER_CONTEXT CurrentContext;
|
|
|
|
CurrentContext = (PPDH_LOGGER_CONTEXT) pLog->lpMappedFileBase;
|
|
if (GetLoggerContext(CurrentContext) < ContextCount) {
|
|
if (CurrentContext->LoggerState != PdhProcessTraceStart
|
|
&& CurrentContext->LoggerState != PdhProcessTraceEnd
|
|
&& CurrentContext->LoggerState != PdhProcessTraceFirstPath) {
|
|
CurrentContext->LoggerState = PdhProcessTraceRewind;
|
|
SetEvent(CurrentContext->hSyncWMI);
|
|
WaitForSingleObject(CurrentContext->hSyncPDH, INFINITE);
|
|
}
|
|
Status = ERROR_SUCCESS;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
PDH_FUNCTION
|
|
PdhiReadWmiHeaderRecord(
|
|
PPDHI_LOG pLog,
|
|
LPVOID pRecord,
|
|
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
|
|
//
|
|
Status = PdhWmiEnsureFirstRun(CurrentContext);
|
|
if (Status == ERROR_SUCCESS) {
|
|
Status = PdhiGetCounterPathRecord(CurrentContext, pRecord, dwMaxSize);
|
|
pLog->pLastRecordRead = CurrentContext->CounterPathBuffer;
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
PDH_FUNCTION
|
|
PdhiBuildDataBlock(
|
|
PPDHI_LOG pLog,
|
|
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(
|
|
PPDHI_LOG pLog,
|
|
LPVOID pRecord,
|
|
DWORD dwMaxSize,
|
|
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
|
|
//
|
|
Status = PdhWmiEnsureFirstRun(CurrentContext);
|
|
if (Status != ERROR_SUCCESS) {
|
|
goto Cleanup;
|
|
}
|
|
|
|
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;
|
|
pLog->llFileSize = DataBlockInfo.CurrentTime;
|
|
}
|
|
|
|
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(
|
|
PPDHI_LOG pLog,
|
|
ULONGLONG TimeStamp,
|
|
LPVOID pRecord,
|
|
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;
|
|
}
|
|
|
|
// Wait until logfiles are scaned first to collect
|
|
// 1) Counter Path information
|
|
// 2) Time Range information
|
|
//
|
|
Status = PdhWmiEnsureFirstRun(CurrentContext);
|
|
if (Status != ERROR_SUCCESS) {
|
|
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;
|
|
}
|
|
|
|
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;
|
|
pLog->llFileSize = DataBlockInfo.CurrentTime;
|
|
}
|
|
|
|
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(
|
|
PPDHI_LOG pLog,
|
|
LPDWORD pdwNumEntries,
|
|
PPDH_TIME_INFO pInfo,
|
|
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
|
|
//
|
|
Status = PdhWmiEnsureFirstRun(CurrentContext);
|
|
if (Status != ERROR_SUCCESS) {
|
|
return Status;
|
|
}
|
|
|
|
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(
|
|
PPDHI_LOG pLog,
|
|
LPCWSTR szMachineName,
|
|
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(
|
|
PPDHI_LOG pLog,
|
|
LPCWSTR szMachineName,
|
|
DWORD dwLangId,
|
|
LPCWSTR szObjectName,
|
|
DWORD dwObjectId,
|
|
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);
|
|
StringCchCopyW(pPerfObject->szObjectName, lstrlenW(szObjectName) + 1, szObjectName);
|
|
InsertTailList(& pPerfMachine->LogObjectList, & pPerfObject->Entry);
|
|
|
|
Cleanup:
|
|
return pPerfObject;
|
|
}
|
|
|
|
DWORD
|
|
PdhWmiGetLogPerfIndexByName(
|
|
PPDHI_LOG pLog,
|
|
LPCWSTR szMachineName,
|
|
DWORD dwLangId,
|
|
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(
|
|
PPDHI_LOG pLog,
|
|
LPCWSTR szMachineName,
|
|
DWORD dwLangId,
|
|
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
|
|
//
|
|
ZeroMemory(szNumber, sizeof(szNumber));
|
|
_ltow(dwIndex, szNumber, 10);
|
|
pszReturnName = szNumber;
|
|
}
|
|
return pszReturnName;
|
|
}
|
|
|
|
PPDHI_BINARY_LOG_RECORD_HEADER
|
|
PdhiGetWmiSubRecord(
|
|
PPDHI_LOG pLog,
|
|
PPDHI_BINARY_LOG_RECORD_HEADER pRecord,
|
|
DWORD dwRecordId,
|
|
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;
|
|
}
|
|
}
|
|
|
|
__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(
|
|
PPDHI_LOG pLog,
|
|
PPERF_DATA_BLOCK pDataBlock,
|
|
LPCWSTR szMachineName,
|
|
LPCWSTR szObjectName,
|
|
DWORD dwObjectId,
|
|
DWORD dwLangId,
|
|
PDHI_COUNTER_TABLE CounterTable
|
|
)
|
|
{
|
|
PDH_STATUS Status = ERROR_SUCCESS;
|
|
PPERF_OBJECT_TYPE pObjectDef = GetObjectDefByTitleIndex(pDataBlock, dwObjectId);
|
|
PPERF_COUNTER_DEFINITION pCountDef;
|
|
PPERF_INSTANCE_DEFINITION pInstDef;
|
|
DWORD dwItems;
|
|
LPWSTR szItemName;
|
|
DWORD dwItemLen;
|
|
WCHAR szInstanceName[PDH_MAX_COUNTER_PATH];
|
|
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;
|
|
}
|
|
|
|
pCountDef = FirstCounter(pObjectDef);
|
|
if (pCountDef == NULL) {
|
|
Status = PDH_NO_COUNTERS;
|
|
goto Cleanup;
|
|
}
|
|
|
|
dwItems = 0;
|
|
while (pCountDef != NULL && 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(pObjectDef, pCountDef);
|
|
}
|
|
|
|
if (pFirstInstList == NULL) {
|
|
Status = PDH_NO_COUNTERS;
|
|
goto Cleanup;
|
|
}
|
|
|
|
if (pObjectDef->NumInstances != PERF_NO_INSTANCES) {
|
|
dwItems = 0;
|
|
pInstDef = FirstInstance(pObjectDef);
|
|
while (pInstDef != NULL && dwItems < (DWORD) pObjectDef->NumInstances) {
|
|
ZeroMemory(szInstanceName, sizeof(WCHAR) * PDH_MAX_COUNTER_PATH);
|
|
dwItemLen = GetFullInstanceNameStr(pDataBlock, pObjectDef, pInstDef, szInstanceName, PDH_MAX_COUNTER_PATH);
|
|
if (dwItemLen > 0) {
|
|
Status = PdhiFindInstance(& pFirstInstList->InstList,
|
|
szInstanceName,
|
|
(lstrcmpiW(szInstanceName, gszTotal) == 0) ? FALSE : TRUE,
|
|
& pInstance);
|
|
}
|
|
dwItems ++;
|
|
pInstDef = NextInstance(pObjectDef, pInstDef);
|
|
}
|
|
}
|
|
|
|
Cleanup:
|
|
return Status;
|
|
}
|
|
|
|
PPERF_DATA_BLOCK
|
|
PdhWmiMergeObjectBlock(
|
|
PPDHI_LOG pLog,
|
|
LPWSTR szMachine,
|
|
PPDHI_BINARY_LOG_RECORD_HEADER pThisMasterRecord,
|
|
PPDHI_BINARY_LOG_RECORD_HEADER pThisSubRecord
|
|
)
|
|
{
|
|
PPERF_DATA_BLOCK pDataBlock = (PPERF_DATA_BLOCK)
|
|
((LPBYTE) pThisSubRecord + sizeof(PDHI_BINARY_LOG_RECORD_HEADER));
|
|
DWORD dwType = pThisMasterRecord->dwType;
|
|
DWORD dwSize = sizeof(PDHI_BINARY_LOG_RECORD_HEADER);
|
|
DWORD dwTotal = pThisMasterRecord->dwLength;
|
|
DWORD dwCopied = 0;
|
|
LPWSTR szLocalMachine;
|
|
LPDWORD pdwMachine;
|
|
LARGE_INTEGER PerfTime;
|
|
LPDWORD pdwCopied;
|
|
PPDHI_BINARY_LOG_RECORD_HEADER pThisRecord = NULL;
|
|
PPERF_DATA_BLOCK pRtnBlock = NULL;
|
|
PPERF_DATA_BLOCK pBlock = NULL;
|
|
PPERF_OBJECT_TYPE pObject = NULL;
|
|
|
|
PPDH_LOGGER_CONTEXT CurrentContext;
|
|
PPDHI_BINARY_LOG_HEADER_RECORD pBinLogHeader;
|
|
DWORD dwCtrTotal;
|
|
DWORD dwCtrSize;
|
|
PPDHI_LOG_COUNTER_PATH pPath;
|
|
|
|
|
|
if (pLog->pPerfmonInfo != NULL) {
|
|
szLocalMachine = (LPWSTR) (((LPBYTE) pLog->pPerfmonInfo) + sizeof(LARGE_INTEGER)
|
|
+ sizeof(LONGLONG) + sizeof(LONGLONG));
|
|
if (lstrcmpiW(szLocalMachine, szMachine) != 0) {
|
|
G_FREE(pLog->pPerfmonInfo);
|
|
pLog->pPerfmonInfo = NULL;
|
|
}
|
|
else {
|
|
RtlCopyMemory(& PerfTime, pLog->pPerfmonInfo, sizeof(LARGE_INTEGER));
|
|
|
|
if (PerfTime.QuadPart != pDataBlock->PerfTime.QuadPart) {
|
|
G_FREE(pLog->pPerfmonInfo);
|
|
pLog->pPerfmonInfo = NULL;
|
|
}
|
|
else {
|
|
dwCopied = * (LPDWORD) (((LPBYTE) pLog->pPerfmonInfo) + sizeof(LARGE_INTEGER));
|
|
if (dwCopied != 0) {
|
|
pdwMachine = (LPDWORD) (((LPBYTE) pLog->pPerfmonInfo) + sizeof(LARGE_INTEGER) + sizeof(LONGLONG));
|
|
pDataBlock = (PPERF_DATA_BLOCK)
|
|
(((LPBYTE) pdwMachine) + sizeof(LONGLONG) + (* pdwMachine));
|
|
}
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
}
|
|
|
|
CurrentContext = (PPDH_LOGGER_CONTEXT) pLog->lpMappedFileBase;
|
|
if (GetLoggerContext(CurrentContext) >= ContextCount) {
|
|
goto Cleanup;
|
|
}
|
|
|
|
pBinLogHeader = (PPDHI_BINARY_LOG_HEADER_RECORD) CurrentContext->CounterPathBuffer;
|
|
if (pBinLogHeader == NULL) {
|
|
goto Cleanup;
|
|
}
|
|
dwCtrTotal = pBinLogHeader->RecHeader.dwLength;
|
|
dwCtrSize = sizeof(PDHI_BINARY_LOG_HEADER_RECORD);
|
|
pPath = (PPDHI_LOG_COUNTER_PATH) (PPDHI_LOG_COUNTER_PATH) (((LPBYTE) pBinLogHeader) + dwCtrSize);
|
|
|
|
dwCopied = QWORD_MULTIPLE((lstrlenW(szMachine) + 1) * sizeof(WCHAR));
|
|
pLog->pPerfmonInfo = G_ALLOC(dwTotal + sizeof(LARGE_INTEGER) + sizeof(LONGLONG) + sizeof(LONGLONG) + dwCopied);
|
|
if (pLog->pPerfmonInfo == NULL) goto Cleanup;
|
|
|
|
pdwMachine = (LPDWORD) (((LPBYTE) pLog->pPerfmonInfo) + sizeof(LARGE_INTEGER) + sizeof(LONGLONG));
|
|
* pdwMachine = dwCopied;
|
|
szLocalMachine = (LPWSTR) (((LPBYTE) pdwMachine) + sizeof(LONGLONG));
|
|
StringCbCopyW(szLocalMachine, dwCopied, szMachine);
|
|
|
|
pRtnBlock = (PPERF_DATA_BLOCK) (((LPBYTE) szLocalMachine) + dwCopied);
|
|
dwCopied = 0;
|
|
|
|
if (dwSize >= dwTotal) {
|
|
pThisRecord = NULL;
|
|
}
|
|
else {
|
|
pThisRecord = (PPDHI_BINARY_LOG_RECORD_HEADER)
|
|
(((LPBYTE) pThisMasterRecord) + sizeof(PDHI_BINARY_LOG_RECORD_HEADER));
|
|
}
|
|
|
|
while (pThisRecord != NULL) {
|
|
dwSize += pThisRecord->dwLength;
|
|
if (pThisRecord->dwLength > 0 && (WORD)(pThisRecord->dwType & 0x0000FFFF) == BINLOG_START_WORD) {
|
|
szLocalMachine = (pPath->lMachineNameOffset != 0xFFFFFFFF)
|
|
? (LPWSTR) (((LPBYTE) & (pPath->Buffer[0])) + pPath->lMachineNameOffset)
|
|
: szMachine;
|
|
if (lstrcmpiW(szLocalMachine, szMachine) == 0) {
|
|
if (pThisRecord->dwType == BINLOG_TYPE_DATA_LOC_OBJECT) {
|
|
pBlock = (PPERF_DATA_BLOCK) (((LPBYTE) pThisRecord) + sizeof(PDHI_BINARY_LOG_RECORD_HEADER));
|
|
if (dwCopied == 0) {
|
|
RtlCopyMemory(pRtnBlock, pBlock, pBlock->TotalByteLength);
|
|
dwCopied = pBlock->TotalByteLength;
|
|
}
|
|
else {
|
|
PPERF_OBJECT_TYPE pEndObject = (PPERF_OBJECT_TYPE) (((LPBYTE) pBlock) + pBlock->TotalByteLength);
|
|
|
|
pObject = FirstObject(pBlock);
|
|
if ((pObject != NULL) && (pObject < pEndObject)
|
|
&& (pObject->TotalByteLength < pBlock->TotalByteLength)) {
|
|
RtlCopyMemory((((LPBYTE) pRtnBlock) + dwCopied), pObject, pObject->TotalByteLength);
|
|
dwCopied += pObject->TotalByteLength;
|
|
pRtnBlock->TotalByteLength = dwCopied;
|
|
pRtnBlock->NumObjectTypes ++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
dwCtrSize += pPath->dwLength;
|
|
if (dwCtrSize >= dwCtrTotal) {
|
|
pThisRecord = NULL;
|
|
}
|
|
else if (dwSize >= dwTotal) {
|
|
pThisRecord = NULL;
|
|
}
|
|
else {
|
|
pPath = (PPDHI_LOG_COUNTER_PATH) (((LPBYTE) pPath) + pPath->dwLength);
|
|
pThisRecord = (PPDHI_BINARY_LOG_RECORD_HEADER) (((LPBYTE) pThisRecord) + pThisRecord->dwLength);
|
|
}
|
|
}
|
|
else {
|
|
pThisRecord = NULL;
|
|
}
|
|
}
|
|
|
|
pdwCopied = (LPDWORD) (((LPBYTE) pLog->pPerfmonInfo) + sizeof(LARGE_INTEGER));
|
|
* pdwCopied = dwCopied;
|
|
|
|
if (dwCopied == 0) {
|
|
G_FREE(pRtnBlock);
|
|
}
|
|
else {
|
|
RtlCopyMemory(pLog->pPerfmonInfo, & pRtnBlock->PerfTime, sizeof(LARGE_INTEGER));
|
|
pDataBlock = pRtnBlock;
|
|
}
|
|
|
|
Cleanup:
|
|
return pDataBlock;
|
|
}
|
|
|
|
PDH_FUNCTION
|
|
PdhiEnumMachinesFromWmiLog(
|
|
PPDHI_LOG pLog,
|
|
LPVOID pBuffer,
|
|
LPDWORD lpdwBufferSize,
|
|
BOOL bUnicodeDest
|
|
)
|
|
{
|
|
PDH_STATUS Status = ERROR_SUCCESS;
|
|
PPDH_LOGGER_CONTEXT CurrentContext = (PPDH_LOGGER_CONTEXT) pLog->lpMappedFileBase;
|
|
DWORD dwBufferUsed = 0;
|
|
DWORD dwNewBuffer = 0;
|
|
DWORD dwItemCount = 0;
|
|
LPVOID LocalBuffer = NULL;
|
|
LPVOID TempBuffer = NULL;
|
|
DWORD LocalBufferSize = 0;
|
|
PPDHI_LOG_MACHINE pMachine;
|
|
DWORD dwLogger;
|
|
|
|
if (GetLoggerContext(CurrentContext) >= ContextCount) {
|
|
Status = PDH_INVALID_ARGUMENT;
|
|
}
|
|
else {
|
|
Status = PdhWmiEnsureFirstRun(CurrentContext);
|
|
if (Status == ERROR_SUCCESS) {
|
|
LocalBufferSize = MEDIUM_BUFFER_SIZE;
|
|
LocalBuffer = G_ALLOC(LocalBufferSize * (bUnicodeDest ? sizeof(WCHAR) : sizeof(CHAR)));
|
|
if (LocalBuffer == NULL) {
|
|
Status = PDH_MEMORY_ALLOCATION_FAILURE;
|
|
goto Cleanup;
|
|
}
|
|
|
|
dwItemCount = 0;
|
|
dwBufferUsed = 0;
|
|
dwItemCount = 0;
|
|
for (dwLogger = 0; dwLogger < CurrentContext->LoggerCount; dwLogger ++) {
|
|
for (pMachine = CurrentContext->LogInfo[dwLogger].MachineList;
|
|
pMachine != NULL; pMachine = pMachine->next) {
|
|
if (pMachine->szMachine != NULL) {
|
|
dwNewBuffer = lstrlenW(pMachine->szMachine) + 1;
|
|
while (LocalBufferSize < (dwBufferUsed + dwNewBuffer)) {
|
|
TempBuffer = LocalBuffer;
|
|
LocalBufferSize += MEDIUM_BUFFER_SIZE;
|
|
LocalBuffer = G_REALLOC(TempBuffer,
|
|
LocalBufferSize * (bUnicodeDest ? sizeof(WCHAR) : sizeof(CHAR)));
|
|
if (LocalBuffer == NULL) {
|
|
if (TempBuffer != NULL) G_FREE(TempBuffer);
|
|
Status = PDH_MEMORY_ALLOCATION_FAILURE;
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
Status = AddUniqueWideStringToMultiSz((LPVOID) LocalBuffer,
|
|
pMachine->szMachine,
|
|
LocalBufferSize - dwBufferUsed,
|
|
& dwNewBuffer,
|
|
bUnicodeDest);
|
|
if (Status == ERROR_SUCCESS) {
|
|
if (dwNewBuffer > 0) {
|
|
dwBufferUsed = dwNewBuffer;
|
|
dwItemCount ++;
|
|
}
|
|
}
|
|
else {
|
|
// PDH_MORE_DATA should not happen because we enlarge buffer before
|
|
// AddUniqueWideStringToMultiSz() call.
|
|
if (Status == PDH_MORE_DATA) Status = PDH_INVALID_DATA;
|
|
break;
|
|
}
|
|
}
|
|
else {
|
|
dwNewBuffer = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (Status == ERROR_SUCCESS) {
|
|
if (dwItemCount > 0) {
|
|
dwBufferUsed ++;
|
|
}
|
|
if (pBuffer && (dwBufferUsed <= * lpdwBufferSize)) {
|
|
RtlCopyMemory(pBuffer, LocalBuffer, dwBufferUsed * (bUnicodeDest ? sizeof(WCHAR) : sizeof(CHAR)));
|
|
}
|
|
else {
|
|
if (pBuffer) RtlCopyMemory(pBuffer,
|
|
LocalBuffer,
|
|
(* lpdwBufferSize) * (bUnicodeDest ? sizeof(WCHAR) : sizeof(CHAR)));
|
|
Status = PDH_MORE_DATA;
|
|
}
|
|
* lpdwBufferSize = dwBufferUsed;
|
|
}
|
|
|
|
Cleanup:
|
|
if (LocalBuffer != NULL) G_FREE(LocalBuffer);
|
|
return Status;
|
|
}
|
|
|
|
PDH_FUNCTION
|
|
PdhiEnumObjectsFromWmiLog(
|
|
PPDHI_LOG pLog,
|
|
LPCWSTR szMachineName,
|
|
LPVOID pBuffer,
|
|
LPDWORD pcchBufferSize,
|
|
DWORD dwDetailLevel,
|
|
BOOL bUnicodeDest
|
|
)
|
|
{
|
|
PDH_STATUS Status = ERROR_SUCCESS;
|
|
PPDH_LOGGER_CONTEXT CurrentContext = (PPDH_LOGGER_CONTEXT) pLog->lpMappedFileBase;
|
|
DWORD dwBufferUsed = 0;
|
|
DWORD dwNewBuffer = 0;
|
|
DWORD dwItemCount = 0;
|
|
LPVOID LocalBuffer = NULL;
|
|
LPVOID TempBuffer = NULL;
|
|
DWORD LocalBufferSize = 0;
|
|
PPDHI_LOG_MACHINE pMachine = NULL;
|
|
PPDHI_LOG_OBJECT pObject = NULL;
|
|
LPWSTR szLocMachine = (LPWSTR) szMachineName;
|
|
DWORD dwLogger;
|
|
BOOL bNoMachine = TRUE;
|
|
|
|
UNREFERENCED_PARAMETER(dwDetailLevel);
|
|
|
|
if (GetLoggerContext(CurrentContext) >= ContextCount) {
|
|
Status = PDH_INVALID_ARGUMENT;
|
|
}
|
|
else {
|
|
Status = PdhWmiEnsureFirstRun(CurrentContext);
|
|
if (Status == ERROR_SUCCESS) {
|
|
|
|
LocalBufferSize = MEDIUM_BUFFER_SIZE;
|
|
LocalBuffer = G_ALLOC(LocalBufferSize * (bUnicodeDest ? sizeof(WCHAR) : sizeof(CHAR)));
|
|
if (LocalBuffer == NULL) {
|
|
Status = PDH_MEMORY_ALLOCATION_FAILURE;
|
|
goto Cleanup;
|
|
}
|
|
|
|
if (szLocMachine == NULL) szLocMachine = (LPWSTR) szStaticLocalMachineName;
|
|
|
|
dwBufferUsed = 0;
|
|
dwNewBuffer = 0;
|
|
dwItemCount = 0;
|
|
|
|
for (dwLogger = 0; dwLogger < CurrentContext->LoggerCount; dwLogger ++) {
|
|
for (pMachine = CurrentContext->LogInfo[dwLogger].MachineList;
|
|
pMachine != NULL; pMachine = pMachine->next) {
|
|
if (lstrcmpiW(pMachine->szMachine, szLocMachine) == 0) break;
|
|
}
|
|
if (pMachine == NULL) continue;
|
|
|
|
bNoMachine = FALSE;
|
|
for (pObject = pMachine->ObjList; pObject != NULL; pObject = pObject->next) {
|
|
if (pObject->szObject != NULL) {
|
|
dwNewBuffer = (lstrlenW(pObject->szObject) + 1);
|
|
while (LocalBufferSize < (dwBufferUsed + dwNewBuffer)) {
|
|
LocalBufferSize += MEDIUM_BUFFER_SIZE;
|
|
TempBuffer = LocalBuffer;
|
|
LocalBuffer = G_REALLOC(TempBuffer,
|
|
LocalBufferSize * (bUnicodeDest ? sizeof(WCHAR) : sizeof(CHAR)));
|
|
if (LocalBuffer == NULL) {
|
|
if (TempBuffer != NULL) G_FREE(TempBuffer);
|
|
Status = PDH_MEMORY_ALLOCATION_FAILURE;
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
Status = AddUniqueWideStringToMultiSz((LPVOID) LocalBuffer,
|
|
pObject->szObject,
|
|
LocalBufferSize - dwBufferUsed,
|
|
& dwNewBuffer,
|
|
bUnicodeDest);
|
|
if (Status == ERROR_SUCCESS) {
|
|
if (dwNewBuffer > 0) {
|
|
dwBufferUsed = dwNewBuffer;
|
|
dwItemCount ++;
|
|
}
|
|
}
|
|
else {
|
|
// PDH_MORE_DATA should not happen because we enlarge buffer before
|
|
// AddUniqueWideStringToMultiSz() call.
|
|
if (Status == PDH_MORE_DATA) Status = PDH_INVALID_DATA;
|
|
break;
|
|
}
|
|
}
|
|
else {
|
|
dwNewBuffer = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (Status == ERROR_SUCCESS) {
|
|
if (bNoMachine) {
|
|
Status = PDH_CSTATUS_NO_MACHINE;
|
|
}
|
|
else if (dwItemCount == 0) {
|
|
Status = PDH_CSTATUS_NO_OBJECT;
|
|
}
|
|
else {
|
|
dwBufferUsed ++;
|
|
}
|
|
if (Status == ERROR_SUCCESS && dwBufferUsed > 0) {
|
|
if (pBuffer && (dwBufferUsed <= * pcchBufferSize)) {
|
|
RtlCopyMemory(pBuffer, LocalBuffer, dwBufferUsed * (bUnicodeDest ? sizeof(WCHAR) : sizeof(CHAR)));
|
|
}
|
|
else {
|
|
if (pBuffer) RtlCopyMemory(pBuffer,
|
|
LocalBuffer,
|
|
(* pcchBufferSize) * (bUnicodeDest ? sizeof(WCHAR) : sizeof(CHAR)));
|
|
Status = PDH_MORE_DATA;
|
|
}
|
|
}
|
|
* pcchBufferSize = dwBufferUsed;
|
|
}
|
|
|
|
Cleanup:
|
|
G_FREE(LocalBuffer);
|
|
return Status;
|
|
}
|
|
|
|
PDH_FUNCTION
|
|
PdhiEnumObjectItemsFromWmiLog(
|
|
PPDHI_LOG pLog,
|
|
LPCWSTR szMachineName,
|
|
LPCWSTR szObjectName,
|
|
PDHI_COUNTER_TABLE CounterTable,
|
|
DWORD dwDetailLevel,
|
|
DWORD dwFlags
|
|
)
|
|
{
|
|
DWORD dwTempBufferSize;
|
|
LPVOID pTempBuffer = NULL;
|
|
LPVOID ptrTemp;
|
|
PDH_STATUS pdhStatus = ERROR_SUCCESS;
|
|
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[PDH_MAX_COUNTER_PATH];
|
|
DWORD dwRecordLength;
|
|
BOOL bCopyThisObject;
|
|
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;
|
|
}
|
|
|
|
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->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) {
|
|
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);
|
|
StringCchPrintfW(szCompositeInstance, PDH_MAX_COUNTER_PATH, L"%ws%ws%ws",
|
|
szThisParentName, cszSlash, szThisInstanceName);
|
|
}
|
|
else {
|
|
StringCchCopyW(szCompositeInstance, PDH_MAX_COUNTER_PATH, szThisInstanceName);
|
|
}
|
|
|
|
if (pPath->dwIndex > 0 && pPath->dwIndex != PERF_NO_UNIQUE_ID) {
|
|
StringCchCatW(szCompositeInstance, PDH_MAX_COUNTER_PATH, L"#");
|
|
_ltow(pPath->dwIndex, (LPWSTR)(szCompositeInstance + lstrlenW(szCompositeInstance)), 10L);
|
|
}
|
|
pdhStatus = PdhiFindInstance(& pInstList->InstList,
|
|
szCompositeInstance,
|
|
(lstrcmpiW(szCompositeInstance, gszTotal) == 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_LOC_OBJECT) {
|
|
PPERF_DATA_BLOCK pTmpBlock = (PPERF_DATA_BLOCK)
|
|
((LPBYTE) pThisSubRecord + sizeof(PDHI_BINARY_LOG_RECORD_HEADER));
|
|
pPerfBlock = PdhWmiMergeObjectBlock(
|
|
pLog, (LPWSTR) szMachineName, pThisMasterRecord, pThisSubRecord);
|
|
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, gszTotal) == 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_MORE_DATA) {
|
|
pdhStatus = ERROR_SUCCESS;
|
|
}
|
|
|
|
Cleanup:
|
|
G_FREE(pTempBuffer);
|
|
return pdhStatus;
|
|
}
|
|
|
|
PDH_FUNCTION
|
|
PdhiGetWmiLogCounterInfo(
|
|
PPDHI_LOG pLog,
|
|
PPDHI_COUNTER pCounter
|
|
)
|
|
{
|
|
PDH_STATUS Status = ERROR_SUCCESS;
|
|
DWORD dwObjectId;
|
|
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;
|
|
PPERF_OBJECT_TYPE pPerfObject = NULL;
|
|
DWORD dwItems = 0;
|
|
PPERF_COUNTER_DEFINITION pPerfCounter;
|
|
PPERF_INSTANCE_DEFINITION pPerfInstance;
|
|
PPDH_LOGGER_CONTEXT CurrentContext;
|
|
BOOL bNeedEnumerate = TRUE;
|
|
|
|
dwObjectId = PdhWmiGetLogPerfIndexByName(
|
|
pLog, pCounter->pCounterPath->szMachineName, 9, pCounter->pCounterPath->szObjectName);
|
|
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((PDH_HLOG) pLog,
|
|
pCounter->pCounterPath->szMachineName,
|
|
pCounter->pCounterPath->szObjectName,
|
|
NULL,
|
|
& dwCounterSize,
|
|
NULL,
|
|
& dwInstanceSize,
|
|
0,
|
|
0,
|
|
TRUE);
|
|
if (Status != ERROR_SUCCESS && Status != PDH_MORE_DATA) {
|
|
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);
|
|
if (pPerfCounter != NULL) {
|
|
while (pPerfCounter != NULL && 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(pPerfObject, 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 != NULL) {
|
|
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;
|
|
}
|
|
}
|
|
else {
|
|
Status = PDH_ENTRY_NOT_IN_LOG_FILE;
|
|
}
|
|
}
|
|
|
|
Cleanup:
|
|
return Status;
|
|
}
|
|
|
|
PDH_FUNCTION
|
|
PdhiGetWmiLogFileSize(
|
|
PPDHI_LOG pLog,
|
|
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 += (((LONGLONG) 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 + (((LONGLONG) 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;
|
|
}
|