Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Direktes lesen auf dem physischen Datenträger (https://www.delphipraxis.net/196698-direktes-lesen-auf-dem-physischen-datentraeger.html)

Delphi-Delphin 10. Jun 2018 17:06


Direktes lesen auf dem physischen Datenträger
 
Wie kann man direkt auf dem physischen Datenträger lesen? Ich würde gerne auf den MBR/GPT und die Bootblöcke der einzelnen Partitionen zugreifen.

Verwendet wird Lazarus.

KodeZwerg 10. Jun 2018 17:26

AW: Direktes lesen auf dem physischen Datenträger
 
MSDN-Library durchsuchenCreateFile mit "\\.\PhysicalDrive0" (Admin Rechte!)
Das öffnet Festplatte 0 bei Dir (also die erste)

Delphi-Delphin 11. Jun 2018 16:41

AW: Direktes lesen auf dem physischen Datenträger
 
Danke.

Gibt es denn eine Funktion, die mir die erkannten physischen Datenträger auflisten kann?

KodeZwerg 11. Jun 2018 17:14

AW: Direktes lesen auf dem physischen Datenträger
 
Hmmm.... das erste war noch einfach für mich zu beantworten da es Winapi war.
Hier mische ich Delphi mit Winapi, keine Ahnung in wie fern das kompatibel zu Lazarus ist.
Folgender Code ermittelt alle Laufwerke mit Ihren Namen, da findest Du schon die passende Stelle wo Du Dich reinklinken kannst, wenn nicht, frage :-)
Delphi-Quellcode:
function GetVolumeLabel(DriveChar: Char): string;
var
  NotUsed:    DWORD;
  VolumeFlags: DWORD;
  VolumeInfo: array[0..MAX_PATH] of Char;
  VolumeSerialNumber: DWORD;
  Buf: array [0..MAX_PATH] of Char;
begin
    GetVolumeInformation(PChar(DriveChar + ':\'),
    Buf, SizeOf(VolumeInfo), @VolumeSerialNumber, NotUsed,
    VolumeFlags, nil, 0);
 
    SetString(Result, Buf, StrLen(Buf));  { Set return result }
    Result:=AnsiUpperCase(Result)
end;
 
procedure TForm1.Button1Click(Sender: TObject);
var
  Drive : Char;
  DriveLetter : String;
begin
  For Drive := 'A' To 'Z' Do
    begin
    DriveLetter := Drive + ':\';
    If GetDriveType(PChar(DriveLetter)) = DRIVE_FIXED Then
      begin
      Memo1.Lines.Add(Drive + ': ' + GetVolumeLabel(Drive));
    end;
  end;
end;
oder enumeriere die Laufwerke auf diese Winapi/Delphi Weise wie hier beschrieben.
Zitat:

The simplest way is actually to use GetDiskFreeSpaceEx from the sysutils.pas file.
There are 2 parts to this example. the 1st is the important part using GetDiskFreeSpaceEX.
Delphi-Quellcode:
function DriveSpace(DriveLetter : String; var FreeSpace, UsedSpace, TotalSpace : int64) : Boolean;
begin
  Result := SysUtils.GetDiskFreeSpaceEx(Pchar(DriveLetter), UsedSpace, TotalSpace, @FreeSpace);

  if UsedSpace > 0 then
    UsedSpace := TotalSpace - FreeSpace;

  if not Result then
  begin
    UsedSpace  := 0;
    TotalSpace := 0;
    FreeSpace  := 0;
  end;
end;
If you are going to request drives that you already know the drive letter for such as C: then that is all you need.
Usage would be something like:
Delphi-Quellcode:
var
  FS,
  US,
  TS : Int64
begin
  DriveSpace('C:', FS, US, TS);
  //Do something with the 3 variables.
end;
Having said that if you want to find the drives as well you could use something like this:
Delphi-Quellcode:
procedure ListDrivesOfType(DriveType : Integer; var Drives : TStringList);
var
  DriveMap,
  dMask : DWORD;
  dRoot : String;
  I    : Integer;
begin
  dRoot    := 'A:\'; //' // work around highlighting
  DriveMap := GetLogicalDrives;
  dMask    := 1;

  for I := 0 to 32 do
  begin
    if (dMask and DriveMap) <> 0 then
      if GetDriveType(PChar(dRoot)) = DriveType then
      begin
        Drives.Add(dRoot[1] + ':');
      end;

    dMask := dMask shl 1;
    Inc(dRoot[1]);
  end;
end;
Note the DriveType integer, should be one of the following:
Delphi-Quellcode:
DRIVE_UNKNOWN    = 0;
DRIVE_NO_ROOT_DIR = 1;
DRIVE_REMOVABLE  = 2;
DRIVE_FIXED      = 3;
DRIVE_REMOTE     = 4;
DRIVE_CDROM      = 5;
DRIVE_RAMDISK    = 6;
(I have taken these straight out of windows.pas)
Now finally to answer your question (and this is very rough) the following would add information into a memo (called memo1) for all FIXED HARD DRIVES:
Delphi-Quellcode:
Procedure TAform.SomeNameICantThinkOfNow;
const
  BytesPerMB = 1048576;
var
  MyDrives  : TStringlist;
  I : Integer;
  FreeSpace,
  UsedSpace,
  TotalSpace : int64;
begin
  MyDrives := TStringlist.Create;
  ListDrivesOfType(DRIVE_FIXED, MyDrives);

  Memo1.Lines.Clear;

  for I := 0 to MyDrives.Count - 1 do
  begin
    FreeSpace := 0;
    UsedSpace := 0;
    TotalSpace := 0;

    if DriveSpace(MyDrives.Strings[I], FreeSpace, UsedSpace, TotalSpace) then
    begin
      FreeSpace := FreeSpace div BytesPerMB;
      UsedSpace := UsedSpace div BytesPerMB;
      TotalSpace := TotalSpace div BytesPerMB;

      Memo1.Lines.Add('Drive: ' + MyDrives.Strings[I] + ' = Free Space :' + IntToStr(FreeSpace) +
                      ' Used Space: ' + IntToStr(UsedSpace) + ' Total Space: ' + IntToStr(TotalSpace));
    end;
  end;
end;
I did say it would be nasty! I have just run this up in the IDE and it works, I have done as MB but really you should convert to Double and choose your formatting if doing as MB to be more precise as the example I have create above will of course just round up.
Hope this is of some small assistance.

jus 12. Jun 2018 08:49

AW: Direktes lesen auf dem physischen Datenträger
 
Oder du machst die Abfrage über WMI. Oft bekommt man hier schneller mehr Infos, als sich mit irgendwelche APIs herumzuschlagen.

lg,
jus

KodeZwerg 12. Jun 2018 09:22

AW: Direktes lesen auf dem physischen Datenträger
 
Liste der Anhänge anzeigen (Anzahl: 1)
*entfernt*
und er schrieb
Zitat:

Zitat von Delphi-Delphin (Beitrag 1404559)
Gibt es denn eine Funktion, die mir die erkannten physischen Datenträger auflisten kann?

Was das WMI Beispiel voll und ganz abgedeckt hatte.

An TE, im Anhang ist ein Binary von dem WMI Beispiel, schau es Dir an, wenn es das ist was Du brauchst das findest Du als Source hier in DP.

Daniel 12. Jun 2018 09:24

AW: Direktes lesen auf dem physischen Datenträger
 
Er schreibt, dass er auf den MBR zugreifen möchte. Wie hilft ihm da dieses WMI-Beispiel?

KodeZwerg 12. Jun 2018 10:41

AW: Direktes lesen auf dem physischen Datenträger
 
Zitat:

Zitat von Daniel (Beitrag 1404605)
dass er auf den MBR zugreifen möchte

Delphi-Quellcode:
type
  TMBR = Array of Byte;

Function GetMBR (const DiskNumber: Byte; const MBRSize: Cardinal; out MBR: TMBR): Boolean;
var
  nBytesRead ,
  fHandle : Cardinal;
begin
  fHandle := CreateFile(
    PChar('\\.\PHYSICALDRIVE'+IntToStr(DiskNumber)),
    GENERIC_READ, FILE_SHARE_WRITE,
    nil,
    OPEN_EXISTING,
    0, 0);
  if fHandle = INVALID_HANDLE_VALUE then
  begin
    Result := False;
    ShowMessage('CreateFile - Fehler: Invalid Handle' +#13#10#13#10+
                'Hinweis: liegen Admin-Rechte vor?');
    exit;
  end;
  SetLength(MBR, MBRSize);
  Result := ReadFile(fHandle, MBR[0], MBRSize, nBytesRead, nil);
  if nBytesRead-1 <> High(MBR) then Result := False;
  if not Result then
  begin
    ShowMessage('ReadFile - Fehler' +#13#10#13#10+
                'Es sollten '+IntToStr(High(MBR))+ ' bytes gelesen werden' +#13#10+
                'aber nur '+ IntToStr(nBytesRead-1) +' bytes waren lesbar!');
  end;
  CloseHandle(fHandle);
end;
So könnte ein möglicher Aufruf aussehen:
Delphi-Quellcode:
procedure x;
var
  MyMBR: TMBR;
begin
  if GetMBR(0, 512, MyMBR) then // <<-- 512 als MBR Größe ist nicht immer korrekt, also vorher diesen Wert ermitteln, das dient nur als Beispiel
  begin
   // mach was mit MyMBR
  end;
end;
So könnte ein möglicher Ansatz für MBR sein.

KodeZwerg 12. Jun 2018 17:15

AW: Direktes lesen auf dem physischen Datenträger
 
Ich bin gerade den Code nochmal durchgegangen, es kann sehr gut möglich sein das ich
Delphi-Quellcode:
 if nBytesRead-1 <> High(MBR) then Result := False;
das falsch habe und es
Delphi-Quellcode:
 if nBytesRead <> High(MBR)+1 then Result := False;
lauten müsste, beim weiteren
Delphi-Quellcode:
nBytesRead
das
Delphi-Quellcode:
-1
dann weglassen aber beim
Delphi-Quellcode:
High(MBR)
ein
Delphi-Quellcode:
+1
ranbaumeln.

Delphi-Delphin 18. Jun 2018 12:26

AW: Direktes lesen auf dem physischen Datenträger
 
Vielen Dank, für deine großartige Hilfe.

Deine Exe liefert sogar noch viel mehr Informationen, als ich brauche. ;)

Mit dem Code lässt sich also sehr gut was anfangen. Der verlinkte Code ließ sich auch fehlerfrei im Lazarus kompilieren.

Edit: Hab auch noch einen Fehler im Code gefunden.
Bei Writeln(Format('Size %d',[VarToInt(FWbemObject.Size)]));// Uint64 kommt es zu einem Überlauf, da die Funktion selbst nur einen 32 Bit Integer verwendet.

Angepasst:
Delphi-Quellcode:
//-----------------------------------------------------------------------------------------------------
// This code was generated by the Wmi Delphi Code Creator http://theroadtodelphi.wordpress.com
// Version: 1.8.3.0
// LIABILITY DISCLAIMER
// THIS GENERATED CODE IS DISTRIBUTED "AS IS". NO WARRANTY OF ANY KIND IS EXPRESSED OR IMPLIED.
// YOU USE IT AT YOUR OWN RISK. THE AUTHOR NOT WILL BE LIABLE FOR DATA LOSS,
// DAMAGES AND LOSS OF PROFITS OR ANY OTHER KIND OF LOSS WHILE USING OR MISUSING THIS CODE.
//----------------------------------------------------------------------------------------------------
program GetWMI_DiskDriveInfo;

{$APPTYPE CONSOLE}

uses
 // SysUtils, ActiveX, ComObj, Variants;
  SysUtils,
  ActiveX,
  ComObj,
  Variants;

function VarToInt(const AVariant: Variant): integer;
begin Result := StrToIntDef(Trim(VarToStr(AVariant)), 0); end;

function VarToQWord(const AVariant: Variant): QWord;
begin Result := StrToQWordDef(Trim(VarToStr(AVariant)), 0); end;

// Die Klasse "Win32_DiskDrive" stellt ein physikalisches Laufwerk eines Computer dar,
// auf dem das Win32-Betriebssystem ausgeführt wird. Jede Schnittstelle zu einem physikalischen
// Win32-Laufwerk ist ein Mitglied dieser Klasse. Die Funktionen des Laufwerks in diesem
// Objekt entsprechen den logischen Laufwerkmerkmalen. Ein Objekt, das auf einem anderen logischen Gerät basiert,
// ist kein Mitglied dieser Klasse.
// Beispiel: IDE-Festplatte.

procedure GetWin32_DiskDriveInfo;
const
  WbemUser ='';
  WbemPassword ='';
  WbemComputer ='localhost';
  wbemFlagForwardOnly = $00000020;
var
  FSWbemLocator : OLEVariant;
  FWMIService : OLEVariant;
  FWbemObjectSet: OLEVariant;
  FWbemObject : OLEVariant;
  oEnum : IEnumvariant;
  iValue : LongWord;
  i: integer;
begin
  FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
  FWMIService := FSWbemLocator.ConnectServer(WbemComputer, 'root\CIMV2', WbemUser, WbemPassword);
  FWbemObjectSet:= FWMIService.ExecQuery('SELECT * FROM Win32_DiskDrive','WQL',wbemFlagForwardOnly);
  oEnum := IUnknown(FWbemObjectSet._NewEnum) as IEnumVariant;
  i:=0;
  while oEnum.Next(1, FWbemObject, iValue) = 0 do
  begin
    Writeln(Format('*** DISK %d ***',[i]));
    Writeln(Format('Availability %d',[VarToInt(FWbemObject.Availability)]));// Uint16
    Writeln(Format('BytesPerSector %d',[VarToInt(FWbemObject.BytesPerSector)]));// Uint32
// Writeln(Format('Capabilities %d',[VarToInt(FWbemObject.Capabilities)]));// Array of Uint16
// Writeln(Format('CapabilityDescriptions %s',[VarToStr(FWbemObject.CapabilityDescriptions)]));// Array of VarToStr
    Writeln(Format('Caption %s',[VarToStr(FWbemObject.Caption)]));// VarToStr
    Writeln(Format('CompressionMethod %s',[VarToStr(FWbemObject.CompressionMethod)]));// String
    Writeln(Format('ConfigManagerErrorCode %d',[VarToInt(FWbemObject.ConfigManagerErrorCode)]));// Uint32
    Writeln(Format('ConfigManagerUserConfig %s',[VarToStr(FWbemObject.ConfigManagerUserConfig)]));// Boolean
    Writeln(Format('CreationClassName %s',[VarToStr(FWbemObject.CreationClassName)]));// String
    Writeln(Format('DefaultBlockSize %d',[VarToInt(FWbemObject.DefaultBlockSize)]));// Uint64
    Writeln(Format('Description %s',[VarToStr(FWbemObject.Description)]));// String
    Writeln(Format('DeviceID %s',[VarToStr(FWbemObject.DeviceID)]));// String
    Writeln(Format('ErrorCleared %s',[VarToStr(FWbemObject.ErrorCleared)]));// Boolean
    Writeln(Format('ErrorDescription %s',[VarToStr(FWbemObject.ErrorDescription)]));// String
    Writeln(Format('ErrorMethodology %s',[VarToStr(FWbemObject.ErrorMethodology)]));// String
    Writeln(Format('FirmwareRevision %s',[VarToStr(FWbemObject.FirmwareRevision)]));// String
    Writeln(Format('Index %d',[VarToInt(FWbemObject.Index)]));// Uint32
    Writeln(Format('InstallDate %s',[VarToStr(FWbemObject.InstallDate)]));// Datetime
    Writeln(Format('InterfaceType %s',[VarToStr(FWbemObject.InterfaceType)]));// String
    Writeln(Format('LastErrorCode %d',[VarToInt(FWbemObject.LastErrorCode)]));// Uint32
    Writeln(Format('Manufacturer %s',[VarToStr(FWbemObject.Manufacturer)]));// String
    Writeln(Format('MaxBlockSize %d',[VarToInt(FWbemObject.MaxBlockSize)]));// Uint64
    Writeln(Format('MaxMediaSize %d',[VarToInt(FWbemObject.MaxMediaSize)]));// Uint64
    Writeln(Format('MediaLoaded %s',[VarToStr(FWbemObject.MediaLoaded)]));// Boolean
    Writeln(Format('MediaType %s',[VarToStr(FWbemObject.MediaType)]));// String
    Writeln(Format('MinBlockSize %d',[VarToInt(FWbemObject.MinBlockSize)]));// Uint64
    Writeln(Format('Model %s',[VarToStr(FWbemObject.Model)]));// String
    Writeln(Format('Name %s',[VarToStr(FWbemObject.Name)]));// String
    Writeln(Format('NeedsCleaning %s',[VarToStr(FWbemObject.NeedsCleaning)]));// Boolean
    Writeln(Format('NumberOfMediaSupported %d',[VarToInt(FWbemObject.NumberOfMediaSupported)]));// Uint32
    Writeln(Format('Partitions %d',[VarToInt(FWbemObject.Partitions)]));// Uint32
    Writeln(Format('PNPDeviceID %s',[VarToStr(FWbemObject.PNPDeviceID)]));// String
    Writeln(Format('PowerManagementCapabilities %d',[VarToInt(FWbemObject.PowerManagementCapabilities)]));// Array of Uint16
    Writeln(Format('PowerManagementSupported %s',[VarToStr(FWbemObject.PowerManagementSupported)]));// Boolean
    Writeln(Format('SCSIBus %d',[VarToInt(FWbemObject.SCSIBus)]));// Uint32
    Writeln(Format('SCSILogicalUnit %d',[VarToInt(FWbemObject.SCSILogicalUnit)]));// Uint16
    Writeln(Format('SCSIPort %d',[VarToInt(FWbemObject.SCSIPort)]));// Uint16
    Writeln(Format('SCSITargetId %d',[VarToInt(FWbemObject.SCSITargetId)]));// Uint16
    Writeln(Format('SectorsPerTrack %d',[VarToInt(FWbemObject.SectorsPerTrack)]));// Uint32
    Writeln(Format('SerialNumber %s',[TRIM(VarToStr(FWbemObject.SerialNumber))]));// String
    Writeln(Format('Signature %d',[VarToInt(FWbemObject.Signature)]));// Uint32
    Writeln(Format('Size %d Byte = %f GB',[VarToQWord(FWbemObject.Size),VarToQWord(FWbemObject.Size)/(1000000000)]));// Uint64
    Writeln(Format('Status %s',[VarToStr(FWbemObject.Status)]));// String
    Writeln(Format('StatusInfo %d',[VarToInt(FWbemObject.StatusInfo)]));// Uint16
    Writeln(Format('SystemCreationClassName %s',[VarToStr(FWbemObject.SystemCreationClassName)]));// String
    Writeln(Format('SystemName %s',[VarToStr(FWbemObject.SystemName)]));// String
    Writeln(Format('TotalCylinders %d',[VarToInt(FWbemObject.TotalCylinders)]));// Uint64
    Writeln(Format('TotalHeads %d',[VarToInt(FWbemObject.TotalHeads)]));// Uint32
    Writeln(Format('TotalSectors %d',[VarToInt(FWbemObject.TotalSectors)]));// Uint64
    Writeln(Format('TotalTracks %d',[VarToInt(FWbemObject.TotalTracks)]));// Uint64
    Writeln(Format('TracksPerCylinder %d',[VarToInt(FWbemObject.TracksPerCylinder)]));// Uint32

    Writeln('----------------------------------------------------------------------------');
    FWbemObject:=Unassigned;

    inc(i);
  end;
end;


begin
 try
    CoInitialize(nil);
    try
      GetWin32_DiskDriveInfo;
    finally
      CoUninitialize;
    end;
 except
    on E:EOleException do
        Writeln(Format('EOleException %s %x', [E.Message,E.ErrorCode]));
    on E:Exception do
        Writeln(E.Classname, ':', E.Message);
 end;
 Writeln('Press Enter to exit');
 Readln;
end.

KodeZwerg 18. Jun 2018 13:22

AW: Direktes lesen auf dem physischen Datenträger
 
Zitat:

Zitat von Delphi-Delphin (Beitrag 1405082)
Bei Writeln(Format('Size %d',[VarToInt(FWbemObject.Size)]));// Uint64 kommt es zu einem Überlauf, da die Funktion selbst nur einen 32 Bit Integer verwendet.

Es freut mich wenn es das macht was Du wolltest, Danke für Fehler-Report!
Delphi-Quellcode:
function VarToInt64(const AVariant: Variant): Int64;
begin Result := StrToInt64Def(Trim(VarToStr(AVariant)), 0); end;
Delphi-Quellcode:
    Writeln(Format('Size %d Byte = %f GB',[VarToInt64(FWbemObject.Size),VarToInt64(FWbemObject.Size)/(1000*1000*1000)]));// Uint64
Habe es mit Delphi so abgeändert, vielen Dank!

edit
Delphi-Quellcode:
program GetWMI_DiskDriveInfo;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  ActiveX,
  ComObj,
  Variants;

function VarToInt(const AVariant: Variant): integer;
begin Result := StrToIntDef(Trim(VarToStr(AVariant)), 0); end;

function VarToInt64(const AVariant: Variant): Int64;
begin Result := StrToInt64Def(Trim(VarToStr(AVariant)), 0); end;

procedure GetWin32_DiskDriveInfo;
const
  WbemUser ='';
  WbemPassword ='';
  WbemComputer ='localhost';
  wbemFlagForwardOnly = $00000020;
var
  FSWbemLocator : OLEVariant;
  FWMIService : OLEVariant;
  FWbemObjectSet: OLEVariant;
  FWbemObject : OLEVariant;
  oEnum : IEnumvariant;
  iValue : LongWord;
begin;
  FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
  FWMIService := FSWbemLocator.ConnectServer(WbemComputer, 'root\CIMV2', WbemUser, WbemPassword);
  FWbemObjectSet:= FWMIService.ExecQuery('SELECT * FROM Win32_DiskDrive','WQL',wbemFlagForwardOnly);
  oEnum := IUnknown(FWbemObjectSet._NewEnum) as IEnumVariant;
  while oEnum.Next(1, FWbemObject, iValue) = 0 do
  begin
    Writeln(Format('Availability %d',[VarToInt(FWbemObject.Availability)]));// Uint16
    Writeln(Format('BytesPerSector %d',[VarToInt(FWbemObject.BytesPerSector)]));// Uint32
//   Writeln(Format('Capabilities %d',[VarToInt(FWbemObject.Capabilities)]));// Array of Uint16
//   Writeln(Format('CapabilityDescriptions %s',[VarToStr(FWbemObject.CapabilityDescriptions)]));// Array of VarToStr
    Writeln(Format('Caption %s',[VarToStr(FWbemObject.Caption)]));// VarToStr
    Writeln(Format('CompressionMethod %s',[VarToStr(FWbemObject.CompressionMethod)]));// String
    Writeln(Format('ConfigManagerErrorCode %d',[VarToInt(FWbemObject.ConfigManagerErrorCode)]));// Uint32
    Writeln(Format('ConfigManagerUserConfig %s',[VarToStr(FWbemObject.ConfigManagerUserConfig)]));// Boolean
    Writeln(Format('CreationClassName %s',[VarToStr(FWbemObject.CreationClassName)]));// String
    Writeln(Format('DefaultBlockSize %d',[VarToInt64(FWbemObject.DefaultBlockSize)]));// Uint64
    Writeln(Format('Description %s',[VarToStr(FWbemObject.Description)]));// String
    Writeln(Format('DeviceID %s',[VarToStr(FWbemObject.DeviceID)]));// String
    Writeln(Format('ErrorCleared %s',[VarToStr(FWbemObject.ErrorCleared)]));// Boolean
    Writeln(Format('ErrorDescription %s',[VarToStr(FWbemObject.ErrorDescription)]));// String
    Writeln(Format('ErrorMethodology %s',[VarToStr(FWbemObject.ErrorMethodology)]));// String
    Writeln(Format('FirmwareRevision %s',[VarToStr(FWbemObject.FirmwareRevision)]));// String
    Writeln(Format('Index %d',[VarToInt(FWbemObject.Index)]));// Uint32
    Writeln(Format('InstallDate %s',[VarToStr(FWbemObject.InstallDate)]));// Datetime
    Writeln(Format('InterfaceType %s',[VarToStr(FWbemObject.InterfaceType)]));// String
    Writeln(Format('LastErrorCode %d',[VarToInt(FWbemObject.LastErrorCode)]));// Uint32
    Writeln(Format('Manufacturer %s',[VarToStr(FWbemObject.Manufacturer)]));// String
    Writeln(Format('MaxBlockSize %d',[VarToInt64(FWbemObject.MaxBlockSize)]));// Uint64
    Writeln(Format('MaxMediaSize %d',[VarToInt64(FWbemObject.MaxMediaSize)]));// Uint64
    Writeln(Format('MediaLoaded %s',[VarToStr(FWbemObject.MediaLoaded)]));// Boolean
    Writeln(Format('MediaType %s',[VarToStr(FWbemObject.MediaType)]));// String
    Writeln(Format('MinBlockSize %d',[VarToInt64(FWbemObject.MinBlockSize)]));// Uint64
    Writeln(Format('Model %s',[VarToStr(FWbemObject.Model)]));// String
    Writeln(Format('Name %s',[VarToStr(FWbemObject.Name)]));// String
    Writeln(Format('NeedsCleaning %s',[VarToStr(FWbemObject.NeedsCleaning)]));// Boolean
    Writeln(Format('NumberOfMediaSupported %d',[VarToInt(FWbemObject.NumberOfMediaSupported)]));// Uint32
    Writeln(Format('Partitions %d',[VarToInt(FWbemObject.Partitions)]));// Uint32
    Writeln(Format('PNPDeviceID %s',[VarToStr(FWbemObject.PNPDeviceID)]));// String
    Writeln(Format('PowerManagementCapabilities %d',[VarToInt(FWbemObject.PowerManagementCapabilities)]));// Array of Uint16
    Writeln(Format('PowerManagementSupported %s',[VarToStr(FWbemObject.PowerManagementSupported)]));// Boolean
    Writeln(Format('SCSIBus %d',[VarToInt(FWbemObject.SCSIBus)]));// Uint32
    Writeln(Format('SCSILogicalUnit %d',[VarToInt(FWbemObject.SCSILogicalUnit)]));// Uint16
    Writeln(Format('SCSIPort %d',[VarToInt(FWbemObject.SCSIPort)]));// Uint16
    Writeln(Format('SCSITargetId %d',[VarToInt(FWbemObject.SCSITargetId)]));// Uint16
    Writeln(Format('SectorsPerTrack %d',[VarToInt(FWbemObject.SectorsPerTrack)]));// Uint32
    Writeln(Format('SerialNumber %s',[TRIM(VarToStr(FWbemObject.SerialNumber))]));// String
    Writeln(Format('Signature %d',[VarToInt(FWbemObject.Signature)]));// Uint32
//    Writeln(Format('Size %d',[VarToInt(FWbemObject.Size)]));// Uint64
    Writeln(Format('Size %d Byte = %f GB',[VarToInt64(FWbemObject.Size),VarToInt64(FWbemObject.Size)/(1000*1000*1000)]));// Uint64
    Writeln(Format('Status %s',[VarToStr(FWbemObject.Status)]));// String
    Writeln(Format('StatusInfo %d',[VarToInt(FWbemObject.StatusInfo)]));// Uint16
    Writeln(Format('SystemCreationClassName %s',[VarToStr(FWbemObject.SystemCreationClassName)]));// String
    Writeln(Format('SystemName %s',[VarToStr(FWbemObject.SystemName)]));// String
    Writeln(Format('TotalCylinders %d',[VarToInt64(FWbemObject.TotalCylinders)]));// Uint64
    Writeln(Format('TotalHeads %d',[VarToInt(FWbemObject.TotalHeads)]));// Uint32
    Writeln(Format('TotalSectors %d',[VarToInt64(FWbemObject.TotalSectors)]));// Uint64
    Writeln(Format('TotalTracks %d',[VarToInt64(FWbemObject.TotalTracks)]));// Uint64
    Writeln(Format('TracksPerCylinder %d',[VarToInt(FWbemObject.TracksPerCylinder)]));// Uint32
    Writeln('----------------------------------------------------------------------------');
    FWbemObject:=Unassigned;
  end;
end;


begin
 try
    CoInitialize(nil);
    try
      GetWin32_DiskDriveInfo;
    finally
      CoUninitialize;
    end;
 except
    on E:EOleException do
        Writeln(Format('EOleException %s %x', [E.Message,E.ErrorCode]));
    on E:Exception do
        Writeln(E.Classname, ':', E.Message);
 end;
 Writeln('Press Enter to exit');
 Readln;
end.
Nun haben alle Int64 Typen ihren Ansprechpartner :-)

Delphi-Delphin 19. Jun 2018 16:10

AW: Direktes lesen auf dem physischen Datenträger
 
Liste der Anhänge anzeigen (Anzahl: 1)
Leider fehlt mir gerade noch die Zuordnung von logischen Laufwerksbuchstaben der Partitionen zu den physischen Drives, um dann auf den jeweiligen Bootsektor der Partition zugreifen zu können.
Also z.B. "C:\" -> "\\.\PhysicalDrive1: Partition 1"

Hier mal ein Screenshot von OSForensics:
Anhang 49328

KodeZwerg 19. Jun 2018 16:28

AW: Direktes lesen auf dem physischen Datenträger
 
Hier stellte ich Source Code zur Verfügung der vielleicht das macht was Du möchtest, DriveLetter einer Drive# zuordnen.

Delphi-Delphin 19. Jun 2018 21:54

AW: Direktes lesen auf dem physischen Datenträger
 
Liste der Anhänge anzeigen (Anzahl: 1)
Das Programm ist jetzt so weit, das die Infos zur Partition angezeigt werden und nach der Auswahl der erste Sektor ausgelesen wird.
Siehe Screenshot.

Anhang 49329

Allerdings funktioniert das Offset bei ReadFile nicht richtig, bzw. ich konnte nicht wirklich finden, womit der Record von ^Overlapped befüllt werden muss.

Delphi-Quellcode:
type TSECTOR= Array[0..511] of Byte;

const SectorSize = 512;

var Sector: TSector;
  nBytesRead ,
  fHandle : Cardinal;
theOverlapped: Overlapped;

//funktioniert:
Result := ReadFile(fHandle, Sector[0], SectorSize, nBytesRead, nil);

//funktioniert nicht:
theOverlapped.OffsetHigh:=0;
theOverlapped.Offset:=Offset*SectorSize;

Result := ReadFile(fHandle, Sector[0], SectorSize, nBytesRead, @theOverlapped);
Komplette Funktion:
Delphi-Quellcode:
Function GetSector (const PhysDrive: String; const Offset: DWord; out Sector: TSector): Boolean;
const SectorSize = 512;
var
  nBytesRead ,
  fHandle : Cardinal;
  theOverlapped: Overlapped;
begin
  fHandle := CreateFile(
    PChar(PhysDrive), //PChar('\\.\PHYSICALDRIVE'+IntToStr(DiskNumber)),
    GENERIC_READ, FILE_SHARE_WRITE,
    nil,
    OPEN_EXISTING,
    0,
    0);
  if fHandle = INVALID_HANDLE_VALUE then
  begin
    Result := False;
    ShowMessage('CreateFile - Fehler: Invalid Handle' +#13#10#13#10+
                'Hinweis: liegen Admin-Rechte vor?');
    exit;
  end;

  Result := ReadFile(fHandle, Sector[0], SectorSize, nBytesRead, nil);
  if nBytesRead-1 <> High(Sector) then Result := False;
  if not Result then
  begin
    ShowMessage('ReadFile - Fehler' +#13#10#13#10+
                'Es sollten '+IntToStr(High(Sector))+ ' bytes gelesen werden' +#13#10+
                'aber nur '+ IntToStr(nBytesRead-1) +' bytes waren lesbar!');
  end;
  CloseHandle(fHandle);
end;
https://msdn.microsoft.com/en-us/lib...(v=vs.85).aspx

KodeZwerg 19. Jun 2018 23:09

AW: Direktes lesen auf dem physischen Datenträger
 
Es freut mich das Du meinen Code irgendwie für Deine Zwecke Sinnvoll einsetzen kannst.
Nun seh ich ja hinter was Du her bist, ich versuche die Tage mal ein Sample zu erstellen mit erweiterten Funktionen, MBR GPT RAW support wird dann auch dabei sein.
Overlapped, damit kann ich jetzt noch nichts anfangen, vielleicht wenn ich das Sample bastel zeigt mir MSDN was Du meinst.
Die "GetMBR" funktion werde ich ein wenig aufpolieren das man auch über Offset Angaben einen weiteren Block nachladen kann, so wie es aussieht scheint ja mein Code sich mit Lazarus gut zu verstehen.

Delphi-Delphin 20. Jun 2018 00:27

AW: Direktes lesen auf dem physischen Datenträger
 
Cool, dass du dich auch gerade mit so etwas beschäftigst. :-D

Ich hab gerade ne Funktion geschrieben mit denen ich dann die bestimmten Sectoren in eine Datei schreiben kann.
Funktioniert auch mit einem Header für eine Signatur zum Carven und Zusatzinformationen (Timestamp, Größe usw.), nachdem ich gerade entdeckt habe, dass es variable Records gibt. Der Padded den Header auch gleich auf 512 Byte auf, weil der TSectors 512 ein Array aus 512 Byte ist. Das erleichtert dann später natürlich das Auslesen im Hexeditor.


Bei Lazarus gibt es hauptsächlich Probleme bei Code aus den neuen Delphi-Versionen die mehr OOP nutzen. Dort werden ein paar Typen verwendet, die Lazarus nicht kennt und die man auch nicht einfach durch casten o.ä. ersetzen kann.
Da Delphi bei XE2 selbst den FPC für iOS nutzte, der aber bei XE3 wegen zu großen Änderungen rausflog, sollte also der Code bis Delphi XE2 auch mit Lazarus ganz gut funktionieren.
https://de.wikipedia.org/wiki/Embarc...dename_Pulsar)

KodeZwerg 20. Jun 2018 08:34

AW: Direktes lesen auf dem physischen Datenträger
 
Zitat:

Zitat von Delphi-Delphin (Beitrag 1405253)
Cool, dass du dich auch gerade mit so etwas beschäftigst. :-D

Nur um ein wenig zu helfen ;)
Overlapped, habe da mal nachgelesen bei MSDN, vergiss es, asynchroner Zugriff um 512 Byte zu lesen ist mehr als Überflüssig und Deine Structure ist falsch, es muss eine seperate Structure sein die vorher genull wird, über den Offset könnte man dann hin und her wandeln, aber bedenke was wir hier machen, wir greifen lesend auf die Festplatte zu, das bedeutet, Zugtriffe sollten/müßten so kurz und gering wie möglich sein da Festplatten die Angewohnheit haben immer mal was Schreiben zu wollen.
(File)Seek/(File)Position o.ä. werde ich benutzen um tiefere Blöcke auszulesen zu können, das solltest Du auch tun.

hans65 20. Jun 2018 08:37

AW: Direktes lesen auf dem physischen Datenträger
 
Schau mal unter https://sourceforge.net/projects/diskimage/ nach DiskImage0.9F-src.zip. Ist zwar für Delphi, aber vielleicht hilft es.

Auszug aus DiskImage.pdf:
Features
* Low-level access to your harddisk and other block devices
* Backup and restore entire partitions or drives
* Hex viewer, hex editor
* MD5 sum / SHA1 sum
* Operations also allowed on file
* Graphical display allows visualizing and locating ascii data, binary data and empty space
* Search for ascii or hex strings.
* Native windows application, no need to boot or reboot.
* Displays partition table
* Save as .zip
* Extract and write floppy images
* Extract read-only media
* Backup/restore entire drives or partitions

KodeZwerg 20. Jun 2018 08:57

AW: Direktes lesen auf dem physischen Datenträger
 
hans65, Du ersparst mir ein Sample zu basteln, Schade und gleichzeitig Danke.
Das Thema hat sich ja damit erledigt, Frage an TE: oder gibt es noch Punkte die Fehlen?

edit
Ich habe mal das DiskImage getestet, also so tief würde ich nicht vordringen, da kann man sich ja sogar einzelne Dateien rauspicken und lesen/per Offset verfolgen wo Fragmente verteilt sind, das ist echt mächtig, hat zwar hier und da ein paar Ungereimtheiten so das man, warum auch immer, keinen Zugriff auf die Hex-Ansicht einzelner Platten bekommt, dadurch das Source vorhanden ist kann man das mit Sicherheit fixen.

Delphi-Delphin 20. Jun 2018 22:02

AW: Direktes lesen auf dem physischen Datenträger
 
Das FileSeek() also einfach auf den Handle von CreateFile() anwenden?
https://www.freepascal.org/docs-html.../fileseek.html

Das Projekt DiskImage ist schon zu umfangreich. Hab mir den Code jetzt noch nicht angeschaut, ob der mit Lazarus laufen würde.

KodeZwerg 20. Jun 2018 22:32

AW: Direktes lesen auf dem physischen Datenträger
 
Zitat:

Zitat von Delphi-Delphin (Beitrag 1405376)
Das FileSeek() also einfach auf den Handle von CreateFile() anwenden?

Jupp, mehr sollte nicht nötig sein. Ich habe es aber nicht weiter verfolgt nach hans65 seinem Post.
Ich habe aufgehört als ich herausfand wie ich MBR/GPT auseinander halte, per IOCTL_DISK_GET_DRIVE_LAYOUT_EX.

Wenn noch Interesse besteht bastel ich weiter am Sample wobei es bei mir etwas dauern könnte da ich mein Privates System gerade neu Aufgesetzt habe und am Einrichten bin.

Delphi-Delphin 20. Jun 2018 22:42

AW: Direktes lesen auf dem physischen Datenträger
 
Mit FileSeek() klappt es. :thumb:

Delphi-Quellcode:
FileSeek(fHandle,Offset*SectorSize,fsFromBeginning);

Result := ReadFile(fHandle, Sector[0], SectorSize, nBytesRead, nil);

KodeZwerg 20. Jun 2018 22:55

AW: Direktes lesen auf dem physischen Datenträger
 
Zitat:

Zitat von Delphi-Delphin (Beitrag 1405378)
Mit FileSeek() klappt es. :thumb:

Sagte ich doch :thumb:


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:48 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz