Metode IWDFIoRequest::UnmarkCancelable (wudfddi.h)

[Peringatan: UMDF 2 adalah versi terbaru UMDF dan pengganti UMDF 1. Semua driver UMDF baru harus ditulis menggunakan UMDF 2. Tidak ada fitur baru yang ditambahkan ke UMDF 1 dan ada dukungan terbatas untuk UMDF 1 pada versi Windows 10 yang lebih baru. Driver Universal Windows harus menggunakan UMDF 2. Untuk informasi selengkapnya, lihat Mulai menggunakan UMDF.]

Metode UnmarkCancelable menonaktifkan pembatalan permintaan I/O.

Sintaks

HRESULT UnmarkCancelable();

Mengembalikan nilai

UnmarkCancelable mengembalikan salah satu nilai berikut:

Menampilkan kode Deskripsi
S_OK

UnmarkCancelable menonaktifkan penggunaan metode IRequestCallbackCancel::OnCancel yang sebelumnya terdaftar melalui panggilan ke metode IWDFIoRequest::MarkCancelable .

HRESULT_FROM_WIN32 (ERROR_OPERATION_ABORTED)
Permintaan saat ini sedang dibatalkan.

Keterangan

Driver dapat memanggil IWDFIoRequest::UnmarkCancelable untuk menonaktifkan pembatalan permintaan I/O, jika driver sebelumnya disebut IWDFIoRequest::MarkCancelable untuk mengaktifkan pembatalan permintaan.

Jika driver sebelumnya disebut MarkCancelable, driver harus memanggil UnmarkCancelable sebelum memanggil IWDFIoRequest::Complete di luar panggilan ke metode panggilan IRequestCallbackCancel::OnCancel .

Namun, driver tidak boleh memanggil UnmarkCancelable setelah panggilan OnCancelSelesai.

Jika UnmarkCancelable mengembalikan HRESULT_FROM_WIN32(ERROR_OPERATION_ABORTED), lalu OnCancel menyelesaikan permintaan, driver tidak boleh menggunakan objek permintaan.

Jika UnmarkCancelable mengembalikan HRESULT_FROM_WIN32(ERROR_OPERATION_ABORTED), driver tidak boleh menyelesaikan permintaan sebelum kerangka kerja memanggil OnCancel. Jika tidak, kerangka kerja mungkin memanggil OnCancel driver dengan permintaan yang tidak valid.

Contoh

Contoh kode berikut menunjukkan bagaimana driver dapat memanggil IWDFIoRequest::UnmarkCancelable sebelum memanggil IWDFIoRequest::Complete, di luar panggilan ke metode IRequestCallbackCancel::OnCancel .

Contoh ini juga menunjukkan bagaimana Anda dapat menggunakan OnCancel untuk mempercepat penyelesaian permintaan. Dalam hal ini, panggilan balik OnCancel tidak selalu menyelesaikan/membatalkan permintaan yang ditentukan.

//
// The driver calls CompletePendingRequest when it is ready to complete the request with error/success.
// You must previously initialize m_CompleteCancelledRequest to zero.
//
VOID
CompletePendingRequest( 
    HRESULT hr,
    DWORD   information
    )
{
    LONG shouldComplete = 1;

    if (m_PendingRequest) {
        HRESULT hrUnmark = m_PendingRequest->UnmarkCancelable();
        if (HRESULT_FROM_WIN32(ERROR_OPERATION_ABORTED) == hrUnmark) { 
            //
            // We are racing with OnCancel.  We cannot complete m_PendingRequest until after
            // both IWDFIoRequest::Complete and OnCancel have finished with it. To
            // guarantee this, the last to run (either OnCancel or CompletePendingRequest) will
            // be the one to complete the request. 
            //
            shouldComplete = InterlockedExchange(&m_CompleteCancelledRequest, 1);
        }

        // 
        // If we were first to set m_CompleteCancelledRequest to 1, then drop out here
        // and rely on OnCancel to complete the request.
        // 

        if (1 == shouldComplete) { 
            IWDFIoRequest *FxRequest = (IWDFIoRequest*)InterlockedExchangePointer((PVOID *)&m_PendingRequest, NULL);
            InterlockedExchange(&m_CompleteCancelledRequest, 0);
            FxRequest->SetInformation(information);
            FxRequest->Complete(hr);
        }
   }
}

//
// The framework calls OnCancel when an application cancels a pending I/O request. 
//
VOID
STDMETHODCALLTYPE
OnCancel(
    _In_ IWDFIoRequest *pWdfRequest
    )
{
    if (m_PendingRequest != pWdfRequest) {
        TraceEvents(TRACE_LEVEL_ERROR, 
                    YOURDEVICE_TRACE_DEVICE, 
                    "%!FUNC! Cancelled request does not match pending request.");
    }

    // 
    // Add your code to speed up the completion of the request.  Maybe you need to reset the hardware or 
    // do some other domain-specific task.
    //

    //
    // Since we only complete the request if we were the last to run (see comment in
    // CompletePendingRequest), if we are *not* the last to run we rely on CompletePendingRequest 
    // to complete this request.
    //

    LONG shouldComplete = InterlockedExchange(&m_CompleteCancelledRequest, 1);
    if (1 == shouldComplete) { 
        //
        // Enter this block only if we are the last to run.
        // Otherwise, rely on CompletePendingRequest to complete this request.
        //
        (void*) InterlockedExchangePointer((PVOID *)&m_PendingRequest, NULL);
        InterlockedExchange(&m_CompleteCancelledRequest, 0);
        pWdfRequest->Complete(HRESULT_FROM_WIN32(ERROR_CANCELLED));
     } 
 
}


Dalam contoh kode berikutnya, driver menyimpan permintaan I/O dalam objek antrean yang diimplementasikan driver yang disebut MyQueue. Antarmuka MyQueue driver mengimplementasikan beberapa metode dasar untuk memanipulasi antrean, seperti IsEmpty, RemoveHead, Cleanup, GetFirstNodePosition, GetAt, dan RemoveAt.

Driver juga mendefinisikan struktur CommandInformation yang menyimpan satu permintaan I/O dari MyQueue.

Metode MyQueue::D eQueue menghapus permintaan I/O dari antrean, memanggil UnmarkCancelable untuk menonaktifkan pembatalan permintaan, lalu mengembalikan permintaan untuk diproses.


void MyQueue::DeQueue(__out CommandInformation* CommandInfo)
{
    CComCritSecLock<CComAutoCriticalSection> scopeLock(m_CriticalSection);

    if (NULL != CommandInfo)
    {
        for (;;) 
        {
            if (TRUE == IsEmpty()) 
            {
                ZeroMemory(CommandInfo, sizeof(CommandInformation));
                break;
            }
            //
            // If queue is not empty, retrieve the first element from the list.
            //
            *CommandInfo = RemoveHead(); 
            if (HRESULT_FROM_WIN32(ERROR_OPERATION_ABORTED) != (CommandInfo->Request)->UnmarkCancelable())
            {
                //
                // UnmarkCancelable was successful.
                // Ownership of this request has been transferred back to this driver.
                //
                break;
            }
            else
            {
                //
                // If UMDF returns HRESULT_FROM_WIN32(ERROR_OPERATION_ABORTED) for UnmarkCancelable,
                // that means UMDF is planning on cancelling the request. However, since this call
                // popped the request off our internal queue, let’s cleanup the generic command object
                // and let OnCancel complete the request.               
                //                
                CommandInfo->Cleanup();
            }
        }    
    }
}

//
// The framework calls OnCancel when an application cancels a dispatched I/O request.
//
void MyQueue::OnCancel(__in IWDFIoRequest* Request)
{
    {
        CComCritSecLock<CComAutoCriticalSection> scopeLock(m_CriticalSection);

        POSITION pos = GetFirstNodePosition();

        while (NULL != pos)
        {
            //
            // Find the request and remove it from our driver-implemented queue.
            //
            CommandInformation commandInfo = GetAt(pos);
            if (Request == commandInfo.Request)
            {
                RemoveAt(pos);
                commandInfo.Cleanup();
                break;
            }

            GetNext(pos);
        }
    }

    //
    // Cancel/Complete the request.
    //
    // The request might not be in the queue when the framework calls OnCancel. 
    // This occurs if DeQueue receives HRESULT_FROM_WIN32(ERROR_OPERATION_ABORTED)
    // when it calls UnmarkCancelable for the request. In this case, as soon as
    // DeQueue releases the scopeLock, the framework calls OnCancel to cancel the request.
    //
    Request->Complete(HRESULT_FROM_WIN32(ERROR_CANCELLED));
}



Lihat juga contoh kode di WdfRequestUnmarkCancelable. Saat ditulis untuk driver KMDF, contoh ini menunjukkan bagaimana Anda dapat menggunakan sinkronisasi otomatis kerangka kerja untuk mengelola sinkronisasi antara panggilan balik pembatalan dan utas lain yang memanggil rutinitas Unmark .

Persyaratan

Persyaratan Nilai
Akhir dukungan Tidak tersedia di UMDF 2.0 dan yang lebih baru.
Target Platform Desktop
Versi UMDF minimum 1,5
Header wudfddi.h (termasuk Wudfddi.h)
DLL WUDFx.dll

Lihat juga

IRequestCallbackCancel::OnCancel

IWDFIoRequest

IWDFIoRequest::Complete

IWDFIoRequest::MarkCancelable