Continuing my previous question , I was able to use this delphi block to implement a crazy FAST scan using this EnumMFTEntries () function , but I am having problems with the following tasks:
Task # 1: Request change journal to get new changed files (modified, renamed, deleted, etc.)
I adapted this broken procedure after reading the EnumMFTEntries() function as well as the StCroixSkipper USN Journal Explorer (in C #).
For some reason, message file names are always # 0
function EnumUsnEntries(ARootHandle : Cardinal; AMFTEnumBuff : Pointer; EnumCallBack : TMFTEnumCallback) : Boolean; var P : Pointer; UsnEnum : Pointer; BytesRet : Cardinal; PUSN : PUSNRecord; ReadUSN : TReadUSNJournalData; PReadUSN : PReadUSNJournalData; UsnJournalData : TUSNJournalData; BUF_SIZE : Integer; begin Result := False; if (ARootHandle = INVALID_HANDLE_VALUE) OR (AMFTEnumBuff = nil) then Exit; QueryUSNJournal(ARootHandle, UsnJournalData); with ReadUSN do begin StartUsn := UsnJournalData.NextUsn; ReasonMask := USN_REASON_DATA_OVERWRITE OR USN_REASON_DATA_EXTEND OR USN_REASON_NAMED_DATA_OVERWRITE OR USN_REASON_NAMED_DATA_TRUNCATION OR USN_REASON_FILE_CREATE OR USN_REASON_FILE_DELETE OR USN_REASON_EA_CHANGE OR USN_REASON_SECURITY_CHANGE OR USN_REASON_RENAME_OLD_NAME OR USN_REASON_RENAME_NEW_NAME OR USN_REASON_INDEXABLE_CHANGE OR USN_REASON_BASIC_INFO_CHANGE OR USN_REASON_HARD_LINK_CHANGE OR USN_REASON_COMPRESSION_CHANGE OR USN_REASON_ENCRYPTION_CHANGE OR USN_REASON_OBJECT_ID_CHANGE OR USN_REASON_REPARSE_POINT_CHANGE OR USN_REASON_STREAM_CHANGE OR USN_REASON_CLOSE; ReturnOnlyOnClose := 0; Timeout := 0; BytesToWaitFor := 0; UsnJournalID := UsnJournalData.UsnJournalID; end; // with BUF_SIZE := SizeOf(ReadUSN); GetMem(P, BUF_SIZE); try ZeroMemory(P, BUF_SIZE); while DeviceIoControl(ARootHandle, FSCTL_READ_USN_JOURNAL, Addr(ReadUSN){UsnEnum}, SizeOf(ReadUSN{TReadUSNJournalData}), P, BUF_SIZE, BytesRet, nil) do begin PUSN := PUSNRecord{PReadUSNJournalData}(Integer(P) + SizeOf(Int64)); while (BytesRet > 0{60}) do begin if Not EnumCallBack(PUSN, nil{Extra}) then Exit; if PUSN.RecordLength > 0 then Dec(BytesRet, PUSN.RecordLength) else Break; PUSN := PUSNRecord(Cardinal(PUSN) + PUSN.RecordLength); end; // while CopyMemory(UsnEnum{MFTEnum}, P, SizeOf(Int64)); end; // while Result := True; finally FreeMem(P); end; // try/finally end;
Task number 2: Limit the scan in a specific folder?
If I'm not mistaken, it is possible, in part, to do this by specifying StartUsn in EnumMFTEntries () but it is not clear how to do this.
Task number 3: Get the full path to the file name?
For example, EnumMFTEntries() always returns only the name, together with its parent folder number, it does not understand what is the fastest way to get the full path.
I hope that I do not ask too much, these tasks are really closely related, I really really hope that the community will help here so that Delphi developers can easily achieve an insanely fast folder scan. Despite its usefulness, the change log / MFT is one of the most interesting but forgotten technologies. That must change!
Thedude
source share