2012-01-29 49 views
4

我正在嘗試收聽ETW內核事件。Windows ETW:內核使用者未收到EventCallback或BufferCallback事件

  • 第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步:Enable kernel events。這通過呼叫StartTrace完成。在我來說,我想跟蹤內核interruptsEVENT_TRACE_FLAG_INTERRUPT)和deferred procedure callsEVENT_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 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從未的回報,但也EventCallbackBufferCallback是不斷調用。

我在做什麼錯了?


更新:我的回調函數:

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; 
+0

根據我的經驗(至少在實時跟蹤中),即使會話不存在,OpenTrace()也總是「成功」。只有當您調用ProcessTrace()時,它纔會失敗,並返回ERROR_WMI_INSTANCE_NOT_FOUND。我不知道內核提供者的行爲如何,但是使用自定義實時提供者需要在OpenTrace()之前啓動StartTrace()。我認爲將事件跟蹤到文件時也是如此。 – Luke 2012-01-30 14:55:29

回答

0

我發現了這個問題。

我使用的標題不是四字對齊的。

德爾福公司的說法是,正在使用關鍵字packed

0

你不能同時提供LoggerName和LOGFILENAME。如果您提供LoggerName,則LogFileName必須爲空。見this link.