Seite 1 von 2

master file table MFT auslesen

Verfasst: 31.08.2013 15:07
von derschutzhund
Kann mir jemand sagen wie man den "master file table" der gesamten Festplatte auslesen kann?
Die Festplatte ist in NTFS formatiert.

LG

Wolfgang

Re: master file table MFT auslesen

Verfasst: 31.08.2013 20:05
von sibru
Ich würd da mal an die API-Funktion CreateFile() denken, anscheinend kann man
damit auch direkt auf Laufwerke zugreifen (siehe unten, CodeZeile 51).
Hab´ unter http://www.codeguru.com/cpp/w-p/system/ ... dWrite.htm
folgenden C-Code gefunden, der mit nem bischen Glück und sehr viel Fleis
(Umsetzung zu PB) zum Ziel führen könnte:

Code: Alles auswählen

char * ReadSectors(int drive, DWORD startinglogicalsector, int numberofsectors)
{
 
// All msdos data structures must be packed on a 1 byte boundary
#pragma pack (1)
struct
{
DWORD StartingSector ;
WORD NumberOfSectors ;
DWORD pBuffer;
}ControlBlock;
#pragma pack ()
 
#pragma pack (1)
typedef struct _DIOC_REGISTERS
{
DWORD reg_EBX;
DWORD reg_EDX;
DWORD reg_ECX;
DWORD reg_EAX;
DWORD reg_EDI;
DWORD reg_ESI;
DWORD reg_Flags;
} DIOC_REGISTERS ;
#pragma pack ()
 
char* buffer = (char*)malloc (512*numberofsectors);
HANDLE hDevice ;
DIOC_REGISTERS reg ;
BOOL fResult ;
DWORD cb ;
 
// Creating handle to vwin32.vxd (win 9x)
hDevice = CreateFile ( "\\\\.\\vwin32",
0,
0,
NULL,
0,
FILE_FLAG_DELETE_ON_CLOSE,
NULL );
 
if ( hDevice == INVALID_HANDLE_VALUE )
{
// win NT/2K/XP code
HANDLE hDevice;
DWORD bytesread;
 
char _devicename[] = "\\\\.\\C:";  // <---- so sollte es gehen !?!?!?
_devicename[4] += drive;
 
// Creating a handle to disk drive using CreateFile () function ..
hDevice = CreateFile(_devicename,
GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL);
 
if (hDevice == INVALID_HANDLE_VALUE)
return NULL;
 
// Setting the pointer to point to the start of the sector we want to read ..
SetFilePointer (hDevice, (startinglogicalsector*512), NULL, FILE_BEGIN);
 
if (!ReadFile (hDevice, buffer, 512*numberofsectors, &bytesread, NULL) )
return NULL;
}
else
{
// code for win 95/98
ControlBlock.StartingSector = (DWORD)startinglogicalsector;
ControlBlock.NumberOfSectors = (DWORD)numberofsectors ;
ControlBlock.pBuffer = (DWORD)buffer ;
 
//-----------------------------------------------------------
// SI contains read/write mode flags
// SI=0h for read and SI=1h for write
// CX must be equal to ffffh for
// int 21h's 7305h extention
// DS:BX -> base addr of the
// control block structure
// DL must contain the drive number
// (01h=A:, 02h=B: etc)
//-----------------------------------------------------------
 
reg.reg_ESI = 0x00 ;
reg.reg_ECX = -1 ;
reg.reg_EBX = (DWORD)(&ControlBlock);
reg.reg_EDX = drive+1;
reg.reg_EAX = 0x7305 ;
 
// 6 == VWIN32_DIOC_DOS_DRIVEINFO
fResult = DeviceIoControl ( hDevice,
6,
&(reg),
sizeof (reg),
&(reg),
sizeof (reg),
&cb,
0);
 
if (!fResult || (reg.reg_Flags & 0x0001)) return NULL;
}
 
CloseHandle(hDevice);
return buffer;
}
Und hier vielleicht noch ´n bischen allgemeine Doc zur PartitionsTabelle
in Form von´nem Uralt-QBasicCode...

Code: Alles auswählen

SUB DriveSpecs (D$) 'D$=nackter LaufwerksBuchstabe !!!
IF LTRIM$(D$) = "" THEN GOTO DriveError
Drive$ = "'" + D$ + ":'"
DriveNr% = ASC(UCASE$(D$)) - 65
IF DriveNr% < 0 OR DriveNr% > 3 THEN
DriveError:
	PRINT Drive$; ": ungltige Laufwerks-Angabe"
	END
END IF
Drive% = DriveNr%
IF Drive% > 1 THEN Drive% = Drive% + 126

'----- Laufwerks-Daten holen -----
ClearReg
reg.AX = CVI(CHR$(0) + CHR$(8))      'AH=8 AL=0
reg.DX = CVI(CHR$(Drive%) + CHR$(0))'DH=0 DL=Drive%
CALL INTERRUPTX(&H13, reg, reg)
'----- splitt in ?L% und ?H% -----
AX$ = MKI$(reg.AX): AL% = ASC(AX$): ah% = ASC(MID$(AX$, 2))
BX$ = MKI$(reg.BX): BL% = ASC(BX$): BH% = ASC(MID$(BX$, 2))
CX$ = MKI$(reg.CX): CL% = ASC(CX$): CH% = ASC(MID$(CX$, 2))
DX$ = MKI$(reg.DX): DL% = ASC(DX$): DH% = ASC(MID$(DX$, 2))
'----- Register anzeigen -----
IF Show > 1 THEN
PRINT "AX="; bin(ah% + 0, 8); "_"; bin(AL% + 0, 8); "  AH="; ah%; "  AL="; AL%
PRINT "BX="; bin(BH% + 0, 8); "_"; bin(BL% + 0, 8); "  BH="; BH%; "  BL="; BL%
PRINT "CX="; bin(CH% + 0, 8); "_"; bin(CL% + 0, 8); "  CH="; CH%; "  CL="; CL%
PRINT "DX="; bin(DH% + 0, 8); "_"; bin(DL% + 0, 8); "  DH="; DH%; "  DL="; DL%
END IF
'----- Daten auspacken -----
DriveStatus = ah%
DriveTyp = BL%
'CX:     76543210 76543210
'        ³      ³ ³³ÀÄÄÄÄÁÄÄÄ Anz. Sektoren
'        ³      ³ ÀÁÄÄÄÄÄÄÄÄÄ HighBits of Anz. Cylinder
'        ÀÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄ LowBits of Anz. Cylinder
CL$ = bin(CL% + 0, 8)
maxSect% = bin2dez(MID$(CL$, 3))
maxCyl& = CH% + bin2dez(LEFT$(CL$, 2)) * 256
maxHead% = DH% + 1
maxDrive = DL%
'----- Daten anzeigen -----
IF Show > 1 THEN
	PRINT "Fehlerstatus="; DriveStatus; " [AX]"
	PRINT "DriveNum=    "; DriveNr%; "(von"; maxDrive; ")"
	PRINT "Cyinder=     "; maxCyl& + 1; " [CH]"
	PRINT "Sectors=     "; maxSect%; " [CL]"
	PRINT "Heads=       "; maxHead%; " [DH]"
	IF DriveType THEN
		PRINT "DriveTyp=    "; DriveTyp; " [BL] (";
		SELECT CASE DriveTyp
			CASE 1: PRINT "5.25"; CHR$(34); " 360 KB)"
			CASE 2: PRINT "5.25"; CHR$(34); " 1.2 MB)"
			CASE 3: PRINT "3.5"; CHR$(34); "  720 KB)"
			CASE 4: PRINT "3.5"; CHR$(34); " 1.44 MB)"
			CASE ELSE:
				PRINT ; "???) [" + LTRIM$(STR$(DriveTyp)) + "]"
		END SELECT
	END IF
END IF



FUNCTION LBA& (Cyl&, Head%, Sect%) 'CHS --> LBA umrechnen
LBA& = Cyl& * maxHead% * maxSect% + Head% * maxSect% + Sect%
END FUNCTION



SUB PartitionsTabelle
readSector 0, 0, 1 'Part.-Table, muá mit $55AA (dez 85 170) enden
IF ASC(MID$(Buffer$, 511)) <> 85 OR ASC(MID$(Buffer$, 512)) <> 170 THEN
	PRINT "Lauferk "; Drive$; ": keine Partitions-Tabelle gefunden !!!"
	END
END IF
StartPos% = 446
such.Partitionen:
 IF StartPos% + 15 > LEN(Buffer$) THEN
 PRINT "Lauferk "; Drive$; ": keine Partition gefunden !!!"
 END
 END IF
 sysID% = ASC(MID$(Buffer$, StartPos% + 5, 1))
 IF sysID% > 0 THEN
	 ptc% = ptc% + 1
	 pt.id%(ptc%) = sysID%
	 active% = ASC(Buffer$)
	 IF active% THEN act.part% = ptc%
	 PRINT sysID%; "("; STR$(ASC(Buffer$)); ")"
' END IF
 ELSE
 StartPos% = StartPos% + 16
 
 IF StartPos% + 16 < LEN(Buffer$) THEN GOTO such.Partitionen
		END IF

StartHead% = BufferBytes(StartPos% + 2, 1)
StartSect% = BufferBytes(StartPos% + 3, 1)
StartCyl& = BufferBytes(StartPos% + 4, 1)
endhead% = BufferBytes(StartPos% + 6, 1)
endsect% = BufferBytes(StartPos% + 7, 1)
endCyl& = BufferBytes(StartPos% + 8, 1)
IF Show THEN
PRINT "Lauferk "; Drive$; ": Start lt. MBR="; CHS.Show$(StartCyl&, StartHead%, StartSect%);
END IF
END SUB

SUB readSector (CylNr&, HeadNr%, SectNr%)
' einlesen eines Festplatten-Sektor's (512 Bytes) in Buffer$
restart:
ClearReg
reg.AX = CVI(CHR$(1) + CHR$(2)) '1 Sektor, Int13-Fnc=02 (readSector)
'CX:     76543210 76543210
'        ³      ³ ³³ÀÄÄÄÄÁÄÄÄ Sektor-Nr
'        ³      ³ ÀÁÄÄÄÄÄÄÄÄÄ HighBits Cylinder-Nr
'        ÀÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄ LowBits Cylinder-Nr
CH% = INT(CylNr& / 256)
CX$ = bin$((CylNr& - CH% * 256), 8) + bin$(CH% + 0, 2) + bin$(SectNr% + 0, 6)
CX& = bin2dez(CX$): IF CX& > 32767 THEN CX& = CX& - 65536
reg.CX = CX&
reg.DX = CVI(CHR$(Drive%) + CHR$(HeadNr%))
reg.ES = VARSEG(Buffer)
reg.BX = VARPTR(Buffer)
CALL INTERRUPTX(&H13, reg, reg)
AX$ = MKI$(reg.AX): AL% = ASC(AX$): ah% = ASC(MID$(AX$, 2))
IF ah% THEN
	PRINT "read Sector "; CHS.Show$(CylNr&, HeadNr%, SectNr%); ": Fehler "; ah%
	IF ah% = 4 AND ErrCnt% < 5 THEN
		ErrCnt% = ErrCnt% + 1
		GOTO restart
	END IF


	END
END IF

'     IF ((Reg.flags AND 2048) > 0 AND (Reg.flags AND 128) = 0) THEN
'        PRINT "Disk not found in drive "; CHR$(65 + DriveNum); ":"
'        END
'     END IF
IF Show THEN
OPEN "HD.blk" FOR OUTPUT AS #9
PRINT #9, "CHS= "; CHS.Show$(CylNr&, HeadNr%, SectNr%); " (LBA="; LBA(CylNr&, HeadNr%, SectNr%); ")"
PRINT #9, Buffer
CLOSE #9
END IF
END SUB


viel Glück !!!

Re: master file table MFT auslesen

Verfasst: 31.08.2013 20:44
von derschutzhund
Danke, ist doch schon mal ein Anfang!

Es geht um ein Programm für die schnelle Suche nach Dateien auf einer Festplatte!
Es gibt das Programm "Suche Everything" das unschlagbar schnell die gesamte Festplatte scannt daraus eine Datenbank erzeugt. Die anschließende Suche nach Dateinamen läuft dann in Echtzeit!
Diese Suchgeschwindigkeit (200 GB mit 500.000 Dateien werden in 30 Sek. durchsucht) ist wohl nur zu erreichen wenn man die Dateinamen aus dem MFT liest.

Re: master file table MFT auslesen

Verfasst: 31.08.2013 23:30
von sibru
Oops, falsches Pferd...
Der obrige Code befasst sich sich mit dem MBR (MasterBootRecord), in dem die Daten von Partitionen
(AnfangsSektorAdrsse, Länge, BetriebsSystem...ect) enthalten ist...
Sorry, nicht so richtig gelesen...

Re: master file table MFT auslesen

Verfasst: 01.09.2013 10:22
von derschutzhund
Hallöchen,

bin immer noch dabei einen Ansatz zu finden und dazu habe ich mich mal auf der Seite von "suche Everything" umgesehen.
Im Forum habe ich etwas interessantes gefunden:

http://forum.voidtools.com/viewforum.ph ... faeb44be31

Da gibt es eine C# everything.dll hier der Link: http://forum.voidtools.com/viewtopic.php?f=10&t=541

Hier ist die dll in einem Clarionprojekt
http://support.voidtools.com/Everything/Clarion

Kann man diese C# dll in Purebasic einbinden?
Das wäre ideal, denn dann hätten wir eine tuboschnelle Suchfunktion!!

Wenn die Einbindung in Windows grundsätzlich möglich ist, wie sieht es dann aus wenn es unter Linux compiliert wird?

Bin schon auf eure Antwort gespannt!

LG

Wolfgang

Re: master file table MFT auslesen

Verfasst: 01.09.2013 11:10
von Kiffi
so, wie ich das sehe, ist das eine normale C-DLL (also kein C#).
Sollte also kein großes Problem sein, sie von PB aus aufzurufen.

Das SDK ist allerdings von 2009...

Grüße ... Kiffi

Re: master file table MFT auslesen

Verfasst: 01.09.2013 11:18
von derschutzhund
Ist doch schon mal super! ... und was sind schon 4 Jahre :wink:
Das wäre erst mal ein Einstieg und vielleicht gibt es ja etwas das neuer ist, falls erforderlich.
Du hattest vor Jahren auch schon mal so eine Frage zum MFT gestellt glaube ich?
Hast du das dann eingestellt?

Wenn ich das richtig verstanden habe dann kann man mit einer dll nichts unter Linux anfangen?

Re: master file table MFT auslesen

Verfasst: 01.09.2013 11:38
von Kiffi
derschutzhund hat geschrieben:Du hattest vor Jahren auch schon mal so eine Frage zum MFT gestellt glaube ich?
Hast du das dann eingestellt?
joh, war 2006. Hatte eine ähnliche Idee wie Du jetzt ;-)
Habe ich dann aber doch sein lassen, weil mir das zu
kompliziert war (Es gab damals auch kein SDK).
derschutzhund hat geschrieben:Wenn ich das richtig verstanden habe dann kann man mit einer dll nichts unter Linux anfangen?
Mit Windows-DLLs kannst Du unter Linux nichts anfangen. Das ist korrekt.
Allerdings könnte man unter Linux AFAIK aus dem C-Source des SDK eine
SO-Datei generieren, welche dann das DLL-Pendant wäre. Das müssten
Dir allerdings die C-Experten hier genauer erklären können...

Grüße ... Kiffi

Re: master file table MFT auslesen

Verfasst: 01.09.2013 12:33
von _JON_
Die everything SDK ist nur zum fernsteuern von everything in anderen Programmen, nix mehr.

Du müsstest wohl oder übel selbst einen $MFT Parser basteln.
2 bis 3 Monate solltest aber einplanen :mrgreen:

Re: master file table MFT auslesen

Verfasst: 01.09.2013 12:35
von Kiffi
_JON_ hat geschrieben:Die everything SDK ist nur zum fernsteuern von everything in anderen Programmen, nix mehr.
oha! :shock: Okeee, falsch gedacht.

Nix für ungut ... Kiffi