Compartilhar via


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

[Aplica-se somente ao KMDF]

Se o driver precisar interceptar um IRP (pacote de solicitação de E/S) antes ou depois que a estrutura manipular 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 menores 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 principal e secundário especificado.

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

Depois que o driver chama WdfDeviceWdmDispatchPreprocessedIrp, a estrutura processa o IRP da mesma maneira que teria 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 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 IoCompletion antes de chamar WdfDeviceWdmDispatchPreprocessedIrp.

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

Chamando WdfDeviceWdmDispatchPreprocessedIrp

Como o gerenciador de E/S adiciona um local de pilha de E/S adicional ao IRP, a função de retorno de chamada EvtDeviceWdmIrpPreprocess deve chamar IoSkipCurrentIrpStackLocation ou IoCopyCurrentIrpStackLocationToNext (para configurar o próximo local de pilha de E/S no IRP) antes de chamar WdfDeviceWdmDispatchPreprocessedIrp.

Se o driver estiver pré-processando um IRP, mas não pós-processando o IRP, o driver não precisará definir uma rotina IoCompletion para o IRP e pode 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 deverá chamar IoCopyCurrentIrpStackLocationToNext e, em seguida, ele deverá chamar IoSetCompletionRoutine para definir uma rotina IoCompletion para o IRP, como 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);
}

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

Para obter mais informações sobre quando chamar IoCopyCurrentIrpStackLocationToNext, IoSkipCurrentIrpStackLocation e IoSetCompletionRoutine, consulte Passando IRPs para baixo na Pilha de Driver.