加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

delphi – Windows ETW:内核使用者不接收EventCallback或Buffer

发布时间:2020-12-15 09:12:01 所属栏目:大数据 来源:网络整理
导读:我正在尝试收听ETW内核事件. 步骤1:调用 OpenTrace ,指定在调用 ProcessTrace 期间将调用的 EventCallback 和可选 BufferCallback 函数: var logFile: EVENT_TRACE_LOGFILE; currentTrace: TRACEHANDLE;begin ZeroMemory(@logFile,sizeof(logFile)); logFi
我正在尝试收听ETW内核事件.

>步骤1:调用OpenTrace,指定在调用ProcessTrace期间将调用的EventCallback和可选BufferCallback函数:

var
    logFile: EVENT_TRACE_LOGFILE;
    currentTrace: TRACEHANDLE;
begin
    ZeroMemory(@logFile,sizeof(logFile));

    logFile.LoggerName := KERNEL_LOGGER_NAME;
    logFile.LogFileName := 'C:UsersIanfoo.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:Enable kernel events.这是通过调用StartTrace完成的.在我的情况下,我想跟踪内核interrupts(EVENT_TRACE_FLAG_INTERRUPT)和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:UsersIanfoo.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,sessionProperties);
    if (hr <> ERROR_SUCCESS) then
          raise EWin32Error.Create(SysErrorMessage(hr));

并且日志成功启动(我可以看到foo.etl开始增长到它的5 MB circuluar限制).
>步骤3:调用ProcessTrace,阻止它将所有挂起事件传递给步骤1中指定的EventCallback处理程序:

var
   res: LongWord;
begin
   res := EventTrace.ProcessTrace(@currentTrace,1,nil,nil);
   if (res <> ERROR_SUCCESS) then
      raise EWin32Error.Create(SysErrorMessage(res));

除了ProcessTrace立即重复返回,并且没有调用回调 – 即使etl文件存在并且正在增长.

如果我将记录从基于文件更改为实时日志记录:

>第1步 – OpenTrace更改以支持实时:

logFile.ProcessTraceMode := PROCESS_TRACE_MODE_REAL_TIME;

>第2步 – StartTrace更改以支持实时:

sessionProperties.LogFileMode := EVENT_TRACE_REAL_TIME_MODE;

在这种情况下,ProcessTrace永远不会返回,但是从未调用过EventCallback或BufferCallback.

我究竟做错了什么?

更新:我的回调函数:

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;

解决方法

我发现了这个问题.

我使用的标题不是四字对齐的.

在Delphi的说法中,正在使用关键字packed.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读