Показать структуру разделов жесткого диска

Previous  Top  Next

    
 

 

 

Code:

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.