次の図は、プロトコル ドライバーの送信操作を示しています。これには、ドライバー スタック内のプロトコル ドライバー、NDIS、および基になるドライバーが含まれます。
プロトコル ドライバーは、 NdisSendNetBufferLists 関数を呼び出して、 NET_BUFFER_LIST 構造体の一覧で定義されているネットワーク データを送信します。
プロトコル ドライバーは、各NET_BUFFER_LIST構造体の SourceHandle メンバーを、NdisBindingHandle パラメーターに渡すのと同じ値に設定する必要があります。 バインディング ハンドルは、基になるミニポート ドライバーが NdisMSendNetBufferListsComplete を呼び出した後、NDIS がプロトコル ドライバーにNET_BUFFER_LIST構造体を返すために必要な情報を提供します。
NdisSendNetBufferLists を呼び出す前に、プロトコル ドライバーは、NET_BUFFER_LIST_INFO マクロで送信要求に付随する情報を設定できます。 基になるドライバーは、NET_BUFFER_LIST_INFO マクロを使用してこの情報を取得できます。
プロトコル ドライバーが NdisSendNetBufferLists 呼び出されるとすぐに、NET_BUFFER_LIST構造体と関連するすべてのリソースの所有権が放棄されます。 NDIS は ProtocolSendNetBufferListsComplete 関数を呼び出して、構造体とデータをプロトコル ドライバーに返します。 NDIS では、 ProtocolSendNetBufferListsComplete にリストを渡す前に、複数の送信要求から NET_BUFFER_LIST 構造体の単一のリンクされたリストに構造体とデータを収集できます。
NDIS が ProtocolSendNetBufferListsComplete を呼び出すまで、プロトコル ドライバーによって開始される送信の現在の状態は不明です。 プロトコル ドライバーは、 NdisSendNetBufferLists を呼び出すときに、送信要求に割り当てられたすべてのリソースの所有権を一時的に解放します。 NDIS が ProtocolSendNetBufferListsComplete に構造体を返す前に、プロトコル ドライバーは、NET_BUFFER_LIST構造体または関連するデータを調べようとしないでください。
ProtocolSendNetBufferListsComplete は、送信操作を完了するために必要な後処理を実行します。 たとえば、プロトコル ドライバーは、ネットワーク データの送信をプロトコル ドライバーに要求したクライアントに、送信操作が完了したことを通知できます。
NDIS が ProtocolSendNetBufferListsComplete を呼び出すと、プロトコル ドライバーは 、NetBufferLists パラメーターで指定されたNET_BUFFER_LIST構造体に関連付けられているすべてのリソースの所有権を回復します。 ProtocolSendNetBufferListsComplete は、これらのリソースを解放するか (たとえば、 NdisFreeNetBuffer と NdisFreeNetBufferList を呼び出すことによって)、 または NdisSendNetBufferLists への後続の呼び出しで再利用できるように準備することができます。
NDIS は常に、 NdisSendNetBufferLists に渡されるプロトコルによって決定された順序で、基になるミニポート ドライバーにプロトコル提供のネットワーク データを送信しますが、基になるドライバーはランダムな順序で要求の送信を完了できます。 つまり、バインドされているすべてのプロトコル ドライバーは、基になるドライバーに FIFO でプロトコル ドライバーが NdisSendNetBufferLists に渡すネットワーク データを送信する NDIS に依存できます。 ただし、どのプロトコル ドライバーも、NdisMSendNetBufferListsComplete が基になるドライバーによって同じ順序で呼び出されるとは限りません。