c++ - Windows EVENTLOGRECORD 结构中的可变长度字段如何工作?

标签 c++ winapi

我曾尝试确定 EVENTLOGRECORD 数据的可变长度部分是如何工作的,但收效甚微。

Winnt.h定义了结构体,以及后面的数据,如下:

typedef struct _EVENTLOGRECORD {
DWORD  Length;        // Length of full record
DWORD  Reserved;      // Used by the service
DWORD  RecordNumber;  // Absolute record number
DWORD  TimeGenerated; // Seconds since 1-1-1970
DWORD  TimeWritten;   // Seconds since 1-1-1970
DWORD  EventID;
WORD   EventType;
WORD   NumStrings;
WORD   EventCategory;
WORD   ReservedFlags; // For use with paired events (auditing)
DWORD  ClosingRecordNumber; // For use with paired events (auditing)
DWORD  StringOffset;  // Offset from beginning of record
DWORD  UserSidLength;
DWORD  UserSidOffset;
DWORD  DataLength;
DWORD  DataOffset;    // Offset from beginning of record
//
// Then follow:
//
// WCHAR SourceName[]
// WCHAR Computername[]
// SID   UserSid
// WCHAR Strings[]
// BYTE  Data[]
// CHAR  Pad[]
// DWORD Length;

    //
} EVENTLOGRECORD, *PEVENTLOGRECORD;

我可以使用以下代码提取第一个似乎是源代码的 block ,但它肯定不是预期的方法:

memcpy(&strings, pRecord+sizeof(EVENTLOGRECORD), tmpLog->UserSidOffset);

但是从 Winnt.h 中的注释,我也得到了计算机名称。

那么谁能解释一下如何从 EVENTLOGRECORD 结构中确定“SourceName”的长度,并解释一下 StringOffset、DataLength 和 DataOffset 是什么?

谢谢。

最佳答案

注意:在整个回答过程中,我假设您有一个指向该结构的指针,如下所示:

EVENTLOGRECORD * elr;

缩短代码片段。

So can someone explain how to determine the "SourceName" length from the EVENTLOGRECORD structure

没有字段指定它有多长,但您可以很容易地确定它:它是记录中定义明确的字段之后的第一个字段,因此您可以简单地执行以下操作:

WCHAR * SourceName=(WCHAR *)((unsigned char *)elr + sizeof(*elr));

现在,在 SourceName你有一个指向那个字符串的指针;您可以使用通常的字符串函数轻松确定其长度。

对了,在SourceName的终结符之后应该有 ComputerName字符串。

and explain what StringLength

没有 StringLength成员(member),你在说什么?

DataLength and DataOffset are?

事件日志也由嵌入在记录中的任意二进制数据组成。

DataOffset成员指定此类数据从记录开始的偏移量,DataLength指定该数据的长度。如果您要将该数据复制到缓冲区(假设它足够大),您会这样做:

memcpy(targetBuffer,(unsigned char *)elr + elr->DataOffset,elr->DataLength);

顺便说一下,与其直接阅读包含文件,不如阅读 documentation , 它更容易理解。


关于StringOffset的附录

StringOffset字段指定与事件关联的字符串从记录开始的偏移量。

StringOffset现场工作非常像DataOffset上面描述的字段,但没有对应的 StringLength字段,因为可以使用普通字符串函数轻松确定每个字符串的长度(事实上,字符串部分只是由几个以 NUL 结尾的字符串一个接一个地组成)。

此外,通过检查 DataOffset 可以很容易地确定字符串部分结束的位置。成员,实际上字符串部分在数据 block 开始的地方结束。 EVENTLOGRECORD结构还提供了 NumStrings字段以确定字符串部分中包含的字符串数(感谢 Remy Lebeau)。

如果您要将这些字符串放在 vector<wstring> 中你会做这样的事情(小心,未经测试的代码):

vector<wstring> strings;
for(
        wchar_t * ptr=(wchar_t *)((unsigned char *)elr + elr->StringOffset);
        strings.size()<elr->NumStrings;
        ptr+=strings.back().length() + 1
    )
    strings.push_back(wstring(ptr));

关于c++ - Windows EVENTLOGRECORD 结构中的可变长度字段如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3087422/

相关文章:

winapi - windows系统字体规范是什么

c# - 在 Windows 消息上设置 Hook

c++ - 有没有办法抑制cppclean问题?

windows - Windows 的 "Safely Remove Hardware"对话框如何获取 "foreground love"?

c++ - 是否可以重载模板类?

c++ - 如何更改 libwx_gtk2ud_richtext-2.8 的名称

C++\Win32 以低优先级模式运行应用程序/线程?

c# - 消除运行连续 exe 文件的闪烁

c++ - 编译模板和/或使用模板编译的正确程序是什么?

c++ - "primary-expression before ' 。 g++ 中的 ' token error"