1.9 Работа с реестром в режиме ядра
Работа с реестром из драйвера уровня ядра необходима, так как именно в системном реестре хранится информация о настройках протоколирования. Информация о настройках хранится в ключе реестра, связанном с устройством, к которому подключается драйвер-фильтр. Имя этого устройства соответствует шаблону HKEY_LOCAL_MACHINE\System\CurrentControlSet\Enum\USB\XXX\XXX\DeviceParameters.
Доступ ключу устройства в реестре в драйвере предоставляется функцией IoOpenDeviceRegistryKey. Перечислим ее параметры:
Таблица 1.9.1. Параметры функции IoOpenDeviceRegistry
Тип параметра | Описание параметра |
IN PDEVICE_OBJECT DeviceObject | Указатель на объект физического устройства, ключ которого должен быть открыт |
IN ULONG DevInstKeyType | Параметр определяющий, связан ли открываемый ключ непосредственно с физ. устройством или его программным обеспечением |
IN ACCESS_MASK DesiredAccess | Этот параметр определяет права доступа к ключу |
OUT PHANDLE DevInstRegKey | Указатель на переменную, куда следует поместить дескриптор открытого ключа |
Открыв основной ключ, следует получить доступ к вложенному в него ключу с параметрами протоколирования. Для этого используется функция ZwOpenKey. Перечислим ее параметры:
Таблица 1.9.2. Параметры функции ZwOpenKey
Тип параметра | Описание параметра |
OUT PHANDLE KeyHandle | Указатель на переменную, куда следует поместить дескриптор открытого ключа |
IN ACCESS_MASK DesiredAccess | Этот параметр определяет права доступа к ключу |
IN POBJECT_ATTRIBUTES pObjectAttributes | Указатель на заполненную вызывающим кодом структуру данных, которая при использовании в данной функции должна содержать имя открываемого ключа |
Открыв ключ собственных параметров драйверу необходимо считать настройки протоколирования. Для чтения значения параметров ключа реестра используется функция ZwQueryValueKey. Перечислим ее параметры:
Таблица 1.9.3. Параметры функции ZwQueryValueKey
Тип параметра | Описание параметра |
IN HANDLE KeyHandle | Дескриптор ключа, которому принадлежит считываемый параметр |
IN PUNICODE_STRING ValueName | Строка юникод-символов, содержащая имя параметра ключа |
IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass | Этот параметр принимает одно их трех значений в зависимости от полноты информации о параметре: KeyValueBasicInformation KeyValueFullInformation KeyValuePartialInformation |
OUT PVOID KeyInformation | Указатель на буфер, выделенный вызывающим кодом, в который должна быть помещена запрашиваемая информация |
IN ULONG Length | Длина предоставленного буфера |
OUT PULONG ResultLength | Указатель на переменную, содержащую число реально записанных в KeyInformation байт |
После того, как работа с ключом реестра закончена, его дескриптор следует освободить вызовом функции ZwClose.
1.10 MDL‑списки
MDL‑список – это структура, хранящая отображение блока виртуальной памяти на физическую память. MDL‑список используется в разрабатываемом драйвере для хранения информации из URB‑пакетов, связанных с вводом / выводом USB‑устройства. Кроме того, обмен информацией с USB‑устройством в режиме прямого доступа к памяти ведется именно посредством MDL‑списков.
Перед использовании MDL‑списка в драйвере необходимо провести ряд подготовительных действий:
· выделить область в страничной памяти с помощью вызова функции
ExAllocatePool;
· вызвать функцию MmCreateMdl, создающую и инициализирующую MDL‑список;
· выполнить фиксацию страниц, описанных в MDL‑списке, в физической памяти с помощью вызова функции MmProbeAndLockPages.
После завершения использования MDL‑списка его следует освободить:
· отменить фиксацию страниц страничной памяти в оперативной памяти вызовом функции MmUnlockPages;
· очистить MDL‑список, вызвав функцию IoFreeMdl;
· освободить выделенную под список страничную память вызовом
ExFreePool.
2. Конструкторский раздел
2.1 Точки входа разрабатываемого драйвера
Разрабатываемый драйвер является драйвером нижнего уровня. В стеке драйверов USB‑накопителя он находится непосредственно под драйвером устройства, если после его загрузки не произойдет установки какого-либо другого драйвера-фильтра нижнего уровня.
Разрабатываемый драйвер включает в себя следующие точки входа:
· DriverEntry;
· AddDevice;
· DriverUnload;
· Функции обработки IRP‑пакетов:
· обработка IRP‑пакетов с кодами IRP_MJ_INTERNAL_DEVICE_CONTROL – функция DispatchInternalDeviceControl;
· обработка IRP пакетов с прочими кодами – функция DispatchRoutine.
Рассмотрим каждую из них более подробно.
2.1.1 Функция DriverEntry
В этой функции происходит регистрация всех стандартных точек входа драйвера и обработчиков IRP‑пакетов. В разрабатываемом драйвере пакеты IRP c кодами, не равными IRP_MJ_INTERNAL_DEVICE_CONTROL обрабатываются функцией DispatchRoutine.
2.1.2 Функция AddDevice
Управление этой функции передается диспетчером ввода / вывода после того, как завершает свою работу DriverEntry. AddDevice создает функциональный объект устройства с помощью вызова IoCreateDevice и подключает его к стеку драйверов выбранного устройства (вызовом IoAttachDeviceToDeviceStack). Кроме того, в этой функции производятся действия по подготовке к протоколированию: считываются настройки из системного реестра, выделяется буфер для сбора протоколируемой информации, создается лог-файл.
... системы и их особенностями в целом, мы разобрались, теперь самое время приступить к более детальному, конкретному рассмотрению многообразия ОС, которое обычно начинается с рассмотрения краткой истории появления и развития. Операционная система Unix Считается, что в появлении Юникса в частности виновата... компьютерная игра. Дело в том, что Кен Томпсон непонятно чего ради создал игрушку «Space ...
0 комментариев