操作前コールバック ルーチンの記述
ミニフィルター ドライバーは、1 つ以上の 操作前コールバック ルーチン を使用して I/O 操作をフィルター処理します。 操作前コールバック ルーチン は、レガシ フィルター モデル で使用されるディスパッチ ルーチンに似ています。
ミニフィルターは、コールバック ルーチンのエントリ ポイントを FLT_REGISTRATION 構造体の OperationRegistration メンバーに格納することによって、特定の種類の I/O 操作の事前操作コールバック ルーチンを登録します。 ミニフィルターは DriverEntry ルーチンの FltRegisterFilter にパラメーターとしてこのメンバーを FltMgr に渡します。
ミニフィルターは、操作前または操作後のコールバック ルーチンを登録した I/O 操作の種類のみを受け取ります。 ミニフィルターは 操作後のコールバック ルーチン を登録せずに、特定の種類の I/O 操作の操作前コールバック ルーチンを登録できます。その逆も同様です。
すべての操作前コールバック ルーチンは、次のように定義されます。
typedef FLT_PREOP_CALLBACK_STATUS
(*PFLT_PRE_OPERATION_CALLBACK) (
IN OUT PFLT_CALLBACK_DATA Data,
IN PCFLT_RELATED_OBJECTS FltObjects,
OUT PVOID *CompletionContext
);
FltMgr が特定の I/O 操作に対してミニフィルターの事前操作コールバック ルーチンを呼び出すと、ミニフィルターは I/O 操作を一時的に制御します。 ミニフィルターは、次のいずれかになるまでこのコントロールを保持します。
操作前コールバック ルーチンから FLT_PREOP_PENDING 以外の状態値を返します。
FltCompletePendedPreOperation を、操作前コールバック ルーチンで以前にペンドされた操作を処理した作業ルーチンから呼び出します。
次の表に、ミニフィルターの操作前コールバック ルーチンの使用シナリオをいくつか示し、各シナリオの実装の詳細と戻り値を示します。
使用シナリオ | 実装 | 返される値 |
---|---|---|
ルーチンは操作に関連せず、操作の最終状態を必要としません。また、操作後のコールバックもありません。 | I/O 操作を渡し、完了時にミニフィルターの操作後コールバックを呼び出さないよう FltMgr に指示します。 | FLT_PREOP_SUCCESS_NO_CALLBACK |
このルーチンには、操作の最終状態が必要です。 | 操作を渡し FltMgr にミニフィルターの操作後コールバック ルーチンを呼び出すよう指示します。 | FLT_PREOP_SUCCESS_WITH_CALLBACK |
ミニフィルターは、この操作を完了するか、後で処理を続行する必要があります。 | 操作を保留中の状態にします。 FltCompletePendedPreOperation を使用して、後で操作を完了します。 FLT_PREOP_PENDING を返す操作前ルーチンと FltCompletePendingOperation が呼び出される間に、許容される競合が発生する可能性があります。 FltMgr は、ドライバーからの入力なしでこのシナリオを処理します。 | FLT_PREOP_PENDING |
操作後処理は、ディスパッチ ルーチンが呼び出されたのと同じスレッドのコンテキストで発生する必要があります。 この条件により、一貫性のある IRQL が保証され、メインローカル変数の状態が保持されます。 | 操作を後操作と同期します。 | FLT_PREOP_SYNCHRONIZE |
操作前コールバック ルーチンは、操作を完了する必要があります。 | 操作の処理を停止し、最終的な NTSTATUS 値を割り当てます。 | FLT_PREOP_COMPLETE |
IRQL と操作前のコールバック ルーチン
FltMgr には、ミニフィルターが操作前コールバック (またはコールバック) で何を行うかを知る方法はありません。 そのため、FltMgr には、ミニポートの運用前コールバックの呼び出しが問題を引き起こす可能性があるかどうかを知る方法はありません。 (管理者特権の IRQL で安全に実行できることと、できないことがあります)。 そのため、IRQL を認識し、適切に処理するのはミニフィルターに任されます。 ミニフィルターは、呼び出 された IRQL を認識する必要がある状況で、 KeGetCurrentIRQL を安全かつ安価に呼び出すことができます。
ミニフィルターの操作前コールバック ルーチン IRQL に関する次の情報は、理解するのに役立ちます。
操作前コールバックは、IRQL = PASSIVE_LEVEL または IRQL = APC_LEVELで呼び出すことができます。 ほとんどの事前操作コールバックは、I/O 要求を発生させたスレッドのコンテキストで、IRQL = PASSIVE_LEVEL で呼び出されます。 IRQL = APC_LEVEL で呼び出されるのは、一部の操作前コールバックだけです。
IRP ベースの操作では、上位のフィルターまたはミニフィルター ドライバーがワーカー スレッドによる処理の操作をペンドした場合、ミニフィルターの操作前コールバックをシステム ワーカー スレッドのコンテキストで呼び出すことができます。 操作前コールバックはレガシ フィルターのディスパッチ ルーチンに相当するため、レガシ フィルターの ディスパッチ ルーチンの IRQL とスレッド コンテキスト を知ることは役に立つ場合があります。
IRQL > APC_LEVEL の操作後ルーチンでコンテキスト オブジェクトを取得することはできません。 代わりに、操作前ルーチンの間にコンテキスト オブジェクトを取得し、それを操作後ルーチンに渡すか、IRQL <= APC_LEVEL で操作後処理を実行します。 コンテキストの詳細については 「コンテキスト」 を参照してください。
関連記事
ミニフィルター インスタンス スタックへ I/O 操作を渡す