Мониторинг удалений и изменений на томе NTFS с помощью MFT_ENUM_DATA

Я использую этот код для заполнения базы данных всех файлов на диске:

TCHAR szVolumePath[_MAX_PATH] = L"\\\\.\\d:";

HANDLE hDrive = CreateFile(szVolumePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL);

MFT_ENUM_DATA_V0 med = { 0 };
med.StartFileReferenceNumber = 0;
med.LowUsn = 0;
med.HighUsn = MAXLONGLONG;

DWORD cb;
PUSN_RECORD pRecord;

unsigned char pData[sizeof(DWORDLONG) + 0x10000] = { 0 }; 

while (DeviceIoControl(hDrive, FSCTL_ENUM_USN_DATA, &med, sizeof(med), pData, sizeof(pData), &cb, NULL) != FALSE)
{
    pRecord = (PUSN_RECORD)&pData[sizeof(USN)];
    while ((PBYTE)pRecord < (pData + cb))
    {
        wstring sz((LPCWSTR)(PBYTE)pRecord + pRecord->FileNameOffset, pRecord->FileNameLength / sizeof(WCHAR));

        // file the database

        pRecord = (PUSN_RECORD)((PBYTE)pRecord + pRecord->RecordLength);
    }
    med.StartFileReferenceNumber = *(DWORDLONG *)pData;
}

Как только цикл завершен, база данных успешно заполнена.

Но как продолжить (в качестве фоновой задачи) отслеживать в реальном времени изменения / удаления файлов? (пример: отобразить MessageBox() "Файл readme.txt был переименован.")

Должен ли я перезапускать такой цикл каждую 1 секунду, с med.StartFileReferenceNumber = самый высокий FileReferenceNumber, который вы видели раньше?


Примечание: я немного не хочу запускать этот код каждую 1 секунду (99% времени, даром). Делая это каждые 10 секунд, вы избежите использования такого большого количества ресурсов, но перед обнаружением изменений будет задержка, в то время как я знаю некоторые программы индексирования, которые не имеют такой задержки.

Примечание 2: я прочитал Как я могу обнаружить только удаленные, измененные и созданные файлы на томе? но цель основного ответа - запустить его один раз, а не постоянно в фоновом режиме.

Примечание 3: Я посмотрел на этот полезный пример кода от Microsoft, следящего за вашими дисками NTFS: объяснение журнала изменений Windows 2000.

Примечание 4: Должен ли я сохранить FSCTL_ENUM_USN_DATA для начальной загрузки базы данных, а затем использовать вместо него FSCTL_READ_USN_JOURNAL?

Note5: ReadDirectoryChangesW или же FindNextChangeNotification (первый дает полный путь изменений в уведомлениях, второй нет) не может быть использован, потому что он не даст FileReferenceNumber удаленного файла (нужно открыть файл и использовать NtQueryInformationFile получить это; но это невозможно для удаленных файлов); и FileReferenceNumber необходим для обновления файловой базы данных (файловая база данных использует карту / словарь с FileReferenceNumber s в качестве ключей).

0 ответов

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