我正在看WDK中名为minispy ...的文件系统筛选器驱动程序示例,尤其是它们如何使用FilterSendMessage和相关功能在用户空间和内核之间传递数据:
http://msdn.microsoft.com/zh-CN/library/windows/hardware/ff541513%28v=vs.85%29.aspx
如果您安装WDK,则我正在查看并要引用的代码应位于此处:
WinDDK根目录\ version \ src \ filesys \ miniFilter \ minispy
所以基本上我要看的第一件事是inc \ minispy.h中的共享头文件:
#pragma warning(push)
#pragma warning(disable:4200) // disable warnings for structures with zero length arrays.
typedef struct _LOG_RECORD {
ULONG Length; // Length of log record. This Does not include
ULONG SequenceNumber; // space used by other members of RECORD_LIST
ULONG RecordType; // The type of log record this is.
ULONG Reserved; // For alignment on IA64
RECORD_DATA Data;
WCHAR Name[]; // This is a null terminated string
} LOG_RECORD, *PLOG_RECORD;
Run Code Online (Sandbox Code Playgroud)
在这里,我们有没有明确指定大小的名称,看起来他们正在使用一些选项来为此禁用警告。
现在,我要检查的位置是filter \ mspyLib.c:
(我只复制了我认为相关的行...)
VOID SpySetRecordName (__inout PLOG_RECORD LogRecord, __in PUNICODE_STRING Name)
ULONG nameCopyLength;
PCHAR copyPointer = (PCHAR)LogRecord->Name;
...
// A bunch of code for getting nameCopyLength from UNICODE_STRING -- I understand this.
...
// comment about adding sizeof(PVOID) for IA64 alignment -- I understand this.
LogRecord->Length = ROUND_TO_SIZE( (LogRecord->Length + nameCopyLength + sizeof( UNICODE_NULL )), sizeof( PVOID ) );
RtlCopyMemory( copyPointer, Name->Buffer, nameCopyLength );
copyPointer += nameCopyLength;
*((PWCHAR) copyPointer) = UNICODE_NULL;
Run Code Online (Sandbox Code Playgroud)
所以我的问题基本上是这是使用FilterSendMessage在结构中传递字符串以进行用户内核通信的最佳方法吗?我在描绘这些结构的布局时遇到麻烦,如果名称字符串太大,会发生什么情况。同样,对结构的分配发生在堆栈上的用户空间组件中,但是调整大小发生在作用于传递给结构的指针上的内核空间组件中。我认为这不是我不了解零长度数组的问题,而是用户空间组件如何在调整其大小之前知道为Name字段保留多少空间?
从本质上讲,这似乎是动态调整大小的数组的一种形式,在多个线程中对此进行了讨论,例如:
首先,是的,它似乎是动态大小数组的一种形式。基本上,Name字符串放置在结构末尾的后面。在用户模式和内核模式之间传递数据时,这是经常使用的技巧。这种方法有几个优点:
这是非常有用的方法。我个人使用这样的技巧来避免多次调用内存函数(分配、复制、移动等),即使在简单的应用程序中也是如此。在开发 Windows 驱动程序时,我到处都能看到这样的结构(即 ZwQueryInformationFile、ZwQueryDirectoryFile 等)