Condividi tramite


Esempio: Semplice Pass-Through dispatch e completamento

Nota

Per garantire un'affidabilità e prestazioni ottimali, usare i driver minifilter del file system con il supporto di Gestione filtri anziché i driver di filtro del file system legacy. Per convertire il driver legacy in un driver minifilter, vedere Linee guida per la conversione dei driver di filtro legacy.

Per impostare una routine di completamento per un IRP e passare l'IRP inattiva, una routine di invio del driver di filtro del file system legacy deve eseguire le azioni seguenti:

Questa tecnica è illustrata nell'esempio di codice seguente:

IoCopyCurrentIrpStackLocationToNext( Irp ); 
IoSetCompletionRoutine( Irp,                                 // Irp
                        MyLegacyFilterPassThroughCompletion, // CompletionRoutine
                        (PVOID)recordList,                   // Context
                        TRUE,                                // InvokeOnSuccess
                        TRUE,                                // InvokeOnError
                        TRUE);                               // InvokeOnCancel
return IoCallDriver ( NextLowerDriverDeviceObject, Irp ); 

In questo esempio la chiamata a IoSetCompletionRoutine imposta una routine di completamento per un IRP.

I primi due parametri nella chiamata a IoSetCompletionRoutine sono un puntatore all'IRP e al nome della routine di completamento. Il terzo parametro è un puntatore a una struttura definita dal driver da passare alla routine di completamento. Questa struttura contiene informazioni di contesto necessarie alla routine di completamento quando esegue l'elaborazione di completamento in IRP. La struttura del contesto deve essere allocata da un pool non di paging, perché la routine di completamento può essere chiamata in IRQL DISPATCH_LEVEL.

Gli ultimi tre parametri passati a IoSetCompletionRoutine sono flag che specificano se la routine di completamento viene chiamata quando la richiesta di I/O ha esito positivo, ha esito negativo o viene annullata.

Se una routine dispatch imposta una routine di completamento e restituisce immediatamente dopo aver chiamato IoCallDriver (come illustrato nella routine di invio precedente), la routine di completamento corrispondente deve controllare il flag PendingReturned di IRP e, se impostato, chiamare IoMarkIrpPending. Dovrebbe quindi restituire STATUS_SUCCESS, come illustrato nell'esempio seguente:

if (Irp->PendingReturned) {
    IoMarkIrpPending( Irp );
}
return STATUS_SUCCESS;
  • Vantaggi di questo approccio

    L'impostazione di una routine di completamento consente al driver di elaborare ulteriormente l'IRP dopo l'elaborazione dei driver di livello inferiore. La routine di completamento può decidere come elaborare l'IRP in base al risultato dell'operazione di I/O richiesta.

  • Svantaggi di questo approccio

    Poiché viene eseguito in un contesto di thread arbitrario in IRQL <= DISPATCH_LEVEL, una routine di completamento può eseguire solo un'elaborazione limitata su IRP.