Czy jest możliwa inna, szybsza metoda na pobranie listy plików/katalogów znajdujących się na partycji (lub całym dysku), pobrana bezpośrednio z hmm, tabeli partycji lub jakichś innych metod np: z systemów ReFS, NTFS, EXT3, FAT32, itp?
szczerze to nie wydaje mi się (a przynajmniej ja o takiej nie słyszałem). Najszybciej powinno być asynchroniczne FindFirstFileEx
z flagą FIND_FIRST_EX_LARGE_FETCH
Na pewno jest możliwe, skoro istnieją programy do odczytywania usuniętych danych. M.in. listują usunięte pliki i katalogi. Poza tym system też to robi. Więc pewnie wystarczy się odwołać albo do sterownika hdd (jeśli można), albo bezpośrednio do dysku, ale tu już asm.
zobacz Everything: https://www.voidtools.com/
Aplikacja faktycznie momentalnie znajduje każdy plik na dysku i podaje dokładną lokalizację. Posiada źródła w C i bibliteki 32/64bit do wykorzystania.
Ciekaw jestem jednak na jakiej zasadzie ona działa. Według FAQ korzysta z indeksu NTFSa:
What are the system requirements for "Everything"?
"Everything" will run on Windows XP, Vista, Windows 7, Windows 8 and Windows 10 Indexing NTFS volumes requires the Everything service or running "Everything" as administrator.
Ciekaw jestem jednak na jakiej zasadzie ona działa.
Przecież sam napisałeś, że:
Posiada źródła w C i bibliteki 32/64bit do wykorzystania.
więc... trzeba kuknąć w źródła i sprawdzić jak działa; W Delphi można bez problemu posługiwać się WinAPI, dlatego też można sobie przetłumaczyć ten kod i wykorzystać; Nie będzie to łatwie, ale nie niemożliwe.
tu masz początek w Delphi - jak czytać MBR, żeby określić czy to NTFS (tylko z nim zadziała), jak pobrać adres początku tablicy MFT. Więcej nie zdążyłem (ale jeszcze popróbuję)
wzorowałem się na https://www.codeproject.com/kb/vb/mftread.aspx i http://ftp.kolibrios.org/users/Asper/docs/NTFS/ntfsdoc.html#id4752135
program NTFSIndexRead;
{$APPTYPE CONSOLE}
{$R *.res}
uses
madExcept,
madLinkDisAsm,
madListHardware,
madListProcesses,
madListModules,
System.SysUtils,
System.Generics.Collections,
Winapi.Windows;
type
TBuffer = array[0..1023] of byte;
TMFTAttribute = packed record
AttributeType: Cardinal;
Length: Cardinal;
NonResidentFlag: Byte;
NameLength: Byte;
OffsetToTheName: Word;
Flags: Word;
AttributeID: Word;
LengthOfTheAttribute: Cardinal;
OffsetToTheAttribute: Word;
IndexedFlag: Byte;
Padding: Byte;
end;
procedure SetFileOffset(const hFile: THandle; const Offset: UInt64);
var
LowPart, HighPart: UInt32;
begin
LowPart := Offset and $ffffffff;
HighPart := (Offset shr 32) and $ffffffff;
SetFilePointer(hFile, LowPart, @HighPart, FILE_BEGIN);
WriteLn('Reading from: ', Offset, ' Low: ' , LowPart, ' High: ', HighPart);
end;
function ReadSector(const Disk: string; var Buffer: TBuffer; StartFrom: UInt64): Boolean;
var
hFile: THandle;
Readed: Cardinal;
begin
hFile := CreateFile(
PWideChar('\\.\' + Disk),
GENERIC_READ,
FILE_SHARE_READ or FILE_SHARE_WRITE,
nil,
OPEN_EXISTING,
0,
0);
if hFile = INVALID_HANDLE_VALUE then
begin
WriteLn('Open Error');
CloseHandle(hFile);
Exit(False);
end;
SetFileOffset(hFile, StartFrom);
Result := ReadFile(hFile, Buffer, Length(Buffer), &Readed, nil);
CloseHandle(hFile);
end;
procedure PrintBuffer(const Buffer: TBuffer; const SectorNumber: Cardinal);
var
i, j: Integer;
Offset: Integer;
b: Byte;
begin
WriteLn('');
Offset := SectorNumber * Length(Buffer);
for i := 0 to Length(Buffer) div 16 - 1 do
begin
Write(IntToHex(i * 16 + Offset, 8), ': ');
for j := 0 to 15 do
begin
if j = 8 then
write(' - ');
write(IntToHex(Buffer[i * 16 + j], 2), ' ');
end;
for j := 0 to 15 do
begin
if j = 8 then
write(' ');
b := Buffer[i * 16 + j];
if (b < 32) or (b > 127) then
write('.')
else
write(Chr(b));
end;
Writeln('');
end;
end;
function IsNTFSDrive(const Disk: string): Boolean;
var
Buffer: TBuffer;
begin
Result := ReadSector(Disk, Buffer, 0);
if Result then
Result := (Buffer[3] = 78) and (Buffer[4] = 84) and (Buffer[5] = 70) and (Buffer[6] = 83);
end;
function HexToInt(const Buffer: TBuffer; const Offset, Length: Cardinal): Cardinal;
var
i: Integer;
begin
Result := 0;
for i := Offset to Offset + Length - 1 do
Result := Result + (Buffer[i] shl ((i - Offset) * 8));
end;
function GetAttributes(const Buffer: TBuffer; const Offset: Cardinal): TList<TMFTAttribute>;
var
AttributeOffset: Cardinal;
MFTAttribute: TMFTAttribute;
FileAttribute: Byte;
begin
Result := TList<TMFTAttribute>.Create;
FileAttribute := 0;
AttributeOffset := HexToInt(Buffer, 20, 2) + 1;
repeat
WriteLn('Odczyt atrybutu');
Move(Buffer[AttributeOffset - 1], MFTAttribute, SizeOf(MFTAttribute));
WriteLn('AttributeType: ', MFTAttribute.AttributeType);
if MFTAttribute.AttributeType = $30 then
Inc(FileAttribute);
Result.Add(MFTAttribute);
Inc(AttributeOffset, MFTAttribute.Length);
if FileAttribute = 2 then
Break;
if MFTAttribute.AttributeType = -1 then
Break;
until AttributeOffset >= 1024;
end;
var
Buffer: TBuffer;
Disk: string;
BytesPerSect: Cardinal;
SectPerCluster: Cardinal;
MFTCluster: Cardinal;
Offset: Cardinal;
begin
Write('Podaj literę dysku: ');
ReadLn(Disk);
if IsNTFSDrive(Disk) then
begin
Writeln('To jest dysk NTFS.');
end
else
Writeln('To nie jest dysk NTFS.');
if ReadSector(Disk, Buffer, 0) then
begin
PrintBuffer(Buffer, 0);
BytesPerSect := HexToInt(Buffer, $0b, 2);
SectPerCluster := HexToInt(Buffer, $0d, 1);
MFTCluster := HexToInt(Buffer, $30, 8);
Writeln('Bytes per Sector: ', BytesPerSect);
WriteLn('Sectors Per Cluster: ', SectPerCluster);
Writeln('$MFT cluster number: ', MFTCluster);
ReadLn;
//Read MFT
if ReadSector(Disk, Buffer, MFTCluster * SectperCluster * BytesPerSect) then
begin
PrintBuffer(Buffer, 0);
//GetAttributes(Buffer, 0).Free;
end;
end;
Readln;
end.
Dzięki **abrakadaber **
Znalazłem też inny program czytający z MFT (źródło w Delphi):
http://web.archive.org/web/20051111145922/http://koti.mbnet.fi/smiika/downloads/DiskBuddy.zip