Canceling a Send Request in a Filter Driver
Filter drivers can cancel send requests that were originated by the filter driver or that were originated by overlying drivers.
Canceling Filter Driver Send Requests
The following figure illustrates canceling a send request that was originated by a filter driver.
A filter driver calls the NDIS_SET_NET_BUFFER_LIST_CANCEL_ID macro for each NET_BUFFER_LIST structure that it creates for send operations. The NDIS_SET_NET_BUFFER_LIST_CANCEL_ID function marks the specified data with a cancellation identifier.
Before assigning cancellation IDs to network data, a filter driver must call NdisGeneratePartialCancelId to obtain the high-order byte of each cancellation ID that it assigns. This ensures that the driver does not duplicate cancellation IDs assigned by other drivers in the system. Drivers typically call NdisGeneratePartialCancelId one time from the DriverEntry routine. However, drivers can obtain more than one partial cancellation identifier by calling NdisGeneratePartialCancelId multiple times.
To cancel the pending transmission of data in a marked NET_BUFFER_LIST structure, a filter driver passes the cancellation ID to the NdisFCancelSendNetBufferLists function. Drivers can obtain a NET_BUFFER_LIST structure's cancellation ID by calling the NDIS_GET_NET_BUFFER_LIST_CANCEL_ID macro.
If a filter driver marks all NET_BUFFER_LIST structures with the same cancellation identifier, it can cancel all pending transmissions with a single call to NdisFCancelSendNetBufferLists. If a filter driver marks all NET_BUFFER_LIST structures within a subgroup of NET_BUFFER_LIST structures with a unique identifier, it can cancel all pending transmissions within that subgroup with a single call to NdisFCancelSendNetBufferLists.
NDIS calls the cancel send function of the underlying drivers. After aborting the pending transmission, the underlying drivers call a send complete function (for example NdisMSendNetBufferListsComplete) to return the NET_BUFFER_LIST structures with a completion status of NDIS_STATUS_SEND_ABORTED. NDIS, in turn, calls the filter driver's FilterSendNetBufferListsComplete function.
In FilterSendNetBufferListsComplete, a filter driver can call NDIS_SET_NET_BUFFER_LIST_CANCEL_ID with CancelId set to NULL. This prevents the NET_BUFFER_LIST from accidentally being used again with a stale cancellation ID.
Canceling Send Requests Originated by Overlying Drivers
The following figure illustrates canceling a send request that was originated by an overlying driver.
Overlying drivers call a cancel send function ( NdisFCancelSendNetBufferLists or NdisCancelSendNetBufferLists) to cancel outstanding send requests. These overlying drivers must mark the send data with a cancellation ID before making a send request.
NDIS calls a filter driver's FilterCancelSendNetBufferLists function to cancel the transmission of all NET_BUFFER_LIST structures that are marked with a specified cancellation identifier.
FilterCancelSendNetBufferLists performs the following operations:
Traverses the filter driver's list of queued NET_BUFFER_LIST structures for the specified filter module and calls the NDIS_GET_NET_BUFFER_LIST_CANCEL_ID macro to obtain the cancellation identifier for each structure. The filter driver compares the cancellation ID that NDIS_GET_NET_BUFFER_LIST_CANCEL_ID returns with the cancellation ID that NDIS passed to FilterCancelSendNetBufferLists.
Removes from the send queue (unlinks) all NET_BUFFER_LIST structures whose cancellation identifiers match the specified cancellation identifier.
Calls the NdisFSendNetBufferListsComplete function for all unlinked NET_BUFFER_LIST structures to return the structures. The filter driver sets the status field of the NET_BUFFER_LIST structures to NDIS_STATUS_SEND_ABORTED.
Calls the NdisFCancelSendNetBufferLists function to pass the cancel send request to underlying drivers. The filter driver passes on the cancellation identifier that it received from the overlying driver. The cancel operation proceeds as with a filter-driver-originated cancel send operation.