W_SEND_PACKETS_HANDLER callback function

Note   NDIS 5. x has been deprecated and is superseded by NDIS 6. x. For new NDIS driver development, see Network Drivers Starting with Windows Vista. For information about porting NDIS 5. x drivers to NDIS 6. x, see Porting NDIS 5.x Drivers to NDIS 6.0.

The MiniportSendPackets function is required for drivers that do not have a MiniportSend, MiniportWanSend, or MiniportCoSendPackets function. MiniportSendPackets transfers some number of packets, specified as an array of packet pointers, over the network.



VOID MiniportSendPackets(
  _In_ NDIS_HANDLE   MiniportAdapterContext,
  _In_ PPNDIS_PACKET PacketArray,
  _In_ UINT          NumberOfPackets
{ ... }


  • MiniportAdapterContext [in]
    Specifies the handle to a miniport driver-allocated context area in which the driver maintains per-NIC state, set up by MiniportInitialize.

  • PacketArray [in]
    Pointer to the initial element in a packet array, with each element specifying the address of a packet descriptor for a packet to be transmitted, along with an associated out-of-band data block containing information such as the packet priority, an optional timestamp, and the per-packet status to be set by MiniportSendPackets.

  • NumberOfPackets [in]
    Specifies the number of pointers to packet descriptors at PacketArray.

Return value



If a driver registers both MiniportSendPacketsand MiniportSendfunctions when it initializes, NDIS always calls its MiniportSendPacketsfunction. If a driver registers both MiniportSendPacketsand MiniportCoSendPacketsfunctions, NDIS calls its MiniportCoSendPacketsfunction when any bound protocol calls NdisCoSendPackets.

The input packet descriptor pointers have been ordered according to the order in which the packets should be sent over the network by the protocol driver that set up the packet array. The NDIS library preserves the protocol-determined ordering when it submits each packet array to MiniportSendPackets.

Consequently, MiniportSendPacketsshould transmit each packet in any given array sequentially. MiniportSendPacketscan call NdisQueryPacketto extract information, such as the number of buffer descriptors chained to the packet and the total size in bytes of the requested transfer. It can call NdisGetFirstBufferFromPacket, NdisGetFirstBufferFromPacketSafe, NdisQueryBuffer, NdisQueryBufferSafe, or NdisQueryBufferOffsetto extract information about individual buffers containing the data to be transmitted.

MiniportSendPacketscan retrieve any protocol-supplied out-of-band information associated with each packet by using the relevant NDIS_GET_PACKET_TIME_TO_SENDand NDIS_GET_PACKET_MEDIA_SPECIFIC_INFOmacros.

Each protocol driver must set up packet arrays with packet descriptors that are fully set up to be passed by the underlying driver's MiniportSendPacketsfunction to its NIC. That is, the protocol is responsible for determining what is required, based on the medium type selected by the miniport driver to which the protocol bound itself. However, a protocol can supply packets shorter than the minimum for the selected medium, which MiniportSendPacketsmust pad if its medium imposes a minimum-length requirement on transmits.

Any NDIS intermediate driver that layers itself between a higher-level protocol and an underlying NIC driver has the same responsibility as any protocol driver to set up packets according to the requirements of the underlying miniport driver and its selected medium. Such an intermediate driver must repackage each incoming send packet in a fresh packet descriptor that was allocated by the intermediate driver.

MiniportSendPacketscan use only the eight-byte area at MiniportReservedwithin the NDIS_PACKETstructure for its own purposes. Consequently, an NDIS intermediate driver that forwards send requests to an underlying NIC driver must repackage the packets given to its MiniportSendPacketsfunction in fresh packet descriptors, which the intermediate driver allocates from packet pool, so that the underlying miniport driver has a MiniportReservedarea it can use.

If the underlying driver's MiniportQueryInformationfunction set the NDIS_MAC_OPTION_NO_LOOPBACK flag when the NDIS library queried the OID_GEN_MAC_OPTIONS, the miniport driver must not attempt to loop back any packets. The NDIS library provides software loopback support for such a driver.

Whether the driver is serialized or deserialized determines how its MiniportSendPacketsfunction handles the completion of input packet descriptor(s) when this driver function is called.

Serialized Miniports

The MiniportSendPacketsfunction of a serialized driver sets one of the following values in the Statusmember of the NDIS_PACKET_OOB_DATAblock associated with an input packet descriptor:

    The driver (or its NIC) has accepted the packet data for transmission, so MiniportSendPackets is returning the packet and the associated out-of-band data, which NDIS will return to the protocol that made this request.

    The driver will complete the transmit operation asynchronously with NdisMSendComplete.

    The serialized miniport driver currently cannot set up the transmit operation due to resource constraints, so NDIS should queue this packet and all remaining packets in the given array for resubmission to MiniportSendPackets when the driver next calls NdisMSendResourcesAvailable or NdisMSendComplete.

    When MiniportSendPackets sets this value for a packet in the input array, the NDIS library assumes all remaining packets in the array have the same status set, so NDIS requeues the associated packets in the same order, which preserves the protocol-determined ordering of the packet array. NDIS reflects this status to the protocol as NDIS_STATUS_PENDING for this packet and for all remaining packets in the given array.

    The given packet was invalid or unacceptable to the NIC. Setting this status or any other driver-determined NDIS_STATUS_XXX error value for a packet effectively completes the packet, which NDIS returns to the allocating protocol as a failed send request.

When MiniportSendPacketsreturns control, a serialized driver can no longer access anything in the given packet array with the following exceptions:

  • If MiniportSendPackets set the Status for a packet to NDIS_STATUS_PENDING, the miniport driver can access the packet descriptor and any media-specific information in the associated out-of-band data block. MiniportSendPackets can use the buffer descriptors chained to that packet descriptor, as well.

    After the driver calls NdisMSendComplete with the final status of the transmit operation, ownership of the given packet descriptor, out-of-band data block, and associated buffers reverts to the allocating protocol. A miniport driver should never return NDIS_STATUS_RESOURCES for a packet it passes to NdisMSendComplete.

  • If MiniportSendPackets set the Status for a packet to NDIS_STATUS_RESOURCES, the miniport driver can access the packet descriptor, its associated out-of-band data block, and the buffer descriptors chained to that packet when NDIS resubmits the send request, along with subsequent elements of the packet array, to MiniportSendPackets.

Setting NDIS_STATUS_RESOURCES for an incoming packet causes NDIS to requeue the associated packet and those specified by all remaining array elements for subsequent resubmission to the MiniportSendPacketsfunction of a serialized driver. NDIS assumes that a subsequent call to NdisMSendResourcesAvailableor NdisMSendComplete, whichever occurs first, indicates that such a driver's MiniportSendPacketsfunction is ready to accept more packets for transmission. NDIS preserves the original ordering of returned array elements when it resubmits them as a packet array to MiniportSendPackets.

The MiniportSendPacketsfunction of a serialized miniport driver runs at IRQL = DISPATCH_LEVEL.

Deserialized Miniports

The NDIS library ignores the OOB block in all packet descriptors it submits to the MiniportSendPacketsfunctions of deserialized drivers and assumes that all deserialized miniports will complete each packet descriptor input to their MiniportSendPacketsfunctions asynchronously with NdisMSendComplete. Consequently, such a deserialized driver's MiniportSendPacketsfunction usually ignores the Statusmember of the NDIS_PACKET_OOB_DATAblock, but it can set this member to the same status as it subsequently passes to NdisMSendComplete.

Rather than relying on NDIS to queue and resubmit send packets whenever MiniportSendPacketshas insufficient resources to transmit the given packets, a deserialized miniport driver manages its own internal packet queuing. Such a driver is responsible for holding incoming send packets in its internal queue until they can be transmitted over the network and for preserving the protocol-determined ordering of packet descriptors incoming to its MiniportSendPacketsfunction. A deserialized miniport driver must complete each incoming send packet with NdisMSendComplete, and it cannot call NdisMSendResourcesAvailable.

A deserialized miniport driver should never pass STATUS_INSUFFICIENT_RESOURCES to NdisMSendCompletewith a protocol-allocated packet descriptor that was originally submitted to its MiniportSendPacketsfunction. Such a returned status effectively fails the send operation requested by the protocol, and NDIS would return the packet descriptor and all associated resources to the protocol that originally allocated it.

The MiniportSendPacketsfunction of a deserialized miniport driver can be called at any IRQL <= DISPATCH_LEVEL. The MiniportSendPacketsfunction of a deserialized driver is responsible for synchronizing access to its internal queues of packet descriptors with the driver's other MiniportXxx functions that also access the same queues.


Target platform



Not supported for NDIS 6.0 drivers in Windows Vista. Use MiniportSendNetBufferLists instead. Supported for NDIS 5.1 drivers in Windows Vista and Microsoft Windows XP.


Ndis.h (include Ndis.h)


<= DISPATCH_LEVEL (see Remarks section)

See also




























Send comments about this topic to Microsoft