Função IoBuildAsynchronousFsdRequest (wdm.h)

A rotina IoBuildAsynchronousFsdRequest aloca e configura um IRP a ser enviado para drivers de nível inferior.

Sintaxe

__drv_aliasesMem PIRP IoBuildAsynchronousFsdRequest(
  [in]           ULONG            MajorFunction,
  [in]           PDEVICE_OBJECT   DeviceObject,
  [in, out]      PVOID            Buffer,
  [in, optional] ULONG            Length,
  [in, optional] PLARGE_INTEGER   StartingOffset,
  [in, optional] PIO_STATUS_BLOCK IoStatusBlock
);

Parâmetros

[in] MajorFunction

O código de função principal a ser definido no IRP. Esse código pode ser IRP_MJ_PNP, IRP_MJ_READ, IRP_MJ_WRITE, IRP_MJ_FLUSH_BUFFERS ou IRP_MJ_SHUTDOWN.

[in] DeviceObject

Um ponteiro para o objeto de dispositivo do próximo driver inferior. Esse objeto representa o dispositivo de destino para a operação de leitura, gravação, liberação ou desligamento.

[in, out] Buffer

Um ponteiro para um buffer no qual os dados são lidos ou dos quais os dados são gravados. O valor desse argumento é NULL para solicitações de liberação e desligamento.

[in, optional] Length

O comprimento, em bytes, do buffer apontado por Buffer. Para dispositivos como discos, esse valor deve ser um múltiplo inteiro do tamanho do setor. Começando com Windows 8, o tamanho do setor pode ser de 4.096 ou 512 bytes. Em versões anteriores do Windows, o tamanho do setor é sempre de 512 bytes. Esse parâmetro é necessário para solicitações de leitura e gravação, mas deve ser zero para solicitações de liberação e desligamento.

[in, optional] StartingOffset

Um ponteiro para o deslocamento inicial na mídia de entrada/saída. O valor desse argumento é zero para solicitações de liberação e desligamento.

[in, optional] IoStatusBlock

Um ponteiro para o endereço de um bloco de status de E/S no qual os drivers a serem chamados retornam status finais sobre a operação solicitada.

Retornar valor

IoBuildAsynchronousFsdRequest retornará um ponteiro para um IRP ou um ponteiro NULL se o IRP não puder ser alocado.

Comentários

Os drivers intermediários ou de nível mais alto podem chamar IoBuildAsynchronousFsdRequest para configurar IRPs para solicitações enviadas a drivers de nível inferior. O driver de chamada deve fornecer uma rotina IoCompletion para o IRP, para que o IRP possa ser desalocado com IoFreeIrp. Para obter mais informações sobre a desalocação do IRP, consulte Exemplos.

O IRP que é criado contém apenas informações suficientes para iniciar a operação e concluir o IRP. Nenhuma outra informação de contexto é rastreada porque uma solicitação assíncrona é independente de contexto.

Drivers de nível inferior podem impor restrições aos parâmetros fornecidos a essa rotina. Por exemplo, os drivers de disco podem exigir que os valores fornecidos para Length e StartingOffset sejam múltiplos inteiros do tamanho do setor do dispositivo.

Um driver intermediário ou de nível mais alto também pode chamar IoBuildDeviceIoControlRequest, IoAllocateIrp ou IoBuildSynchronousFsdRequest para configurar solicitações enviadas a drivers de nível inferior. Somente um driver de nível mais alto pode chamar IoMakeAssociatedIrp.

Durante uma chamada IoBuildAsynchronousFsdRequest , o gerenciador de E/S define o membro Tail.Overlay.Thread da estrutura IRP para apontar para o objeto thread do chamador, mas não faz uma referência contada ao objeto thread em nome do chamador. Depois que o chamador envia o IRP para o driver do dispositivo de destino, esse driver pode usar o membro Tail.Overlay.Thread para acessar o objeto thread. Por exemplo, um driver de armazenamento pode chamar a rotina IoSetHardErrorOrVerifyDevice e fornecer um ponteiro para o IRP como um parâmetro de entrada. Durante essa chamada, IoSetHardErrorOrVerifyDevice usa o membro Tail.Overlay.Thread para acessar o objeto thread. Quando o objeto thread é acessado dessa forma, o driver que chamou IoBuildAsynchronousFsdRequest para alocar o IRP é responsável por garantir que o objeto de thread permaneça válido enquanto o IRP está sendo manipulado.

Para manter o objeto thread válido, o driver que chama IoBuildAsynchronousFsdRequest pode fazer uma referência contada no objeto thread antes de enviar o IRP. Por exemplo, esse driver pode chamar a rotina e o fornecimento de ObReferenceObjectByPointerWithTag , como o parâmetro Object , o ponteiro do objeto do membro Tail.Overlay.Thread da estrutura IRP . Posteriormente, a rotina de conclusão desse driver pode desreferenciar o objeto chamando uma rotina como ObDereferenceObjectWithTag.

Um driver pode chamar IoBuildAsynchronousFsdRequest em um thread e enviar o IRP alocado por essa chamada em outro thread. Antes de enviar o IRP, esse driver deve definir o membro Tail.Overlay.Thread do IRP para apontar para o objeto de thread para o thread de envio. Normalmente, o driver chama a rotina PsGetCurrentThread para obter o ponteiro do objeto thread.

Um driver que chama IoBuildAsynchronousFsdRequest para alocar um IRP não precisa necessariamente fazer uma referência contada no objeto de thread apontado pelo membro Tail.Overlay.Thread do IRP. Em vez disso, o driver pode usar outra técnica para garantir que esse objeto de thread permaneça válido enquanto o IRP está sendo manipulado. Por exemplo, se o driver criou o thread, o thread pode aguardar até que o IRP seja concluído para terminar sozinho.

Exemplos

Antes de chamar IoFreeIrp, será necessária uma etapa adicional para liberar o buffer para um IRP criado por IoBuildAsynchronousFsdRequest se todos os seguintes itens forem verdadeiros:

  • O buffer foi alocado do pool de memória do sistema.

  • No objeto do dispositivo de destino, o sinalizador DO_DIRECT_IO é definido no campo DeviceObject-Flags>.

  • O campo Irp-MdlAddress> não é NULL.

Antes de liberar o buffer para esse IRP, chame a rotina MmUnlockPages com Irp-MdlAddress> como o valor do parâmetro. Essa chamada diminui a contagem de referência extra que IoBuildAsynchronousFsdRequest adicionou às páginas do pool no MDL. Caso contrário, a chamada subsequente para IoFreeMdl bugará marcar porque a contagem de referência para essas páginas de pool será 2, não 1. O exemplo de código a seguir mostra as chamadas MmUnlockPages, IoFreeMdl e IoFreeIrp para esse caso:

if (((DeviceObject->Flags & DO_DIRECT_IO) == DO_DIRECT_IO) &&
    (Irp->MdlAddress != NULL))
{
    MmUnlockPages(Irp->MdlAddress);
}

IoFreeMdl(Irp->MdlAddress);
IoFreeIrp(Irp);

Requisitos

Requisito Valor
Plataforma de Destino Universal
Cabeçalho wdm.h (include Wdm.h, Ntddk.h, Ntifs.h)
Biblioteca NtosKrnl.lib
DLL NtosKrnl.exe
IRQL IRQL <= APC_LEVEL
Regras de conformidade da DDI ForwardedAtBadIrqlFsdAsync(wdm), HwStorPortProhibitedDIs(storport), IoBuildFsdComplete(wdm), IoBuildFsdForward(wdm), IoBuildFsdFree(wdm)

Confira também

IO_STACK_LOCATION

IRP

IoAllocateIrp

IoBuildDeviceIoControlRequest

IoBuildSynchronousFsdRequest

IoCallDriver

IoFreeIrp

IoFreeMdl

IoMakeAssociatedIrp

IoSetCompletionRoutine

IoSetHardErrorOrVerifyDevice

MmUnlockPages

ObDereferenceObjectWithTag

ObReferenceObjectByPointerWithTag

PsGetCurrentThread