Función IoBuildAsynchronousFsdRequest (wdm.h)

La rutina IoBuildAsynchronousFsdRequest asigna y configura un IRP que se enviará a controladores de nivel inferior.

Sintaxis

__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
);

Parámetros

[in] MajorFunction

El código de función principal que se va a establecer en irP. Este código puede ser IRP_MJ_PNP, IRP_MJ_READ, IRP_MJ_WRITE, IRP_MJ_FLUSH_BUFFERS o IRP_MJ_SHUTDOWN.

[in] DeviceObject

Puntero al objeto de dispositivo del controlador inferior siguiente. Este objeto representa el dispositivo de destino para la operación de lectura, escritura, vaciado o apagado.

[in, out] Buffer

Puntero a un búfer en el que se leen datos o desde los que se escriben los datos. El valor de este argumento es NULL para las solicitudes de vaciado y apagado.

[in, optional] Length

Longitud, en bytes, del búfer al que apunta buffer. Para dispositivos como discos, este valor debe ser un número entero múltiplo del tamaño del sector. A partir de Windows 8, el tamaño del sector puede ser de 4096 o 512 bytes. En versiones anteriores de Windows, el tamaño del sector siempre es de 512 bytes. Este parámetro es necesario para las solicitudes de lectura y escritura, pero debe ser cero para las solicitudes de vaciado y apagado.

[in, optional] StartingOffset

Puntero al desplazamiento inicial en el medio de entrada y salida. El valor de este argumento es cero para las solicitudes de vaciado y apagado.

[in, optional] IoStatusBlock

Puntero a la dirección de un bloque de estado de E/S en el que los controladores a los que se llama devuelven el estado final sobre la operación solicitada.

Valor devuelto

IoBuildAsynchronousFsdRequest devuelve un puntero a un IRP o un puntero NULL si no se puede asignar el IRP.

Comentarios

Los controladores intermedios o de nivel superior pueden llamar a IoBuildAsynchronousFsdRequest para configurar IRP para las solicitudes enviadas a controladores de nivel inferior. El controlador de llamada debe proporcionar una rutina de IoCompletion para irP, por lo que el IRP se puede desasignar con IoFreeIrp. Para obtener más información sobre la desasignación de IRP, vea Ejemplos.

El IRP que se compila contiene solo suficiente información para iniciar la operación y completar el IRP. No se realiza un seguimiento de ninguna otra información de contexto porque una solicitud asincrónica es independiente del contexto.

Los controladores de nivel inferior pueden imponer restricciones en los parámetros proporcionados a esta rutina. Por ejemplo, los controladores de disco pueden requerir que los valores proporcionados para Length y StartingOffset sean múltiplos enteros del tamaño del sector del dispositivo.

Un controlador intermedio o de nivel superior también puede llamar a IoBuildDeviceIoControlRequest, IoAllocateIrp o IoBuildSynchronousFsdRequest para configurar las solicitudes que envía a controladores de nivel inferior. Solo un controlador de nivel superior puede llamar a IoMakeAssociatedIrp.

Durante una llamada a IoBuildAsynchronousFsdRequest , el administrador de E/S establece el miembro Tail.Overlay.Thread de la estructura IRP para que apunte al objeto de subproceso del llamador, pero no toma una referencia contada al objeto de subproceso en nombre del autor de la llamada. Una vez que el autor de la llamada envía el IRP al controlador para el dispositivo de destino, este controlador podría usar el miembro Tail.Overlay.Thread para acceder al objeto de subproceso. Por ejemplo, un controlador de almacenamiento podría llamar a la rutina IoSetHardErrorOrVerifyDevice y proporcionar un puntero al IRP como parámetro de entrada. Durante esta llamada, IoSetHardErrorOrVerifyDevice usa el miembro Tail.Overlay.Thread para tener acceso al objeto de subproceso. Cuando se accede al objeto de subproceso de esta manera, el controlador que llamó a IoBuildAsynchronousFsdRequest para asignar el IRP es responsable de garantizar que el objeto de subproceso permanezca válido mientras se controla el IRP.

Para mantener válido el objeto de subproceso, el controlador que llama a IoBuildAsynchronousFsdRequest puede tomar una referencia contada en el objeto de subproceso antes de enviar el IRP. Por ejemplo, este controlador puede llamar a la rutina ObReferenceObjectByPointerWithTag y proporcionar, como parámetro Object , el puntero de objeto del miembro Tail.Overlay.Thread de la estructura IRP . Más adelante, la rutina de finalización de este controlador puede desreferenciar el objeto llamando a una rutina como ObDereferenceObjectWithTag.

Un controlador puede llamar a IoBuildAsynchronousFsdRequest en un subproceso y enviar el IRP asignado por esta llamada en otro subproceso. Antes de enviar el IRP, este controlador debe establecer el miembro Tail.Overlay.Thread del IRP para que apunte al objeto de subproceso para el subproceso de envío. Normalmente, el controlador llama a la rutina PsGetCurrentThread para obtener el puntero del objeto de subproceso.

Un controlador que llama a IoBuildAsynchronousFsdRequest para asignar un IRP no necesariamente necesita tomar una referencia contada en el objeto de subproceso al que apunta el miembro Tail.Overlay.Thread del IRP. En su lugar, el controlador podría usar otra técnica para garantizar que este objeto de subproceso sigue siendo válido mientras se controla el IRP. Por ejemplo, si el controlador creó el subproceso, el subproceso puede esperar hasta que el IRP se complete para finalizarse.

Ejemplos

Antes de llamar a IoFreeIrp, se requiere un paso adicional para liberar el búfer de un IRP compilado por IoBuildAsynchronousFsdRequest si se cumple lo siguiente:

  • El búfer se asignó desde el grupo de memoria del sistema.

  • En el objeto de dispositivo del dispositivo de destino, la marca DO_DIRECT_IO se establece en el campo DeviceObject-Flags>.

  • El campo Irp-MdlAddress> no es NULL.

Antes de liberar el búfer para este IRP, llame a la rutina MmUnlockPages con Irp-MdlAddress> como valor de parámetro. Esta llamada disminuye el recuento de referencias adicional que IoBuildAsynchronousFsdRequest agregó a las páginas del grupo en MDL. De lo contrario, la llamada posterior a IoFreeMdl comprobará el error porque el recuento de referencias de estas páginas del grupo será 2, no 1. En el ejemplo de código siguiente se muestran las llamadas MmUnlockPages, IoFreeMdl e IoFreeIrp para este caso:

if (((DeviceObject->Flags & DO_DIRECT_IO) == DO_DIRECT_IO) &&
    (Irp->MdlAddress != NULL))
{
    MmUnlockPages(Irp->MdlAddress);
}

IoFreeMdl(Irp->MdlAddress);
IoFreeIrp(Irp);

Requisitos

Requisito Value
Plataforma de destino Universal
Encabezado wdm.h (incluya Wdm.h, Ntddk.h, Ntifs.h)
Library NtosKrnl.lib
Archivo DLL NtosKrnl.exe
IRQL IRQL <= APC_LEVEL
Reglas de cumplimiento de DDI ForwardedAtBadIrqlFsdAsync(wdm), HwStorPortProhibitedDDIs(storport), IoBuildFsdComplete(wdm), IoBuildFsdForward(wdm), IoBuildFsdFree(wdm)

Consulte también

IO_STACK_LOCATION

IRP

IoAllocateIrp

IoBuildDeviceIoControlRequest

IoBuildSynchronousFsdRequest

IoCallDriver

IoFreeIrp

IoFreeMdl

IoMakeAssociatedIrp

IoSetCompletionRoutine

IoSetHardErrorOrVerifyDevice

MmUnlockPages

ObDereferenceObjectWithTag

ObReferenceObjectByPointerWithTag

PsGetCurrentThread