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 |
---|---|
|
Se ha cancelado la solicitud de E/S. Consulta Comentarios para obtener más información. |
|
|
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:
- Finalice o detenga el procesamiento de la solicitud, junto con subrecquests que podría haber creado.
- Llame a WdfRequestComplete y especifique un valor de estado de STATUS_CANCELLED.
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.
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.
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) |