2.1.1 Registering as an NDIS Protocol Driver

A driver registers its ProtocolXxx functions with NDIS in the context of its DriverEntry function by calling NdisRegisterProtocol, defined as follows:

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

The NdisProtocolHandle returned by this call is opaque to a protocol driver. The handle must be retained by the protocol driver and provided as an input parameter in future calls to NDIS, to open an adapter for example.

Before making this call, DriverEntry must do the following:

  1. Zero-initialize a structure of type NDIS_PROTOCOL_CHARACTERISTICS, for instance with a call to NdisZeroMemory. This assures that unused members for optional entry points are set to NULL. If the structure is not zeroed, any unused members must be set to NULL before calling NdisRegisterProtocol.

  2. Store the addresses of the mandatory ProtocolXxx functions, as well as any optional ProtocolXxx functions the driver exports, in the characteristics structure members, as follows:

    BindAdapterHandler
    This is an optional function in protocol drivers. A PnP-ready protocol driver specifies this entry point so it can be called by NDIS at the ProtocolBindAdapter function when an adapter is available. Specifying this entry point requires a V4.0 structure at ProtocolCharacteristics.
    UnbindAdapterHandler
    This is a required function if the protocol driver registered a ProtocolBindAdapter function. Specifying this entry point also requires a V4.0 structure at ProtocolCharacteristics.
    OpenAdapterCompleteHandler
    This is a required function. If a protocol driver’s call to NdisOpenAdapter returns NDIS_STATUS_PENDING, ProtocolOpenAdapterComplete is subsequently called to complete the binding operation.
    CloseAdapterCompleteHandler
    This is a required function. If a protocol driver’s call to NdisCloseAdapter returns NDIS_STATUS_PENDING, ProtocolCloseAdapterComplete is subsequently called to complete the unbinding operation.
    ReceiveHandler
    This is a required function. ProtocolReceive is called with a pointer to a lookahead buffer. If this buffer contains less than the full, received network packet, ProtocolReceive calls NdisTransferData with a protocol-allocated packet descriptor specifiying protocol-allocated buffer(s) to obtain the remainder of the received packet.
    ReceiveCompleteHandler
    This is a required function. ProtocolReceiveComplete is called to indicate that any received packets previously indicated to ProtocolReceive can now be postprocessed.
    TransferCompleteHandler
    This is a required function unless the protocol binds itself exclusively to underlying NIC driver(s) that indicate packets with NdisMIndicateReceivePacket. ProtocolTransferDataComplete is called when a previous call to NdisTransferData returned NDIS_STATUS_PENDING and the remaining data has been copied into the protocol-supplied buffers chained to a given packet descriptor.
    ReceivePacketHandler
    This is an optional function. A ProtocolReceivePacket function should be provided if the protocol driver might be bound to a NIC driver that indicates an array of one or more packets by calling NdisMIndicateReceivePacket. Specifying this entry point requires a V4.0 structure at ProtocolCharacteristics.
    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, ProtocolSendComplete is called once for each packet passed to NdisSendPackets, whether or not it returned pending.
    ResetCompleteHandler
    This is a required function. ProtocolResetComplete is called when a protocol-initiated reset operation, begun with a call to NdisReset that returned NDIS_STATUS_PENDING, is completed.
    RequestCompleteHandler
    This is a required function. ProtocolRequestComplete is called when a protocol-initiated query or set operation, begun with a call to NdisRequest that returned NDIS_STATUS_PENDING, is completed.
    StatusHandler
    This is a required function. ProtocolStatus is called to handle status changes indicated by the underlying NDIS driver.
    StatusCompleteHandler
    This is a required function. ProtocolStatusComplete is called by NDIS, along with ProtocolStatus, to report the start and end of an NDIS- or NIC-driver-initiated reset operation.

A protocol driver should set the ProtocolCharacteristics TranslateHandler and UnloadHandler members to NULL. The TranslateHandler  member is reserved for future use. NDIS never calls an entry point specified in UnloadHandler on Windows NT platforms. Instead, the Windows NT I/O Manager calls the Unload routine that the protocol driver sets in the driver object passed in to the protocol's DriverEntry function.