Criando solicitações IOCTL em drivers

Um driver de classe ou outro driver de nível superior pode alocar IRPs para solicitações de controle de E/S e enviá-los para o driver mais próximo e inferior da seguinte forma:

  1. Alocar ou reutilizar um pacote de solicitação de E/S (IRP) com o código de função principal IRP_MJ_DEVICE_CONTROL ou IRP_MJ_INTERNAL_DEVICE_CONTROL. Você pode usar a rotina IoBuildDeviceIoControlRequest para alocar especificamente um IRP IOCTL. Você também pode usar rotinas de criação e inicialização de IRP de uso geral, como IoAllocateIrp, IoReuseIrp ou IoInitializeIrp. Para obter mais informações sobre a alocação de IRP, consulte Criando IRPs para Lower-Level Drivers.

  2. Configurar o local de pilha de E/S do driver inferior para o IRP com o código IOCTL_XXX e os parâmetros apropriados.

  3. Se a solicitação IOCTL for concluída de forma assíncrona, chame a rotina KeInitializeEvent para inicializar um objeto de evento como um evento de notificação. O driver usa esse evento para aguardar a conclusão de uma operação de E/S.

  4. Chame IoSetCompletionRoutine com o IRP para que o driver superior possa fornecer uma rotina IoCompletion , se necessário, para fazer o seguinte:

    • Determine como o driver inferior tratou uma determinada solicitação.

    • Reutilizar o IRP para enviar outra solicitação ou descartar o IRP criado pelo driver, depois que o driver inferior concluir uma operação solicitada. O driver não pode reutilizar IRPs criados por IoBuildDeviceIoControlRequest . Para obter mais informações, consulte Reutiling IRPs.

  5. Chame IoCallDriver para passar a solicitação para o driver inferior.

  6. Se IoCallDriver retornar STATUS_PENDING, chame a rotina KeWaitForSingleObject para colocar o thread atual em um estado de espera. O driver define o parâmetro Object da rotina como o endereço do objeto de evento que foi inicializado na chamada para KeInitializeEvent.

    Nota Se o driver chamar KeWaitForSingleObject com seu parâmetro Timeout definido como NULL ou para o endereço de uma variável que contém um valor diferente de zero, o driver deverá estar em execução em IRQL <= APC_LEVEL em um contexto de thread nãobitrário. Caso contrário, o driver deverá estar em execução em IRQL <= DISPATCH_LEVEL.

O evento é sinalizado por sua rotina IoCompletion quando a solicitação IOCTL é concluída. Depois que o evento é sinalizado, o thread retoma a execução.

Importante Se o driver alocar o objeto de evento como uma variável local na pilha, o driver deverá chamar KeWaitForSingleObject com seu parâmetro WaitMode definido como KernelMode. Esse valor de parâmetro impede que a pilha seja pageada.

Para evitar problemas de sincronização e possíveis violações de acesso, os parâmetros para códigos de controle de E/S raramente incluem ponteiros inseridos. Exceto para determinadas solicitações SCSI, os buffers em Irp-AssociatedIrp.> SystemBuffer, em Irp-MdlAddress > e emParâmetros. DeviceIoControl. Type3InputBuffer no local de pilha de E/S de um driver não contêm ponteiros para outros buffers de dados, nem contêm estruturas que contêm ponteiros para códigos de controle de E/S definidos pelo sistema. Para obter mais informações sobre como os buffers de dados são usados com IRPs que contêm códigos de controle de E/S, consulte Descrições de buffer para códigos de controle de E/S.

No entanto, um par de drivers de classe/porta que define códigos de controle de E/S internos pode passar um ponteiro inserido para a memória alocada pelo driver de nível superior para o driver de nível inferior. Um par de drivers de classe/porta é responsável por garantir que o seguinte seja verdadeiro:

  • Somente um driver por vez pode acessar os dados.

  • Buffers de dados privados são acessíveis em um contexto de thread arbitrário pelo driver de porta.

Os drivers de exibição podem chamar a função GDI EngDeviceIoControl para enviar solicitações de controle de E/S específicas do dispositivo, bem como solicitações de controle de E/S públicas definidas pelo sistema, por meio do driver de porta de vídeo do sistema até os drivers de miniporte de vídeo específicos do adaptador correspondentes.

Qualquer componente de modo de usuário de um pacote de driver pode chamar DeviceIoControl para enviar solicitações de controle de E/S para uma pilha de driver. O gerenciador de E/S cria uma IRP_MJ_DEVICE_CONTROL e a entrega para o driver de nível mais alto.