7

前の質問の続きで、このDelphi ユニットを使用して、このEnumMFTEntries() 関数を使用してクレイジーな FAST ドライブ スキャンを実装することができましたが、次のタスクを実行するのに問題があります。

タスク 1: クエリを実行change journalして、新しく変更されたファイル (変更、名前変更、削除など) を取得します。

関数と StCroixSkipper の USN Journal Explorer (C#)の両方を読んだ後、この壊れたルーチンを適応させました。EnumMFTEntries()

何らかの理由で報告されたファイル名は常に #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: スキャンを特定のフォルダーに制限しますか?

私が間違っていなければ、EnumMFTEntries()関数でを定義することで部分的にそうすることができるようですが、それを行う方法は明確ではありません。StartUsn

タスク #3: ファイル名のフル パスを取得しますか?

たとえば、 はEnumMFTEntries()常に名前のみを返し、その親フォルダーの参照番号も返すため、フル パスを取得する最速の方法は明確ではありません。


これらのタスクは非常に密接に関連しています。Delphi開発者が非常に高速なフォルダ スキャンを簡単に実行できるようにするために、コミュニティがここで役立つことを願っています。その有用性にもかかわらず、変更ジャーナル/MFT は、最も興味深いが忘れられているテクノロジの 1 つです。これは変わらなければなりません!

4

1 に答える 1

2

タスク #2: 最初に FSCTL_READ_FILE_USN_DATA を発行して最後の変更の usn 番号を取得し、次にその usn 番号に割り当てられた StartUsn メンバーを使用して FSTCL_READ_USN_JOURNAL を発行して、変更に関する有効な情報を取得することにより、usn データ検索を特定のファイル/ディレクトリに制限できます (timrstamp、理由)。ただし、この方法で取得できるのは最後の変更のみです。すべての変更を取得するには、特定のファイル参照番号で読み取り usn ジャーナル データをフィルタリングすることしかできないと思います。詳細については、MSDN ライブラリを参照してください。

于 2013-01-30T06:00:19.730 に答える