1.1.1.2 Registering an Intermediate Driver as a Protocol

An intermediate driver registers its ProtocolXxx functions with NDIS by calling NdisRegisterProtocol declared as follows:

VOID
    NdisRegisterProtocol(
        OUT PNDIS_STATUS
Status,
        OUT PNDIS_HANDLE
NdisProtocolHandle,
        IN NDIS_PROTOCOL_CHARACTERISTICS
ProtocolCharacteristics,
        IN UINT
CharacteristicsLength
        );

Before calling NdisRegisterProtocol, the intermediate driver must:

  1. Zero a structure of type NDIS_PROTOCOL_CHARACTERISTICS. An intermediate driver can use a 4.0 ProtocolCharacteristics or a 3.0 ProtocolCharacteristics structure.

  2. Store the addresses of the mandatory ProtocolXxx functions as well as any optional ProtocolXxx functions the driver supports.

The NdisProtocolHandle returned by this call is opaque to an intermediate driver. The handle must be retained by the intermediate driver and provided as an input parameter in future calls made by the protocol part of the intermediate driver to NDIS, for instance to open underlying adapter.

The possible optional and required functions an intermediate driver can export are listed below:

BindAdapterHandler
NDIS calls this function to request the intermediate driver to bind to an underlying NIC or virtual NIC whose name is passed as a parameter to this handler, particularly if the intermediate driver registered its MiniportXxx functions with NdisIMRegisterLayeredMiniport. Supplying a ProtocolBindAdapter function makes an intermediate driver PnP-ready. See Section 1.2 for more information on dynamic binding.
UnbindAdapterHandler
This is a required function if an intermediate driver supplies a ProtocolBindAdapter function. ProtocolUnbindAdapter is called by NDIS to close a binding to the underlying NIC or virtual NIC whose name is passed to this function. ProtocolUnbindAdapter calls NdisCloseAdapter and deallocates resources when the binding is successfully closed.
OpenAdapterCompleteHandler
This is a required function. If an intermediate driver’s call to NdisOpenAdapter returns NDIS_STATUS_PENDING, ProtocolOpenAdapterComplete is subsequently called to complete the binding.
CloseAdapterCompleteHandler
This is a required function. If an intermediate driver’s call to NdisCloseAdapter returns NDIS_STATUS_PENDING, ProtocolCloseAdapterComplete is subsequently called to complete the unbinding.
ReceiveHandler
This is a required function. ProtocolReceive is called with a pointer to a lookahead buffer containing data received over the network. If this buffer contains less than the full net packet, ProtocolReceive calls NdisTransferData with a packet descriptor to get the remainder of the net packet. If the underlying driver calls NdisMIndicateReceivePacket to indicate receives, the lookahead buffer passed to ProtocolReceive will always contain a full net packet.
ReceivePacketHandler
This is an optional function. A ProtocolReceivePacket function is provided if the intermediate driver will be layered over any NIC driver that indicates an array of pointer(s) to one or more packet descriptors or that supplies out-of-band data with its receive indications by calling NdisMIndicateReceivePacket. If a developer is unsure of the environment in which the intermediate driver will execute, this function should be provided because the intermediate driver will achieve better performance over any underlying NIC driver that makes multipacket receive indications.
ReceiveCompleteHandler
This is a required function. ProtocolReceiveComplete is called when any packets previously indicated to ProtocolReceive can be postprocessed.
TransferDataCompleteHandler
This is a required function if the ProtocolReceive function ever calls NdisTransferData. If a previous call to NdisTransferData to copy the remainder of a received packet returned NDIS_STATUS_PENDING, ProtocolTransferDataComplete is called when the transfer operation is done.
ResetCompleteHandler
This is a required function. ProtocolResetComplete is called when a reset operation, begun with a call to NdisReset that returned NDIS_STATUS_PENDING, is done. Usually, intermediate drivers do not call NdisReset, but the drivers above them might, so an intermediate driver could forward such a reset request to the underlying NDIS driver.

RequestCompleteHandler

This is a required function. ProtocolRequestComplete is called upon completion of a query/set operation, begun with a call to NdisRequest that returned NDIS_STATUS_PENDING, is done.

SendCompleteHandler
This is a required function. ProtocolSendComplete is called for each packet transmitted with a call to NdisSend that returned NDIS_STATUS_PENDING as the status of the send operation. If an array of packets is sent by calling NdisSendPackets, ProtocolSendComplete is called once for each packet passed to NdisSendPackets. The intermediate driver can determine the status of a send operation that calls NdisSendPackets only from the status argument input to ProtocolSendComplete.
StatusHandler
This is a required function. ProtocolStatus is called by NDIS with status notifications initiated by an underlying NIC driver.
StatusCompleteHandler
This is a required function. ProtocolStatusComplete is called by NDIS to indicate that a status change, previously indicated to ProtocolStatus, is now complete.

An UnloadHandler entry is ignored in Windows NT platforms; it should be set to NULL. The TranslateHandler member of the characteristics structure is reserved for system use and should also be set to NULL.