Fungsi WdfRequestMarkCancelable (wdfrequest.h)
[Berlaku untuk KMDF dan UMDF]
Metode WdfRequestMarkCancelable memungkinkan pembatalan permintaan I/O tertentu.
Sintaks
void WdfRequestMarkCancelable(
[in] WDFREQUEST Request,
[in] PFN_WDF_REQUEST_CANCEL EvtRequestCancel
);
Parameter
[in] Request
Handel ke objek permintaan kerangka kerja.
[in] EvtRequestCancel
Penunjuk ke fungsi panggilan balik EvtRequestCancel yang ditentukan driver, yang dipanggil kerangka kerja jika membatalkan permintaan I/O.
Nilai kembali
Tidak ada
Keterangan
Pemeriksaan bug terjadi jika driver menyediakan handel objek yang tidak valid.
Setelah driver Anda menerima permintaan I/O dari kerangka kerja, driver dapat memanggil WdfRequestMarkCancelable atau, dimulai dengan KMDF versi 1.9, WdfRequestMarkCancelableEx untuk membuat permintaan dapat dibatalkan.
Saat memanggil WdfRequestMarkCancelable, driver Anda harus menentukan fungsi panggilan balik EvtRequestCancel . Kerangka kerja memanggil fungsi panggilan balik jika manajer I/O atau driver lain mencoba membatalkan permintaan I/O.
Memilih antara WdfRequestMarkCancelable dan WdfRequestMarkCancelableEx
Jika driver Anda menggunakan sinkronisasi otomatis kerangka kerja, driver dapat memanggil WdfRequestMarkCancelable atau WdfRequestMarkCancelableEx.Jika driver tidak menggunakan sinkronisasi otomatis, driver harus memanggil WdfRequestMarkCancelableEx alih-alih WdfRequestMarkCancelable karena alasan berikut:
- Jika permintaan yang ditentukan telah dibatalkan, WdfRequestMarkCancelable memanggil fungsi panggilan balik EvtRequestCancel driver sebelum kembali. Jika driver memperoleh spinlock sebelum memanggil WdfRequestMarkCancelable dan mencoba untuk memperoleh spinlock yang sama di dalam EvtRequestCancel, utas yang sama mencoba untuk memperoleh spinlock yang sama dua kali, menyebabkan kebuntuan.
- Namun, karena WdfRequestMarkCancelableEx tidak pernah memanggil EvtRequestCancel, skenario ini tidak terjadi. Jika permintaan telah dibatalkan, WdfRequestMarkCancelableEx mengembalikan STATUS_CANCELLED. Jika driver Anda memperoleh spinlock (yang mengatur IRQL ke DISPATCH_LEVEL) sebelum memanggil WdfRequestMarkCancelableEx dan melepaskan spinlock (yang mengatur IRQL ke PASSIVE_LEVEL) setelah WdfRequestMarkCancelableEx kembali, fungsi panggilan balik EvtRequestCancel tidak akan dipanggil sebelum spinlock dirilis. Oleh karena itu, kebuntuan tidak terjadi bahkan jika fungsi panggilan balik EvtRequestCancel menggunakan spinlock yang sama.
Memproses permintaan setelah mengaktifkan pembatalan
Setelah driver memanggil WdfRequestMarkCancelable untuk mengaktifkan pembatalan, permintaan tetap dapat dibatalkan sementara driver memiliki objek permintaan, kecuali driver memanggil WdfRequestUnmarkCancelable.Jika driver telah memanggil WdfRequestMarkCancelable, dan jika fungsi panggilan balik EvtRequestCancel driver belum dijalankan dan disebut WdfRequestComplete, driver harus memanggil WdfRequestUnmarkCancelable sebelum memanggil WdfRequestComplete di luar fungsi panggilan balik EvtRequestCancel .
Jika driver memanggil WdfRequestForwardToIoQueue untuk meneruskan permintaan ke antrean yang berbeda, aturan berikut berlaku:
-
Permintaan I/O tidak dapat dibatalkan ketika driver Anda meneruskannya ke antrean yang berbeda.
Umumnya, driver Anda tidak boleh memanggil WdfRequestMarkCancelable untuk mengaktifkan pembatalan permintaan sebelum memanggil WdfRequestForwardToIoQueue. Jika driver membuat permintaan dapat dibatalkan, driver harus memanggil WdfRequestUnmarkCancelable untuk menonaktifkan pembatalan sebelum memanggil WdfRequestForwardToIoQueue.
-
Saat permintaan berada dalam antrean kedua, kerangka kerja memilikinya dan dapat membatalkannya tanpa memberi tahu driver.
Jika driver memerlukan pemberitahuan pembatalan (sehingga dapat membatalkan alokasi sumber daya apa pun yang mungkin telah dialokasikan sebelum memanggil WdfRequestForwardToIoQueue), driver harus mendaftarkan fungsi panggilan balik EvtIoCanceledOnQueue , dan harus menggunakan memori konteks khusus permintaan untuk menyimpan informasi tentang sumber daya permintaan.
- Setelah kerangka kerja menghapus antrean permintaan dari antrean kedua dan mengirimkannya ke driver, driver dapat memanggil WdfRequestMarkCancelable untuk mengaktifkan pembatalan.
Contoh
Contoh kode berikut menunjukkan bagian dari dua fungsi panggilan balik:
- Fungsi panggilan balik EvtIoRead yang melakukan pekerjaan khusus permintaan (seperti membuat subkueri untuk dikirim ke target I/O), lalu mengaktifkan pembatalan permintaan I/O yang diterima.
- Fungsi panggilan balik EvtRequestCancel yang membatalkan permintaan I/O.
VOID
MyEvtIoRead(
IN WDFQUEUE Queue,
IN WDFREQUEST Request,
IN size_t Length
)
{
...
// Perform request-specific work here
// (such as creating subrequests
// to send to an I/O target).
...
WdfRequestMarkCancelable(
Request,
MyEvtRequestCancel
);
}
...
}
VOID
MyEvtRequestCancel(
IN WDFREQUEST Request
)
{
// Remove request-specific work here, because
// we don't want the work to be done if the
// request was canceled.
WdfRequestComplete(
Request,
STATUS_CANCELLED
);
}
Persyaratan
Persyaratan | Nilai |
---|---|
Target Platform | Universal |
Versi KMDF minimum | 1,0 |
Versi UMDF minimum | 2.0 |
Header | wdfrequest.h (termasuk Wdf.h) |
Pustaka | Wdf01000.sys (KMDF); WUDFx02000.dll (UMDF) |
IRQL | <=DISPATCH_LEVEL |
Aturan kepatuhan DDI | DeferredRequestCompleted(kmdf), DriverCreate(kmdf), EvtIoStopCancel(kmdf), InvalidReqAccess(kmdf), InvalidReqAccessLocal(kmdf), KmdfIrql(kmdf), KmdfIrql2(kmdf), KmdfIrqlExplicit(kmdf), MarkCancOnCancReqLocal(kmdf), ReqIsCancOnCancReq(kmdf), ReqMarkCancelableSend(kmdf), ReqNotCanceledLocal(kmdf), RequestCompleted(kmdf), RequestCompletedLocal( kmdf) |