Nota
L'accesso a questa pagina richiede l'autorizzazione. Puoi provare ad accedere o a cambiare directory.
L'accesso a questa pagina richiede l'autorizzazione. Puoi provare a cambiare directory.
All'ingresso, una routine IoCompletion riceve un puntatore Context. Quando una routine dispatch chiama IoSetCompletionRoutine, può fornire un puntatore context . Questo puntatore può fare riferimento a qualsiasi informazione di contesto determinata dal driver richiesta dalla routine IoCompletion per elaborare un IRP. L'area di contesto non può essere impaginabile perché la routine IoCompletion può essere chiamata in IRQL = DISPATCH_LEVEL.
Considerare le linee guida di implementazione seguenti per le routine IoCompletion:
Una routine IoCompletion può controllare il blocco di stato I/O di IRP per determinare il risultato dell'operazione di I/O.
Se la routine dispatch ha allocato l'IRP di input usando IoAllocateIrp o IoBuildAsynchronousFsdRequest, la routine IoCompletion deve chiamare IoFreeIrp per rilasciare tale IRP, preferibilmente prima di completare l'IRP originale.
La routine IoCompletion deve rilasciare qualsiasi risorsa per-IRP che la routine dispatch abbia allocato per l'IRP allocato dal driver, preferibilmente prima di liberare l'IRP corrispondente.
Ad esempio, se la routine dispatch alloca un MDL con IoAllocateMdl e chiama IoBuildPartialMdl per alloca un IRP di trasferimento parziale, la routine IoCompletion deve rilasciare l'MDL con IoFreeMdl. Se alloca le risorse per mantenere lo stato relativo all'IRP originale, deve liberare tali risorse, preferibilmente prima di chiamare IoCompleteRequest con l'IRP originale e sicuramente prima di restituire il controllo.
In generale, prima di liberare o completare un IRP, la routine IoCompletion dovrebbe liberare tutte le risorse per IRP allocate dalla routine dispatch. In caso contrario, il driver deve mantenere lo stato delle risorse da liberare prima che la routine IoCompletion restituisca il controllo dal completamento della richiesta originale.
Se la routine IoCompletion non riesce a completare l'IRP originale con STATUS_SUCCESS, deve impostare il blocco di stato I/O nell'IRP originale sul valore restituito nell'IRP allocato dal driver che ha causato l'esito negativo della richiesta originale.
Se la routine IoCompletion completa la richiesta originale con STATUS_PENDING, deve chiamare IoMarkIrpPending con l'IRP originale prima di chiamare IoCompleteRequest.
Se la routine IoCompletion deve causare il fallimento dell'IRP originale con un errore STATUS_XXX, può registrare un errore. Tuttavia, è responsabilità del driver di dispositivo sottostante registrare eventuali errori di I/O del dispositivo che si verificano, quindi le routine IoCompletion in genere non registrano errori.
Quando la routine IoCompletion elabora e libera l'IRP allocato dal driver, deve restituire il controllo con STATUS_MORE_PROCESSING_REQUIRED.
La restituzione di STATUS_MORE_PROCESSING_REQUIRED dalla routine IoCompletion impedisce al gestore di I/O di completare l'elaborazione per un IRP che è stato interamente allocato e liberato dal driver. Una seconda chiamata a IoCompleteRequest fa sì che il gestore di I/O riprenda a chiamare le routine di completamento di IRP, a partire dalla routine di completamento immediatamente sopra la routine restituita STATUS_MORE_PROCESSING_REQUIRED.
Se la routine IoCompletion riutilizza un IRP in ingresso per inviare una o più richieste a driver inferiori o se la routine ritenta le operazioni non riuscite, deve aggiornare qualsiasi contesto gestito dalla routine IoCompletion su ogni riutilizzo o nuovo tentativo di IRP. Può quindi configurare nuovamente la posizione dello stack di I/O del driver inferiore successivo, chiamare IoSetCompletionRoutine con il proprio punto di ingresso e chiamare IoCallDriver per IRP.
La routine IoCompletion non deve chiamare IoMarkIrpPending a ogni riutilizzo o nuovo tentativo di IRP.
La routine di invio ha già contrassegnato l'IRP originale come in sospeso. Fino a quando tutti i driver della catena completano l'IRP originale con IoCompleteRequest, rimane in sospeso.
Prima di ritentare una richiesta, la routine IoCompletion deve reimpostare il blocco di stato di I/O con STATUS_SUCCESS per Stato e zero per Informazioni, possibilmente dopo aver salvato le informazioni sull'errore restituite.
Per ogni tentativo, la routine IoCompletion in genere decrementa un conteggio dei tentativi configurato dalla routine dispatch. In genere, la routine IoCompletion deve chiamare IoCompleteRequest per interrompere l'IRP quando alcuni tentativi hanno avuto esito negativo.
La routine IoCompletion deve restituire STATUS_MORE_PROCESSING_REQUIRED dopo aver chiamato IoSetCompletionRoutine e IoCallDriver con un IRP che sta riutilizzando o ritentando.
La restituzione di STATUS_MORE_PROCESSING_REQUIRED dalla routine IoCompletion impedisce al manager di I/O di elaborare il completamento di un IRP riutilizzato o ritentato.
Se la routine IoCompletion non riesce a completare l'IRP originale con STATUS_SUCCESS, deve lasciare il blocco di stato di I/O restituito dai driver inferiori per l'operazione di riutilizzo o ripetizione dei tentativi che fa fallire l'IRP nella routine IoCompletion.
Se la routine IoCompletion completerà la richiesta originale con STATUS_PENDING, deve chiamare IoMarkIrpPending con l'IRP originale prima di chiamare IoCompleteRequest.
Se la routine IoCompletion deve causare il fallimento dell'IRP originale con un errore STATUS_XXX, può registrare un errore. Tuttavia, è responsabilità del driver di dispositivo sottostante registrare eventuali errori di I/O del dispositivo che si verificano, quindi le routine IoCompletion in genere non registrano errori.
Qualsiasi driver che imposta una routine IoCompletion in un IRP e quindi passa l'IRP a un driver inferiore deve controllare il flag IRP-PendingReturned> nella routine IoCompletion. Se il flag è impostato, la routine IoCompletion deve chiamare IoMarkIrpPending con IRP. Tuttavia, un driver che inoltra l'IRP e quindi attende un evento non deve contrassegnare l'IRP come in sospeso. Al contrario, la routine IoCompletion deve segnalare l'evento e restituire STATUS_MORE_PROCESSING_REQUIRED.
La routine IoCompletion deve rilasciare tutte le risorse allocate dalla routine dispatch per l'elaborazione dell'IRP originale, preferibilmente prima che la routine IoCompletion chiami IoCompleteRequest con l'IRP originale e sicuramente prima che la routine IoCompletion restituisca il controllo dal completamento dell'IRP originale.
Se un driver di livello superiore imposta la routine IoCompletion nell'IRP originale, la routine IoCompletion del driver non viene chiamata finché non vengono chiamate le routine IoCompletion di tutti i driver di livello inferiore.
Fornire un aumento di priorità nelle chiamate a IoCompleteRequest
Se un driver di dispositivo di livello più basso può completare un IRP nella routine di dispatch, chiama IoCompleteRequest con un PriorityBoost di IO_NO_INCREMENT. Non è necessario alcun aumento della priorità di esecuzione perché il driver può presumere che il richiedente originale non stia attendendo il completamento della sua operazione di I/O.
In caso contrario, il driver di livello più basso fornisce un valore specifico del sistema e del tipo di dispositivo che aumenta la priorità di runtime del richiedente per compensare il tempo che il richiedente ha atteso nella richiesta di I/O del dispositivo. Per i valori boost, vedere Wdm.h o Ntddk.h.
I driver di livello superiore applicano lo stesso PriorityBoost dei rispettivi driver di dispositivo sottostanti quando chiamano IoCompleteRequest.
Effetto della chiamata di IoCompleteRequest
Quando un driver chiama IoCompleteRequest, il gestore di I/O riempie la posizione dello stack I/O del driver con zeri prima di chiamare il driver di livello superiore successivo, se presente, che configura una routine IoCompletion da chiamare per l'IRP.
Una routine IoCompletion del driver di livello superiore può controllare solo il blocco di stato I/O di IRP per determinare come tutti i driver inferiori hanno gestito la richiesta.
Il chiamante di IoCompleteRequest non deve tentare di accedere all'IRP appena completato. Un tentativo di questo tipo è un errore di programmazione che causa un arresto anomalo del sistema.