Compartir a través de


Función WdfRequestMarkCancelableEx (wdfrequest.h)

[Se aplica a KMDF y UMDF]

El método WdfRequestMarkCancelableEx habilita la cancelación de una solicitud de E/S especificada.

Sintaxis

NTSTATUS WdfRequestMarkCancelableEx(
  [in] WDFREQUEST             Request,
  [in] PFN_WDF_REQUEST_CANCEL EvtRequestCancel
);

Parámetros

[in] Request

Identificador de un objeto de solicitud de marco.

[in] EvtRequestCancel

Puntero a una función de devolución de llamada EvtRequestCancel definida por el controlador, que el marco llama si cancela la solicitud de E/S.

Valor devuelto

WdfRequestMarkCancelableEx devuelve STATUS_SUCCESS si habilita correctamente la cancelación de la solicitud de E/S especificada. De lo contrario, este método podría devolver uno de los siguientes valores:

Código devuelto Descripción
STATUS_CANCELLED
Se ha cancelado la solicitud de E/S. Consulta Comentarios para obtener más información.
STATUS_INVALID_DEVICE_REQUEST
  • El controlador no posee la solicitud de E/S.
  • La solicitud de E/S ya se puede cancelar.
 

Este método también podría devolver otros valores NTSTATUS.

Se produce una comprobación de errores si el controlador proporciona un identificador de objeto no válido.

Comentarios

Una vez que el controlador haya recibido una solicitud de E/S del marco, el controlador puede llamar a WdfRequestMarkCancelable o, a partir de la versión 1.9 de KMDF, WdfRequestMarkCancelableEx para que la solicitud se pueda cancelar. Para obtener información sobre cómo elegir entre los dos métodos, consulte WdfRequestMarkCancelable.

Al llamar a WdfRequestMarkCancelableEx, el controlador debe especificar una función de devolución de llamada EvtRequestCancel . El marco llama a la función de devolución de llamada si el administrador de E/S u otro controlador está intentando cancelar la solicitud de E/S.

Si WdfRequestMarkCancelableEx devuelve un error, el controlador debe realizar las mismas actividades de cancelación que realiza la función de devolución de llamada EvtRequestCancel . Por ejemplo:

  1. Finalice o detenga el procesamiento de la solicitud, junto con subrecquests que podría haber creado.
  2. Llame a WdfRequestComplete y especifique un valor de estado de STATUS_CANCELLED.
Consulte los ejemplos de código siguientes para la implementación.

Dado que WdfRequestMarkCancelableEx nunca llama a EvtRequestCancel, este método es seguro del riesgo de interbloqueo descrito en los comentarios de WdfRequestMarkCancelable.

Procesamiento de una solicitud después de habilitar la cancelación

Una vez que un controlador llama a WdfRequestMarkCancelableEx para habilitar la cancelación, la solicitud permanece cancelable mientras el controlador posee el objeto de solicitud, a menos que el controlador llame a WdfRequestUnmarkCancelable.

Si un controlador ha llamado a WdfRequestMarkCancelableEx y si la función de devolución de llamada EvtRequestCancel del controlador no se ha ejecutado y llamado A WdfRequestComplete, el controlador debe llamar a WdfRequestUnmarkCancelable antes de llamar a WdfRequestComplete fuera de la función de devolución de llamada EvtRequestCancel.

Si el controlador llama a WdfRequestForwardToIoQueue para reenviar la solicitud a otra cola, se aplican las reglas siguientes:

  • Las solicitudes de E/S no se pueden cancelar cuando el controlador los reenvía a otra cola.

    Por lo general, el controlador no debe llamar a WdfRequestMarkCancelableEx para habilitar la cancelación de la solicitud antes de llamar a WdfRequestForwardToIoQueue. Si el controlador realiza la solicitud cancelable, debe llamar a WdfRequestUnmarkCancelable para deshabilitar la cancelación antes de llamar a WdfRequestForwardToIoQueue.

  • Mientras la solicitud está en la segunda cola, el marco lo posee y puede cancelarlo sin notificar al controlador.

    Si el controlador requiere una notificación de cancelación (para que pueda desasignar los recursos que podría haber asignado antes de llamar a WdfRequestForwardToIoQueue), el controlador debe registrar una función de devolución de llamada EvtIoCanceledOnQueue y debe usar la memoria de contexto específica de la solicitud para almacenar información sobre los recursos de la solicitud.

  • Una vez que el marco ha puesto en cola la solicitud de la segunda cola y la ha entregado al controlador, el controlador puede llamar a WdfRequestMarkCancelableEx para habilitar la cancelación.
Para obtener más información sobre WdfRequestMarkCancelableEx, vea Cancelar solicitudes de E/S.

Ejemplos

En los ejemplos de código siguientes se muestran partes de dos funciones de devolución de llamada:

  • Una función de devolución de llamada EvtIoRead que realiza un trabajo específico de la solicitud (por ejemplo, la creación de subrecquests para enviar a un destino de E/S) y, a continuación, habilita la cancelación de la solicitud de E/S recibida.
  • Una función de devolución de llamada EvtRequestCancel que cancela una solicitud de E/S.
En el primer ejemplo, el controlador usa la sincronización automática del marco. En el segundo ejemplo, el controlador proporciona su propia sincronización mediante interbloqueos.

Ejemplo 1: un controlador que usa la sincronización automática.

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

Ejemplo 2: un controlador que usa su propia sincronización.

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

Requisitos

Requisito Value
Plataforma de destino Universal
Versión mínima de KMDF 1,9
Versión mínima de UMDF 2.0
Encabezado wdfrequest.h (incluya Wdf.h)
Library Wdf01000.sys (KMDF); WUDFx02000.dll (UMDF)
IRQL <=DISPATCH_LEVEL
Reglas de cumplimiento de DDI DeferredRequestCompleted(kmdf), DriverCreate(kmdf), EvtIoStopCancel(kmdf), InvalidReqAccess(kmdf), InvalidReqAccessLocal(kmdf), KmdfIrql(kmdf), KmdfIrql2(kmdf), KmdfIrqlExplicit(kmdf), MarkCancOnCancReqLocal(kmdf), ReqIsCancOnCancOnCancReq(kmdf), ReqMarkCancelableSend(kmdf), ReqNotCanceledLocal(kmdf), RequestCompleted(kmdf), RequestCompletedLocal( kmdf)

Consulte también

EvtRequestCancel

WdfRequestComplete

WdfRequestForwardToIoQueue

WdfRequestMarkCancelable

WdfRequestUnmarkCancelable