Q&A on Windows 2000 NDISWAN and NDIS Intermediate Drivers issues from Robert Schlabbach (robert@powerstation.isdn.cs.TU-Berlin.DE):
December 17, 1999

 
 
Q: Why does my NDISWAN miniport crash when compiling it as an NDIS 5.0 miniport?
 
A: Windows 2000 doesn't support NDISWAN miniports in NDIS 5.0 - it blindly assumes that your miniport must be a CoNDISWAN miniport, and calls one of the Co* functions, which are typically initialized to NULL pointers, thus the crash. Either stick with NDIS 4.0, or change your NDISWAN miniport to a CoNDISWAN miniport. Note that intermediate drivers cannot have a connection-oriented upper edge in Windows 2000, thus writing an intermediate driver with NDISWAN interface at its upper edge is not possible in NDIS 5.0, you need to stick to NDIS 4.0.
 
 
Q: What are NDIS "filter" drivers and how to they relate to NDIS intermediate drivers?
 
A: An NDIS filter driver is a special case of an NDIS intermediate driver. A filter driver binds the adapter below it _exclusively_, exposes exactly _one_ virtual adapter per bound adapter, which has the same upper edge as the adapter below it. In contrast to general NDIS intermediate drivers, filter drivers offer builtin installation support for the virtual adapters, which is documented in the DDK. Non-filter intermediate drivers require a Notify Object for installation (see next question).
 
 
Q: How do I install an NDIS intermediate driver in Windows 2000?
 
A: An NDIS intermediate driver consists of two parts: A protocol portion and a miniport portion, which exposes the virtual adapter(s). You need two INF files, one for each portion. The user will install using the protocol INF. This INF must a) include the copy operation of the miniport INF and b) specify a Notify Object (see next question). You should use the ExcludeFromSelect directive in your miniport INF so that the user can't install it by accident. The PASSTHRU sample in the Windows 2000 DDK contains two samples INFs that explain how to do this.
 
 
Q: Do I need a Notify Object to install my NDIS intermediate driver in Windows 2000?
 
A: Unfortunately, you do (unless your IM happens to be the special case of a "filter" driver, see above). The reason is that you'll have to call NdisIMInitializeDeviceInstance() at some point in your ProtocolBindAdapter() function - and you need the device name of the instance of the miniport portion installed for that adapter. The protocol can't find this out by itself - that's where the Notify Object comes into play. It must install the miniport, retrieve its device instance name and put it in the protocol's parameters registry subkey, so that the protocol can retrieve the required information from there. The builtin filter support puts this information in the registry in your protocol's parameters key under Parameters\Adapters\<Adapter GUID> as value "UpperBindings" of type REG_SZ. When you call NdisOpenProtocolConfiguration(), it'll try to open this key, so you best put your data in the same place.
 
 
Q: What do I have to do in my NDIS intermediate driver's Notify Object?
 
A: Basically, you need to write a Notify Object that installs and removes instances of the miniport portion in its NotifyBindingPath() member function, retrieve the installed miniport's BindName, prefix it with "\Device\", and write it to the protocol's parameters subkey in the location mentioned above. The <Adapter GUID> subkey name is the BindName of the adapter you're binding to. Doing the installation and removal in NotifyBindingPath() has one drawback, though: The miniport instances will be _immediately_ installed and removed when the user checks/unchecks the protocol in the NIC's connection properties, cancellation isn't possible. The "right" path would be to defer all the installation and removal operations until ApplyRegistryChanges() is called - but this path is blocked by Microsoft: A "reentrancy" check disables these operations at that point (apparently Microsoft thinks developers are too stupid to realize that these operations might lead to their ApplyRegistryChanges() function to be called again, which could lead to endless installation loops if the developer doesn't take care of this by setting a flag and exiting immediately when the flag is set...). If anyone knows of a better solution, I'd love to hear it! To get started on writing the Notify Object, see the "SFilter" sample in the Windows 2000 DDK (found under ddk\src\network\config\filter).
 
 
Q: What flaws does Microsoft's "SFilter" sample Notify Object have? How do I remedy them?
 
A: First off, the sample clutters up the registry with its typelib, which it never removes. The typelib is unnecessary anyway. Just get rid off the .RGS and .IDL files and kill the typelib resource from the .RC file. Use the DECLARE_REGISTRY() macro in your class definition instead of DECLARE_REGISTRY_RESOURCEID(), and remove the TRUE arg from the _Module.RegisterServer() call in DllRegisterServer(). Second, the DLL is not unloaded after the Notify Object is uninstalled. Actually, it's "cached" for 10 minutes after uninstallation, but you can rid of that delay: Change the threading model (now in your DECLARE_REGISTRY() macro) from both to "THREADFLAGS_APARTMENT" and call CoFreeUnusedLibraries() in your DllUnregisterServer() function prior to exiting. That way, the DLL will be unloaded right after uninstallation, but unfortunately still not in time for a DelFiles directive in your INF to remove it (Microsoft is aware of this problem and concluded that they'll have to fix their binding engine for this to work).
 
 
*EOF*