NDIS_STATUS
ProtocolReceive(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_HANDLE MacReceiveContext,
IN PVOID HeaderBuffer,
IN UINT HeaderBufferSize,
IN PVOID LookAheadBuffer,
IN UINT LookaheadBufferSize,
IN UINT PacketSize
);
ProtocolReceive is a required driver function that determines whether a received network packet is of interest to the protocol’s client(s) and, if so, copies the indicated data and, possibly, calls NdisTransferData to retrieve the rest of the indicated packet.
The indicating driver ensures this number is at least as large as the size it returned for the protocol’s preceding call to NdisRequest with OID_GEN_CURRENT_LOOKAHEAD or the size of the packet, whichever is less.
If PacketSize is less than or equal to the given LookaheadBufferSize,
the lookahead buffer contains the entire packet. If the underlying driver made
the indication with NdisMIndicateReceivePacket, the lookahead buffer
always contains a full network packet.
ProtocolReceive determines whether the protocol must call NdisTransferData by comparing this parameter to the given LookaheadBufferSize.
ProtocolReceive can return either of the following:
Returning this status quickly for rejected packets yields higher performance
for the protocol and the highest possible network I/O throughput for the
system as a whole.
NDIS provides equal packet access for any number of protocol drivers bound above an underlying NIC miniport. NDIS can use the status that ProtocolReceive returns to optimize the order in which bound protocols receive indications for subsequent packets.
When a miniport calls a filter-specific NdisM..IndicateReceive function, NDIS calls the ProtocolReceive functions of bound protocols. A call to an NdisM..IndicateReceive function indicates that a network packet, or some initial lookahead portion of it, is available for inspection by bound protocols. Each ProtocolReceive function, in turn, inspects the packet header and data, optionally copies as much of the header and/or data as is made available, and calls NdisTransferData to instruct the NIC driver to copy any remaining data into a protocol-supplied buffer chained to a protocol-allocated packet descriptor if the protocol accepts the packet. ProtocolReceive can call NdisTransferData only once per receive indication.
Before a miniport calls NdisMIndicateReceivePacket with a packet array, it can set the Status member of an out-of-band block associated with a packet descriptor in the array to NDIS_STATUS_RESOURCES. This also causes NDIS to call the ProtocolReceive functions of bound protocols with the network packet header and data specified by that packet descriptor and, separately, with the received network packets specified in all subsequent descriptors in the indicated packet array. Each ProtocolReceive function, in turn, inspects the given network packet header and data and each optionally copies the indicated network packet data.
If the underlying miniport supplies out-of-band information with the receives it indicates, ProtocolReceive can call NdisQueryReceiveInformation to retrieve the out-of-band information for each such packet. Because such an underlying miniport always indicates full-packet receives, ProtocolReceive will never call NdisTransferData for a packet indicated with NdisMIndicateReceivePacket.
NDIS calls ProtocolReceive functions sequentially as calls to NdisM..IndicateReceive or NdisMIndicateReceivePacket occur, but it can indicate a packet to bound protocols using separate calls. However, every protocol must be able to handle out-of-order received packets since neither NDIS nor the underlying NIC miniport has any control over the network over which packets are transmitted.
A driver writer should minimize the amount of time spent in the ProtocolReceive function so that the protocol does not lose additional incoming packets, particularly from underlying drivers that call the filter-specific NdisM..IndicateReceive functions. ProtocolReceive must either reject an incoming packet or recognize the packet as of interest to its client(s) quickly. If it accepts the packet, ProtocolReceive must find a place to put packet data and copy the data quickly. Shortly after ProtocolReceive returns, when time constraints are not so severe, any underlying miniport that made one or more indications with NdisM..IndicateReceive will call the corresponding NdisM..IndicateReceiveComplete. The protocol driver’s ProtocolReceiveComplete function then performs any necessary postprocessing for the original indication(s).
The underlying driver does not remove any headers or trailers from the packet data received on its NIC, nor does it remove any received padding. In other words, a packet can include padding in the data and length indicated to protocols. ProtocolReceive is responsible for detecting and ignoring such padding.
The buffers at HeaderBuffer and LookAheadBuffer passed to ProtocolReceive are read-only and valid only until ProtocolReceive returns control. ProtocolReceive must copy all the indicated data that the driver needs into protocol-allocated storage. Whether the protocol can copy the indication directly depends on the NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA flag returned for the OID_GEN_MAC_OPTIONS query. If this flag was set, ProtocolReceive can use NdisMoveMemory to copy the indicated data to its own storage; otherwise, it should use TdiCopyLookaheadData. However, the protocol can call TdiCopyLookaheadData even if the underlying driver set the NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA flag.
The ProtocolReceive function of an NDIS intermediate driver cannot simply forward receive indications to still higher-level protocols. Such an attempt can cause a deadlock. Instead, such a driver must repackage the indication in a fresh packet descriptor and call NdisIMSwitchToMiniport to forward the indication from the appropriate context. If NdisIMSwitchToMiniport returns FALSE, the driver must call NdisIMQueueMiniportCallback and forward the indication from a protocol-supplied MiniportCallback function.
By default, ProtocolReceive runs at IRQL DISPATCH_LEVEL in an arbitrary thread context.
MiniportTransferData, NdisAllocatePacket, NdisGetFirstBufferFromPacket, NdisIMQueueMiniportCallback, NdisIMSwitchToMiniport, NdisMArcIndicateReceive, NdisMEthIndicateReceive, NdisMFddiIndicateReceive, NdisMIndicateReceivePacket, NdisMoveMemory, NdisMTrIndicateReceive, NdisMWanIndicateReceive, NdisQueryReceiveInformation, ProtocolReceiveComplete, ProtocolReceivePacket, ProtocolTransferDataComplete, TdiCopyLookaheadData