Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
Este artigo descreve como criar um código de controle de E/S exclusivo (IOCTL). IOCTLs podem ser:
- IOCTLs públicas, que normalmente são definidas pelo sistema e documentadas pela Microsoft.
- IOCTLs privadas, que normalmente se destinam a ser usadas exclusivamente 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.
IOCTL layout
Um IOCTL é um valor de 32 bits que consiste em vários campos. A figura a seguir ilustra o layout ao nível de bits de um IOCTL.
Cada campo na IOCTL tem uma finalidade específica, conforme descrito na tabela a seguir:
| Campo | Bits em IOCTL | Descrição |
|---|---|---|
| Comum | 31 | Os fornecedores devem definir esse bit quando usam um valor atribuído pelo fornecedor para DeviceType. |
| Tipo de dispositivo | 16-30 | Identifica o tipo de dispositivo. Esse valor deve corresponder ao valor definido no membro DeviceType da estrutura DEVICE_OBJECT do driver. Os fornecedores devem usar um valor de 32768 a 65535 (0x8000 a 0xffff) e devem definir o bit Comum . Os valores de 0 a 32767 (0x0000 a 0x7fff) estã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 gestor de E/S criará IRPs e chamará o driver com IOCTL específica somente se o chamador solicitar os direitos de acesso especificados. Este 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 que ele deve executar. Para um IOCTL criado pelo fornecedor, use um valor de 2048 a 4095 (0x800 a 0xfff) e defina o bit personalizado . Valores inferiores a 2048 (0x000 a 0x7ff) estã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 Orientação para definir os bits do método. |
Macro para definir códigos de controle de E/S
Use a macro CTL_CODE fornecida pelo sistema para definir novos códigos de controle de E/S. Esta macro é definida em devioctl.h da seguinte forma:
#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 em mente as seguintes regras ao definir novos códigos de controle de E/S:
Se um novo IOCTL estiver disponível para componentes de software em modo de utilizador, deve ser usado com solicitações IRP_MJ_DEVICE_CONTROL. Os componentes de modo de utilizador chamam DeviceIoControl para enviar pedidos IRP_MJ_DEVICE_CONTROL.
Se um novo IOCTL estiver disponível apenas para componentes de driver de 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, seja destinado a ser utilizado com os pedidos IRP_MJ_DEVICE_CONTROL ou IRP_MJ_INTERNAL_DEVICE_CONTROL, utiliza o seguinte formato:
#define IOCTL_Device_Function CTL_CODE(DeviceType, Function, Method, Access)
Escolha um nome constante descritivo para o IOCTL, do formato IOCTL_Device_Function, onde Device indica o tipo de dispositivo e Function indica a operação. Por exemplo, a constante de IOCTL_VIDEO_ENABLE_CURSOR fornecida pelo sistema usa "VIDEO" para Dispositivo e "ENABLE_CURSOR" para Função.
Orientação para definir os bits de acesso
Ao definir um novo IOCTL, você deve escolher um valor para o campo Bit de acesso que indique o tipo de acesso que um chamador deve solicitar ao abrir o objeto de arquivo que representa o dispositivo. O gestor de E/S criará IRPs e chamará o driver com uma IOCTL específica somente se o chamador tiver solicitado 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 acesso irrestrito ao seu dispositivo não cria um caminho possível para usuários mal-intencionados comprometerem o sistema.
Leitura_de_Dados_de_Ficheiro (FILE_READ_DATA)
O gerenciador de E/S envia o IRP apenas 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.
ESCREVER_DADOS_FICHEIRO
O gerenciador de E/S envia o IRP apenas 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 com OR quando o chamador deve ter direitos de acesso tanto de leitura quanto de gravação.
Alguns códigos de controle de E/S definidos pelo sistema têm um valor de acesso de FILE_ANY_ACCESS, que permite que o chamador envie a IOCTL específica, independentemente do acesso concedido ao dispositivo. Exemplos incluem códigos de controlo de E/S que são enviados aos 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 do IOCTL público IOCTL_DISK_SET_PARTITION_INFO mostra que esta solicitação de E/S pode ser enviada a um controlador apenas se o chamador tiver direitos de acesso tanto de leitura como de escrita:
#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.
Orientação para definir os bits do método
Ao definir um novo IOCTL, você deve escolher um valor para o campo de bit Method 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 com Buffer
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 usam 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 direta , 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 gestor de E/S não fornece buffers de sistema ou MDLs. O IRP fornece os endereços virtuais de modo de usuário dos buffers de entrada e saída que foram 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 pode ser usado somente se o driver estiver garantido para ser executado no contexto do thread que originou a solicitação de controle de E/S. Apenas um driver de modo kernel de nível mais alto é garantido para 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 este método, o controlador de nível mais alto:
- Deve determinar se deve configurar o acesso em buffer ou direto aos dados do usuário no recebimento da solicitação.
- Pode ser necessário bloquear o buffer do utilizador.
- Deve encapsular seu acesso ao buffer do usuário em um manipulador de exceção estruturado (consulte Manipulando exceções).
Caso contrário, o chamador de modo de usuário de origem pode alterar os dados armazenados em buffer antes que o driver possa usá-los, ou o chamador pode ser substituído no momento em que o driver está acessando o buffer do usuário.
Para obter mais informações, consulte Usar sem buffer nem E/S 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.