Blog

USN Journal i ExportFromUSN

Wyszukiwanie plików w Eksploratorze Windows jest zepsute. Wchodzę na "Ten komputer", wpisuję nazwę pliku i czekam. I czekam. Irytujące.

Chciałem zrobić coś na wzór uproszczonego Everything z ładniejszym UI. Żeby to osiągnąć, musiałem zrozumieć jak Everything działa tak szybko.

Co to USN Journal?

USN Journal (Update Sequence Number Journal) to wbudowany mechanizm NTFS, który rejestruje każdą zmianę w systemie plików. Każdy plik i folder na dysku NTFS ma swój unikalny numer referencyjny (File Reference Number, FRN). Journal zapisuje co się zmieniło i kiedy.

Zamiast skanować cały dysk plik po pliku, można poprosić system o listę wszystkich rekordów z Master File Table (MFT). To właśnie robi plik ExportFromUSN.cpp w moim projekcie FileFinder.

winioctl.h i kody FSCTL

Aby komunikować się z USN Journal, trzeba użyć funkcji DeviceIoControl z Windows API. Nagłówek winioctl.h definiuje kody sterujące (FSCTL), które mówią systemowi co chcemy zrobić:

  • FSCTL_ENUM_USN_DATA – enumeruje rekordy MFT, zwraca listę wszystkich plików i folderów na dysku.
  • FSCTL_READ_USN_JOURNAL – czyta zmiany z journala w czasie rzeczywistym.
  • FSCTL_QUERY_USN_JOURNAL – sprawdza status journala (czy istnieje, jaki ma zakres USN).

Struktury danych

Windows API oferuje kilka wersji struktur do pracy z USN Journal:

MFT_ENUM_DATA

Struktura wejściowa dla FSCTL_ENUM_USN_DATA. Określa zakres USN i od którego numeru FRN zacząć enumerację. Przy pierwszym wywołaniu StartFileReferenceNumber ustawiam na 0, a przy kolejnych używam wartości zwróconej z poprzedniego wywołania.

USN_RECORD

Rekord zwracany przez system. Istnieje kilka wersji:

  • USN_RECORD_V2 – najczęściej używana, zawiera FRN, ParentFRN, nazwę pliku, atrybuty.
  • USN_RECORD_V3 – używa 128-bitowych FRN (dla ReFS i nowszych wersji Windows).
  • USN_RECORD_V4 – dodatkowe informacje o zakresach zmian.

W moim projekcie używam V2, bo wystarcza do NTFS i jest prostsza w obsłudze. Pole MajorVersion w rekordzie mówi którą wersję dostaliśmy.

Jak działa ExportFromUSN

Plik wykonuje następujące kroki:

  1. Otwiera uchwyt do dysku (CreateFile na \\.\C:).
  2. Sprawdza czy USN Journal istnieje (FSCTL_QUERY_USN_JOURNAL).
  3. W pętli wywołuje FSCTL_ENUM_USN_DATA, za każdym razem przesuwając StartFileReferenceNumber.
  4. Dla każdego rekordu wyciąga FRN, ParentFRN i nazwę pliku.
  5. Zapisuje dane do pliku CSV (później konwertowanego na SQLite).

Cały skan dysku z milionami plików trwa kilka sekund. Dla porównania, rekurencyjne przechodzenie przez FindFirstFile/FindNextFile trwałoby minuty.

Wersje struktur

Microsoft dodaje nowe wersje struktur w kolejnych wersjach Windows. Przy wyborze wersji trzeba pamiętać o kompatybilności:

  • USN_JOURNAL_DATA_V0, V1, V2 – różne wersje metadanych journala.
  • USN_RECORD_V2, V3, V4 – różne formaty rekordów.

Używam V2 bo działa na Windows 7+ i nie potrzebuję 128-bitowych FRN.

Więcej o projekcie: FileFinder