Share via


Creazione di runtime di integrazione per driver Lower-Level

Per allocare un IRP per una richiesta asincrona, che verrà elaborata in un contesto di thread arbitrario da driver inferiori, una routine DispatchReadWrite può chiamare una delle routine di supporto seguenti:

  • IoAllocateIrp, che alloca un IRP e un numero di posizioni dello stack di I/O inizializzate zero

    La routine dispatch deve configurare la posizione dello stack di I/O del driver inferiore successivo per l'IRP appena allocata, in genere copiando (eventualmente modificate) le informazioni dal proprio percorso dello stack nell'IRP originale. Se un driver di livello superiore alloca una posizione dello stack di I/O propria per un IRP appena allocato, la routine dispatch può configurare le informazioni sul contesto per richiesta per l'uso della routine IoCompletion .

  • IoBuildAsynchronousFsdRequest, che configura la posizione dello stack I/O del driver inferiore successivo per il chiamante, in base ai parametri specificati dal chiamante

    I driver di livello superiore possono chiamare questa routine per allocare i provider di integrazione per le richieste di IRP_MJ_READ, IRP_MJ_WRITE, IRP_MJ_FLUSH_BUFFERS e IRP_MJ_SHUTDOWN .

    Quando viene chiamata una routine IoCompletion per questo tipo di IRP, può controllare il blocco di stato di I/O e, se necessario o possibile, configurare la posizione dello stack I/O del driver inferiore successivo nell'IRP e ripetere la richiesta o riutilizzarla. Tuttavia, la routine IoCompletion non dispone di alcuna risorsa di archiviazione del contesto locale per se stessa nell'IRP, pertanto il driver deve mantenere il contesto della richiesta originale altrove nella memoria residente.

  • IoMakeAssociatedIrp, che alloca un IRP e un numero di posizioni dello stack I/O inizializzate zero e associa l'IRP a un IRP master .

    I driver intermedi non possono chiamare IoMakeAssociatedIrp per creare irP per i driver inferiori.

    Qualsiasi driver di livello più alto che chiama IoMakeAssociatedIrp per creare irP per i driver inferiori può restituire il controllo al gestore di I/O dopo aver inviato i relativi IRP associati e chiamando IoMarkIrpPending per l'IRP master originale. Un driver di livello più alto può basarsi sul gestore di I/O per completare l'IRP master quando tutti gli IRP associati sono stati completati da driver inferiori.

    I driver impostano raramente una routine IoCompletion per un IRP associato. Se un driver di livello più alto chiama IoSetCompletionRoutine per un IRP associato creato, il gestore di I/O non completa l'IRP master se il driver restituisce STATUS_MORE_PROCESSING_REQUIRED dalla routine IoCompletion . In queste circostanze, la routine IoCompletion del driver deve completare in modo esplicito l'IRP master con IoCompleteRequest.

Se un driver alloca una posizione dello stack di I/O propria in una nuova istanza di IRP, la routine dispatch deve chiamare IoSetNextIrpStackLocation prima di chiamare IoGetCurrentIrpStackLocation per configurare il contesto nella propria posizione dello stack IoCompletion per la routine IoCompletion . Per altre informazioni, vedere Elaborazione di runtime di integrazione in un driver Intermediate-Level.

La routine dispatch deve chiamare IoMarkIrpPending con l'IRP originale, ma non con eventuali IRP allocati dal driver perché la routine IoCompletion li libererà.

Se la routine dispatch alloca i provider di integrazione per i trasferimenti parziali e il driver di dispositivo sottostante potrebbe controllare un dispositivo multimediale rimovibile, la routine dispatch deve configurare il contesto del thread nei relativi IRP appena allocati dal valore in Tail.Overlay.Thread nell'IRP originale.

Un driver sottostante per un dispositivo multimediale rimovibile potrebbe chiamare IoSetHardErrorOrVerifyDevice, che fa riferimento al puntatore in Irp-Tail.Overlay.Thread>, per un IRP allocato dal driver. Se il driver chiama questa routine di supporto, il driver del file system può inviare una finestra di dialogo al thread utente appropriato che richiede all'utente di annullare, ritentare o interrompere un'operazione che il driver non è riuscito a soddisfare. Per altre informazioni, vedere Supporto di supporti rimovibili .

Le routine dispatch devono restituire STATUS_PENDING dopo l'invio di tutti i runtime di integrazione allocati dal driver a driver inferiori.

La routine IoCompletion di un driver deve liberare tutti gli IRP allocati dal driver con IoFreeIrp prima di chiamare IoCompleteRequest per l'IRP originale. Al termine dell'IRP originale, la routine IoCompletion deve liberare tutti i runtime di integrazione allocati dal driver prima di restituire il controllo .

Ogni driver di livello superiore configura qualsiasi irP allocato (e riutilizzato) del driver per driver inferiori in modo che sia irrilevante per il driver di dispositivo sottostante se una determinata richiesta proviene da un driver intermedio o proviene da qualsiasi altra origine, ad esempio un file system o un'applicazione in modalità utente.

I driver di livello più alto possono chiamare IoMakeAssociatedIrp per allocare i provider di integrazione e configurarli per una catena di driver inferiori. Il gestore di I/O completa automaticamente l'IRP originale quando sono stati completati tutti i relativi IRP associati, purché il driver non chiami IoSetCompletionRoutine con l'IRP originale o con uno dei provider di integrazione associati allocati. I driver di livello più elevato non devono, tuttavia, allocare i provider di integrazione associati per qualsiasi IRP che richiede un'operazione di I/O memorizzata nel buffer.

Un driver di livello intermedio non può allocare irP per i driver di livello inferiore chiamando IoMakeAssociatedIrp. Qualsiasi IRP ricevuto da un driver intermedio potrebbe essere già un IRP associato e un driver non può associare un altro IRP a tale IRP.

Se invece un driver intermedio crea irP per driver inferiori, deve chiamare IoAllocateIrp, IoBuildDeviceIoControlRequest, IoBuildSynchronousFsdRequest o IoBuildAsynchronousFsdRequest. Tuttavia, IoBuildSynchronousFsdRequest può essere chiamato solo nelle circostanze seguenti:

  • Da un thread creato dal driver per la compilazione di runtime di integrazione per le richieste di lettura o scrittura, poiché tale thread può attendere in un contesto di thread non arbiverso (proprio) su un oggetto dispatcher, ad esempio un evento inizializzato dal driver passato a IoBuildSynchronousFsdRequest

  • Nel contesto del thread di sistema durante l'inizializzazione o durante lo scaricamento

  • Per creare irP per operazioni intrinsecamente sincrone, ad esempio creazione, scaricamento, arresto, chiusura e richieste di controllo del dispositivo

Tuttavia, è più probabile che un driver chiami IoBuildDeviceIoControlRequest per allocare i runtime di integrazione del controllo del dispositivo rispetto a IoBuildSynchronousFsdRequest.