5

私は minispy と呼ばれる WDK のファイル システム フィルター ドライバーの例を見ています。

http://msdn.microsoft.com/en-us/library/windows/hardware/ff541513%28v=vs.85%29.aspx

WDK をインストールする場合、私が見て参照するコードは次の場所にあります。

WinDDK ルート ディレクトリ\バージョン\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;

ここには、明示的なサイズが指定されていない名前があり、これに対する警告を無効にするためにいくつかのオプションを使用しているようです。

今、これがどこに記入されているかを見ています、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;

だから私の質問は基本的に、これが FilterSendMessage を使用してユーザーとカーネルの通信のために構造体の内部で文字列を渡すための最良の方法ですか? これらの構造体のレイアウトと、名前の文字列が大きすぎるとどうなるかを理解するのに苦労しています。また、構造体の割り当てはスタック上のユーザー空間コンポーネントで発生しますが、サイズ変更は、構造体に渡されたポインターに作用するカーネル空間コンポーネントで発生します。これは、長さゼロの配列を理解していないことが問題だと思いますが、ユーザー空間コンポーネントは、名前フィールドのサイズを変更する前に予約するスペースをどのように知っていますか?

これは本質的に、次のようないくつかのスレッドで議論されている動的サイズの配列の形式のようです。

C: 動的にサイズ変更される構造体の推奨スタイル

4

2 に答える 2

-1

新しい接続を開くには、最初に FilterConnectCommunicationPort () を呼び出し、次に FilterSendMessage ()呼び出す必要があります。

于 2016-11-05T11:51:18.860 に答える
-1

まず第一に、はい、動的にサイズ変更された配列の形式のようです。基本的に、Name文字列は構造体の末尾の直後に配置されます。ユーザーモードとカーネルモードの間でデータを渡すとき、これは非常によく使われるトリックです。このアプローチにはいくつかの利点があります。

  • 複数のメモリ割り当ては必要ありません。
  • ユーザー モードからカーネル モードに (およびその逆に) データを渡す場合、多くの場合、あるバッファーから別のバッファーにメモリをコピーする必要があります (FilterSendMessage がそれを行うと思います)。文字列を格納するために別のメモリ位置へのポインタを使用する場合、メモリをコピー (またはロック) するために複数の呼び出しが必要になります。ユーザー提供のメッセージを処理する場合、OS がデータ構造のレイアウトを知ることは不可能です。この問題を解決する鍵は、上記のような単純な構造を使用することです。

非常に有用なアプローチです。私は個人的にこのようなトリックを使用して、単純なアプリケーションでもメモリ関数 (割り当て、コピー、移動など) の複数回の呼び出しを回避しています。Windows ドライバーを開発していると、どこにでもそのような構造が見られます (つまり、ZwQueryInformationFile、ZwQueryDirectoryFile など)。

于 2012-06-11T20:10:27.343 に答える