New driver installation on Windows - windows

I am trying to find what happens when new driver is installed for windows. (What kernel data structures are modified.) Does anyone know any good documentation on this topic. It is a bit painful to debug this.
Thanks

When a driver is installed is it placed into the Driver Store (see http://msdn.microsoft.com/en-us/library/ff544868%28v=vs.85%29.aspx)
When a new device is discovered that does not have a current driver association the PNP manager looks at the driver store to see if any of the stored drivers will match the new device.
If the PNP manager finds a driver to match the device it will execute the directives in the drivers inf file. This typically creates a service entry in the registry (HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services), copies the driver binaries to somewhere like \Windows\System32\drivers etc. Also the PNP manager will create an association of that device to that driver (HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum I think) so that next time it can shortcut the process.
I don't think any kernel data structures are modified when a driver is installed. Do you mean to ask when a driver is loaded?

Related

Installing a driver for a specific device

I would like to install a custom driver for a specific device in my machine programmatically:
The driver comes as an .inf file (with some other files as well).
The device is one of two identical network adapters in my computer.
As far as I know the only way to achieve this goal is to use the Microsoft Setup API. From reading the documentation I would assume that I need to perform two steps:
Use "DiInstallDriver" to install my .inf-based driver into the driver store (see https://learn.microsoft.com/en-us/windows/win32/api/newdev/nf-newdev-diinstalldrivera).
Use "DiInstallDevice" to apply my driver to the device (see https://learn.microsoft.com/en-us/windows/win32/api/newdev/nf-newdev-diinstalldevice).
Would this be the correct/easiest way to do this?
If so, here's a follow up question: DiInstallDevice requires two parameters which I don't know how to acquire:
DeviceInfoData: this should point to the network adapter I want to modify. How do I get this?
DriverInfoData: this should probably point to the driver I installed in step 1? How do I get this?
PS: Doing all this manually is uper easy: Open device manager, right-click the network adapter, select 'Update driver', choose .imf file from disk -> done!
But in this case I need to do it programmatically.
PPS: DevCon is not an option. It only allows to exchange the driver based on an Hardware ID. And that ID is the same for both of my network adapters (since they are exactly identical). So it would change the driver both devices.
You don’t need to call two methods, DiInstallDriver not only preinstalls a driver in the driver store, but also installs the driver on devices present in the system that the driver supports.
You can refer to the following documents: Functions that Simplify Driver Installation
It seems that UpdateDriverForPlugAndPlayDevices is the simplest way.
For DiInstallDevice, this function should only be use if both of the following are true:
The application incorporates more than one device instance of the same type, that is, all the device instances have the same hardware IDs and compatible IDs.
The application requires that device-instance-specific drivers be installed on the device instances.
UpdateDriverForPlugAndPlayDevices or DiInstallDriver is the
simplest way for an installation application to install a new driver
that is the best match for devices in the system. ... The basic operation
of UpdateDriverForPlugAndPlayDevices is similar to the operation of
DiInstallDriver. However UpdateDriverForPlugAndPlayDevices
supports additional installation options.
You can specify the HardwareId of network adapter for the UpdateDriverForPlugAndPlayDevices. If you want to install your .inf driver no matter what a better driver already exists on your computer, you also need to specify InstallFlags as INSTALLFLAG_FORCE.(Caution: Forcing the installation of the driver can result in replacing a more compatible or newer driver with a less compatible or older driver.)

Windows driver with or without INF file

I've seen two ways to install Windows drivers.
a. Using both SYS file and INF file. (such as NDIS driver)
b. Only use SYS file, the driver will be loaded by a service. (such as drivers in
C:\Windows\System32\drivers)
So, my question is:
1. What kind of drivers or situations require INF a file?
2. What is the root cause of this difference?
There are different kinds of drivers on Windows. Each type of driver has its own story for how the driver is installed. Here are a few common types of drivers.
PNP device driver. A PNP device driver operates a device in the device tree. PNP drivers are loaded by PNP when the device is enumerated by its parent bus. In order for PNP to know which type of device your driver supports (and a bunch of other stuff), you need a PNP-style INF that describes your driver.
SCM-managed driver (sometimes called "legacy driver"). SCM loads these drivers based on the same rules it uses to start NT services. SCM does not require any INF. You can register a new driver with SCM by simply running sc.exe create my_cool_driver type=kernel binPath=c:\my\driver.sys start=auto or calling the CreateService API. But if you already have an INF for other reasons, you can use any style of INF to do the same via the AddService directive.
NDIS lightweight filter (LWF) driver. LWFs are not loaded by NDIS; NDIS doesn't care how they're loaded. Most LWFs choose to be loaded by SCM, since that's easy to control. An NetCfg-style INF is still required, though, since NDIS needs to know what types of network adapters to attach the filter to (Ethernet vs WLAN, for example).
Export driver. An export driver is loaded by the memory manager when Mm is trying to load some other driver that imports functions from it. An export driver is just a kernel equivalent of a DLL — it just provides APIs to other drivers. Export drivers don't need an INF; they just need to be put into the right directory on disk. If you already have an INF for other reasons, you can use the CopyFiles directive to do this.
WinUSB driver. WinUSB is a built-in driver that delegates most of the responsibilities of managing a USB device to usermode APIs, so any application can easily do simple things with the device. This means pretty much any application can be the driver for the device. If the USB device puts certain data in its hardware descriptor, Windows will know to automatically set up WinUSB, so no INF is required. But if the hardware does not advertise that it needs WinUSB, then you'll need a WinUSB-style INF to tell Windows to set up WinUSB for you. Beyond that, you don't need an INF to call WinUSB APIs from your application.
If you're just experimenting and want to call a few kernel APIs for fun, you can choose any type of driver. Most people find that an SCM-managed driver is the easiest, since you don't need any INF and you get full control over when the driver starts and stops. But in any other situation, the choice of driver type is largely dictated by the problem you're trying to solve. For example, if you're writing a driver for a PCI GPU, you must use a PNP driver, and therefore must have a PCI-style INF.

Change installed device driver

I am trying to change the installed driver for a device using SetupAPI. The driver is already present on the PC, just not currently selected.
More specifically, I am trying undo the installation of a third-party driver for a USB composite device, and install the default windows driver instead.
I already got it almost working like this: First, find the device using
SetupDiGetClassDevs
SetupDiEnumDeviceInfo
SetupDiGetDeviceInstanceId
to find the device.
Next, find the default USB composite device driver I want to install using
SetupDiBuildDriverInfoList
SetupDiEnumDriverInfo
SetupDiGetDriverInfoDetail
Once I found the driver, I call
SetupDiSetSelectedDriver
SetupDiInstallDevice
This actually does switch the driver back, as can be observed in device manager.
However, the third party driver put the device into its own group/category, and this change is not undone when using my approach.
Manually selecting the standard USB composite device driver in the device manager does restore the device category back to USB Controllers, which is why I think my driver installation process is incomplete. What might I be missing?
Turns out the working installation sequence is
SetupDiSetSelectedDevice
SetupDiSetSelectedDriver
InstallSelectedDriver // From newdev.dll, not in a public header

Is it possible to fully install a driver when the device is not present?

Is it possible to fully install (and not just pre-install) a device driver on a system before the physical device is plugged in? In particular, I'm looking at the D2XX drivers by FTDI. Their driver installation program effectively runs dpinst.exe, and if you watch the console output of that program it says this:
No matching device was found for 'c:\drivers\ftdiport.inf'. Driver will be installed when plugged in.
The trouble is that I'm also using their .NET library for accessing the device, and that library is funny. It pops up an alert in the constructor if the driver isn't installed. Of course the usual solution is to simply plug in the device and let the driver installation finish as normal, but sometimes this is neglected. The pitfalls with having an unavoidable popup box in a 3rd party library should be obvious.
So does anyone know of a way to automate the full installation, and not just the pre-installation? Are there any dangers to copying the driver to the system folder manually / in advance?
You seem to mention "fully install" by "staging" the driver not by "loading" the driver. You can refer to the source code of "devcon.exe" for dp_add command, which actually do staging the driver package. Staged driver package will be being searched by PnP Manager when the unknown device is detected.

Remove incorrect binding of composite device to custom driver

Our latest WHQL'ed custom driver has an incorrect entry for one of our upcoming product. The upcoming product is composite device and our WHQL'ed driver has an entry which matches the device ID for the composite device instead of the individual interfaces.
When the new device is connected to machines which have the WHQL'ed driver, the device gets binded to our driver and not to Windows Generic Parent Driver (usbccgp.sys). This prevents the interfaces in the device from being listed.
We could manually fix this by uninstalling the driver for the device and making it to bind to usbccgp.sys driver. In Vista and higher versions, we could delete the driver binaries at the time of uninstall. But there is no direct way to completely delete the driver binaries in XP. This makes it very difficult to cleanly uninstall the driver
Can this be fixed using an uninstaller? What is the best way to fix the affected machine in an automated way?
Download the Windows Driver Development Kit (Win DDK) and locate the devcon.exe executable for your architecture. Then, from an elevated command prompt:
devcon.exe find =usb
To list all of your current devices.
devcon.exe -r remove =usb *YOUR_HARDWARE_ID*
Will complete disassociate the device and driver from the target machine. If you have trouble getting the hardware id you can blow away all your USB drivers and let Windows auto-detect them after reboot.
devcon.exe -r remove =usb *
Extreme, yes. Effective, yes. We work with virtual comm ports all day and our test machines often experience your same issue. This technique has yet to fail.

Resources