Windows ETW:内核使用者未收到EventCallback或BufferCallback事件 [英] Windows ETW: Kernel consumer receives no EventCallback or BufferCallback events
问题描述
我正在尝试监听ETW内核事件。
i am trying to listen to ETW kernel events.
-
步骤1:致电
OpenTrace
,指定EventCallback
和可选的BufferCallback
函数,这些函数将在我呼叫ProcessTrace
:
Step 1: Call
OpenTrace
, specifying theEventCallback
and optionalBufferCallback
functions that will be called during my call toProcessTrace
:
var
logFile: EVENT_TRACE_LOGFILE;
currentTrace: TRACEHANDLE;
begin
ZeroMemory(@logFile, sizeof(logFile));
logFile.LoggerName := KERNEL_LOGGER_NAME;
logFile.LogFileName := 'C:\Users\Ian\foo.etl';
logFile.ProcessTraceMode := 0;
logFile.EventCallback := RealtimeEventCallback;
logFile.BufferCallback := BufferCallback; //optional
currentTrace := OpenTrace(@logFile);
if (currentTrace = INVALID_PROCESSTRACE_HANDLE) or (currentTrace = -1) then
RaiseLastWin32Error();
步骤2:启用内核事件。通过调用 StartTrace
。就我而言,我想跟踪内核中断( EVENT_TRACE_FLAG_INTERRUPT
)和延迟的过程调用( EVENT_TRACE_FLAG_DPC
):
Step 2: Enable kernel events. This is done by calling StartTrace
. In my case i want to trace kernel interrupts (EVENT_TRACE_FLAG_INTERRUPT
) and deferred procedure calls (EVENT_TRACE_FLAG_DPC
):
var
sessionProperties: PEVENT_TRACE_PROPERTIES;
bufferSize: Int64;
th: TRACEHANDLE;
loggerName: string;
logFilePath: string;
begin
loggerName := KERNEL_LOGGER_NAME;
logFilePath := 'C:\Users\Ian\foo.etl';
bufferSize := sizeof(EVENT_TRACE_PROPERTIES)
+ 1024 //maximum session name is 1024 characters
+ 1024; //maximum log file name is 1024 characters
sessionProperties := AllocMem(bufferSize);
ZeroMemory(sessionProperties, bufferSize);
sessionProperties.Wnode.BufferSize := bufferSize;
sessionProperties.Wnode.ClientContext := 1; //QPC clock resolution
sessionProperties.Wnode.Flags := WNODE_FLAG_TRACED_GUID;
sessionProperties.Wnode.Guid := SystemTraceControlGuid;
sessionProperties.EnableFlags := EVENT_TRACE_FLAG_INTERRUPT or EVENT_TRACE_FLAG_DPC;
sessionProperties.LogFileMode := EVENT_TRACE_FILE_MODE_CIRCULAR;
sessionProperties.MaximumFileSize := 5; // 5 MB
sessionProperties.LoggerNameOffset := sizeof(EVENT_TRACE_PROPERTIES);
sessionProperties.LogFileNameOffset := sizeof(EVENT_TRACE_PROPERTIES)+1024;
//Copy LoggerName to the offset address
MoveMemory(Pointer(Cardinal(sessionProperties)+sessionProperties.LoggerNameOffset), PChar(loggerName), Length(loggerName)+1);
//Copy LogFilePath to the offset address
MoveMemory(Pointer(Cardinal(sessionProperties)+sessionProperties.LogFileNameOffset), PChar(logFilePath), Length(logFilePath)+1);
hr := StartTrace({var}th, PChar(loggerName), sessionProperties);
if (hr <> ERROR_SUCCESS) then
raise EWin32Error.Create(SysErrorMessage(hr));
并且日志成功启动(我可以看到 foo.etl
开始增长到其5 MB的循环限制。
And the log is started sucessfully (i can see foo.etl
begin to grow to its 5 MB circuluar limit).
步骤3:致电 ProcessTrace
,直到它已将所有未决事件传递到 EventCallback
处理程序:
Step 3: Call ProcessTrace
, which blocks until it has delivered all pending events to the EventCallback
handler specified in Step 1:
var
res: LongWord;
begin
res := EventTrace.ProcessTrace(@currentTrace, 1, nil, nil);
if (res <> ERROR_SUCCESS) then
raise EWin32Error.Create(SysErrorMessage(res));
除了 ProcessTrace
立即立即重复返回,并且没有调用回调-即使etl文件存在并且正在增长。
Except that ProcessTrace
repeatedly returns immediately, and no callback is called - even though the etl file is present and growing.
如果我将日志记录从基于文件更改为实时日志记录:
If i change the logging from File Based to Realtime logging:
-
第1步-
OpenTrace
更改为支持实时:
logFile.ProcessTraceMode := PROCESS_TRACE_MODE_REAL_TIME;
步骤2- StartTrace
更改支持实时:
sessionProperties.LogFileMode := EVENT_TRACE_REAL_TIME_MODE;
在这种情况下 ProcessTrace
从不 返回,但 EventCallback
或 BufferCallback
曾经被叫过。
In this case ProcessTrace
never returns, but neither EventCallback
or BufferCallback
are ever called.
我在做什么错了?
更新:我的回调函数:
function BufferCallback(Logfile: PEVENT_TRACE_LOGFILE): LongWord; stdcall;
begin
ShowMessage('BufferCallback');
Result := 1; //return true to keep processing rows
end;
procedure RealtimeEventCallback(pEvent: PEVENT_TRACE); stdcall;
begin
ShowMessage('EventCallback');
nEvents := nEvents+1;
end;
推荐答案
我发现了问题。
我使用的标头没有四字对齐。
The headers i was using were not quad-word aligned.
在Delphi中,关键字已打包
。
In Delphi parlance, the keyword packed
was being used.
这篇关于Windows ETW:内核使用者未收到EventCallback或BufferCallback事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!