Показать структуру разделов жесткого диска
01.01.2007
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ComCtrls; type TForm1 = class(TForm) Button1: TButton; TreeView1: TTreeView; procedure FormCreate(Sender: TObject); private { Private declarations } public { Public declarations } Function SearchLogicalDisks:Int64; end; var Form1: TForm1; implementation Uses Disk; TYPE {---------------------- Структура описателя раздела -------------------------} PPartition = ^TPartition; TPartition { }=packed Record Boot { Флаг активности $80=YES, $00=NO }: BYTE; BegHead { Головка }: BYTE; BegCylSec { Цылиндер и сектор }: WORD; PartType { Код типа раздела (Смотрите ниже) }: BYTE; EndHead { Головка }: BYTE; EndCylSec { Цылиндер и сектор }: WORD; Sector { Номер начального сектора раздела }: LongInt; PartSize { Размер раздела в секторах }: LongInt; end; const PARTITION_ENTRY_UNUSED = $00; // Entry unused PARTITION_FAT_12 = $01; // 12-bit FAT entries PARTITION_XENIX_1 = $02; // Xenix PARTITION_XENIX_2 = $03; // Xenix PARTITION_FAT_16 = $04; // 16-bit FAT entries PARTITION_EXTENDED = $05; // Extended partition entry PARTITION_FAT16 = $06; // Unformatted PARTITION_IFS = $07; // IFS Partition PARTITION_OS2BOOTMGR = $08; // OS/2 Boot Manager/OPUS/Coherent swap PARTITION_FAT32 = $0B; // FAT32 PARTITION_FAT32_XINT13 = $0C; // FAT32 using extended int13 services PARTITION_XINT13 = $0E; // Win95 partition using extended int13 services PARTITION_XINT13_EXTENDED = $0F; // Same as type 5 but uses extended int13 services PARTITION_PREP = $41; // PowerPC Reference Platform (PReP) Boot Partition PARTITION_LDM = $42; // Logical Disk Manager partition PARTITION_UNIX = $63; // Unix PARTITION_LINUX_SWAP = $82; // Linux swap PARTITION_LINUX_EXT2 = $83; // Linux ext2 VALID_NTFT = $C0; // NTFT uses high order bits {--------- Структура главной загрузочной записи и таблицы разделов ----------} TYPE PPartitionTable = ^TPartitionTable; TPartitionTable { }=packed Record Boot { Загрузочная запись (MSB) }:array[1..446] of Byte; Partition { Описатель радела 1 }:array[1..4] of TPartition; TrailSig { Сигнатура AA55h }:array[1..2] of byte; end; Var MNode,ExtNode,Node:TTreeNode; HddNumber:Byte; function ReadSector (Sector:Int64; Count:word; Var Buffer): DWORD; Begin Result:=ReadPlysicalSector (HddNumber,Sector,Count,Buffer); end; // Ф-ция заполняет масив таблицу разделов, возвращает номер // активного раздела или $FF при неправельном построение... Function GetPartitionTable(PartitionSector:Int64; Var PartitionTable:PPartitionTable):Byte; Var I : Byte; Begin ReadSector(PartitionSector,1,PartitionTable^); For i:=1 to 4 do If PPartitionTable(PartitionTable)^.Partition[i].Boot = $80 Then Result:=(i+1); If (Result > 1) or (Result < 1) Then Result:=$FF; // Ошибка построения разделов end; function PartitionTypeToString (Value : Integer) : String; begin case Value of $00:Result:='Unused'; $01:Result:='FAT 12'; $02:Result:='XENIX Root'; $03:Result:='XENIX Usr'; $04:Result:='FAT 16'; $05:Result:='Extended Partition'; $06:Result:='FAT 16'; $07:Result:='NTFS'; $08:Result:='AIX bootable'; $09:Result:='AIX data Coher'; $0A:Result:='OS/2 Swap'; $0B:Result:='FAT 32'; $0C:Result:='FAT 32 LBA'; $0E:Result:='DOS Extended'; $0F:Result:='DOS Extended LBA'; $10:Result:='OPUS'; $12:Result:='Compaq Diagnostics'; $16:Result:='Hidden (PM)'; $17:Result:='NTFS Hidden (PM)'; $18:Result:='AST swap'; $19:Result:='Willowtech Photon'; $1B:Result:='FAT32 Hidden(PM)'; $1E:Result:='FAT 16 (Win ME)'; $20:Result:='Willowsoft Overture'; $21:Result:='Oxygen FSo2'; $22:Result:='Oxygen Ext'; $24:Result:='NEC-DOS v3x'; $38:Result:='Theos'; $3C:Result:='PMagic'; $40:Result:='Venix 286'; $41:Result:='Personal RISC Boot'; $42:Result:='Secure FS'; $45:Result:='EUMEL/Elan'; $46:Result:='EUMEL/Elan'; $47:Result:='EUMEL/Elan'; $48:Result:='EUMEL/Elan'; $4D:Result:='QNX 1.Part'; $4E:Result:='QNX 2.Part'; $4F:Result:='QNX 3.Part'; $50:Result:='OnTrack Read-Only'; $51:Result:='OnTrack R/W'; $52:Result:='Microport'; $53:Result:='OnTrack, Aux3'; $54:Result:='OnTrack, DDO'; $55:Result:='EZ-Drive'; $56:Result:='Golden Bow'; $5C:Result:='Priam EDisk'; $61:Result:='Speed Stor'; $63:Result:='GNUHurd'; $64:Result:='Netware 286'; $65:Result:='Netware 386 v4x'; $67:Result:='Netware'; $68:Result:='Netware'; $69:Result:='Netware 386 v3x'; $70:Result:='DiskSecure MuliBoot'; $75:Result:='PC/ix'; $7E:Result:='F.I.X.'; $80:Result:='MINIX 1.1-1.4a'; $81:Result:='Linux'; $82:Result:='Linux swap'; $83:Result:='Linux'; $85:Result:='Linux Ext part'; $86:Result:='NTFS FAT 16'; $87:Result:='HPFS'; $93:Result:='Amoeba FS'; $94:Result:='Amoeba BadBlockTable'; $98:Result:='Datalight ROM-DOS'; $99:Result:='Unix'; $A0:Result:='Notebook swap'; $A5:Result:='FreeBSD'; $A6:Result:='OpenBSD'; $A7:Result:='NEXTSTEP'; $A9:Result:='NetBSD'; $AA:Result:='Olivetti FAT12'; $B0:Result:='BOOTSTAR Dummy'; $B6:Result:='Windows NT mirror'; $B7:Result:='BSDI'; $B8:Result:='BSDI swap'; $BE:Result:='Solaris boot'; $C0:Result:='CTOS'; $C1:Result:='DR-DOS (FAT 12 bit)'; $C4:Result:='DR-DOS (FAT 16 bit)'; $C6:Result:='DR-DOS (Huge)'; $C7:Result:='Syrinx Boot'; $CC:Result:='DR-DOS FAT32 LBA'; $CE:Result:='DR-DOS FAT16 LBA'; $D0:Result:='Multiuser DOS FAT 12'; $D1:Result:='Multiuser DOS FAT 12'; $D4:Result:='Multiuser DOS FAT 16'; $D5:Result:='Multiuser DOS ext'; $D6:Result:='Multiuser DOS FAT 16'; $D8:Result:='CP/M-86'; $DB:Result:='CP/M / Concurrent DOS'; $E1:Result:='Speed Stor DOS access'; $E2:Result:='DOS readonly XFDisk'; $E3:Result:='DOS readonly'; $E4:Result:='SpeedStor FAT 16 ext'; $EB:Result:='BeOS'; $F1:Result:='SpeedStor'; $F2:Result:='DOS secondary'; $F4:Result:='SpeedStor DOS access'; $F5:Result:='Prologue'; $FE:Result:='IBM PS2'; $FF:Result:='Xenix Bad Block Table'; else Result := 'Unknown'; end; end; {$R *.dfm} Function TForm1.SearchLogicalDisks:Int64; Label PrimPartFound, PrimPartNotFound, ExtPartFound, OtherExtPartFound1, OtherExtPartFound2, NextDriveNotPresent0, ReadSMBR, NextDriveNotPresent1, SearchEnd; TYPE TData = record // Номер раздела PartitionNumber : Byte; // Начальный номер основного раздела DOS PriDOS_StartSector : Int64; // Начальный номер расширенного раздела DOS ExtDOS_StartSector : Int64; // Нчальный сектор текущего логического диска CurrentDrive_StartSector : Int64; // Номер логического диска LogicalDriveNumber : Byte; // Флаг присутствияв системе следующего диска NextDrivePresent : Boolean; end; PData = ^TData; Var // Таблица разделов Partition : PPartitionTable; // Переменные... Data : PData; I : Integer; Begin MNode:=TreeView1.Items.Add(nil,'HDD Driver'); Result:=0; // Выделяем память для наших переменных New(Data); // Онулируем все переменные FillMemory(Data,SizeOf(TData),0); // Выделяем память для таблиц разделов New(Partition); GetPartitionTable(Data.CurrentDrive_StartSector,Partition); Data.NextDrivePresent:=False; // Проверить код основного раздела For i:=0 to 3 do IF (Partition.Partition[1].PartType <> $00) or ((Partition.Partition[1].PartType <> $05) and (Partition.Partition[1].PartType <> $0F)) Then with Partition.Partition[1] do Begin Node:=TreeView1.Items.AddChild(MNode,'1st partition ('+ PartitionTypeToString(PartType)+') '); Break; goto PrimPartFound; end else if Partition.Partition[1].Sector = 0 Then Begin Break; //----- Result:=1; -----\\ // Диск не размечен goto SearchEnd; end else IF (Partition.Partition[1].PartType <> $05) or (Partition.Partition[1].PartType <> $0F) Then Begin Break; //----- Result:=2; -----\\ // Основной раздел определен как расширеный goto SearchEnd; end else Begin Break; //----- Result:=3; -----\\ // Не определенный раздел goto SearchEnd; end; PrimPartFound: Begin Data.PriDOS_StartSector:= Partition.Partition[1].Sector; Inc(Data.LogicalDriveNumber); // Проверить код расширенного раздела For i:=0 to 3 do IF ((Partition.Partition[2].PartType = $05) or (Partition.Partition[2].PartType = $0F)) and (Partition.Partition[2].PartType <> $00) Then Begin ExtNode:=TreeView1.Items.AddChild(MNode, '2st partition ('+PartitionTypeToString(Partition.Partition[2].PartType)+') '); // Проверить коды других разделов Node:=TreeView1.Items.AddChild(MNode, '3st partition ('+PartitionTypeToString(Partition.Partition[3].PartType)+') '); Node:=TreeView1.Items.AddChild(MNode, '4st partition ('+PartitionTypeToString(Partition.Partition[4].PartType)+') '); Break; goto ExtPartFound end else Begin Break; goto NextDriveNotPresent0; end; // Имеется расширенный раздел ExtPartFound: Begin // Извлечь адрес сектора Data.ExtDOS_StartSector := Partition.Partition[2].Sector; Data.NextDrivePresent := True; end; end; NextDriveNotPresent0: Begin // Имеется следующий диск? if not Data.NextDrivePresent Then goto SearchEnd; Data.CurrentDrive_StartSector:=Data.ExtDOS_StartSector; end; {- ЦИКЛ ОПРОСА ЛОГИЧЕСКИХ ДИСКОВ РАСШИРЕННОГО РАЗДЕЛА -} ReadSMBR: Begin Inc(Data.LogicalDriveNumber); Node:=ExtNode; ExtNode:=TreeView1.Items.AddChild(ExtNode, '1st partition ('+PartitionTypeToString(Partition.Partition[1].PartType)+') '); ExtNode:=TreeView1.Items.AddChild(Node, '2st partition ('+PartitionTypeToString(Partition.Partition[2].PartType)+') '); // Прочитать очередной SMBR GetPartitionTable(Data^.CurrentDrive_StartSector,Partition); Data.NextDrivePresent:=False; // Смещение второй записи If Partition.Partition[2].Sector = 0 Then goto NextDriveNotPresent1; Data.CurrentDrive_StartSector:= Partition.Partition[2].Sector+ Data.ExtDOS_StartSector; Data.NextDrivePresent:=True; NextDriveNotPresent1: Begin // Имеется следующий диск? if not Data.NextDrivePresent then goto SearchEnd else goto ReadSMBR; end; end; SearchEnd: Result:=DATA.LogicalDriveNumber; // Освобождаем память if Assigned(Partition) Then Dispose(Partition); // Освобождаем память if Assigned(Data) Then Dispose(Data); Exit; end; procedure TForm1.FormCreate(Sender: TObject); begin HddNumber:=0; SearchLogicalDisks; end; end.