IO_COMPLETION_ROUTINE función de devolución de llamada (wdm.h)

La rutina IoCompletion completa el procesamiento de operaciones de E/S.

Sintaxis

IO_COMPLETION_ROUTINE IoCompletionRoutine;

NTSTATUS IoCompletionRoutine(
  [in]           PDEVICE_OBJECT DeviceObject,
  [in]           PIRP Irp,
  [in, optional] PVOID Context
)
{...}

Parámetros

[in] DeviceObject

Puntero proporcionado por el autor de la llamada a una estructura de DEVICE_OBJECT . Este es el objeto de dispositivo para el dispositivo de destino, creado anteriormente por la rutina AddDevice del controlador.

[in] Irp

Puntero proporcionado por el autor de la llamada a una estructura IRP que describe la operación de E/S.

[in, optional] Context

Puntero proporcionado por el autor de la llamada a información de contexto específica del controlador, proporcionada anteriormente al llamar a IoSetCompletionRoutine o IoSetCompletionRoutineEx. La información de contexto debe almacenarse en memoria no paginada, ya que se puede llamar a una rutina de IoCompletion en DISPATCH_LEVEL. Para obtener más información, vea la sección Comentarios que se muestra más adelante.

Valor devuelto

Si la rutina IoCompletion determina que se requiere procesamiento adicional para el IRP, debe devolver STATUS_MORE_PROCESSING_REQUIRED. Para obtener más información, vea la sección Comentarios que se muestra más adelante. De lo contrario, debe devolver STATUS_SUCCESS. (El administrador de E/S solo comprueba la presencia o ausencia de STATUS_MORE_PROCESSING_REQUIRED).

Comentarios

La rutina ioCompletion de un controlador se ejecuta en un subproceso arbitrario o contexto DPC, y en un IRQL menor o igual que DISPATCH_LEVEL. Dado que el código escrito para ejecutarse en DISPATCH_LEVEL también se ejecutará en niveles inferiores, las rutinas de IoCompletion deben diseñarse para su ejecución en DISPATCH_LEVEL. Sin embargo, dado que no se garantiza que estas rutinas se ejecuten en DISPATCH_LEVEL, no deben llamar a rutinas del sistema que realmente requieran ejecución en DISPATCH_LEVEL. (Para obtener más información sobre las IRQL, consulte Administración de prioridades de hardware).

Para registrar una rutina de IoCompletion para un IRP específico, un controlador debe llamar a IoSetCompletionRoutine o IoSetCompletionRoutineEx, que almacena la dirección de la rutina de IoCompletion en la ubicación de pila de E/S del controlador inferior siguiente. (Por lo tanto, un controlador de nivel inferior no puede registrar una rutina de IoCompletion ). Normalmente, un controlador llama a IoSetCompletionRoutine o IoSetCompletionRoutineEx desde una de sus rutinas de envío, cada vez que se recibe un IRP. La mayoría de los controladores, incluidos todos los controladores PnP, pueden usar IoSetCompletionRoutine para registrar su rutina de IoCompletion . Los controladores que no son PnP que se pueden descargar antes de que se ejecute su rutina de IoCompletion deben usar IoSetCompletionRoutineEx en su lugar.

Cuando cualquier controlador completa un IRP, llama a IoCompleteRequest, que a su vez llama a la rutina ioCompletion de cada controlador de nivel superior, desde el siguiente nivel superior al más alto, hasta que se haya llamado a todas las rutinas de IoCompletion más altas o hasta que una rutina devuelva STATUS_MORE_PROCESSING_REQUIRED.

Al crear el IRP, asigne una ubicación de pila para el controlador actual, así como los controladores inferiores. Si no asigna suficientes ubicaciones de pila, el puntero DeviceObject puede establecerse en NULL cuando se llama a la rutina de finalización. Puede evitar asignar una ubicación de pila adicional para el controlador actual si usa el campo Contexto para pasar información a IoCompletion en lugar de confiar en el parámetro DeviceObject .

Si una rutina de IoCompletion devuelve STATUS_MORE_PROCESSING_REQUIRED, la llamada del controlador inferior a IoCompleteRequest devuelve inmediatamente. En este caso, un controlador de nivel superior tendrá que llamar a IoCompleteRequest para completar el IRP.

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

Ejemplos

Para definir una rutina de devolución de llamada de IoCompletion , primero debe proporcionar una declaración de función que identifique el tipo de rutina de devolución de llamada que está definiendo. Windows proporciona un conjunto de tipos de función de devolución de llamada para controladores. Declarar una función mediante los tipos de función de devolución de llamada ayuda a Code Analysis for Drivers, Static Driver Verifier (SDV) y otras herramientas de comprobación encuentran errores y es un requisito para escribir controladores para el sistema operativo Windows.

Por ejemplo, para definir una rutina de devolución de llamada de IoCompletion denominada MyIoCompletion, use el tipo IO_COMPLETION_ROUTINE como se muestra en este ejemplo de código:

IO_COMPLETION_ROUTINE MyIoCompletion;

A continuación, implemente la rutina de devolución de llamada de la siguiente manera:

_Use_decl_annotations_
NTSTATUS
  MyIoCompletion(
    PDEVICE_OBJECT  DeviceObject,
    PIRP  Irp,
    PVOID  Context
    )
  {
      // Function body
  }

El tipo de función IO_COMPLETION_ROUTINE se define en el archivo de encabezado Wdm.h. Para identificar con más precisión los errores al ejecutar las herramientas de análisis de código, asegúrese de agregar la anotación a la _Use_decl_annotations_ definición de la función. La _Use_decl_annotations_ anotación garantiza que se usen las anotaciones que se aplican al tipo de función IO_COMPLETION_ROUTINE en el archivo de encabezado. Para obtener más información sobre los requisitos de las declaraciones de función, vea Declarar funciones mediante tipos de roles de función para controladores WDM. Para obtener información sobre _Use_decl_annotations_, consulte Anotación del comportamiento de la función.

Requisitos

Requisito Value
Plataforma de destino Escritorio
Encabezado wdm.h (incluya Wdm.h, Ntddk.h, Ntifs.h)
IRQL Se llama en IRQL <= DISPATCH_LEVEL (consulte la sección Comentarios).