Implement the change log in Delphi (step 2)

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!

+7
source share
1 answer

To task # 2: you can restrict the search for usn data to a specific / dir file by first issuing FSCTL_READ_FILE_USN_DATA to get the number of the last change, and then FSTCL_READ_USN_JOURNAL with the StartUsn member assigned to this usn to get reliable information about the change (timrstamp, reason). However, only the last change can be obtained in this way. To get all the changes, I think that it is possible to filter only usn log data by a specific file reference number. Additional information in the MSDN library.

+2
source

All Articles