Partilhar via


IRPs de pré-processamento e pós-processamento

[Aplica-se apenas ao KMDF]

Se o driver precisar intercetar um pacote de solicitação de E/S (IRP) antes ou depois que a estrutura manipula o IRP, o driver poderá chamar WdfDeviceInitAssignWdmIrpPreprocessCallback para registrar uma função de retorno de chamada de evento EvtDeviceWdmIrpPreprocess para um código de função de E/S principal e, opcionalmente, para códigos de função de E/S secundária específicos associados ao código principal. Posteriormente, a estrutura chama a função de retorno de chamada EvtDeviceWdmIrpPreprocess do driver sempre que o driver recebe um IRP que contém um código de função maior e menor especificado.

A função de retorno de chamada EvtDeviceWdmIrpPreprocess pode fazer o que for necessário para pré-processar o IRP e, depois, deve chamar WdfDeviceWdmDispatchPreprocessedIrp para retornar o IRP à infraestrutura, a menos que o driver esteja a manipular um IRP que a infraestrutura não suporte.

Depois que o driver chama WdfDeviceWdmDispatchPreprocessedIrp, a estrutura processa o IRP exatamente da mesma forma que o faria se o driver não tivesse fornecido uma função de retorno de chamada EvtDeviceWdmIrpPreprocess. Se o código de função de E/S do IRP for aquele que a estrutura passa para os drivers, o driver receberá o IRP novamente como um objeto de solicitação.

Se o driver precisar pós-processar o IRP depois que um driver de nível inferior concluir o IRP, a função de retorno de chamada EvtDeviceWdmIrpPreprocess do driver poderá chamar IoSetCompletionRoutine para definir uma rotina de IoCompletion antes de chamar WdfDeviceWdmDispatchPreprocessedIrp.

Depois que o driver chama WdfDeviceInitAssignWdmIrpPreprocessCallback, o framework faz com que o gestor de E/S adicione uma localização adicional de pilha de E/S a todos os IRPs para que a função de retorno de chamada EvtDeviceWdmIrpPreprocess possa definir uma rotina de IoCompletion. A função de callback deve atualizar o ponteiro de localização da pilha de E/S do IRP antes de chamar WdfDeviceWdmDispatchPreprocessedIrp.

Chamando WdfDeviceWdmDispatchPreprocessedIrp

Como o gestor de E/S adiciona uma localização de pilha de E/S adicional ao IRP, a função de retorno de chamada EvtDeviceWdmIrpPreprocess deve chamar IoSkipCurrentIrpStackLocation ou IoCopyCurrentIrpStackLocationToNext (para configurar a próxima localização da pilha de E/S no IRP) antes de chamar WdfDeviceWdmDispatchPreprocessedIrp.

Se o driver estiver pré-processando um IRP, mas não o pós-processando, o driver não precisará definir uma rotina deIoCompletionpara o IRP e poderá chamar IoSkipCurrentIrpStackLocation, como mostra o exemplo de código a seguir.

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

Se o driver estiver pós-processando o IRP, o driver tem de chamar IoCopyCurrentIrpStackLocationToNexte, em seguida, tem de chamar IoSetCompletionRoutine para definir uma rotina IoCompletion para o IRP, conforme mostra o exemplo de código a seguir.

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

O seu driver não deve chamar IoCopyCurrentIrpStackLocationToNext (e, portanto, não deve definir uma rotina IoCompletion) se o identificador de objeto de dispositivo que a função de retorno de chamada EvtDeviceWdmIrpPreprocess do driver recebe representa um objeto de dispositivo físico (PDO), e se o código de função principal do IRP é IRP_MJ_PNP ou IRP_MJ_POWER. Caso contrário, o Verificador de Controlador relatará um erro.

Para obter mais informações sobre quando chamar IoCopyCurrentIrpStackLocationToNext, IoSkipCurrentIrpStackLocation, e IoSetCompletionRoutine, consulte Enviar IRPs pela pilha de drivers.