Прямое управление дисковым устройством
Несмотря на то что набор функций, предназначенных для работы с дисками и файлами в среде Microsoft Windows NT, достаточно мощный и удобный, иногда его возможностей может оказаться недостаточно. Например, если вы разрабатываете систему защиты от несанкционированного копирования дискет, вам могут потребоваться средства нестандартного форматирования дискет. Вам также может потребоваться выполнять из приложения извлечение сменного носителя данных или блокировку последнего в накопителе, проверку замены сменного носителя данных или другие “необычные” операции.
Создавая аналогичную програму MS-DOS, вы можете выполнить нестандартное форматиование, например, с помощью функций BIOS или обращаясь непосредственно к портам дискового контроллера. В среде Microsoft Windows NT оба эти способа непригодны, так как функции BIOS и порты контроллера диска недоступны для обычных приложений, работающих в защищенном режиме.
Выход, однако, есть.
Он заключается в прямом обращении к драйверу дискового устройства с помощью функции управления вводом/выводом, которая называется DeviceIoControl. По своим возможностям он напоминает способ, описанный нами в 19 томе “Библиотеки системного программиста” и связанный с использованием функций GENERIC IOCTL.
Прототип функции DeviceIoControl мы привели ниже:
BOOL DeviceIoControl(
HANDLE hDevice, // идентификатор устройства
DWORD dwIoControlCode, // код выполняемой операции
LPVOID lpInBuffer, // буфер для входных данных
DWORD nInBufferSize, // размер буфера lpInBuffer
LPVOID lpOutBuffer, // буфер для выходных данных
DWORD nOutBufferSize, // размер буфера lpOutBuffer
LPDWORD lpBytesReturned, // указатель на счетчик
// выведенных байт
LPOVERLAPPED lpOverlapped); // указатель на
// структуру OVERLAPPED
Через параметр hDevice вы должны передать идентификатор устройства, полученный от функции CreateFile. Для того чтобы воспользоваться этой функцией для открывания устройства, вы должны указать имя устройства следующим образом (пример приведен для диска C:):
hDevice = CreateFile(“\\\\.\\C:”, 0, FILE_SHARE_READ, NULL,
OPEN_EXISTING, 0, NULL);
С помощью параметра dwIoControlCode можно задать один из следующих кодов операции:
Код операции |
Описание |
FSCTL_DISMOUNT_VOLUME |
Размонтирование тома |
FSCTL_GET_COMPRESSION |
Определение состояния компрессии для каталога или файла |
FSCTL_LOCK_VOLUME |
Блокирование тома |
FSCTL_SET_COMPRESSION |
Установка состояния компрессии для каталога или файла |
FSCTL_UNLOCK_VOLUME |
Разблокирование тома |
IOCTL_DISK_CHECK_VERIFY |
Проверка замены носителя данных для устройства со сменным носителем |
IOCTL_DISK_EJECT_MEDIA |
Извлечение носителя данных из устройства с интерфейсом SCSI |
IOCTL_DISK_FORMAT_TRACKS |
Форматирование нескольких дорожек диска |
IOCTL_DISK_GET_DRIVE_GEOMETRY |
Получение информации о физической геометрии диска |
IOCTL_DISK_GET_DRIVE_LAYOUT |
Получение информации о всех разделах диска |
IOCTL_DISK_GET_MEDIA_TYPES |
Получение информации о среде, которую можно использовать для хранения данных в устройстве |
IOCTL_DISK_GET_PARTITION_INFO |
Полечение информации о разделе диска |
IOCTL_DISK_LOAD_MEDIA |
Загрузка носителя данных в устройство |
IOCTL_DISK_MEDIA_REMOVAL |
Включение или отключение механизма извлечения носителя данных |
IOCTL_DISK_PERFORMANCE |
Получение информации о производительности устройства |
IOCTL_DISK_REASSIGN_BLOCKS |
Перевод блоков диска в область резервных блоков |
IOCTL_DISK_SET_DRIVE_LAYOUT |
Создание разделов на диске |
IOCTL_DISK_SET_PARTITION_INFO |
Установка типа разделов диска |
IOCTL_DISK_VERIFY |
Выполнение логического форматирования |
IOCTL_SERIAL_LSRMST_INSERT |
Разрешение или запрещение добавления информации о состоянии линии и модема в поток передаваемых данных |
В буфер, адрес которого передается через параметр lpOutBuffer, будет записан результат выполнения операции. Формат этого буфера также зависит от кода операции.
При необходимости с помощью функции DeviceIoControl вы можете выполнять асинхронные операции, подготовив структуру типа OVERLAPPED и передав ее адрес через параметр lpOverlapped. Не забудьте также при открывании устройства указать функции CreateFile флаг FILE_FLAG_OVERLAPPED.