Программирование для Windows NT

Прямое управление дисковым устройством


Несмотря на то что набор функций, предназначенных для работы с дисками и файлами в среде 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

Разрешение или запрещение добавления информации о состоянии линии и модема в поток передаваемых данных

Через параметр lpInBuffer вы должны передать функции DeviceIoControl адрес управляющего блока, необходимого для выполнения опрации. Формат этого блока зависит от кода выполняемой операции. В документации SDK приведены форматы управляющих блоков для всех перечисленных выше кодов операций.

В буфер, адрес которого передается через параметр lpOutBuffer, будет записан результат выполнения операции. Формат этого буфера также зависит от кода операции.

При необходимости с помощью функции DeviceIoControl вы можете выполнять асинхронные операции, подготовив структуру типа OVERLAPPED и передав ее адрес через параметр lpOverlapped. Не забудьте также при открывании устройства указать функции CreateFile флаг FILE_FLAG_OVERLAPPED.


Содержание раздела