VOID
TdiBuildDisconnect (
IN PIRP Irp,
IN PDEVICE_OBJECT DevObj,
IN PFILE_OBJECT FileObj,
IN PVOID CompRoutine,
IN PVOID Contxt,
IN PLARGE_INTEGER Time,
IN PULONG Flags,
IN PTDI_CONNECTION_INFORMATION RequestConnectionInfo,
OUT PTDI_CONNECTION_INFORMATION ReturnConnectionInfo
);
TdiBuildDisconnect sets up an internal device control IRP for a TDI_DISCONNECT request to the underlying transport through which a local-node client has already established an endpoint-to-endpoint connection with a remote-node peer or to which that client previously made a listen request in anticipation of establishing such a connection.
The client previously made a successful request, set up with TdiBuildAssociateAddress, to the transport to set up an association between this connection endpoint and a local-node address. In addition, the client previously did one of the following:
An explicit time-out must be specified as the negative of the number of
100-nanosecond intervals, relative to the current system time, that its
disconnection attempt is allowed to remain pending before the transport fails
this disconnect request. If this pointer is NULL, the transport uses its own
default time-out interval for disconnecting from any remote node.
A client can make a disconnect request with TDI_DISCONNECT_ABORT at any time
its connection is not idle. For example, such a client might want to cancel a
pending connect or listen request that it made previously. As another example,
a client can force the underlying transport to close an endpoint-to-endpoint
connection by issuing a second disconnect request with TDI_DISCONNECT_ABORT
when its preceding disconnect request with TDI_DISCONNECT_RELEASE remains
pending.
The TDI_DISCONNECT_WAIT flag is not used.
Clients can set only one of the preceding options in a disconnect request. The
transport will fail any attempt to set more than one of these options.
TdiBuildDisconnect sets IRP_MJ_INTERNAL_DEVICE_CONTROL as the MajorFunction and TDI_DISCONNECT as the MinorFunction codes in the transport's I/O stack location of the given IRP. This IRP requests that an already established endpoint-to-endpoint connection with a remote-node peer be broken.
A client also can issue a disconnect request to reject an incoming request to connect that was initiated by a remote-node peer. In this case, the client is responding to a completed TDI_LISTEN request that it made previously with the TDI_QUERY_ACCEPT option selected, or the client is rejecting an offered connection from its ClientEventConnect function. Such a client calls TdiBuildDisconnect either with zero or with TDI_DISCONNECT_ABORT at Flags.
While an established endpoint-to-endpoint connection is being disconnected, the underlying transport driver usually refuses any incoming requests for the connection and stops all activity at the specified connection endpoint. However, that connection endpoint remains valid for reuse by the client when the disconnect operation is done.
Because any disconnection operation takes time to complete, the client can receive additional TSDUs on an established endpoint-to-endpoint connection before its disconnect IRP is fully completed. Therefore, a client can assume that the context it maintains for such a connection remains valid until it is notified of disconnect completion, for example, by a call to the IoCompletion routine it supplied to TdiBuildDisconnect. Disconnect-completion notification implies the cessation of all activity, including receive indications, on the connection.
Unless a client requests a controlled disconnect with TDI_DISCONNECT_RELEASE, the transport completes no outstanding I/O requests on the connection and does not confirm that the remote-node peer has been notified of the disconnection before it returns control from a disconnect request. For such a disconnect request, the underlying transport simply cancels all outstanding requests on the given connection, completes its client's disconnect request, and returns control.
Either client on an established endpoint-to-endpoint connection can request a controlled disconnect if the underlying TDI transports support this. If so, the client that initiates the disconnection operation with a TDI_DISCONNECT request causes both transports to coordinate their operations so the remote-node peer is informed that the connection is closing and both transports complete any pending transfers on the connection before it is broken. In these circumstances, the remote-node client must confirm the disconnect before the underlying transport can return from the initiating (local-node) client's disconnect request.
The following summarizes the sequence of operations for a controlled disconnect:
ClientEventDisconnect, TdiBuildConnect, TdiBuildListen, TdiBuildInternalDeviceControlIrp, TDI_CONNECTION_INFORMATION, TDI_DISCONNECT