Treiberpaketisolation
Die Isolierung von Treiberpaketen ist eine Voraussetzung für Windows-Treiber, die dafür sorgt, dass Treiberpakete resilienter gegenüber externen Änderungen, einfacher zu aktualisieren und unkomplizierter zu installieren sind.
Hinweis
Auch wenn die Isolierung von Treiberpaketen für Windows-Treiber erforderlich ist, profitieren Windows-Desktop-Treiber dennoch von ihr, da sie die Resilienz und die Wartungsfähigkeit verbessert.
Die folgende Tabelle zeigt in der linken Spalte einige Beispiele für veraltete Pakete, die für Windows-Treiber nicht mehr zugelassen sind, und in der rechten Spalte das erforderliche Verhalten für Windows-Treiber.
Nicht-isolierter Treiber | Isolierter Treiber |
---|---|
INF copies files to %windir%\System32 or %windir%\System32\drivers | Treiberdateien werden aus dem Treiber-Store ausgeführt |
Interaktion mit Gerätestacks/Treibern über fest programmierte Pfade | Interagiert mit Gerätestacks/Treibern über vom System bereitgestellte Funktionen oder Geräteschnittstellen |
Fest programmierte Pfade zu globalen Registrierungsorten | Verwendet HKR und vom System bereitgestellte Funktionen zur relativen Ermittlung von Registrierungs- und Dateistatus |
Runtime schreibt Dateien an einen beliebigen Ort | Dateien werden relativ zu den vom Betriebssystem bereitgestellten Speicherorten geschrieben |
Hilfe bei der Feststellung, ob Ihr Treiberpaket die Anforderungen an die Isolierung von Treiberpaketen erfüllt, finden Sie unter Validierung von Windows-Treibern. Beispiele dafür, wie Sie eine INF aktualisieren können, um die Anforderungen an die Isolierung des Treiberpakets zu erfüllen, finden Sie unter Portieren einer INF, um die Isolierung des Treiberpakets zu gewährleisten.
Ausführen aus dem Treiber-Store
Alle isolierten Treiberpakete lassen ihre Treiberpaketdateien im Treiber-Store. Das bedeutet, dass sie DIRID 13 in ihrer INF angeben, um den Speicherort für die Dateien des Treiberpakets bei der Installation festzulegen. Weitere Informationen darüber, wie Sie dies in einem Treiberpaket verwenden, finden Sie unter Aus dem Store ausführen.
Lesen und Schreiben des Status
Hinweis
Wenn Ihre Komponente ein Gerät oder eine Geräteschnittstelle Eigenschaften verwendet, um den Status zu speichern, verwenden Sie weiterhin diese Methode und die entsprechenden APIs des Betriebssystems, um den Status zu speichern und darauf zuzugreifen. Die folgende Anleitung für Registrierungs- und Dateistatus gilt für andere Status, die von einer Komponente gespeichert werden müssen.
Der Zugriff auf verschiedene Registrierungs- und Dateistatus sollte durch den Aufruf von Funktionen erfolgen, die dem Aufrufer den Speicherort des Status mitteilen. Der Status wird dann relativ zu diesem Speicherort gelesen/geschrieben. Verwenden Sie keine fest kodierten absoluten Registrierungs- und Dateipfade.
Dieser Abschnitt enthält die folgenden Unterabschnitte:
Registrierungsstatus
Dieser Abschnitt enthält die folgenden Unterabschnitte:
Registrierungsstatus von PnP-Geräten
Isolierte Treiberpakete und Komponenten für den Benutzermodus verwenden in der Regel einen von zwei Orten, um den Status des Geräts in der Registrierung zu speichern. Dies sind der Hardwareschlüssel (Geräteschlüssel) für das Gerät und der Softwareschlüssel (Treiberschlüssel) für das Gerät. Der Hardwareschlüssel ist in der Regel für Einstellungen vorgesehen, die sich darauf beziehen, wie eine einzelne Instanz des Geräts mit der Hardware interagiert. Zum Beispiel, um eine Funktion der Hardware zu aktivieren oder die Hardware in einen bestimmten Modus zu versetzen. Der Softwareschlüssel dient in der Regel für Einstellungen, die sich darauf beziehen, wie eine einzelne Instanz des Geräts mit dem System und anderer Software interagiert. Zum Beispiel, um den Speicherort einer Datendatei festzulegen, um mit einem Framework zu interagieren oder um auf App-Einstellungen für ein Gerät zuzugreifen. Verwenden Sie eine der folgenden Optionen, um ein Handle zu diesen Speicherorten der Registrierung zu erhalten:
IoOpenDeviceRegistryKey (WDM)
CM_Open_DevNode_Key (user-mode code)
INF AddReg-Direktive unter Verwendung von HKR reg-root Einträgen in einem add-registry-section, der von einem INF DDInstall-Abschnitt oder DDInstall.HW-Abschnitt referenziert wird, wie unten gezeigt:
[ExampleDDInstall.HW]
AddReg = Example_DDInstall.AddReg
[Example_DDInstall.AddReg]
HKR,,ExampleValue,,%13%\ExampleFile.dll
Registrierungsstatus von Geräteschnittstellen
Um den Registrierungsstatus der Geräteschnittstelle zu lesen und zu schreiben, verwenden Sie eine der folgenden Optionen:
CM_Open_Device_Interface_Key (user-mode code)
INF AddReg-Direktive mit HKR reg-root-Einträgen in einem Add-registry-section, der von einem add-interface-section referenziert wird
Registrierungsstatus von Diensten
Der Status eines Dienstes sollte in eine von 3 Kategorien eingeteilt werden
Nicht veränderbarer Registrierungsstatus des Dienstes
Der unveränderliche Status des Dienstes ist der Status, der vom Treiberpaket, das den Dienst installiert, bereitgestellt wird. Diese Registrierungswerte, die von der INF für Treiber- und Win32-Dienste festgelegt werden, müssen unter dem Unterschlüssel „Parameter“ des Dienstes gespeichert werden, indem Sie eine HKR-Zeile in einem AddReg-Abschnitt bereitstellen und dann auf diesen Abschnitt im Dienstinstallationsabschnitt in der INF verweisen. Zum Beispiel:
[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
Um vom Dienst aus zur Laufzeit auf den Speicherort dieses Status zuzugreifen, verwenden Sie eine dieser Funktionen:
IoOpenDriverRegistryKey (WDM) mit einem DRIVER_REGKEY_TYPE von DriverRegKeyParameters
GetServiceRegistryStateKey (Win32-Dienste) mit einem SERVICE_REGISTRY_STATE_TYPE von ServiceRegistryStateParameters
Diese von der INF im Unterschlüssel „Parameter“ für den Dienst bereitgestellten Registrierungswerte sollten nur zur Laufzeit gelesen und nicht verändert werden. Sie sollten als schreibgeschützt behandelt werden.
Wenn es sich bei den von der INF gelieferten Registrierungswerten um Standardeinstellungen handelt, die zur Laufzeit überschrieben werden können, sollten die überschreibenden Werte in den internen Registrierungsstatus des Dienstes oder gemeinsamen Registrierungsstatus des Dienstes geschrieben werden. Beim Abrufen der Einstellungen kann die Einstellung zunächst im veränderbaren Status gesucht werden. Wenn sie dort nicht vorhanden ist, kann die Einstellung im unveränderlichen Status gesucht werden. RtlQueryRegistryValueWithFallback kann verwendet werden, um Einstellungen wie diese abzufragen, die eine Überschreibung und einen Standardwert haben.
Interner Registrierungsstatus des Dienstes
Der interne Status eines Dienstes ist ein Status, der zur Laufzeit geschrieben wird und nur dem Dienst selbst gehört und verwaltet wird und nur für diesen Dienst zugänglich ist. Um auf den Speicherort für den internen Status des Dienstes zuzugreifen, verwenden Sie eine der folgenden Funktionen des Dienstes:
IoOpenDriverRegistryKey (WDM) mit einem DRIVER_REGKEY_TYPE von DriverRegKeyPersistentState
GetServiceRegistryStateKey (Win32-Dienste) mit einem SERVICE_REGISTRY_STATE_TYPE von ServiceRegistryStatePersistent
Wenn der Dienst anderen Komponenten die Möglichkeit bieten will, diese Einstellungen zu ändern, muss der Dienst eine Schnittstelle bereitstellen, die eine andere Komponente aufrufen kann und die dem Dienst mitteilt, wie er diese Einstellungen ändern kann. Ein Win32-Dienst könnte zum Beispiel eine COM- oder RPC-Schnittstelle und ein Treiberdienst eine IOCTL-Schnittstelle über eine Geräteschnittstelle bereitstellen.
Gemeinsamer Registrierungsstatus des Dienstes
Der gemeinsame Status eines Dienstes ist ein Status, der zur Laufzeit geschrieben wird und mit anderen Komponenten im Benutzermodus geteilt werden kann, wenn diese ausreichend privilegiert sind. Um auf den Speicherort für diesen gemeinsamen Dienststatus zuzugreifen, verwenden Sie eine dieser Funktionen:
IoOpenDriverRegistryKey (WDM) mit einem DRIVER_REGKEY_TYPE von DriverRegKeySharedPersistentState
GetSharedServiceRegistryStateKey (Win32-Dienste) mit einem SERVICE_SHARED_REGISTRY_STATE_TYPE von ServiceSharedRegistryPersistentState
Dateistatus
Dieser Abschnitt enthält die folgenden Unterabschnitte:
Status der Gerätedatei
Wenn Dateien, die sich auf ein Gerät beziehen, zur Laufzeit geschrieben werden müssen, sollten diese Dateien relativ zu einem Handle oder Dateipfad gespeichert werden, der über die APIs des Betriebssystems bereitgestellt wird. Ein Beispiel für Dateien, die hier gespeichert werden sollten, sind gerätespezifische Konfigurationsdateien. Um auf den Speicherort dieses Status zuzugreifen, verwenden Sie eine der folgenden Funktionen des Dienstes:
IoGetDeviceDirectory (WDM) mit dem Parameter DirectoryType festgelegt auf DeviceDirectoryData
Status der Servicedatei
Der Status der Servicedatei kann in eine von 3 Kategorien eingeteilt werden
Nicht veränderbarer Status der Servicedatei
Unveränderliche Status der Servicedatei sind Dateien, die Teil des Treiberpakets sind. Weitere Informationen zum Zugriff auf diese Dateien finden Sie unter Ausführen aus dem Treiber-Store.
Interner Status der Servicedatei
Ein interner Status der Servicedatei ist ein Status, der zur Laufzeit geschrieben wird und nur dem Dienst selbst gehört und verwaltet wird und auf den nur dieser Dienst Zugriff hat. Um auf den Speicherort für den internen Status des Dienstes zuzugreifen, verwenden Sie eine der folgenden Funktionen des Dienstes:
IoGetDriverDirectory (WDM, KMDF) mit dem Parameter DirectoryType festgelegt auf DriverDirectoryData
GetServiceDirectory (Win32-Dienste) mit dem Parameter eDirectoryType festgelegt auf ServiceDirectoryPersistentState
Wenn der Dienst anderen Komponenten die Möglichkeit bieten will, diese Einstellungen zu ändern, muss der Dienst eine Schnittstelle bereitstellen, die eine andere Komponente aufrufen kann und die dem Dienst mitteilt, wie er diese Einstellungen ändern kann. Ein Win32-Dienst könnte zum Beispiel eine COM- oder RPC-Schnittstelle und ein Treiberdienst eine IOCTL-Schnittstelle über eine Geräteschnittstelle bereitstellen.
Gemeinsamer Status der Servicedatei
Der Status der gemeinsam genutzten Status der Servicedatei ist ein Status, der zur Laufzeit geschrieben wird und mit anderen Komponenten im Benutzermodus geteilt werden kann, wenn diese ausreichend privilegiert sind. Um auf den Speicherort für diesen gemeinsamen Dienststatus zuzugreifen, verwenden Sie eine dieser Funktionen:
IoGetDriverDirectory (WDM, KMDF) mit dem Parameter DirectoryType festgelegt auf DriverDirectorySharedData
GetSharedServiceDirectory (Win32-Dienste), wobei der Parameter DirectoryType auf ServiceSharedDirectoryPersistentState festgelegt ist
DriverData und ProgramData
Dateien, die mit anderen Komponenten gemeinsam genutzt werden können, aber nicht in die Kategorie Gemeinsamer Status der Servicedatei passen, können entweder an DriverData
- oder ProgramData
-Speicherorte geschrieben werden.
Diese Speicherorte bieten Komponenten einen Ort, an dem sie temporäre Zustände oder Zustände schreiben können, die von anderen Komponenten verbraucht und möglicherweise von einem System gesammelt und kopiert werden sollen, um von einem anderen System verarbeitet zu werden. Dies gilt zum Beispiel für angepasste Log-Dateien oder Crash Dumps.
Vermeiden Sie das Schreiben von Dateien im Root der Verzeichnisse DriverData
oder ProgramData
. Erstellen Sie stattdessen ein Unterverzeichnis mit Ihrem Firmennamen und schreiben Sie dann Dateien und weitere Unterverzeichnisse in dieses Verzeichnis.
Bei einem Firmennamen wie Contoso könnte zum Beispiel ein Kernel-Mode-Treiber eine angepasste Log-Datei nach \DriverData\Contoso\Logs
schreiben und eine User-Mode-Anwendung könnte die Log-Dateien aus %DriverData%\Contoso\Logs
sammeln oder analysieren.
DriverData
Das Verzeichnis DriverData
steht in Windows 10 ab Version 1803 zur Verfügung und ist für Administrator*innen und UMDF-Treiber zugreifbar.
Treiber im Kernel-Modus greifen auf das Verzeichnis DriverData
über einen vom System bereitgestellten symbolischen Link namens \DriverData
zu.
Benutzer*innen greifen auf das Verzeichnis DriverData
mit Hilfe der Umgebungsvariablen %DriverData%
zu.
ProgramData
Die Umgebungsvariable %ProgramData%
für den Benutzermodus steht den Komponenten des Benutzermodus für das Speichern von Daten zur Verfügung.
Temporäre Dateien
Temporäre Dateien werden in der Regel für Zwischenvorgänge verwendet. Diese können in einen Unterpfad unter den Umgebungsvariablen %TEMP%
oder %TMP%
geschrieben werden. Da der Zugriff auf diese Speicherorte über Umgebungsvariablen erfolgt, ist diese Möglichkeit auf Komponenten im Benutzermodus beschränkt. Es gibt keine Garantien für die Lebensdauer oder das Fortbestehen dieser temporären Dateien, nachdem Handles auf sie geschlossen wurden. Das Betriebssystem oder der Benutzer*innen können sie jederzeit löschen und sie bleiben möglicherweise nicht über einen Neustart hinaus bestehen.
Vermeiden Sie das Schreiben von Dateien im Root der Verzeichnisse %TEMP%
oder %TMP%
. Erstellen Sie stattdessen ein Unterverzeichnis mit Ihrem Firmennamen und schreiben Sie dann Dateien und weitere Unterverzeichnisse in dieses Verzeichnis.
Eigenschaftsstatus
Sowohl Geräte als auch Geräteschnittstellen unterstützen das Speichern des Status über das PnP-Eigenschaftsmodell. Das Eigenschaftsmodell bietet die Möglichkeit, strukturierte Eigenschaftsdaten für ein Gerät oder eine Geräteschnittstelle zu speichern. Dies ist für kleinere Daten gedacht, die vernünftigerweise in die vom Eigenschaftsmodell unterstützten Eigenschaftstypen passen.
Für den Zugriff auf Geräteeigenschaften können diese APIs verwendet werden:
WDM-Treiber
WDF-Treiber
Benutzermodus-Code
Für den Zugriff auf Eigenschaften von Geräteschnittstellen können diese APIs verwendet werden:
WDM-Treiber
WDF-Treiber
Benutzermodus-Code
Verwenden von Geräteschnittstellen
Wenn ein Treiber anderen Komponenten die Möglichkeit bieten möchte, den internen Status des Treibers zu lesen oder zu ändern, sollte der Treiber eine Schnittstelle bereitstellen, die eine andere Komponente aufrufen kann und die dem Treiber mitteilt, welche Einstellungen er zurückgeben oder wie er bestimmte Einstellungen ändern soll. Der Treiberdienst könnte zum Beispiel eine IOCTL-Schnittstelle über eine Geräteschnittstelle bereitstellen.
In der Regel stellt der Treiber, dem der Status gehört, eine Geräteschnittstelle in einer angepassten Geräteschnittstellenklasse zur Verfügung. Wenn der Treiber bereit ist, dass andere Komponenten auf den Status zugreifen können, aktiviert er die Schnittstelle. Um benachrichtigt zu werden, wenn eine Geräteschnittstelle aktiviert ist, können sich Benutzer*innen für Geräteschnittstellen-Ankunftsbenachrichtigungen registrieren und Kernel-Komponenten können IoRegisterPlugPlayNotification verwenden. Damit diese Komponenten auf den Status zugreifen können, muss der Treiber, der die Schnittstelle aktiviert, einen Vertrag für seine angepasste Geräte-Schnittstellenklasse definieren. Dieser Vertrag ist in der Regel eine von zwei Arten:
Ein E/A-Vertrag kann mit dieser Geräte-Schnittstellenklasse verknüpft werden, der einen Mechanismus für den Zugriff auf den Status bereitstellt. Andere Komponenten verwenden die aktivierte Geräteschnittstelle, um E/A-Anfragen zu senden, die dem Vertrag entsprechen.
Eine Direct-Call-Schnittstelle, die über eine Abfrage-Schnittstelle zurückgegeben wird. Andere Treiber könnten IRP_MN_QUERY_INTERFACE senden, um Funktionszeiger von dem aufzurufenden Treiber zu erhalten.
Wenn der Treiber, dem der Status gehört, den direkten Zugriff auf den Status zulässt, könnten andere Treiber alternativ auf den Status zugreifen, indem sie die vom System bereitgestellten Funktionen für den programmgesteuerten Zugriff auf den Status der Geräteschnittstelle verwenden. Weitere Informationen finden Sie unter Geräteschnittstellen-Registrierungsstatus.
Diese Schnittstellen oder der Status (je nach verwendeter Freigabemethode) müssen ordnungsgemäß versioniert werden, damit der Treiber, dem der Status gehört, unabhängig von anderen Komponenten, die auf diesen Status zugreifen, gewartet werden kann. Die Anbieter von Treibern können sich nicht darauf verlassen, dass andere Komponenten zur gleichen Zeit wie der Treiber gewartet werden und auf der gleichen Version bleiben.
Da Geräte und Treiber, die Schnittstellen steuern, kommen und gehen, sollten Treiber und Anwendungen den Aufruf von IoGetDeviceInterfaces beim Start der Komponente vermeiden, um eine Liste der aktivierten Schnittstellen zu erhalten. Stattdessen ist es am besten, sich für Benachrichtigungen über das Eintreffen oder Entfernen von Geräteschnittstellen zu registrieren und dann die entsprechende Funktion aufzurufen, um die Liste der auf dem Computer vorhandenen aktivierten Schnittstellen zu erhalten.
Weitere Informationen über Geräteschnittstellen finden Sie unter:
Kurzreferenz der Betriebssystemunterstützung für Status-Management-APIs
Die meisten Treiberpakete müssen eine Reihe von Betriebssystemversionen unterstützen. Unter Unterstützung mehrerer Betriebssystemversionen finden Sie weitere Informationen darüber, wie Sie dies in einem Treiberpaket erreichen. In den folgenden Tabellen finden Sie eine Kurzreferenz darüber, wann der Betriebssystem-Support für verschiedene Status-Management-APIs hinzugefügt wurde.
WDM-Treiber
Betriebssystem | Hinzugefügte Unterstützung |
---|---|
Windows 2000 | IoOpenDeviceRegistryKey IoOpenDeviceInterfaceRegistryKey |
Windows Vista | IoGetDevicePropertyData IoSetDevicePropertyData |
Windows 8 | IoGetDeviceInterfacePropertyData IoSetDeviceInterfacePropertyData |
Windows 8,1 | IoQueryFullDriverPath |
Windows 10 1803 | IoOpenDriverRegistryKey für RegKeyType von DriverRegKeyParameters und DriverRegKeyPersistentState IoGetDeviceDirectory IoGetDriverDirectory für DirectoryType von DriverDirectoryImage und DriverDirectoryData |
Windows 10 1809 | RtlQueryRegistryValueWithFallback |
Windows 11 21H2 | IoOpenDriverRegistryKey für RegKeyType von DriverRegKeySharedPersistentState IoGetDriverDirectory für DirectoryType von DriverDirectorySharedData |
KMDF-Treiber
UMDF-Treiber
Benutzermodus-Code
Betriebssystem | Hinzugefügte Unterstützung |
---|---|
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 |