フィルター ドライバーからのデータの送信

フィルター ドライバーは、送信要求を開始したり、上位ドライバーが開始する送信要求をフィルター処理したりできます。 プロトコル ドライバーが NdisSendNetBufferLists 関数を呼び出すと、NDIS は指定した NET_BUFFER_LIST 構造体をドライバー スタックの最上位フィルター モジュールに送信します。

フィルター ドライバーが開始した送信要求

次の図は、フィルター ドライバーによって開始された送信操作を示しています。

Diagram showing a send operation initiated by a filter driver with NdisFSendNetBufferLists function.

フィルター ドライバーは、NdisFSendNetBufferLists 関数を呼び出して、NET_BUFFER_LIST 構造体の一覧で定義されているネットワーク データを送信します。

フィルター ドライバーは、作成する各 NET_BUFFER_LIST 構造体の SourceHandle メンバーをを、NdisFSendNetBufferListsNdisFilterHandle パラメーターに渡すものと同じ値に設定する必要があります。 NDIS ドライバーは、ドライバーが生成しなかった NET_BUFFER_LIST 構造体の SourceHandle メンバーを変更してはいけません。

NdisFSendNetBufferLists を呼び出す前に、フィルター ドライバーは、NET_BUFFER_LIST_INFO マクロで送信要求に付随する情報を設定できます。 下位ドライバーは、NET_BUFFER_LIST_INFO マクロを使用してこの情報を取得できます。

フィルター ドライバーが NdisFSendNetBufferLists を呼び出すとすぐに、NET_BUFFER_LIST 構造体とすべての関連リソースの所有権が放棄されます。 NDIS は、送信要求を処理するか、下位ドライバーに要求を渡すことができます。

NDIS は、フィルター ドライバーに構造体とデータを返す FilterSendNetBufferListsComplete 関数を呼び出します。 NDIS は、FilterSendNetBufferListsComplete にリストを渡す前に、複数の送信要求からの構造体とデータを NET_BUFFER_LIST 構造体の単一のリンクされたリストに収集できます

NDIS が FilterSendNetBufferListsComplete を呼び出すまで、送信要求の現在の状態は不明です。 フィルター ドライバーは、NDIS が FilterSendNetBufferListsComplete に構造体を返す前に、NET_BUFFER_LIST 構造体または関連するデータを調べないようにする必要があります。

FilterSendNetBufferListsComplete は、送信操作を完了するために必要な後処理を実行します。

NDIS が FilterSendNetBufferListsComplete を呼び出すと、フィルター ドライバーは、NetBufferLists パラメーターで指定された NET_BUFFER_LIST 構造体に関連付けられているすべてのリソースの所有権を回復します。 FilterSendNetBufferListsComplete は、これらのリソースを解放するか (たとえば、NdisFreeNetBuffer 関数と NdisFreeNetBufferList 関数を呼び出すことで)、NdisFSendNetBufferLists への後続の呼び出しで再利用できるようにリソースを準備することができます。

NDIS は常に、NdisFSendNetBufferLists に渡されたフィルター ドライバーによって決定された順序で、下位ドライバーにフィルター供給のネットワーク データを送信します。 ただし、指定した順序でデータを送信した後、下位ドライバーは任意の順序でバッファーを返すことができます。

フィルター ドライバーは、生成した送信要求のループバックを要求できます。 ループバックを要求するために、ドライバーは NdisFSendNetBufferListsSendFlags パラメーターに NDIS_SEND_FLAGS_CHECK_FOR_LOOPBACK フラグを設定します。 NDIS は、送信データを含む受信パケットを示します。

注: フィルター ドライバーは、生成した送信要求を追跡し、このような要求が完了したときに NdisFSendNetBufferListsComplete 関数を呼び出さないようにする必要があります。

送信要求のフィルター処理

次の図は、下位ドライバーによって開始される送信要求のフィルター処理を示しています。

Diagram depicting the process of filtering a send request initiated by an overlying driver using FilterSendNetBufferLists function.

NDIS は、フィルター ドライバーの FilterSendNetBufferLists 関数を呼び出して、上位ドライバーの送信要求をフィルター処理します。

フィルター ドライバーは、他のドライバーから受け取る NET_BUFFER_LIST 構造体の SourceHandle メンバーを変更してはいけません。

フィルター ドライバーは、データをフィルター処理し、下位ドライバーにフィルター処理されたデータを送信できます。 FilterSendNetBufferLists に送信された 各 NET_BUFFER構造体に対して、フィルター ドライバーは次の操作を実行できます。

  • NdisFSendNetBufferLists 関数を呼び出して、次の下位ドライバーにバッファーを渡します。 NDIS は、フィルター ドライバーのコンテキスト空間 (NET_BUFFER_LIST_CONTEXT 構造体を参照) の可用性を保証します。 フィルター ドライバーは、NdisFSendNetBufferLists を呼び出す前にバッファーの内容を変更できます。 フィルター処理されたデータの処理は、フィルター ドライバーによって開始された送信操作と同様に続行されます。

  • NdisFSendNetBufferListsComplete 関数を呼び出してバッファーを破棄します。

  • 後で処理するために、バッファーをローカル データ構造のキューに入れます。 フィルター ドライバーの設計によって、キューに入ったバッファーをドライバーが処理する原因が決まります。 たとえば、タイムアウト後の処理や、特定のバッファーの受信後の処理などがあります。

    注: ドライバーが後で処理するために送信要求をキューに入れる場合は、送信キャンセル要求をサポートする必要があります。 送信キャンセル要求の詳細については、「フィルター ドライバーでの送信要求のキャンセル」を参照してください。

  • バッファーをコピーし、コピーを使用して送信要求を生成します。 送信操作は、フィルター ドライバーが開始する送信要求に似ています。 この場合、ドライバーは NdisFSendNetBufferListsComplete 関数を呼び出すことで、上位ドライバーに元のバッファーを返す必要があります。

送信要求が完了すると、ドライバー スタックが上に進みます。 ミニポート ドライバーが NdisMSendNetBufferListsComplete 関数を呼び出すと、NDIS は最下位の上位フィルター モジュールの FilterSendNetBufferListsComplete 関数を呼び出します。

送信操作が完了すると、フィルター ドライバーは、フィルター ドライバーが FilterSendNetBufferLists で行った、上位ドライバーのバッファー記述子への変更を元に戻します。 ドライバーは、NdisFSendNetBufferListsComplete 関数を呼び出して、上位ドライバーに NET_BUFFER_LIST 構造体のリンクされたリストを返し、送信要求の最終的な状態を返します。

最上位のフィルター モジュールが NdisFSendNetBufferListsComplete を呼び出すと、NDIS は、発信元プロトコル ドライバーの ProtocolSendNetBufferListsComplete 関数を呼び出します。

FilterSendNetBufferLists 関数を提供しないフィルター ドライバーは、引き続き送信要求を開始できます。 このようなドライバーが送信要求を開始する場合は、FilterSendNetBufferListsComplete 関数を提供する必要があり、ドライバー スタックの完全なイベントを渡してはなりません。

フィルター ドライバーは、上位ドライバーのループバック要求を渡すか、フィルター処理できます。 ループバック要求を渡すために、NDIS が FilterSendNetBufferListsSendFlags パラメーターで NDIS_SEND_FLAGS_CHECK_FOR_LOOPBACK を設定した場合、フィルター ドライバーは NdisFSendNetBufferLists を呼び出すときに SendFlags パラメーターで NDIS_SEND_FLAGS_CHECK_FOR_LOOPBACK を設定します。 NDIS は、送信データを含む受信パケットを示します。

一般に、フィルター ドライバーは、NDIS が標準サービス (ループバックなど) を提供できないように動作を変更する場合、フィルター ドライバーは NDIS のそのサービスを提供する必要があります。 たとえば、ハードウェア アドレスの要求を変更するフィルター ドライバー (OID_802_3_CURRENT_ADDRESS を参照) は、新しいハードウェア アドレスに転送されるバッファーのループバックを処理する必要があります。 この場合、フィルターによってアドレスが変更されたため、NDIS は通常提供するループバック サービスを提供できません。 また、フィルター ドライバーが無作為検出モードを設定する場合 (OID_GEN_CURRENT_PACKET_FILTER を参照)、そのドライバーが受け取る追加データを、上位ドライバーに渡してはいけません。