Поделиться через


Создание irP для драйверов Lower-Level

Чтобы выделить IRP для асинхронного запроса, который будет обрабатываться в произвольном контексте потока более низкими драйверами, подпрограмма DispatchReadWrite может вызвать одну из следующих процедур поддержки:

  • IoAllocateIrp, который выделяет IRP и ряд расположений стека ввода-вывода с нулевой инициализацией.

    Подпрограмма диспетчеризации должна настроить расположение стека ввода-вывода следующего ниже драйвера для только что выделенного IRP, как правило, путем копирования (возможно, измененных) сведений из собственного расположения стека в исходном IRP. Если драйвер более высокого уровня выделяет собственное расположение стека ввода-вывода для только что выделенного IRP, подпрограмма диспетчеризации может настроить там сведения контекста для каждого запроса для использования подпрограммой IoCompletion .

  • IoBuildAsynchronousFsdRequest, который настраивает расположение стека ввода-вывода следующего ниже драйвера для вызывающего объекта в соответствии с параметрами, заданными вызывающим объектом.

    Драйверы более высокого уровня могут вызывать эту подпрограмму для выделения irP для запросов IRP_MJ_READ, IRP_MJ_WRITE, IRP_MJ_FLUSH_BUFFERS и IRP_MJ_SHUTDOWN запросов.

    Когда для такого IRP вызывается подпрограмма IoCompletion, она может проверка блок состояния ввода-вывода и при необходимости (или возможно) настроить расположение стека ввода-вывода следующего ниже драйвера в IRP и повторить запрос или повторно использовать его. Однако подпрограмма IoCompletion не имеет локального хранилища контекста в IRP, поэтому драйвер должен поддерживать контекст исходного запроса в другом месте в постоянной памяти.

  • IoMakeAssociatedIrp, который выделяет IRP и несколько расположений стека ввода-вывода с нулевой инициализацией и связывает его с master IRP.

    Промежуточные драйверы не могут вызывать IoMakeAssociatedIrp для создания irP для более низких драйверов.

    Любой драйвер самого высокого уровня, вызывающий IoMakeAssociatedIrp для создания irP для более низких драйверов, может вернуть управление диспетчеру ввода-вывода после отправки связанных поставщиков irP в и вызова IoMarkIrpPending для исходного, master IRP. Драйвер самого высокого уровня может полагаться на диспетчер ввода-вывода для выполнения master IRP, когда все связанные irP были завершены более низкими драйверами.

    Драйверы редко задают подпрограмму IoCompletion для связанного IRP. Если драйвер самого высокого уровня вызывает IoSetCompletionRoutine для связанного IRP, который он создает, диспетчер ввода-вывода не завершает master IRP, если драйвер возвращает STATUS_MORE_PROCESSING_REQUIRED из своей процедуры IoCompletion. В таких случаях подпрограмма IoCompletion драйвера должна явно завершить master IRP с помощью IoCompleteRequest.

Если драйвер выделяет собственное расположение стека ввода-вывода в новом IRP, подпрограмма диспетчеризации должна вызвать IoSetNextIrpStackLocation , прежде чем вызывать IoGetCurrentIrpStackLocation , чтобы настроить контекст в собственном расположении стека ввода-вывода для подпрограммы IoCompletion . Дополнительные сведения см. в разделе Обработка IRP в драйвере Intermediate-Level.

Подпрограмма диспетчеризации должна вызывать IoMarkIrpPending с исходным IRP, но не с выделенными драйверами IRP, так как процедура IoCompletion освободит их.

Если подпрограмма диспетчеризации выделяет irP для частичной передачи, а базовый драйвер устройства может управлять устройством со съемным носителем, подпрограмма диспетчеризации должна настроить контекст потока в новых выделенных irPs из значения Tail.Overlay.Thread в исходном IRP.

Базовый драйвер для устройства со съемным носителем может вызывать IoSetHardErrorOrVerifyDevice, который ссылается на указатель на Irp-Tail.Overlay.Thread> для выделенного драйвером IRP. Если драйвер вызывает эту подпрограмму поддержки, драйвер файловой системы может отправить диалоговое окно в соответствующий поток пользователя, который предлагает пользователю отменить, повторить или завершить операцию, которую драйвер не может удовлетворить. Дополнительные сведения см. в разделе Поддержка съемных носителей .

Подпрограммы диспетчеризации должны возвращать STATUS_PENDING после отправки всех выделенных драйверами IRP в более низкие драйверы.

Подпрограмма IoCompletion драйвера должна освободить все выделенные драйвером IRP с помощью IoFreeIrp , прежде чем вызывать IoCompleteRequest для исходного IRP. После завершения исходного IRP подпрограмма IoCompletion должна освободить все выделенные драйвером IRP, прежде чем она возвращает управление.

Каждый драйвер более высокого уровня настраивает все выделенные (и повторно использованные) irP для более низких драйверов таким образом, что базовому драйверу устройства не имеет значения, поступает ли данный запрос от промежуточного драйвера или из любого другого источника, например файловой системы или приложения в пользовательском режиме.

Драйверы самого высокого уровня могут вызывать IoMakeAssociatedIrp , чтобы выделить IRP и настроить их для цепочки более низких драйверов. Диспетчер операций ввода-вывода автоматически завершает исходный IRP после завершения всех связанных с ним irP, если драйвер не вызывает IoSetCompletionRoutine с исходным IRP или с любыми связанными irp, которые он выделяет. Однако драйверы самого высокого уровня не должны выделять связанные irP для любых IRP, запрашивающих операцию буферизованного ввода-вывода.

Драйвер среднего уровня не может выделить IRP для драйверов более низкого уровня, вызвав IoMakeAssociatedIrp. Любой IRP, получаемый промежуточным драйвером, уже может быть связанным IRP, и драйвер не может связать другое IRP с таким IRP.

Вместо этого, если промежуточный драйвер создает irP для более низких драйверов, он должен вызывать IoAllocateIrp, IoBuildDeviceIoControlRequest, IoBuildSynchronousFsdRequest или IoBuildAsynchronousFsdRequest. Однако ioBuildSynchronousFsdRequest можно вызывать только в следующих случаях:

  • Создаваемым драйвером потоком для создания IRP для запросов на чтение или запись, так как такой поток может ожидать в контексте неарбитарного потока (собственного) объекта диспетчера, например инициализированного драйвером события, переданного в IoBuildSynchronousFsdRequest.

  • В контексте системного потока во время инициализации или во время выгрузки

  • Создание irP для синхронных операций, таких как создание, очистка, завершение работы, закрытие и запросы на управление устройством

Однако драйвер с большей вероятностью вызывает IoBuildDeviceIoControlRequest для выделения irp управления устройствами, чем IoBuildSynchronousFsdRequest.