Диспетчерские точки входа драйвера
При использовании метода METHOD_NEITHER, оба буфера передаются в соответствии с методом Neither. То есть, не производится проверка доступности памяти, не выделяются промежуточные буфера и не создаются MDL. В пакете IRP передаются виртуальные адреса буферов в пространстве памяти инициатора запроса ввода/вывода. Адрес буфера OutBuffer передается в фиксированной части IRP в поле Irp › UserBuffer, адрес буфера InBuffer передается в стеке размещения ввода/вывода в поле stack › Parameters.DeviceControl.Type3InputBuffer.
Положение буферов показано в таблице 7.
Таблица 7. Положение буферов.
METHOD BUFFERED | METHOD IN DIRECT | METHOD OUT DIRECT | METHOD NEITHER | ||
InBuffer | Метод передачи | Buffered I/O | Buffered I/O | Buffered I/O | Виртуальный адрес инициатора запроса |
Если существует, то где расположен | Адрес промежуточного буфера в фиксированной части IRP в поле Irp › AssociatedIrp.SystemBuffer | В стеке размещения ввода/вывода виртуальный адрес инициатора запроса в Parame ters.DeviceloControl. TypeSInputBuffer | |||
Длина | Длина в байтах в поле Parameters.DeviceloControl.InputBuffer Length в текущем стеке размещения ввода/вывода. | ||||
Out Buffer | Метод передачи | Buffered I/O | Direct I/O | Direct I/O | Виртуальный адрес инициатора запроса |
Если существует, то где расположен | Адрес промежуточного буфера в фиксированной части IRP в поле Irp › Associate-dlrp.SystemB uffer | MDL, адрес в Irp › MdlAd – dress | MDL, адрес в Irp › MdlAd – dress | Виртуальный адрес инициатора запроса в Irp › UserBuffer | |
Длина | Длина в байтах в поле Parameters.DeviceloControl.OutputBufferLength в текущем стеке размещения ввода/вывода. |
Для завершения запроса IRP необходимо установить поле Irp › IoStatus.Information равным числу прочитанных/записанных в буфер байт. В случае буферизованного ввода/вывода это поле укажет Диспетчеру ввода/вывода, сколько байт нужно скопировать из промежуточного буфера в невыгружаемой области системного адресного пространства в пользовательский буфер.
Пример обработки
Пример получения адресов и длин буферов в диспетчерской функции драйвера, обрабатывающей функциональные коды IRP_MJ_CREATE, IRP_MJ_CLOSE и IRP_MJ_DEVICE_CONTROL:
stack = loGetCurrentlrpStackLocation (Irp); switch (pIrpStack › MajorFunction) { case IRP_MJ_CREATE: case IRP_MJ_CLOSE: break; case IRP_MJ_DEVICE_CONTROL: switch (stack › Parameters.DeviceloControl.loControlCode) { case IOCTL_MY_BUFFERED: InBuffer = Irp › AssociatedIrp.SystemBuffer; InLength = stack › Parameters.DeviceloControl.InputBuffer.Length; OutBuffer = Irp › AssociatedIrp.SystemBuffer; OutLength = stack › Parameters.DeviceloControl.OutputBufferLength; case IOCTL_MY_IN_DIRECT: //OutBuffer доступен только для чтения InBuffer = Irp › AssociatedIrp.SystemBuffer; InLength = stack › Parameters.DeviceloControl.InputBufferLength; OutBuffer = MmGetSystemAddressForMdl(Irp › MdlAddress); OutLength = stack › Parameters.DeviceloControl.OutputBufferLength; break; case IOCTL_MY_OUT_DIRECT: //OutBuffer доступен для чтения/записи InBuffer = Irp › AssociatedIrp.SystemBuffer; InLength = stack › Parameters.DeviceloControl.InputBufferLength; OutBuffer = MmGetSystemAddressForMdl(Irp › MdlAddress ); OutLength = stack › Parameters.DeviceloControl.OutputBufferLength; break; case IOCTL_MY_NEITHER: InBuffer = irpStack › Parameters.DeviceloControl.Type3InputBuffer; InLength = irpStack › Parameters.DeviceIoControl.InputBufferLength; OutBuffer = Irp › UserBuffer; OutLength = irpStack › Parameters.Device!oControl.OutputBufferLength; break;