Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Este artigo descreve como criar um IOCTL (código de controle de E/S) exclusivo. IOCTLs podem ser:
- IOCTLs públicos, que geralmente são definidos pelo sistema e documentados pela Microsoft.
- IOCTLs privados, que geralmente devem ser usados de forma exclusiva pelos componentes de software de um fornecedor para se comunicarem entre si. Eles geralmente são definidos no arquivo de cabeçalho de um fornecedor e não são documentados pela Microsoft.
Layout IOCTL
Um IOCTL é um valor de 32 bits que consiste em vários campos. A figura a seguir ilustra o layout bit a bit de um IOCTL:

Cada campo no IOCTL tem uma finalidade específica, conforme descrito na tabela a seguir:
| Campo | Bits no IOCTL | Descrição |
|---|---|---|
| Comum | 31 | Os fornecedores devem definir esse bit quando usam um valor atribuído pelo fornecedor para DeviceType. |
| DeviceType | 16-30 | Identifica o tipo de dispositivo. Esse valor deve corresponder ao valor definido no membro DeviceType da estrutura de DEVICE_OBJECT do driver. Os fornecedores devem usar um valor de 32768 a 65535 (0x8000 até 0xffff) e devem definir o bit Comum . Os valores de 0 a 32767 (0x0000 até 0x7fff) são reservados para a Microsoft. Para obter mais informações, consulte Especificando tipos de dispositivo. |
| Acesso | 14-15 | Indica o tipo de acesso que um chamador deve solicitar ao abrir o objeto de arquivo que representa o dispositivo (consulte IRP_MJ_CREATE). O gerenciador de E/S criará IRPs e chamará o driver com um IOCTL específico apenas se o chamador solicitar os direitos de acesso especificados. Esse campo é especificado usando as seguintes constantes definidas pelo sistema: FILE_ANY_ACCESS, FILE_READ_DATA e FILE_WRITE_DATA. |
| Personalizado | 13 | Quando definido, indica que o IOCTL é um IOCTL definido pelo fornecedor. |
| Função | 2-12 | Código exclusivo para o driver que identifica a função a ser executada. Para um IOCTL criado pelo fornecedor, use um valor de 2048 a 4095 (0x800 até 0xfff) e defina o bit Personalizado . Valores inferiores a 2048 (0x000 até 0x7ff) são reservados para a Microsoft. |
| Método | 0-1 | Indica como o sistema deve passar dados entre o chamador de DeviceIoControl (ou IoBuildDeviceIoControlRequest) e o driver que manipula o IRP. Para obter mais informações, consulte Diretrizes para definir os bits do Método. |
Macro para definir códigos de controle de E/S
Use a macro de CTL_CODE fornecida pelo sistema para definir novos códigos de controle de E/S. Essa macro é definida em devioctl.h da seguinte maneira:
#define CTL_CODE( DeviceType, Function, Method, Access ) ( \
((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
)
Consulte a seção anterior para obter uma descrição de DeviceType, Function, Method e Access.
Tenha as seguintes regras em mente ao definir novos códigos de controle de E/S:
Se um novo IOCTL estiver disponível para componentes de software no modo de usuário, ele deverá ser usado com solicitações IRP_MJ_DEVICE_CONTROL. Os componentes do modo usuário chamam DeviceIoControl para enviar solicitações de IRP_MJ_DEVICE_CONTROL.
Se um novo IOCTL estiver disponível apenas para componentes de driver em modo kernel, ele deverá ser usado com solicitações IRP_MJ_INTERNAL_DEVICE_CONTROL. Os componentes do modo kernel podem criar solicitações IRP_MJ_INTERNAL_DEVICE_CONTROL chamando IoBuildDeviceIoControlRequest. Para obter mais informações, consulte Criando solicitações IOCTL em drivers.
A definição de um novo código IOCTL, destinado ao uso com solicitações IRP_MJ_DEVICE_CONTROL ou IRP_MJ_INTERNAL_DEVICE_CONTROL, usa o seguinte formato:
#define IOCTL_Device_Function CTL_CODE(DeviceType, Function, Method, Access)
Escolha um nome de constante descritivo para o IOCTL, do formulário IOCTL_Device_Function, em que o dispositivo indica o tipo de dispositivo e a Função indica a operação. Por exemplo, a constante IOCTL_VIDEO_ENABLE_CURSOR fornecida pelo sistema usa "VIDEO" para Dispositivo e "ENABLE_CURSOR" para Função.
Diretrizes para definir os bits do Access
Ao definir um novo IOCTL, você deve escolher um valor para o campo de bits do Access que indica o tipo de acesso que um chamador deve solicitar ao abrir o objeto de arquivo que representa o dispositivo. O gerenciador de E/S criará IRPs e chamará o driver com um IOCTL específico apenas se o chamador solicitar os direitos de acesso especificados.
O acesso é especificado usando as seguintes constantes definidas pelo sistema:
FILE_ANY_ACCESS
O gerenciador de E/S envia o IRP para qualquer chamador que tenha um identificador para o objeto de arquivo que representa o objeto de dispositivo de destino. Antes de especificar FILE_ANY_ACCESS para um novo código IOCTL, você deve ter certeza absoluta de que permitir o acesso irrestrito ao seu dispositivo não cria um caminho possível para usuários mal-intencionados comprometerem o sistema.
LEITURA_DE_ARQUIVO
O gerenciador de E/S envia o IRP somente para um chamador com direitos de acesso de leitura, permitindo que o driver de dispositivo subjacente transfira dados do dispositivo para a memória do sistema.
ARQUIVO_ESCREVER_DADOS
O gerenciador de E/S envia o IRP somente para um chamador com direitos de acesso de gravação, permitindo que o driver de dispositivo subjacente transfira dados da memória do sistema para seu dispositivo.
FILE_READ_DATA e FILE_WRITE_DATA podem ser combinados usando a operação OR se o chamador precisar ter direitos de acesso tanto para leitura quanto para gravação.
Alguns códigos de controle de E/S definidos pelo sistema têm um valor de Acesso de FILE_ANY_ACCESS, o que permite que o chamador envie o IOCTL específico, independentemente do acesso concedido ao dispositivo. Exemplos incluem códigos de controle de E/S que são enviados para drivers de dispositivos exclusivos.
Outros códigos de controle de E/S definidos pelo sistema exigem que o chamador tenha direitos de acesso de leitura, direitos de acesso de gravação ou ambos. Por exemplo, a seguinte definição da IOCTL_DISK_SET_PARTITION_INFO IOCTL pública mostra que essa solicitação de E/S só poderá ser enviada a um driver se o chamador tiver direitos de acesso de leitura e gravação:
#define IOCTL_DISK_SET_PARTITION_INFO\
CTL_CODE(IOCTL_DISK_BASE, 0x008, METHOD_BUFFERED,\
FILE_READ_DATA | FILE_WRITE_DATA)
Os drivers podem usar IoValidateDeviceIoControlAccess para executar uma verificação de acesso mais rigorosa do que a fornecida pelos bits de Acesso de um IOCTL.
Diretrizes para definir os bits do Método
Ao definir um novo IOCTL, você deve escolher um valor para o campo bit Método que indica como o sistema deve passar dados entre o chamador de DeviceIoControl (ou IoBuildDeviceIoControlRequest) e o driver que manipula o IRP.
Use uma das seguintes constantes definidas pelo sistema para definir o campo Método .
MÉTODO_BUFFERED
Especifica o método de E/S em buffer , que normalmente é usado para transferir pequenas quantidades de dados por solicitação. A maioria dos códigos de controle de E/S para dispositivos e drivers intermediários usa esse valor.
Para obter informações sobre como o sistema especifica buffers de dados para códigos de controle de E/S METHOD_BUFFERED, consulte Descrições de buffer para códigos de controle de E/S.
Para obter mais informações sobre E/S em buffer, consulte Usando E/S em buffer.
METHOD_IN_DIRECT ou METHOD_OUT_DIRECT
Especifica o método de E/S direto , que normalmente é usado para ler ou gravar grandes quantidades de dados usando DMA ou PIO que devem ser transferidos rapidamente.
Especifique METHOD_IN_DIRECT se o chamador de DeviceIoControl ou IoBuildDeviceIoControlRequest passar dados para o driver.
Especifique METHOD_OUT_DIRECT se o chamador de DeviceIoControl ou IoBuildDeviceIoControlRequest receberá dados do driver.
Para obter informações sobre como o sistema especifica buffers de dados para códigos de controle de E/S METHOD_IN_DIRECT e METHOD_OUT_DIRECT, consulte Descrições de buffer para códigos de controle de E/S.
Para obter mais informações sobre E/S direta, consulte Usando E/S Direta.
METHOD_NEITHER
Especifica que o método de E/S não é armazenado em buffer ou direto. O gerenciador de E/S não fornece buffers ou MDLs do sistema. O IRP fornece os endereços virtuais do modo de usuário dos buffers de entrada e saída especificados para DeviceIoControl ou IoBuildDeviceIoControlRequest, sem validá-los ou mapeá-los.
Para obter informações sobre como o sistema especifica buffers de dados para códigos de controle de E/S METHOD_NEITHER, consulte Descrições de buffer para códigos de controle de E/S.
Esse método só poderá ser usado se o driver tiver a garantia de estar em execução no contexto do thread que originou a solicitação de controle de E/S. Somente um driver de modo kernel de nível mais alto tem garantia de atender a essa condição. Portanto, METHOD_NEITHER raramente é usado para IOCTLs que são passados para drivers de dispositivo de baixo nível.
Com esse método, o driver de nível mais alto:
- Deve determinar se é necessário configurar o acesso em buffer ou direto aos dados do usuário no recebimento da solicitação.
- Talvez seja necessário bloquear o buffer de usuário.
- Deve encapsular seu acesso ao buffer de usuário em um manipulador de exceção estruturado (consulte Tratamento de Exceções).
Caso contrário, o chamador do modo de usuário de origem poderá alterar os dados armazenados em buffer antes que o driver possa usá-los, ou o chamador poderá ser trocado no momento em que o driver estiver acessando o buffer do usuário.
Para obter mais informações, consulte Não usar E/S com buffer nem direta.
Outras macros úteis
As macros a seguir são úteis para extrair os campos devicetype de 16 bits e método de 2 bits de um IOCTL.
#define DEVICE_TYPE_FROM_CTL_CODE(ctrlCode) (((ULONG)(ctrlCode & 0xffff0000)) >> 16)
#define METHOD_FROM_CTL_CODE(ctrlCode) ((ULONG)(ctrlCode & 3))
Essas macros são definidas em Wdm.h e Ntddk.h.