Внедрение журнала изменений в Delphi (шаг 2)

Продолжая свой предыдущий вопрос, я смог использовать этот модуль delphi для реализации сумасшедшего сканирования дисков FAST с помощью этой функции EnumMFTEntries(), но у меня возникли проблемы при выполнении следующих задач:

Задача № 1: Запрос change journal чтобы получить недавно измененные файлы (измененные, переименованные, удаленные и т. д.)

Я адаптировал эту нарушенную рутину после прочтения EnumMFTEntries() функции, а также в USN Journal Explorer от StCroixSkipper (в C#).

По некоторым причинам сообщаемые имена файлов всегда #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;

Задача № 2: Ограничить сканирование определенной папкой?

Если я не ошибаюсь, представляется возможным частично сделать это, определив StartUsn в функции EnumMFTEntries(), но не ясно, как это сделать.

Задача № 3: Получить полный путь к имени файла?

Например, EnumMFTEntries() всегда возвращайте только имя вместе с номером ссылки на родительскую папку, не ясно, какой самый быстрый способ получить полный путь.


Я надеюсь, что я не слишком многого требую, эти задачи действительно тесно связаны, я очень надеюсь, что сообщество поможет здесь облегчить разработчикам на Delphi безумное быстрое сканирование папок. Несмотря на свою полезность, журнал изменений / MFT является одной из самых интересных, но забытых технологий. Это должно измениться!

1 ответ

Решение

В задаче № 2: вы можете ограничить поиск данных usn определенным файлом /dir, сначала отправив FSCTL_READ_FILE_USN_DATA, чтобы получить номер последнего изменения usn, а затем FSTCL_READ_USN_JOURNAL с членом StartUsn, назначенным этому номеру usn, чтобы получить действительную информацию об изменении (timrstamp, причина). Однако только последнее изменение может быть получено таким образом. Чтобы получить все изменения, я думаю, что можно фильтровать только прочитанные данные журнала usn по определенному номеру файла. Больше информации в библиотеке MSDN.

Другие вопросы по тегам