Receiving NET_BUFFER Structures in CoNDIS Drivers
The following figure illustrates a basic CoNDIS receive operation, which involves a protocol driver, NDIS, and a miniport driver.
As the preceding figure shows, miniport drivers call the NdisMCoIndicateReceiveNetBufferLists function to indicate NET_BUFFER structures to overlying drivers. In most miniport drivers, each NET_BUFFER structure is attached to a separate NET_BUFFER_LIST structure, so protocol drivers can create a subset of the original list of NET_BUFFER_LIST structures and forward them to different clients. However, the number of NET_BUFFER structures that are attached to a NET_BUFFER_LIST depends on the driver.
After the miniport driver links all the NET_BUFFER_LIST structures, the miniport driver passes a pointer to the first NET_BUFFER_LIST structure in the list to the NdisMCoIndicateReceiveNetBufferLists function. NDIS examines the NET_BUFFER_LIST structures and calls the ProtocolCoReceiveNetBufferLists function of the protocol driver that is associated with the specified virtual connection (VC). NDIS passes a subset of the list that includes only the NET_BUFFER_LIST structures that are associated with the correct binding to each protocol driver.
If the NDIS_RECEIVE_FLAGS_STATUS_RESOURCES flag is set in the CoReceiveFlags parameter for a protocol driver's ProtocolCoReceiveNetBufferLists function, NDIS regains ownership of the NET_BUFFER_LIST structures immediately after ProtocolCoReceiveNetBufferLists returns.
If the NDIS_RECEIVE_FLAGS_STATUS_RESOURCES flag is not set in the CoReceiveFlags parameter for a protocol driver's ProtocolCoReceiveNetBufferLists function, the protocol driver can retain ownership of the NET_BUFFER_LIST structures. In this case, the protocol driver must return the NET_BUFFER_LIST structures by calling the NdisReturnNetBufferLists function.
If a miniport driver runs low on receive resources, it can set the NDIS_RECEIVE_FLAGS_STATUS_RESOURCES flag in the CoReceiveFlags parameter for the NdisMCoIndicateReceiveNetBufferLists function. In that case, the driver can reclaim ownership of all of the indicated NET_BUFFER_LIST structures and embedded NET_BUFFER structures as soon as NdisMCoIndicateReceiveNetBufferLists returns. If a miniport driver indicates NET_BUFFER structures with the NDIS_RECEIVE_FLAGS_RESOURCES flag set, the protocol drivers must copy the data, so you should avoid using NDIS_RECEIVE_FLAGS_RESOURCES in this way. A miniport driver should detect when it has low receive resources and should complete any steps that are necessary to avoid this situation.
NDIS calls a miniport driver's MiniportReturnNetBufferLists function after the protocol driver calls NdisReturnNetBufferLists.
Note If a miniport driver indicates a NET_BUFFER_LIST structure with a given status, NDIS is not required to indicate the NET_BUFFER_LIST structure to the overlying drivers with the same status. For example, NDIS could copy a NET_BUFFER_LIST structure with the NDIS_RECEIVE_FLAGS_RESOURCES flag set and indicate the copy to the overlying drivers with this flag cleared.
NDIS can return NET_BUFFER_LIST structures to the miniport driver in any arbitrary order and in any combination. That is, the linked list of NET_BUFFER_LIST structures that NDIS returns to a miniport driver by calling MiniportReturnNetBufferLists can have NET_BUFFER_LIST structures from different previous calls to NdisMCoIndicateReceiveNetBufferLists.
Miniport drivers must set the SourceHandle member in the NET_BUFFER_LIST structures to the same value as the NdisVcHandle parameter of NdisMCoIndicateReceiveNetBufferLists. so that NDIS can return the NET_BUFFER_LIST structures to the correct miniport driver.
Intermediate drivers also set the SourceHandle member in the NET_BUFFER_LIST structure to the NdisVcHandle value. If an intermediate driver forwards a receive indication, the driver must save the SourceHandle value that the underlying driver provided before it writes to the SourceHandle member. When NDIS returns a forwarded NET_BUFFER_LIST structure to the intermediate driver, the intermediate driver must restore the SourceHandle that it saved.