|
Registriert seit: 15. Nov 2003 Ort: Berlin 948 Beiträge Delphi 10.2 Tokyo Professional |
#1
Hallo,
hier ein kleines Beispiel für die Verwendung von IOCTL_STORAGE_GET_DEVICE_NUMBER, IOCTL_DISK_GET_DRIVE_GEOMETRY und IOCTL_DISK_GET_DRIVE_LAYOUT. Damit es läuft braucht man die jwaWinIOCTL bzw. die entsprechenden Deklaration(en). Kernstück ist die Unit uDevice:
Delphi-Quellcode:
Und das Formular:
unit uDevice;
interface uses Classes, Windows, jwaWindows; type TDeviceRec = record DeviceNr : DWORD; DeviceStr : String; DriveStr : String; PartitionStr : String; PartitionNr : DWORD; DeviceTyp : DEVICE_TYPE; DiskGeometry : DISK_GEOMETRY; PartitionData : PARTITION_INFORMATION; end; TDynDeviceRec = record DeviceNr : DWORD; DeviceStr : String; DiskGeometry : DISK_GEOMETRY; PartitionData : Array of PARTITION_INFORMATION; MediaTypeStr : String; end; TDeviceRecList = Array of TDeviceRec; TDynDeviceRecList = Array of TDynDeviceRec; function GetAllLogicalDevices(var aDeviceRecList : TDeviceRecList) : Boolean; function GetAllPhysicalDevices(var aDynDeviceRecList : TDynDeviceRecList) : Boolean; implementation uses SysUtils; function MediaTypeToStr(aMediaType : MEDIA_TYPE) : String; begin case aMediatype of Unknown : Result := 'UNKNOWN'; F5_1Pt2_512 : Result := '5.25" floppy, with 1.2MB and 512 bytes/sector'; F3_1Pt44_512 : Result := '3.5" floppy, with 1.44MB and 512 bytes/sector'; F3_2Pt88_512 : Result := '3.5" floppy, with 2.88MB and 512 bytes/sector'; F3_20Pt8_512 : Result := '3.5" floppy, with 20MB and 512 bytes/sector'; F3_720_512 : Result := '3.5" floppy, with 720KB and 512 bytes/sector'; F5_360_512 : Result := '5.25" floppy, with 360KB and 512 bytes/sector'; F5_320_512 : Result := '5.25" floppy, with 320KB and 512 bytes/sector'; F5_320_1024 : Result := '5.25" floppy, with 360KB and 1024 bytes/sector'; F5_180_512 : Result := '5.25" floppy, with 180KB and 512 bytes/sector'; F5_160_512 : Result := '5.25" floppy, with 160KB and 512 bytes/sector'; RemovableMedia : Result := 'Removable media other than floppy'; FixedMedia : Result := 'Fixed hard disk media'; F3_120M_512 : Result := '3.5" floppy, with 120MB and 512 bytes/sector'; F3_640_512 : Result := '3.5" floppy, with 640MB and 512 bytes/sector'; F5_640_512 : Result := '5.25" floppy, with 640KB and 512 bytes/sector'; F5_720_512 : Result := '5.25" floppy, with 720KB and 512 bytes/sector'; F3_1Pt2_512 : Result := '3.5" floppy, with 1.2MB and 512 bytes/sector'; F3_1Pt23_1024 : Result := '3.5" floppy, with 1.23MB and 1024 bytes/sector'; F5_1Pt23_1024 : Result := '5.25" floppy, with 1.23KB and 1024 bytes/sector'; F3_128Mb_512 : Result := '3.5" floppy, with 128MB and 512 bytes/sector'; F3_230Mb_512 : Result := '3.5" floppy, with 230MB and 512 bytes/sector'; F8_256_128 : Result := '8" floppy, with 256KB and 128 bytes/sector'; F3_200Mb_512 : Result := '3.5" floppy, with 200MB and 512 bytes/sector. (HiFD)'; F3_240M_512 : Result := '3.5" floppy, with 240MB and 512 bytes/sector. (HiFD)'; F3_32M_512 : Result := '3.5" floppy, with 32MB and 512 bytes/sector'; end; end; function DeviceTypeToStr(aDeviceType : DEVICE_TYPE):String; begin case aDeviceType of FILE_DEVICE_BEEP : Result :='BEEP'; FILE_DEVICE_CD_ROM : Result :='CD-ROM'; FILE_DEVICE_CD_ROM_FILE_SYSTEM : Result :='CD-ROM FILE-SYSTEM'; FILE_DEVICE_CONTROLLER : Result :='CONTROLLER'; FILE_DEVICE_DATALINK : Result :='DATALINK'; FILE_DEVICE_DFS : Result :='DFS'; FILE_DEVICE_DISK : Result :='DISK'; FILE_DEVICE_DISK_FILE_SYSTEM : Result :='DISK FILE-SYSTEM'; FILE_DEVICE_FILE_SYSTEM : Result :='FILE-SYSTEM'; FILE_DEVICE_INPORT_PORT : Result :='INPORT-PORT'; FILE_DEVICE_KEYBOARD : Result :='KEYBOARD'; FILE_DEVICE_MAILSLOT : Result :='MAILSLOT'; FILE_DEVICE_MIDI_IN : Result :='MIDI_IN'; FILE_DEVICE_MIDI_OUT : Result :='MIDI_OUT'; FILE_DEVICE_MOUSE : Result :='MOUSE'; FILE_DEVICE_MULTI_UNC_PROVIDER : Result :='MULTI UNC-PROVIDER'; FILE_DEVICE_NAMED_PIPE : Result :='NAMED-PIPE'; FILE_DEVICE_NETWORK : Result :='NETWORK'; FILE_DEVICE_NETWORK_BROWSER : Result :='NETWORK-BROWSER'; FILE_DEVICE_NETWORK_FILE_SYSTEM : Result :='NETWORK FILE-SYSTEM'; FILE_DEVICE_NULL : Result :='NULL'; FILE_DEVICE_PARALLEL_PORT : Result :='PARALLEL-PORT'; FILE_DEVICE_PHYSICAL_NETCARD : Result :='PHYSICAL-NETCARD'; FILE_DEVICE_PRINTER : Result :='PRINTER'; FILE_DEVICE_SCANNER : Result :='SCANNER'; FILE_DEVICE_SERIAL_MOUSE_PORT : Result :='SERIAL MOUSE-PORT'; FILE_DEVICE_SERIAL_PORT : Result :='SERIAL-PORT'; FILE_DEVICE_SCREEN : Result :='SCREEN'; FILE_DEVICE_SOUND : Result :='SOUND'; FILE_DEVICE_STREAMS : Result :='STREAMS'; FILE_DEVICE_TAPE : Result :='TAPE'; FILE_DEVICE_TAPE_FILE_SYSTEM : Result :='TAPE FILE-SYSTEM'; FILE_DEVICE_TRANSPORT : Result :='TRANSPORT'; FILE_DEVICE_UNKNOWN : Result :='UNKNOWN'; FILE_DEVICE_VIDEO : Result :='VIDEO'; FILE_DEVICE_VIRTUAL_DISK : Result :='VIRTUAL-DISK'; FILE_DEVICE_WAVE_IN : Result :='WAVE_IN'; FILE_DEVICE_WAVE_OUT : Result :='WAVE_OUT'; FILE_DEVICE_8042_PORT : Result :='8042-PORT'; FILE_DEVICE_NETWORK_REDIRECTOR : Result :='NETWORK-REDIRECTOR'; FILE_DEVICE_BATTERY : Result :='BATTERY'; FILE_DEVICE_BUS_EXTENDER : Result :='BZS EXTENDER'; FILE_DEVICE_MODEM : Result :='MODEM'; FILE_DEVICE_VDM : Result :='VDM'; FILE_DEVICE_MASS_STORAGE : Result :='MASS-STORAGE'; FILE_DEVICE_SMB : Result :='SMB'; FILE_DEVICE_KS : Result :='KS'; FILE_DEVICE_CHANGER : Result :='CHANGER'; FILE_DEVICE_SMARTCARD : Result :='SMARTCARD'; FILE_DEVICE_ACPI : Result :='ACPI'; FILE_DEVICE_DVD : Result :='DVD'; FILE_DEVICE_FULLSCREEN_VIDEO : Result :='FULLSCREEN VIDEO'; FILE_DEVICE_DFS_FILE_SYSTEM : Result :='DFS FILE-SYSTEM'; FILE_DEVICE_DFS_VOLUME : Result :='DFS-VOLUME'; FILE_DEVICE_SERENUM : Result :='SERENUM'; FILE_DEVICE_TERMSRV : Result :='TERMINAL-SERVER'; FILE_DEVICE_KSEC : Result :='KSEC'; FILE_DEVICE_FIPS : Result :='FIPS'; FILE_DEVICE_INFINIBAND : Result :='INFINIBAND'; else Result := IntToStr(aDeviceType); end; end; function DeviceExists(aDeviceNumber : DWORD) : Boolean; var hVolume : THandle; begin hVolume := CreateFile(PChar(Format('\\.\PHYSICALDRIVE%d', [aDeviceNumber])), GENERIC_READ, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0); CloseHandle(hVolume); Result := hVolume <> INVALID_HANDLE_VALUE; end; function GetDeviceNumber(const aDriveLetter : PChar; var aDeviceRec : TDeviceRec) : Boolean; overload; var pVolume : PChar; dwSize : DWORD; hVolume : THandle; SDN : STORAGE_DEVICE_NUMBER; DG : DISK_GEOMETRY; pDLI : PDRIVE_LAYOUT_INFORMATION; lpBytesReturned : DWORD; Ret, dliSize : Integer; begin Ret := -1; dwSize := 6; pVolume := StrAlloc(dwSize); try StrPCopy(pVolume, Format('\\.\%s:', [Copy(aDriveLetter, 1, 1)])); hVolume := CreateFile(pVolume, GENERIC_READ, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0); if hVolume <> INVALID_HANDLE_VALUE then begin if DeviceIOControl(hVolume, IOCTL_STORAGE_GET_DEVICE_NUMBER, nil, 0, @SDN, SizeOf(SDN), @lpBytesReturned, nil) then begin Ret := SDN.DeviceNumber; with aDeviceRec do begin DeviceNr := Ret; PartitionNr := SDN.PartitionNumber; DeviceTyp := SDN.DeviceType; DriveStr := Format('%s:\', [aDriveLetter]); case SDN.DeviceType of FILE_DEVICE_DISK : DeviceStr := Format('\\.\PHYSICALDRIVE%d', [DeviceNr]); else DeviceStr := Format('DEVICE: %s ', [DeviceTypeToStr(DeviceTyp)]); end; PartitionStr := Format('Partition%d', [PartitionNr]); end; end; if DeviceIOControl(hVolume, IOCTL_DISK_GET_DRIVE_GEOMETRY, nil, 0, @DG, SizeOf(DG), @lpBytesReturned, nil) then aDeviceRec.DiskGeometry := DG; // Für den folgenden Aufruf müssen wir ausreichend Speicher reserviren // Falls ich ein Fragt warum 16 Partitionen, sollte sich gesondert informieren;-) dliSize := SizeOf(DRIVE_LAYOUT_INFORMATION) + (15 * SizeOf(PARTITION_INFORMATION)); // Wir nutzen GetMem da DRIVE_LAYOUT_INFORMATION.PartitionCount ein // statisches Array ist GetMem(pDLI, dliSize); if DeviceIOControl(hVolume, IOCTL_DISK_GET_DRIVE_LAYOUT, nil, 0, pDLI, dliSize, @lpBytesReturned, nil) then begin // Hier verkürzen wir das ganze, da wir ja wissen welche Partition // wir auslesen wollen aDeviceRec.PartitionData := pDLI^.PartitionEntry[aDeviceRec.PartitionNr-1]; // Und geben den Speicher wieder frei FreeMem(pDLI, dliSize); end; CloseHandle(hVolume); end; finally StrDispose(pVolume); end; Result := Ret > -1; end; function GetDeviceNumber(const aPhysicalDrive : Byte; var aDynDeviceRec : TDynDeviceRec) : Boolean; overload; var pVolume : PChar; dwSize : DWORD; hVolume : THandle; DG : DISK_GEOMETRY; pDLI : PDRIVE_LAYOUT_INFORMATION; lpBytesReturned : DWORD; I, piCount, dliSize : Integer; begin Result := false; dwSize := Length(Format('\\.\PHYSICALDRIVE%d', [aPhysicalDrive])) + 1; pVolume := StrAlloc(dwSize); try StrPCopy(pVolume, Format('\\.\PHYSICALDRIVE%d', [aPhysicalDrive])); hVolume := CreateFile(pVolume, GENERIC_READ, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0); if hVolume <> INVALID_HANDLE_VALUE then begin aDynDeviceRec.DeviceNr := aPhysicalDrive; aDynDeviceRec.DeviceStr:= pVolume; if DeviceIOControl(hVolume, IOCTL_DISK_GET_DRIVE_GEOMETRY, nil, 0, @DG, SizeOf(DG), @lpBytesReturned, nil) then begin aDynDeviceRec.DiskGeometry := DG; aDynDeviceRec.MediaTypeStr := MediaTypeToStr(DG.MediaType); end; // Für den folgenden Aufruf müssen wir ausreichend Speicher reserviren // Falls sich ein Fragt warum 16 Partitionen, sollte er sich // gesondert informieren;-) dliSize := SizeOf(DRIVE_LAYOUT_INFORMATION) + (15 * SizeOf(PARTITION_INFORMATION)); // Wir nutzen GetMem da DRIVE_LAYOUT_INFORMATION.PartitionCount ein // statisches Array ist GetMem(pDLI, dliSize); if DeviceIOControl(hVolume, IOCTL_DISK_GET_DRIVE_LAYOUT, nil, 0, pDLI, dliSize, @lpBytesReturned, nil) then begin // IOCTL_DISK_GET_DRIVE_LAYOUT bringt in // DRIVE_LAYOUT_INFORMATION.PartitionCount immer 4 zurück // egal ob 1, 2 oder mehr Primärepartitionen vorhanden sind. piCount := 0; for I := 0 to pDLI^.PartitionCount - 1 do begin if pDLI^.PartitionEntry[I].StartingOffset.LowPart = 0 then Break; Inc(piCount); end; SetLength(aDynDeviceRec.PartitionData, piCount); for I := 0 to piCount-1 do aDynDeviceRec.PartitionData[I] := pDLI^.PartitionEntry[I]; // Speicher wieder freigeben FreeMem(pDLI, dliSize); end; CloseHandle(hVolume); Result := true; end; finally StrDispose(pVolume); end; end; function GetAllLogicalDevices(var aDeviceRecList : TDeviceRecList) : Boolean; var drives : DWORD; letter : Char; SL : TStringList; begin SL := TStringList.Create; try for letter := 'C' to 'Z' do case GetDriveType(PChar(letter + ':\')) of DRIVE_REMOVABLE : SL.Add(letter); DRIVE_FIXED : SL.Add(Letter); end; Result := SL.Count > 0; if Result then begin SetLength(aDeviceRecList, SL.Count); for drives := 0 to SL.Count - 1 do GetDeviceNumber(PChar(SL.Strings[drives]), aDeviceRecList[drives]); end; finally SL.Free; end; end; function GetAllPhysicalDevices(var aDynDeviceRecList : TDynDeviceRecList) : Boolean; var I : Byte; J : Byte; C : Byte; DR : TDynDeviceRec; begin C := 0; SetLength(aDynDeviceRecList, HIGH(Byte)); for I := 0 to HIGH(BYTE) do begin if DeviceExists(I) then begin if GetDeviceNumber(I, DR) then begin try with aDynDeviceRecList[C] do begin DeviceNr := DR.DeviceNr; DeviceStr := DR.DeviceStr; DiskGeometry := DR.DiskGeometry; MediaTypeStr := DR.MediaTypeStr; SetLength(PartitionData, Length(DR.PartitionData)); for J := 0 to Length(DR.PartitionData) - 1 do PartitionData[J] := DR.PartitionData[J]; end; Inc(C); except end; end; end; end; SetLength(aDynDeviceRecList, C); Result := Length(aDynDeviceRecList) > 0; end; end.
Delphi-Quellcode:
Siehe auch Anhang. Ich gebe ja zu ein wenig Optimierung könnte das ganze vertragen
unit frmMain;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ActnList, Menus, ComCtrls, uDevice; type TMainForm = class(TForm) ActionList1: TActionList; MainMenu1: TMainMenu; mnuFile: TMenuItem; mnuDevice: TMenuItem; _aDummy: TAction; aFileExit: TAction; aDeviceLogical: TAction; aDevicePhysical: TAction; mnuFileExit: TMenuItem; mnuDeviceLogical: TMenuItem; N1: TMenuItem; mnuDevicePhysical: TMenuItem; tvDevices: TTreeView; procedure aFileExitExecute(Sender: TObject); procedure aDeviceLogicalExecute(Sender: TObject); procedure aDevicePhysicalExecute(Sender: TObject); private { Private-Deklarationen } DRL : TDeviceRecList; DDRL: TDynDeviceRecList; function FindRootNode(aName : String; aTreeView : TTreeView) : TTreeNode; procedure ClearList; public { Public-Deklarationen } end; var MainForm: TMainForm; implementation {$R *.dfm} procedure TMainForm.aDeviceLogicalExecute(Sender: TObject); var I : Integer; R : TTreeNode; begin tvDevices.Items.BeginUpdate; tvDevices.Items.Clear; ClearList; if GetAllLogicalDevices(DRL) then begin for I := 0 to Length(DRL) -1 do begin R := FindRootNode(DRL[I].DeviceStr, tvDevices); if R <> nil then tvDevices.Items.AddChild(R, Format('%s (%s)', [DRL[I].PartitionStr, DRL[I].DriveStr])) else begin R := tvDevices.Items.AddChild(nil, DRL[I].DeviceStr); tvDevices.Items.AddChild(R, Format('%s (%s)', [DRL[I].PartitionStr, DRL[I].DriveStr])); end; end; tvDevices.Items.AlphaSort(); end; tvDevices.Items.EndUpdate; end; procedure TMainForm.aDevicePhysicalExecute(Sender: TObject); var I, J : Integer; N, R : TTreeNode; begin tvDevices.Items.BeginUpdate; tvDevices.Items.Clear; ClearList; if GetAllPhysicalDevices(DDRL) then begin for I := 0 to Length(DDRL) -1 do begin R := FindRootNode(DDRL[I].DeviceStr, tvDevices); if R <> nil then tvDevices.Items.AddChild(R, Format('%s ', [DDRL[I].MediaTypeStr])) else begin R := tvDevices.Items.AddChild(nil, DDRL[I].DeviceStr); N := tvDevices.Items.AddChild(R, Format('%s ', [DDRL[I].MediaTypeStr])); for J := 0 to Length(DDRL[I].PartitionData) -1 do tvDevices.Items.AddChild(N, Format('Partition%d', [J])); end; end; tvDevices.Items.AlphaSort(); end; tvDevices.Items.EndUpdate; end; procedure TMainForm.aFileExitExecute(Sender: TObject); begin ClearList; Close; end; function TMainForm.FindRootNode(aName : String; aTreeView : TTreeView) : TTreeNode; var I : Integer; begin Result := nil; aTreeView.Items.BeginUpdate; for I := 0 to aTreeView.Items.Count - 1 do if aTreeView.Items[I].Text = aName then begin Result := aTreeView.Items[I]; Break; end; aTreeView.Items.EndUpdate; end; procedure TMainForm.ClearList; var I : Integer; begin if Length(DDRL) > 0 then begin for I := Length(DDRL) -1 downto 0 do if Length(DDRL[I].PartitionData) > 0 then SetLength(DDRL[I].PartitionData, 0); SetLength(DDRL, 0); end; if Length(DRL) > 0 then SetLength(DRL, 0); end; end. ![]() Falls es Fragen gibt, fragen. Viele Grüße Geändert von Alter Mann ( 8. Sep 2010 um 10:20 Uhr) |
![]() |
Ansicht |
![]() |
![]() |
![]() |
ForumregelnEs ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.
BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus. Trackbacks are an
Pingbacks are an
Refbacks are aus
|
|
Nützliche Links |
Heutige Beiträge |
Sitemap |
Suchen |
Code-Library |
Wer ist online |
Alle Foren als gelesen markieren |
Gehe zu... |
LinkBack |
![]() |
![]() |