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


Регистрация процедуры IoCompletion

Чтобы зарегистрировать подпрограмму IoCompletion , подпрограмма диспетчеризации вызывает IoSetCompletionRoutine, предоставляя адрес подпрограммы IoCompletion и IRP, которые затем будут передаваться в более низкие драйверы с помощью IoCallDriver.

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

Цель процедуры IoCompletion — отслеживать, что драйверы более низкого уровня делали с IRP, и выполнять дополнительную обработку завершения, если это необходимо. В частности, ниже перечислены наиболее распространенные способы использования процедур IoCompletion драйвера.

  • Удаление IRP, выделенного драйвером с помощью IoAllocateIrp или IoBuildAsynchronousFsdRequest

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

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

  • Повторная попытка запроса, завершаемого драйвером более низкого уровня с ошибкой

    Драйверы самого высокого уровня, такие как файловые системы, скорее всего, имеют подпрограммы IoCompletion , которые пытаются повторить запросы, чем промежуточные драйверы, за исключением драйверов классов, размещенных над тесно связанных драйверов портов. Однако любой промежуточный драйвер использует подпрограммы IoCompletion для повторных запросов.

В то время как подпрограмма DispatchReadWrite самого высокого или промежуточного уровня драйвера, скорее всего, обрабатывает irp, для которых требуется процедура IoCompletion , любая подпрограмма диспетчеризации в любом драйвере, который передает irP в более низкие драйверы, может зарегистрировать подпрограмму IoCompletion .

Для поставщиков irP, выделенных драйвером, и повторно используемых поставщиков интеграции подпрограмма диспетчеризации должна вызывать IoSetCompletionRoutine со следующими логическими параметрами:

  • Параметр InvokeOnSuccess имеет значение TRUE.

  • Параметр InvokeOnError имеет значение TRUE.

  • Параметр InvokeOnCancel имеет значение TRUE , если какой-либо более низкий драйвер в цепочке может обрабатывать отменяемые irP.

    Обычно параметру InvokeOnCancel присваивается значение TRUE, независимо от того, может ли возвращаться IRP с STATUS_CANCELLED, чтобы гарантировать, что подпрограмма IoCompletion освобождает все выделенные драйвером IRP или проверяет состояние завершения каждого повторного использования IRP.

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

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

  • Подпрограмма диспетчеризации должна вызывать IoSetCompletionRoutine со всеми параметрами InvokeOnXxx для выделенных им параметров IRP.

Подпрограмма диспетчеризации, которая повторно использует irP для последовательности операций или выполняет повторную операцию ввода-вывода, должна вызывать IoSetCompletionRoutine для каждого IRP, который будет использоваться повторно или повторно использоваться.

  • Подпрограмма диспетчеризации должна сохранять сведения о состоянии исходного IRP для последующего использования подпрограммой IoCompletion .

    Например, подпрограмма DispatchReadWrite должна сохранить соответствующие параметры передачи входного IRP для процедуры IoCompletion перед настройкой частичной передачи для следующего ниже драйвера в этом IRP. Сохранение параметров особенно важно, если подпрограмма DispatchReadWrite изменяет любые параметры, необходимые подпрограмме IoCompletion , чтобы определить, когда был выполнен исходный запрос.

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

  • При повторном использовании IRP подпрограмма диспетчеризации должна вызывать IoSetCompletionRoutine со всеми параметрами InvokeOnXxx, равными TRUE.

  • Для асинхронного запроса подпрограмма диспетчеризации любого промежуточного драйвера должна вызывать IoMarkIrpPending для исходного IRP. Затем он должен вернуть STATUS_PENDING после отправки IRP в более низкие драйверы.