Creación de solicitudes IOCTL en controladores
Un controlador de clase u otro controlador de nivel superior puede asignar IRP para las solicitudes de control de E/S y enviarlos al siguiente controlador inferior de la siguiente manera:
Asigne o reutilice un paquete de solicitud de E/S (IRP) con el código de función principal IRP_MJ_DEVICE_CONTROL o IRP_MJ_INTERNAL_DEVICE_CONTROL. Puede usar la rutina IoBuildDeviceIoControlRequest para asignar específicamente un IRP de IOCTL. También puede usar rutinas de creación e inicialización de IRP de uso general, como IoAllocateIrp, IoReuseIrp o IoInitializeIrp. Para obtener más información sobre la asignación de IRP, consulte Creación de IRP para controladores de Lower-Level.
Configure la ubicación de pila de E/S del controlador inferior para irP con el código IOCTL_XXX y los parámetros adecuados.
Si la solicitud IOCTL se va a completar de forma asincrónica, llame a la rutina KeInitializeEvent para inicializar un objeto de evento como evento de notificación. El controlador usa este evento para esperar a que se complete una operación de E/S.
Llame a IoSetCompletionRoutine con el IRP para que el controlador superior pueda proporcionar una rutina de IoCompletion , si es necesario, para hacer lo siguiente:
Determine cómo el controlador inferior controló una solicitud determinada.
Reutilice el IRP para enviar otra solicitud o eliminar el IRP creado por el controlador después de que el controlador inferior complete una operación solicitada. El controlador no puede reutilizar los IRP creados por IoBuildDeviceIoControlRequest . Para obtener más información, consulte Reutilización de IRP.
Llame a IoCallDriver para pasar la solicitud al controlador inferior.
Si IoCallDriver devuelve STATUS_PENDING, llame a la rutina KeWaitForSingleObject para colocar el subproceso actual en un estado de espera. El controlador establece el parámetro Object de la rutina en la dirección del objeto de evento que se inicializó en la llamada a KeInitializeEvent.
Nota Si el controlador llama a KeWaitForSingleObject con su parámetro Timeout establecido en NULL o en la dirección de una variable que contiene un valor distinto de cero, el controlador debe ejecutarse en IRQL <= APC_LEVEL en un contexto de subproceso nobitrario. De lo contrario, el controlador debe ejecutarse en IRQL <= DISPATCH_LEVEL.
La rutina IoCompletion señala el evento cuando se ha completado la solicitud IOCTL. Una vez que se señaliza el evento, el subproceso reanuda la ejecución.
Importante Si el controlador asigna el objeto de evento como una variable local en la pila, el controlador debe llamar a KeWaitForSingleObject con su parámetro WaitMode establecido en KernelMode. Este valor de parámetro impide que la pila se pagina.
Para evitar problemas de sincronización y posibles infracciones de acceso, los parámetros de los códigos de control de E/S rara vez incluyen punteros incrustados. Excepto para determinadas solicitudes SCSI, los búferes en Irp-AssociatedIrp>. SystemBuffer, en Irp-MdlAddress > y enParameters. DeviceIoControl. Type3InputBuffer en la ubicación de pila de E/S de un controlador no contienen punteros a otros búferes de datos, ni contienen estructuras que contienen punteros para códigos de control de E/S definidos por el sistema. Para obtener más información sobre cómo se usan los búferes de datos con IRP que contienen códigos de control de E/S, vea Descripciones del búfer para códigos de control de E/S.
Sin embargo, un par de controladores de clase/puerto que definen códigos de control de E/S internos pueden pasar un puntero incrustado a la memoria asignada por el controlador desde el controlador de nivel superior al controlador de nivel inferior. Este par de controladores de clase/puerto es responsable de garantizar que se cumple lo siguiente:
Solo un controlador a la vez puede acceder a los datos.
El controlador de puerto puede acceder a los búferes de datos privados en un contexto de subproceso arbitrario.
Los controladores de pantalla pueden llamar a la función GDI EngDeviceIoControl para enviar solicitudes de control de E/S definidas de forma privada, específicas del dispositivo, así como solicitudes de control de E/S públicas definidas por el sistema, a través del controlador de puerto de vídeo del sistema hasta los controladores de miniporte de vídeo específicos del adaptador correspondientes.
Cualquier componente en modo de usuario de un paquete de controladores puede llamar a DeviceIoControl para enviar solicitudes de control de E/S a una pila de controladores. El administrador de E/S crea una solicitud de IRP_MJ_DEVICE_CONTROL y la entrega al controlador de nivel superior.