Создание драйверов экспорта
Драйвер экспорта — это библиотека DLL в режиме ядра, которая может быть загружена различными компонентами, зависящими от оборудования или стека устройства, но не имеет некоторых характеристик полного драйвера в режиме ядра. В частности, драйвер экспорта не имеет таблицы диспетчера, не имеет места в стеке драйверов и не имеет записи в базе данных диспетчера управления службами, определяющей его как системную службу. Хотя драйвер экспорта не имеет таблицы диспетчеризации, он может предоставлять подпрограммы диспетчеризации стандартному драйверу. Стандартный драйвер вставляет подпрограммы диспетчеризации в собственную таблицу диспетчеризации. Драйвер экспорта имеет подпрограмму DriverEntry, которая никогда не вызывается.
Драйверы экспорта в режиме ядра особенно хорошо подходят для реализации части пары драйверов, которая не зависит от базовых характеристик стека и оборудования.
Windows включает несколько драйверов экспорта, которые загружаются другими драйверами, например:
- Драйвер порта SCSI
- Драйвер класса ленты
- Драйвер контроллера интегрированной среды разработки — это драйверы экспорта, предоставляемые системой.
Стандартные драйверы также могут работать в качестве драйверов экспорта. Чтобы драйвер функционировал в обоих случаях, он должен быть построен как драйвер экспорта и загружен как обычный драйвер.
Создание драйвера экспорта
Чтобы создать драйвер экспорта в Visual Studio, выполните следующую процедуру:
- Создайте проект на основе шаблона, например Пустой драйвер WDM.
- Добавьте в проект файл определения модуля, например:
LIBRARY mydriver.sys
EXPORTS
DllInitialize PRIVATE
DllUnload PRIVATE
Точкой входа для библиотеки DLL в режиме ядра всегда является DllInitialize. Система вызывает подпрограмму DllInitialize в режиме ядра сразу после загрузки библиотеки DLL. Драйверы экспорта должны предоставлять подпрограммы DllInitialize . Вы можете использовать подпрограмму DllInitialize для получения или инициализации ресурсов, необходимых другим подпрограммам в библиотеке DLL.
Невозможно указать точку входа с помощью макроса DLLENTRY .
NTSTATUS DllInitialize(
_In_ PUNICODE_STRING RegistryPath
);
RegistryPath — это указатель на подсчитываемую строку Юникода, указывающую путь к разделу реестра БИБЛИОТЕКи 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.