![]() |
Partition auslesen mit DeviceIoControl und IOCTL_DISK_GET_PARTITION_INFO_EX
Liste der Anhänge anzeigen (Anzahl: 1)
Ich will meine Partitionen auslesen, und deren Zugehörigkeit zu den Harddisks.
Hier mal die Deklaration (das ist die von ![]()
Delphi-Quellcode:
Und es scheint auch soweit zu funktionieren. Allerdings habe ich noch Probleme mit
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);
Delphi-Quellcode:
. Ich habe in diversen Posts gelesen, dass es
PartitionInfoEx: array[0..10] of _PARTITION_INFORMATION_EX
Delphi-Quellcode:
lauten soll. Aber dann erhalte ich gar keine Informationen.
PartitionInfoEx: array[0..0] of _PARTITION_INFORMATION_EX
Hier mal meine Procedure, mit der ich die Daten abfrage:
Delphi-Quellcode:
Ich wäre nach dem was ich gelesen habe mal davon ausgegangen, dass das Array partitionInfoEx hinterher der Partitionsanzahl entsprechende Elemente beinhaltet. Dem ist aber nicht so. Wenn ich es mit 0..0 deklariere, dann ist bleibt es eben auch leer, und wenn ich z.B. 0..10 deklariere, dann erhalte ich auch 11 Elemente, die dann aber eben zum Teil uninitialisierte Werte enthalten (ist klar).
procedure TForm1.btn2Click(Sender: TObject);
var RetBytes: DWORD; hDevice: Cardinal; Status: LongBool; Drive: string; Layout: DRIVE_LAYOUT_INFORMATION_EX; I,p: Integer; begin 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 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)+'. Festplatte abfrage fehlgeschalten') else begin mmo1.Lines.Add(IntToStr(i)+'. 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)+'. 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; 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; 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; Ich will ja hinterher in partitionInfoEx eben nur die Partitionen haben, die auf dem Datenträger auch existieren. Gut, nun gibt es ja auch noch PartitionCount aus DRIVE_LAYOUT_INFORMATION_EX. Diese liefert mir aber entweder 0, 1 oder 4. Meine Aufteilung sie in der Datenträgerverwaltung so aus: 1. HDD 1. Partition 350 MB System-reserved 2. Partition 931,17 GB c: 2. HDD 1. Partition 931,51 GB D: 3. HDD Keine Partition. Ist der CardReader ohne Karte 4. HDD 1. Partition 1000,00 GB I: (ist tatsächlich iSCSi von meinem NAS, deswegen genau 1000 GB); Wenn ich mein Testprogramm starte bekomme ich folgendes:
Code:
0. Festplatte = 4 Partitionen
0. Partition: Part-Typ : MBR PartitionNr: 1 StartSektor: 1048576 Länge : 367001600 Größe : 350,00 MB 2. Partition: PartitionNr: 0 StartSektor: 2 Länge : 3087428650860807 Größe : 2,74 PB 1. Festplatte = 4 Partitionen 0. Partition: Part-Typ : MBR PartitionNr: 1 StartSektor: 1048576 Länge : 1000202043392 Größe : 931,51 GB 1. Partition: PartitionNr: 3429319 StartSektor: 2421637 Länge : 4213862 Größe : 4,02 MB 3. Partition: PartitionNr: 3654587 StartSektor: 2787577 Länge : 2128090 Größe : 2,03 MB 2. Festplatte = 1 Partitionen 3. Festplatte = 4 Partitionen 0. Partition: Part-Typ : MBR PartitionNr: 1 StartSektor: 1048576 Länge : 1073738678272 Größe : 1.000,00 GB Die Partitionen mit Länge 0 oder StartSector 0 ignoriere ich mal. Bei der letzten HDD und beim CardReader stimmt das ja auch soweit. Aber bei meiner Bootplatte wird die 2. Partition mit Startsektor 0 oder Länge 0 ausgelese und eine 2. Partition mit einer wünschenswerten Größe angezeigt. Und bei der 2. Platte, wird zwar die 1. Partition richtig ausgelesen, aber aufgrund des PartitiionCount, mütte ich von 4 Partitionen ausgehen. Was mache ich noch falsch, bzw. wie kann man das besser lösen. Warum bekomme ich teilweise PartitionCount von 4? Ich hab mal das Testprojekt angehängt. |
AW: Partition auslesen mit DeviceIoControl und IOCTL_DISK_GET_PARTITION_INFO_EX
Ich glaube
![]() Zitat:
Delphi-Quellcode:
castest.
DRIVE_LAYOUT_INFORMATION_EX
Delphi-Quellcode:
ist quasi der Hinweis an den Compiler, das hinter dem Record/Header noch ein Array mit diesem Typ hängt. Um den Speicher dafür musst du dich selbst kümmern.
PartitionInfoEx: array[0..0] of _PARTITION_INFORMATION_EX
|
AW: Partition auslesen mit DeviceIoControl und IOCTL_DISK_GET_PARTITION_INFO_EX
Bin je wieder einen Schritt weiter.
PartitionCount liefert bei MBR-Partitionen immer ein vielfaches von 4 zurück. Das erklärt schon mal, warum also immer 4 dort steht. Also muss man anders an die Information, welche Partitionen denn nun wirklich exstieren. Dabei hilft DRIVE_LAYOUT_INFORMATION_EX.PartitionInfoEx[p].Mbr.PartitionType, worin im Falle von MBR diese Information gefunden werden kann.
Delphi-Quellcode:
das Ergebnis schaut jetzt so aus:
Const
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; . . . 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; end;
Code:
Bis auf die Tatsache, dass mir bei meiner 1. Platte die 2. Partition als UNUSED angezeigt wird, was definitiv nicht so ist, kann ich damit schon mal arbeiten. Da die anderen Platten nur eine Partition haben, muss ich mir erst mal noch eine weitere einbauen, um mal zu testen, was bei mehreren Partitionen so passiert.
1. Festplatte = 4 Partitionen
1. Partition: Part-Typ : MBR Part-Style : PARTITION_IFS PartitionNr: 1 StartSektor: 1048576 Länge : 367001600 Größe : 350,00 MB 2. Partition: Part-Typ : MBR Part-Style : PARTITION_ENTRY_UNUSED PartitionNr: 0 StartSektor: 0 Länge : 0 Größe : 0,00 Byte 3. Partition: PartitionNr: 0 StartSektor: 2 Länge : 3087428650860807 Größe : 2,74 PB 4. Partition: Part-Typ : MBR Part-Style : PARTITION_ENTRY_UNUSED PartitionNr: 0 StartSektor: 0 Länge : 0 Größe : 0,00 Byte 2. Festplatte = 4 Partitionen 1. Partition: Part-Typ : MBR Part-Style : PARTITION_IFS PartitionNr: 1 StartSektor: 1048576 Länge : 1000202043392 Größe : 931,51 GB 2. Partition: PartitionNr: 3429319 StartSektor: 2421637 Länge : 4213862 Größe : 4,02 MB 3. Partition: Part-Typ : MBR Part-Style : Unbekannt PartitionNr: 1781809 StartSektor: 0 Länge : 0 Größe : 0,00 Byte 4. Partition: PartitionNr: 3654587 StartSektor: 2787577 Länge : 2128090 Größe : 2,03 MB 3. Festplatte = 1 Partitionen 1. Partition: Part-Typ : MBR Part-Style : PARTITION_ENTRY_UNUSED PartitionNr: 0 StartSektor: 0 Länge : 0 Größe : 0,00 Byte 4. Festplatte = 4 Partitionen 1. Partition: Part-Typ : MBR Part-Style : PARTITION_IFS PartitionNr: 1 StartSektor: 1048576 Länge : 1073738678272 Größe : 1.000,00 GB 2. Partition: PartitionNr: 8 StartSektor: 0 Länge : -6047066961440 Größe : -6.047.066.961.440,00 Byte 3. Partition: Part-Typ : MBR Part-Style : PARTITION_ENTRY_UNUSED PartitionNr: 1 StartSektor: 0 Länge : 0 Größe : 0,00 Byte 4. Partition: Part-Typ : MBR Part-Style : PARTITION_ENTRY_UNUSED PartitionNr: 0 StartSektor: 0 Länge : 0 Größe : 0,00 Byte |
AW: Partition auslesen mit DeviceIoControl und IOCTL_DISK_GET_PARTITION_INFO_EX
Zitat:
|
AW: Partition auslesen mit DeviceIoControl und IOCTL_DISK_GET_PARTITION_INFO_EX
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.dll' name 'FindFirstVolumeW'; function FindNextVolume(hFindVolume: THandle; lpszVolumeName: LPTSTR; cchBufferLength: DWORD): BOOL; stdcall; external 'kernel32.dll' name 'FindNextVolumeW'; function FindVolumeClose(hFindVolume: THandle): BOOL; stdcall; external 'kernel32.dll' name 'FindVolumeClose'; function GetVolumePathNames(lpszVolumeName: LPCTSTR; lpszVolumePathName: LPTSTR; cchBufferLength: DWORD; lpcchReturnLength: PDWORD): BOOL; stdcall; external 'kernel32.dll' name '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. |
AW: Partition auslesen mit DeviceIoControl und IOCTL_DISK_GET_PARTITION_INFO_EX
Gibt es denn keinen hier, der das schon mal gemacht hat? Vielleicht muss ich in DRIVE_LAYOUT_INFORMATION_EX das Array anders initialisieren?
|
AW: Partition auslesen mit DeviceIoControl und IOCTL_DISK_GET_PARTITION_INFO_EX
Zitat:
Liest Du denn die Adresse der FolgePartition richtig aus? (so auf die schnelle hab' ich da nichts gefunden) Gruß K-H |
AW: Partition auslesen mit DeviceIoControl und IOCTL_DISK_GET_PARTITION_INFO_EX
Naja, die ich lese ja nicht die Partitionen direkt.
Rufe die Funktion DeviceIoControl auf und übergebe diese den CommandString IOCTL_DISK_GET_DRIVE_LAYOUT_EX. Die Funktion soll dann alle im Record DRIVE_LAYOUT_INFORMATION_EX deklarierten Daten auslesen und im Array PartitionInfoEx eben alle PartitonInformationen ablegen, also ParitionStyle, StartOffset, Länge usw. Dieses Array muss mindestens so groß sein, wie die Funktion Partitionen darin speichern will. Heißt, will sie 1 Partition speichern würde ein Array[0..0] reichen. Will sie 2 Speichern, dann muss es mindestens ein Array[0..1] sein. Größer darf das Array aber wohl immer sein. Wenn ich im Interface
Delphi-Quellcode:
angebe, wie ich es schon auf einigen Seiten gelesen habe, dann bekomme ich von DeviceIoControl ein False zurück.
PartitionInfoEx: array[0..0] of _PARTITION_INFORMATION_EX;
Mit
Delphi-Quellcode:
bekomme ich zumindest mal mehr zurück.
PartitionInfoEx: array[0..15] of _PARTITION_INFORMATION_EX;
Aber es kommen nur für die 1. Partition die richtigen Daten. Die Inhalte von den dahinterliegenden Array-Elementen sind eher willkürlich. Da aber die Funktion DeviceIoControl True zurückmeldet, gehe ich mal davon aus, dass sie grundsätzlich mit dem zur Verfügung stehenden Speicher zufrieden ist. Vielleicht habe ich ja auch den Record falsch deklariert (Mit den Übersetzungen aus C in Delphi habe ich gar keine Erfahrung). Oder vielleicht berechne ich bei GetMem den Speicher falsch. Da MS da ganz sicher keine Fehler macht, muss er ja bei mir liegen. Aber ich habe so gar keine Idee mehr (mangels Erfahrung), woran das liegen kann. |
AW: Partition auslesen mit DeviceIoControl und IOCTL_DISK_GET_PARTITION_INFO_EX
Deine Structs waren an einigen Stellen falsch, deshalb hast du bei den späteren Einträgen an den falschen Offsets gelesen. So funktioniert es:
Delphi-Quellcode:
type
PARTITION_INFORMATION_MBR = record PartitionType: Byte; BootIndicator: Boolean; RecognizedPartition: Boolean; HiddenSectors: DWord; end; PARTITION_INFORMATION_GPT = record PartitionType: TGUID; PartitionId: TGUID; Attributes: DWORD64; Name: array[0..35] of WCHAR; end; PARTITION_STYLE = type DWord; PARTITION_INFORMATION_EX = record PartitionStyle: PARTITION_STYLE; StartingOffset: LARGE_INTEGER; PartitionLength: LARGE_INTEGER; PartitionNumber: DWord; RewritePartition: Boolean; case Integer of 0: (Mbr: PARTITION_INFORMATION_MBR); 1: (Gpt: PARTITION_INFORMATION_GPT); end; TPartitionInformationEx = PARTITION_INFORMATION_EX; PPartitionInformationEx = ^TPartitionInformationEx; DRIVE_LAYOUT_INFORMATION_MBR = record Signature: DWord; end; DRIVE_LAYOUT_INFORMATION_GPT = record DiskId: TGUID; StartingUsableOffset: LARGE_INTEGER; UsableLength: LARGE_INTEGER; MaxPartitionCount: DWord; end; DRIVE_LAYOUT_INFORMATION_UNION = record case Integer of 0: (Mbr: DRIVE_LAYOUT_INFORMATION_MBR); 1: (Gpt: DRIVE_LAYOUT_INFORMATION_GPT); end; DRIVE_LAYOUT_INFORMATION_EX = record PartitionStyle: DWord; PartitionCount: DWord; DriveLayoutInformation: DRIVE_LAYOUT_INFORMATION_UNION; PartitionEntry: array[0..0] of PARTITION_INFORMATION_EX; end; TDriveLayoutInformationEx = DRIVE_LAYOUT_INFORMATION_EX; PDriveLayoutInformationEx = ^TDriveLayoutInformationEx; procedure PrintVolumeInformation(PhysicalDriveId: Integer); var hDevice: THandle; LayoutInfo: PDriveLayoutInformationEx; LayoutInfoSize, BytesReturned: DWord; I: Integer; begin hDevice := CreateFile(PChar('\\.\PhysicalDrive' + IntToStr(PhysicalDriveId)), 0, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0); if (hDevice = INVALID_HANDLE_VALUE) then RaiseLastOSError; try LayoutInfoSize := SizeOf(TDriveLayoutInformationEx) + SizeOf(TPartitionInformationEx) * 3; GetMem(LayoutInfo, LayoutInfoSize); try while (not DeviceIoControl(hDevice, IOCTL_DISK_GET_DRIVE_LAYOUT_EX, nil, 0, LayoutInfo, LayoutInfoSize, BytesReturned, nil)) do begin if (GetLastError <> ERROR_INSUFFICIENT_BUFFER) then RaiseLastOSError; LayoutInfoSize := LayoutInfoSize + SizeOf(TPartitionInformationEx) * 4; ReallocMem(LayoutInfo, LayoutInfoSize); end; for I := 0 to LayoutInfo^.PartitionCount - 1 do begin WriteLn(LayoutInfo^.PartitionEntry[I].PartitionNumber); // .. end; finally FreeMem(LayoutInfo); end; finally CloseHandle(hDevice); end; end; |
AW: Partition auslesen mit DeviceIoControl und IOCTL_DISK_GET_PARTITION_INFO_EX
Delphi-Quellcode:
müsste das nicht so sein:
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
Delphi-Quellcode:
begin
for h := 1 to 9 do begin Device:='\\.\Harddisk'+IntToStr(h); // ohne die 1 hdevice:=CreateFile(PChar(Device), 0, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0); if hDevice <> INVALID_HANDLE_VALUE then begin |
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:48 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz