The control codes that return update sequence number (USN) change journal records,
FSCTL_READ_USN_JOURNAL and
FSCTL_ENUM_USN_DATA, return similar data in the output
buffer. Both return a USN followed by zero or more change journal records, each in a
USN_RECORD_V2 or
USN_RECORD_V3 structure.
The target volume for USN operations must be ReFS or NTFS 3.0 or later. To obtain the NTFS version of a volume,
open a command prompt with Administrator access rights and execute the following command:
FSUtil.exe FSInfo NTFSInfo X:
where X is the drive letter of the volume.
The following list identifies ways to get change journal records:
- Use FSCTL_ENUM_USN_DATA to get a listing
(enumeration) of all change journal records between two USNs.
- Use FSCTL_READ_USN_JOURNAL to be more
selective, such as selecting specific reasons for changes or returning when a file is closed.
Note Both of these operations return only the subset of change journal records that meet the specified
criteria.
The USN returned as the first item in the output buffer is the USN of the next record number to be retrieved.
Use this value to continue reading records from the end boundary forward.
The FileName member of
USN_RECORD_V2 or
USN_RECORD_V3 contains the name of the file to which the
record in question applies. The file name varies in length, so
USN_RECORD_V2 and
USN_RECORD_V3 are variable length structures. Their first
member, RecordLength, is the length of the structure (including the file name), in
bytes.
When you work with the FileName member of
USN_RECORD_V2 and
USN_RECORD_V3 structures, do not assume that the file name
contains a trailing '\0' delimiter. To determine the length of the file name, use
the FileNameLength member.
The following example calls
FSCTL_READ_USN_JOURNAL and walks the buffer of
change journal records that the operation returns.
#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);
}
The size in bytes of any record specified by a
USN_RECORD_V2 or
USN_RECORD_V3 structure is at most
((MaxComponentLength - 1) * Width) + Size where
MaxComponentLength is the maximum length in characters of the record file name. The
width is the size of a wide character, and the Size is the size of the structure.
To obtain the maximum length, call the
GetVolumeInformation function and examine the
value pointed to by the lpMaximumComponentLength parameter. Subtract one from
MaxComponentLength to account for the fact that the definition of
USN_RECORD and
USN_RECORD_V3 includes one character of the file
name.
In the C programming language, the largest possible record size is the following:
(MaxComponentLength - 1) * sizeof(WCHAR) + sizeof(USN_RECORD)
Send comments about this topic to Microsoft
Build date: 4/17/2012