Creazione di richieste IOCTL nei driver

Un driver di classe o un altro driver di livello superiore può allocare IRP per le richieste di controllo I/O e inviarle al driver inferiore successivo come indicato di seguito:

  1. Allocare o riutilizzare un pacchetto di richiesta I/O (IRP) con il codice della funzione principale IRP_MJ_DEVICE_CONTROL o IRP_MJ_INTERNAL_DEVICE_CONTROL. È possibile usare la routine IoBuildDeviceIoControlRequest per allocare specificamente un IOCTL IRP. È anche possibile usare routine di creazione e inizializzazione generiche, ad esempio IoAllocateIrp, IoReuseIrp o IoInitializeIrp. Per altre informazioni sull'allocazione di IRP, vedere Creazione di IRP per i driver di Lower-Level.

  2. Configurare la posizione dello stack I/O del driver inferiore per l'IRP con il codice IOCTL_ XXX e i parametri appropriati.

  3. Se la richiesta IOCTL deve essere completata in modo asincrono, chiamare la routine KeInitializeEvent per inizializzare un oggetto evento come evento di notifica. Il driver usa questo evento per attendere il completamento di un'operazione di I/O.

  4. Chiamare IoSetCompletionRoutine con l'IRP in modo che il driver superiore possa fornire una routine IoCompletion , se necessario, per eseguire le operazioni seguenti:

    • Determinare il modo in cui il driver inferiore ha gestito una determinata richiesta.

    • Riutilizzare l'IRP per inviare un'altra richiesta o eliminare l'IRP creato dal driver, dopo che il driver inferiore completa un'operazione richiesta. Il driver non può riutilizzare gli indirizzi IP creati da IoBuildDeviceIoControlRequest . Per altre informazioni, vedere Riutilizzo di IRP.

  5. Chiamare IoCallDriver per passare la richiesta al driver inferiore.

  6. Se IoCallDriver restituisce STATUS_PENDING, chiamare la routine KeWaitForSingleObject per inserire il thread corrente in uno stato di attesa. Il driver imposta il parametro Object della routine sull'indirizzo dell'oggetto evento inizializzato nella chiamata a KeInitializeEvent.

    Nota Se il driver chiama KeWaitForSingleObject con il relativo parametro Timeout impostato su NULL o sull'indirizzo di una variabile contenente un valore diverso da zero, il driver deve essere in esecuzione in IRQL <= APC_LEVEL in un contesto di thread non arbitro. In caso contrario, il driver deve essere in esecuzione in IRQL <= DISPATCH_LEVEL.

L'evento viene segnalato dalla routine IoCompletion al termine della richiesta IOCTL. Dopo aver segnalato l'evento, il thread riprende l'esecuzione.

Importante Se il driver alloca l'oggetto evento come variabile locale nello stack, il driver deve chiamare KeWaitForSingleObject con il parametro WaitMode impostato su KernelMode. Questo valore di parametro impedisce che lo stack venga impaginato.

Per evitare problemi di sincronizzazione e possibili violazioni di accesso, i parametri per i codici di controllo I/O includono raramente puntatori incorporati. Ad eccezione di determinate richieste SCSI, i buffer in Irp-AssociatedIrp>. SystemBuffer, in Irp-MdlAddress > e in Parametri. DeviceIoControl. Type3InputBuffer nella posizione dello stack I/O di un driver non contengono puntatori ad altri buffer di dati, né contengono strutture che contengono puntatori per i codici di controllo I/O definiti dal sistema. Per altre informazioni sul modo in cui vengono usati i buffer di dati con indirizzi IP che contengono codici di controllo I/O, vedere Descrizioni del buffer per i codici di controllo I/O.

Tuttavia, una coppia di driver di classe/porta che definiscono codici di controllo I/O interni può passare un puntatore incorporato alla memoria allocata dal driver di livello superiore al driver di livello inferiore. Tale coppia di driver di classe/porta è responsabile per garantire che sia vero quanto segue:

  • Un solo driver alla volta può accedere ai dati.

  • I buffer di dati privati sono accessibili in un contesto di thread arbitrario dal driver di porta.

I driver di visualizzazione possono chiamare la funzione GDI EngDeviceIoControl per inviare richieste di controllo I/O specifiche del dispositivo, nonché richieste di controllo di I/O definite dal sistema, tramite il driver della porta video del sistema fino ai driver di miniport video specifici della scheda corrispondente.

Qualsiasi componente in modalità utente di un pacchetto driver può chiamare DeviceIoControl per inviare richieste di controllo I/O a uno stack di driver. Il gestore di I/O crea una richiesta di IRP_MJ_DEVICE_CONTROL e la recapita al driver di livello più alto.