Диспетчерские точки входа драйвера
Информация, требуемая для выполнения запроса ввода/вывода, содержится в различных элементах как фиксированной части IRP, так и стека размещения ввода/вывода. Рассмотрим эти элементы. Структура поля Parameters в стеке размещения ввода/ вывода зависит от кода главной и второстепенной функции ввода/вывода.
Нас в основном будет интересовать структура поля Parameters для запросов чтения, записи и пользовательских запросов ввода/вывода:
- IRPJVIJ_READ. Параметры для этого функционального кода содержат следующее:
- Parameters.Read.Length (ULONG) содержит размер в байтах буфера инициатора запроса.
- Parameters. Read.Key (ULONG) содержит ключевое значение, которое нужно использовать при чтении. Обычно представляет интерес только для драйверов файловой системы.
- Parameters.Read.ByteOfFset (LARGE_INTEGER) содержит смещение (обычно в файле), с которого должна начаться операция чтения.
- IRP_MJ_WRITE. Параметры для этого функционального кода следующие:
- Parameters. Write.Length (ULONG) содержит размер в байтах буфера инициатора запроса.
- Parameters.Write.Key (ULONG) содержит ключевое значение, которое нужно использовать при записи. Обычно представляет интерес только для драйверов файловой системы.
- Parameters.Write.ByteOffset (LARGE_INTEGER) содержит смещение (обычно в файле) с которого должна начаться операция записи.
- IRPJMJ_DEVICE_CONTROL. Параметры для этого функционального кода следующие:
- Parameters.DeviceloControl.OutputBufferLength (ULONG) содержит длину в байтах буфера OutBuffer.
- Parameters.DeviceloControl.InputBufferLength (ULONG) содержит длину в байтах буфера InBuffer.
- Parameters. DeviceloControl.ControlCode (ULONG) содержит код управления вводом/выводом, идентифицирующий запрашиваемую функцию управления устройством. Этот управляющий код обычно предварительно определен драйвером с использованием макрокоманды CTL_CODE.
- Parameters.DeviceloControl.TypeSInputBuffer (PVOID) содержит виртуальный адрес буфера инициатора запроса InBuffer (см. функцию Win32 API DeviceloControl()). Адрес обычно используется только тогда, когда IOCTL использует METHOD_NEITHER.
Запросы чтения и записи IRP_MJ_READ и IRPJVLMVRITE
Метод передачи буфера, используемый в запросах чтения и записи, контролируется полем Flags объекта-устройства. После создания объекта-устройства с помощью функции loCreateDevice() необходимо инициализировать это поле. Поле может иметь установленными несколько флагов, при этом применяются следующие правила:
- Если установлены флаги DO_BUFFERED_IO или DO_DIRECT_IO, метод передачи буфера будет соответственно буферизованным или прямым.
- Если поле флагов не инициализировано (никакие флаги не установлены), используется метод передачи буфера Neither ("никакой" ввода/вывода).
- Одновременная установка флагов DO_BUFFERED_IO и DO_DIRECT_IO запрещена и будет являться ошибкой.
- Установленный полем Flags метод передачи будет использован и запросом чтения, и запросом записи.
Расположение буфера в зависимости от метода его передачи для запросов чтения и записи полностью определяется таблицей 6.
Для завершения запроса IRP на чтение/запись, необходимо установить поле Irp>IoStatus.Information равным числу прочитанных/записанных в буфер байт. В случае буферизованного ввода/вывода это поле укажет Диспетчеру ввода/вывода, сколько байт нужно скопировать из промежуточного буфера в невыгружаемой области системного адресного пространства в пользовательский буфер.
Пример обработки запросов чтения/записи
Данный пример обработки запросов чтения/записи демонстрирует получение адреса буфера для чтения/записи и его длины. Такой код вставляется в обработчик диспетчерских функций MajorFunction[IRP__MJ_READ], MajorFuriction[IRP_MJ_WRITE].
//получение адреса буфера для чтения/записи //в случае буферизованного ввода/вывода BufferAddress = Irp › AssociatedIrp.SystemBuffer/ //в случае прямого ввода/вывода BufferAddress = MmGetSystemAddressForMdl(Irp › MdlAddress)/ //в случае Neither i/o BufferAddress = Irp › AssociatedIrp.UserBuffer; //получение длины буфера для чтения/записи stack = = loGetCurrentlrpStackLocation (Irp); BufferLength = stack › Parameters.Read.Length;