Compartir a través de


Pasar IRP a la pila de controladores

Cuando la rutina de distribución de un controlador recibe un IRP, debe llamar a IoGetCurrentIrpStackLocation para que pueda comprobar su propia ubicación de pila de E/S y determinar que los parámetros son válidos. Si el controlador no puede satisfacer y completar la propia solicitud, puede realizar una de las siguientes acciones:

  • Pase el IRP para su posterior procesamiento mediante controladores de nivel inferior.

  • Cree uno o varios IRP nuevos y páselos a controladores de nivel inferior.

Un controlador de nivel superior debe pasar una solicitud de E/S a un controlador inferior como se indica a continuación:

  1. Si el controlador pasará el IRP de entrada al siguiente controlador de nivel inferior, la rutina de distribución debe llamar a IoSkipCurrentIrpStackLocation o IoCopyCurrentIrpStackLocationToNext para configurar la ubicación de pila de E/S del controlador inferior siguiente.

    Si el controlador llama a IoAllocateIrp para asignar uno o varios IRP adicionales para controladores inferiores, la rutina de envío debe inicializar la ubicación de pila de E/S del controlador inferior siguiente siguiendo los pasos descritos en Procesamiento de IRP en un controlador de Intermediate-Level.

    La rutina de distribución puede modificar algunos de los parámetros de la ubicación de pila de E/S del controlador inferior siguiente para determinadas solicitudes. Por ejemplo, un controlador de nivel superior podría modificar los parámetros de una solicitud de transferencia grande cuando el dispositivo subyacente tiene un límite conocido en la capacidad de transferencia y reutilizar el IRP para enviar solicitudes de transferencia parcial al controlador de dispositivo subyacente.

  2. Llame a IoSetCompletionRoutine.

    Si la rutina de distribución pasa un IRP recibido al controlador inferior siguiente, establecer una rutina de IoCompletion es opcional pero útil, ya que la rutina puede realizar tareas como determinar cómo los controladores inferiores completaron la solicitud, reutilizar el IRP para transferencias parciales, actualizar el estado que mantiene el controlador si realiza el seguimiento de IRP y reintentar una solicitud que se devolvió con un error.

    Si la rutina de distribución ha asignado nuevos IRP, se requiere establecer una rutina de IoCompletion porque la rutina debe liberar cada IRP después de que los controladores inferiores lo hayan completado.

    Para obtener más información sobre las rutinas de IoCompletion , consulte Finalización de IRP.

  3. Llame a IoCallDriver con cada IRP que los controladores inferiores procesen.

  4. Devuelve un valor NTSTATUS adecuado, como:

    • STATUS_PENDING

      Normalmente, el controlador devuelve STATUS_PENDING si el IRP de entrada es una solicitud asincrónica, como IRP_MJ_READ o IRP_MJ_WRITE.

    • Resultado de la llamada a IoCallDriver

      El controlador devuelve con frecuencia el resultado de la llamada a IoCallDriver si el IRP de entrada es una solicitud sincrónica, como IRP_MJ_CREATE.

Un controlador de dispositivo de nivel más bajo pasa cualquier IRP que no pueda completar en su rutina de envío a otras rutinas de controlador de la siguiente manera:

  1. Llame a IoMarkIrpPending con el IRP de entrada.

  2. Llame a IoStartPacket para pasar o poner en cola el IRP a la rutina StartIo del controlador, a menos que el controlador administre su propia cola de IRP interna, como se describe en Colas de IRP administradas por controladores.

    Si el controlador no tiene una rutina StartIo pero controla irP cancelables, debe registrar una rutina Cancelar o implementar una cola irP segura para cancelaciones. Para obtener más información sobre las rutinas Cancel, consulte Canceling IRP (Cancelar IRP).

  3. Devuelve STATUS_PENDING.