Home > OS >  Using netcfg to remove an NDIS LWF doesn't remove it from the driver store?
Using netcfg to remove an NDIS LWF doesn't remove it from the driver store?

Time:05-06

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:

  1. 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?

  2. 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?

CodePudding user response:

Right, as you've noticed, netcfg.exe -i is not the exact opposite of netcfg.exe -u.

Installation does these steps:

  1. Install the INF you provided with -l to the driver store (SetupCopyOEMInf)

  2. Call INetCfgClassSetup::Install to:

    1. Query PNP for the "best match" for the componentId you provided with -i (SetupDiBuildDriverInfoList, SetupDiSelectBestCompatDrv)
    2. Run all the sections in the INF (AddReg, AddService, etc)
    3. Register a LWF/Protocol/TDI driver with the system using info in the Ndi registry key

Uninstall does these steps:

  1. Call INetCfgComponent::DeInstall to:
    1. Deregister your LWF/Protocol/TDI driver with the system
    2. Run the special .Remove section of the INF (which, hopefully, contains a DelReg, 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.

  • Related