Supporto dei client Kernel-Mode nei driver UMDF 1.x
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 informazioni, vedi Introduzione a UMDF.
Avviso
Vedere anche Supporto di client Kernel-Mode in UMDF 2.x.
Le versioni UMDF 1.9 e successive consentono ai driver UMDF di supportare i client in modalità kernel. Un client in modalità kernel può essere uno dei seguenti:
Driver in modalità kernel esistente sopra un driver UMDF nello stack di driver di un dispositivo.
Un driver in modalità kernel per uno stack di dispositivi, che supporta un dispositivo, apre un handle a un altro dispositivo e lo stack di driver del secondo dispositivo contiene un driver UMDF.
In altre parole, un driver UMDF che supporta i client in modalità kernel può ricevere richieste di I/O da un driver in modalità kernel. Il driver in modalità kernel può inoltrare le richieste di I/O ricevute da un'applicazione in modalità utente oppure creare nuove richieste di I/O e inviarle al driver in modalità utente.
Per determinare se il driver UMDF deve supportare i client in modalità kernel, è necessario comprendere lo stack di driver a cui verrà aggiunto il driver e dove risiederà il driver. È anche necessario determinare se un driver di un altro stack potrebbe inviare richieste di I/O al dispositivo del driver.
Il driver deve supportare i client in modalità kernel se:
Un driver in modalità kernel può trovarsi direttamente sopra il driver UMDF in uno stack di driver. Ad esempio, un driver di filtro in modalità kernel potrebbe risiedere direttamente sopra un driver di funzione basato su UMDF.
Un driver in modalità kernel da un altro stack può inviare richieste di I/O al dispositivo del driver. Ad esempio, il driver potrebbe creare un collegamento simbolico che un driver in modalità kernel in un altro stack può usare per aprire un handle al dispositivo del driver. Il driver in modalità kernel può quindi inviare richieste di I/O al dispositivo.
Come supportare i client in modalità kernel in un driver UMDF
Un driver UMDF può ricevere richieste di I/O da un driver in modalità kernel solo se il driver UMDF ha abilitato il supporto per i client in modalità kernel. Inoltre, se un'installazione del dispositivo tenta di caricare driver in modalità kernel sopra un driver UMDF nello stack di driver del dispositivo, il framework consente ai driver di caricare solo se il driver UMDF ha abilitato il supporto per i client in modalità kernel.
Per abilitare il supporto di un driver UMDF per i client in modalità kernel, il file INF del driver UMDF deve includere una direttiva UmdfKernelModeClientPolicy nella relativa DDInstall INF. Sezione WDF . Se il file INF del driver UMDF non include questa direttiva, UMDF non consente l'esecuzione di un driver in modalità kernel installato sopra il driver UMDF.
Il framework fornisce due metodi utili per i driver che supportano client in modalità kernel. Un driver può chiamare il metodo IWDFIoRequest2::GetRequestorMode per determinare se una richiesta di I/O proviene dalla modalità kernel o dall'utente. Se la richiesta di I/O proviene dalla modalità utente, il driver può chiamare IWDFIoRequest2::IsFromUserModeDriver per determinare se la richiesta proviene da un'applicazione o da un altro driver in modalità utente.
Restrizioni sui driver in modalità kernel
Un driver UMDF può elaborare le richieste di I/O da un driver in modalità kernel solo se il driver in modalità kernel soddisfa i requisiti seguenti:
Il driver in modalità kernel deve essere in esecuzione in IRQL = PASSIVE_LEVEL quando invia la richiesta di I/O.
A meno che il driver non abbia impostato la direttiva INF UmdfFileObjectPolicy su AllowNullAndUnknownFileObjects, ogni richiesta di I/O inviata da un driver in modalità kernel a un driver in modalità utente deve avere un oggetto file associato. Il framework deve essere stato precedentemente informato che il gestore di I/O ha creato l'oggetto file. Tale notifica fa sì che il framework chiami la funzione di callback IQueueCallbackCreate::OnCreateFile , ma tale funzione di callback è facoltativa.
La richiesta di I/O non può contenere un codice di funzione IRP_MJ_INTERNAL_DEVICE_CONTROL .
I buffer della richiesta di I/O non devono contenere puntatori a informazioni aggiuntive, perché il driver in modalità utente non può dereferenziare i puntatori.
Se la richiesta di I/O contiene un codice di controllo di I/O che specifica il metodo di accesso al buffer "nessuno", il driver in modalità kernel deve inviare la richiesta di I/O nel contesto del processo dell'applicazione che ha creato la richiesta di I/O. Per altre informazioni su come supportare il metodo "nessuno" in un driver di base UMDF, vedere Using Neither Buffered I/O or or Direct I/O in UMDF Drivers.For more information about how to support the "neither" method in a UMDF-base driver, see Using Neither Buffered I/O nor Direct I/O in UMDF Drivers.
Il driver UMDF potrebbe modificare i dati di output di una richiesta di I/O in modalità utente. Di conseguenza, il driver in modalità kernel deve convalidare tutti i dati di output ricevuti dal driver in modalità utente.
Il client in modalità kernel deve in genere convalidare il valore Information che un driver UMDF passa a IWDFIoRequest::CompleteWithInformation. Se il client è un driver KMDF, può chiamare WdfRequestGetCompletionParams per ottenere queste informazioni in una struttura di IO_STATUS_BLOCK.
In genere, il framework non convalida il valore delle informazioni che un driver UMDF passa a IWDFIoRequest::CompleteWithInformation. Questo parametro specifica in genere il numero di byte trasferiti. Il framework convalida il valore delle informazioni solo per i buffer di output e solo per il metodo di accesso ai dati I/O memorizzato nel buffer . Ad esempio, il framework verifica che il numero di byte trasferiti non superi le dimensioni del buffer di output di un'operazione di lettura, se il metodo di accesso viene memorizzato nel buffer di I/O.
Gestione dei valori di stato restituiti in un driver UMDF 1.x
Il passaggio dei valori di stato restituiti dalla modalità utente alla modalità kernel richiede particolare attenzione, come indicato di seguito:
I driver UMDF versione 1 in genere ricevono valori restituiti tipizzati HRESULT, mentre i driver in modalità kernel basati su KMDF e WDM in genere ricevono valori tipizzati NTSTATUS. Se un UMDF 1. X driver completa una richiesta di I/O e se il driver ha un client in modalità kernel, la chiamata del driver a IWDFIoRequest::Complete o IWDFIoRequest::CompleteWithInformation deve specificare un valore HRESULT generato dal driver da un valore NTSTATUS. In generale, UMDF 1. I driver x devono usare la macro HRESULT_FROM_NT (definita in Winerror.h) per restituire lo stato a un client in modalità kernel. Nell'esempio seguente viene illustrato come utilizzare questa macro durante il completamento di una richiesta.
hr = HRESULT_FROM_NT(STATUS_BUFFER_OVERFLOW) request->Complete(HRESULT_FROM_NT(STATUS_BUFFER_OVERFLOW); return hr;
Per restituire un valore HRESULT specifico a un client in modalità kernel, i callback seguenti devono usare la macro HRESULT_FROM_NT:
- IPnpCallback::OnQueryRemove
- IPnpCallback::OnQueryStop
- IPnpCallbackHardware::OnPrepareHardware
- IPnpCallbackHardware::OnReleaseHardware
Per usare i valori NTSTATUS definiti in ntstatus.h, UMDF 1. x driver deve includere queste due righe prima di includere eventuali intestazioni aggiuntive.
#define UMDF_USING_NTSTATUS #include <ntstatus.h>
Non utilizzare la macro HRESULT_FROM_NT per convertire STATUS_SUCCESS da un valore NTSTATUS a un valore HRESULT. È sufficiente restituire S_OK, come illustrato nell'esempio seguente.
request->Complete(S_OK);
Il framework completa alcune richieste di I/O per conto dei driver UMDF. A volte il framework non converte i valori restituiti tipizzati HRESULT in valori NTSTATUS equivalenti, quindi il framework potrebbe passare uno stato di completamento tipizzato HRESULT a un client in modalità kernel.
A causa di questa situazione, i client in modalità kernel non devono usare la macro NT_ERROR durante il test dello stato di completamento di una richiesta di I/O, perché la macro NT_ERROR non restituisce TRUE per i valori di errore HRESULT. I driver in modalità kernel devono usare la macro NT_SUCCESS durante il test dello stato di completamento di una richiesta di I/O.
Supporto client in modalità kernel nelle versioni precedenti di UMDF
Per le versioni UMDF precedenti alla versione 1.9, il file INF di un driver può includere una direttiva INF AddReg per creare un valore del Registro di sistema UpperDriverOk di dimensioni REG_DWORD nella sottochiave WUDF della chiave hardware del dispositivo.
Se il valore del Registro di sistema UpperDriverOk è impostato su un numero diverso da zero, il framework consente il caricamento dei driver in modalità kernel sopra il driver in modalità utente. I driver in modalità kernel possono inoltrare richieste di I/O da applicazioni in modalità utente al driver UMDF, ma i driver in modalità kernel non possono inviare richieste di I/O create in modalità kernel al driver UMDF.
Per le versioni UMDF 1.9 e successive, il valore del Registro di sistema UpperDriverOk è obsoleto e supportato solo per i driver esistenti. I nuovi driver devono usare la direttiva UmdfKernelModeClientPolicy .