Erstellen von Exporttreibern

Ein Exporttreiber ist eine Kernelmodus-DLL, die von einer Vielzahl anderer hardwarespezifischer oder gerätestapelspezifischer Komponenten geladen werden kann, aber nicht über einige der Merkmale eines vollständigen Kernelmodustreibers verfügt. Insbesondere verfügt ein Exporttreiber nicht über eine Dispatchtabelle, er hat keinen Platz im Treiberstapel und keinen Eintrag in der Datenbank des Dienststeuerungs-Managers, der ihn als Systemdienst definiert. Ein Exporttreiber verfügt zwar nicht über eine Dispatchtabelle, kann aber Dispatchroutinen für einen Standardtreiber bereitstellen. Der Standardtreiber fügt die Dispatchroutinen in eine eigene Dispatchtabelle ein. Ein Exporttreiber verfügt über eine Stub-DriverEntry-Routine , die nie aufgerufen wird.

Exporttreiber im Kernelmodus eignen sich besonders gut für die Implementierung des Teils eines Treiberpaars, der von den zugrunde liegenden Stapel- und Hardwaremerkmalen unabhängig ist.

Windows enthält mehrere Exporttreiber, die von anderen Treibern geladen werden, z. B.:

  • SCSI-Porttreiber
  • Bandklassentreiber
  • IDE-Controllertreiber sind alle vom System bereitgestellten Exporttreiber.

Standardtreiber können auch als Exporttreiber fungieren. Damit ein Treiber auf beide Arten funktioniert, muss er als Exporttreiber erstellt und als regulärer Treiber geladen werden.

Erstellen eines Exporttreibers

Gehen Sie wie folgt vor, um einen Exporttreiber in Visual Studio zu erstellen:

  1. Erstellen Sie ein neues Projekt aus einer Vorlage, z. B . Leerer WDM-Treiber.
  2. Fügen Sie dem Projekt eine Moduldefinitionsdatei hinzu, z. B.:
LIBRARY mydriver.sys
EXPORTS
  DllInitialize PRIVATE
  DllUnload PRIVATE

Der Einstiegspunkt für eine Kernelmodus-DLL ist immer DllInitialize. Das System ruft die DllInitialize-Routine einer Kernelmodus-DLL sofort nach dem Laden der DLL auf. Exporttreiber müssen DllInitialize-Routinen bereitstellen. Sie können die DllInitialize-Routine verwenden, um Ressourcen zu erhalten oder zu initialisieren, die für andere Routinen in der DLL erforderlich sind.

Sie können den Einstiegspunkt nicht mithilfe des DLLENTRY-Makros angeben.

NTSTATUS DllInitialize(
  _In_ PUNICODE_STRING RegistryPath
);

RegistryPath ist ein Zeiger auf eine gezählte Unicode-Zeichenfolge, die den Pfad zum Registrierungsschlüssel der DLL angibt,HKEY_LOCAL_MACHINE\CurrentControlSet\Services\DllName. DLL-Routinen können diesen Schlüssel verwenden, um DLL-spezifische Informationen zu speichern. Der Puffer, auf den registryPath verweist, wird freigegeben, sobald DllInitialize beendet wird. Wenn die DLL den Schlüssel verwendet, muss DllInitialize daher den Schlüsselnamen duplizieren.

Der Buildprozess generiert eine Exportbibliothek mit einer LIB-Erweiterung und einen Exporttreiber mit einer .sys-Erweiterung.

Importieren von Funktionen aus einem Exporttreiber

Um Funktionen zu importieren, die von einem Exporttreiber exportiert werden, sollten Sie die Funktionen mithilfe des makros DECLSPEC_IMPORT deklarieren, das in Ntdef.h definiert ist. Beispiel:

DECLSPEC_IMPORT int LoadPrinterDriver (int arg1); 

Dieses Makro wird in eine __declspec(dllimport)-Speicherklassendeklaration auf diesen Plattformen aufgelöst, sofern erforderlich, und auf diesen Plattformen, falls nicht erforderlich, in nichts.

Im Exporttreiber sollte die zu exportierende Funktion mit dem makro "DECLSPEC_EXPORT" deklariert werden. Dieses Makro wird auf diesen Plattformen in eine __declspec(dllexport)-Speicherklassendeklaration aufgelöst, falls erforderlich, und auf diesen Plattformen, falls nicht erforderlich, in nichts. Wenn ein Exporttreiber eine Dispatchroutine an einen Standardtreiber liefert, muss diese Routine nicht exportiert werden.

Laden und Entladen eines Exporttreibers

Exporttreiber müssen im Verzeichnis %Windir%\System32\Drivers installiert sein. Ab Windows 2000 behält das Betriebssystem eine Referenzanzahl bei, die angibt, wie oft die Funktionen des Exporttreibers von anderen Treibern importiert wurden. Das System verringert diese Anzahl, wenn einer der importierenden Treiber entladen wird. Wenn die Verweisanzahl auf 0 (null) fällt, entlädt das System den Exporttreiber. Der Exporttreiber muss jedoch den Standardeinstiegspunkt und die Entladeroutinen DllInitialize und DllUnload enthalten, andernfalls aktiviert das Betriebssystem diesen Verweisanzahlmechanismus nicht.

Das System ruft die DllUnload-Routine einer Kernelmodus-DLL auf, wenn die DLL entladen wird.

NTSTATUS DllUnload(void);

Exporttreiber müssen DllUnload-Routinen bereitstellen. Sie können die DllUnload-Routine verwenden, um alle Ressourcen freizugeben, die von den Routinen in der DLL verwendet werden.