Диспетчерские точки входа драйвера
Запросы IRP_MJ_DEVICE_CONTROL и IRP^MJJNTERNA^DEVICE^CONTROL
Как говорилось выше, точка входа драйвера IRP_MJ_DEVICE_CONTROL вызывается при вызове пользовательской программой функции DeviceloControl().
Прототип этой функции:
BOOL DeviceloControl (HANDLE hDevice,// описатель открытого устройства DWORD dwIoControlCode,// контрольный код запрашиваемой операции DWORD nlnBufferSize, LPVOID IpOutBuffer,// адрес буфера со входными данными DWORD nOutBufferSize, LPDWORD IpBytesReturnedy// размер входного буфера // адрес буфера для приема // выходных данных // размер выходного буфера // адрес переменной // для получения // числа реально // переданных байтов данных LPOVERLAPPED IpOverlapped // адрес структуры // для обеспечения // асишсронности // ввода/вывода
Зачем нужен IRP_MJ_DEVICE_CONTROL? Когда драйвер поддерживает определенный тип устройства, такое устройство обычно имеет набор специализированных возможностей, которые могут управляться через драйвер. Эти возможности не могут быть задействованы использованием стандартных кодов функций IRP_MJ_CREATE, IRP_MJ_CLOSE, IRP_MJ_READ и IRP_MJ_WRITE. Например, драйвер устройства для лентопротяжного устройства SCSI должен обеспечить механизм, который дает возможность пользователям послать запрос на стирание ленты. Такие зависящие от устройства запросы описываются, используя главный функциональный код IRP_MJ_DEVICE_CONTROL. Устройство обычно может принимать несколько разнотипных команд. Для драйвера тип такой команды указывается Кодом Управления ввода/вывода (IOCTL), который передается как часть запроса ввода/вывода.
Возвращаясь к функции DeviceloControl(), код управления ввода/вывода (IOCTL) указывается во втором параметре этой функции. Код управления ввода/вывода имеет специальный формат, указывающий метод передачи буфера и другую информацию. Этот формат будет рассмотрен в следующем разделе. Путаница может возникнуть при задании буфера для ввода/вывода.
Как видно из прототипа функции DeviceloControl(), она может передавать два буфера (третий и пятый параметры). Несмотря на названия буферов – входной и выходной буфер – выходной буфер может быть использован как для передачи данных в драйвер, так и для приема данных из драйвера. Разница будет в используемом методе передачи буфера. Использование буферов будет подробно рассмотрено в разделе "Получение буфера".
Задание кода управления вводом/выводом (IOCTL)
Формат кода управления ввода/вывода показан на рис. 11.
Рис. 11. Формат кода управления вводом/выводом
CTL_CODE(DeviceType, Function, Method, Access) – специальный макрос, определенный в заголовочных файлах ntddk.h и windows.h, для задания кода в формате, представленном на рис. 11.