Passando IRPs para baixo na pilha de driver

Quando a rotina de expedição de um driver recebe um IRP, ele deve chamar IoGetCurrentIrpStackLocation para que ele possa marcar seu próprio local de pilha de E/S e determinar que todos os parâmetros são válidos. Se o driver não puder atender e concluir a solicitação em si, ele poderá fazer um dos seguintes procedimentos:

  • Passe o IRP para processamento adicional por drivers de nível inferior.

  • Crie um ou mais NOVOS IRPs e passe-os para drivers de nível inferior.

Um driver de nível superior deve passar uma solicitação de E/S para um driver mais baixo da seguinte maneira:

  1. Se o driver passar o IRP de entrada para o próximo driver de nível inferior, a rotina de expedição deverá chamar IoSkipCurrentIrpStackLocation ou IoCopyCurrentIrpStackLocationToNext para configurar o local da pilha de E/S do driver mais baixo.

    Se o driver chamar IoAllocateIrp para alocar um ou mais IRPs adicionais para drivers inferiores, a rotina de expedição deverá inicializar o local da pilha de E/S do driver mais baixo seguindo as etapas descritas em Processando IRPs em um driver de Intermediate-Level.

    A rotina de expedição pode modificar alguns dos parâmetros no local da pilha de E/S do próximo driver inferior para determinadas solicitações. Por exemplo, um driver de nível superior pode modificar os parâmetros de uma solicitação de transferência grande quando o dispositivo subjacente tiver um limite conhecido na capacidade de transferência e reutilizar o IRP para enviar solicitações de transferência parcial para o driver de dispositivo subjacente.

  2. Chame IoSetCompletionRoutine.

    Se a rotina de expedição estiver passando um IRP recebido para o driver inferior seguinte, definir uma rotina IoCompletion é opcional, mas útil, pois a rotina pode executar tarefas como determinar como drivers inferiores concluíram a solicitação, reutilizar o IRP para transferências parciais, atualizar qualquer estado que o driver mantém se rastrear IRPs e repetir uma solicitação que foi retornada com um erro.

    Se a rotina de expedição tiver alocado novos IRPs, a configuração de uma rotina IoCompletion será necessária porque a rotina deve liberar cada IRP depois que os drivers inferiores a tiverem concluído.

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

  3. Chame IoCallDriver com cada IRP a ser processado por drivers inferiores.

  4. Retornar um valor NTSTATUS apropriado, como:

    • STATUS_PENDING

      O driver geralmente retornará STATUS_PENDING se o IRP de entrada for uma solicitação assíncrona, como IRP_MJ_READ ou IRP_MJ_WRITE.

    • O resultado da chamada para IoCallDriver

      O driver frequentemente retorna o resultado da chamada para IoCallDriver se o IRP de entrada for uma solicitação síncrona, como IRP_MJ_CREATE.

Um driver de dispositivo de nível mais baixo passa qualquer IRP que ele não possa concluir em sua rotina de expedição para outras rotinas de driver da seguinte maneira:

  1. Chame IoMarkIrpPending com o IRP de entrada.

  2. Chame IoStartPacket para passar ou enfileirar o IRP para a rotina StartIo do driver, a menos que o driver gerencie seu próprio enfileiramento IRP interno, conforme descrito em Filas IRP gerenciadas pelo driver.

    Se o driver não tiver uma rotina StartIo , mas manipular IRPs canceláveis, ele deverá registrar uma rotina Cancelar ou implementar uma fila IRP cancel-safe. Para obter mais informações sobre o Cancelamento de rotinas, consulte Cancelando IRPs.

  3. Retornar STATUS_PENDING.