The Windows networking subsystem is composed of a set of kernel-mode drivers, a set of user-mode
services and DLLs, and their configuration data stored in the registry. Most of this document
is devoted to understanding the registry-based configuration details.
NDIS is primarily implemented via callback functions. There is a main subsystem driver (ndis.sys), which sets
up the framework for packet handling, and there are drivers that are basically just libraries of callbacks that
the NDIS system calls when certain things happen.
The NDIS subsystem takes care of much of what network drivers used to have to do. For example, ndis.sys provides
the ISR for all incoming packets. It also provides commonly-used data structures such as packets, and takes care
of driver-to-driver communication across a well-defined interface.
There are several kinds of NDIS drivers:
Again, NDIS IM drivers are an exception. Instead of RootDevice just having the instance GUID in the
MULTI_SZ array, it actually has that GIUD plus the GUID of one other miniport, in that order. I think
that's the way a filter driver associates itself with the next object down in the stack. Because there
is one instance of the IM for each underlying Miniport to be filtered, this mechanism winds up filtering
all existing Miniports.
One exception to this case is with NDIS Intermediate drivers. They do not have an Ndi key.
When it exists, the Ndi key has one subkey, Interfaces. The Interfaces key has two values: UpperRange
and LowerRange. These are binding class names that the given component can bind to on its upper and
lower edges. These can be Microsoft-specified or made up by the programmer to force private binding.
There doesn't seem to be a place that these values are defined, so it looks like they are called into
existence by .inf files.
I've also seen additional keys, like 'params', under Ndi, but I think they're just driver-defined parameters
and such, and are specific to the driver as provided by the manufacturer.
The adapter keys have no values and one sub-key each, Connection. Here we find the PnPInstanceId value, set to the
Plug-n-Play ID of the device, as well as Name, which is the display name for Network Control Panel and Device
Manager. Sometimes (real lan adapters usually?) there is a ShowIcon value also, which seems to always be set
to 1.
The Descriptions key has a value for the display name of each of the miniports. The data seems to always be
set to 1, except in the case of an NDIS IM driver, in which case it's set to 1 2 3 ..., presumably allowing
the GUI to figure out how to decorate the names of the miniports in device manager.
Each client guid has a subkey Ndi. The Ndi key has ClsId, which is looks like it's an Instance GUID, CoServices,
which appears to be the list of services the Ndi installs with the component, Service, which is the Win2k
service name. The Ndi key has one subkey, Interfaces, which again defines binding relationships. The MS
client's LowerRange value of netbios,netbios_smb means it can bind to any netbios or netbios_smb drivers
below it. Its UpperRange of winnet5, which is also the upperRange for a few NetService. That word doesn't
appear anywhere else in the registry, though, so I wonder if it would still work if it were noupper or something.
Another option concerning the ClsId key: this might be the class Id of the interface object for the device manager.
Filter drivers have more than this. Because filter drivers are two-part[1], the service appears here. The
NDI key, in addition to the other stuff it has, lists FilterClass, FilterDeviceInfFile, FilterDeviceInfId,
and HelpText. The Interfaces key lists noupper and nolower as filter types, but it also has a FilteredMediaTypes
value populated by the INF. Posfire has Ethernet,tokenring,fddi,wan as the value data here.
The Ndi key has the standard stuff - ClsId, HelpText, Service, etc. The Interfaces subkey of the Ndi key contains
the same old, mostly confusing, bindings stuff. There is occasionally a linkage key, with Bind, Export, and Route,
in similar style as the miniport information above. In particular, this happens with Netbios_Smb.
All of these keys have the standard windows service stuff - start type, path, etc. They also all have an enum subkey
that holds the PnP ID and location on the enumeration tree of the device(s) in question.
In addition, NetBT has a parameters key that is structured similarly to TCPIP's. Global parameters such as
timeouts, etc., are in the Parameters key, and interface-specific parameters are set in one of the interface
subkeys under parameters. The interfaces are of the form Tcpip_{GUID}, and correspond to the TCPIP interfaces.
Adapters - has no values of its own but lists the two targets specified in the bind value above: the
device object of the physical NIC and NdisWanIP. The NIC entry has two values: an IpConfig value with data set
to TCPIP\PARAMETERS\{adapter's GUID} and an LLInterface value with empty data. The NDISWANIP key has four values:
IpConfig, set to TCPIP\PARAMETERS\{the two mysterious GUIDs}; IpInterfaces, set to some apparently meaningless
binary data; LLInterface with data WANARP, and NumInterfaces set to 2.
DNSRegisteredAdapters - this key is empty on both test boxes.
Interfaces - this subkey has a GUID for each interface enumerated by the Adapters key, including the ones identified
by NdisWanIp. Inside each subkey are interface-specific tcp/ip configuration parameters.
PersistentRoutes - has a value name for each route saved as a persistent route
Winsock - has some winsock-specific config parameters including a big old binary value that I don't understand.
As can be imagined, INFs are very flexible, but they're not very well documented. The best source of documentation of
the INF format is in the DDK (with overlapping but slightly different info in Win9x and WinNt versions). The platform
SDK also has some INF-related info. Beyond that, the best references are sample INFs provided in the DDK and third-party
INFs from other vendors.
Drivers
There are lots of drivers that make up the networking subsystem. In general, they are divided into two classes:
These drivers are all kernel-mode .sys files that communicate with one another via either callback functions or IRPs.
Like all drivers, they have entries in the Service Control Manager (SCM) database found at
HKLM\System\CurrentControlSet\Services in the registry. Most of the driver files themselves are located in the standard
place, %SystemRoot%\System32\Drivers.
NDIS
NDIS (Network Device Interface Specification). The NDIS subsystem forms most of the nuts and bolts of the
networking on the computer. NDIS is responsible for getting packets from hardware up to TDI drivers for handing
to apps. It's big and complicated.
These components associate themselves with one another via "binding". The binding process informs the NDIS
framework about the order in which packets are to be passed from one driver to the next.
The Registry
All NDIS configuration is contained in the registry. The data is contained in several places:
INF files
All of the madness that we just went through in the registry happened because INF files told it to. In particular,
network INF files are interpreted in combination between the Network Device Installer and Device Manager. Device
Manager does the generic stuff like PnP identification and driver selection, and it looks like it also handles the basics
of file copying, service creation, registry modifications, etc. Then, at some point after Device Manager is done, the
Network Device Installer is invoked and takes another pass through the system at configuration of the network components.
Here, bindings are processed and components are logically linked together to form the networking subsystem.
Reference
GUIDs
[1] NDIS Intermediate drivers are one binary with two parts. The "lower edge" looks like a protocol (like TCP/IP
or something). The "upper edge" looks like a miniport. This binary is installed with a pair of INFs. The
weird part is that one INF is a NetService INF and the other is a Net inf. The NetService is the one that
gets fed to the network control panel since the Net component is hidden by its INF. However, there is not
an entry in the NetService GIUD. Marking the driver as filter does weird things to the NDI.