Figure 5.4 shows how a TDI client can make queries about the features of its underlying transport or request its underlying transport to set its state data to client-specified values.
Figure 5.4 Setting and Querying Information in the Transport
A TDI client can query certain transport driver information, such as connection-status information, activity on a particular transport address, transport-specific limits on datagram size and number, driver statistics, and internal send/receive buffer sizes if the transport buffers data internally. A client also can set some state information in the underlying transport, although it cannot override the underlying transport-determined values for certain size limits by issuing set-information requests.
If a client wants to query information concerning an open transport address or a connection endpoint, it submits a TDI_QUERY_INFORMATION request, set up with TdiBuildQueryInformation, to the underlying transport. When it uses this macro, the client passes pointers to the file object that represents the address or connection endpoint and to a client-supplied buffer in which the transport returns the requested information.
To set transport information, the client issues a TDI_SET_INFORMATION request, set up with TdiBuildSetInformation.
For each of these operations, the client also passes a system-defined TDI_QUERY_XXX value as the QType or SType parameter to the TdiBuild..Information macros to discriminate among the types of information that can be queried and set.
To query or set information that does not specifically concern an address or a connection endpoint, a client first must open a control channel in the TDI driver before submitting its query/set-information request(s). For example, a client querying information about the underlying transport's broadcast address for connectionless-data transmission or the transport's current statistics uses a control channel.
To open a control channel, the client calls ZwCreateFile with a NULL EaBuffer pointer. The client's call to ZwCreateFile causes the I/O Manager to create a client-process-specific file object to represent the control channel and to call its underlying transport’s TdiDispatchCreate routine with an IRP containing the client-supplied parameters to ZwCreateFile. TdiDispatchCreate notes the absence of EA information, and the transport sets up internal state for the open control channel and for this client if the call succeeds.
As an alternative for opening a file object that represents a control channel, the client can call IoGetDeviceObjectPointer, which returns pointers to the named device object and corresponding file object.
After ZwCreateFile returns a file handle to the client and the client has obtained a pointer to the file object with ObReferenceObjectByHandle, it is ready to make certain types of TDI_QUERY_INFORMATION or TDI_QUERY_SET_INFORMATION IOCTL requests to its underlying transport.
When its query- and/or set-information operations are complete, the client must close the open control channel by passing the file handle that was returned by ZwCreateFile to ZwClose or passing the file object pointer that was returned by IoGetDeviceObjectPointer to ObDereferenceObject, as described later in Section 5.13.