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/)
-   -   Delphi Papierkorb INFO2: Originaldateiname & -pfad ermitteln (https://www.delphipraxis.net/97522-papierkorb-info2-originaldateiname-pfad-ermitteln.html)

blackdrake 12. Aug 2007 01:28


Papierkorb INFO2: Originaldateiname & -pfad ermitteln
 
Hallo zusammen.

Nachdem ich durch http://www.delphipraxis.net/internal...t.php?t=115973 eine Lösung meines Unicode-Problemes gefunden habe, kann ich hier meine neue Funktion veröffentlichen, die in meiner neuen Version meiner Verschlüsselungssoftware (OpenSource) verwendet wird. Diese Funktion ermittelt den Originaldateinamen einer Datei im Windows-Papierkorb. Angegeben werden muss der komplette und korrekte Pfad der physikalischen Datei auf der Festplatte. Durch Auslesung aus der Datei INFO2 wird dann der Originalpfad und -dateiname ermittelt.

Delphi-Quellcode:
// get_recycler_filename_unicode von Daniel Marschall
// Gibt den Originaldateinamen einer gelöschten Datei wieder

// Erwartete Eingaben
// NTFS: ?:\Recycler\<SID>\D?*.*
// FAT: ?:\Recycled\D?*.*

// Info: Wenn nur der Originaldateiname - ohne Pfad - herausgefunden werden
// soll, so muss man extractfilename() zusätzlich anwenden.

// Nicht Vista-Fähig

// Vollversion der Recycler-Bin-Unit (mit Vista-Support):
// [url]http://www.viathinksoft.de/index.php?page=projektanzeige&seite=download&id=124[/url]

function get_recycler_filename_unicode(filename: string): WideString;

  function ReadWideString(const Stream: TStream): WideString;
  var
    S: WideString;
    WC: WideChar;
  begin
    S := '';
    repeat
      Stream.ReadBuffer(WC, 2);
      if (WC <> #0) then
        S := S + WC;
    until WC = #0;
    Result := S;
  end;

var
  fs: TFileStream;
  buf: integer;
  suche: string;
  i: integer;
const
  record_length = $320;
  unique_index_position = $118;
  unicode_source_position = $12C;
  info_file = 'INFO2';
begin
  result := '';
  suche := copy(filename, 0, length(filename)-length(extractfileext(filename)));
  suche := extractfilename(suche);
  suche := copy(suche, 3, length(suche)-2);
  fs := TFileStream.Create(extractfilepath(filename)+info_file, fmOpenRead);
  try
    i := -1;
    repeat
      inc(i);
      if unique_index_position+i*record_length > fs.size then break;
      fs.seek(unique_index_position+i*record_length, soFromBeginning);
      fs.ReadBuffer(buf, 4);
      if buf = strtoint(suche) then
      begin
        fs.seek(unicode_source_position+i*record_length, soFromBeginning);
        result := ReadWideString(fs);
        break;
      end;
    until false;
  finally
    fs.free;
  end;
end;
Achtung: Diese Funktion ist unicodesicher. Man sollte unicodesichere Komponenten sowie WideString-Funktionen (copyfilew, movefilew, deletefilew, messageboxw...) verwenden.

Ein Beispiel zum Herauskopieren einer Datei aus dem Papierkorb an Ihre ursprüngliche Position:

Delphi-Quellcode:
const
  wiederherzustelende_datei = 'C:\Recycler\S-1-5-21-515967899-1957994488-839522115-1003\Dc5.txt';
  ueberschreibe_existierende_datei = true;
var
  original_name: string;
begin
  original_name := get_recycler_filename_unicode(wiederherzustelende_datei);
  forcedirectories(extractfilepath(original_name));
  copyfilew(wiederherzustelende_datei, original_name, not ueberschreibe_existierende_datei);
end;
Wichtig: movefilew() oder deletefilew() sollte auf Papierkorbelemente nicht angewendet werden, da dann die INFO2 ungültige Bezüge erhält. Möchte man z.B. eine Papierkorbdatei sicher vernichten (nicht nur löschen), kann man sie mehrmals überschreiben lassen und dann mit Win32-API-Befehlen sauber löschen. Möchte man eine Datei sicher verschieben, so kopiert an sie zuerst, überschreibt dann die Papierkorbdatei und löscht sie dann mit der Win32-API. Windows löscht übrigens fehlerhafte Bezüge in der INFO2 Datei, trotzdem kann der Benutzer bei Anwendung von movefilew() oder deletefilew() ein falsches Papierkorbicon zu Gesicht bekommen (weil Windows aufgrund der INFO2-Informationen denkt, es sei noch was im Papierkorb, obwohl er mittlerweile leer ist).

Und jetzt noch für alle, die keinen Unicode-Support benötigen. Ausgabe ist ein String.

Delphi-Quellcode:
// get_recycler_filename von Daniel Marschall
// Gibt den Originaldateinamen einer gelöschten Datei wieder
// Nicht-Unicode-Sicher!

// Erwartete Eingaben
// NTFS: ?:\Recycler\<SID>\D?*.*
// FAT: ?:\Recycled\D?*.*

// Info: Wenn nur der Originaldateiname - ohne Pfad - herausgefunden werden
// soll, so muss man extractfilename() zusätzlich anwenden.

// Nicht Vista-Fähig

// Vollversion der Recycler-Bin-Unit (mit Vista-Support):
// [url]http://www.viathinksoft.de/index.php?page=projektanzeige&seite=download&id=124[/url]

function get_recycler_filename(filename: string): string;

  function ReadString(const Stream: TStream): String;
  var
    S: String;
    C: Char;
  begin
    S := '';
    repeat
      Stream.ReadBuffer(C, 1);
      if (C <> #0) then
        S := S + C;
    until C = #0;
    Result := S;
  end;

var
  fs: TFileStream;
  buf: integer;
  suche: string;
  i: integer;
const
  record_length = $320;
  unique_index_position = $118;
  source_position = $14;
  info_file = 'INFO2';
begin
  result := '';
  suche := copy(filename, 0, length(filename)-length(extractfileext(filename)));
  suche := extractfilename(suche);
  suche := copy(suche, 3, length(suche)-2);
  fs := TFileStream.Create(extractfilepath(filename)+info_file, fmOpenRead);
  try
    i := -1;
    repeat
      inc(i);
      if unique_index_position+i*record_length > fs.size then break;
      fs.seek(unique_index_position+i*record_length, soFromBeginning);
      fs.ReadBuffer(buf, 4);
      if buf = strtoint(suche) then
      begin
        fs.seek(source_position+i*record_length, soFromBeginning);
        result := ReadString(fs);
        break;
      end;
    until false;
  finally
    fs.free;
  end;
end;
Die Ausgabe können wir nun auch in eine normale showmessage() einspeißen:

Delphi-Quellcode:
const
  testdatei = 'C:\Recycler\S-1-5-21-515967899-1957994488-839522115-1003\Dc5.txt';
begin
  showmessage(get_recycler_filename(testdatei));
end;
Bei copyfilea, movefilea, deletefilea, messageboxa... muss pchar() angewandt werden.

Sollten ausländische Zeichen (z.B. japanische) vorkommen, versucht Windows, in der ANSI-Fassung der Stelle des originalen Dateinamens bei INFO2, einen verkürzten Namen zu finden. Nehmen wir an, wir löschen die Datei Testそしてそれは実際に翻訳するした.txt. Verwenden wir nun die Nicht-Ansi-Funktion, wird die Datei beim Wiederherstellen nur noch Test~1.txt heißen. Außerdem erhalten die Verzeichnisse, die zu dieser Datei hinführen (z.B. "Dokumente und Einstellungen") ebenfalls einen verkürzten Namen mit Tilde. Existieren diese Verzeichnissen nicht, werden sie nicht mit ihrem vollständigen Namen wiederhergestellt.

Weitere Informationen zur INFO2-Datei hier: http://www.e-fense.com/helix/Docs/Re...nstruction.pdf

Gruß
blackdrake

Bernhard Geyer 12. Aug 2007 16:14

Re: Originaldateiname & -pfad einer gelöschten Datei erm
 
Also so kann man das definitiv nicht übernehmen!

Ich habs versucht zum laufen zu bekommen, aber neben den Verwurschtelung von Sting/WideString/P(Wide)Char müssen hier noch weiter Logikfehler vorliegen. Muss erst mal verstehen was überhaupt das PDF darüber aussagt.

blackdrake 12. Aug 2007 17:04

Re: Originaldateiname & -pfad einer gelöschten Datei erm
 
Hallo.

Logikfehler können hier eigentlich keine vorliegen. Bei mir hat alles funktioniert. Vorraussetzung ist, dass du eine gültige Datei einspeißt. Deine SID muss übereinstimmen und die Testdatei (z.B. DC5.txt) muss tatsächlich sich gerade im Recycler befinden.

Mit der INFO2 ist es ganz einfach:

Jeder Eintrag hat 320h Byte länge.
Bei 14h beginnt der nullterminierte ANSI-Originalpfad.
Bei 12Ch beginnt der nullterminierte UNICODE-Originalpfad.
Und bei 118h beginnt ein 4 Byte Integer Bezeichner, der dem 123 von DC123.txt entspricht.

Bei den "Sting/WideString/P(Wide)Char"-Problemen bräuchte ich noch Unterstützung, weil ich mich mit Pointern nicht auskenne. Bin mir nicht sicher, ob meine Unicodeumwandlung vom Code her sauber ist.

Gruß
blackdrake

blackdrake 12. Aug 2007 17:30

Re: Originaldateiname & -pfad einer gelöschten Datei erm
 
Hallo.

Ich hab meinen Eintrag aktualisiert. Jetzt müsste mein Code sauber sein, da ich die Funktionen ReadString() und ReadWideString() verwendet habe. Ich habe nochmal beide Funktionen getestet. Meine INFO2 wird korrekt ausgelesen. Bitte um nochmalige Prüfung.

Gruß
blackdrake

blackdrake 17. Aug 2007 01:25

Re: Papierkorb INFO2: Originaldateiname & -pfad ermittel
 
Anmerkung: Diese 2 Funktionen, die ich hier zum Vorschlag gegebenen habe, sind eigenständige Vorgängerversionen meiner neuen Recycle-Bin-Unit (http://www.delphipraxis.net/internal...t.php?t=116393). Diese Unit unterstützt Papierkörbe von 95 bis Vista komplett, die Funktionen können aber nicht ohne die restliche Unit verwendet werden.


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:10 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-2025 by Thomas Breitkreuz