IO_COMPLETION_ROUTINE função de retorno de chamada (wdm.h)

A rotina IoCompletion conclui o processamento de operações de E/S.

Sintaxe

IO_COMPLETION_ROUTINE IoCompletionRoutine;

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

Parâmetros

[in] DeviceObject

Ponteiro fornecido pelo chamador para uma estrutura DEVICE_OBJECT . Esse é o objeto de dispositivo para o dispositivo de destino, criado anteriormente pela rotina AddDevice do driver.

[in] Irp

Ponteiro fornecido pelo chamador para uma estrutura IRP que descreve a operação de E/S.

[in, optional] Context

Ponteiro fornecido pelo chamador para informações de contexto específicas do driver, fornecidas anteriormente ao chamar IoSetCompletionRoutine ou IoSetCompletionRoutineEx. As informações de contexto devem ser armazenadas na memória nãopagada, pois uma rotina IoCompletion pode ser chamada em DISPATCH_LEVEL. Para obter mais informações, consulte a seção Comentários a seguir.

Retornar valor

Se a rotina IoCompletion determinar que o processamento adicional é necessário para o IRP, ele deverá retornar STATUS_MORE_PROCESSING_REQUIRED. Para obter mais informações, consulte a seção Comentários a seguir. Caso contrário, ele deverá retornar STATUS_SUCCESS. (O gerente de E/S verifica apenas a presença ou ausência de STATUS_MORE_PROCESSING_REQUIRED.)

Comentários

A rotina IoCompletion de um driver é executada em um thread arbitrário ou contexto DPC e em um IRQL menor ou igual a DISPATCH_LEVEL. Como o código escrito para ser executado em DISPATCH_LEVEL também será executado em níveis inferiores, as rotinas de IoCompletion devem ser projetadas para execução em DISPATCH_LEVEL. No entanto, como essas rotinas não têm garantia de serem executadas em DISPATCH_LEVEL, elas não devem chamar rotinas do sistema que realmente exigem execução em DISPATCH_LEVEL. (Para obter mais informações sobre IRQLs, consulte Gerenciando prioridades de hardware.)

Para registrar uma rotina IoCompletion para um IRP específico, um driver deve chamar IoSetCompletionRoutine ou IoSetCompletionRoutineEx, que armazena o endereço da rotina IoCompletion no local da pilha de E/S do driver mais baixo. (Portanto, um driver de nível mais baixo não pode registrar uma rotina IoCompletion .) Um driver normalmente chama IoSetCompletionRoutine ou IoSetCompletionRoutineEx de uma de suas rotinas de expedição, cada vez que um IRP é recebido. A maioria dos drivers, incluindo todos os drivers PnP, pode usar IoSetCompletionRoutine para registrar sua rotina IoCompletion . Drivers não PnP que podem ser descarregados antes da execução da rotina IoCompletion devem usar IoSetCompletionRoutineEx .

Quando qualquer driver conclui um IRP, ele chama IoCompleteRequest, que, por sua vez, chama a rotina IoCompletion de cada driver de nível superior, do mais alto para o mais alto, até que todas as rotinas IoCompletion mais altas tenham sido chamadas ou até que uma rotina retorne STATUS_MORE_PROCESSING_REQUIRED.

Ao criar o IRP, aloque um local de pilha para o driver atual, bem como quaisquer drivers inferiores. Se você não alocar locais de pilha suficientes, o ponteiro DeviceObject poderá ser definido como NULL quando a rotina de conclusão for chamada. Você pode evitar alocar um local de pilha extra para o driver atual se usar o campo Contexto para passar informações para IoCompletion , em vez de depender do parâmetro DeviceObject .

Se uma rotina IoCompletion retornar STATUS_MORE_PROCESSING_REQUIRED, a chamada do driver inferior para IoCompleteRequest retornará imediatamente. Nesse caso, um driver de nível superior precisará chamar IoCompleteRequest para concluir o IRP.

Para obter mais informações sobre como implementar rotinas IoCompletion , consulte Concluindo IRPs.

Exemplos

Para definir uma rotina de retorno de chamada IoCompletion , primeiro você deve fornecer uma declaração de função que identifique o tipo de rotina de retorno de chamada que você está definindo. O Windows fornece um conjunto de tipos de função de retorno de chamada para drivers. Declarar uma função usando os tipos de função de retorno de chamada ajuda a Análise de Código para Drivers, SDV ( Verificador de Driver Estático ) e outras ferramentas de verificação a encontrar erros e é um requisito para escrever drivers para o sistema operacional Windows.

Por exemplo, para definir uma rotina de retorno de chamada IoCompletion chamada MyIoCompletion, use o tipo IO_COMPLETION_ROUTINE conforme mostrado neste exemplo de código:

IO_COMPLETION_ROUTINE MyIoCompletion;

Em seguida, implemente sua rotina de retorno de chamada da seguinte maneira:

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

O tipo de função IO_COMPLETION_ROUTINE é definido no arquivo de cabeçalho Wdm.h. Para identificar erros com mais precisão ao executar as ferramentas de análise de código, adicione a _Use_decl_annotations_ anotação à sua definição de função. A _Use_decl_annotations_ anotação garante que as anotações aplicadas ao tipo de função IO_COMPLETION_ROUTINE no arquivo de cabeçalho sejam usadas. Para obter mais informações sobre os requisitos para declarações de função, consulte Declarando funções usando tipos de função de função para drivers WDM. Para obter informações sobre _Use_decl_annotations_, consulte Anotando o comportamento da função.

Requisitos

Requisito Valor
Plataforma de Destino Área de Trabalho
Cabeçalho wdm.h (include Wdm.h, Ntddk.h, Ntifs.h)
IRQL Chamado em IRQL <= DISPATCH_LEVEL (consulte a seção Comentários).