Compartir a través de


Finalización de solicitudes de E/S en UMDF

Advertencia

UMDF 2 es la versión más reciente de UMDF y sustituye a UMDF 1. Todos los controladores UMDF nuevos deben escribirse con 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.

Los ejemplos de UMDF 1 archivados se pueden encontrar en la Windows 11, versión 22H2 : actualización de ejemplos de controladores de mayo de 2022.

Para obtener más información, consulta Introducción con UMDF.

Cada solicitud de E/S debe completarse finalmente por un controlador UMDF. Para completar una solicitud, el controlador debe llamar al método IWDFIoRequest::Complete o IWDFIoRequest::CompleteWithInformation . Cuando el controlador completa la solicitud, indica uno de los escenarios siguientes:

  • La operación de E/S solicitada finalizó correctamente.

  • Se inició la operación de E/S solicitada, pero no se pudo realizar antes de que finalice.

  • La operación de E/S solicitada no se admite o no es válida en el momento en que se recibió y, por lo tanto, no se puede comunicar con el dispositivo.

  • Se canceló la operación de E/S solicitada.

El controlador llama al método IWDFIoRequest::CompleteWithInformation para pasar información adicional sobre la operación de solicitud. Por ejemplo, para una operación de lectura, el controlador debe proporcionar el número de bytes leídos.

Para completar una solicitud de E/S, el controlador debe pasar el estado de finalización adecuado al parámetro CompletionStatus en la llamada a IWDFIoRequest::Complete o IWDFIoRequest::CompleteWithInformation. El controlador usa un código HRESULT para comunicar el estado de la solicitud completada.

El proceso host del controlador UMDF convierte el código HRESULT en un código NTSTATUS antes de pasar la solicitud completada al reflector (Wudfrd.sys). El reflector pasa el código NTSTATUS al sistema operativo. El sistema operativo convierte el código NTSTATUS en un código de error de Microsoft Win32 antes de presentar el resultado a la aplicación que realiza la llamada.

Para asegurarse de que los códigos de error del controlador se pueden convertir correctamente, debe crear códigos de error mediante cualquiera de las técnicas siguientes:

  • Use un código de error de Winerror.h y aplique la macro HRESULT_FROM_WIN32.

  • Use un código de error de Ntstatus.h y aplique la macro HRESULT_FROM_NT.

Para obtener más información sobre estas macros, consulte la documentación de Microsoft Windows SDK.

En el código de ejemplo siguiente se muestra cómo completar una solicitud con un código de error adecuado:

VOID
STDMETHODCALLTYPE
CMyQueue::OnWrite(
    __in IWDFIoQueue *pWdfQueue,
    __in IWDFIoRequest *pWdfRequest,
    __in SIZE_T BytesToWrite
    )
{
            -------------------- 
    if( BytesToWrite > MAX_WRITE_LENGTH ) {
        pWdfRequest->CompleteWithInformation(HRESULT_FROM_WIN32(ERROR_MORE_DATA), 0);
        return;
    }
            ---------------------
}

Cuando un controlador completa correctamente una solicitud, devuelve S_OK, que es un valor HRESULT. Dado que S_OK equivale a NO_ERROR en Winerror.h y STATUS_SUCCESS en Ntstatus.h, las macros de conversión no son necesarias.

Si el comprobador de controladores está habilitado para el reflector, identifica un código de estado no válido y provoca una comprobación de errores del sistema.

Nota El comprobador de controladores para Windows XP provoca incorrectamente una comprobación de errores del sistema para códigos de error win32 cuyos valores superan el decimal 1024 (1024L). Si el controlador se ejecuta en Windows XP, tenga en cuenta este problema si habilita el comprobador de controladores para el reflector.

Si el controlador envió previamente una solicitud a un controlador de nivel inferior, el controlador requiere una notificación cuando el controlador de nivel inferior completa la solicitud. Para registrarse para recibir notificaciones, el controlador llama al método IWDFIoRequest::SetCompletionCallback para registrar la interfaz del método al que llama el marco cuando el controlador de nivel inferior completa la solicitud. El controlador implementa la función de devolución de llamada IRequestCallbackRequestCompletion::OnCompletion para realizar las operaciones necesarias para completar la solicitud.

Un controlador no completa una solicitud de E/S que ha creado llamando a IWDFDevice::CreateRequest. En su lugar, el controlador debe llamar a IWDFObject::D eleteWdfObject para eliminar el objeto de solicitud, normalmente después de que un destino de E/S haya completado la solicitud.

Por ejemplo, un controlador puede recibir una solicitud de lectura o escritura para una cantidad de datos mayor que los destinos de E/S del controlador pueden controlarse a la vez. El controlador debe dividir los datos en varias solicitudes más pequeñas y enviar estas solicitudes más pequeñas a uno o varios destinos de E/S. Entre las técnicas para controlar esta situación se incluyen las siguientes:

  • Llamar a IWDFDevice::CreateRequest para crear un único objeto de solicitud adicional que represente una solicitud más pequeña.

    El controlador puede enviar esta solicitud de forma sincrónica a un destino de E/S. La función de devolución de llamada IRequestCallbackRequestCompletion::OnCompletion de la solicitud más pequeña puede llamar a IWDFIoRequest2::Reuse para que el controlador pueda reutilizar la solicitud y enviarlo de nuevo al destino de E/S. Una vez que el destino de E/S completa la última de las solicitudes más pequeñas, la función de devolución de llamada OnCompletion puede llamar a IWDFObject::D eleteWdfObject para eliminar el objeto de solicitud creado por el controlador y el controlador puede llamar a IWDFIoRequest::Complete para completar la solicitud original.

  • Llamar a IWDFDevice::CreateRequest para crear varios objetos de solicitud adicionales que representan las solicitudes más pequeñas.

    Los destinos de E/S del controlador pueden procesar estas múltiples solicitudes más pequeñas de forma asincrónica. El controlador puede registrar una función de devolución de llamada OnCompletion para cada una de las solicitudes más pequeñas. Cada vez que se llama a la función de devolución de llamada OnCompletion , puede llamar a IWDFObject::D eleteWdfObject para eliminar un objeto de solicitud creado por el controlador. Una vez que el destino de E/S completa todas las solicitudes más pequeñas, el controlador puede llamar a IWDFIoRequest::Complete para completar la solicitud original.

Obtener información de finalización

Para obtener información sobre una solicitud de E/S que haya completado otro controlador, un controlador basado en UMDF puede:

Además, un controlador basado en UMDF puede usar el método IWDFIoRequest2::GetStatus para obtener el estado actual de una solicitud de E/S, ya sea antes o después de que se haya completado la solicitud.