Einzelnen Beitrag anzeigen

Benutzerbild von Captnemo
Captnemo

Registriert seit: 27. Jan 2003
Ort: Bodenwerder
1.126 Beiträge
 
Delphi XE4 Architect
 
#5

AW: Partition auslesen mit DeviceIoControl und IOCTL_DISK_GET_PARTITION_INFO_EX

  Alt 9. Okt 2015, 09:50
So, ich hab jetzt alles soweit, dass ich die Partitionen theoretisch auslesen könnte.
Leider liest er mir aber immer nur die erste Partition einer Festplatte aus. Woran könnte das noch liegen?

Hier mal mein Code:
Delphi-Quellcode:
unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    mmo1: TMemo;
    btn1: TButton;
    btn2: TButton;
    mmo2: TMemo;
    procedure btn1Click(Sender: TObject);
    procedure btn2Click(Sender: TObject);
  private
    function GetSizeAsString(Size: Int64): string;
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

  const
    PARTITION_BASIC_DATA_GUID = 'ebd0a0a2-b9e5-4433-87c0-68b6b72699c7';
    PARTITION_ENTRY_UNUSED_GUID = '00000000-0000-0000-0000-000000000000';
    PARTITION_SYSTEM_GUID = 'c12a7328-f81f-11d2-ba4b-00a0c93ec93b';
    PARTITION_MSFT_RESERVED_GUID = 'e3c9e316-0b5c-4db8-817d-f92df00215ae';
    PARTITION_LDM_METADATA_GUID = '5808c8aa-7e8f-42e0-85d2-e1e90434cfb3';
    PARTITION_LDM_DATA_GUID = 'af9b60a0-1431-4f62-bc68-3311714a69ad';
    PARTITION_MSFT_RECOVERY_GUID = 'de94bba4-06d1-4d40-a16a-bfd50179d6ac';

    GTP_ATTRIBUTE_PLATFORM_REQUIRED = $0000000000000001;
    GPT_BASIC_DATA_ATTRIBUTE_NO_DRIVE_LETTER = $8000000000000000;
    GPT_BASIC_DATA_ATTRIBUTE_HIDDEN = $4000000000000000;
    GTP_BASIC_data_ATTRIBUTE_SHADOW_COPY = $2000000000000000;
    GTP_BASIC_DATA_ATTRIBUTE_READ_ONLY = $1000000000000000;

    PARTITION_ENTRY_UNUSED = $00;
    PARTITION_EXTENDED = $05;
    PARTITION_FAT_12 = $01;
    PARTITION_FAT_16 = $04;
    PARTITION_FAT32 = $0B;
    PARTITION_IFS = $07;
    PARTITION_LDM = $42;
    PARTITION_NTFT = $80;
    VALID_NTFT = $C0;



  Type
    PARTITION_STYLE = type Integer;

    PARTITION_INFORMATION_MBR = record
      PartitionType: Byte;
      BootIndicator: BOOL;
      RecognizedPartition: BOOL;
      HiddenSecorts: DWORD;
    end;

    PARTITION_INFORMATION_GPT = record
      PartitonType: TGUID;
      PartitionId: TGUID;
      Attributes: DWORD64;
      Name: WCHAR;
    end;

    _PARTITION_INFORMATION_EX = record
      PartitionStyle: PARTITION_STYLE;
      StartingOffset: LARGE_INTEGER;
      PartitionLength: LARGE_INTEGER;
      PartitionNumber: ULONG;
      RewritePartition: Boolean;
      case Integer of
       0: (Mbr: PARTITION_INFORMATION_MBR);
       1: (Gpt: PARTITION_INFORMATION_GPT);
    end;

    DRIVE_LAYOUT_INFORMATION_MBR = record
      Signature: ULONG;
    end;

    DRIVE_LAYOUT_INFORMATION_GPT = record
      DiskID: TGUID;
      StartingusableOffset: LARGE_INTEGER;
      UsableLength: LARGE_INTEGER;
      MaxPartitionCount: ULONG;
    end;

    DRIVE_LAYOUT_INFORMATION_EX = record
      PartitionStyle: DWORD;
      PartitionCount: DWORD;
      DriveLayoutInfoType: record
        case Integer of
          0: (Mbr: DRIVE_LAYOUT_INFORMATION_MBR);
          1: (Gpt: DRIVE_LAYOUT_INFORMATION_GPT);
      end;
      PartitionInfoEx: array[0..10] of _PARTITION_INFORMATION_EX;
    end;

  const
    PARTITION_STYLE_MBR = PARTITION_STYLE(0);
    PARTITION_STYLE_GPT = PARTITION_STYLE(1);
    PARTITION_STYLE_RAW = PARTITION_STYLE(2);

  function FindFirstVolume(lpszVolumeName: LPTSTR; cchBufferLength: DWord): THandle; stdcall; external 'kernel32.dllname 'FindFirstVolumeW';
  function FindNextVolume(hFindVolume: THandle; lpszVolumeName: LPTSTR; cchBufferLength: DWORD): BOOL; stdcall; external 'kernel32.dllname 'FindNextVolumeW';
  function FindVolumeClose(hFindVolume: THandle): BOOL; stdcall; external 'kernel32.dllname 'FindVolumeClose';
  function GetVolumePathNames(lpszVolumeName: LPCTSTR; lpszVolumePathName: LPTSTR; cchBufferLength: DWORD; lpcchReturnLength: PDWORD): BOOL; stdcall; external 'kernel32.dllname 'GetVolumePathNamesForVolumeNameW';


var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.btn1Click(Sender: TObject);
var
  h, p: Integer;
  Device: string;
  hDevice: Cardinal;
  PARTITION_INFORMATION_EX: _PARTITION_INFORMATION_EX;
  Len: Cardinal;
  StartOffset, PartLength: Int64;
begin
  for h := 1 to 9 do
  begin
    Device:='\\.\Harddisk1'+IntToStr(h);
    hdevice:=CreateFile(PChar(Device), 0, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
    if hDevice <> INVALID_HANDLE_VALUE then
    begin
      ZeroMemory(@PARTITION_INFORMATION_EX, SizeOf(PARTITION_INFORMATION_EX));
      DeviceIoControl(hDevice, IOCTL_DISK_GET_PARTITION_INFO_EX, nil, 0, @PARTITION_INFORMATION_EX, SizeOf(PARTITION_INFORMATION_EX), Len, nil);
      StartOffset:=PARTITION_INFORMATION_EX.StartingOffset.QuadPart;
      PartLength:=PARTITION_INFORMATION_EX.PartitionLength.QuadPart;
      mmo1.Lines.Add(Device+' = '+IntToStr(StartOffset)+' - '+IntToStr(PartLength));
      CloseHandle(hDevice);
    end;
    //end;
  end;
end;

procedure TForm1.btn2Click(Sender: TObject);
var
  RetBytes: DWORD;
  hDevice: Cardinal;
  Status: LongBool;
  Drive: string;
  Layout: ^DRIVE_LAYOUT_INFORMATION_EX;
  I,p: Integer;
  PartCount: Integer;
begin
  mmo1.Lines.Clear;
  mmo2.Lines.Clear;
  for I := 0 to 15 do
  begin
    Drive:='\\.\PhysicalDrive'+IntToStr(i);
    hDevice:=CreateFile(PChar(Drive), 0, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
    if hDevice<>INVALID_HANDLE_VALUE then
    begin
      GetMem(Layout, SizeOf(DRIVE_LAYOUT_INFORMATION_EX) + (SizeOf(_PARTITION_INFORMATION_EX)*15));
      Status:=DeviceIoControl(hDevice, IOCTL_DISK_GET_DRIVE_LAYOUT_EX, nil, 0, Layout, SizeOf(DRIVE_LAYOUT_INFORMATION_EX), RetBytes, nil);
      if (Status=False) then
        mmo1.lines.Add(IntToStr(i+1)+'. Festplatte abfrage fehlgeschalten') else
      begin
        PartCount:=0;
        mmo1.Lines.Add(IntToStr(i+1)+'. Festplatte = '+inttostr(Layout.PartitionCount)+' Partitionen');
         for p := 0 to Layout.PartitionCount-1 do
        begin
// if (Layout.partitionInfoEx[p].StartingOffset.QuadPart<>0) and (Layout.partitionInfoEx[p].PartitionLength.QuadPart<>0) then
// begin
            mmo1.Lines.Add(' '+inttostr(p+1)+'. Partition: ');
            case Layout.partitionInfoEx[p].PartitionStyle of
              PARTITION_STYLE_MBR: mmo1.Lines.Add(' Part-Typ : MBR');
              PARTITION_STYLE_GPT: mmo1.Lines.Add(' Part-Typ : GPT');
              PARTITION_STYLE_RAW: mmo1.Lines.Add(' Part-Typ : RAW');
            end;
            if Layout.PartitionInfoEx[p].PartitionStyle=PARTITION_STYLE_MBR then
            begin
              case Layout.PartitionInfoEx[p].Mbr.PartitionType of
                PARTITION_ENTRY_UNUSED: mmo1.lines.Add(' Part-Style : PARTITION_ENTRY_UNUSED');
                PARTITION_EXTENDED: mmo1.lines.Add(' Part-Style : PARTITION_EXTENDED');
                PARTITION_FAT_12: mmo1.lines.Add(' Part-Style : PARTITION_FAT_12');
                PARTITION_FAT_16: mmo1.lines.Add(' Part-Style : PARTITION_FAT_16');
                PARTITION_FAT32: mmo1.lines.Add(' Part-Style : PARTITION_FAT32');
                PARTITION_IFS: mmo1.lines.Add(' Part-Style : PARTITION_IFS');
                PARTITION_LDM: mmo1.lines.Add(' Part-Style : PARTITION_LDM');
                PARTITION_NTFT: mmo1.lines.Add(' Part-Style : PARTITION_NTFT');
                VALID_NTFT: mmo1.lines.Add(' Part-Style : VALID_NTFT');
              else
                mmo1.lines.Add(' Part-Style : Unbekannt');
              end;
              if Layout.PartitionInfoEx[p].Mbr.PartitionType<>PARTITION_ENTRY_UNUSED then
                Inc(PartCount);
            end;
            mmo1.lines.Add(' PartitionNr: '+IntToStr(Layout.partitionInfoEx[p].PartitionNumber));
            mmo1.Lines.Add(' StartSektor: '+IntToStr(Layout.partitionInfoEx[p].StartingOffset.QuadPart));
            mmo1.lines.Add(' Länge : '+IntToStr(Layout.partitionInfoEx[p].PartitionLength.QuadPart));
            mmo1.Lines.Add(' Größe : '+GetSizeAsString(Layout.partitionInfoEx[p].PartitionLength.QuadPart));
// end;
          mmo2.Lines.Add(IntToStr(i+1)+'. Festplatte = '+inttostr(PartCount)+' Partitionen');
          if Layout.PartitionInfoEx[p].Mbr.PartitionType=PARTITION_IFS then
          begin
            mmo2.Lines.Add(#9+inttostr(p+1)+'.Partition:'+#9+GetSizeAsString(Layout.partitionInfoEx[p].PartitionLength.QuadPart));
          end;
        end;
      end;
      CloseHandle(hDevice);
    end;// else mmo1.lines.Add(IntToStr(i)+'. Festplatte hat kein hDeviceHandle');
  end;

end;

function TForm1.GetSizeAsString(Size: Int64): string;
var
  new: Extended;
  Sign: String;
  c: Integer;
begin
  c:=0;
  new:=Size;
  while new>1024 do
  begin
    new:=new/1024;
    Inc(c);
  end;
  case c of
    0: Sign:=' Byte';
    1: Sign:=' KB';
    2: Sign:=' MB';
    3: Sign:=' GB';
    4: Sign:=' TB';
    5: Sign:=' PB';
    6: Sign:=' EB';
    7: Sign:=' ZB';
    8: Sign:=' YB';
  else
    Sign:=' ('+intToStr(c)+')';
  end;
  Result:=FormatFloat('#,##0.00', new)+Sign;
end;

end.
Dieter
9 von 10 Stimmen in meinem Kopf sagen ich bin nicht verrückt. Die 10. summt dazu die Melodie von Supermario Bros.
MfG Captnemo
  Mit Zitat antworten Zitat