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;
}
예제 #2
0
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);
			}
		}
	}
}
예제 #3
0
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;
        }
    }
}