Condividi tramite


Completamento delle richieste di I/O in UMDF

Avviso

UMDF 2 è la versione più recente di UMDF e sostituisce UMDF 1. Tutti i nuovi driver UMDF devono essere scritti usando UMDF 2. Non vengono aggiunte nuove funzionalità a UMDF 1 ed è disponibile un supporto limitato per UMDF 1 nelle versioni più recenti di Windows 10. I driver di Windows universali devono usare UMDF 2.

Gli esempi di UMDF 1 archiviati sono disponibili nell'aggiornamento degli esempi di driver di Windows 11 versione 22H2 - Maggio 2022.

Per altre info, vedi Introduzione con UMDF.

Ogni richiesta di I/O deve essere completata da un driver UMDF. Per completare una richiesta, il driver deve chiamare il metodo IWDFIoRequest::Complete o IWDFIoRequest::CompleteWithInformation . Quando il driver completa la richiesta, indica uno degli scenari seguenti:

  • Operazione di I/O richiesta completata correttamente.

  • Operazione di I/O richiesta avviata ma non riuscita prima del completamento.

  • L'operazione di I/O richiesta non è supportata o non è valida al momento della ricezione e pertanto non può comunicare con il dispositivo.

  • L'operazione di I/O richiesta è stata annullata.

Il driver chiama il metodo IWDFIoRequest::CompleteWithInformation per passare informazioni aggiuntive sull'operazione di richiesta. Ad esempio, per un'operazione di lettura, il driver deve fornire il numero di byte letti.

Per completare una richiesta di I/O, il driver deve passare lo stato di completamento appropriato al parametro CompletionStatus nella chiamata a IWDFIoRequest::Complete o IWDFIoRequest::CompleteWithInformation. Il driver usa un codice HRESULT per comunicare lo stato della richiesta completata.

Il processo host del driver UMDF converte il codice HRESULT in un codice NTSTATUS prima di passare la richiesta completata al riflettore (Wudfrd.sys). Il riflettore passa il codice NTSTATUS al sistema operativo. Il sistema operativo converte il codice NTSTATUS in un codice di errore Di Microsoft Win32 prima di presentare il risultato all'applicazione chiamante.

Per assicurarsi che i codici di errore del driver possano essere convertiti correttamente, è necessario creare codici di errore tramite una delle tecniche seguenti:

  • Usare un codice di errore di Winerror.h e applicare la macro HRESULT_FROM_WIN32.

  • Usare un codice di errore di Ntstatus.h e applicare la macro HRESULT_FROM_NT.

Per altre informazioni su queste macro, vedere la documentazione di Microsoft Windows SDK.

Il codice di esempio seguente illustra come completare una richiesta con un codice di errore appropriato:

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

Quando un driver completa correttamente una richiesta, restituisce S_OK, ovvero un valore HRESULT. Poiché S_OK equivale a NO_ERROR in Winerror.h e STATUS_SUCCESS in Ntstatus.h, le macro di conversione non sono necessarie.

Se Driver Verifier è abilitato per il riflettore, identifica un codice di stato non valido e causa un controllo di bug di sistema.

Nota Driver Verifier per Windows XP causa erroneamente un controllo di bug di sistema per i codici di errore Win32 i cui valori superano decimale 1024 (1024L). Se il driver viene eseguito in Windows XP, tenere presente questo problema se si abilita Driver Verifier per il riflettore.

Se il driver ha inviato in precedenza una richiesta a un driver di livello inferiore, il driver richiede una notifica quando il driver di livello inferiore completa la richiesta. Per eseguire la registrazione per la notifica, il driver chiama il metodo IWDFIoRequest::SetCompletionCallback per registrare l'interfaccia per il metodo che il framework chiama quando il driver di livello inferiore completa la richiesta. Il driver implementa la funzione di callback IRequestCallbackRequestCompletion::OnCompletion per eseguire le operazioni necessarie per completare la richiesta.

Un driver non completa una richiesta di I/O creata chiamando IWDFDevice::CreateRequest. Al contrario, il driver deve chiamare IWDFObject::D eleteWdfObject per eliminare l'oggetto richiesta, in genere dopo che una destinazione di I/O ha completato la richiesta.

Ad esempio, un driver potrebbe ricevere una richiesta di lettura o scrittura per una quantità di dati maggiore rispetto alle destinazioni di I/O del driver può gestire contemporaneamente. Il driver deve dividere i dati in diverse richieste più piccole e inviare queste richieste più piccole a una o più destinazioni di I/O. Le tecniche per la gestione di questa situazione includono:

  • Chiamata di IWDFDevice::CreateRequest per creare un singolo oggetto richiesta aggiuntivo che rappresenta una richiesta più piccola.

    Il driver può inviare questa richiesta in modo sincrono a una destinazione di I/O. La funzione di callback IRequestCallbackRequestCompletion::OnCompletion della richiesta più piccola può chiamare IWDFIoRequest2::Reuse in modo che il driver possa riutilizzare la richiesta e inviarla nuovamente alla destinazione di I/O. Dopo aver completato l'ultima delle richieste più piccole, la funzione di callback OnCompletion può chiamare IWDFObject::D eleteWdfObject per eliminare l'oggetto richiesta creata dal driver e il driver può chiamare IWDFIoRequest::Complete per completare la richiesta originale.

  • Chiamata di IWDFDevice::CreateRequest per creare diversi oggetti richiesta aggiuntivi che rappresentano le richieste più piccole.

    Le destinazioni di I/O del driver possono elaborare queste più richieste più piccole in modo asincrono. Il driver può registrare una funzione di callback OnCompletion per ognuna delle richieste più piccole. Ogni volta che viene chiamata la funzione di callback OnCompletion , può chiamare IWDFObject::D eleteWdfObject per eliminare un oggetto richiesta creato dal driver. Al termine di tutte le richieste più piccole, il driver può chiamare IWDFIoRequest::Complete per completare la richiesta originale.

Recupero delle informazioni di completamento

Per ottenere informazioni su una richiesta di I/O completata da un altro driver, un driver basato su UMDF può:

Inoltre, un driver basato su UMDF può usare il metodo IWDFIoRequest2::GetStatus per ottenere lo stato corrente di una richiesta di I/O, prima o dopo il completamento della richiesta.