Windows ETW:内核使用者未收到EventCallback或BufferCallback事件 [英] Windows ETW: Kernel consumer receives no EventCallback or BufferCallback events

查看:135
本文介绍了Windows ETW:内核使用者未收到EventCallback或BufferCallback事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试监听ETW内核事件。

i am trying to listen to ETW kernel events.

  • Step 1: Call OpenTrace, specifying the EventCallback and optional BufferCallback functions that will be called during my call to ProcessTrace:

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屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆