/*++ Copyright (C) 1996-1999 Microsoft Corporation Module Name: log_wmi.c Abstract: --*/ #include #include #include #include #include #include #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 #include #include #include #include #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; }