Driver package isolation

Driver package isolation is a requirement for Windows Drivers that makes driver packages more resilient to external changes, easier to update, and more straightforward to install.

Note

While driver package isolation is required for Windows Drivers, Windows Desktop Drivers still benefit from it through improved resiliency and serviceability.

The following table shows some example legacy driver package practices that are no longer allowed for Windows Drivers in the left column along with the required behavior for Windows Drivers in the right column.

Non-isolated driver Isolated driver
INF copies files to %windir%\System32 or %windir%\System32\drivers Driver files are run from the driver store
Interacts with device stacks/drivers using hardcoded paths Interacts with device stacks/drivers using system-supplied functions or device interfaces
Hardcodes path to global registry locations Uses HKR and system-supplied functions for relative location of registry and file state
Runtime file writes to any location Files are written relative to locations supplied by the operating system

For help in determining if your driver package meets driver package isolation requirements, see Validating Windows Drivers. For examples of how to update an INF to meet driver package isolation requirements, see Porting an INF to follow driver package isolation.

Run from driver store

All isolated driver packages leave their driver package files in the driver store. This means that they specify DIRID 13 in their INF to specify the location for driver package files on install. For more information on how to use this in a driver package, see Run from driver store.

Reading and writing state

Note

If your component is using device or device interface properties to store state, continue to use that method and the appropriate OS API's to store and access state. The following guidance for registry and file state is for other state that needs to be stored by a component.

Access to various registry and file state should be done by calling functions that provide a caller with the location of the state and then the state is read/written relative to that location. Do not use hardcoded absolute registry paths and file paths.

This section contains the following subsections:

Registry state

This section contains the following subsections:

PnP device registry state

Isolated driver packages and user-mode components typically use one of two locations to store device state in the registry. These are the hardware key (device key) for the device and the software key (driver key) for the device. The hardware key is typically for settings related to how an individual device instance interacts with the hardware. For example, to enable a hardware feature or put the hardware into a specific mode. The software key is typically for settings related to how an individual device instance interacts with the system and other software. For example, to configure the location of a data file, to inter operate with a framework, or to access app settings for a device. To retrieve a handle to these registry locations, use one of the following options:

[ExampleDDInstall.HW]
AddReg = Example_DDInstall.AddReg

[Example_DDInstall.AddReg] 
HKR,,ExampleValue,,%13%\ExampleFile.dll

Device interface registry state

To read and write device interface registry state, use one of the following options:

Service registry state

Service state should be classified into one of 3 categories

Immutable service registry state

Immutable service state is state that is provided by the driver package that installs the service. These registry values that are set by the INF for driver and Win32 services must be stored under the "Parameters" subkey of the service by providing an HKR line in an AddReg section, and then referencing that section in the service install section in the INF. For example:

[ExampleDDInstall.Services]
Addservice = ExampleService, 0x2, Example_Service_Inst

[Example_Service_Inst]
DisplayName    = %ExampleService.SvcDesc%
ServiceType    = 1
StartType      = 3
ErrorControl   = 1
ServiceBinary  = %13%\ExampleService.sys
AddReg=Example_Service_Inst.AddReg

[Example_Service_Inst.AddReg]
HKR, Parameters, ExampleValue, 0x00010001, 1

To access the location of this state from the service at runtime, use one of these functions:

These registry values supplied by the INF in the "Parameters" subkey for the service should only be read at runtime and not modified. They should be treated as read only.

If the registry values supplied by the INF are default settings that can be overwritten at runtime, the override values should be written into the Internal service registry state or Shared service registry state for the service. When retrieving the settings, the setting can be looked for first in the mutable state. If it does not exist there, then the setting can be looked for in the immutable state. RtlQueryRegistryValueWithFallback can be used to help query settings such as these that have an override and a default value.

Internal service registry state

Internal service state is state that is written at runtime and owned and managed by only the service itself and is only accessible to that service. To access the location for internal service state, use one of these functions from the service:

If the service wants to allow other components to modify these settings, the service must expose an interface that another component can call into that tells the service how to alter these settings. For example, a Win32 service could expose a COM or RPC interface and a driver service could expose an IOCTL interface via a device interface.

Shared service registry state

Shared service state is state that is written at runtime and can be shared with other user mode components if they are sufficiently privileged. To access the location for this shared service state, use one of these functions:

File state

This section contains the following subsections:

Device file state

If files related to a device need to be written at runtime, those files should be stored relative to a handle or file path provided via OS API's. Configuration files specific to that device is one example of what types of files to be stored here. To access the location of this state, use one of these functions from the service:

Service file state

Service file state can be classified into one of 3 categories

Immutable service file state

Immutable service file state are files that are part of the driver package. For more information on accessing those files, see Run from Driver Store.

Internal service file state

Internal service file state is state that is written at runtime and owned and managed by only the service itself and is only accessible to that service. To access the location for internal service state, use one of these functions from the service:

If the service wants to allow other components to modify these settings, the service must expose an interface that another component can call into that tells the service how to alter these settings. For example, a Win32 service could expose a COM or RPC interface and a driver service could expose an IOCTL interface via a device interface.

Shared service file state

Shared service file state is state that is written at runtime and can be shared with other user mode components if they are sufficiently privileged. To access the location for this shared service state, use one of these functions:

DriverData and ProgramData

Files that can be shared with other components but that do not fit into the shared service file state category can be written to either DriverData or ProgramData locations.

These locations offer components a location to write temporary state or state that is meant to be consumed by other components and potentially collected and copied from a system to be processed by another system. For example, custom log files or crash dumps fit this description.

Avoid writing files in the root of the DriverData or ProgramData directories. Instead, create a subdirectory with your company name and then write files and further subdirectories within that directory.

For example, for a company name of Contoso, a kernel-mode driver could write a custom log to \DriverData\Contoso\Logs and a user-mode application could collect or analyze the log files from %DriverData%\Contoso\Logs.

DriverData

The DriverData directory is available in Windows 10, version 1803 and later, and is accessible to administrators and UMDF drivers.

Kernel-mode drivers access the DriverData directory by using a system-supplied symbolic link called \DriverData.

User-mode programs access the DriverData directory by using the environment variable %DriverData%.

ProgramData

The %ProgramData% user-mode environment variable is available for user-mode components to use when storing data.

Temporary files

Temporary files are typically used in intermediate operations. These can be written to a sub-path under the %TEMP% or %TMP% environment variables. Since these locations are accessed through environment variables, this ability is limited to user mode components. There are no guarantees on the lifetime or persistence of these temporary files after handles to them are closed. The operating system or user may remove them at any time and they may not persist across a reboot.

Avoid writing files in the root of the %TEMP% or %TMP% directories. Instead, create a subdirectory with your company name and then write files and further subdirectories within that directory.

Property state

Both devices and device interfaces support storing state via the PnP property model. The property model allows for structured property data to be stored against a device or device interface. This is meant for smaller data that reasonably fits into the property types supported by the property model.

To access device properties, these APIs can be used:

To access device interface properties, these APIs can be used:

Using device interfaces

If a driver wants to allow other components to read or modify the driver's internal state, the driver should expose an interface that another component can call into that tells the driver what settings to return or how to modify particular settings. For example, the driver service could expose an IOCTL interface via a device interface.

Typically, the driver that owns the state exposes a device interface in a custom device interface class. When the driver is ready for other components to have access to the state, it enables the interface. To get notified when a device interface is enabled, user mode components can register for device interface arrival notifications and kernel mode components can use IoRegisterPlugPlayNotification. For these components to access the state, the driver enabling the interface must define a contract for its custom device interface class. This contract typically is one of two kinds:

  • An I/O contract can be associated with that device interface class that provides a mechanism for accessing the state. Other components use the enabled device interface to send I/O requests that conform to the contract.

  • A direct-call interface that gets returned via a query interface. Other drivers could send IRP_MN_QUERY_INTERFACE to retrieve function pointers from the driver to call.

Alternatively, if the driver that owns the state allows direct access to the state, other drivers could access state by using system-supplied functions for programmatic access to device interface state. See Device Interface Registry State for more information.

These interfaces or state (depending on sharing method used) need to be properly versioned so the driver owning the state can be serviced independently of other components that access that state. Driver vendors cannot rely on other components being serviced at the same time as the driver and staying at the same version.

Because devices and drivers controlling interfaces come and go, drivers and applications should avoid calling IoGetDeviceInterfaces at component start-up to get a list of enabled interfaces. Instead, the best practice is to register for notifications of device interface arrival or removal and then call the appropriate function to get the list of existing enabled interfaces on the machine.

For more information about device interfaces, see:

Quick reference of operating system support for state management APIs

Most driver packages need to support a range of operating system versions. See Supporting multiple operating system versions for more information on how to achieve this in a driver package. The following tables provide a quick reference of when operating system support was added for various state management APIs.

WDM drivers

Operating system Support added
Windows 2000 IoOpenDeviceRegistryKey
IoOpenDeviceInterfaceRegistryKey
Windows Vista IoGetDevicePropertyData
IoSetDevicePropertyData
Windows 8 IoGetDeviceInterfacePropertyData
IoSetDeviceInterfacePropertyData
Windows 8.1 IoQueryFullDriverPath
Windows 10 1803 IoOpenDriverRegistryKey for RegKeyType of DriverRegKeyParameters and DriverRegKeyPersistentState
IoGetDeviceDirectory
IoGetDriverDirectory for DirectoryType of DriverDirectoryImage and DriverDirectoryData
Windows 10 1809 RtlQueryRegistryValueWithFallback
Windows 11 21H2 IoOpenDriverRegistryKey for RegKeyType of DriverRegKeySharedPersistentState
IoGetDriverDirectory for DirectoryType of DriverDirectorySharedData

KMDF drivers

KMDF version Support added
1.0 WdfDeviceOpenRegistryKey
WdfFdoInitOpenRegistryKey
WdfDriverOpenParametersRegistryKey
WdfDeviceQueryProperty
WdfDeviceAllocAndQueryProperty
WdfFdoInitQueryProperty
WdfFdoInitAllocAndQueryProperty
1.13 WdfDeviceQueryPropertyEx
WdfDeviceAllocAndQueryPropertyEx
WdfDeviceAssignProperty
WdfFdoInitQueryPropertyEx
WdfFdoInitAllocAndQueryPropertyEx
1.25 WdfDriverOpenPersistentStateRegistryKey (Windows 10 1803)

UMDF drivers

UMDF version Support added
2.0 WdfDeviceOpenRegistryKey
WdfFdoInitOpenRegistryKey
WdfDriverOpenParametersRegistryKey
WdfDeviceQueryProperty
WdfDeviceAllocAndQueryProperty
WdfDeviceQueryPropertyEx
WdfDeviceAllocAndQueryPropertyEx
WdfDeviceAssignProperty
WdfFdoInitQueryProperty
WdfFdoInitAllocAndQueryProperty
WdfFdoInitQueryPropertyEx
WdfFdoInitAllocAndQueryPropertyEx
WdfDeviceQueryInterfaceProperty (Windows 8.1)
WdfDeviceAllocAndQueryInterfaceProperty (Windows 8.1)
WdfDeviceAssignInterfaceProperty (Windows 8.1)
2.25 WdfDeviceRetrieveDeviceDirectoryString
WdfDriverOpenPersistentStateRegistryKey (Windows 10 1803)
2.27 WdfDriverRetrieveDriverDataDirectoryString

User mode code

Operating system Support added
Windows 2000 CM_Open_DevNode_Key
Windows Vista CM_Open_Device_Interface_Key
CM_Get_DevNode_Property
CM_Set_DevNode_Property
CM_Get_Device_Interface_Property
CM_Set_Device_Interface_Property
Windows 10 2004 GetServiceRegistryStateKey
GetServiceDirectory
Windows 11 21H2 GetSharedServiceRegistryStateKey
GetSharedServiceDirectory