Функция IoBuildAsynchronousFsdRequest (wdm.h)
Подпрограмма IoBuildAsynchronousFsdRequest выделяет и настраивает IRP для отправки драйверам более низкого уровня.
Синтаксис
__drv_aliasesMem PIRP IoBuildAsynchronousFsdRequest(
[in] ULONG MajorFunction,
[in] PDEVICE_OBJECT DeviceObject,
[in, out] PVOID Buffer,
[in, optional] ULONG Length,
[in, optional] PLARGE_INTEGER StartingOffset,
[in, optional] PIO_STATUS_BLOCK IoStatusBlock
);
Параметры
[in] MajorFunction
Код основной функции, задающейся в IRP. Этот код может быть IRP_MJ_PNP, IRP_MJ_READ, IRP_MJ_WRITE, IRP_MJ_FLUSH_BUFFERS или IRP_MJ_SHUTDOWN.
[in] DeviceObject
Указатель на объект устройства следующего ниже драйвера. Этот объект представляет целевое устройство для операций чтения, записи, очистки или завершения работы.
[in, out] Buffer
Указатель на буфер, в который считываются или из которого записываются данные. Значение этого аргумента равно NULL для запросов на очистку и завершение работы.
[in, optional] Length
Длина (в байтах) буфера, на который указывает буфер. Для таких устройств, как диски, это значение должно быть целым числом, кратным размеру сектора. Начиная с Windows 8 размер сектора может составлять 4096 или 512 байт. В более ранних версиях Windows размер сектора всегда составляет 512 байт. Этот параметр является обязательным для запросов на чтение и запись, но должен быть равен нулю для запросов на очистку и завершение работы.
[in, optional] StartingOffset
Указатель на начальное смещение на входном-выходном носителе. Значение этого аргумента равно нулю для запросов на очистку и завершение работы.
[in, optional] IoStatusBlock
Указатель на адрес блока состояния ввода-вывода, в котором вызываемые драйверы возвращают окончательное состояние запрошенной операции.
Возвращаемое значение
IoBuildAsynchronousFsdRequest возвращает указатель на IRP или указатель NULL , если IRP не может быть выделен.
Комментарии
Драйверы среднего или самого высокого уровня могут вызывать IoBuildAsynchronousFsdRequest для настройки IRP для запросов, отправляемых драйверам более низкого уровня. Вызывающий драйвер должен предоставить подпрограмму IoCompletion для IRP, чтобы его можно было освободить с помощью IoFreeIrp. Дополнительные сведения о освобождении IRP см. в разделе Примеры.
Создаваемый IRP содержит только достаточно сведений для начала операции и завершения IRP. Другие сведения о контексте не отслеживаются, так как асинхронный запрос не зависит от контекста.
Драйверы более низкого уровня могут накладывать ограничения на параметры, предоставляемые этой подпрограмме. Например, для драйверов дисков может потребоваться, чтобы значения , предоставленные для Length и StartingOffset , были целыми числами, кратными размеру сектора устройства.
Драйвер среднего или самого высокого уровня также может вызывать IoBuildDeviceIoControlRequest, IoAllocateIrp или IoBuildSynchronousFsdRequest для настройки запросов, отправляемых драйверам более низкого уровня. Только драйвер самого высокого уровня может вызывать IoMakeAssociatedIrp.
Во время вызова IoBuildAsynchronousFsdRequest диспетчер ввода-вывода задает элемент Tail.Overlay.Thread структуры IRP , чтобы он указывал на объект потока вызывающего объекта, но не принимает отсчетную ссылку на объект потока от имени вызывающего объекта. После того как вызывающий объект отправляет IRP драйверу для целевого устройства, этот драйвер может использовать член Tail.Overlay.Thread для доступа к объекту потока. Например, драйвер хранилища может вызвать подпрограмму IoSetHardErrorOrVerifyDevice и предоставить указатель на IRP в качестве входного параметра. Во время этого вызова IoSetHardErrorOrVerifyDevice использует член Tail.Overlay.Thread для доступа к объекту потока. Если доступ к объекту потока осуществляется таким образом, драйвер, который вызвал IoBuildAsynchronousFsdRequest для выделения IRP, отвечает за то, чтобы объект потока оставался действительным во время обработки IRP.
Чтобы сохранить допустимый объект потока, драйвер, вызывающий IoBuildAsynchronousFsdRequest , может принять отсчетную ссылку на объект потока перед отправкой IRP. Например, этот драйвер может вызывать подпрограмму ObReferenceObjectByPointerWithTag и предоставлять в качестве параметра Object указатель объекта из элемента Tail.Overlay.Thread структуры IRP . Позже подпрограмма завершения этого драйвера может разыменовать объект, вызвав подпрограмму , например ObDereferenceObjectWithTag.
Драйвер может вызвать IoBuildAsynchronousFsdRequest в одном потоке и отправить IRP, выделенный этим вызовом, в другой поток. Перед отправкой IRP этот драйвер должен задать элемент Tail.Overlay.Thread IRP, чтобы он указывал на объект потока для отправляющего потока. Как правило, драйвер вызывает подпрограмму PsGetCurrentThread , чтобы получить указатель на объект потока.
Драйверу, который вызывает IoBuildAsynchronousFsdRequest для выделения IRP, не обязательно требуется учитывать ссылку на объект потока, на который указывает элемент Tail.Overlay.Thread IRP. Вместо этого драйвер может использовать другой метод, гарантирующий, что этот объект потока остается действительным во время обработки IRP. Например, если драйвер создал поток, поток может ждать завершения IRP, чтобы завершить себя.
Примеры
Перед вызовом IoFreeIrp требуется дополнительный шаг для освобождения буфера для IRP, созданного IoBuildAsynchronousFsdRequest , если все верно:
Буфер был выделен из системного пула памяти.
В объекте устройства для целевого устройства флаг DO_DIRECT_IO устанавливается в поле DeviceObject-Flags>.
Поле Irp-MdlAddress> не равно NULL.
Перед освобождением буфера для этого IRP вызовите подпрограмму MmUnlockPages с Irp-MdlAddress> в качестве значения параметра. Этот вызов уменьшает количество дополнительных ссылок, добавленных IoBuildAsynchronousFsdRequest на страницы пула в MDL. В противном случае последующий вызов IoFreeMdl приведет к ошибке проверка, так как количество ссылок для этих страниц пула будет 2, а не 1. В следующем примере кода показаны вызовы MmUnlockPages, IoFreeMdl и IoFreeIrp для этого случая:
if (((DeviceObject->Flags & DO_DIRECT_IO) == DO_DIRECT_IO) &&
(Irp->MdlAddress != NULL))
{
MmUnlockPages(Irp->MdlAddress);
}
IoFreeMdl(Irp->MdlAddress);
IoFreeIrp(Irp);
Требования
Требование | Значение |
---|---|
Целевая платформа | Универсальное |
Верхняя часть | wdm.h (включая Wdm.h, Ntddk.h, Ntifs.h) |
Библиотека | NtosKrnl.lib |
DLL | NtosKrnl.exe |
IRQL | IRQL <= APC_LEVEL |
Правила соответствия DDI | ForwardedAtBadIrqlFsdAsync(wdm), HwStorPortProhibitedDDIs(storport), IoBuildFsdComplete(wdm), IoBuildFsdForward(wdm), IoBuildFsdFree(wdm) |