Linee guida per la conversione dei driver di filtro legacy
Gli sviluppatori sono invitati a convertire i driver di filtro legacy nel modello di gestione filtri per ottenere funzionalità migliori per i driver di filtro e migliorare l'affidabilità del sistema. Gli sviluppatori esperti dovrebbero trovare relativamente facile convertire un driver di filtro legacy in un driver minifilter. Filtrare gli sviluppatori di driver in Microsoft consigliano l'approccio seguente:
Iniziare con una suite di test di regressione affidabile per verificare il comportamento tra il driver di filtro legacy e il driver minifilter con porta.
Creare una shell del driver minifilter e spostare sistematicamente le funzionalità dal driver di filtro legacy al driver minifilter. Ad esempio, ottenere il funzionamento dell'allegato e quindi eseguire una porta a un'operazione alla volta, testando dopo ogni operazione.
Modificare l'ultima comunicazione in modalità utente/kernel, in modo da poter usare strumenti esistenti per testare il driver minifilter.
Compilare con PREfast e testare con l'opzione Di verifica filtro I/O del filtro abilitata in Verifica driver abilitata.
Durante il processo di conversione, è necessario esaminare tutto il codice driver di filtro legacy per sfruttare al meglio le funzionalità di gestione filtri. In particolare, tenere presente quanto segue:
Le operazioni di I/O basate su IRP possono essere eseguite con la stessa operazione, che consente di ridurre la duplicazione del codice.
Quando si registra per le operazioni, un driver minifilter può scegliere in modo esplicito di ignorare tutte le operazioni di I/O di paging e di I/O memorizzate nella cache, che elimina la necessità di controllare il codice.
Le notifiche delle istanze semplificano notevolmente la logica di collegamento/scollegamento.
Registrare solo per le operazioni che il driver minifilter deve gestire; è possibile ignorare tutto il resto.
Sfruttare il supporto di gestione dei nomi e del contesto di filtro.
Sfruttare il supporto di Gestione filtri per l'emissione di I/O non ricorsivi.
A differenza dei driver di filtro legacy, i driver minifilter non possono basarsi sulle variabili locali per mantenere il contesto dall'elaborazione preoperazione all'elaborazione della post-operazione. Valutare la possibilità di allocare un elenco lookaside per archiviare lo stato dell'operazione.
Assicurarsi di rilasciare riferimenti al termine di un nome o di un contesto.
Le porte di completamento in modalità utente aggiungono una tecnica potente per la creazione di code. Probabilmente sarà necessaria solo una singola connessione a una singola porta denominata.
Nella tabella seguente vengono elencate le operazioni comuni in un driver di filtro legacy e come vengono mappate al modello di gestione filtri.
Modello di driver di filtro legacy | Modello di gestione filtri |
---|---|
Operazione pass-through senza routine di completamento |
Se il driver minifilter non funziona mai per questo tipo di operazione di I/O, non registrare una routine di callback preoperazione o postoperazione per questa operazione. In caso contrario, restituire FLT_PREOP_SUCCESS_NO_CALLBACK dalla routine di callback di preoperazione registrata per questa operazione. |
Operazione pass-through con una routine di completamento |
Restituire FLT_PREOP_SUCCESS_WITH_CALLBACK dalla routine di callback di preoperazione. |
Operazione penna nella routine di callback di preoperazione |
Chiamare FltLockUserBuffer in base alle esigenze per assicurarsi che tutti i buffer utente siano bloccati correttamente in modo che possano essere accessibili in un thread di lavoro. Accodare il lavoro a un thread di lavoro chiamando routine di supporto, ad esempio FltAllocateDeferredIoWorkItem e FltQueueDeferredIoWorkItem. Restituire FLT_PREOP_PENDING dalla routine di callback di preoperazione. Quando è pronto per restituire l'operazione di I/O alla gestione filtri, chiamare FltCompletePendedPreOperation. Vedere In sospeso un'operazione di I/O in una routine di callback di preoperazione. |
Operazione pend nella routine di callback postperazione |
Nella routine di callback di preoperazione chiamare FltLockUserBuffer per assicurarsi che i buffer utente siano bloccati correttamente in modo che possano essere accessibili in un thread di lavoro. Accodare il lavoro a un thread di lavoro chiamando routine di supporto, ad esempio FltAllocateGenericWorkItem e FltQueueGenericWorkItem. Restituire FLT_POSTOP_MORE_PROCESSING_REQUIRED dalla routine di callback di postperazione. Quando è pronto per restituire l'operazione di I/O alla gestione filtri, chiamare FltCompletePendedPostOperation. Vedere In sospeso un'operazione di I/O in una routine di callback postperation. |
Sincronizzare l'operazione |
Restituire FLT_PREOP_SYNCHRONIZE dalla routine di callback di preoperazione. |
Completare l'operazione nella routine di callback di preoperazione |
Impostare lo stato dell'operazione finale e le informazioni nel membro IoStatus della struttura FLT_CALLBACK_DATA per l'operazione. Restituire FLT_PREOP_COMPLETE dalla routine di callback di preoperazione. Vedere Completamento di un'operazione di I/O in una routine di callback di preoperazione. |
Completare l'operazione dopo aver eseguito la penna nella routine di callback di preoperazione |
Impostare lo stato dell'operazione finale e le informazioni nel membro IoStatus della struttura FLT_CALLBACK_DATA per l'operazione. Chiamare FltCompletePendedPreOperation dal thread di lavoro che elabora l'operazione di I/O, passando FLT_PREOP_COMPLETE come parametro CallbackStatus . Vedere Completamento di un'operazione di I/O in una routine di callback di preoperazione. |
Eseguire tutto il lavoro di completamento nella routine di completamento |
Restituire FLT_POSTOP_FINISHED_PROCESSING dalla routine di callback di postperazione. |
Eseguire il lavoro di completamento in IRQL sicuro |
Chiamare FltDoCompletionProcessingWhenSafe dalla routine di callback postoperation. Vedere Verificare che l'elaborazione del completamento venga eseguita in IRQL sicuro. |
Segnalare un evento dalla routine di completamento |
Restituire FLT_PREOP_SYNCHRONIZE dalla routine di callback di preoperazione per questa operazione. Gestione filtri chiama la routine di callback postperazione nello stesso contesto del thread della routine di callback di preoperazione, in IRQL <= APC_LEVEL. |
Esito negativo di un'operazione di creazione riuscita |
Chiamare FltCancelFileOpen dalla routine di callback di postperazione per l'operazione di creazione. Impostare un valore NTSTATUS di errore appropriato nel membro IoStatus della struttura FLT_CALLBACK_DATA per l'operazione. Restituire FLT_POSTOP_FINISHED_PROCESSING. Vedere Errore di un'operazione di I/O in una routine di callback postperation. |
Impedire l'I/O tramite il percorso di I/O rapido per un'operazione di I/O |
Restituire FLT_STATUS_DISALLOW_FAST_IO dalla routine di callback di preoperazione per l'operazione. Vedere Disallowing a Fast I/O Operation in a Preoperation Callback Routine. |
Modificare i parametri per un'operazione di I/O |
Impostare i valori dei parametri modificati nel membro Iopb della struttura FLT_CALLBACK_DATA per l'operazione. Contrassegnare la struttura FLT_CALLBACK_DATA come sporca chiamando FltSetCallbackDataDirty, tranne quando si è modificato il contenuto del membro IoStatus della struttura FLT_CALLBACK_DATA. |
Bloccare il buffer utente per l'operazione |
Usare le tecniche e le linee guida descritte in Accesso ai buffer utente per un'operazione di I/O. |