TdiBuildDisconnect

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.

Parameters

Irp
Points to a client-supplied IRP, either originating in a higher level network component or allocated with TdiBuildInternalDeviceControlIrp.
DevObj
Points to the device object created by the next lower TDI transport driver.
FileObj
Points to a file object representing the connection endpoint.

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:

  • Made a successful request, set up with TdiBuildConnect, to establish an endpoint-to-endpoint connection with a remote-node peer

  • Accepted this connection offer from its remote-node peer, which initiated the TDI_CONNECT request

  • Submitted a successful request, set up with TdiBuildListen, that has just been satisfied by a connection offer from a remote-node peer
CompRoutine
Specifies the entry point of a client-supplied IoCompletion routine or NULL. The I/O Manager calls this routine when the given IRP is completed, unless the client sets this parameter to NULL.
Contxt
Points to a client-determined context. This client-supplied pointer is passed in to the IoCompletion routine when it is called with the completed IRP. Contxt should be NULL if CompRoutine is NULL.
Time
Points to a variable specifying a system-relative time-out interval that the transport is to use for the disconnection attempt, or this parameter can be NULL.

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.

Flags
Points to a variable that is either zero or, if the underlying transport supports controlled disconnects, to one of the following:
TDI_DISCONNECT_ABORT
Specifies that the underlying transport should close the connection immediately without attempting to complete any pending requests. This value is the default, equivalent to setting Flags to zero.

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.

TDI_DISCONNECT_RELEASE
Specifies that the underlying transport should initiate a controlled disconnect, as described later (see Comments). The remote-node client also issues a disconnect request with this value to confirm a controlled disconnect.

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.

RequestConnectionInfo
Points to a client-supplied buffer containing a TDI_CONNECTION_INFORMATION structure, possibly containing disconnection data if the client sends any when initiating an endpoint-to-endpoint controlled disconnection. This parameter should be NULL unless the caller initiated a disconnection with TDI_DISCONNECT_RELEASE.
ReturnConnectionInfo
Points to a caller-supplied buffer, also formatted as TDI_CONNECTION_INFORMATION structure, in which the transport returns any disconnect data it received from the remote node, assuming the remote-node client initiated a controlled disconnection. This parameter should be NULL unless the caller is acknowledging a disconnection with TDI_DISCONNECT_RELEASE. The local-node client cannot retrieve any returned disconnect data after it reuses the connection in a request set up with TdiBuildListen or TdiBuildConnect.

Comments

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:

  1. The local-node client initiates a disconnection by making a disconnect request in which TDI_DISCONNECT_RELEASE was set at Flags. Subsequently, this client can no longer send data on the connection, but it can continue to receive data from its remote-node peer. The underlying transport carries out any pending send operations and completes the pending send requests it is currently holding when such a local-node client makes its disconnect request.

  2. The transport on the remote node completes any pending receive requests its client has made. Then, the remote-node transport notifies its client of the pending disconnect, either by calling ClientEventDisconnect if the remote-node client has registered this event handler or by returning an error code on an outstanding request made by its client. After such a notification, the remote-node client can no longer receive data on the connection, but it can continue to send data until it submits disconnect request with the TDI_DISCONNECT_RELEASE option to the underlying transport.

  3. When the remote-node client has finished sending data, it makes a disconnect request to its underlying transport with the TDI_DISCONNECT_RELEASE option selected. The underlying transport completes all outstanding sends on the connection normally before completing its client's disconnect request. When this transport returns from the disconnect, the connection has been closed from the point of view of its remote-node client. However, the connection endpoint is still valid and that client can reuse it later.

  4. The remote-node transport notifies the local-node transport to confirm disconnect-completion at the remote node. At this point, the original controlled disconnect request is completed by the local-node transport and the connection has been closed from the point of view of the local-node client. However, the connection endpoint is still valid and that client can reuse it later.

See Also

ClientEventDisconnect, TdiBuildConnect, TdiBuildListen, TdiBuildInternalDeviceControlIrp, TDI_CONNECTION_INFORMATION, TDI_DISCONNECT