TDI_SET_EVENT_HANDLER

When a kernel-mode client makes a TDI_SET_EVENT_HANDLER request, it asks the underlying TDI transport driver to call the specified ClientEventXxx routine whenever the corresponding network event occurs.

IRP

The transport calls IoGetCurrentIrpStackLocation with the given Irp to get a pointer to its own I/O stack location in the IRP, shown in the following list as IrpSp. IRP members relevant to this request include the following:

IoStatus.Status
Specifies the final status of the set-event-handler request. The transport sets this member before it completes the IRP, possibly to one of the following:

STATUS_SUCCESS
STATUS_INVALID_ADDRESS_COMPONENT
STATUS_INVALID_PARAMETER

The IoStatus.Information member is zero since no data is transferred for this request.

IrpSp->MajorFunction
Specifies IRP_MJ_INTERNAL_DEVICE_CONTROL. The transport can ignore this member if it exports a TdiDispatchInternalDeviceControl routine that handles only TDI_XXX requests.
IrpSp->MinorFunction
Specifies TDI_SET_EVENT_HANDLER.
IrpSp->FileObject
Points to an open file object representing a local-node address. The transport uses the FsContext and, possibly, FsContext2 fields to access the state it maintains about this address.

Depending on the type of ClientEventXxx handler to be registered, this address might be or become associated with an established endpoint-to-endpoint connection made by this client.

IrpSp->Parameters
Points to a TDI_REQUEST_KERNEL_SET_EVENT structure, defined as follows:
struct _TDI_REQUEST_KERNEL_SET_EVENT { 
    LONG EventType; 
    PVOID EventHandler; 
    PVOID EventContext; 
} TDI_REQUEST_KERNEL_SET_EVENT, *PTDI_REQUEST_KERNEL_SET_EVENT; 
 

The transport uses the members of this structure as follows:

EventType
Specifies the type of ClientEventXxx handler to be registered (see Comments).
EventHandler
Specifies the entry point of the ClientEventXxx routine to be called when this type of event occurs. This member can be NULL if the client is deregistering a previously registered event handler.
EventContext
Specifies a pointer to be passed, uninterpreted by the transport, to the given ClientEventXxx routine whenever it is called. This member can be NULL if EventHandler is NULL.

Comments

When its client first opens a file object that represents an address, a TDI transport initializes all event handlers associated with that address to NULL for the client.

Subsequently when the client calls TdiBuildSetEventHandler to set up this IRP, it specifies the type of handler to be registered. The transport finds this information at IrpSp->Parameters in the EventType member. On input, EventType can be one of the following system-defined values:

TDI_EVENT_CONNECT
Register the given ClientEventConnect handler to be called when an endpoint-to-endpoint connection is offered by a remote-node peer.
TDI_EVENT_DISCONNECT
Register the given ClientEventDisconnect handler to be called when an established endpoint-to-endpoint connection is being closed by the remote-node peer.
TDI_EVENT_RECEIVE
Register the given ClientEventReceive handler to be called when a normal receive comes in on an endpoint-to-endpoint connection from the remote node and the transport will give the client the opportunity to copy all or part of the buffered TSDU.
TDI_EVENT_CHAINED_RECEIVE
Register the given ClientEventChainedReceive handler to be called when a normal receive comes in on an endpoint-to-endpoint connection from the remote node and the transport can give this client read-only access to the buffered full TSDU until the client calls TdiReturnChainedReceives with the TsduDescriptor.
TDI_EVENT_RECEIVE_EXPEDITED
Register the given ClientEventReceiveExpedited handler to be called when an expedited receive comes in on an endpoint-to-endpoint connection from the remote node and the transport will give this client the opportunity to copy all or part of the buffered TSDU.
TDI_EVENT_CHAINED_RECEIVE_EXPEDITED
Register the given ClientEventChainedReceiveExpedited handler to be called when an expedited receive comes in on an endpoint-to-endpoint connection from the remote node and the transport can give this client read-only access to the buffered full TSDU until the client calls TdiReturnChainedReceives with the TsduDescriptor.
TDI_EVENT_RECEIVE_DATAGRAM
Register the given ClientEventReceive handler to be called when a datagram comes in from a remote node and the transport will give this client the opportunity to copy all or part of the buffered TSDU.
TDI_EVENT_CHAINED_RECEIVE_DATAGRAM
Register the given ClientEventChainedReceiveDatagram handler to be called when a datagram comes in from a remote node and the transport can give this client read-only access to the buffered full TSDU until the client calls TdiReturnChainedReceives with the TsduDescriptor.
TDI_EVENT_ERROR
Register the given ClientEventError handler to be called if an error occurs in the transport or in an underlying driver such that network I/O on this local-node address has become unreliable or impossible.
TDI_EVENT_SEND_POSSIBLE
Register the given ClientEventSendPossible handler to be called when the underlying transport, which previously returned a submitted send request with STATUS_DEVICE_NOT_READY, next has internal buffer space available into which it can copy the resubmitted client-supplied data to be sent.

In addition to the preceding system-defined events, a transport can extend this interface at the discretion of the driver writer to support notifications of transport-specific events to kernel-mode clients. Such a transport must define TDI_EVENT_XXX codes in which the most significant bit is set.

A TDI transport can indicate an event to a client while an event of the same kind is in progress. In other words, ClientEventXxx handlers are re-entrant.

A TDI transport can call a client-supplied ClientEvent(Chained)ReceiveXxx handler immediately if it is receiving data from the remote node, even before the transport completes the set-event-handler IRP that provided this client entry point.

In general, a transport calls ClientEventChainedReceiveXxx handlers when the transport's ProtocolReceivePacket function is called with a receive indication. A call to ProtocolReceivePacket implies that the underlying NDIS driver is temporarily relinquishing ownership of all its resources for the indication specified by the input NDIS_PACKET-type descriptor until that packet descriptor is returned to the underlying NDIS driver.

The transport must set up such an indication as previously described (see TDI_RECEIVE), passing the NDIS_PACKET-type descriptor as the TsduDescriptor input to its clients' ClientEventChainedReceiveXxx handlers. The clients' subsequent calls to TdiReturnChainedReceives returns the TsduDescriptor and all resources it describes to the indicating driver underlying the transport.

On the other hand, a transport calls ClientEventReceiveXxx handlers when the transport's ProtocolReceive function is called with a receive indication. A call to ProtocolReceive implies that the underlying NDIS driver expects all higher level network components to copy the indicated data and return as quickly as possible so the lower driver can regain control of the resources it used to make the receive indication.

A client can disable an already registered event handler by making a subsequent TDI_SET_EVENT_HANDLER request in which the EventType member specifies the type of handler but the EventHandler and EventContext members are NULL.

TdiBuildSetEventHandler is the macro a client uses to fill in the IRP.

See Also

ClientEventChainedReceive, ClientEventChainedReceiveDatagram, ClientEventChainedReceiveExpedited, ClientEventConnect, ClientEventDisconnect, ClientEventError, ClientEventReceive, ClientEventReceiveDatagram, ClientEventReceiveExpedited, ClientEventSendPossible, ProtocolReceive, ProtocolReceivePacket, TdiBuildSetEventHandler, TdiDispatchInternalDeviceControl, TDI_RECEIVE, TdiReturnChainedReceives