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 要求の取り消しを無効にします。
構文
HRESULT UnmarkCancelable();
戻り値
UnmarkCancelable は、次のいずれかの値を返します。
リターン コード | 説明 |
---|---|
|
IWDFIoRequest::MarkCancelable メソッドの呼び出しによって以前に登録された IRequestCallbackCancel::OnCancel メソッドの使用を無効にしました。 |
|
要求は現在取り消されています。 |
注釈
ドライバーは 、以前に IWDFIoRequest::MarkCancelable を呼び出して要求の取り消しを有効にした場合に、 IWDFIoRequest::UnmarkCancelable を呼び出して I/O 要求の取り消しを無効にすることができます。
ドライバーが以前に MarkCancelable を呼び出した場合、ドライバーは IWDFIoRequest::Complete を呼び出す前に UnmarkCancelable を呼び出す必要があります。IRequestCallbackCancel::OnCancel コールバック メソッドの呼び出しの外部で完了します。
ただし、OnCancel が Complete を呼び出した後、ドライバーは UnmarkCancelable を呼び出してはなりません。
UnmarkCancelable が HRESULT_FROM_WIN32(ERROR_OPERATION_ABORTED) を返し、OnCancel が要求を完了した場合、ドライバーは要求オブジェクトを使用してはいけません。
UnmarkCancelable が HRESULT_FROM_WIN32(ERROR_OPERATION_ABORTED) を返す場合、フレームワークが OnCancel を呼び出す前に、ドライバーが要求を完了してはなりません。 それ以外の場合、フレームワークは無効な要求でドライバーの OnCancel を呼び出す可能性があります。
例
次のコード例は、ドライバーが IWDFIoRequest::UnmarkCancelable を呼び出す前に IWDFIoRequest::Complete を呼び出す方法を示しています。 IRequestCallbackCancel::OnCancel メソッドの呼び出しの外部。
この例では、 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));
}
}
次のコード例では、ドライバーは MyQueue というドライバー実装キュー オブジェクトに I/O 要求を格納します。 ドライバーの MyQueue インターフェイスには、 IsEmpty、 RemoveHead、 Cleanup、 GetFirstNodePosition、 GetAt、 RemoveAt など、キューを操作するための基本的なメソッドがいくつか実装されています。
ドライバーは、MyQueue からの単一の I/O 要求を保持する CommandInformation 構造体も定義します。
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 |
Header | wudfddi.h (Wudfddi.h を含む) |
[DLL] | WUDFx.dll |