IRP de preprocesamiento y posprocesamiento
[Solo se aplica a KMDF]
Si el controlador debe interceptar un paquete de solicitud de E/S (IRP) antes o después de que el marco controle el IRP, el controlador puede llamar a WdfDeviceInitAssignWdmIrpPreprocessCallback para registrar una función de devolución de llamada de evento EvtDeviceWdmIrpPreprocess para un código de función de E/S principal y, opcionalmente, para códigos de función de E/S menores específicos asociados al código principal. Posteriormente, el marco llama a la función de devolución de llamada EvtDeviceWdmIrpPreprocess del controlador cada vez que el controlador recibe un IRP que contiene un código de función principal y secundario especificado.
La función de devolución de llamada EvtDeviceWdmIrpPreprocess puede hacer lo que sea necesario para preprocesar el IRP y, a continuación, debe llamar a WdfDeviceWdmDispatchPreprocessedIrp para devolver el IRP al marco a menos que el controlador controle un IRP que el marco no admita.
Después de que el controlador llame a WdfDeviceWdmDispatchPreprocessedIrp, el marco procesa el IRP de la misma manera que tendría si el controlador no hubiera proporcionado una función de devolución de llamada EvtDeviceWdmIrpPreprocess . Si el código de la función de E/S del IRP es uno que el marco pasa a los controladores, el controlador recibirá el IRP de nuevo como un objeto de solicitud.
Si el controlador necesita posprocesar el IRP después de que un controlador de nivel inferior complete el IRP, la función de devolución de llamada EvtDeviceWdmIrpPreprocess del controlador puede llamar a IoSetCompletionRoutine para establecer una rutina de IoCompletion antes de llamar a WdfDeviceWdmDispatchPreprocessedIrp.
Una vez que el controlador llama a WdfDeviceInitAssignWdmIrpPreprocessCallback, el marco hace que el administrador de E/S agregue una ubicación de pila de E/ S adicional a todos los IRP para que la función de devolución de llamada EvtDeviceWdmIrpPreprocess pueda establecer una rutina de IoCompletion . La función de devolución de llamada debe actualizar el puntero de ubicación de pila de E/S de IRP antes de llamar a WdfDeviceWdmDispatchPreprocessedIrp.
Llamar a WdfDeviceWdmDispatchPreprocessedIrp
Dado que el administrador de E/S agrega una ubicación de pila de E/S adicional al IRP, la función de devolución de llamada EvtDeviceWdmIrpPreprocess debe llamar a IoSkipCurrentIrpStackLocation o IoCopyCurrentIrpStackLocationToNext (para configurar la siguiente ubicación de pila de E/S en IRP) antes de llamar a WdfDeviceWdmDispatchPreprocessedIrp.
Si el controlador está preprocesando un IRP, pero no posprocesando el IRP, el controlador no necesita establecer una rutina de IoCompletion para IRP y puede llamar a IoSkipCurrentIrpStackLocation, como se muestra en el ejemplo de código siguiente.
NTSTATUS
EvtDeviceMyIrpPreprocess(
IN WDFDEVICE Device,
IN OUT PIRP Irp
)
{
//
// Perform IRP preprocessing operations here.
//
...
//
// Deliver the IRP back to the framework.
//
IoSkipCurrentIrpStackLocation(Irp);
return WdfDeviceWdmDispatchPreprocessedIrp(Device, Irp);
}
Si el controlador está posprocesando el IRP, el controlador debe llamar a IoCopyCurrentIrpStackLocationToNext y, a continuación, debe llamar a IoSetCompletionRoutine para establecer una rutina de IoCompletion para irP, como se muestra en el ejemplo de código siguiente.
NTSTATUS
EvtDeviceMyIrpPreprocess(
IN WDFDEVICE Device,
IN OUT PIRP Irp
)
{
//
// Perform IRP preprocessing operations here, if needed.
//
...
//
// Set a completion routine and deliver the IRP back to
// the framework.
//
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(
Irp,
MyIrpCompletionRoutine,
NULL,
TRUE,
TRUE,
TRUE
);
return WdfDeviceWdmDispatchPreprocessedIrp(Device, Irp);
}
El controlador no debe llamar a IoCopyCurrentIrpStackLocationToNext (y, por lo tanto, no debe establecer una rutina ioCompletion ) si el objeto de dispositivo controla que la función de devolución de llamada EvtDeviceWdmIrpPreprocess del controlador representa un objeto de dispositivo físico (PDO) y si el código de función principal del IRP es IRP_MJ_PNP o IRP_MJ_POWER. De lo contrario, el Comprobador de controladores notificará un error.
Para obtener más información sobre cuándo llamar a IoCopyCurrentIrpStackLocationToNext, IoSkipCurrentIrpStackLocation y IoSetCompletionRoutine, consulte Paso de IRP a la pila de controladores.