ULONG GetTraceEventInfo( __in PEVENT_RECORD Event, __inout PPROCESSING_CONTEXT LogContext, __out PTRACE_EVENT_INFO* EventInfo ) /*++ Routine Description: This routine retrieves the TRACE_EVENT_INFO structure for the passed EVENT_RECORD Event. This structure contains the meta- information about the event. Arguments: Event - Supplies the structure representing an event. EventInfo - Receives the event meta-information. Return Value: ERROR_SUCCESS - Success. Win32 error code - TdhGetEventInformation() failed. --*/ { ULONG Status = ERROR_SUCCESS; PPROCESSING_DATA_CONTEXT DataContext= &LogContext->DataContext; ULONG BufferSize = DataContext->EventInfoBufferSize; do { if (Status == ERROR_INSUFFICIENT_BUFFER) { Status = ResizeBuffer(&DataContext->EventInfoBuffer, &DataContext->EventInfoBufferSize, BufferSize); if (DataContext->EventInfoBuffer == NULL) { return ERROR_OUTOFMEMORY; } DataContext->EventInfoBufferSize = BufferSize; } Status = TdhGetEventInformation(Event, 0, NULL, (PTRACE_EVENT_INFO)DataContext->EventInfoBuffer, &BufferSize); } while (Status == ERROR_INSUFFICIENT_BUFFER); if (Status == ERROR_SUCCESS) { *EventInfo = (PTRACE_EVENT_INFO)DataContext->EventInfoBuffer; } return Status; }
void CALLBACK EventRecordCallback(_In_ EVENT_RECORD* per) { auto data = static_cast<EventTraceData*>(per->UserContext); static std::unordered_map<GUID, std::vector<BYTE>, GuidHash> fragment; if (false) { std::wostringstream s; WCHAR tmp[39]; if (per->EventHeader.ProviderId == __uuidof(Microsoft_Windows_Networking_Correlation)) { s << "C"; } else if (per->EventHeader.ProviderId == __uuidof(Microsoft_Windows_NDIS_PacketCapture)) { s << "P"; } else { StringFromGUID2(per->EventHeader.ProviderId, tmp, ARRAYSIZE(tmp)); s << tmp; } StringFromGUID2(per->EventHeader.ActivityId, tmp, ARRAYSIZE(tmp)); s << ", Activity ID: " << tmp; for (int i = 0; i < per->ExtendedDataCount; ++i) { const auto& e = per->ExtendedData[i]; if (e.ExtType == EVENT_HEADER_EXT_TYPE_RELATED_ACTIVITYID) { const auto& r = *(const EVENT_EXTENDED_ITEM_RELATED_ACTIVITYID*)(e.DataPtr); StringFromGUID2(r.RelatedActivityId, tmp, ARRAYSIZE(tmp)); s << ", RelatedActivityId: " << tmp; } else { s << ", ExtType: " << e.ExtType; } } if (per->UserDataLength <= 26 || *((BYTE*)per->UserData + 24) != 0x08 || *((BYTE*)per->UserData + 25) != 0x00) { if (per->EventHeader.ProviderId == __uuidof(Microsoft_Windows_NDIS_PacketCapture)) { s << " !"; } } if (per->EventHeader.ProviderId != __uuidof(Microsoft_Windows_Networking_Correlation)) { ULONG bufferSize = 0; auto statusSize = TdhGetEventInformation(per, 0, nullptr, nullptr, &bufferSize); if (statusSize != ERROR_INSUFFICIENT_BUFFER) { return; } auto buffer = std::make_unique<std::uint8_t[]>(bufferSize); auto info = reinterpret_cast<TRACE_EVENT_INFO*>(buffer.get()); auto status = TdhGetEventInformation(per, 0, nullptr, info, &bufferSize); if (status != ERROR_SUCCESS) { return; } for (ULONG i = 0; i < info->TopLevelPropertyCount; i++) { const auto& propertyInfo = info->EventPropertyInfoArray[i]; auto name = reinterpret_cast<PCWSTR>(buffer.get() + propertyInfo.NameOffset); if (std::wcscmp(name, L"FragmentSize") != 0) { continue; } PROPERTY_DATA_DESCRIPTOR desc{ reinterpret_cast<uintptr_t>(name), ULONG_MAX, }; ULONG propertyBufferSize; auto statusPropSize = TdhGetPropertySize(per, 0, nullptr, 1, &desc, &propertyBufferSize); if (statusPropSize != ERROR_SUCCESS) { continue; } auto propertyBuffer = std::make_unique<std::uint8_t[]>(propertyBufferSize); auto statusProp = TdhGetProperty(per, 0, nullptr, 1, &desc, propertyBufferSize, propertyBuffer.get()); if (statusProp != ERROR_SUCCESS) { continue; } if ((propertyInfo.Flags & PropertyStruct) != 0) { continue; } if (propertyInfo.nonStructType.InType != TDH_INTYPE_UINT32) { continue; } s << L", Fragment size: " << *reinterpret_cast<UINT32*>(propertyBuffer.get()); } } s << "\r\n"; OutputDebugStringW(s.str().c_str()); } if (per->EventHeader.ProviderId != __uuidof(Microsoft_Windows_NDIS_PacketCapture)) { return; } ULONG bufferSize = 0; auto statusSize = TdhGetEventInformation(per, 0, nullptr, nullptr, &bufferSize); if (statusSize != ERROR_INSUFFICIENT_BUFFER) { return; } auto buffer = std::make_unique<std::uint8_t[]>(bufferSize); auto info = reinterpret_cast<TRACE_EVENT_INFO*>(buffer.get()); auto status = TdhGetEventInformation(per, 0, nullptr, info, &bufferSize); if (status != ERROR_SUCCESS) { return; } for (ULONG i = 0; i < info->TopLevelPropertyCount; i++) { const auto& propertyInfo = info->EventPropertyInfoArray[i]; auto name = reinterpret_cast<PCWSTR>(buffer.get() + propertyInfo.NameOffset); if (std::wcscmp(name, L"Fragment") != 0) { continue; } PROPERTY_DATA_DESCRIPTOR desc{ reinterpret_cast<uintptr_t>(name), ULONG_MAX, }; ULONG propertyBufferSize; auto statusPropSize = TdhGetPropertySize(per, 0, nullptr, 1, &desc, &propertyBufferSize); if (statusPropSize != ERROR_SUCCESS) { continue; } auto propertyBuffer = std::make_unique<std::uint8_t[]>(propertyBufferSize); auto statusProp = TdhGetProperty(per, 0, nullptr, 1, &desc, propertyBufferSize, propertyBuffer.get()); if (statusProp != ERROR_SUCCESS) { continue; } if ((propertyInfo.Flags & PropertyStruct) != 0) { continue; } if (propertyInfo.nonStructType.InType != TDH_INTYPE_BINARY) { continue; } std::wostringstream s; WCHAR tmp[39]; StringFromGUID2(per->EventHeader.ActivityId, tmp, ARRAYSIZE(tmp)); s << tmp << ' ' << std::hex << per->EventHeader.Flags; auto it = fragment.find(per->EventHeader.ActivityId); if (it == fragment.end()) { if ((per->EventHeader.EventDescriptor.Keyword & KeywordPacketEnd) != 0) { data->Packet.push(std::vector<std::uint8_t>(propertyBuffer.get(), propertyBuffer.get() + propertyBufferSize)); } else { fragment.emplace( per->EventHeader.ActivityId, std::vector<std::uint8_t>(propertyBuffer.get(), propertyBuffer.get() + propertyBufferSize)); } } else { it->second.insert( it->second.end(), propertyBuffer.get(), propertyBuffer.get() + propertyBufferSize); if ((per->EventHeader.EventDescriptor.Keyword & KeywordPacketEnd) != 0) { data->Packet.push(std::move(it->second)); fragment.erase(it); } } } }
static void WINAPI _HandleEvent(_In_ PEVENT_RECORD per) { if (!_s_fIsEnding) { PTRACE_EVENT_INFO ptei = nullptr; // Populate ptei. { DWORD cbEventInfo = 0; DWORD status = TdhGetEventInformation(per, 0, nullptr, nullptr, &cbEventInfo); if (ERROR_INSUFFICIENT_BUFFER == status) { ptei = (TRACE_EVENT_INFO*)malloc(cbEventInfo); if (ptei != nullptr) { status = TdhGetEventInformation(per, 0, nullptr, ptei, &cbEventInfo); if (status != ERROR_SUCCESS) { free(ptei); ptei = nullptr; } } } } // Timestamp { FILETIME ft; ft.dwHighDateTime = per->EventHeader.TimeStamp.HighPart; ft.dwLowDateTime = per->EventHeader.TimeStamp.LowPart; SYSTEMTIME st; FileTimeToSystemTime(&ft, &st); SystemTimeToTzSpecificLocalTime(nullptr, &st, &st); wchar_t wszDate[100]; GetDateFormatEx(LOCALE_NAME_INVARIANT, NULL, &st, L"yyyyy-MM-dd", wszDate, ARRAYSIZE(wszDate), nullptr); wchar_t wszTime[100]; GetTimeFormatEx(LOCALE_NAME_INVARIANT, NULL, &st, L"HH:mm:ss", wszTime, ARRAYSIZE(wszTime)); // yyyy-MM-dd HH:mm:ss:fffffff // Windows refuses to give us milliseconds for free, let alone fractions of milliseconds wprintf(L"%s ", wszDate); wprintf(L"%s", wszTime); wprintf(L".%07u, ", ft.dwLowDateTime % ((1000000000 /*nanoseconds per second*/) / (100 /* nanoseconds per interval */))); } // Thread ID wprintf(L"Thread %lu, ", per->EventHeader.ThreadId); // Provider name or GUID { const wchar_t* providerName = ptei ? TEI_PROVIDER_NAME(ptei) : nullptr; if (providerName != nullptr) { wprintf(L"%s, ", (BYTE*)ptei + ptei->ProviderNameOffset); } else { BSTR bstrGuid; if (SUCCEEDED(StringFromCLSID(per->EventHeader.ProviderId, &bstrGuid))) { wprintf(L"%s, ", bstrGuid); ::CoTaskMemFree(bstrGuid); } } } // Task name or id { const wchar_t* taskName = ptei ? TEI_TASK_NAME(ptei) : nullptr; if (taskName != nullptr) { wprintf(L"%s, ", taskName); } else { // printf converts 8-bit chars to 16-bit ints, in case you don't know wprintf(L"%hu, ", per->EventHeader.EventDescriptor.Task); } } // Event ID // wprintf(L"%hu, ", per->EventHeader.EventDescriptor.Id); // Activity ID //{ // BSTR bstrGuid; // if (SUCCEEDED(StringFromCLSID(per->EventHeader.ActivityId, &bstrGuid))) // { // wprintf(L"%s, ", bstrGuid); // ::CoTaskMemFree(bstrGuid); // } //} // Opcode name or ID { wchar_t* opcodeName = ptei ? TEI_OPCODE_NAME(ptei) : nullptr; if (opcodeName != nullptr) { wprintf(L"%s, ", (BYTE*)ptei + ptei->OpcodeNameOffset); } else { wprintf(L"%hu, ", per->EventHeader.EventDescriptor.Opcode); } } // Payload if (EVENT_HEADER_FLAG_STRING_ONLY == (per->EventHeader.Flags & EVENT_HEADER_FLAG_STRING_ONLY)) { wprintf(L"%s", (LPWSTR)per->UserData); } else { for (USHORT i = 0; i < ptei->TopLevelPropertyCount; i++) { DWORD status = PrintProperties(per, ptei, i, nullptr, 0); if (ERROR_SUCCESS != status) { wprintf(L"Printing top level properties failed."); } wprintf(L", "); } } // endl wprintf(L"\r\n"); // combat stdout buffering _flushall(); if (ptei != nullptr) { free(ptei); ptei = nullptr; } } else { if (!_s_fIsClosed) { CloseTrace(*((TRACEHANDLE*)per->UserContext)); _s_fIsClosed = true; } } }