Sources
Delphi Russian Knowledge Base
DRKB - это самая большая и удобная в использовании база знаний по Дельфи в рунете, составленная Виталием Невзоровым

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

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.