Bagikan melalui


Pemrosesan Awal dan Pemrosesan Akhir IRP

[Hanya berlaku untuk KMDF]

Jika driver Anda harus mencegat paket permintaan I/O (IRP) sebelum atau setelah kerangka kerja menangani IRP, driver dapat memanggil WdfDeviceInitAssignWdmIrpPreprocessCallback untuk mendaftarkan EvtDeviceWdmIrpPreprocess fungsi panggilan balik peristiwa untuk kode fungsi I/O utama dan, secara opsional, untuk kode fungsi I/O kecil tertentu yang terkait dengan kode utama. Selanjutnya, kerangka kerja memanggil fungsi callback EvtDeviceWdmIrpPreprocess dari driver setiap kali driver menerima IRP yang berisi kode fungsi mayor dan minor tertentu.

Fungsi panggilan balik EvtDeviceWdmIrpPreprocess dapat melakukan apa pun yang diperlukan untuk melakukan praprosem IRP, dan kemudian harus memanggil WdfDeviceWdmDispatchPreprocessedIrp untuk mengembalikan IRP ke kerangka kerja kecuali driver menangani IRP yang tidak didukung kerangka kerja.

Setelah driver memanggil WdfDeviceWdmDispatchPreprocessedIrp, kerangka kerja memproses IRP dengan cara yang sama seperti yang akan dilakukan jika driver tidak menyediakan fungsi panggilan balik EvtDeviceWdmIrpPreprocess. Jika kode fungsi I/O IRP adalah kode yang diteruskan kerangka kerja ke driver, driver akan menerima IRP lagi sebagai objek permintaan.

Jika driver perlu memproses ulang IRP setelah driver tingkat bawah menyelesaikan IRP, fungsi panggilan balik EvtDeviceWdmIrpPreprocess dapat memanggil IoSetCompletionRoutine untuk menyetel rutinitas IoCompletion sebelum memanggil WdfDeviceWdmDispatchPreprocessedIrp.

Setelah driver Anda memanggil WdfDeviceInitAssignWdmIrpPreprocessCallback, kerangka kerja menyebabkan manajer I/O menambahkan tumpukan I/O tambahan lokasi ke semua RUN sehingga fungsi panggilan balikEvtDeviceWdmIrpPreprocess dapat mengatur IoCompletion rutinitas. Fungsi panggilan balik harus memperbarui penunjuk lokasi tumpukan I/O IRP sebelum memanggil WdfDeviceWdmDispatchPreprocessedIrp.

Memanggil WdfDeviceWdmDispatchPreprocessedIrp

Karena manajer I/O menambahkan lokasi tumpukan I/O tambahan ke IRP, fungsi panggilan balikEvtDeviceWdmIrpPreprocess harus memanggil IoSkipCurrentIrpStackLocation atau IoCopyCurrent IrpStackLocationToNext (untuk menyiapkan lokasi tumpukan I/O berikutnya di IRP) sebelum memanggil WdfDeviceWdmDispatchPreprocessedIrp.

Jika driver Anda melakukan praproses IRP, tetapi tidak pascaproses IRP, driver tidak perlu mengatur IoCompletion rutin untuk IRP dan dapat memanggil IoSkipCurrentIrpStackLocation, seperti yang ditunjukkan contoh kode berikut.

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

Jika driver Anda memproses IRP setelahnya, driver harus memanggil IoCopyCurrentIrpStackLocationToNext, kemudian memanggil IoSetCompletionRoutine untuk menetapkan rutinasi IoCompletion untuk IRP, seperti yang ditunjukkan dalam contoh kode berikut.

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

Driver Anda tidak boleh memanggil IoCopyCurrentIrpStackLocationToNext (dan oleh karena itu tidak boleh mengatur rutin IoCompletion) jika objek perangkat yang diterima oleh fungsi panggilan balik EvtDeviceWdmIrpPreprocess driver mewakili objek perangkat fisik (PDO), dan jika kode fungsi utama IRP adalah IRP_MJ_PNP atau IRP_MJ_POWER. Jika tidak, Driver Verifier akan melaporkan kesalahan.

Untuk informasi selengkapnya tentang kapan harus memanggil IoCopyCurrentIrpStackLocationToNext, IoSkipCurrentIrpStackLocation, dan IoSetCompletionRoutine, lihat Passing IRPs ke bawah Driver Stack.