ClientEventChainedReceiveExpedited

NTSTATUS
ClientEventChainedReceiveExpedited(
IN PVOID TdiEventContext,
IN CONNECTION_CONTEXT ConnectionContext,
IN ULONG ReceiveFlags,
IN ULONG ReceiveLength,
IN ULONG StartingOffset,
IN PMDL Tsdu,
IN PVOID TsduDescriptor
);

ClientEventChainedReceiveExpedited is an event handler that the underlying TDI transport calls in response to an incoming expedited receive from a remote node with which the client has an established endpoint-to-endpoint connection.

The transport calls this handler, rather than ClientEventReceiveExpedited, when it is indicating a full TSDU and the client can be given direct read-only access to the buffered TSDU until the client has consumed the data.

Parameters

TdiEventContext

Points to the context the client provided in the IRP it previously set up with TdiBuildSetEventHandler to register ClientEventChainedReceiveExpedited.

ConnectionContext

Points to the client's context area for this connection endpoint. The client previously supplied this value to its underlying transport when its ClientEventConnect handler accepted a connection offer from the remote-node peer and/or when it opened the connection endpoint with ZwCreateFile.

ReceiveFlags

Specifies the nature of the receive indication as a combination (ORed) of the following flags:

TDI_RECEIVE_EXPEDITED

The buffer mapped at Tsdu contains expedited data received from the client's remote-node peer. This flag is always set when ClientEventChainedReceiveExpedited is called.

TDI_RECEIVE_ENTIRE_MESSAGE

The buffer mapped at Tsdu contains a full TSDU, and the client retains read-only access to this buffer until the client consumes the indicated data if ClientEventChainedReceiveExpedited returns STATUS_PENDING. This flag is always set when ClientEventChainedReceiveExpedited is called.

TDI_RECEIVE_AT_DISPATCH_LEVEL

The receive is being indicated at IRQL DISPATCH_LEVEL. This flag restricts the set of support routines that the client can call in processing this indication. Some transports never set this flag, whatever the current IRQL, when making receive-event notifications.

ReceiveLength

Specifies the number of bytes of client data in the buffer mapped at Tsdu.

StartingOffset

Specifies the byte offset at which the client data starts within the buffer mapped at Tsdu.

Tsdu

Points to an MDL, possibly the initial MDL in a chain, mapping the buffer containing the received TSDU.

TsduDescriptor

Points to a descriptor for the received TSDU. The client must call TdiReturnChainedReceives with this pointer subsequently if ClientEventChainedReceiveExpedited returns STATUS_PENDING for this receive indication. This pointer should be treated as a handle to an opaque variable, to be used by the client only as a parameter to TdiReturnChainedReceives if ClientEventChainedReceiveExpedited returns STATUS_PENDING.

Return Value

ClientEventChainedReceiveExpedited can return one of the following:

STATUS_SUCCESS

Indicates the client consumed all the data in the given TSDU and is returning ownership of the buffer immediately.

STATUS_PENDING

Indicates the client is retaining ownership of the buffer containing the given TSDU until it calls TdiReturnChainedPackets with the given TsduDescriptor.

STATUS_DATA_NOT_ACCEPTED

Indicates the client is not interested in the TSDU.

If the underlying transport buffers receives internally, the client might retrieve the data with a TDI_RECEIVE request, unless the transport discards buffered data indicated to ClientEventChainedReceive(Xxx) handlers.

Comments

A call to ClientEventChainedReceiveExpedited gives the client read-only access to the indicated TSDU for the range within the buffer specified by the input StartingOffset and ReceiveLength. If the indicated data is of interest to the client, ClientEventChainedReceiveExpedited either copies the indicated range of TSDU data into a client-allocated internal buffer and returns STATUS_SUCCESS immediately or retains control of the buffer by returning STATUS_PENDING. If it returns STATUS_PENDING, the client must call TdiReturnChainedReceives subsequently with the input TsduDescriptor to relinquish control of the buffer after the client has consumed the data.

In general, such a call to TdiReturnChainedReceives should occur as quickly as possible. Holding on to a buffer passed to ClientEventChainedReceiveExpedited for any extended period constrains I/O throughput in underlying driver(s), because the driver that allocated the buffer cannot reuse this resource for subsequent receive indications until TdiReturnChainedReceives is called.

Because calls to ClientEventChainedReceiveExpedited always indicate the availability of a full TSDU, the client never has to set up TDI_RECEIVE requests for such an indication, as the corresponding ClientEventReceiveExpedited handler sometimes must to obtain a full TSDU. Consequently, receive indications made to ClientEventChainedReceiveExpedited increase network I/O throughput and performance by decreasing call overhead for the client, for its underlying transport, and for the system overall. A transport never calls the corresponding ClientEventReceiveExpedited handler with the same indication it makes to ClientEventChainedReceiveExpedited.

When ClientEventChainedReceiveExpedited returns control with either STATUS_SUCCESS or STATUS_DATA_NOT_ACCEPTED, the underlying transport assumes the client is done with this receive indication.

By default, ClientEventChainedReceiveExpedited runs at IRQL DISPATCH_LEVEL.

See Also

ClientEventChainedReceive, ClientEventReceiveExpedited, TdiBuildSetEventHandler, TdiReturnChainedReceives