Share via


Creación de IRP para controladores de Lower-Level

Para asignar un IRP para una solicitud asincrónica, que se procesará en un contexto de subproceso arbitrario mediante controladores inferiores, una rutina DispatchReadWrite puede llamar a una de las siguientes rutinas de soporte técnico:

  • IoAllocateIrp, que asigna un IRP y una serie de ubicaciones de pila de E/S inicializadas sin inicializar

    La rutina de distribución debe configurar la ubicación de pila de E/S del controlador inferior siguiente para el IRP recién asignado, normalmente copiando (posiblemente modificado) información de su propia ubicación de pila en el IRP original. Si un controlador de nivel superior asigna una ubicación de pila de E/S propia para un IRP recién asignado, la rutina de distribución puede configurar información de contexto por solicitud allí para que la rutina de IoCompletion la use.

  • IoBuildAsynchronousFsdRequest, que configura la ubicación de pila de E/S del controlador inferior siguiente para el autor de la llamada, según los parámetros especificados por el autor de la llamada.

    Los controladores de nivel superior pueden llamar a esta rutina para asignar IRP para solicitudes de IRP_MJ_READ, IRP_MJ_WRITE, IRP_MJ_FLUSH_BUFFERS y IRP_MJ_SHUTDOWN .

    Cuando se llama a una rutina de IoCompletion para este tipo de IRP, puede comprobar el bloque de estado de E/S y, si es necesario (o posible) configurar la ubicación de pila de E/S del controlador inferior siguiente en el IRP y volver a intentar la solicitud o reutilizarla. Sin embargo, la rutina ioCompletion no tiene ningún almacenamiento de contexto local para sí mismo en el IRP, por lo que el controlador debe mantener el contexto sobre la solicitud original en otra parte de la memoria residente.

  • IoMakeAssociatedIrp, que asigna un IRP y una serie de ubicaciones de pila de E/S inicializadas cero, y asocia el IRP con un IRP maestro .

    Los controladores intermedios no pueden llamar a IoMakeAssociatedIrp para crear IRP para controladores inferiores.

    Cualquier controlador de nivel superior que llame a IoMakeAssociatedIrp para crear IRP para controladores inferiores puede devolver el control al administrador de E/S después de enviar sus IRP asociados en y llamar a IoMarkIrpPending para el IRP maestro original. Un controlador de nivel superior puede confiar en el administrador de E/S para completar el IRP maestro cuando todos los IRP asociados han sido completados por controladores inferiores.

    Los controladores rara vez establecen una rutina de IoCompletion para un IRP asociado. Si un controlador de nivel superior llama a IoSetCompletionRoutine para un IRP asociado que crea, el administrador de E/S no completa el IRP maestro si el controlador devuelve STATUS_MORE_PROCESSING_REQUIRED de su rutina de IoCompletion . En estas circunstancias, la rutina ioCompletion del controlador debe completar explícitamente el IRP maestro con IoCompleteRequest.

Si un controlador asigna una ubicación de pila de E/S propia en un nuevo IRP, la rutina de distribución debe llamar a IoSetNextIrpStackLocation antes de llamar a IoGetCurrentIrpStackLocation para configurar el contexto en su propia ubicación de pila de E/S para la rutina de IoCompletion . Para obtener más información, consulte Procesamiento de IRP en un controlador de Intermediate-Level.

La rutina de distribución debe llamar a IoMarkIrpPending con el IRP original, pero no con ningún IRP asignado por el controlador, ya que la rutina ioCompletion los liberará.

Si la rutina de distribución asigna IRP para transferencias parciales y el controlador de dispositivo subyacente podría controlar un dispositivo multimedia extraíble, la rutina de distribución debe configurar el contexto del subproceso en sus IRP recién asignados desde el valor de Tail.Overlay.Thread en el IRP original.

Un controlador subyacente para un dispositivo multimedia extraíble podría llamar a IoSetHardErrorOrVerifyDevice, que hace referencia al puntero en Irp-Tail.Overlay.Thread>, para un IRP asignado por el controlador. Si el controlador llama a esta rutina de soporte técnico, el controlador del sistema de archivos puede enviar un cuadro de diálogo al subproceso de usuario adecuado que pida al usuario que cancele, vuelva a intentar o produzca un error en una operación que el controlador no pudo satisfacer. Consulte Compatibilidad con medios extraíbles para obtener más información.

Las rutinas de envío deben devolver STATUS_PENDING después de enviar todos los IRP asignados por el controlador a controladores inferiores.

La rutina ioCompletion de un controlador debe liberar todos los IRP asignados por el controlador con IoFreeIrp antes de llamar a IoCompleteRequest para el IRP original. Cuando completa el IRP original, la rutina IoCompletion debe liberar todos los IRP asignados por el controlador antes de que devuelva el control.

Cada controlador de nivel superior configura los IRP asignados por controladores (y reutilizados) para los controladores inferiores de tal manera que sea inmaterial para el controlador de dispositivo subyacente si una solicitud determinada procede de un controlador intermedio o se origina en cualquier otro origen, como un sistema de archivos o una aplicación en modo de usuario.

Los controladores de nivel superior pueden llamar a IoMakeAssociatedIrp para asignar IRP y configurarlos para una cadena de controladores inferiores. El administrador de E/S completa automáticamente el IRP original cuando se han completado todas sus IRP asociadas, siempre y cuando el controlador no llame a IoSetCompletionRoutine con el IRP original o con cualquiera de los IRP asociados que asigne. Sin embargo, los controladores de nivel superior no deben asignar IRP asociados para cualquier IRP que solicite una operación de E/S almacenada en búfer.

Un controlador de nivel intermedio no puede asignar IRP para controladores de nivel inferior llamando a IoMakeAssociatedIrp. Cualquier IRP que reciba un controlador intermedio podría ser ya un IRP asociado y un controlador no puede asociar otro IRP con este tipo de IRP.

En su lugar, si un controlador intermedio crea IRP para controladores inferiores, debe llamar a IoAllocateIrp, IoBuildDeviceIoControlRequest, IoBuildSynchronousFsdRequest o IoBuildAsynchronousFsdRequest. Sin embargo, solo se puede llamar a IoBuildSynchronousFsdRequest en las siguientes circunstancias:

  • Mediante un subproceso creado por el controlador para compilar IRP para solicitudes de lectura o escritura, ya que este subproceso puede esperar en un contexto de subproceso nobitrario (propio) en un objeto distribuidor, como un evento inicializado por el controlador pasado a IoBuildSynchronousFsdRequest

  • En el contexto del subproceso del sistema durante la inicialización o durante la descarga

  • Para crear IRP para operaciones intrínsecamente sincrónicas, como crear, vaciar, apagar, cerrar y solicitudes de control de dispositivos

Sin embargo, es más probable que un controlador llame a IoBuildDeviceIoControlRequest para asignar IRP de control de dispositivos que IoBuildSynchronousFsdRequest.