Поделиться через


Создание драйверов экспорта

Драйвер экспорта — это библиотека DLL в режиме ядра, которая может быть загружена различными компонентами, зависящими от оборудования или устройства, но не имеет некоторых характеристик полного драйвера в режиме ядра. В частности, драйвер экспорта не содержит таблицу отправки, она не имеет места в стеке драйверов и не имеет записи в базе данных диспетчера управления службами, которая определяет ее как системную службу. Хотя драйвер экспорта не содержит таблицу отправки, она может предоставлять подпрограммы отправки стандартному драйверу. Стандартный драйвер вставляет подпрограммы диспетчера в собственную таблицу диспетчера. Драйвер экспорта имеет заглушку DriverEntry, которая никогда не вызывается.

Драйверы экспорта в режиме ядра особенно хорошо подходят для реализации части пары драйверов, независимо от базовых характеристик стека и оборудования.

Windows включает несколько драйверов экспорта, загруженных другими драйверами, например:

  • Драйвер порта SCSI
  • Драйвер класса ленты
  • Драйверы контроллера IDE являются поставляемыми системой драйверами экспорта.

Стандартные драйверы также могут функционировать как драйверы экспорта. Чтобы драйвер работал в обоих способах, он должен быть создан как драйвер экспорта и загружен в качестве обычного драйвера.

Создание драйвера экспорта

Чтобы создать драйвер экспорта в Visual Studio, используйте следующую процедуру:

  1. Создайте проект из шаблона, например Пустой драйвер WDM.
  2. Добавьте файл определения модуля в проект, например:
LIBRARY mydriver.sys
EXPORTS
  DllInitialize PRIVATE
  DllUnload PRIVATE

Точка входа для библиотеки DLL в режиме ядра всегда является DllInitialize. Система вызывает подпрограмму DLL в режиме ядра DllInitialize сразу после загрузки библиотеки DLL. Драйверы экспорта должны предоставлять подпрограммы DllInitialize . Подпрограмму DllInitialize можно использовать для получения или инициализации ресурсов, необходимых другим подпрограммам в библиотеке DLL.

Невозможно указать точку входа с помощью макроса DLLENTRY .

NTSTATUS DllInitialize(
  _In_ PUNICODE_STRING RegistryPath
);

RegistryPath — это указатель на подсчитанную строку Unicode, указывающую путь к разделу реестра DLL HKEY_LOCAL_MACHINE\CurrentControlSet\Services\DllName. Процедуры DLL могут использовать этот ключ для хранения информации, специфичной для этой DLL. Буфер, на который указывает RegistryPath, освобождается после выхода DllInitialize . Таким образом, если библиотека DLL использует ключ, dllInitialize должна дублировать имя ключа.

Процесс сборки создает библиотеку экспорта с расширением LIB и драйвером экспорта с расширением .sys.

Импорт функций из драйвера экспорта

Чтобы импортировать функции, экспортированные драйвером экспорта, следует объявить функции с помощью макроса DECLSPEC_IMPORT, который определен в Ntdef.h. Рассмотрим пример.

DECLSPEC_IMPORT int LoadPrinterDriver (int arg1); 

Этот макрос разрешает объявление класса хранилища __declspec(dllimport) на этих платформах, где требуется и не требуется ничего на этих платформах.

В драйвере экспорта экспортируемая функция должна быть объявлена с помощью макроса DECLSPEC_EXPORT. Этот макрос преобразуется в объявление класса памяти __declspec(dllexport) на тех платформах, где это требуется, и игнорируется на тех платформах, где это не требуется. Если драйвер экспорта предоставляет подпрограмму отправки стандартному драйверу, эта подпрограмма не должна быть экспортирована.

Загрузка и выгрузка драйвера экспорта

Драйверы экспорта должны быть установлены в каталоге %Windir%\System32\Drivers. Начиная с Windows 2000 операционная система сохраняет количество ссылок, указывающее количество случаев импорта функций драйвера экспорта другими драйверами. Система уменьшает это число каждый раз, когда один из импортируемых драйверов выгружается. Когда число ссылок падает до нуля, система выгрузит драйвер экспорта. Однако драйвер экспорта должен содержать стандартную точку входа и выгружающие подпрограммы, DllInitialize и DllUnload, иначе операционная система не активирует этот механизм подсчета ссылок.

Система вызывает подпрограмму DllUnload модуля DLL, работающего в режиме ядра, при его выгрузке.

NTSTATUS DllUnload(void);

Драйверы экспорта должны предоставлять подпрограммы DllUnload. Подпрограмму DllUnload можно использовать для освобождения всех ресурсов, используемых подпрограммами в библиотеке DLL.