- Add and Remove Drivers to an offline Windows Image
- Driver types
- Add drivers to an offline Windows image
- Remove drivers from an offline Windows image
- Add drivers to an offline Windows image by using an unattended answer file
- Updating Driver Files
- Write a Hello World Windows Driver (KMDF)
- Create and build a driver
- Write your first driver code
- Build the driver
- Deploy the driver
- Install the driver
- Debug the driver
Add and Remove Drivers to an offline Windows Image
You can use DISM to install or remove driver (.inf) files in an offline Windows or WinPE image. You can either add or remove the drivers directly by using the command prompt, or apply an unattended answer file to a mounted .wim, .ffu, .vhd, or .vhdx file.
When you use DISM to install a device driver to an offline image, the device driver is added to the driver store in the offline image. When the image is booted, Plug and Play (PnP) runs and associates the drivers in the store to the corresponding devices on the computer.
To add drivers to a WindowsВ 10 image offline, you must use a technician computer running WindowsВ 10, Windows ServerВ 2016, or Windows Preinstallation Environment (WinPE) for WindowsВ 10. Driver signature verification may fail when you add a driver to a WindowsВ 10 image offline from a technician computer running any other operating system.
To learn how to add a driver on a running Windows PC, see Add a driver online in audit mode or Install a plug and play device. To learn how to add a driver to a PC running WinPE, see Drvload command line options.
Driver types
- .inf-style drivers: Many drivers include an information file (with an .inf extension) to help install the driver. These can be installed using tools described in this topic.
- .exe-style drivers: Drivers without an .inf file often must be installed like typical Windows desktop applications. To learn how to add these, see Add a driver online in Audit Mode
- Boot-critical drivers: Graphics and storage drivers may sometimes need to be added to the Windows image (as shown in this topic), as well as the Windows PE image, and in the Windows recovery (WinRE) image.
Add drivers to an offline Windows image
To add drivers to an offline image, you have to mount an image prior to adding drivers.
If you’re adding drivers to a WinPE image, you can add them to the WinPE image in the output folder you specified when you ran copype, for example: C:\WinPE_amd64\media\sources\boot.wim . This ensures that drivers will be included in WinPE each time you build WinPE media from that folder.
- Mount a Windows image. For example:
- Add a driver to the image.
To install all of the drivers from a folder and all its subfolders, point to the folder and use the /Recurse option.
To see all DISM driver servicing command line options, see DISM driver servicing command-line options.
Using /Recurse can be handy, but it’s easy to bloat your image with it. Some driver packages include multiple .inf driver packages, which often share payload files from the same folder. During installation, each .inf driver package is expanded into a separate folder. Each individual folder has a copy of the payload files. We’ve seen cases where a popular driver in a 900MB folder added 10GB to images when added with the /Recurse option.
To install an unsigned driver, use /ForceUnsigned to override the requirement that drivers installed on X64-based computers must have a digital signature.
- Check to see if the driver was added. Drivers added to the Windows image are named Oem*.inf. This guarantees unique naming for newly added drivers. For example, the files MyDriver1.inf and MyDriver2.inf are renamed Oem0.inf and Oem1.inf.
- Commit the changes and unmount the image.
Remove drivers from an offline Windows image
- At an elevated command prompt, mount the offline Windows image:
- Remove a specific driver from the image. Multiple drivers can also be removed on one command line.
Removing a boot-critical driver package can make the offline Windows image unbootable. For more information, see DISM Driver Servicing Command-Line Options. пїЅ
- Commit the changes and unmount the image.
Add drivers to an offline Windows image by using an unattended answer file
- Gather the device driver .inf files that you intend to install on the Windows image.
All drivers in the directory and subdirectories that are referenced in the answer file are added to the image. You should manage the answer file and these directories carefully to address concerns about increasing the size of the image with unnecessary driver packages.
- Use WindowsВ System Image Manager (WindowsВ SIM) to create an answer file that contains the paths to the device drivers that you want to install.
- Add the Microsoft-Windows-PnpCustomizationsNonWinPE\DriverPaths\PathAndCredentials\Credentials component to your answer file in the offlineServicing configuration pass.
For each location that you intend to access, add a separate PathAndCredentials list item by right-clicking on DriverPaths in the Answer File pane and clicking Insert New PathAndCredentials.
See Configure components and settings in an answer file for information on how to modify an answer file.
- For each path in Microsoft-Windows-PnpCustomizationsNonWinPE , specify the path to the device driver and the credentials that are used to access the file, if the file is on a network share.
When you include multiple device driver paths by adding multiple PathAndCredentials list items, you must increment the value of Key for each path. For example, you can add two separate driver paths where the value of Key for the first path is equal to 1 and the value of Key for the second path is equal to 2.
- Save the answer file and exit WindowsВ SIM. The answer file must resemble the following sample.
- Mount the Windows image that you intend to install the drivers to by using DISM:
If you’re working with a VHD or FFU, specify /Index:1 .
- Apply the answer file to the mounted Windows image:
For more information about how to apply an answer file, see DISM Unattended Servicing Command-Line Options.
The .inf files referenced in the path in the answer file are added to the Windows image.
- Check to see if the driver was added. Drivers added to the Windows image are named Oem*.inf. This guarantees unique naming for newly added drivers. For example, the files MyDriver1.inf and MyDriver2.inf are renamed Oem0.inf and Oem1.inf.
For example, type:
- Unmount the .wim file and commit the changes. For example, type:
If you need drivers for WinPE to see the local hard disk drive or a network, you must use the windowsPE configuration pass of an answer file to add drivers to the WinPE driver store and to reflect boot-critical drivers required by WinPE. For more information, see Add Device Drivers to Windows During Windows Setup.
Updating Driver Files
Drivers are updated whenever one of the following occurs:
The Hardware Update Wizard is run from Device Manager.
NoteВ В Starting with Windows Vista, this wizard is now named the Update Driver Software Wizard.
Windows Update is run.
Installation software for a device is run.
Starting with Windows Vista, you can run the PnPUtil tool from an elevated command prompt to install or update the driver package for the device.
Use the following guidelines when you write installation software and INF files that update existing drivers.
Installation software can call UpdateDriverForPlugAndPlayDevices, supplying an INF file and a hardware ID, to update drivers for devices that match the hardware ID.
Starting with Windows Vista, installation software can also call one of the following to update drivers:
- DiInstallDriver, which pre-installs a driver and then installs the driver on devices present in the system that the driver supports.
- DiInstallDevice, which installs a specified driver from the driver store on a specified device that is present in the system.
When upgrading a driver, class installers and co-installers should not supply finish-install pages in response to DIF_NEWDEVICEWIZARD_FINISHINSTALL unless absolutely necessary. If possible, obtain finish-install information from the settings of the previous installation.
To the extent possible, class installers and co-installers should avoid basing behavior on whether they are providing an initial installation or are updating drivers for an already-installed device.
Starting with Windows XP, the registry values CoInstallers32 and EnumPropPages32 are deleted before the delivery of DIF_REGISTER_COINSTALLERS. INF files for earlier operating system versions must explicitly either delete these values or perform a nonappending modify operation on them.
Starting with Windows XP, the registry values UpperFilters and LowerFilters are deleted before the delivery of DIF_INSTALLDEVICE. INF files for earlier operating system versions must explicitly either delete these values or perform a nonappending modify operation on them.
Do not use INF DelFiles directives or INF RenFiles directives when updating drivers. Windows cannot guarantee that a particular file is not being used by another device. (Class installers and co-installers can delete or rename files, if they can reliably determine that no devices are using the files.)
Use the INF DelReg directive to remove old device-specific registry entries from a previous installation of the device, if the entries are no longer needed. (Do not remove global registry entries.)
Do not use the INF DelService directive in an INF DDInstall.Services section to remove previously installed device/driver services from the target computer. Windows cannot guarantee that a particular service is not being used by another device. (Class installers and co-installers can delete services, if they can reliably determine that no devices are using the services.)
When updating a class installer, class co-installer, or service DLL, you must give the new version a new file name.
Write a Hello World Windows Driver (KMDF)
This topic describes how to write a very small Universal Windows driver using Kernel-Mode Driver Framework (KMDF) and then deploy and install your driver on a separate computer.
To get started, be sure you have Microsoft Visual Studio, the Windows SDK, and the Windows Driver Kit (WDK) installed.
Debugging Tools for Windows is included when you install the WDK.
Create and build a driver
Open Microsoft Visual Studio. On the File menu, choose New > Project.
In the New Project dialog box, in the left pane, go to Visual C++ > Windows Drivers > WDF.
In the middle pane, select Kernel Mode Driver, Empty (KMDF).
In the Name field, enter «KmdfHelloWorld» for the project name.
When you create a new KMDF or UMDF driver, you must select a driver name that has 32 characters or less. This length limit is defined in wdfglobals.h.
In the Location field, enter the directory where you want to create the new project.
Check Create directory for solution. Select OK.
Visual Studio creates one project and a solution. You can see them in the Solution Explorer window, shown here. (If the Solution Explorer window is not visible, choose Solution Explorer from the View menu.) The solution has a driver project named KmdfHelloWorld.
In the Solution Explorer window, select and hold (or right-click) the KmdfHelloWorld project and choose Properties. Navigate to Configuration Properties > Driver Settings > General, and note that Target Platform defaults to Universal. Select Apply, and then select OK..
In the Solution Explorer window, again select and hold (or right-click) the KmdfHelloWorld project, choose Add, and then select New Item.
In the Add New Item dialog box, select C++ File. For Name, enter «Driver.c».
The file name extension is .c, not .cpp.
Select Add. The Driver.c file is added under Source Files, as shown here.
Write your first driver code
Now that you’ve created your empty Hello World project and added the Driver.c source file, you’ll write the most basic code necessary for the driver to run by implementing two basic event callback functions.
In Driver.c, start by including these headers:
If you can’t add Ntddk.h , open Configuration -> C/C++ -> General -> Additional Include Directories and add C:\Program Files (x86)\Windows Kits\10\Include\ \km , replacing with the appropriate directory in your WDK installation.
Ntddk.h contains core Windows kernel definitions for all drivers, while Wdf.h contains definitions for drivers based on the Windows Driver Framework (WDF).
Next, provide declarations for the two callbacks you’ll use:
Use the following code to write your DriverEntry:
DriverEntry is the entry point for all drivers, like Main() is for many user mode applications. The job of DriverEntry is to initialize driver-wide structures and resources. In this example, you printed «Hello World» for DriverEntry, configured the driver object to register your EvtDeviceAdd callback’s entry point, then created the driver object and returned.
The driver object acts as the parent object for all other framework objects you might create in your driver, which include device objects, I/O queues, timers, spinlocks, and more. For more information about framework objects, see Introduction to Framework Objects.
For DriverEntry, we strongly recommend keeping the name as «DriverEntry» to help with code analysis and debugging.
Next, use the following code to write your KmdfHelloWorldEvtDeviceAdd:
EvtDeviceAdd is invoked by the system when it detects that your device has arrived. Its job is to initialize structures and resources for that device. In this example, you simply printed out a «Hello World» message for EvtDeviceAdd, created the device object, and returned. In other drivers you write, you might create I/O queues for your hardware, set up a device context storage space for device-specific information, or perform other tasks needed to prepare your device.
For the device add callback, notice how you named it with your driver’s name as a prefix (KmdfHelloWorldEvtDeviceAdd). Generally, we recommend naming your driver’s functions in this way to differentiate them from other drivers’ functions. DriverEntry is the only one you should name exactly that.
Your complete Driver.c now looks like this:
This example illustrates a fundamental concept of drivers: they are a «collection of callbacks» that, once initialized, sit and wait for the system to call them when it needs something. This could be a new device arrival event, an I/O request from a user mode application, a system power shutdown event, a request from another driver, or a surprise removal event when a user unplugs the device unexpectedly. Fortunately, to say «Hello World,» you only needed to worry about driver and device creation.
Next, you’ll build your driver.
Build the driver
In the Solution Explorer window, select and hold (or right-click) Solution ‘KmdfHelloWorld’ (1 project) and choose Configuration Manager. Choose a configuration and platform for the driver project. For this exercise, we choose Debug and x64.
In the Solution Explorer window, select and hold (or right-click) KmdfHelloWorld and choose Properties. In Wpp Tracing > All Options, set Run Wpp tracing to No. Select Apply and then OK.
To build your driver, choose Build Solution from the Build menu. Visual Studio shows the build progress in the Output window. (If the Output window is not visible, choose Output from the View menu.) When you have verified that the solution built successfully, you can close Visual Studio.
To see the built driver, in File Explorer, go to your KmdfHelloWorld folder, and then to C:\KmdfHelloWorld\x64\Debug\KmdfHelloWorld. The folder includes:
- KmdfHelloWorld.sys — the kernel-mode driver file
- KmdfHelloWorld.inf — an information file that Windows uses when you install the driver
- KmdfHelloWorld.cat — a catalog file that the installer uses to verify the driver’s test signature
If you see DriverVer set to a date in the future when building your driver, change your driver project settings so that Inf2Cat sets /uselocaltime . To do so, use Configuration Properties->Inf2Cat->General->Use Local Time. Now both Stampinf and Inf2Cat use local time.
Deploy the driver
Typically when you test and debug a driver, the debugger and the driver run on separate computers. The computer that runs the debugger is called the host computer, and the computer that runs the driver is called the target computer. The target computer is also called the test computer.
So far you’ve used Visual Studio to build a driver on the host computer. Now you need to configure a target computer.
When you follow the steps to provision the target computer automatically using a network cable, take note of the port and key. You’ll use them later in the debugging step. In this example, we’ll use 50000 as the port and 1.2.3.4 as the key.
In real driver debugging scenarios, we recommend using a KDNET-generated key. For more information about how to use KDNET to generate a random key, see the Debug Drivers — Step by Step Lab (Sysvad Kernel Mode) topic.
On the host computer, open your solution in Visual Studio. You can double-click the solution file, KmdfHelloWorld.sln, in your KmdfHelloWorld folder.
In the Solution Explorer window, select and hold (or right-click) the KmdfHelloWorld project, and choose Properties.
In the KmdfHelloWorld Property Pages window, go to Configuration Properties > Driver Install > Deployment, as shown here.
Check Remove previous driver versions before deployment.
For Target Device Name, select the name of the computer that you configured for testing and debugging. In this exercise, we use a computer named MyTestComputer.
Select Hardware ID Driver Update, and enter the hardware ID for your driver. For this exercise, the hardware ID is Root\KmdfHelloWorld. Select OK.
In this exercise, the hardware ID does not identify a real piece of hardware. It identifies an imaginary device that will be given a place in the device tree as a child of the root node. For real hardware, do not select Hardware ID Driver Update; instead, select Install and Verify. You’ll see the hardware ID in your driver’s information (INF) file. In the Solution Explorer window, go to KmdfHelloWorld > Driver Files, and double-click KmdfHelloWorld.inf. The hardware ID is located under [Standard.NT$ARCH$].
On the Build menu, choose Deploy Solution. Visual Studio automatically copies the files required to install and run the driver to the target computer. This may take a minute or two.
When you deploy a driver, the driver files are copied to the %Systemdrive%\drivertest\drivers folder on the test computer. If something goes wrong during deployment, you can check to see if the files are copied to the test computer. Verify that the .inf, .cat, test cert, and .sys files, and any other necessary files, are present in the %systemdrive%\drivertest\drivers folder.
For more information about deploying drivers, see Deploying a Driver to a Test Computer.
Install the driver
With your Hello World driver deployed to the target computer, now you’ll install the driver. When you previously provisioned the target computer with Visual Studio using the automatic option, Visual Studio set up the target computer to run test signed drivers as part of the provisioning process. Now you just need to install the driver using the DevCon tool.
On the host computer, navigate to the Tools folder in your WDK installation and locate the DevCon tool. For example, look in the following folder:
C:\Program Files (x86)\Windows Kits\10\Tools\x64\devcon.exe
Copy the DevCon tool to your remote computer.
On the target computer, install the driver by navigating to the folder containing the driver files, then running the DevCon tool.
Here’s the general syntax for the devcon tool that you will use to install the driver:
The INF file required for installing this driver is KmdfHelloWorld.inf. The INF file contains the hardware ID for installing the driver binary, KmdfHelloWorld.sys. Recall that the hardware ID, located in the INF file, is Root\KmdfHelloWorld.
Open a Command Prompt window as Administrator. Navigate to your folder containing the built driver .sys file and enter this command:
devcon install kmdfhelloworld.inf root\kmdfhelloworld
If you get an error message about devcon not being recognized, try adding the path to the devcon tool. For example, if you copied it to a folder on the target computer called C:\Tools, then try using the following command:
c:\tools\devcon install kmdfhelloworld.inf root\kmdfhelloworld
A dialog box will appear indicating that the test driver is an unsigned driver. Select Install this driver anyway to proceed.
Debug the driver
Now that you have installed your KmdfHelloWorld driver on the target computer, you’ll attach a debugger remotely from the host computer.
On the host computer, open a Command Prompt window as Administrator. Change to the WinDbg.exe directory. We will use the x64version of WinDbg.exe from the Windows Driver Kit (WDK) that was installed as part of the Windows kit installation. Here is the default path to WinDbg.exe:
C:\Program Files (x86)\Windows Kits\10\Debuggers\x64
Launch WinDbg to connect to a kernel debug session on the target computer by using the following command. The value for the port and key should be the same as what you used to provision the target computer. We’ll use 50000 for the port and 1.2.3.4 for the key, the values we used during the deploy step. The k flag indicates that this is a kernel debug session.
WinDbg -k net:port=50000,key=1.2.3.4
On the Debug menu, choose Break. The debugger on the host computer will break into the target computer. In the Debugger Command window, you can see the kernel debugging command prompt: kd>.
At this point, you can experiment with the debugger by entering commands at the kd> prompt. For example, you could try these commands:
To let the target computer run again, choose Go from the Debug menu or press «g,» then press «enter.»
To stop the debugging session, choose Detach Debuggee from the Debug menu.
Make sure you use the «go» command to let the target computer run again before exiting the debugger, or the target computer will remain unresponsive to your mouse and keyboard input because it is still talking to the debugger.
For a detailed step-by-step walkthrough of the driver debugging process, see Debug Universal Drivers — Step by Step Lab (Echo Kernel-Mode).
For more information about remote debugging, see Remote Debugging Using WinDbg.