Windows ETW: потребитель ядра не получает событий EventCallback или BufferCallback - PullRequest
4 голосов
/ 29 января 2012

Я пытаюсь прослушать события ядра ETW.

  • Шаг 1: Вызовите OpenTrace, указав EventCallbackи необязательные BufferCallback функции, которые будут вызываться во время моего звонка на 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):

    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 МБ).

  • Шаг 3: Позвоните ProcessTrace, который блокирует до тех пор, пока не доставит все ожидающие события обработчику EventCallback, указанному в шаге 1:

    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;

Ответы [ 2 ]

1 голос
/ 12 февраля 2012

я нашел проблему.

Используемые мной заголовки не были выровнены по четырем словам.

На языке Delphi использовалось ключевое слово packed.

0 голосов
/ 30 января 2012

Вы не можете предоставить и LoggerName, и LogFileName. Если вы укажете LoggerName, LogFileName должно быть нулевым. См. эту ссылку.

...