When i try to remove my NDIS LWF using netcfg -u
, i notice that it doesn't remove it from the driver store (can be seen with pnputil /enum-drivers
).
This is causing problem because on some Windows 10 machines, if we uninstall the previous version of our NDIS LWF and install the new one using netcfg
, for some unknown reason the old inf is still used to install it! And i assume its because the inf still has the same componentID? We are updating the INF file in order to attach to some virtual adapters that we previously couldn't attach. Note that this doesn't happen in Windows 7, and we can install the new one without any problem.
So my questions are:
Why is Windows still using the previous INF from driver store when we try to install the new updated driver that has a different INF?
What is the proper way to fully remove the previous NDIS LWF, including from driver store? If we need to use
pnputil
to fully remove it from driver store, then what is the proper way of finding the OEM number, considering thatpnputil -d
requires an OEM number?
CodePudding user response:
Right, as you've noticed, netcfg.exe -i
is not the exact opposite of netcfg.exe -u
.
Installation does these steps:
Install the INF you provided with
-l
to the driver store (SetupCopyOEMInf
)Call
INetCfgClassSetup::Install
to:- Query PNP for the "best match" for the componentId you provided with
-i
(SetupDiBuildDriverInfoList
,SetupDiSelectBestCompatDrv
) - Run all the sections in the INF (
AddReg
,AddService
, etc) - Register a LWF/Protocol/TDI driver with the system using info in the
Ndi
registry key
- Query PNP for the "best match" for the componentId you provided with
Uninstall does these steps:
- Call
INetCfgComponent::DeInstall
to:- Deregister your LWF/Protocol/TDI driver with the system
- Run the special
.Remove
section of the INF (which, hopefully, contains aDelReg
,DelService
to undo everything done during install step #2.2)
(The descriptions above ignore the driver refcount system (aka OBO_TOKEN
), since it isn't often used — most drivers just use a single refcount. If you exclusively use netcfg.exe
to manage your driver, then you too can ignore refcounts.)
You might be wondering: why is this so very less-than-awesome? The backstory here is that netcfg.exe
was never really meant to be a general-purpose tool for 3rd party software to manage their drivers. It was only meant to be used internally, for the drivers that are built into the OS (ms_tcpip
etc). The assumption was that 3rd party driver installers would want to call proper APIs like INetCfg
, not CreateProcess
some executable and screen-scrape the output. So netcfg.exe
was only built up to be the minimum needed for our internal needs. In particular, very little attention was paid to uninstall, since built-in drivers are rarely uninstalled. (Likewise, argument parsing is inflexible, the help text is not helpful, and the error handling is not robust.)
Starting in Windows 10, built-in drivers are no longer installed using netcfg.exe
, so the OS itself doesn't need netcfg.exe
at all anymore. But by then, 3rd party products had discovered it and taken a dependency on it, so we couldn't just remove netcfg.exe
anymore. Ah well.
Why is Windows still using the previous INF from driver store when we try to install the new updated driver that has a different INF?
This is a common gotcha. Note that, during install, steps #1 and #2 have no association between them. You could install a printer INF and a LWF at the same time — netcfg.exe -l foo.inf -i bar
makes no effort whatsoever to ensure that the "best" component selected in step #2.2 actually came from the INF installed in step #1.
In order to ensure that the driver you want is the "best" driver, you have to ensure that your favored driver wins the PNP driver selection algorithm. I've personally been bitten by this because I didn't bump the DriverVer
line during development iterations. Make sure you increment DriverVer
every time you change the driver.
What is the proper way to fully remove the previous NDIS LWF, including from driver store? If we need to use pnputil to fully remove it from driver store, then what is the proper way of finding the OEM number, considering that pnputil -d requires an OEM number?
Honestly, if you want to do everything really correctly, I suggest avoiding netcfg.exe
entirely. Use the underlying INetCfg
APIs instead. Then your installer will have to manage the driver (SetupCopyOEMInf
/ SetupUninstallOEMInf
).
You aren't losing much by ditching netcfg.exe
and calling INetCfg
yourself. netcfg.exe
doesn't do anything particularly fancy with INetCfg
: its own implementation is nearly exactly taken from this sample code. If you start with that and slap a call to SetupCopyOEMInf
on top, you'll pretty much be at parity with netcfg.exe
already. From there, you can improve it with more robust INF uninstall. You can even write some code to inventory all the INFs with your componentId, to make sure there aren't stale copies of your INF hiding around.
You still have to make that leap of trust from installing an INF to hoping that INetCfgClassSetup::Install
thinks your recently-installed INF is the "best" INF. But if you've removed every other INF with that componentId, then you can be certain that the sole remaining INF must be the best match.