Einzelnen Beitrag anzeigen

Benutzerbild von _frank_
_frank_

Registriert seit: 21. Feb 2003
Ort: Plauen / Bamberg
922 Beiträge
 
Delphi 3 Professional
 
#1

Festplattenzugriff / Imagedatei

  Alt 12. Okt 2007, 23:53
Moin,
aus Gründen der Datenrettung bin ich dabei, von nem Kumpel seiner Festplatte ein Image mit Winhex zu ziehen. Funktioniert, wenn auch träge, ganz gut. Zwischendurch sind immer mal nicht lesbare Sektoren, die Winhex mit dem String ' ? BAD SECTOR ? ' kennzeichnet. soweit so gut. Da das eine ziemliche fummelei ist, diese Blöcke manuell neu von der Platte zu kratzen, hab ich mir gedacht, schreib ich mir ein Programm dafür.

die hauptroutine (scant das image nach dem string durch und schreibt die Offsets in eine Textdatei+länge).Funktioniert super
Wenn ich das programm nicht mit D3 kompiliere (wegen Int64), soll die datenrecovery-Funktion aktiv sein (Compilerschalter). Diese macht nichts weiter, als den offset im Image zu einem gegebenen Startoffset hinzuaddieren (um so auf den Festplattenoffset zu kommen) und durch 512 zu teilen = Sektornummer. Dann soll er einen Sektor laden und diesen an der jeweiligen Stelle in die Imagedatei schreiben. nur komischerweise bricht die readsektor-funktion immer ab und der Buffer ist leer (nur Null-Bytes).

in Edit3 steht der Festplatten-Startoffset: '500000000' (20GB-Grenze, beginn des ersten Images)
Combobox1 ist gespickt mit der Laufwerksbezeichnung 'PhysicalDrive0'.

Delphi-Quellcode:
function ReadSector(Sector: Integer; buffer: pointer; Drive: string):Boolean;
const
  SectorSize = 512;
var
  hDevice: THandle;
  DevName: string;
  nb: {$IFDEF VER100}Integer{$ELSE}Cardinal{$ENDIF};
begin
  result:=false;
  if WIN32PLATFORM = VER_PLATFORM_WIN32_NT then
  begin
    DevName := '\\.\'+Drive;
    hDevice := CreateFile(pChar(DevName), GENERIC_READ,
      FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING,
      FILE_ATTRIBUTE_NORMAL, 0);
    if (hDevice = INVALID_HANDLE_VALUE) then
    begin
      Result:=False;
      Exit;
    end;
    SetFilePointer(hDevice, (Sector-1) * SectorSize,
      nil, FILE_BEGIN );
    Result := ReadFile(hDevice, buffer^, SectorSize, nb, nil) and
      (nb=SectorSize);
    CloseHandle(hDevice);
  end;
end;

procedure TForm1.Button2Click(Sender: TObject);
var fs:TFileStream;
    sl:TStringlist;
    buf:string[16];
    b:array[0..511] of byte;
    s,e,n,c,i:cardinal;
    {$IFNDEF VER100}
    fpbase,fpSector:Int64;
    {$ENDIF}
begin
  abort:=false;
  fs:=TFilestream.Create(edit1.text,fmOpenReadWrite);
  sl:=TStringlist.create;
  s:=0;
  n:=0;
  {$IFNDEF VER100}
  fpBase:=StrToInt64('$'+edit3.Text) div 512; //calc Base-Sector from Offset given
  {$ENDIF}
  while not abort and (fs.Position<fs.Size) do
  begin
    fs.read(buf[0],16);
    if pos('BAD SECTOR',buf)>0 then
    begin
      inc(n);
      s:=fs.Position-16;
      while pos('BAD SECTOR',buf)>0 do
      begin
        fs.read(buf[0],16);
      end;
      e:=fs.position-16;
      sl.Add(IntToHex(s,8)+' - '+IntToHex(e,8)+' ('+IntToHex(e-s,4)+')');
      {$IFNDEF VER100}
      if CheckBox1.checked then
      begin
        fpSector:=fpBase+(s div 512);
        c:=(e-s) div 512;
        for i:=0 to c-1 do
        begin
          fs.position:=s;
          if not ReadSector(fpSector,@b,combobox1.text) then
            ShowMessage('Can''t read from disc');
          fs.write(b,sizeOf(b));
          inc(fpSector);
          inc(s,512);
        end;
      end;
      {$ENDIF}
    end;
    Label1.caption:='Offset: '+IntToHex(fs.position,8)+' ('+Inttostr(n)+'-'+IntToHex(s,8)+')';
    application.ProcessMessages;
  end;
  sl.SaveToFile(edit2.text);
  sl.free;
  fs.free;
end;
was mich noch wundert ist, dass sich die Streamposition innerhalb der for-schleife nicht verändert, obwohl ich explizit den Startwert s um 512 erhöhe und im nächsten Schleifendurchlauf der position zuweise (eigentlich sollte das write reichen, oder? darüber schweigt sich meine DOH aus...).

meine Testroutine für die ReadSektor-Funktion funktioniert tadellos, jedoch in der Hauptroutine nicht....

Delphi-Quellcode:
procedure TForm1.Button4Click(Sender: TObject);
var buf:array[0..511] of byte;
    fs:TFilestream;
begin
  ReadSector(0,@buf,combobox1.text);
  fs:=TFilestream.create('test2.dat',fmCreate or fmOpenReadWrite);
  fs.Write(buf,sizeOf(buf));
  fs.free;
end;
ich hoffe mal, ich habe alle Infos zusammen, und ihr könnt mir helfen. Habe langsam keine Idee mehr, warum der abbricht bzw. wie man das umgeht. ich habe den offset zum testen mal geringer angesetzt, um selbst innerhalb des Int32-Wertebereichs zu bleiben, trotzdem Abbruch.
leider hab ich kaum demo-Programme gefunden, um mir da mehr infos zu holen (bei Luckies seh ich nicht so ganz durch *g*)

//edit: Programm angehängt

Gruß Frank
Angehängte Dateien
Dateityp: zip hddzugriff_156.zip (112,6 KB, 20x aufgerufen)
  Mit Zitat antworten Zitat