- •Л а б о р а т о р н а я р а б о т а № 1 Физическая структура дисковой памяти
- •1. Теоретическая часть
- •2. Практическая часть
- •3. Содержание отчета
- •Основные сведения о системном отладчике debug
- •Л а б о р а т о р н а я р а б о т а № 2 Системные средства распределения дискового пространства в ос Windows и ms dos
- •1. Теоретическая часть
- •2. Практическая часть
- •3.Содержание отчета
- •Л а б о р а т о р н а я р а б о т а № 3 Создание приложений Windows с использованием средств прикладного программирования Win32 api
- •2. Функции для выполнения операций с файлами, папками и дисками
- •2.2. Задание для выполнения к части 1 лабораторной работы
- •Часть 2
- •Processor_intel_486;
- •Часть 3
- •5. Содержание отчета по лабораторной работе
- •Лабораторная работа № 4 Архитектура и особенности файловой системы fat32
- •1.1. Общая характеристика файловой системы fat32
- •1.2. Системные структуры данных fat32
- •1.3. Программная реализация чтения системных структур раздела диска с файловой системой fat 32
- •2. Практическая часть
- •3.Содержание отчета
- •Литература
1.3. Программная реализация чтения системных структур раздела диска с файловой системой fat 32
Обращение к разделу жесткого диска в операционных системах Windows 2000/XP может быть выполнено путем открытия диска как файла с помощью функции CreateFile и указания диска или его раздела по схеме Device Namespace (открывается физический диск - '\\.\PHYSICALDRIVE<n>'). Полученный хэндл в дальнейшем используется для работы с диском с помощью функций ReadFile, WriteFile и DeviceIoControl.
Для выполнения этой операции можно использовать следующий программный код:7
// Drive - номер диска (нумерация с нуля).
hFile := CreateFile(PChar('\\.\PhysicalDrive'+IntToStr(Drive)),
GENERIC_READ, FILE_SHARE_READ or FILE_SHARE_WRITE,nil,OPEN_EXISTING,0,0);
if hFile = INVALID_HANDLE_VALUE then Exit;
В результате появляется возможность воспринимать физический диск как единый файл.
Чтобы получить информацию о геометрии диска можно использовать еще один программный фрагмент:
const
IOCTL_DISK_GET_DRIVE_GEOMETRY = $70000;
type
TDiskGeometry = packed record
Cylinders: Int64; // количество цилиндров
MediaType: DWORD; // тип носителя
TracksPerCylinder: DWORD; // дорожек на цилиндре
SectorsPerTrack: DWORD; // секторов на дорожке
BytesPerSector: DWORD; // байт в секторе
end;
Result := DeviceIoControl(hFile,IOCTL_DISK_GET_DRIVE_GEOMETRY,nil,0,
@DiskGeometry,SizeOf(TDiskGeometry),junk,nil) and (junk = SizeOf(TDiskGeometry));
Функция DeviceIoControl возвращает True, если операция прошла успешно, и False в противном случае.
Основной операцией при работе с системными структурами данных FAT32 является операция чтения содержимого сектора диска. Она может быть выполнена с помощью функции, одна из программных реализаций которых (функция ReadSectors) представлена ниже.
// так как диск - это единый файл, то для перемещения по нему
// с помощью функции SetFilePointer понадобится 64х-разрядная арифметика
function __Mul(a,b: DWORD; var HiDWORD: DWORD): DWORD; // Result = LoDWORD
asm
mul edx
mov [ecx],edx
end;
function ReadSectors(DriveNumber: Byte; StartingSector, SectorCount: DWORD;
Buffer: Pointer; BytesPerSector: DWORD = 512): DWORD;
var
hFile: THandle;
br,TmpLo,TmpHi: DWORD;
begin
Result := 0;
hFile := CreateFile(PChar('\\.\PhysicalDrive'+IntToStr(DriveNumber)),
GENERIC_READ,FILE_SHARE_READ,nil,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
if hFile = INVALID_HANDLE_VALUE then Exit;
TmpLo := __Mul(StartingSector,BytesPerSector,TmpHi);
if SetFilePointer(hFile,TmpLo,@TmpHi,FILE_BEGIN) = TmpLo then
begin
SectorCount := SectorCount*BytesPerSector;
if ReadFile(hFile,Buffer^,SectorCount,br,nil) then Result := br;
end;
CloseHandle(hFile);
end;
Функция ReadSectors возвращает количество прочитанных байт.
Ниже в качестве примера приводится программный код для чтения сектора диска, содержащего структуры MBR и Partition Table.
TPartitionTableEntry = packed record
BootIndicator: Byte; // $80, если активный (загрузочный) раздел
StartingHead: Byte;
StartingCylAndSect: Word;
SystemIndicator: Byte;
EndingHead: Byte;
EndingCylAndSect: Word;
StartingSector: DWORD; // начальный сектор
NumberOfSects: DWORD; // количество секторов
end;
TPartitionTable = packed array [0..3] of TPartitionTableEntry;
PDriveInfo = ^TDriveInfo;
TDriveInfo = record
PartitionTable: TPartitionTable;
LogicalDrives: array [0..3] of PDriveInfo;
end;
const
PartitionTableOffset = $1be;
ExtendedPartitions = [5,$f];
var
MainExPartOffset: DWORD = 0;
function GetDriveInfo(DriveNumber: Byte; DriveInfo: PDriveInfo;
StartingSector: DWORD; BytesPerSector: DWORD = 512): Boolean;
var
buf: array of Byte;
CurExPartOffset: DWORD;
i: Integer;
begin
SetLength(buf,BytesPerSector);
// читаем сектор в буфер
if ReadSectors(DriveNumber,MainExPartOffset+StartingSector,1,@buf[0]) = 0 then
begin
Result := False;
Exit;
end;
// заполняем структуру DriveInfo.PartitionTable
Move(buf[PartitionTableOffset],DriveInfo.PartitionTable,SizeOf(TPartitionTable));
Finalize(buf); // буфер больше не нужен
Result := True;
for i := 0 to 3 do // для каждой записи в Partition Table
if DriveInfo.PartitionTable[i].SystemIndicator in ExtendedPartitions then
begin
New(DriveInfo.LogicalDrives[I]);
if MainExPartOffset = 0 then
begin
MainExPartOffset := DriveInfo.PartitionTable[I].StartingSector;
CurExPartOffset := 0;
end else CurExPartOffset := DriveInfo.PartitionTable[I].StartingSector;
Result := Result and GetDriveInfo(DriveNumber,DriveInfo.LogicalDrives[I],
CurExPartOffset);
end else DriveInfo.LogicalDrives[I] := nil;
end;
Функция GetDriveInfo заполняет структуру DriveInfo и возвращает True, если операция прошла успешно, или False в противном случае.