Freigeben über


IO_COMPLETION_ROUTINE Rückruffunktion (wdm.h)

Die IoCompletion Routine schließt die Verarbeitung von E/A-Vorgängen ab.

Syntax

IO_COMPLETION_ROUTINE IoCompletionRoutine;

NTSTATUS IoCompletionRoutine(
  [in]           PDEVICE_OBJECT DeviceObject,
  [in]           PIRP Irp,
  [in, optional] PVOID Context
)
{...}

Parameter

[in] DeviceObject

Vom Aufrufer bereitgestellter Zeiger auf eine DEVICE_OBJECT Struktur. Dies ist das Geräteobjekt für das Zielgerät, das zuvor vom AddDevice Routine des Treibers erstellt wurde.

[in] Irp

Vom Aufrufer bereitgestellter Zeiger auf eine IRP--Struktur, die den E/A-Vorgang beschreibt.

[in, optional] Context

Vom Aufrufer bereitgestellter Zeiger auf treiberspezifische Kontextinformationen, die zuvor beim Aufrufen IoSetCompletionRoutine oder IoSetCompletionRoutineEx-angegeben wurden. Kontextinformationen müssen im nicht seitenseitigen Speicher gespeichert werden, da eine IoCompletion- Routine bei DISPATCH_LEVEL aufgerufen werden kann. Weitere Informationen finden Sie im folgenden Abschnitt "Hinweise".

Rückgabewert

Wenn die IoCompletion Routine bestimmt, dass für das IRP zusätzliche Verarbeitung erforderlich ist, muss sie STATUS_MORE_PROCESSING_REQUIRED zurückgeben. Weitere Informationen finden Sie im folgenden Abschnitt "Hinweise". Andernfalls sollte STATUS_SUCCESS zurückgegeben werden. (Der E/A-Manager sucht nur nach dem Vorhandensein oder Fehlen von STATUS_MORE_PROCESSING_REQUIRED.)

Bemerkungen

Die IoCompletion Routine eines Treibers wird in einem beliebigen Thread- oder DPC-Kontext und an einem IRQL ausgeführt, der kleiner oder gleich DISPATCH_LEVEL ist. Da Code, der bei DISPATCH_LEVEL ausgeführt wird, auch auf niedrigeren Ebenen ausgeführt wird, sollten IoCompletion- Routinen für die Ausführung bei DISPATCH_LEVEL entwickelt werden. Da diese Routinen jedoch nicht garantiert werden, bei DISPATCH_LEVEL ausgeführt werden, dürfen sie keine Systemroutinen aufrufen, die tatsächlich eine Ausführung bei DISPATCH_LEVEL erfordern. (Weitere Informationen zu IRQLs finden Sie unter Verwalten von Hardwareprioritäten.)

Um eine IoCompletion- Routine für ein bestimmtes IRP zu registrieren, muss ein Treiber IoSetCompletionRoutine oder IoSetCompletionRoutineExaufrufen, in dem die Adresse der IoCompletion Routine im I/O-Stapel des nächsten Treibers gespeichert wird. (Daher kann ein Treiber auf unterster Ebene keine IoCompletion- Routine registrieren.) Ein Treiber ruft in der Regel IoSetCompletionRoutine oder IoSetCompletionRoutineEx aus einer seiner Dispatch-Routinen auf, jedes Mal, wenn ein IRP empfangen wird. Die meisten Treiber, einschließlich aller PnP-Treiber, können IoSetCompletionRoutine- verwenden, um ihre IoCompletion Routine zu registrieren. Nicht-PnP-Treiber, die vor der Ausführung ihrer IoCompletion-Routine möglicherweise entladen werden, sollten stattdessen IoSetCompletionRoutineEx- verwenden.

Wenn ein Treiber ein IRP abgeschlossen hat, ruft er IoCompleteRequestauf, die wiederum die IoCompletion-Routine jedes höheren Treibers vom höchsten zum höchsten Aufruf aufruft, bis alle höheren IoCompletion- Routinen aufgerufen wurden oder bis eine Routine STATUS_MORE_PROCESSING_REQUIRED zurückgibt.

Wenn Sie das IRP erstellen, weisen Sie einen Stapelspeicherort für den aktuellen Treiber sowie alle niedrigeren Treiber zu. Wenn Sie keine ausreichenden Stapelspeicherorte zuweisen, wird der DeviceObject Zeiger möglicherweise auf NULL- festgelegt, wenn die Abschlussroutine aufgerufen wird. Sie können die Zuordnung zusätzlicher Stapelposition für den aktuellen Treiber vermeiden, wenn Sie das Feld Context verwenden, um Informationen an IoCompletion- zu übergeben, anstatt sich auf den parameter DeviceObject zu verlassen.

Wenn eine IoCompletion- Routine STATUS_MORE_PROCESSING_REQUIRED zurückgibt, gibt der Aufruf des niedrigeren Treibers an IoCompleteRequest sofort zurück. In diesem Fall muss ein Treiber auf höherer Ebene IoCompleteRequest- aufrufen, um das IRP abzuschließen.

Weitere Informationen zum Implementieren von IoCompletion Routinen finden Sie unter Abschließen von IRPs.

Beispiele

Um eine IoCompletion- Rückrufroutine zu definieren, müssen Sie zuerst eine Funktionsdeklaration bereitstellen, die den Typ der von Ihnen definierten Rückrufroutine identifiziert. Windows stellt eine Reihe von Rückruffunktionstypen für Treiber bereit. Durch das Deklarieren einer Funktion mithilfe der Rückruffunktionstypen können Codeanalyse für Treiber, statische Treiberüberprüfung (SDV) und andere Überprüfungstools Fehler finden, und es ist eine Anforderung zum Schreiben von Treibern für das Windows-Betriebssystem.

Wenn Sie beispielsweise eine IoCompletion- Rückrufroutine definieren möchten, die MyIoCompletionheißt, verwenden Sie den IO_COMPLETION_ROUTINE Typ, wie in diesem Codebeispiel gezeigt:

IO_COMPLETION_ROUTINE MyIoCompletion;

Implementieren Sie dann Ihre Rückrufroutine wie folgt:

_Use_decl_annotations_
NTSTATUS
  MyIoCompletion(
    PDEVICE_OBJECT  DeviceObject,
    PIRP  Irp,
    PVOID  Context
    )
  {
      // Function body
  }

Der IO_COMPLETION_ROUTINE Funktionstyp wird in der Wdm.h-Headerdatei definiert. Um Fehler genauer zu identifizieren, wenn Sie die Codeanalysetools ausführen, müssen Sie der Funktionsdefinition die _Use_decl_annotations_ Anmerkung hinzufügen. Die _Use_decl_annotations_ Anmerkung stellt sicher, dass die Anmerkungen, die auf den Funktionstyp IO_COMPLETION_ROUTINE in der Headerdatei angewendet werden, verwendet werden. Weitere Informationen zu den Anforderungen für Funktionsdeklarationen finden Sie unter Deklarieren von Funktionen mithilfe von Funktionsrollentypen für WDM-Treiber. Informationen zu _Use_decl_annotations_finden Sie unter Annotating Function Behavior.

Anforderungen

Anforderung Wert
Zielplattform- Desktop
Header- wdm.h (include Wdm.h, Ntddk.h, Ntifs.h)
IRQL- Wird bei IRQL-<= DISPATCH_LEVEL aufgerufen (siehe Abschnitt "Hinweise").