ClientPnPBindingChange function
The ClientPnPBindingChange routing is initially called by TDI as a consequence of the client's own call to TdiRegisterPnPHandlers. At system startup, TDI calls ClientPnPBindingChange as a consequence of underlying transports' calls to TdiRegisterDeviceObject, TdiProviderReady, and TdiDeregisterDeviceObject. Subsequent to system startup, TDI calls ClientPnPBindingChange whenever a transport to which the client is bound calls TdiRegisterDeviceObject and TdiDeregisterDeviceObject.
Syntax
VOID ClientPnPBindingChange(
_In_ TDI_PNP_OPCODE PnPOpcode,
_In_ PUNICODE_STRING DeviceName,
_In_ PWSTR MultiSZBindList
);
Parameters
PnPOpcode [in]
Specifies one of the following values:TDI_PNP_OP_ADD
During system startup, this value indicates an established transport-to-NIC binding and a transport-created, named device object registered with TDI to represent the binding to at least one underlying NIC. The ClientPnPBindingChange routine can pass a pointer to the name of the transport's registered device object (available at DeviceName) as a parameter to ZwCreateFile to bind itself to this transport, and subsequently, the client can use the corresponding device object pointer in client-allocated IRPs.Following system startup, a run-time call to ClientPnPBindingChange with TDI_PNP_OP_ADD can occur because the PnP manager notified NDIS that a new NIC was added to the system. NDIS, in turn, notified the lowest driver in the transport stack (or lower edge of the monolithic transport) by calling its ProtocolBindAdapter function so the transport is established a binding to the new NIC and registered a device object for that transport-to-NIC binding with TDI.
TDI_PNP_OP_DEL
This value indicates that a transport to which the client is bound has just deregistered and deleted a device object for an established binding to an underlying NIC.This call to ClientPnPBindingChange can occur because the PnP manager notified NDIS that a NIC was removed from the system. NDIS, in turn, notified the lowest driver in the transport stack (or lower edge of the monolithic transport) by calling its ProtocolUnbindAdapter function so the transport is tearing down its binding to the NIC.
TDI_PNP_OP_PROVIDERREADY
During system startup, this value indicates that a particular transport is ready to carry out network I/O operations on its established binding(s).This occurs when an initializing transport calls TdiProviderReady. The buffer at DeviceName specifies the generic name of this transport, which the transport previously supplied when it called TdiRegisterProvider.
Such a transport has already done the following:
Established one or more bindings to appropriate NICs in the machine and created named device objects to represent each of its transport-to-NIC bindings.
Registered its named device object(s) with TDI, thereby causing one or more calls to ClientPnPBindingChange with the PnPOpcode TDI_PNP_OP_ADD.
Registered any network addresses known to the transport on those bindings with TDI, thereby causing one or more calls to the client's just registered ClientPnPAddNetAddress routine.
Set up whatever internal state the transport uses to track network I/O through its transport-to-NIC binding(s).
Received a NET_PNP_EVENT notification from NDIS of type NetEventBindsComplete in a call to the ProtocolPnPEvent function of the (monolithic) transport driver or of the lowest driver in the (multidriver) transport stack, which forwards this PnP-event notification up to the TDI transport driver at the top.
The transport's call to TdiProviderReady indicates that this transport has attempted to established bindings to one or more NICs, as configured in the registry of the current machine, has succeeded in establishing at least one such transport-to-NIC binding, and has succeeded in initializing itself to a state of readiness to carry out network I/O operations on its established binding(s).
A client bound to this transport could now make a network I/O request of this transport, or it can set up any additional transport-specific state it will need for tracking run-time network I/O and defer its initial network I/O request until ClientPnPBindingChange is called again with PnPOpcode TDI_PNP_NETREADY.
TDI_PNP_OP_NETREADY
During system startup, this value indicates that all transport-to-NIC bindings configured on the current computer are ready to carry out network I/O operations for potential clients.This occurs when all the transports have registered themselves with TDI by calling TdiProviderReady. The DeviceName and BindingList pointers are NULL when ClientPnPBindingChange is called.
Clients usually wait for this notification to make their initial network I/O requests, thereby avoiding potential conflict for CPU cycles with the system network setup code. For example, any client that binds itself to more than one transport during system startup has a choice of transports available sooner if it defers its initial network I/O request until ClientPnPBindingChange is called with TDI_PNP_OP_NETREADY.
DeviceName [in]
Pointer to a buffered Unicode string that is usually the name of the transport-created device object either representing the transport in general as the target for its clients' network I/O or representing the target for its clients' network I/O through a particular transport-to-NIC binding. Depending on the given PnPOpcode, this input parameter can be one of the following:A pointer to buffered Unicode string that is the transport's generic name, such as "\device\nwlinkipx," for the PnPOpcode TDI_PNP_OP_PROVIDERREADY
A pointer to a buffered Unicode string that is the name of a particular interface, such as "\device\tcpip_{ interfaceGUID}" if the transport supports more than one device interface but creates a single device object
(In this case, the name of the device object actually opened by a client would omit the "_{ interfaceGUID}" suffix.)
NULL for the PnPOpcode TDI_PNP_OP_NETREADY
MultiSZBindList [in]
Subsequent to system startup, points to a buffered binding-order list if PnPOpcode is TDI_PNP_OP_ADD or TDI_PNP_OP_DEL. Otherwise, this parameter is NULL.
Return value
None
Remarks
At system setup, a client must register its ClientPnPBindingChange routine with a call to TdiRegisterPnPHandlers to initialize whatever state the client maintains about its binding(s) to particular transport(s). A successful call to TdiRegisterPnPHandlers causes a sequence of calls to ClientPnPBindingChange to occur, as follows:
TDI calls ClientPnpBindingChange zero or more times with the PnPOpcode TDI_PNP_OP_ADD, passing in the buffered name of a transport-created device object, identified at DeviceName, that is already registered with TDI for an established transport-to-NIC binding. At each such call, ClientPnPBindingChange determines whether to bind itself to this transport, either calling ZwCreateFile or rejecting the binding offer by promptly returning control to TDI.
TDI calls ClientPnPBindingChange zero or more times with the PnPOpcode TDI_PNP_OP_PROVIDERREADY, passing in the buffered name of a registered transport that has already declared its readiness to perform network I/O operations on at least one established transport-to-NIC binding at DeviceName. Each such transport has already called TdiProviderReady because it is done with its initialization and binding-time operations.
TDI continues to call ClientPnPBinding change as already described during system startup whenever subsequently initialized transports, if any, call TdiRegisterDeviceObject and TdiProviderReady.
TDI makes one more system-startup-time call to ClientPnPBinding change with the PnPOpcode TDI_PNP_OP_NETREADY when the last registered TDI transport driver configured in the current computer calls TdiProviderReady. At this stage of system startup, the client usually begins its initial network I/O operations, such as contacting a DC to log on to the network.
Subsequently, TDI notifies the client when a transport to which it is bound creates a new binding or tears down an established binding. The ClientPnPPowerChange handler also is called if a user-initiated network connection or disconnection causes a binding change.
After system startup, ClientPnPBindingChange is called to add or delete a binding only for a transport to which it is bound. When ClientPnPBindingChange is called with a binding offer, the transport has already created the device object identified at DeviceName before it called TdiRegisterDeviceObject. When ClientPnPBindingChange is called to delete an existing binding, the transport will destroy the device object identified at DeviceName as soon as TdiDeregisterDeviceObject returns control to the transport.
Consequently, when ClientPnPBindingChange is called to add a binding, it can allocate per-binding resources, initialize the client's per-binding state, and call ZwCreateFile to bind itself to the new transport-to-NIC stack. The client also can call ZwCreateFile again with any of the network addresses that the transport registers with TDI on the newly established binding as soon as its ClientPnpAddNetAddress routine is called.
Conversely, when ClientPnPBindingChange is called to delete a binding, it must begin the unbinding process and release any per-binding resources that the client allocated. The client can assume that its ClientPnPDelNetAddress routine has been called one or more times because the transport deregisters its addresses when tearing down a binding before it calls TdiDeregisterDeviceObject. However, ClientPnPBindingChange must make a reciprocal call to ZwClose with the handle to the device object that it obtained from ZwCreateFile.
In either case, the information at MultiSZBindList reflects the new binding order for the client when a binding is added or deleted at run time.
For more information, see ZwCreateFile and ZwClose.
A reciprocal call to TdiDeregisterPnPHandlers disables subsequent calls to ClientPnPBindingChange.
TDI calls ClientPnPBindingChange at IRQL < DISPATCH_LEVEL.
Note The TDI feature is deprecated and will be removed in future versions of Microsoft Windows. Depending on how you use TDI, use either the Winsock Kernel (WSK) or Windows Filtering Platform (WFP). For more information about WFP and WSK, see Windows Filtering Platform and Winsock Kernel. For a Windows Core Networking blog entry about WSK and TDI, see Introduction to Winsock Kernel (WSK).
Requirements
Target platform |
Desktop |
Header |
Tdikrnl.h (include TdiKrnl.h) |
IRQL |
< DISPATCH_LEVEL (see Remarks section) |
See also