Vor- und Nachverarbeitung von IRPs

[Gilt nur für KMDF]

Wenn Ihr Treiber ein E/A-Anforderungspaket (IRP) vor oder nach der Verarbeitung des IRP durch das Framework abfangen muss, kann der Treiber WdfDeviceInitAssignWdmIrpPreprocessCallback aufrufen, um eine EvtDeviceWdmIrpPreprocess-Ereignisrückruffunktion für einen Haupt-E/A-Funktionscode und optional für bestimmte kleinere E/A-Funktionscodes zu registrieren, die dem Hauptcode zugeordnet sind. Anschließend ruft das Framework die EvtDeviceWdmIrpPreprocess-Rückruffunktion des Treibers auf, wenn der Treiber ein IRP empfängt, das einen angegebenen Haupt- und Nebenfunktionscode enthält.

Die Rückruffunktion EvtDeviceWdmIrpPreprocess kann alles tun, was erforderlich ist, um das IRP vorzuverarbeiten, und dann muss sie WdfDeviceWdmDispatchPreprocessedIrp aufrufen, um das IRP an das Framework zurückzugeben, es sei denn, der Treiber verarbeitet ein IRP, das vom Framework nicht unterstützt wird.

Nachdem der Treiber WdfDeviceWdmDispatchPreprocessedIrp aufgerufen hat, verarbeitet das Framework den IRP auf die gleiche Weise wie, wenn der Treiber keine EvtDeviceWdmIrpPreprocess-Rückruffunktion bereitgestellt hätte. Wenn der I/O-Funktionscode des IRP einer ist, den das Framework an Treiber übergibt, empfängt der Treiber das IRP erneut als Anforderungsobjekt.

Wenn der Treiber den IRP nach abschluss des IRP durch einen Treiber auf niedrigerer Ebene nachverarbeiten muss, kann die EvtDeviceWdmIrpPreprocess-Rückruffunktion des Treibers IoSetCompletionRoutine aufrufen, um eine IoCompletion-Routine festzulegen, bevor WdfDeviceWdmDispatchPreprocessedIrp aufgerufen wird.

Nachdem Ihr Treiber WdfDeviceInitAssignWdmIrpPreprocessCallback aufgerufen hat, bewirkt das Framework, dass der E/A-Manager allen IRPs einen zusätzlichen E/A-Stapelspeicherort hinzugibt, sodass die EvtDeviceWdmIrpPreprocess-Rückruffunktion eine IoCompletion-Routine festlegen kann. Die Rückruffunktion muss den I/O-Stapelspeicherort des IRP aktualisieren, bevor WdfDeviceWdmDispatchPreprocessedIrp aufgerufen wird.

Aufrufen von WdfDeviceWdmDispatchPreprocessedIrp

Da der E/A-Manager dem IRP einen zusätzlichen E/A-Stapelspeicherort hinzufügt, muss die Rückruffunktion EvtDeviceWdmIrprocessioSkipCurrentIrpStackLocation oder IoCopyCurrentIrpStackLocationToNext aufrufen (um den nächsten E/A-Stapelspeicherort im IRP einzurichten), bevor WdfDeviceWdmDispatchPreprocessEdIrp aufgerufen wird.

Wenn Ihr Treiber ein IRP vorverarbeitet, aber das IRP nicht nachverarbeitet, muss der Treiber keine IoCompletion-Routine für das IRP festlegen und kann IoSkipCurrentIrpStackLocation aufrufen, wie im folgenden Codebeispiel gezeigt.

NTSTATUS
  EvtDeviceMyIrpPreprocess(
    IN WDFDEVICE Device,
    IN OUT PIRP Irp
    )
{
//
// Perform IRP preprocessing operations here.
//
...
//
// Deliver the IRP back to the framework. 
//
IoSkipCurrentIrpStackLocation(Irp);
return WdfDeviceWdmDispatchPreprocessedIrp(Device, Irp);
}

Wenn Ihr Treiber die IRP nachverarbeitet, muss der Treiber IoCopyCurrentIrpStackLocationToNext aufrufen und dann IoSetCompletionRoutine aufrufen, um eine IoCompletion-Routine für das IRP festzulegen, wie im folgenden Codebeispiel gezeigt.

NTSTATUS
  EvtDeviceMyIrpPreprocess(
    IN WDFDEVICE Device,
    IN OUT PIRP Irp
    )
{
//
// Perform IRP preprocessing operations here, if needed.
//
...
//
// Set a completion routine and deliver the IRP back to
// the framework. 
//
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(
                       Irp,
                       MyIrpCompletionRoutine,
                       NULL,
                       TRUE,
                       TRUE,
                       TRUE
                      );
return WdfDeviceWdmDispatchPreprocessedIrp(Device, Irp);
}

Ihr Treiber darf IoCopyCurrentIrpStackLocationToNext nicht aufrufen (und darf daher keine IoCompletion-Routine festlegen), wenn das Geräteobjekt handle, das die EvtDeviceWdmIrpPreprocess-Rückruffunktion des Treibers empfängt, ein physisches Geräteobjekt (PDO) darstellt, und wenn der Hauptfunktionscode des IRP IRP_MJ_PNP oder IRP_MJ_POWER ist. Andernfalls meldet driver verifier einen Fehler.

Weitere Informationen zum Aufrufen von IoCopyCurrentIrpStackLocationToNext, IoSkipCurrentIrpStackLocation und IoSetCompletionRoutine finden Sie unter Übergeben von IRPs im Treiberstapel.