Método IWDFIoRequest::UnmarkCancelable (wudfddi.h)
[Advertencia: UMDF 2 es la versión más reciente de UMDF y sustituye a UMDF 1. Todos los nuevos controladores UMDF deben escribirse mediante UMDF 2. No se agregan nuevas características a UMDF 1 y hay compatibilidad limitada con UMDF 1 en versiones más recientes de Windows 10. Los controladores universales de Windows deben usar UMDF 2. Para obtener más información, consulta Introducción a UMDF.]
El método unmarkCancelable deshabilita la cancelación de una solicitud de E/S.
Sintaxis
HRESULT UnmarkCancelable();
Valor devuelto
UnmarkCancelable devuelve uno de los siguientes valores:
Código devuelto | Descripción |
---|---|
|
unmarkCancelable uso deshabilitado del método IRequestCallbackCancel::OnCancel que se registró anteriormente mediante una llamada al método IWDFIoRequest::MarkCancelable. |
|
La solicitud se está cancelando actualmente. |
Observaciones
Un controlador puede llamar a IWDFIoRequest::UnmarkCancelable para deshabilitar la cancelación de una solicitud de E/S, si el controlador llamó anteriormente a IWDFIoRequest::MarkCancelable para habilitar la cancelación de la solicitud.
Si el controlador llamó anteriormente a MarkCancelable, el controlador debe llamar a UnmarkCancelable antes de llamar a IWDFIoRequest::Complete fuera de una llamada a su IRequestCallbackCancel::OnCancel método de devolución de llamada.
Sin embargo, el controlador no debe llamar a UnmarkCancelable después de llamadas a OnCancelComplete.
Si UnmarkCancelable devuelve HRESULT_FROM_WIN32(ERROR_OPERATION_ABORTED) y, a continuación, OnCancel completa la solicitud, el controlador no debe usar posteriormente el objeto request.
Si UnmarkCancelable devuelve HRESULT_FROM_WIN32(ERROR_OPERATION_ABORTED), el controlador no debe completar la solicitud antes de que el marco llame a OnCancel. De lo contrario, el marco podría llamar al onCancel del controlador con una solicitud no válida.
Ejemplos
En el ejemplo de código siguiente se muestra cómo un controlador puede llamar a IWDFIoRequest::UnmarkCancelable antes de llamar a IWDFIoRequest::Complete, fuera de una llamada a su método IRequestCallbackCancel::OnCancel.
En el ejemplo también se muestra cómo puede usar onCancel para acelerar la finalización de una solicitud. En este caso, el OnCancel devolución de llamada no siempre se completa o cancela la solicitud especificada.
//
// 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));
}
}
En el ejemplo de código siguiente, el controlador almacena las solicitudes de E/S en un objeto de cola implementado por controladores denominado MyQueue. La interfaz de myQueue del controlador implementa algunos métodos básicos para manipular la cola, como IsEmpty, RemoveHead, Cleanup, GetFirstNodePosition, GetAty RemoveAt.
El controlador también define una estructura CommandInformation que contiene una única solicitud de E/S de MyQueue.
El método MyQueue::D eQueue quita una solicitud de E/S de la cola, llama a UnmarkCancelable para deshabilitar la cancelación de la solicitud y, a continuación, devuelve la solicitud de procesamiento.
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));
}
Vea también el ejemplo de código en WdfRequestUnmarkCancelable. Mientras se escribe para un controlador KMDF, en este ejemplo se muestra cómo puede usar el de sincronización automática del marco administrar la sincronización entre la devolución de llamada de cancelación y otro subproceso que llama a la rutina Desmarcar .
Requisitos
Requisito | Valor |
---|---|
fin del soporte técnico | No disponible en UMDF 2.0 y versiones posteriores. |
de la plataforma de destino de | Escritorio |
versión mínima de UMDF | 1.5 |
encabezado de | wudfddi.h (incluya Wudfddi.h) |
DLL de | WUDFx.dll |