IoBuildAsynchronousFsdRequest-Funktion (wdm.h)
Die IoBuildAsynchronousFsdRequest Routine ordnet ein IRP zu und richtet ein IRP ein, das an Treiber niedrigerer Ebene gesendet werden soll.
Syntax
__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
);
Parameter
[in] MajorFunction
Der hauptfunktionscode, der im IRP festgelegt werden soll. Dieser Code kann IRP_MJ_PNP, IRP_MJ_READ, IRP_MJ_WRITE, IRP_MJ_FLUSH_BUFFERSoder IRP_MJ_SHUTDOWN.
[in] DeviceObject
Ein Zeiger auf das Geräteobjekt des nächsten niedrigeren Treibers. Dieses Objekt stellt das Zielgerät für den Lese-, Schreib-, Leer- oder Herunterfahren-Vorgang dar.
[in, out] Buffer
Ein Zeiger auf einen Puffer, in den Daten gelesen oder aus welchen Daten geschrieben werden. Der Wert dieses Arguments ist NULL- für Flush- und Shutdown-Anforderungen.
[in, optional] Length
Die Länge des Puffers in Bytes, auf den Pufferverweist. Bei Geräten wie Datenträgern muss dieser Wert ein ganzzahliges Vielfaches der Sektorgröße sein. Ab Windows 8 kann die Sektorgröße 4.096 oder 512 Byte betragen. In früheren Versionen von Windows beträgt die Sektorgröße immer 512 Byte. Dieser Parameter ist für Lese- und Schreibanforderungen erforderlich, muss jedoch für Flush- und Shutdown-Anforderungen null sein.
[in, optional] StartingOffset
Ein Zeiger auf den Anfangsoffset auf dem Eingabe-/Ausgabemedium. Der Wert dieses Arguments ist null für Flush- und Shutdown-Anforderungen.
[in, optional] IoStatusBlock
Ein Zeiger auf die Adresse eines E/A-Statusblocks, in dem die to-be-aufgerufenen Treiber den endgültigen Status des angeforderten Vorgangs zurückgeben.
Rückgabewert
IoBuildAsynchronousFsdRequest einen Zeiger auf ein IRP oder einen NULL- Zeiger zurück, wenn der IRP nicht zugeordnet werden kann.
Bemerkungen
Treiber auf mittlerer oder höchster Ebene können IoBuildAsynchronousFsdRequest- aufrufen, um IRPs für Anforderungen einzurichten, die an Treiber niedrigerer Ebene gesendet werden. Der Anruftreiber muss eine IoCompletion- Routine für das IRP bereitstellen, sodass das IRP mit IoFreeIrpbehandelt werden kann. Weitere Informationen zur IRP-Deallocation finden Sie unter Beispiele.
Das IRP, das erstellt wird, enthält nur genügend Informationen, um den Vorgang zu starten und das IRP abzuschließen. Es werden keine anderen Kontextinformationen nachverfolgt, da eine asynchrone Anforderung kontextunabhängig ist.
Treiber auf niedrigerer Ebene können Einschränkungen für Parameter auferlegen, die für diese Routine bereitgestellt werden. Beispielsweise können Datenträgertreiber festlegen, dass werte, die für Length angegeben werden, und StartingOffset ganzzahlige Vielfache der Größe des Gerätesektors sein.
Ein Treiber auf mittlerer oder höchster Ebene kann auch IoBuildDeviceIoControlRequest-, IoAllocateIrp-oder IoBuildSynchronousFsdRequest- aufrufen, um Anforderungen einzurichten, die er an Treiber auf niedrigerer Ebene sendet. Nur ein Treiber der höchsten Ebene kann IoMakeAssociatedIrpaufrufen.
Während eines IoBuildAsynchronousFsdRequest- Aufrufs legt der I/O-Manager den Tail.Overlay.Thread- Member der IRP- Struktur fest, um auf das Threadobjekt des Aufrufers zu verweisen, nimmt jedoch keinen gezählten Verweis auf das Threadobjekt im Namen des Aufrufers. Nachdem der Aufrufer das IRP an den Treiber für das Zielgerät gesendet hat, verwendet dieser Treiber möglicherweise das Tail.Overlay.Thread Member für den Zugriff auf das Threadobjekt. Beispielsweise kann ein Speichertreiber den IoSetHardErrorOrVerifyDevice- Routine aufrufen und einen Zeiger als Eingabeparameter auf das IRP bereitstellen. Während dieses Aufrufs verwendet IoSetHardErrorOrVerifyDevice das Tail.Overlay.Thread Member für den Zugriff auf das Threadobjekt. Wenn auf diese Weise auf das Threadobjekt zugegriffen wird, ist der Treiber, der IoBuildAsynchronousFsdRequest aufgerufen hat, um sicherzustellen, dass das Threadobjekt gültig bleibt, während das IRP verarbeitet wird.
Um das Threadobjekt gültig zu halten, kann der Treiber, der IoBuildAsynchronousFsdRequest- aufruft, einen gezählten Verweis auf das Threadobjekt annehmen, bevor der IRP gesendet wird. Beispielsweise kann dieser Treiber die ObReferenceObjectByPointerWithTag Routine aufrufen und bereitstellen, wie der Object Parameter, der Objektzeiger aus dem Tail.Overlay.Thread Member der IRP--Struktur. Später kann die Abschlussroutine dieses Treibers das Objekt durch Aufrufen einer Routine wie ObDereferenceObjectWithTagableiten.
Ein Treiber ruft möglicherweise IoBuildAsynchronousFsdRequest- in einem Thread auf und sendet das von diesem Aufruf in einem anderen Thread zugewiesene IRP. Vor dem Senden des IRP sollte dieser Treiber den Tail.Overlay.Thread Member des IRP festlegen, um auf das Threadobjekt für den sendenden Thread zu zeigen. In der Regel ruft der Treiber die PsGetCurrentThread Routine auf, um den Threadobjektzeiger abzurufen.
Ein Treiber, der IoBuildAsynchronousFsdRequest- aufruft, um ein IRP zuzuweisen, muss nicht unbedingt einen gezählten Verweis auf das Threadobjekt verwenden, auf das vom Tail.Overlay.Thread Member des IRP verwiesen wird. Der Treiber kann stattdessen eine andere Technik verwenden, um sicherzustellen, dass dieses Threadobjekt gültig bleibt, während das IRP verarbeitet wird. Wenn beispielsweise der Treiber den Thread erstellt hat, kann der Thread warten, bis das IRP abgeschlossen ist, um sich selbst zu beenden.
Beispiele
Bevor Sie IoFreeIrp-aufrufen, ist ein zusätzlicher Schritt erforderlich, um den Puffer für ein von IoBuildAsynchronousFsdRequest erstelltes IRP freizulösen, wenn folgendes zutrifft:
Der Puffer wurde aus dem Systemspeicherpool zugewiesen.
Im Geräteobjekt für das Zielgerät wird das DO_DIRECT_IO Flag im Feld DeviceObject->Flags festgelegt.
Das feld >MdlAddress ist ungleich NULL.
Rufen Sie vor dem Freigeben des Puffers für dieses IRP die MmUnlockPages Routine mit Irp->MdlAddress- als Parameterwert auf. Dieser Aufruf erhöht die zusätzliche Verweisanzahl, die IoBuildAsynchronousFsdRequest den Poolseiten in der MDL hinzugefügt wurde. Andernfalls überprüft der nachfolgende Aufruf von IoFreeMdl Fehler, da die Referenzanzahl für diese Poolseiten 2 und nicht 1 ist. Das folgende Codebeispiel zeigt die MmUnlockPages-, IoFreeMdl-und IoFreeIrp- aufrufe für diesen Fall:
if (((DeviceObject->Flags & DO_DIRECT_IO) == DO_DIRECT_IO) &&
(Irp->MdlAddress != NULL))
{
MmUnlockPages(Irp->MdlAddress);
}
IoFreeMdl(Irp->MdlAddress);
IoFreeIrp(Irp);
Anforderungen
Anforderung | Wert |
---|---|
Zielplattform- | Universal |
Header- | wdm.h (include Wdm.h, Ntddk.h, Ntifs.h) |
Library | NtosKrnl.lib |
DLL- | NtosKrnl.exe |
IRQL- | IRQL-<= APC_LEVEL |
DDI-Complianceregeln | ForwardedAtBadIrqlFsdAsync(wdm), HwStorPortProhibitedDIs(storport), IoBuildFsdComplete(wdm), IoBuildFsdForward(wdm), IoBuildFsdFree(wdm) |