2

私はWindowsStartTrace関数のイベントトレースを呼び出しています:

StartTrace(sessionHandle, KERNEL_LOGGER_NAME, sessionProperties);

エラーコード87(ERROR_INVALID_PARAMETER)で失敗しています。MSDNには、このエラーの一般的な原因がいくつか示されています。

  • プロパティNULLです。
  • SessionHandleNULLです。
  • プロパティLogFileNameOffsetメンバーが無効です。
  • プロパティLoggerNameOffsetメンバーが無効です。
  • プロパティLogFileModeメンバーは、無効なフラグの組み合わせを指定します。
  • Wnode.GuidメンバーはSystemTraceControlGuidですが、SessionNameパラメーターはKERNEL_LOGGER_NAMEではありませ

私が呼んでいるコードは次のとおりです。

procedure StartKernelLogging;
var
    sessionProperties: PEVENT_TRACE_PROPERTIES;
    bufferSize: Int64;
    loggerName: AnsiString;
    logFilePath: AnsiString;
    th: TRACEHANDLE;
    hr: Cardinal;
begin
    {
        Allocate memory for the session properties. The memory must
        be large enough to include the log file name and session name,
        which get appended to the end of the session properties structure.
    }
    loggerName := KERNEL_LOGGER_NAME;
    logFilePath := 'C:\Users\Ian\foo.etl';

    bufferSize := sizeof(EVENT_TRACE_PROPERTIES)
            + Length(loggerName)+1
            + Length(logFilePath)+1;

    sessionProperties := AllocMem(bufferSize);

    ZeroMemory(sessionProperties, bufferSize);

    sessionProperties.Wnode.BufferSize := bufferSize;
    sessionProperties.Wnode.Flags := WNODE_FLAG_TRACED_GUID;
    sessionProperties.Wnode.ClientContext := 1; //QPC clock resolution
    sessionProperties.Wnode.Guid := SystemTraceControlGuid;
    sessionProperties.EnableFlags := EVENT_TRACE_FLAG_NETWORK_TCPIP;
    sessionProperties.LogFileMode := EVENT_TRACE_FILE_MODE_CIRCULAR;
    sessionProperties.MaximumFileSize := 5;  // 5 MB
    sessionProperties.LoggerNameOffset := sizeof(EVENT_TRACE_PROPERTIES);
    sessionProperties.LogFileNameOffset := sizeof(EVENT_TRACE_PROPERTIES) + Length(loggerName)+1;

    //Copy LoggerName to the offset address
    MoveMemory(Pointer(Cardinal(sessionProperties)+Cardinal(sessionProperties.LoggerNameOffset)), PAnsiChar(loggerName), Length(loggerName)+1);

    //Copy LogFilePath to the offset address
    MoveMemory(Pointer(Cardinal(sessionProperties)+Cardinal(sessionProperties.LogFileNameOffset)), PAnsiChar(logFilePath), Length(logFilePath)+1);

    th := 0;
    hr := EventTrace.StartTrace({var}th, PChar(loggerName), sessionProperties);
    if (hr <> ERROR_SUCCESS) then
    begin
        raise EWin32Error.Create(SysErrorMessage(hr));
    end;
end;

私の呼び出しの言語に依存しないバージョン:

ADVAPI32.StartTraceA(
     TraceHandle: 0x18F56C
     InstanceName: 0x44E840
     Properties: 0x243BD8);

ここで、TraceHandle64ビット整数を指します。

0018F56C: 00 00 00 00  00 00 00 00

そしてInstanceName、nullで終了するansi文字列へのポインタです。

0044E840: 4E 54 20 4B  65 72 6E 65  NT Kerne
0044E848: 6C 20 4C 6F  67 67 65 72  l Logger
0044E850: 00

Properties構造体へのポインタでありEVENT_TRACE_PROPERTIES、完全な16進ダンプを再現することは控えます。

002A3BD8: 0000009A (154 bytes)

重要な値は2つのオフセットです。

properties.LoggerNameOffset = 116  (i.e. $243BB8 + 116 = $243C4C)
properties.LogFileNameOffset = 133 (i.e. $243BD8 + 133 = $243C5D)

これには、有効なnullで終了するansi文字列も含まれています。

「NTカーネルロガー」:

$243C4C  4B20544E 656E7265  NT Kerne
$243C54  6F4C206C 72656767  l Logger
$243C5C  xxxxxx00           .

"C:\ Users \ Ian \ foo.etl":

$243C5C  5C3A43xx 72657355  .C:\User
$243C64  61495C73 6F665C6E  s\Ian\fo
$243C6C  74652E6F xxxx006C  o.etc.

パラメータが正しくないのはなぜですか?


ボーナスリーディング

アップデート:

セッションパラメータ:

9A 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
AD 4A 81 9E 04 32 D2 11
9A 82 00 60 08 A8 69 39
01 00 00 00 00 00 02 00
00 00 00 00 00 00 00 00
00 00 00 00 05 00 00 00
02 00 00 00 00 00 00 00
00 00 01 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 85 00 00 00
74 00 00 00 

これは次のように分類されます。

000| Wnode.BufferSize:          9A 00 00 00 (154)
004| Wnode.ProviderID:          00 00 00 00
008| Wnode.Version:             00 00 00 00
012| Wnode.Linkage:             00 00 00 00
016| Wnode.Timestamp:           00 00 00 00 00 00 00 00
024| Wnode.Guid:                AD 4A 81 9E 04 32 D2 11 9A 82 00 60 08 A8 69 39 (SystemTraceControlGuid)
040| Wnode.ClientContext:       01 00 00 00 (1)
044| Wnode.Flags:               00 00 02 00 (WNODE_FLAG_TRACED_GUID)
048| BufferSize:          00 00 00 00 
052| MinimumBuffers:      00 00 00 00
056| MaximumBuffers:      00 00 00 00 
060| MaximumFileSize:     05 00 00 00 (5 MB)
064| LogFileMode:         02 00 00 00 (EVENT_TRACE_FILE_MODE_CIRCULAR)
068| FlushTimer:          00 00 00 00
072| EnableFlags:         00 00 01 00 (EVENT_TRACE_FLAG_NETWORK_TCPIP)
076| AgeLimit:            00 00 00 00
080| NumberOfBuffers:     00 00 00 00 
084| FreeBuffers:         00 00 00 00
088| EventsLost:          00 00 00 00 
092| BuffersWritten:      00 00 00 00
096| LogBuffersLost:      00 00 00 00 
100| RealTimeBuffersLost: 00 00 00 00
104| LoggerThreadId:      00 00 00 00 
108| LogFileNameOffset:   85 00 00 00 (133)
112| LoggerNameOffset:    74 00 00 00 (116)
116| NT Kernel Logger\0
133| C:\Users\Ian\foo.etl\0
154|

アラインメントの問題がある場合、私はそれを単独で発見することはできません。


構造:

EVENT_TRACE_PROPERTIES = packed record
   Wnode : WNODE_HEADER;

   // data provided by caller
   BufferSize : Longword;              // buffer size for logging (kbytes)
   MinimumBuffers : Longword;          // minimum to preallocate
   MaximumBuffers : Longword;          // maximum buffers allowed
   MaximumFileSize : Longword;         // maximum logfile size (in MBytes)
   LogFileMode : Longword;             // sequential, circular
   FlushTimer : Longword;              // buffer flush timer, in seconds
   EnableFlags :Longword;              // trace enable flags
   AgeLimit : Longint;                // age decay time, in minutes

   // data returned to caller
   NumberOfBuffers : Longword;         // no of buffers in use
   FreeBuffers : Longword;             // no of buffers free
   EventsLost : Longword;              // event records lost
   BuffersWritten : Longword;          // no of buffers written to file
   LogBuffersLost : Longword;          // no of logfile write failures
   RealTimeBuffersLost : Longword;     // no of rt delivery failures
   LoggerThreadId : HANDLE;            // thread id of Logger
   LogFileNameOffset : Longword;        // Offset to LogFileName
   LoggerNameOffset : Longword;         // Offset to LoggerName
end;

一緒に:

WNODE_HEADER = packed record
   BufferSize : Longword;
   ProviderId : Longword;
   Version : Longword;
   Linkage : Longword;
   TimeStamp : Int64;
   Guid : TGUID;
   ClientContext : Longword;
   Flags : Longword;
end;
4

2 に答える 2

2

ああ、ルークのコメントからのコメントが何を言っているのかわかります。

構造がずれているわけではありません。構造の後のコンテンツは8-byte整列する必要があります。言い換えると:

000| Wnode.BufferSize:          9A 00 00 00 (154)
004| Wnode.ProviderID:          00 00 00 00
     ...snip...
108| LogFileNameOffset:   85 00 00 00 (133)
112| LoggerNameOffset:    74 00 00 00 (116)
116| 00 00 00 00 (4 bytes padding)
120| NT Kernel Logger\0
136| 00 00 00 00 00 00 00 (7 bytes padding)
144| C:\Users\Ian\foo.etl\0

Windowsの境界でデータを整列させる必要があるよう8-byteです(7(Professional(64ビット)))

パディングを支援するためにPad、数値を最も近い8の倍数に切り上げる関数を作成しました。

function Pad(length: Cardinal): Cardinal;
var
    m: Integer;
const
    DataAlignment = 8; //align data on 8-byte boundaries
begin
    Result := length;

    m := length mod DataAlignment;
    if (m > 0) then
        Result := result + DataAlignment-m;
end;

次に、コードの一部を元の質問から変更して使用しました。

  • buffserSize必要な合計を計算します。

    loggerName := KERNEL_LOGGER_NAME;
    logFilePath := 'C:\Users\Ian\foo.etl';
    
    bufferSize := sizeof(EVENT_TRACE_PROPERTIES)
            + Pad(Length(loggerName)+1)
            + Pad(Length(logFilePath)+1);
    
  • 次に、オフセットを8バイト境界にプッシュする必要があります。

    sessionProperties.LoggerNameOffset := Pad(sizeof(EVENT_TRACE_PROPERTIES));
    sessionProperties.LogFileNameOffset := Pad(sizeof(EVENT_TRACE_PROPERTIES)) + Pad(Length(loggerName)+1);
    
  • そして、構造体で宣言されたオフセットに文字列をコピーする限り、私は大丈夫です:

    //Copy LoggerName to the offset address
    MoveMemory(
          Pointer(Cardinal(sessionProperties)+sessionProperties.LoggerNameOffset),
          PAnsiChar(loggerName), Length(loggerName)+1);
    
    //Copy LogFilePath to the offset address
    MoveMemory(
          Pointer(Cardinal(sessionProperties)+sessionProperties.LogFileNameOffset),
          PAnsiChar(logFilePath), Length(logFilePath)+1);
    

そしてblingo-blango、それは機能します。

:すべてのコードはパブリックドメインにリリースされます。アトリビューションは必要ありません。

于 2012-01-29T04:36:29.147 に答える
1

答えではありませんが、私が見つけた興味深いもの:行を置き換える場合:

hr := EventTrace.StartTrace({var}th, PChar(loggerName), sessionProperties);

hr := EventTrace.StartTrace({var}th, KERNEL_LOGGER_NAME, sessionProperties);

その場合、エラーコードはERROR_BAD_LENGTH(24)になります。トレースAPIに別の単位のセットを使用していると思います。私の場合、StartTraceはPWideCharを必要としますが、loggerNameはAnsiStringです。あなたのEventTraceユニットがどのように見えるかはわかりませんが、これがあなたにも当てはまるかどうかはわかりません。それにもかかわらず、StartTrace()呼び出しは成功しません。

于 2012-01-29T04:55:16.020 に答える