2.1.2 Opening an Adapter Underlying a Protocol Driver
The protocol driver reads the registry information stored during setup to build a list of names of adapters to which it will bind. The registry contains binding information written when the network is configured. DriverEntry reads this information, including the names of the adapter or adapters to which it can bind, from the HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet
\Services\ProtocolComponentName\Linkage key in the registry.
A protocol driver calls NdisOpenProtocolConfiguration to obtain a handle to the registry key at HKEY_LOCAL_MACHINE\SYSTEM
\CurrentControlSet\Services\DeviceInstance\Parameters\ProtocolName, where the protocol driver can store adapter-specific information. A protocol driver that stores adapter-specific information in the registry must store it under this key and use NDIS functions to access the information. Once a handle to this key is obtained, a protocol driver calls the NdisRead/WriteConfiguration functions to read and write such information. The NdisRead/WriteConfiguration functions are described in the Network Driver Reference.
If a protocol driver provides a ProtocolBindAdapter function, the SystemSpecific1 parameter passed to this function is passed uninterpreted to NdisOpenProtocolConfiguration at ProtocolSection. If a protocol driver does not provide a ProtocolBindAdapter function, the driver is assumed to know both the name of the adapter it is opening and the string value to be passed at ProtocolSection.
After a protocol driver has retrieved the information it requires from the registry and has registered by calling NdisRegisterProtocol, and before the protocol driver can send packets and receive incoming data, it must bind itself to one or more underlying NICs managed by a miniport or an intermediate NDIS driver. The protocol binds itself to an underlying NIC and the miniport that controls it by calling NdisOpenAdapter, declared as follows:
VOID
NdisOpenAdapter(
OUT PNDIS_STATUS Status,
OUT PNDIS_STATUS OpenErrorStatus,
OUT PNDIS_HANDLE NdisBindingHandle,
OUT PUINT SelectedMediumIndex,
IN PNDIS_MEDIUM MediumArray,
IN UINT MediumArraySize,
IN NDIS_HANDLE NdisProtocolHandle,
IN NDIS_HANDLE ProtocolBindingContext,
IN PNDIS_STRING AdapterName,
IN UINT OpenOptions,
IN PSTRING AddressingInformation
);
A protocol driver passes a handle at ProtocolBindingContext to an adapter-specific context area that it allocated to store state information for the binding. NDIS will return this handle to the protocol driver in subsequent calls pertaining to the binding, for instance, in calls to ProtocolReceive or ProtocolStatus. NDIS returns a handle at NdisBindingHandle to the protocol driver. This handle must be retained by the protocol, usually in its adapter-specific context area. The protocol driver must pass this handle to NDIS in future calls relating to this binding, such as calls to NdisSend or NdisSendPackets.
The protocol driver passes the name of the adapter that it has read from the registry or that was input to the ProtocolBindAdapter function at DeviceName to NdisOpenAdapter at AdapterName. It passes the type(s) of medium(s) it supports at MediumArray. If the call to NdisOpenAdapter succeeds, the underlying NIC driver will select a medium from MediumArray and return its index at SelectedMediumIndex. The value at NdisProtocolHandle is the value returned to the protocol driver from a successful call to NdisRegisterProtocol.
If a protocol driver cannot successfully bind to an underlying adapter, it deallocates any resources it previously allocated for that adapter. If the protocol driver cannot successfully open any of the possible adapters, it should deallocate any global resources the protocol has previously allocated and return an appropriate failure status. In this case, the protocol driver will subsequently be unloaded. Typically, its DriverEntry or ProtocolBindAdapter function should log failed binding attempts with appropriate descriptive information, either by calling NdisWriteErrorLogEntry or an OS-specific support routine, such as IoWriteErrorLogEntry.