I'm doing a bit of driver programming and I have a PNP driver for a pseudo-device that has it's own custom device setup class. The driver is a pseudo-bus enumerator and creates pseudo devices, not unlike the toaster example.
Anyways, I have a whole lot of old, unneeded entries in HKLM\SYSTEM\CurrentControlSet\Enum now. Is there some nice utility for removing old device enumerations in there? I don't seem to be able to do it with devcon or pnputil. I can delete it manually, but that's really tedious given that only SYSTEM has full control privileges over much of what's in Enum.
The reason that devcon remove isn't working is because devcon hardcodes the DIGCF_PRESENT flag, and your old unneeded devices are not currently present. As the devcon source code is publicly available, you can compile your own version that removes the flag.
Hint: start looking in the cmdRemove function.
Related
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 that pnputil -d requires an OEM number?
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
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 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.
Summary
I'm developing an installer for an application that involves installing a USB device based on WinUSB. Everything works except for an annoying issue in which the USB device shows up in the notification pane after installation with the option to safely remove it:
I don't want this option to appear but I'm not sure how to go about preventing it. I believe it should be possible by adding the right directives to the INF file for the device, but Microsoft have done a fantastic job making the INF file format stupidly overcomplicated and I'm having trouble figuring out exactly what to do from the docs.
What I've Tried
The Microsoft docs really aren't helpful enough, but I managed to find an old document called Designing Hardware For Surprise Removal Under Windows XP that seemed promising:
Based on this I tried adding the following content to my INF file:
[USB_Install.HW]
...
AddReg=Dev_AddReg_HW_Removal_Policy
[Dev_AddReg_HW_Removal_Policy]
HKR,,"RemovalPolicy",0x00010001,2
After installing this driver, I went to device manager and was able to confirm that the "Removal policy" property was set to 00000002 (it was 00000003 before). However, the device still showed up with an "Eject" option.
My next attempt was with "Safe removal required", which is currently set to <true>. I had a stab at including the directive for this in my INF file:
[USB_Install.HW]
...
AddReg=Dev_AddReg_HW_Removal_Policy
AddReg=Dev_AddReg_HW_Safe_Removal_Required
[Dev_AddReg_HW_Removal_Policy]
HKR,,"RemovalPolicy",0x00010001,2
[Dev_AddReg_HW_Safe_Removal_Required]
HKR,,"SafeRemovalRequired",0x00010001,0
I used infverif to confirm my INF file was valid, but after installing this version of the driver the "Safe removal required" property is still set to <true> and the device still features an eject option.
Is anyone familiar enough with the convoluted (and quite frankly retarded) INF format to suggest what I need to change to make the "Eject" option disappear?
On our 1200 windows clients we are using KES 10 antivirus.
By error on some desktop workstation we installed the firewall component "klim6".
We need a silent uninstall. Not found within Kaspersky tools.
Which is the working and proper way ?
RUNDLL32.EXE SETUPAPI.DLL,InstallHinfSection DefaultUninstall 132 KES10.inf
NETCFG.EXE -v -u KLIM6
devcon.exe remove =net *klim6*
We need also the explanation of the different behaviour of these tools.
UPDATE : info from the INF file :
; KLIM6.INF -- NDIS Usermode I/O Driver
[version]
Class = NetService
DriverPackageType=Network
[Manufacturer]
%Klft%=KLFT,NTx86,NTia64,NTamd64
As you've noted, there are a variety of tools to work with .INF files. The reason is that there are different flavors of .INF, used for different purposes.
I don't know if there's any official terminology, but here's the terminology that I use:
DefaultInstall-style INFs. Use "rundll32.exe SetupApi.dll,InstallHinfSection" to work with these. You can identify this style of INF because they have "[DefaultInstall]" in them.
PNP-style INFs. Use pnputil.exe (built-in, so more convenient) or devcon.exe (more powerful) to work with these. You can identify PNP-style INFs because they have a "[Manufacturer]" section, and they are not NetCfg-style INFs.
NetCfg-style INFs. Use NetCfg.exe to work with these. You can identify NetCfg-style INFs by the line Class=NETTRANS or Class=NETSERVICE or Class=NETCLIENT. Only those 3 classes are NetCfg-style INFs -- in particular, Class=NET is not a NetCfg-style INF; it is a PNP-style INF.
There are other types of INFs used for Windows Drivers, e.g., storage minifilter-style, or upper/lower-filter style INFs. And other people use INFs for things that have nothing to do with Windows Drivers... so it's a confusing area.
That being said, it's often a mistake to attempt to manually remove a driver. Usually an application's installer will install many 100's of things, only one of which is the driver. If you delete only the driver from an application, you could easily leave dangling bits that damage the system in obvious or subtle ways.
If you really want to do this anyway, you should check the INF file. If it says Class=NET, then use devcon.exe. If it says Class=NETSERVICE, you should use NetCfg.exe.
I also had to remove kaspersky NDIS filter (for different reasons).
The proper way to do this is with netcfg.exe
You need to disabled the Kaspersky's Self-Defense mechanism and exit the product. You can then uninstall it with this command:
C:\Windows\System32\netcfg.exe /v /u kl_klim6
Unfortunatly, I couldn't find an easy way to uninstall the filter in Windows XP but one method is provided Here
Is it possible to take a Windows driver such as a Ports class driver, then have it also set itself up as an NDIS filter (NetService class) driver by calling NdisFRegisterFilterDriver() in it's DriverEntry()? This would be essentially having the driver work double duty as a Ports and NetService class driver, but within a single code base and binary.
I'm attempting to do this and I'm seeing the call to register the NDIS driver fail, specifically with the following trace message:
[0][mp]<==ndisCreateFilterDriverRegistry, FilterServiceName 807EFA18 Status c0000001
[0][mp]==>NdisFRegisterFilterDriver: DriverObject 84C6C428
[0][mp]==>ndisCreateFilterDriverRegistry, FilterServiceName 807EFA18
[0][mp]<==ndisCreateFilterDriverRegistry, FilterServiceName 807EFA18 Status c0000001
I've looked around and it seems that the NDIS driver is heavily dependent on the values placed in the registry from the INF and the INF itself. I've tried to spoof the registry keys by adding the NetCfgInstanceId by hand and calling that value out in my code before trying to register the NDIS filter, but have hit a point where it just seems like the wrong way to go about it.
What is the recommended way to go about this? At this point I'd imagine that this would require a Ports class driver and NetService class driver separately, with some kind of composite driver to tie them together to be able to communicate, or have a way for one or the other to communicate through interprocess communication.
A stern warning
Do not attempt to "install" a filter by manually writing registry keys. As you've noticed, it's not easy, and even if you seem to get it working, it will all collapse when the OS tries to install the next LWF. Furthermore, I added some additional hardening features designed exactly to prevent people from doing this to Windows 10; you'll have to do some significant damage to the OS before you can hijack network bindings in Windows 10.
How to structure your driver package
Anyway, what you're describing is indeed possible. The way to do it is to provide the following in your driver package:
A PNP-style INF. This INF has:
The PORTS class
An AddService directive, that installs your driver service
A CopyFiles directive to bring in any files you need
Any other bits you need for the PNP device
A NetCfg-style INF. This INF has:
The NETSERVICE class
The usual LWF stuff: Characteristics=0x40000, FilterMediaTypes=xxx, FilterType=xxx, etc.
A reference to the service you installed in the other INF (HKR,Ndi,Service,,xxx)
Do not include an AddService or CopyFiles; that's already taken care of by the first INF
One .sys file. This driver does:
In DriverEntry, call NdisFRegisterFilterDriver, and pass the name of your service "xxx"
In DriverEntry, call WdfDriverCreate or fill out the DRIVER_OBJET dispatch table as you normally would for any other PNP driver
Implement FilterAttach and etc normally; implement your WDF EvtXxx or WDM IRP handlers normally
Don't forget to call NdisFDeregisterFilterDriver in EvtDriverUnload or DriverUnload, and also in the failure path for DriverEntry
How to install this fine mess
The good news is that, with these 2 INFs, you can meet your requirement of having 1 .sys file do two things. The bad news is that you've now got 2 INFs. Worse, one of the INFs is a NetCfg-style INF, so you can't just Include+Need it. The only way to install a NetCfg-style INF is to call INetCfgClassSetup::Install (or NetCfg.exe, its command-line wrapper). Windows Update only knows how to install PNP-style INFs, and PNP only knows how to Include other PNP-style INFs.
So the simplest solution is to ship an installer exe/msi that invokes the INetCfg API. If you can do that, it's simply a matter of a couple calls to SetupCopyOemInf and the INetCfg boilerplate that you can find in the bindview sample.
But, if you have to support a hardware-first installation, you need to bring out the big guns. You'll need to write a Co-Installer and include it with your driver package. The Co-Installer's job is to call the INetCfg APIs when your driver package is installed, and deregister when the package is uninstalled.
Co-Installers are generally discouraged, and are not supported for Universal drivers. So you should avoid a Co-Installer unless you've got no choice. Unfortunately I cannot think of any other way to register an NDIS LWF when a PNP device driver is installed through Windows Update. (This doesn't mean there isn't a crafty way to do it; I don't know everything.)
Note that you'd need a Co-Installer anyway even if you were shipping 2 .sys files. The need to call INetCfg doesn't change just because you merged the driver binaries.
Limitations
You'll have a full-fledged NDIS LWF driver, as well as a full-fledged PNP device driver. The only (minor) thing that doesn't work is that you cannot call NdisRegisterDeviceEx in this driver. The reason is that when you call NdisRegisterDeviceEx from a LWF, NDIS will attempt to co-opt your driver's dispatch table. But in this PNP+LWF dual driver, the dispatch table is owned by WDF or by you. This limitation is no problem, since you can call WdfDeviceCreate, and this routine is easier to use and has more features than the NDIS one anyway.
With the above configuration, the driver service is owned by PNP. That means the lifetime of your .sys file is owned by PNP. You cannot manually "net start" a PNP driver service; the only way to get your .sys file loaded is to actually enumerate your hardware. That means you can't have your NDIS LWF running when the hardware is not present. Typically this is what you'd want anyway. If it's not, you can try messing with the ServiceName directive, but there's some weird caveats with that, and I don't fully understand it myself.
I made a device driver. But my system crashed at the moment when it was deleting the device object. I think the symbolic link was deleted and it crashed after it was trying to delete the device as I can't see the symbolic link in the Global.
How do I delete this device now. It also gives me a error popup(system cannot find the file specified Device\Mydriver) when I try to open the listed Mydriver under devices from Winobj.
I tried starting the driver's service again. I do get a handle back when opening the service. But it wont start now. giving the error value of Cannot find the file specified. I was working fine, i mean starting the driver before this crash.
I am a beginner with drivers and doing this to learn, please guide.
I have taken this from : Programming microsoft windows driver 2nd edition by woney
I hope this helps.
Removability of devices in a Plug and Play environment is the ultimate source of the early-unload problem
mentioned in the text. it’s your responsibility to avoid sending an IRP to a driver that might no longer be in memory
and to prevent the PnP manager from unloading a driver that’s still processing an IRP you’ve sent to that driver.
One aspect of how you fulfill that responsibility is shown in the text: take an extra reference to the file object
returned by IoGetDeviceObjectPointer around the call to IoCallDriver. In most drivers, you’ll probably need the
extra reference only when you’re sending an asynchronous IRP. In that case, the code that ordinarily
dereferences the file object is likely to be in some other part of your driver that runs asynchronously with the
call to IoCallDriver—say, in the completion routine you’re obliged to install for an asynchronous IRP. If you send
a synchronous IRP, you’re much more likely to code your driver in such a way that you don’t dereference the file
object until the IRP completes.
Use the interactive boot option and don't load the troublesome driver. Then you can experiment perhaps by adding diagnostic instrumentation to the driver or other debugging techniques to determine the underlying problem.