Сводка по подпрограммам диспетчеризации чтения и записи
При реализации подпрограмм DispatchRead, DispatchWrite или DispatchReadWrite учитывайте следующие моменты:
Драйвер самого высокого уровня в цепочке многоуровневых драйверов отвечает за проверка параметры входящих irps чтения и записи для допустимости перед настройкой расположения стека ввода-вывода драйвера следующего нижнего уровня в IRP.
Драйверы среднего и самого низкого уровня обычно могут полагаться на драйвер самого высокого уровня в своей цепочке для передачи запросов на передачу с допустимыми параметрами. Однако любой драйвер может выполнять проверку работоспособности параметров в расположении стека ввода-вывода IRP, и каждый драйвер устройства должен проверка параметры для условий, которые могут нарушать любые ограничения, накладываемые устройством.
Если подпрограмма DispatchReadWrite завершает IRP с ошибкой, она должна задать элемент состояния стека ввода-вывода с соответствующим значением типа NTSTATUS, задать элемент Information равным нулю и вызвать IoCompleteRequest с IRP и PriorityBoost IO_NO_INCREMENT.
Если драйвер использует буферизованное количество операций ввода-вывода, ему может потребоваться определить структуру, которая будет содержать передаваемые данные, и, возможно, потребуется внутренний буфер некоторых этих структур.
Если драйвер использует прямой ввод-вывод, может потребоваться проверка, описывает ли MDL в Irp-MdlAddress> буфер, содержащий слишком много данных (или слишком много разрывов страниц), для обработки базовым устройством в рамках одной операции передачи. В этом случае драйвер должен разделить исходный запрос на последовательность небольших операций передачи.
Тесно взаимосвязанный драйвер класса может разделить такой запрос в подпрограмме DispatchReadWrite для базового драйвера порта. Для этого требуются драйверы класса SCSI, особенно для запоминающих устройств. Дополнительные сведения о требованиях к драйверам SCSI см. в разделе Драйверы хранилища.
Подпрограмма DispatchReadWrite драйвера устройства нижнего уровня должна отложить разделение большого запроса на частичную передачу до тех пор, пока другая процедура драйвера не выпишет IRP для настройки устройства для передачи.
Если драйвер устройства более низкого уровня помещает IRP в очередь для чтения и записи для дальнейшей обработки собственными подпрограммами, он должен вызвать IoMarkIrpPending , прежде чем помещать IRP в очередь. Подпрограмма DispatchReadWrite также должна возвращать управление с STATUS_PENDING в этих случаях.
Если подпрограмма DispatchReadWrite передает IRP в более низкие драйверы, она должна настроить расположение стека ввода-вывода для следующего ниже драйвера в IRP. Указывает, устанавливает ли драйвер более высокого уровня подпрограмму IoCompletion в IRP перед его передачей с помощью IoCallDriver , зависит от структуры драйвера и элементов, наложенных на него.
Однако драйвер более высокого уровня должен вызывать IoSetCompletionRoutine перед вызовом IoCallDriver , если он выделяет какие-либо ресурсы, такие как IRP или память. Ее подпрограмма IoCompletion должна освободить все ресурсы, выделенные драйвером, когда более низкие драйверы выполнили запрос, но до того, как подпрограмма IoCompletion вызовет IoCompleteRequest с исходным IRP.
Если драйвер более высокого уровня выделяет IRP для более низких драйверов, которые могут включать базовый драйвер устройства со съемным носителем, выделяющий драйвер должен установить контекст потока в каждом IRP, который он выделяет.