Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Questo articolo descrive come creare un codice di controllo I/O univoco (IOCTL). IOCTLs può essere:
- IOCTLs pubblici, che sono generalmente definiti dal sistema e documentati da Microsoft.
- IOCTL privati, solitamente destinati a essere utilizzati esclusivamente dai componenti software di un fornitore per comunicare tra loro. In genere sono definiti nel file di intestazione di un fornitore e non sono documentati da Microsoft.
Layout di IOCTL
Un IOCTL è un valore a 32 bit costituito da diversi campi. La figura seguente illustra il layout bit-wise di un IOCTL:
Ogni campo in IOCTL ha uno scopo specifico, come descritto nella tabella seguente:
Campo | Bit in IOCTL | Descrizione |
---|---|---|
Comune | 31 | I fornitori devono impostare questo bit quando usano un valore assegnato dal fornitore per DeviceType. |
DeviceType | 16-30 | Identifica il tipo di dispositivo. Questo valore deve corrispondere al valore impostato nel membro DeviceType della struttura DEVICE_OBJECT del driver. I fornitori devono usare un valore compreso tra 32768 e 65535 (0x8000 a 0xffff) e impostare il bit Comune. I valori da 0 a 32767 (0x0000 tramite 0x7fff) sono riservati a Microsoft. Per altre informazioni, vedere Specifica dei tipi di dispositivo. |
Accesso | 14-15 | Indica il tipo di accesso che un chiamante deve richiedere all'apertura dell'oggetto file che rappresenta il dispositivo (vedere IRP_MJ_CREATE). Il gestore di I/O creerà gli IRP e chiamerà il driver con un particolare IOCTL solo se il chiamante ha richiesto i diritti di accesso specificati. Questo campo viene specificato usando le costanti definite dal sistema seguenti: FILE_ANY_ACCESS, FILE_READ_DATA e FILE_WRITE_DATA. |
Personalizzato | 13 | Se impostato, indica che IOCTL è un IOCTL definito dal fornitore. |
Funzione | 2-12 | Codice univoco per il driver che identifica la funzione da eseguire. Per un IOCTL creato dal fornitore, usare un valore da 2048 a 4095 (0x800 tramite 0xfff) e impostare il bit personalizzato . I valori minori di 2048 (0x000 tramite 0x7ff) sono riservati a Microsoft. |
metodo | 0-1 | Indica come il sistema deve passare i dati tra il chiamante di DeviceIoControl (o IoBuildDeviceIoControlRequest) e il driver che gestisce l'IRP. Per altre informazioni, vedere Linee guida per l'impostazione dei bit del metodo. |
Macro per la definizione dei codici di controllo di I/O
Utilizzare la macro di CTL_CODE fornita dal sistema per definire nuovi codici di controllo di I/O. Questa macro è definita in devioctl.h come indicato di seguito:
#define CTL_CODE( DeviceType, Function, Method, Access ) ( \
((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
)
Vedere la sezione precedente per una descrizione di DeviceType, Function, Method e Access.
Quando si definiscono nuovi codici di controllo di I/O, tenere presenti le regole seguenti:
Se un nuovo IOCTL sarà disponibile per i componenti software in modalità utente, le richieste devono essere usate con IRP_MJ_DEVICE_CONTROL. I componenti in modalità utente chiamano DeviceIoControl per inviare richieste di IRP_MJ_DEVICE_CONTROL .
Se un nuovo IOCTL sarà disponibile solo per i componenti driver in modalità kernel, deve essere usato con le richieste di IRP_MJ_INTERNAL_DEVICE_CONTROL . I componenti in modalità kernel possono creare richieste di IRP_MJ_INTERNAL_DEVICE_CONTROL chiamando IoBuildDeviceIoControlRequest. Per altre informazioni, vedere Creazione di richieste IOCTL nei driver.
La definizione di un nuovo codice IOCTL, destinato all'uso con richieste di IRP_MJ_DEVICE_CONTROL o IRP_MJ_INTERNAL_DEVICE_CONTROL , usa il formato seguente:
#define IOCTL_Device_Function CTL_CODE(DeviceType, Function, Method, Access)
Scegliere un nome costante descrittivo per IOCTL, nel formato IOCTL_Device_Function, dove Device indica il tipo di dispositivo e Funzione indica l'operazione. Ad esempio, la costante IOCTL_VIDEO_ENABLE_CURSOR fornita dal sistema usa "VIDEO" per Device e "ENABLE_CURSOR" per Function.
Linee guida per l'impostazione dei bit di accesso
Quando si definisce un nuovo IOCTL, è necessario scegliere un valore per il campo bit di Access che indica il tipo di accesso che un chiamante deve richiedere quando si apre l'oggetto file che rappresenta il dispositivo. Il gestore di I/O creerà gli IRP e chiamerà il driver con un particolare IOCTL solo se il chiamante ha richiesto i diritti di accesso specificati.
L'accesso viene specificato usando le costanti definite dal sistema seguenti:
FILE_ANY_ACCESS (Accesso a qualsiasi file)
Il gestore di I/O invia l'IRP per qualsiasi chiamante che dispone di un handle all'oggetto file che rappresenta l'oggetto dispositivo di destinazione. Prima di specificare FILE_ANY_ACCESS per un nuovo codice IOCTL, è necessario essere assolutamente certi che consentire l'accesso senza restrizioni al dispositivo non crei un possibile percorso per gli utenti malintenzionati a compromettere il sistema.
LEGGI_DATI_FILE
Il gestore di I/O invia l'IRP solo per un chiamante con diritti di accesso in lettura, consentendo al driver di dispositivo sottostante di trasferire i dati dal dispositivo alla memoria di sistema.
SCRITTURA_DATI_FILE
Il gestore di I/O invia l'IRP solo per un chiamante con diritti di accesso in scrittura, consentendo al driver di dispositivo sottostante di trasferire i dati dalla memoria di sistema al dispositivo.
FILE_READ_DATA e FILE_WRITE_DATA possono essere combinati con OR se il chiamante deve disporre sia dei diritti di accesso in lettura che in scrittura.
Alcuni codici di controllo di I/O definiti dal sistema hanno un valore di access pari a FILE_ANY_ACCESS, che consente al chiamante di inviare il codice IOCTL specifico indipendentemente dall'accesso concesso al dispositivo. Gli esempi includono i codici di controllo di I/O inviati ai driver di dispositivi esclusivi.
Altri codici di controllo di I/O definiti dal sistema richiedono al chiamante diritti di accesso in lettura, diritti di accesso in scrittura o entrambi. Ad esempio, la definizione seguente del IOCTL_DISK_SET_PARTITION_INFO IOCTL pubblico mostra che questa richiesta di I/O può essere inviata a un driver solo se il chiamante dispone di diritti di accesso in lettura e scrittura:
#define IOCTL_DISK_SET_PARTITION_INFO\
CTL_CODE(IOCTL_DISK_BASE, 0x008, METHOD_BUFFERED,\
FILE_READ_DATA | FILE_WRITE_DATA)
I driver possono usare IoValidateDeviceIoControlAccess per eseguire un controllo di accesso più rigoroso rispetto a quello fornito dai bit di accesso di IOCTL.
Linee guida per l'impostazione dei bit del metodo
Quando si definisce un nuovo IOCTL, è necessario scegliere un valore per il campo Bit metodo che indica come il sistema deve passare i dati tra il chiamante di DeviceIoControl (o IoBuildDeviceIoControlRequest) e il driver che gestisce l'IRP.
Utilizzare una delle costanti definite dal sistema seguenti per impostare il campo Metodo .
Metodo Buffered
Specifica il metodo di I/O memorizzato nel buffer , in genere usato per il trasferimento di piccole quantità di dati per richiesta. La maggior parte dei codici di controllo di I/O per i driver intermedi e dispositivo usa questo valore.
Per informazioni su come il sistema specifica i buffer di dati per METHOD_BUFFERED codici di controllo di I/O, vedere Descrizioni del buffer per i codici di controllo di I/O.
Per altre informazioni sulle operazioni di I/O memorizzate nel buffer, vedere Uso delle operazioni di I/O memorizzate nel buffer.
METHOD_IN_DIRECT o METHOD_OUT_DIRECT
Specifica il metodo di I/O diretto , in genere usato per la lettura o la scrittura di grandi quantità di dati tramite DMA o PIO che deve essere trasferito rapidamente.
Specificare METHOD_IN_DIRECT se il chiamante di DeviceIoControl o IoBuildDeviceIoControlRequest passerà i dati al driver.
Specificare METHOD_OUT_DIRECT se il chiamante di DeviceIoControl o IoBuildDeviceIoControlRequest riceverà i dati dal driver.
Per informazioni su come il sistema specifica i buffer di dati per METHOD_IN_DIRECT e METHOD_OUT_DIRECT codici di controllo di I/O, vedere Descrizioni dei buffer per i codici di controllo I/O.
Per altre informazioni sull'I/O diretto, vedere Uso dell'I/O diretto.
METODO_NESSUNO
Specifica che il metodo di I/O non utilizza buffer e non è diretto. Il gestore di I/O non fornisce buffer di sistema o MDL. IRP fornisce gli indirizzi virtuali in modalità utente dei buffer di input e output specificati in DeviceIoControl o IoBuildDeviceIoControlRequest, senza convalidarli o mapparli.
Per informazioni su come il sistema specifica i buffer di dati per i codici di controllo I/O METHOD_NEITHER, consultare Descrizioni del buffer per i codici di controllo di I/O.
Questo metodo può essere usato solo se il driver è garantito che sia in esecuzione nel contesto del thread che ha originato la richiesta di controllo di I/O. È garantito che solo un driver in modalità kernel di alto livello soddisfi questa condizione, quindi METHOD_NEITHER viene usato raramente per IOCTLs che vengono passati ai driver di dispositivo di basso livello.
Con questo metodo, il driver di livello più alto:
- Deve determinare se configurare l'accesso diretto o memorizzato nel buffer ai dati utente alla ricezione della richiesta.
- È possibile che si debba bloccare il buffer dell'utente.
- È necessario avvolgere l'accesso al buffer utente in un gestore delle eccezioni strutturato (vedere Gestione delle eccezioni).
In caso contrario, il chiamante in modalità utente di origine potrebbe modificare i dati memorizzati nel buffer prima che il driver possa usarlo oppure il chiamante potrebbe essere scambiato esattamente come il driver accede al buffer utente.
Per ulteriori informazioni, vedere Uso di I/O né con buffering né diretto.
Altre macro utili
Le macro seguenti sono utili per estrarre i campi DeviceType a 16 bit e Metodo a 2 bit da un IOCTL.
#define DEVICE_TYPE_FROM_CTL_CODE(ctrlCode) (((ULONG)(ctrlCode & 0xffff0000)) >> 16)
#define METHOD_FROM_CTL_CODE(ctrlCode) ((ULONG)(ctrlCode & 3))
Queste macro sono definite in Wdm.h e Ntddk.h.