フィルター ドライバーからのデータの送信
フィルター ドライバーは、送信要求を開始したり、上位ドライバーが開始する送信要求をフィルター処理したりできます。 プロトコル ドライバーが NdisSendNetBufferLists 関数を呼び出すと、NDIS は指定した NET_BUFFER_LIST 構造体をドライバー スタックの最上位フィルター モジュールに送信します。
フィルター ドライバーが開始した送信要求
次の図は、フィルター ドライバーによって開始された送信操作を示しています。
フィルター ドライバーは、NdisFSendNetBufferLists 関数を呼び出して、NET_BUFFER_LIST 構造体の一覧で定義されているネットワーク データを送信します。
フィルター ドライバーは、作成する各 NET_BUFFER_LIST 構造体の SourceHandle メンバーをを、NdisFSendNetBufferLists の NdisFilterHandle パラメーターに渡すものと同じ値に設定する必要があります。 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 に渡されたフィルター ドライバーによって決定された順序で、下位ドライバーにフィルター供給のネットワーク データを送信します。 ただし、指定した順序でデータを送信した後、下位ドライバーは任意の順序でバッファーを返すことができます。
フィルター ドライバーは、生成した送信要求のループバックを要求できます。 ループバックを要求するために、ドライバーは NdisFSendNetBufferLists の SendFlags パラメーターに NDIS_SEND_FLAGS_CHECK_FOR_LOOPBACK フラグを設定します。 NDIS は、送信データを含む受信パケットを示します。
注: フィルター ドライバーは、生成した送信要求を追跡し、このような要求が完了したときに NdisFSendNetBufferListsComplete 関数を呼び出さないようにする必要があります。
送信要求のフィルター処理
次の図は、下位ドライバーによって開始される送信要求のフィルター処理を示しています。
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 が FilterSendNetBufferLists の SendFlags パラメーターで 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 を参照)、そのドライバーが受け取る追加データを、上位ドライバーに渡してはいけません。