Condividi tramite


Passaggio di un buffer di record del journal delle modifiche

I codici di controllo che restituiscono il numero di sequenza di aggiornamento (USN) modificano i record del journal, FSCTL_READ_USN_JOURNAL e FSCTL_ENUM_USN_DATA, restituiscono dati simili nel buffer di output. Entrambi restituiscono un USN seguito da zero o più record del journal delle modifiche, ognuno in una struttura USN_RECORD_V2 o USN_RECORD_V3.

Il volume di destinazione per le operazioni USN deve essere ReFS o NTFS 3.0 o versione successiva. Per ottenere la versione NTFS di un volume, aprire un prompt dei comandi con diritti di accesso amministratore ed eseguire il comando seguente:

FSUtil.exe FSInfo NTFSInfo X**:**

dove X è la lettera di unità del volume.

L'elenco seguente identifica i modi per ottenere i record del journal delle modifiche:

  • Usare FSCTL_ENUM_USN_DATA per ottenere un elenco (enumerazione) di tutti i record del journal delle modifiche tra due USN.
  • Usare FSCTL_READ_USN_JOURNAL per essere più selettivi, ad esempio la selezione di motivi specifici per le modifiche o la restituzione quando un file viene chiuso.

Nota

Entrambe queste operazioni restituiscono solo il subset di record del journal delle modifiche che soddisfano i criteri specificati.

 

L'USN restituito come primo elemento nel buffer di output è l'USN del numero di record successivo da recuperare. Usare questo valore per continuare a leggere i record dal limite finale in avanti.

Il membro FileName di USN_RECORD_V2 o USN_RECORD_V3 contiene il nome del file a cui si applica il record in questione. Il nome del file varia in lunghezza, quindi USN_RECORD_V2 e USN_RECORD_V3 sono strutture a lunghezza variabile. Il primo membro, RecordLength, è la lunghezza della struttura (incluso il nome del file), in byte.

Quando si lavora con il membro FileName delle strutture USN_RECORD_V2 e USN_RECORD_V3, non si presuppone che il nome del file contenga un delimitatore finale '\0'. Per determinare la lunghezza del nome file, utilizzare il membro FileNameLength .

Nell'esempio seguente viene chiamato FSCTL_READ_USN_JOURNAL e viene illustrato il buffer dei record del journal delle modifiche restituiti dall'operazione.

#include <Windows.h>
#include <WinIoCtl.h>
#include <stdio.h>

#define BUF_LEN 4096

void main()
{
   HANDLE hVol;
   CHAR Buffer[BUF_LEN];

   USN_JOURNAL_DATA JournalData;
   READ_USN_JOURNAL_DATA ReadData = {0, 0xFFFFFFFF, FALSE, 0, 0};
   PUSN_RECORD UsnRecord;  

   DWORD dwBytes;
   DWORD dwRetBytes;
   int I;

   hVol = CreateFile( TEXT("\\\\.\\c:"), 
               GENERIC_READ | GENERIC_WRITE, 
               FILE_SHARE_READ | FILE_SHARE_WRITE,
               NULL,
               OPEN_EXISTING,
               0,
               NULL);

   if( hVol == INVALID_HANDLE_VALUE )
   {
      printf("CreateFile failed (%d)\n", GetLastError());
      return;
   }

   if( !DeviceIoControl( hVol, 
          FSCTL_QUERY_USN_JOURNAL, 
          NULL,
          0,
          &JournalData,
          sizeof(JournalData),
          &dwBytes,
          NULL) )
   {
      printf( "Query journal failed (%d)\n", GetLastError());
      return;
   }

   ReadData.UsnJournalID = JournalData.UsnJournalID;

   printf( "Journal ID: %I64x\n", JournalData.UsnJournalID );
   printf( "FirstUsn: %I64x\n\n", JournalData.FirstUsn );

   for(I=0; I<=10; I++)
   {
      memset( Buffer, 0, BUF_LEN );

      if( !DeviceIoControl( hVol, 
            FSCTL_READ_USN_JOURNAL, 
            &ReadData,
            sizeof(ReadData),
            &Buffer,
            BUF_LEN,
            &dwBytes,
            NULL) )
      {
         printf( "Read journal failed (%d)\n", GetLastError());
         return;
      }

      dwRetBytes = dwBytes - sizeof(USN);

      // Find the first record
      UsnRecord = (PUSN_RECORD)(((PUCHAR)Buffer) + sizeof(USN));  

      printf( "****************************************\n");

      // This loop could go on for a long time, given the current buffer size.
      while( dwRetBytes > 0 )
      {
         printf( "USN: %I64x\n", UsnRecord->Usn );
         printf("File name: %.*S\n", 
                  UsnRecord->FileNameLength/2, 
                  UsnRecord->FileName );
         printf( "Reason: %x\n", UsnRecord->Reason );
         printf( "\n" );

         dwRetBytes -= UsnRecord->RecordLength;

         // Find the next record
         UsnRecord = (PUSN_RECORD)(((PCHAR)UsnRecord) + 
                  UsnRecord->RecordLength); 
      }
      // Update starting USN for next call
      ReadData.StartUsn = *(USN *)&Buffer; 
   }

   CloseHandle(hVol);

}

La dimensione in byte di qualsiasi record specificato da una struttura USN_RECORD_V2 o USN_RECORD_V3 è al massimo ((MaxComponentLength - 1) * Width) + Size in cui MaxComponentLength è la lunghezza massima in caratteri del nome del file di record. La larghezza è la dimensione di un carattere wide e size è la dimensione della struttura.

Per ottenere la lunghezza massima, chiamare la funzione GetVolumeInformation ed esaminare il valore a cui punta il parametro lpMaximumComponentLength . Sottrarre uno da MaxComponentLength per tenere conto del fatto che la definizione di USN_RECORD e USN_RECORD_V3 include un carattere del nome file.

Nel linguaggio di programmazione C, la dimensione massima possibile del record è la seguente:

(MaxComponentLength - 1) * sizeof(WCHAR) + sizeof(USN_RECORD)