Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
MiSHI_LR6_met.doc
Скачиваний:
5
Добавлен:
07.09.2019
Размер:
227.33 Кб
Скачать

2.3. Доступ к дискам с использованием Win32 api

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

В функцию передается дескриптор устройства, для получения которого можно воспользоваться функцией CreateFile (см. л.р. №5), передав ей имя файла, в виде \\.\С: - для доступа, например, к тому С, или \\.\PhysicalDrive0 - для доступа к физическому жесткому диску 0. (В тексте программы на языке Си символы «обратная косая черта» должны быть повторены дважды, например «\\\\.\\С:». Также следует отметить, что для доступа к дискам в Windows NT и выше необходимо иметь права доступа администратора системы).

BOOL DeviceIoControl(

HANDLE hDevice,

DWORD dwIoControlCode,

LPVOID lpInBuffer,

DWORD nInBufferSize,

LPVOID lpOutBuffer,

DWORD nOutBufferSize,

LPDWORD lpBytesReturned,

LPOVERLAPPED lpOverlapped

);

hDevice - Дескриптор устройства - обычно том, каталог, файл или поток.

dwIoControlCode - Управляющий код для операции. Это значение идентифицирует конкретную операцию для выполнения и тип устройства, на котором она должна осуществиться. Краткий перечень управляющих кодов приведен в таблице 5:

Таблица 5 – Краткий перечень кодов операций для функции DeviceIoControl

Код операции

Описание

IOCTL_DISK_CHECK_VERIFY

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

IOCTL_DISK_GET_DRIVE_GEOMETRY

Получение информации о физической геометрии

IOCTL_DISK_GET_DRIVE_LAYOUT

Получение информации о разделах диска

IOCTL_DISK_FORMAT_TRACKS

Форматирование нескольких дорожек диска

IOCTL_DISK_GET_PARTITION_INFO

Получение информации о разделе диска

lpInBuffer - Указатель на буфер ввода данных, который содержит данные необходимые, чтобы, выполнить операцию. Формат этих данных зависит от значения параметра dwIoControlCode. Этот параметр может быть установлен в NULL, если dwIoControlCode определяет операцию, которая не требует ввода данных.

nInBufferSize - Размер буфера ввода данных, в байтах.

lpOutBuffer - Указатель на буфер вывода данных, который должен получить данные, возвращенные операцией. Формат этих данных зависит от значения параметра dwIoControlCode. Этот параметр может быть установлен в NULL, если dwIoControlCode определяет операцию, которая не возвращает данные.

nOutBufferSize - Размер буфера вывода данных, в байтах.

lpBytesReturned - Указатель на переменную, которая получает размер данных, сохраненных в буфере вывода данных, в байтах.

lpOverlapped - Указатель на структуру OVERLAPPED. Данная структура содержит информацию, используемую в асинхронном (или перекрывающем) вводе и выводе данных (I/O)

Если операция завершается успешно, DeviceIoControl возвращает ненулевое значение.

Если операция завершается ошибкой, DeviceIoControl возвращает нуль. Чтобы получить дополнительную информацию об ошибке, необходимо вызвать функцию GetLastError.

Получение информации о разделах диска

Ниже приведен пример использования функции DeviceIoControl для получения информации о разделах диска:

// описатель дискового устройства

HANDLE hDrive;

// получаем hDrive

hDrive = CreateFile(

_T("\\\\.\\PhysicalDrive0"), // диск

GENERIC_READ, // чтение диска разрешено

FILE_SHARE_READ, // попытка постороннего

// процесса открыть файл с

// флагом GENERIC_WRITE не удастся

NULL, // атрибуты безопасности

OPEN_EXISTING, // функция вернет ошибку если

// указанный диск не существует

0, // флаги и атрибуты

NULL

);

// в случае неудачи ничего не делаем

if (hDrive == INVALID_HANDLE_VALUE) {

return;

}

// указатель на структуру для записи информации о разделах диска

_DRIVE_LAYOUT_INFORMATION *layoutInfo;

// размер буфера выходных данных

DWORD outBufSize = 4096;

// буфер для выходных данных

char *outBuf = new char [outBufSize];

// количество полученных байт

DWORD butesReturned;

// прямое обращение к драйверу дискового устройства

bool res = DeviceIoControl(

hDrive,

IOCTL_DISK_GET_DRIVE_LAYOUT,

NULL,

0,

outBuf,

outBufSize,

&butesReturned,

NULL

);

// обращение к драйверу закончилось неудачей

if (!res) {

return;

}

// получаем информацию о разделах диска

layoutInfo = (_DRIVE_LAYOUT_INFORMATION *)outBuf;

// закрываем указатель на том

CloseHandle(hDrive);

В данном примере используется структура _DRIVE_LAYOUT_INFORMATION, содержащая в себе информацию о разделах диска:

struct _DRIVE_LAYOUT_INFORMATION {

DWORD                 PartitionCount;

DWORD                 Signature;

PARTITION_INFORMATION PartitionEntry[1];

};

PartitionCount - Количество разделов на диске. Как отмечалось выше, на дисках с MBR, это значение равно 4. В противном случае неиспользуемые разделы, имеют тип PARTITION_ENTRY_UNUSED.

Signature – значение сигнатуры диска

PartitionEntry – переменная типа _PARTITION_INFORMATION, одна структура для каждого раздела диска:

typedef struct _PARTITION_INFORMATION {

LARGE_INTEGER StartingOffset;

LARGE_INTEGER PartitionLength;

DWORD HiddenSectors;

DWORD PartitionNumber;

BYTE PartitionType;

BOOLEAN BootIndicator;

BOOLEAN RecognizedPartition;

BOOLEAN RewritePartition;

}

StartingOffset - начальное смещение раздела

PartitionLength - Размер раздела, в байтах.

HiddenSectors - Количество скрытых секторов в разделе.

PartitionNumber – Номер раздела

PartitionType – Тип раздела. Возможные константы типов разделов приведены в таблице 6:

Таблица 6 – Возможные константы типов разделов

Тип раздела

Описание

PARTITION_ENTRY_UNUSED

Неиспользуемый раздел

PARTITION_EXTENDED

Расширенный раздел

PARTITION_FAT_12

Раздел файловой системы FAT12

PARTITION_FAT_16

Раздел файловой системы FAT16

PARTITION_FAT32

Раздел файловой системы FAT32

PARTITION_IFS

Раздел IFS

PARTITION_LDM

Менеджер логических дисков

PARTITION_NTFT

Раздел NTFT.

VALID_NTFT

Правильный раздел NTFT. Данный тип раздела указывает, что раздел является частью NTFT Raid 0.

BootIndicator - Если этот элемент имеет значение ИСТИНА, раздел является загрузочным.

RecognizedPartition - Если этот элемент имеет значение ИСТИНА, то данный раздел опознанного типа.

RewritePartition - Если этот элемент имеет значение ИСТИНА, информация о разделе изменилась. При изменении раздела (с IOCTL_DISK_SET_DRIVE_LAYOUT), система использует данный флаг, чтобы определить, какие разделы были изменены.

Получение информации о физической геометрии диска

Ниже приведен пример использования функции DeviceIoControl для получения информации о физической геометрии диска:

// указатель на структуру, хранящую геометрию диска

_DISK_GEOMETRY * diskGeoInfo;

// размер буфера выходных данных

DWORD outBufSize = 4096;

// буфер для выходных данных

char *outBuf = new char [outBufSize];

// количество полученных байт

DWORD butesReturned;

// прямое обращение к драйверу дискового устройства

bool res = DeviceIoControl(

hDrive,

IOCTL_DISK_GET_DRIVE_GEOMETRY,

NULL,

0,

outBuf,

outBufSize,

&butesReturned,

NULL

);

// обращение к драйверу закончилось неудачей

if (!res) {

return;

}

// получаем информацию о физической геометрии диска

diskGeoInfo = (_DISK_GEOMETRY *)outBuf;

В данном примере используется структура _DISK_GEOMETRY, описание которой приведено ниже:

struct _DISK_GEOMETRY {

LARGE_INTEGER Cylinders;

MEDIA_TYPE MediaType;

DWORD TracksPerCylinder;

DWORD SectorsPerTrack;

DWORD BytesPerSector;

};

Cylinders – количество цилиндров

MediaType – тип носителя(Unknown, F3_1Pt44_512 (3.5", 1.44MB, 512 байт/сектор), RemovableMedia(съемный диск), FixedMedia (фиксированный жесткий диск))

TracksPerCylinder – количество дорожек на цилиндре

SectorsPerTrack – количество секторов на дорожке

BytesPerSector – количество байт в секторе

Чтение главной загрузочной записи функциями CreateFile() и ReadFile()

Для чтения MBR можно воспользоваться и функциями CreateFile и ReadFile(см. л.р. №5):

typedef unsigned __int16 word;

typedef unsigned __int32 dword;

struct PART {

byte Boot;

byte Begin_Hd;

word Begin_SecTrk;

byte SysCode;

byte End_Hd;

word End_SecTrk;

dword RelSec;

dword Size;

};

struct MBR {

char LoadCode[0x1be];

struct PART rt[4];

word EndFlag;

};

MBR read_mbr()

{

// MBR

MBR mbrObj;

// описатель (дескриптор) дискового устройства

HANDLE hDrive;

// получаем hDrive

AnsiString driveName = "\\\\.\\C:";

hDrive = CreateFile(

driveName.c_str(),

GENERIC_READ,

FILE_SHARE_READ | FILE_SHARE_WRITE,

NULL,

OPEN_EXISTING,

0,

NULL

);

// в случае неудачи ничего не делаем

if (hDrive == INVALID_HANDLE_VALUE) {

ShowMessage("Не удалось прочесть файл");

return mbrObj;

}

// размер буфера выходных данных = размеру MBR

DWORD outBufSize = 4096;

// буфер для выходных данных

char *outBuf = new char [outBufSize];

// количество полученных байт

DWORD butesReturned;

DWORD dwPtr = SetFilePointer(hDrive, 0, NULL, FILE_BEGIN);

BOOL res = ReadFile(

hDrive,

outBuf,

outBufSize,

&butesReturned,

NULL

);

// в случае неудачи ничего не делаем

if (!res) {

CloseHandle(hDrive);

return mbrObj;

}

int ptr;

// Загрузочная запись

for (ptr=0; ptr<sizeof(mbrObj.LoadCode); ptr++)

{

mbrObj.LoadCode[ptr] = outBuf[ptr];

}

// 4 элемента таблицы разделов

for (int i=0; i<4; i++)

{

mbrObj.rt[i].Boot = outBuf[ptr++];

mbrObj.rt[i].Begin_Hd = outBuf[ptr++];

mbrObj.rt[i].Begin_SecTrk = outBuf[ptr++];

mbrObj.rt[i].Begin_SecTrk = mbrObj.rt[i].Begin_SecTrk << 8;

mbrObj.rt[i].Begin_SecTrk = outBuf[ptr++];

mbrObj.rt[i].SysCode = outBuf[ptr++];

mbrObj.rt[i].End_Hd = outBuf[ptr++];

mbrObj.rt[i].End_SecTrk = outBuf[ptr++];

mbrObj.rt[i].End_SecTrk = mbrObj.rt[i].Begin_SecTrk << 8;

mbrObj.rt[i].End_SecTrk = outBuf[ptr++];

mbrObj.rt[i].RelSec =

(__int64(outBuf[ptr]) << 24) +

(__int64(outBuf[ptr+1]) << 16) +

(__int64(outBuf[ptr+2]) << 8) +

(__int64(outBuf[ptr+3]));

ptr += 4;

mbrObj.rt[i].Size =

(__int64(outBuf[ptr]) << 24) +

(__int64(outBuf[ptr+1]) << 16) +

(__int64(outBuf[ptr+2]) << 8) +

(__int64(outBuf[ptr+3]));

ptr += 4;

}

// Сигнатура (55AAh)

mbrObj.EndFlag = (__int16(outBuf[ptr]) << 8) + outBuf[ptr+1];

// закрываем указатель на том

CloseHandle(hDrive);

return mbrObj;

}

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]