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.
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:
STATUS_SUCCESS
STATUS_INVALID_ADDRESS_COMPONENT
STATUS_INVALID_PARAMETER
The IoStatus.Information member is zero since no data is transferred
for this request.
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.
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:
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:
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.
ClientEventChainedReceive, ClientEventChainedReceiveDatagram, ClientEventChainedReceiveExpedited, ClientEventConnect, ClientEventDisconnect, ClientEventError, ClientEventReceive, ClientEventReceiveDatagram, ClientEventReceiveExpedited, ClientEventSendPossible, ProtocolReceive, ProtocolReceivePacket, TdiBuildSetEventHandler, TdiDispatchInternalDeviceControl, TDI_RECEIVE, TdiReturnChainedReceives