IoBuildAsynchronousFsdRequest-Funktion (wdm.h)

Die IoBuildAsynchronousFsdRequest-Routine ordnet ein IRP zu und richtet sie ein, das an Treiber auf 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_BUFFERS oder IRP_MJ_SHUTDOWN sein.

[in] DeviceObject

Ein Zeiger auf das Geräteobjekt des nächstniedrigen 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 dem Daten geschrieben werden. Der Wert dieses Arguments ist NULL für Leer- und Herunterfahrensanforderungen.

[in, optional] Length

Die Länge des Puffers in Bytes, auf den puffer verweist. Für Geräte wie Datenträger muss dieser Wert ein ganzzahliges Vielfaches der Sektorgröße sein. Ab Windows 8 kann die Sektorgröße 4.096 oder 512 Bytes betragen. In früheren Versionen von Windows beträgt die Sektorgröße immer 512 Bytes. Dieser Parameter ist für Lese- und Schreibanforderungen erforderlich, muss aber für Leer- und Herunterfahrensanforderungen null sein.

[in, optional] StartingOffset

Ein Zeiger auf den Startoffset auf dem Eingabe-/Ausgabemedium. Der Wert dieses Arguments ist 0 für Leer- und Herunterfahrensanforderungen.

[in, optional] IoStatusBlock

Ein Zeiger auf die Adresse eines E/A-status-Blocks, in dem die aufgerufenen Treiber letzte status zum angeforderten Vorgang zurückgeben.

Rückgabewert

IoBuildAsynchronousFsdRequest gibt einen Zeiger auf eine IRP oder einen NULL-Zeiger zurück, wenn der IRP nicht zugeordnet werden kann.

Hinweise

Treiber auf mittlerer oder höchster Ebene können IoBuildAsynchronousFsdRequest aufrufen, um IRPs für Anforderungen einzurichten, die an Treiber auf niedrigerer Ebene gesendet werden. Der aufrufende Treiber muss eine IoCompletion-Routine für die IRP bereitstellen, damit die IRP mit IoFreeIrp zugeordnet 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 den 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 erzwingen, die für diese Routine bereitgestellt werden. Beispielsweise können Datenträgertreiber erfordern, dass die für Length und StartingOffset angegebenen Werte ganzzahlige Vielfache der Sektorgröße des Geräts sind.

Ein Treiber auf mittlerer oder oberster Ebene kann auch IoBuildDeviceIoControlRequest, IoAllocateIrp oder IoBuildSynchronousFsdRequest aufrufen, um Anforderungen einzurichten, die an Treiber auf niedrigerer Ebene gesendet werden. Nur ein Treiber der höchsten Ebene kann IoMakeAssociatedIrp aufrufen.

Während eines IoBuildAsynchronousFsdRequest-Aufrufs legt der E/A-Manager den Tail.Overlay.Thread-Member der IRP-Struktur so fest, dass er auf das Threadobjekt des Aufrufers verweist, nimmt jedoch keinen gezählten Verweis auf das Threadobjekt im Namen des Aufrufers an. Nachdem der Aufrufer den IRP an den Treiber für das Zielgerät gesendet hat, kann dieser Treiber den Tail.Overlay.Thread-Member verwenden, um auf das Threadobjekt zuzugreifen. Beispielsweise kann ein Speichertreiber die IoSetHardErrorOrVerifyDevice-Routine aufrufen und einen Zeiger auf das IRP als Eingabeparameter bereitstellen. Während dieses Aufrufs verwendet IoSetHardErrorOrVerifyDevice den Tail.Overlay.Thread-Member , um auf das Threadobjekt zuzugreifen. Wenn auf diese Weise auf das Threadobjekt zugegriffen wird, ist der Treiber, der IoBuildAsynchronousFsdRequest aufgerufen hat, um das IRP zuzuweisen, dafür verantwortlich, dass das Threadobjekt während der Behandlung des IRP gültig bleibt.

Damit das Threadobjekt gültig bleibt, kann der Treiber, der IoBuildAsynchronousFsdRequest aufruft, vor dem Senden des IRP einen gezählten Verweis auf das Threadobjekt annehmen. Dieser Treiber kann beispielsweise die ObReferenceObjectByPointerWithTag-Routine aufrufen und als Object-Parameter den Objektzeiger aus dem Tail.Overlay.Thread-Member der IRP-Struktur bereitstellen. Später kann die Vervollständigungsroutine dieses Treibers das Objekt dereferenzieren, indem eine Routine wie ObDereferenceObjectWithTag aufgerufen wird.

Ein Treiber kann IoBuildAsynchronousFsdRequest in einem Thread aufrufen und die durch diesen Aufruf zugewiesene IRP in einem anderen Thread senden. Vor dem Senden des IRP sollte dieser Treiber festlegen, dass der Tail.Overlay.Thread-Member des IRP auf das Threadobjekt für den sendenden Thread verweist. In der Regel ruft der Treiber die PsGetCurrentThread-Routine auf, um den Threadobjektzeiger abzurufen.

Ein Treiber, der IoBuildAsynchronousFsdRequest aufruft, um eine IRP zuzuweisen, muss nicht unbedingt einen gezählten Verweis auf das Threadobjekt übernehmen, 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 der Treiber beispielsweise den Thread erstellt hat, kann der Thread warten, bis der IRP abgeschlossen ist, um sich selbst zu beenden.

Beispiele

Vor dem Aufrufen von IoFreeIrp ist ein zusätzlicher Schritt erforderlich, um den Puffer für ein von IoBuildAsynchronousFsdRequest erstelltes IRP frei zu geben, wenn alle folgenden Punkte zutrifft:

  • Der Puffer wurde aus dem Systemspeicherpool zugeordnet.

  • Im Geräteobjekt für das Zielgerät wird das DO_DIRECT_IO-Flag im Feld DeviceObject-Flags> festgelegt.

  • Das Feld "Irp-MdlAddress>" ist nicht 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 hat. Andernfalls wird beim nachfolgenden Aufruf von IoFreeMdl eine Fehlerüberprüfung durchgeführt, da die Verweisanzahl für diese Poolseiten 2 und nicht 1 ist. Das folgende Codebeispiel zeigt die Aufrufe MmUnlockPages, IoFreeMdl und IoFreeIrp 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 Universell
Header wdm.h (einschließlich Wdm.h, Ntddk.h, Ntifs.h)
Bibliothek NtosKrnl.lib
DLL NtosKrnl.exe
IRQL IRQL <= APC_LEVEL
DDI-Complianceregeln ForwardedAtBadIrqlFsdAsync(wdm), HwStorPortProhibitedDIs(storport), IoBuildFsdComplete(wdm), IoBuildFsdForward(wdm), IoBuildFsdFree(wdm)

Weitere Informationen

IO_STACK_LOCATION

IRP

IoAllocateIrp

IoBuildDeviceIoControlRequest

IoBuildSynchronousFsdRequest

IoCallDriver

IoFreeIrp

IoFreeMdl

IoMakeAssociatedIrp

IoSetCompletionRoutine

IoSetHardErrorOrVerifyDevice

MmUnlockPages

ObDereferenceObjectWithTag

ObReferenceObjectByPointerWithTag

PsGetCurrentThread