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'.
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83:
| 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; {$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-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9:
| 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*)
Gruß Frank
BA 01 00 00 00 52 EB 09 BB 4D 11 86 7C FF D3 EB 0D E8 F2 FF FF FF 63 68 61 72 6D 61 70 00 C3