Fungsi WdfRequestMarkCancelableEx (wdfrequest.h)

[Berlaku untuk KMDF dan UMDF]

Metode WdfRequestMarkCancelableEx memungkinkan pembatalan permintaan I/O tertentu.

Sintaks

NTSTATUS WdfRequestMarkCancelableEx(
  [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

WdfRequestMarkCancelableEx mengembalikan STATUS_SUCCESS jika berhasil mengaktifkan pembatalan permintaan I/O yang ditentukan. Jika tidak, metode ini mungkin mengembalikan salah satu nilai berikut:

Menampilkan kode Deskripsi
STATUS_CANCELLED
Permintaan I/O telah dibatalkan. Lihat Keterangan untuk informasi selengkapnya.
STATUS_INVALID_DEVICE_REQUEST
  • Driver tidak memiliki permintaan I/O.
  • Permintaan I/O sudah dapat dibatalkan.
 

Metode ini mungkin juga mengembalikan nilai NTSTATUS lainnya.

Pemeriksaan bug terjadi jika driver menyediakan handel objek yang tidak valid.

Keterangan

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. Untuk informasi tentang memilih antara dua metode, lihat WdfRequestMarkCancelable.

Saat memanggil WdfRequestMarkCancelableEx, 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.

Jika WdfRequestMarkCancelableEx mengembalikan kegagalan, driver harus melakukan aktivitas pembatalan yang sama dengan yang dilakukan fungsi panggilan balik EvtRequestCancel . Contohnya:

  1. Selesaikan atau hentikan pemrosesan permintaan, bersama dengan subrequest yang mungkin telah dibuat.
  2. Panggil WdfRequestComplete, menentukan nilai status STATUS_CANCELLED.
Lihat contoh kode di bawah ini untuk implementasi.

Karena WdfRequestMarkCancelableEx tidak pernah memanggil EvtRequestCancel, metode ini aman dari risiko kebuntuan yang dijelaskan dalam Keterangan WdfRequestMarkCancelable.

Memproses permintaan setelah mengaktifkan pembatalan

Setelah driver memanggil WdfRequestMarkCancelableEx untuk mengaktifkan pembatalan, permintaan tetap dapat dibatalkan sementara driver memiliki objek permintaan, kecuali driver memanggil WdfRequestUnmarkCancelable.

Jika driver telah memanggil WdfRequestMarkCancelableEx, 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 WdfRequestMarkCancelableEx 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 WdfRequestMarkCancelableEx untuk mengaktifkan pembatalan.
Untuk informasi selengkapnya tentang WdfRequestMarkCancelableEx, lihat Membatalkan Permintaan I/O.

Contoh

Contoh kode berikut menunjukkan bagian dari dua fungsi panggilan balik:

  • Fungsi panggilan balik EvtIoRead yang melakukan pekerjaan khusus permintaan (seperti membuat subrequest untuk dikirim ke target I/O), lalu mengaktifkan pembatalan permintaan I/O yang diterima.
  • Fungsi panggilan balik EvtRequestCancel yang membatalkan permintaan I/O.
Dalam contoh pertama, driver menggunakan sinkronisasi otomatis kerangka kerja. Dalam contoh kedua, driver menyediakan sinkronisasinya sendiri dengan menggunakan spinlock.

Contoh 1: Driver yang menggunakan sinkronisasi otomatis.

VOID
MyEvtIoRead(
    IN WDFQUEUE  Queue,
    IN WDFREQUEST  Request,
    IN size_t  Length
    )
{
...
    NTSTATUS status;
...
    // Perform request-specific work here
    // (such as creating subrequests 
    // to send to an I/O target). 
...
    status = WdfRequestMarkCancelableEx(
                                        Request,
                                        MyEvtRequestCancel
                                        );

    if (!NT_SUCCESS(status)) {
       // Remove request-specific work here, because
       // we don't want the work to be done if the
       // request was canceled or an error occurred.

        WdfRequestComplete (Request, status);
    }
...
}

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

Contoh 2: Driver yang menggunakan sinkronisasinya sendiri.

VOID
MyEvtIoRead(
    IN WDFQUEUE  Queue,
    IN WDFREQUEST  Request,
    IN size_t  Length
    )
{
...
    NTSTATUS status;
...
    WdfSpinlockAcquire(MyCancelSpinLock);
    // Perform request-specific work here
    // (such as creating subrequests 
    // to send to an I/O target). 
...
    status = WdfRequestMarkCancelableEx(
                                        Request,
                                        MyEvtRequestCancel
                                        );

    if (!NT_SUCCESS(status)) {
        // Remove request-specific work here, because
        // we don't want the work to be done if the
        // request was canceled or an error occurred.
     }
    WdfSpinlockRelease(MyCancelSpinLock);
    if (!NT_SUCCESS(status)) {
        WdfRequestComplete (
                            Request,
                            Status
                            );
    }
...
}
VOID
MyEvtRequestCancel(
    IN WDFREQUEST  Request
 )
{
    WdfSpinlockAcquire(MyCancelSpinLock);
    // Remove request-specific work here, because
    // we don't want the work to be done if the
    // request was canceled.
    WdfSpinlockRelease(MyCancelSpinLock);
    WdfRequestComplete (Request, STATUS_CANCELLED);
}

Persyaratan

Persyaratan Nilai
Target Platform Universal
Versi KMDF minimum 1.9
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)

Lihat juga

EvtRequestCancel

WdfRequestComplete

WdfRequestForwardToIoQueue

WdfRequestMarkCancelable

WdfRequestUnmarkCancelable