NTSTATUS
ClientEventReceiveDatagram (
IN PVOID TdiEventContext,
IN LONG SourceAddressLength,
IN PVOID SourceAddress,
IN LONG OptionsLength,
IN PVOID Options,
IN ULONG ReceiveDatagramFlags,
IN ULONG BytesIndicated,
IN ULONG BytesAvailable,
OUT ULONG * BytesTaken,
IN PVOID Tsdu,
OUT PIRP * IoRequestPacket
);
ClientEventReceiveDatagram is an event handler that the underlying TDI transport calls in response to an incoming receive from a remote node that was directed to a local-node transport address that the client has opened.
Parameters
TdiEventContext
Points to the client-supplied context provided in the IRP that was set up with TdiBuildSetEventHandler when ClientEventReceiveDatagram was registered with the underlying transport.
SourceAddressLength
Specifies the size in bytes of the buffer at SourceAddress.
SourceAddress
Points to a buffer specifying the remote-node transport address from which the datagram was sent.
OptionsLength
Specifies the size in bytes of the buffer at Options. Zero implies no option string is available. Options is NULL if this parameter is zero.
Options
Points to a buffer specifying a string of transport-specific options sent with the datagram. This pointer is NULL if OptionsLength is zero.
ReceiveDatagramFlags
Specifies the nature of the receive-datagram indication as a combination (ORed) of the following flags:
TDI_RECEIVE_ENTIRE_MESSAGE
The buffer mapped at Tsdu contains a full TSDU. The client should return control as quickly as possible after copying the indicated data into an internal buffer if it accepts the TSDU.
If this flag is clear (or if TDI_RECEIVE_PARTIAL is set by a legacy transport), ClientEventReceiveDatagram must check the BytesAvailable and BytesIndicated parameters to determine how much of the TSDU has been provided. Although legacy transports continue to set the TDI_RECEIVE_PARTIAL flag, newer transports leave clear the TDI_RECEIVE_ENTIRE_MESSAGE flag to indicate partial TSDUs to their clients.
TDI_RECEIVE_COPY_LOOKAHEAD
Unless TDI_RECEIVE_ENTIRE_MESSAGE is set, BytesAvailable is something less than BytesIndicated, and ClientEventReceiveDatagram should copy the number of bytes available into an internal buffer, set the variable at BytesTaken, and return control. The client will subsequently submit one or more TDI_RECEIVE_DATAGRAM requests to get the remainder of the TSDU.
TDI_RECEIVE_BROADCAST
The receive was broadcast.
TDI_RECEIVE_MULTICAST
The receive was multicast.
TDI_RECEIVE_PEEK
The transport has buffered some receive data internally, but not yet the full TSDU. The client can examine the buffer mapped at Tsdu to decide whether to submit a TDI_RECEIVE_DATAGRAM request for the TSDU.
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.
BytesIndicated
Specifies the number of bytes of data in the buffer at Tsdu. This parameter is always less than or equal to the value of BytesAvailable. A TDI transport provides at least 128 bytes of data in a receive indication to its client, unless the received datagram is less than 128 bytes in length. If BytesAvailable is greater than BytesIndicated, the transport has received data that it does not present when it calls ClientEventReceiveDatagram.
BytesAvailable
Specifies the total number of bytes in the received TSDU.
BytesTaken
Points to a caller-supplied variable in which ClientEventReceiveDatagram returns the number of bytes of data it copied from the datagram.
Tsdu
Points to an MDL, possibly the initial MDL in a chain, mapping the buffer containing the received TSDU data.
IoRequestPacket
Points to a caller-supplied variable in which ClientEventReceiveDatagram returns a pointer to an IRP that it set up with TdiBuildReceiveDatagram. If this parameter is NULL, the client will not be making a receive request for the remainder of the TSDU.
Return Value
ClientEventReceiveDatagram can return one of the following:
STATUS_SUCCESS
Indicates the client copied all the data in the given TSDU and set the variable at BytesTaken to the value at BytesIndicated.
STATUS_MORE_PROCESSING_REQUIRED
Indicates the client has supplied an IRP requesting the remainder of the TSDU, usually after copying BytesIndicated into an internal buffer.
STATUS_DATA_NOT_ACCEPTED
Indicates this client is not interested in the TSDU.
Comments
When a datagram arrives from a remote node, the transport calls the registered ClientEvent(Chained)ReceiveDatagram handlers for each client with an open file object representing an address that matches the destination address of the datagram. Because a datagram is not associated with an established connection, the TDI driver passes the transport address of the remote-node sender at SourceAddress to the receiving client along with the datagram.
ClientEventReceiveDatagram accepts or rejects a TSDU that the TDI driver has received on a particular transport address that the client opened with a preceding call to ZwCreateFile. A datagram TSDU is discrete. Unlike a normal or expedited TSDU, it cannot be transmitted as a sequence of records. In other words, a full datagram is available to the TDI transport, although the driver might not pass all of it in a single call to ClientEventReceiveDatagram.
The transport has removed the transport-layer header from the TSDU before it calls ClientEventReceiveDatagram.
The driver does not call ClientEventReceiveDatagram if the client has an outstanding receive or receive-datagram request on the local transport address that is the target of an incoming datagram.
When ClientEventReceiveDatagram is called, it can do one of the following:
·Reject the indicated TSDU if it has no use for the data by returning STATUS_DATA_NOT_ACCEPTED
·Copy all of the data into an internal buffer if TDI_RECEIVE_ENTIRE_MESSAGE is set in the ReceiveFlags and return STATUS_SUCCESS
When it has finished copying receive data, ClientEventReceiveDatagram sets the variable at BytesTaken to the number of bytes of data accepted before it returns control.
·If TDI_RECEIVE_ENTIRE_MESSAGE is clear (or TDI_RECEIVE_PARTIAL is set), copy all of the indicated data, set up an IRP for a TDI_RECEIVE_DATAGRAM request, and return STATUS_MORE_PROCESSING_REQUIRED
If the ClientEventReceiveDatagram issues a receive-datagram request, the transport retrieves any data that ClientEventReceiveDatagram did not receive, along with any new data the TDI transport has available. If the client does not make such a receive-datagram request, it loses this data.
Any TDI transport driver that supports internal buffering should retain a datagram during its clients' receive-datagram operations to satisfy any subsequent receive-datagram requests. The client of such a TDI driver can determine the total amount of buffer space it allocates for received datagrams by submitting a request, set up with TdiBuildQueryInformation for the QType TDI_QUERY_DATAGRAM_INFO or TDI_QUERY_MAX_DATAGRAM_INFO. Usually, such a transport's buffer space for datagrams is around four kilobytes.
To receive indications for broadcast datagrams that the TDI driver receives on the network, the client must open the local-node broadcast address of its underlying transport and register a ClientEvent(Chained)ReceiveDatagram handler on the address.
By default, ClientEventReceiveDatagram runs at IRQL DISPATCH_LEVEL.
See Also
ClientEventChainedReceiveDatagram, ClientEventReceive, TdiBuildInternalDeviceControlIrp, TdiBuildReceiveDatagram, TdiBuildSetEventHandler, TA_ADDRESS