Funzione IoBuildAsynchronousFsdRequest (wdm.h)

La routine IoBuildAsynchronousFsdRequest alloca e configura un IRP da inviare ai driver di livello inferiore.

Sintassi

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

Parametri

[in] MajorFunction

Codice della funzione principale da impostare in IRP. Questo codice può essere IRP_MJ_PNP, IRP_MJ_READ, IRP_MJ_WRITE, IRP_MJ_FLUSH_BUFFERS o IRP_MJ_SHUTDOWN.

[in] DeviceObject

Puntatore all'oggetto dispositivo del driver inferiore successivo. Questo oggetto rappresenta il dispositivo di destinazione per l'operazione di lettura, scrittura, scaricamento o arresto.

[in, out] Buffer

Puntatore a un buffer in cui i dati vengono letti o da cui vengono scritti i dati. Il valore di questo argomento è NULL per le richieste di scaricamento e arresto.

[in, optional] Length

Lunghezza, in byte, del buffer a cui punta Buffer. Per i dispositivi come i dischi, questo valore deve essere un numero intero multiplo delle dimensioni del settore. A partire da Windows 8, le dimensioni del settore possono essere pari a 4.096 o 512 byte. Nelle versioni precedenti di Windows, le dimensioni del settore sono sempre di 512 byte. Questo parametro è obbligatorio per le richieste di lettura e scrittura, ma deve essere zero per le richieste di scaricamento e arresto.

[in, optional] StartingOffset

Puntatore all'offset iniziale sul supporto di input/output. Il valore di questo argomento è zero per le richieste di scaricamento e arresto.

[in, optional] IoStatusBlock

Puntatore all'indirizzo di un blocco di stato di I/O in cui i driver da chiamare restituiscono lo stato finale dell'operazione richiesta.

Valore restituito

IoBuildAsynchronousFsdRequest restituisce un puntatore a un'istanza di IRP o un puntatore NULL se l'IRP non può essere allocato.

Commenti

I driver intermedi o di livello più alto possono chiamare IoBuildAsynchronousFsdRequest per configurare i provider di integrazione per le richieste inviate ai driver di livello inferiore. Il driver chiamante deve fornire una routine IoCompletion per l'IRP, quindi l'IRP può essere deallocato con IoFreeIrp. Per altre informazioni sulla deallocazione di IRP, vedere Esempi.

L'IRP compilato contiene solo informazioni sufficienti per avviare l'operazione e completare l'IRP. Nessun'altra informazione di contesto viene rilevata perché una richiesta asincrona è indipendente dal contesto.

I driver di livello inferiore potrebbero imporre restrizioni ai parametri forniti a questa routine. Ad esempio, i driver del disco potrebbero richiedere che i valori specificati per Length e StartingOffset siano multipli interi delle dimensioni del settore del dispositivo.

Un driver intermedio o di livello più alto può anche chiamare IoBuildDeviceIoControlRequest, IoAllocateIrp o IoBuildSynchronousFsdRequest per configurare le richieste inviate ai driver di livello inferiore. Solo un driver di livello più alto può chiamare IoMakeAssociatedIrp.

Durante una chiamata IoBuildAsynchronousFsdRequest , il gestore di I/O imposta il membro Tail.Overlay.Thread della struttura IRP in modo che punti all'oggetto thread del chiamante, ma non accetta un riferimento conteggiato all'oggetto thread per conto del chiamante. Dopo che il chiamante invia l'IRP al driver per il dispositivo di destinazione, questo driver potrebbe usare il membro Tail.Overlay.Thread per accedere all'oggetto thread. Ad esempio, un driver di archiviazione potrebbe chiamare la routine IoSetHardErrorOrVerifyDevice e fornire un puntatore all'IRP come parametro di input. Durante questa chiamata, IoSetHardErrorOrVerifyDevice usa il membro Tail.Overlay.Thread per accedere all'oggetto thread. Quando si accede all'oggetto thread in questo modo, il driver che ha chiamato IoBuildAsynchronousFsdRequest per allocare l'IRP è responsabile di garantire che l'oggetto thread rimanga valido durante la gestione dell'IRP.

Per mantenere valido l'oggetto thread, il driver che chiama IoBuildAsynchronousFsdRequest può accettare un riferimento conteggiato sull'oggetto thread prima di inviare l'IRP. Ad esempio, questo driver può chiamare la routine ObReferenceObjectByPointerWithTag e fornire, come parametro Object , il puntatore all'oggetto dal membro Tail.Overlay.Thread della struttura IRP . Successivamente, la routine di completamento del driver può dereferenziare l'oggetto chiamando una routine come ObDereferenceObjectWithTag.

Un driver potrebbe chiamare IoBuildAsynchronousFsdRequest in un thread e inviare l'IRP allocato da questa chiamata in un altro thread. Prima di inviare l'IRP, questo driver deve impostare il membro Tail.Overlay.Thread dell'IRP in modo che punti all'oggetto thread per il thread di invio. In genere, il driver chiama la routine PsGetCurrentThread per ottenere il puntatore dell'oggetto thread.

Un driver che chiama IoBuildAsynchronousFsdRequest per allocare un IRP non deve necessariamente accettare un riferimento conteggiato sull'oggetto thread a cui punta il membro Tail.Overlay.Thread di IRP. Il driver potrebbe invece usare un'altra tecnica per garantire che questo oggetto thread rimanga valido durante la gestione di IRP. Ad esempio, se il driver ha creato il thread, il thread può attendere il completamento dell'IRP per terminare se stesso.

Esempio

Prima di chiamare IoFreeIrp, è necessario un passaggio aggiuntivo per liberare il buffer per un IRP compilato da IoBuildAsynchronousFsdRequest se sono tutti true:

  • Il buffer è stato allocato dal pool di memoria di sistema.

  • Nell'oggetto dispositivo per il dispositivo di destinazione il flag DO_DIRECT_IO viene impostato nel campo DeviceObject-Flags>.

  • Il campo Irp-MdlAddress> non è NULL.

Prima di liberare il buffer per questo IRP, chiamare la routine MmUnlockPages con Irp-MdlAddress> come valore del parametro. Questa chiamata decrementa il conteggio dei riferimenti aggiuntivo aggiunto a IoBuildAsynchronousFsdRequest alle pagine del pool in MDL. In caso contrario, la chiamata successiva a IoFreeMdl verificherà bug perché il conteggio dei riferimenti per queste pagine del pool sarà 2, non 1. L'esempio di codice seguente illustra le chiamate MmUnlockPages, IoFreeMdl e IoFreeIrp per questo caso:

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

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

Requisiti

Requisito Valore
Piattaforma di destinazione Universale
Intestazione wdm.h (include Wdm.h, Ntddk.h, Ntifs.h)
Libreria NtosKrnl.lib
DLL NtosKrnl.exe
IRQL IRQL <= APC_LEVEL
Regole di conformità DDI ForwardedAtBadIrqlFsdAsync(wdm), HwStorPortProhibitedDDIs(storport), IoBuildFsdComplete(wdm), IoBuildFsdForward(wdm), IoBuildFsdFree(wdm)

Vedi anche

IO_STACK_LOCATION

IRP

IoAllocateIrp

IoBuildDeviceIoControlRequest

IoBuildSynchronousFsdRequest

IoCallDriver

IoFreeIrp

IoFreeMdl

IoMakeAssociatedIrp

IoSetCompletionRoutine

IoSetHardErrorOrVerifyDevice

MmUnlockPages

ObDereferenceObjectWithTag

ObReferenceObjectByPointerWithTag

PsGetCurrentThread