IWDFIoRequest::UnmarkCancelable 方法 (wudfddi.h)
[警告: UMDF 2 是最新版的 UMDF,並取代 UMDF 1。 所有新的 UMDF 驅動程式都應該使用 UMDF 2 來撰寫。 未將新功能新增至 UMDF 1,而且較新版本的 Windows 10 上不支援 UMDF 1。 通用 Windows 驅動程式必須使用 UMDF 2。 如需詳細資訊,請參閱使用 UMDF 使用者入門。]
UnmarkCancelable 方法會停用 I/O 要求的取消。
Syntax
HRESULT UnmarkCancelable();
傳回值
UnmarkCancelable 會傳回下列其中一個值:
傳回碼 | 描述 |
---|---|
|
UnmarkCancelable 已停用先前透過 IWDFIoRequest::MarkCancelable 方法呼叫註冊的 IRequestCallbackCancel::OnCancel 方法。 |
|
要求目前正在取消。 |
備註
如果驅動程式先前稱為 IWDFIoRequest::MarkCancelable,可以呼叫 IWDFIoRequest::UnmarkCancelable 來停用 I/O 要求的取消。
如果驅動程式先前稱為 MarkCancelable,則驅動程式必須先呼叫 UnmarkCancelable ,再呼叫 IWDFIoRequest::Complete ,再呼叫其 IRequestCallbackCancel::OnCancel 回呼方法。
不過,在 OnCancel 呼叫 Complete 之後,驅動程式不得呼叫 UnmarkCancelable。
如果 UnmarkCancelable 傳回HRESULT_FROM_WIN32 (ERROR_OPERATION_ABORTED) ,然後 OnCancel 完成要求,驅動程式不得後續使用要求物件。
如果 UnmarkCancelable 傳回HRESULT_FROM_WIN32 (ERROR_OPERATION_ABORTED) ,則驅動程式在架構呼叫 OnCancel 之前,不得完成要求。 否則,架構可能會以無效的要求呼叫驅動程式的 OnCancel 。
範例
下列程式代碼範例示範驅動程式如何在呼叫其 IRequestCallbackCancel::OnCancel 方法之前呼叫 IWDFIoRequest::Complete 之前呼叫 IWDFIoRequest::Complete。
此範例也會示範如何使用 OnCancel 來加速完成要求。 在此情況下, OnCancel 回呼不一定會完成/取消指定的要求。
//
// 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));
}
}
在下一個程式代碼範例中,驅動程式會將I/O要求儲存在名為 MyQueue 的驅動程序實作佇列物件中。 驅動程式的 MyQueue 介面會實作一些基本方法來操作佇列,例如 IsEmpty、 RemoveHead、 Cleanup、 GetFirstNodePosition、 GetAt 和 RemoveAt。
驅動程式也會定義 CommandInformation 結構,以保存 來自 MyQueue 的單一 I/O 要求。
MyQueue::D eQueue 方法會從佇列移除 I/O 要求、呼叫 UnmarkCancelable 以停用取消要求,然後傳回處理要求。
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));
}
另請參閱 WdfRequestUnmarkCancelable 上的程式碼範例。 針對 KMDF 驅動程式撰寫時,此範例示範如何使用架構的 自動同步 處理來管理取消回呼與另一個呼叫 Unmark 例程的線程之間的同步處理。
規格需求
需求 | 值 |
---|---|
終止支援 | UMDF 2.0 和更新版本中無法使用。 |
目標平台 | 桌面 |
最低UMDF版本 | 1.5 |
標頭 | wudfddi.h (包括 Wudfddi.h) |
Dll | WUDFx.dll |