563 lines
17 KiB
C
563 lines
17 KiB
C
/*
|
|
* Process Hacker Extended Tools -
|
|
* ETW monitoring
|
|
*
|
|
* Copyright (C) 2010-2015 wj32
|
|
*
|
|
* This file is part of Process Hacker.
|
|
*
|
|
* Process Hacker is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* Process Hacker is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "exttools.h"
|
|
#include "etwmon.h"
|
|
|
|
ULONG NTAPI EtpEtwBufferCallback(
|
|
_In_ PEVENT_TRACE_LOGFILE Buffer
|
|
);
|
|
|
|
VOID NTAPI EtpEtwEventCallback(
|
|
_In_ PEVENT_RECORD EventRecord
|
|
);
|
|
|
|
NTSTATUS EtpEtwMonitorThreadStart(
|
|
_In_ PVOID Parameter
|
|
);
|
|
|
|
ULONG EtpStopEtwRundownSession(
|
|
VOID
|
|
);
|
|
|
|
ULONG NTAPI EtpRundownEtwBufferCallback(
|
|
_In_ PEVENT_TRACE_LOGFILE Buffer
|
|
);
|
|
|
|
VOID NTAPI EtpRundownEtwEventCallback(
|
|
_In_ PEVENT_RECORD EventRecord
|
|
);
|
|
|
|
NTSTATUS EtpRundownEtwMonitorThreadStart(
|
|
_In_ PVOID Parameter
|
|
);
|
|
|
|
static GUID ProcessHackerGuid = { 0x1288c53b, 0xaf35, 0x481b, { 0xb6, 0xb5, 0xa0, 0x5c, 0x39, 0x87, 0x2e, 0xd } };
|
|
static GUID SystemTraceControlGuid_I = { 0x9e814aad, 0x3204, 0x11d2, { 0x9a, 0x82, 0x00, 0x60, 0x08, 0xa8, 0x69, 0x39 } };
|
|
static GUID KernelRundownGuid_I = { 0x3b9c9951, 0x3480, 0x4220, { 0x93, 0x77, 0x9c, 0x8e, 0x51, 0x84, 0xf5, 0xcd } };
|
|
static GUID DiskIoGuid_I = { 0x3d6fa8d4, 0xfe05, 0x11d0, { 0x9d, 0xda, 0x00, 0xc0, 0x4f, 0xd7, 0xba, 0x7c } };
|
|
static GUID FileIoGuid_I = { 0x90cbdc39, 0x4a3e, 0x11d1, { 0x84, 0xf4, 0x00, 0x00, 0xf8, 0x04, 0x64, 0xe3 } };
|
|
static GUID TcpIpGuid_I = { 0x9a280ac0, 0xc8e0, 0x11d1, { 0x84, 0xe2, 0x00, 0xc0, 0x4f, 0xb9, 0x98, 0xa2 } };
|
|
static GUID UdpIpGuid_I = { 0xbf3a50c5, 0xa9c9, 0x4988, { 0xa0, 0x05, 0x2d, 0xf0, 0xb7, 0xc8, 0x0f, 0x80 } };
|
|
|
|
// ETW tracing layer
|
|
|
|
BOOLEAN EtEtwEnabled;
|
|
static UNICODE_STRING EtpSharedKernelLoggerName = RTL_CONSTANT_STRING(KERNEL_LOGGER_NAME);
|
|
static UNICODE_STRING EtpPrivateKernelLoggerName = RTL_CONSTANT_STRING(L"PhEtKernelLogger");
|
|
static TRACEHANDLE EtpSessionHandle;
|
|
static PUNICODE_STRING EtpActualKernelLoggerName;
|
|
static PGUID EtpActualSessionGuid;
|
|
static PEVENT_TRACE_PROPERTIES EtpTraceProperties;
|
|
static BOOLEAN EtpEtwActive;
|
|
static BOOLEAN EtpStartedSession;
|
|
static BOOLEAN EtpEtwExiting;
|
|
static HANDLE EtpEtwMonitorThreadHandle;
|
|
|
|
// ETW rundown layer
|
|
|
|
static UNICODE_STRING EtpRundownLoggerName = RTL_CONSTANT_STRING(L"PhEtRundownLogger");
|
|
static TRACEHANDLE EtpRundownSessionHandle;
|
|
static PEVENT_TRACE_PROPERTIES EtpRundownTraceProperties;
|
|
static BOOLEAN EtpRundownActive;
|
|
static HANDLE EtpRundownEtwMonitorThreadHandle;
|
|
|
|
VOID EtEtwMonitorInitialization(
|
|
VOID
|
|
)
|
|
{
|
|
if (PhGetOwnTokenAttributes().Elevated && PhGetIntegerSetting(SETTING_NAME_ENABLE_ETW_MONITOR))
|
|
{
|
|
EtStartEtwSession();
|
|
|
|
if (EtEtwEnabled)
|
|
EtpEtwMonitorThreadHandle = PhCreateThread(0, EtpEtwMonitorThreadStart, NULL);
|
|
}
|
|
}
|
|
|
|
VOID EtEtwMonitorUninitialization(
|
|
VOID
|
|
)
|
|
{
|
|
if (EtEtwEnabled)
|
|
{
|
|
EtpEtwExiting = TRUE;
|
|
EtStopEtwSession();
|
|
}
|
|
|
|
if (EtpRundownActive)
|
|
{
|
|
EtpStopEtwRundownSession();
|
|
}
|
|
}
|
|
|
|
VOID EtStartEtwSession(
|
|
VOID
|
|
)
|
|
{
|
|
ULONG result;
|
|
ULONG bufferSize;
|
|
|
|
if (WindowsVersion >= WINDOWS_8)
|
|
{
|
|
EtpActualKernelLoggerName = &EtpPrivateKernelLoggerName;
|
|
EtpActualSessionGuid = &ProcessHackerGuid;
|
|
}
|
|
else
|
|
{
|
|
EtpActualKernelLoggerName = &EtpSharedKernelLoggerName;
|
|
EtpActualSessionGuid = &SystemTraceControlGuid_I;
|
|
}
|
|
|
|
bufferSize = sizeof(EVENT_TRACE_PROPERTIES) + EtpActualKernelLoggerName->Length + sizeof(WCHAR);
|
|
|
|
if (!EtpTraceProperties)
|
|
EtpTraceProperties = PhAllocate(bufferSize);
|
|
|
|
memset(EtpTraceProperties, 0, sizeof(EVENT_TRACE_PROPERTIES));
|
|
|
|
EtpTraceProperties->Wnode.BufferSize = bufferSize;
|
|
EtpTraceProperties->Wnode.Guid = *EtpActualSessionGuid;
|
|
EtpTraceProperties->Wnode.ClientContext = 1;
|
|
EtpTraceProperties->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
|
|
EtpTraceProperties->MinimumBuffers = 1;
|
|
EtpTraceProperties->LogFileMode = EVENT_TRACE_REAL_TIME_MODE;
|
|
EtpTraceProperties->FlushTimer = 1;
|
|
EtpTraceProperties->EnableFlags = EVENT_TRACE_FLAG_DISK_IO | EVENT_TRACE_FLAG_DISK_FILE_IO | EVENT_TRACE_FLAG_NETWORK_TCPIP;
|
|
EtpTraceProperties->LogFileNameOffset = 0;
|
|
EtpTraceProperties->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
|
|
|
|
if (WindowsVersion >= WINDOWS_8)
|
|
EtpTraceProperties->LogFileMode |= EVENT_TRACE_SYSTEM_LOGGER_MODE;
|
|
|
|
result = StartTrace(&EtpSessionHandle, EtpActualKernelLoggerName->Buffer, EtpTraceProperties);
|
|
|
|
if (result == ERROR_SUCCESS)
|
|
{
|
|
EtEtwEnabled = TRUE;
|
|
EtpEtwActive = TRUE;
|
|
EtpStartedSession = TRUE;
|
|
}
|
|
else if (result == ERROR_ALREADY_EXISTS)
|
|
{
|
|
EtEtwEnabled = TRUE;
|
|
EtpEtwActive = TRUE;
|
|
EtpStartedSession = FALSE;
|
|
// The session already exists.
|
|
//result = ControlTrace(0, EtpActualKernelLoggerName->Buffer, EtpTraceProperties, EVENT_TRACE_CONTROL_UPDATE);
|
|
}
|
|
else
|
|
{
|
|
EtpEtwActive = FALSE;
|
|
EtpStartedSession = FALSE;
|
|
}
|
|
}
|
|
|
|
ULONG EtpControlEtwSession(
|
|
_In_ ULONG ControlCode
|
|
)
|
|
{
|
|
// If we have a session handle, we use that instead of the logger name.
|
|
|
|
EtpTraceProperties->LogFileNameOffset = 0; // make sure it is 0, otherwise ControlTrace crashes
|
|
|
|
return ControlTrace(
|
|
EtpStartedSession ? EtpSessionHandle : 0,
|
|
EtpStartedSession ? NULL : EtpActualKernelLoggerName->Buffer,
|
|
EtpTraceProperties,
|
|
ControlCode
|
|
);
|
|
}
|
|
|
|
VOID EtStopEtwSession(
|
|
VOID
|
|
)
|
|
{
|
|
if (EtEtwEnabled)
|
|
EtpControlEtwSession(EVENT_TRACE_CONTROL_STOP);
|
|
}
|
|
|
|
VOID EtFlushEtwSession(
|
|
VOID
|
|
)
|
|
{
|
|
if (EtEtwEnabled)
|
|
EtpControlEtwSession(EVENT_TRACE_CONTROL_FLUSH);
|
|
}
|
|
|
|
ULONG NTAPI EtpEtwBufferCallback(
|
|
_In_ PEVENT_TRACE_LOGFILE Buffer
|
|
)
|
|
{
|
|
return !EtpEtwExiting;
|
|
}
|
|
|
|
VOID NTAPI EtpEtwEventCallback(
|
|
_In_ PEVENT_RECORD EventRecord
|
|
)
|
|
{
|
|
if (memcmp(&EventRecord->EventHeader.ProviderId, &DiskIoGuid_I, sizeof(GUID)) == 0)
|
|
{
|
|
// DiskIo
|
|
|
|
ET_ETW_DISK_EVENT diskEvent;
|
|
|
|
memset(&diskEvent, 0, sizeof(ET_ETW_DISK_EVENT));
|
|
diskEvent.Type = -1;
|
|
|
|
switch (EventRecord->EventHeader.EventDescriptor.Opcode)
|
|
{
|
|
case EVENT_TRACE_TYPE_IO_READ:
|
|
diskEvent.Type = EtEtwDiskReadType;
|
|
break;
|
|
case EVENT_TRACE_TYPE_IO_WRITE:
|
|
diskEvent.Type = EtEtwDiskWriteType;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (diskEvent.Type != -1)
|
|
{
|
|
DiskIo_TypeGroup1 *data = EventRecord->UserData;
|
|
|
|
if (WindowsVersion >= WINDOWS_8)
|
|
{
|
|
diskEvent.ClientId.UniqueThread = UlongToHandle(data->IssuingThreadId);
|
|
diskEvent.ClientId.UniqueProcess = EtThreadIdToProcessId(diskEvent.ClientId.UniqueThread);
|
|
}
|
|
else
|
|
{
|
|
if (EventRecord->EventHeader.ProcessId != -1)
|
|
{
|
|
diskEvent.ClientId.UniqueProcess = UlongToHandle(EventRecord->EventHeader.ProcessId);
|
|
diskEvent.ClientId.UniqueThread = UlongToHandle(EventRecord->EventHeader.ThreadId);
|
|
}
|
|
}
|
|
|
|
diskEvent.IrpFlags = data->IrpFlags;
|
|
diskEvent.TransferSize = data->TransferSize;
|
|
diskEvent.FileObject = (PVOID)data->FileObject;
|
|
diskEvent.HighResResponseTime = data->HighResResponseTime;
|
|
|
|
EtProcessDiskEvent(&diskEvent);
|
|
EtDiskProcessDiskEvent(&diskEvent);
|
|
}
|
|
}
|
|
else if (memcmp(&EventRecord->EventHeader.ProviderId, &FileIoGuid_I, sizeof(GUID)) == 0)
|
|
{
|
|
// FileIo
|
|
|
|
ET_ETW_FILE_EVENT fileEvent;
|
|
|
|
memset(&fileEvent, 0, sizeof(ET_ETW_FILE_EVENT));
|
|
fileEvent.Type = -1;
|
|
|
|
switch (EventRecord->EventHeader.EventDescriptor.Opcode)
|
|
{
|
|
case 0: // Name
|
|
fileEvent.Type = EtEtwFileNameType;
|
|
break;
|
|
case 32: // FileCreate
|
|
fileEvent.Type = EtEtwFileCreateType;
|
|
break;
|
|
case 35: // FileDelete
|
|
fileEvent.Type = EtEtwFileDeleteType;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (fileEvent.Type != -1)
|
|
{
|
|
FileIo_Name *data = EventRecord->UserData;
|
|
|
|
fileEvent.FileObject = (PVOID)data->FileObject;
|
|
PhInitializeStringRef(&fileEvent.FileName, data->FileName);
|
|
|
|
EtDiskProcessFileEvent(&fileEvent);
|
|
}
|
|
}
|
|
else if (
|
|
memcmp(&EventRecord->EventHeader.ProviderId, &TcpIpGuid_I, sizeof(GUID)) == 0 ||
|
|
memcmp(&EventRecord->EventHeader.ProviderId, &UdpIpGuid_I, sizeof(GUID)) == 0
|
|
)
|
|
{
|
|
// TcpIp/UdpIp
|
|
|
|
ET_ETW_NETWORK_EVENT networkEvent;
|
|
|
|
memset(&networkEvent, 0, sizeof(ET_ETW_NETWORK_EVENT));
|
|
networkEvent.Type = -1;
|
|
|
|
switch (EventRecord->EventHeader.EventDescriptor.Opcode)
|
|
{
|
|
case EVENT_TRACE_TYPE_SEND: // send
|
|
networkEvent.Type = EtEtwNetworkSendType;
|
|
networkEvent.ProtocolType = PH_IPV4_NETWORK_TYPE;
|
|
break;
|
|
case EVENT_TRACE_TYPE_RECEIVE: // receive
|
|
networkEvent.Type = EtEtwNetworkReceiveType;
|
|
networkEvent.ProtocolType = PH_IPV4_NETWORK_TYPE;
|
|
break;
|
|
case EVENT_TRACE_TYPE_SEND + 16: // send ipv6
|
|
networkEvent.Type = EtEtwNetworkSendType;
|
|
networkEvent.ProtocolType = PH_IPV6_NETWORK_TYPE;
|
|
break;
|
|
case EVENT_TRACE_TYPE_RECEIVE + 16: // receive ipv6
|
|
networkEvent.Type = EtEtwNetworkReceiveType;
|
|
networkEvent.ProtocolType = PH_IPV6_NETWORK_TYPE;
|
|
break;
|
|
}
|
|
|
|
if (memcmp(&EventRecord->EventHeader.ProviderId, &TcpIpGuid_I, sizeof(GUID)) == 0)
|
|
networkEvent.ProtocolType |= PH_TCP_PROTOCOL_TYPE;
|
|
else
|
|
networkEvent.ProtocolType |= PH_UDP_PROTOCOL_TYPE;
|
|
|
|
if (networkEvent.Type != -1)
|
|
{
|
|
PH_IP_ENDPOINT source;
|
|
PH_IP_ENDPOINT destination;
|
|
|
|
if (networkEvent.ProtocolType & PH_IPV4_NETWORK_TYPE)
|
|
{
|
|
TcpIpOrUdpIp_IPV4_Header *data = EventRecord->UserData;
|
|
|
|
networkEvent.ClientId.UniqueProcess = UlongToHandle(data->PID);
|
|
networkEvent.TransferSize = data->size;
|
|
|
|
source.Address.Type = PH_IPV4_NETWORK_TYPE;
|
|
source.Address.Ipv4 = data->saddr;
|
|
source.Port = _byteswap_ushort(data->sport);
|
|
destination.Address.Type = PH_IPV4_NETWORK_TYPE;
|
|
destination.Address.Ipv4 = data->daddr;
|
|
destination.Port = _byteswap_ushort(data->dport);
|
|
}
|
|
else if (networkEvent.ProtocolType & PH_IPV6_NETWORK_TYPE)
|
|
{
|
|
TcpIpOrUdpIp_IPV6_Header *data = EventRecord->UserData;
|
|
|
|
networkEvent.ClientId.UniqueProcess = UlongToHandle(data->PID);
|
|
networkEvent.TransferSize = data->size;
|
|
|
|
source.Address.Type = PH_IPV6_NETWORK_TYPE;
|
|
source.Address.In6Addr = data->saddr;
|
|
source.Port = _byteswap_ushort(data->sport);
|
|
destination.Address.Type = PH_IPV6_NETWORK_TYPE;
|
|
destination.Address.In6Addr = data->daddr;
|
|
destination.Port = _byteswap_ushort(data->dport);
|
|
}
|
|
|
|
networkEvent.LocalEndpoint = source;
|
|
|
|
if (networkEvent.ProtocolType & PH_TCP_PROTOCOL_TYPE)
|
|
networkEvent.RemoteEndpoint = destination;
|
|
|
|
EtProcessNetworkEvent(&networkEvent);
|
|
}
|
|
}
|
|
}
|
|
|
|
NTSTATUS EtpEtwMonitorThreadStart(
|
|
_In_ PVOID Parameter
|
|
)
|
|
{
|
|
ULONG result;
|
|
EVENT_TRACE_LOGFILE logFile;
|
|
TRACEHANDLE traceHandle;
|
|
|
|
// See comment in EtEtwProcessesUpdatedCallback.
|
|
if (WindowsVersion >= WINDOWS_8)
|
|
EtUpdateProcessInformation();
|
|
|
|
memset(&logFile, 0, sizeof(EVENT_TRACE_LOGFILE));
|
|
logFile.LoggerName = EtpActualKernelLoggerName->Buffer;
|
|
logFile.ProcessTraceMode = PROCESS_TRACE_MODE_REAL_TIME | PROCESS_TRACE_MODE_EVENT_RECORD;
|
|
logFile.BufferCallback = EtpEtwBufferCallback;
|
|
logFile.EventRecordCallback = EtpEtwEventCallback;
|
|
|
|
while (TRUE)
|
|
{
|
|
result = ERROR_SUCCESS;
|
|
traceHandle = OpenTrace(&logFile);
|
|
|
|
if (traceHandle != INVALID_PROCESSTRACE_HANDLE)
|
|
{
|
|
while (!EtpEtwExiting && (result = ProcessTrace(&traceHandle, 1, NULL, NULL)) == ERROR_SUCCESS)
|
|
NOTHING;
|
|
|
|
CloseTrace(traceHandle);
|
|
}
|
|
|
|
if (EtpEtwExiting)
|
|
break;
|
|
|
|
if (result == ERROR_WMI_INSTANCE_NOT_FOUND)
|
|
{
|
|
// The session was stopped by another program. Try to start it again.
|
|
EtStartEtwSession();
|
|
}
|
|
|
|
// Some error occurred, so sleep for a while before trying again.
|
|
// Don't sleep if we just successfully started a session, though.
|
|
if (!EtpEtwActive)
|
|
Sleep(250);
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
ULONG EtStartEtwRundown(
|
|
VOID
|
|
)
|
|
{
|
|
ULONG result;
|
|
ULONG bufferSize;
|
|
|
|
bufferSize = sizeof(EVENT_TRACE_PROPERTIES) + EtpRundownLoggerName.Length + sizeof(WCHAR);
|
|
|
|
if (!EtpRundownTraceProperties)
|
|
EtpRundownTraceProperties = PhAllocate(bufferSize);
|
|
|
|
memset(EtpRundownTraceProperties, 0, sizeof(EVENT_TRACE_PROPERTIES));
|
|
|
|
EtpRundownTraceProperties->Wnode.BufferSize = bufferSize;
|
|
EtpRundownTraceProperties->Wnode.ClientContext = 1;
|
|
EtpRundownTraceProperties->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
|
|
EtpRundownTraceProperties->MinimumBuffers = 1;
|
|
EtpRundownTraceProperties->LogFileMode = EVENT_TRACE_REAL_TIME_MODE;
|
|
EtpRundownTraceProperties->FlushTimer = 1;
|
|
EtpRundownTraceProperties->LogFileNameOffset = 0;
|
|
EtpRundownTraceProperties->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
|
|
|
|
result = StartTrace(&EtpRundownSessionHandle, EtpRundownLoggerName.Buffer, EtpRundownTraceProperties);
|
|
|
|
if (result == ERROR_ALREADY_EXISTS)
|
|
{
|
|
EtpStopEtwRundownSession();
|
|
// ControlTrace (called from EtpStopEtwRundownSession) screws up the structure.
|
|
EtpRundownTraceProperties->Wnode.BufferSize = bufferSize;
|
|
EtpRundownTraceProperties->LogFileNameOffset = 0;
|
|
EtpRundownTraceProperties->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
|
|
result = StartTrace(&EtpRundownSessionHandle, EtpRundownLoggerName.Buffer, EtpRundownTraceProperties);
|
|
}
|
|
|
|
if (result != ERROR_SUCCESS)
|
|
return result;
|
|
|
|
result = EnableTraceEx(&KernelRundownGuid_I, NULL, EtpRundownSessionHandle, 1, 0, 0x10, 0, 0, NULL);
|
|
|
|
if (result != ERROR_SUCCESS)
|
|
{
|
|
EtpStopEtwRundownSession();
|
|
return result;
|
|
}
|
|
|
|
EtpRundownActive = TRUE;
|
|
EtpRundownEtwMonitorThreadHandle = PhCreateThread(0, EtpRundownEtwMonitorThreadStart, NULL);
|
|
|
|
return result;
|
|
}
|
|
|
|
ULONG EtpStopEtwRundownSession(
|
|
VOID
|
|
)
|
|
{
|
|
EtpRundownTraceProperties->LogFileNameOffset = 0;
|
|
return ControlTrace(0, EtpRundownLoggerName.Buffer, EtpRundownTraceProperties, EVENT_TRACE_CONTROL_STOP);
|
|
}
|
|
|
|
ULONG NTAPI EtpRundownEtwBufferCallback(
|
|
_In_ PEVENT_TRACE_LOGFILE Buffer
|
|
)
|
|
{
|
|
return !EtpEtwExiting;
|
|
}
|
|
|
|
VOID NTAPI EtpRundownEtwEventCallback(
|
|
_In_ PEVENT_RECORD EventRecord
|
|
)
|
|
{
|
|
// TODO: Find a way to call CloseTrace when the enumeration finishes so we can
|
|
// stop the trace cleanly.
|
|
|
|
if (memcmp(&EventRecord->EventHeader.ProviderId, &FileIoGuid_I, sizeof(GUID)) == 0)
|
|
{
|
|
// FileIo
|
|
|
|
ET_ETW_FILE_EVENT fileEvent;
|
|
|
|
memset(&fileEvent, 0, sizeof(ET_ETW_FILE_EVENT));
|
|
fileEvent.Type = -1;
|
|
|
|
switch (EventRecord->EventHeader.EventDescriptor.Opcode)
|
|
{
|
|
case 36: // FileRundown
|
|
fileEvent.Type = EtEtwFileRundownType;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (fileEvent.Type != -1)
|
|
{
|
|
FileIo_Name *data = EventRecord->UserData;
|
|
|
|
fileEvent.FileObject = (PVOID)data->FileObject;
|
|
PhInitializeStringRef(&fileEvent.FileName, data->FileName);
|
|
|
|
EtDiskProcessFileEvent(&fileEvent);
|
|
}
|
|
}
|
|
}
|
|
|
|
NTSTATUS EtpRundownEtwMonitorThreadStart(
|
|
_In_ PVOID Parameter
|
|
)
|
|
{
|
|
EVENT_TRACE_LOGFILE logFile;
|
|
TRACEHANDLE traceHandle;
|
|
|
|
memset(&logFile, 0, sizeof(EVENT_TRACE_LOGFILE));
|
|
logFile.LoggerName = EtpRundownLoggerName.Buffer;
|
|
logFile.ProcessTraceMode = PROCESS_TRACE_MODE_REAL_TIME | PROCESS_TRACE_MODE_EVENT_RECORD;
|
|
logFile.BufferCallback = EtpRundownEtwBufferCallback;
|
|
logFile.EventRecordCallback = EtpRundownEtwEventCallback;
|
|
logFile.Context = &traceHandle;
|
|
|
|
traceHandle = OpenTrace(&logFile);
|
|
|
|
if (traceHandle != INVALID_PROCESSTRACE_HANDLE)
|
|
{
|
|
ProcessTrace(&traceHandle, 1, NULL, NULL);
|
|
|
|
if (traceHandle != 0)
|
|
CloseTrace(traceHandle);
|
|
}
|
|
|
|
NtClose(EtpRundownEtwMonitorThreadHandle);
|
|
EtpRundownEtwMonitorThreadHandle = NULL;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|