You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
791 lines
20 KiB
791 lines
20 KiB
/*++
|
|
|
|
Copyright (c) 2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
usn.c
|
|
|
|
Abstract:
|
|
|
|
This file contains code for commands that affect
|
|
the usn journal.
|
|
|
|
Author:
|
|
|
|
Wesley Witt [wesw] 1-March-2000
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include <precomp.h>
|
|
|
|
|
|
#define MAX_USN_DATA 4096
|
|
|
|
//
|
|
// Arguments and lengths
|
|
//
|
|
|
|
#define ARG_MAXSIZE L"m="
|
|
#define ARG_MAXSIZE_LEN 2
|
|
|
|
#define ARG_ALLOCDELTA L"a="
|
|
#define ARG_ALLOCDELTA_LEN 2
|
|
|
|
|
|
INT
|
|
UsnHelp(
|
|
IN INT argc,
|
|
IN PWSTR argv[]
|
|
)
|
|
{
|
|
DisplayMsg( MSG_USAGE_USN );
|
|
return EXIT_CODE_SUCCESS;
|
|
}
|
|
|
|
__inline PUSN_RECORD
|
|
NextUsnRecord(
|
|
const PUSN_RECORD input
|
|
)
|
|
{
|
|
ULONGLONG output;
|
|
|
|
// Get the base address of the current record.
|
|
(PUSN_RECORD) output = input;
|
|
|
|
// Add the size of the record (structure + file name after the end
|
|
// of the structure).
|
|
output += input->RecordLength;
|
|
|
|
// Round up the record size to match the 64-bit alignment, if the
|
|
// size is not already a multiple of 8. Perform a bitwise AND
|
|
// operation here instead of division because it is much faster than
|
|
// division. However, the bitwise AND operation only works because
|
|
// the divisor 8 is a power of 2.
|
|
|
|
if (output & 8-1) {
|
|
// Round down to nearest multiple of 8.
|
|
output &= -8;
|
|
// Then add 8.
|
|
output += 8;
|
|
}
|
|
|
|
return((PUSN_RECORD) output);
|
|
}
|
|
|
|
VOID
|
|
DisplayUsnRecord(
|
|
const PUSN_RECORD UsnRecord
|
|
)
|
|
{
|
|
|
|
WCHAR DateString[128];
|
|
WCHAR TimeString[128];
|
|
TIME_FIELDS TimeFields;
|
|
SYSTEMTIME SystemTime;
|
|
|
|
RtlTimeToTimeFields(&UsnRecord->TimeStamp, &TimeFields);
|
|
|
|
SystemTime.wYear = TimeFields.Year ;
|
|
SystemTime.wMonth = TimeFields.Month ;
|
|
SystemTime.wDayOfWeek = TimeFields.Weekday ;
|
|
SystemTime.wDay = TimeFields.Day ;
|
|
SystemTime.wHour = TimeFields.Hour ;
|
|
SystemTime.wMinute = TimeFields.Minute ;
|
|
SystemTime.wSecond = TimeFields.Second ;
|
|
SystemTime.wMilliseconds = TimeFields.Milliseconds;
|
|
|
|
|
|
GetDateFormat( LOCALE_USER_DEFAULT,
|
|
DATE_SHORTDATE,
|
|
&SystemTime,
|
|
NULL,
|
|
DateString,
|
|
sizeof( DateString ) / sizeof( DateString[0] ));
|
|
|
|
GetTimeFormat( LOCALE_USER_DEFAULT,
|
|
FALSE,
|
|
&SystemTime,
|
|
NULL,
|
|
TimeString,
|
|
sizeof( TimeString ) / sizeof( TimeString[0] ));
|
|
|
|
DisplayMsg(
|
|
MSG_USNRECORD,
|
|
UsnRecord->MajorVersion,
|
|
UsnRecord->MinorVersion,
|
|
QuadToPaddedHexText( UsnRecord->FileReferenceNumber ),
|
|
QuadToPaddedHexText( UsnRecord->ParentFileReferenceNumber ),
|
|
QuadToPaddedHexText( UsnRecord->Usn ),
|
|
QuadToPaddedHexText( UsnRecord->TimeStamp.QuadPart ),
|
|
TimeString, DateString,
|
|
UsnRecord->Reason,
|
|
UsnRecord->SourceInfo,
|
|
UsnRecord->SecurityId,
|
|
UsnRecord->FileAttributes,
|
|
UsnRecord->FileNameLength,
|
|
UsnRecord->FileNameOffset,
|
|
UsnRecord->FileNameLength/sizeof(WCHAR),
|
|
UsnRecord->FileName
|
|
);
|
|
}
|
|
|
|
|
|
INT
|
|
CreateUsnJournal(
|
|
IN INT argc,
|
|
IN PWSTR argv[]
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine create the USN journal for the volume specified.
|
|
|
|
Arguments:
|
|
|
|
argc - The argument count.
|
|
argv - Array of Strings of the form :
|
|
' fscutl crusnj m=<max-value> a=<alloc-delta> <volume pathname>'.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
HANDLE FileHandle = INVALID_HANDLE_VALUE;
|
|
WCHAR FileName[MAX_PATH];
|
|
BOOL Status;
|
|
DWORD BytesReturned;
|
|
CREATE_USN_JOURNAL_DATA InBuffer;
|
|
ULONGLONG MaxSize;
|
|
ULONGLONG AllocDelta;
|
|
PWSTR EndPtr;
|
|
INT ExitCode = EXIT_CODE_SUCCESS;
|
|
|
|
try {
|
|
|
|
if (argc != 3) {
|
|
DisplayMsg( MSG_USAGE_CREATEUSN );
|
|
if (argc != 0) {
|
|
ExitCode = EXIT_CODE_FAILURE;
|
|
}
|
|
leave;
|
|
}
|
|
|
|
if (!IsVolumeLocalNTFS( argv[2][0] )) {
|
|
DisplayMsg( MSG_NTFS_REQUIRED );
|
|
ExitCode = EXIT_CODE_FAILURE;
|
|
leave;
|
|
}
|
|
|
|
if (wcslen( DotPrefix ) + wcslen( argv[2] ) + 1 > MAX_PATH) {
|
|
DisplayMsg( MSG_FILENAME_TOO_LONG );
|
|
ExitCode = EXIT_CODE_FAILURE;
|
|
leave;
|
|
}
|
|
|
|
wcscpy( FileName, DotPrefix );
|
|
wcscat( FileName, argv[2] );
|
|
|
|
FileHandle = CreateFile(
|
|
FileName,
|
|
GENERIC_WRITE,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL
|
|
);
|
|
if (FileHandle == INVALID_HANDLE_VALUE) {
|
|
DisplayError();
|
|
ExitCode = EXIT_CODE_FAILURE;
|
|
leave;
|
|
}
|
|
|
|
if (_wcsnicmp( argv[0], ARG_MAXSIZE, ARG_MAXSIZE_LEN)
|
|
|| wcslen( argv[0] ) == ARG_MAXSIZE_LEN) {
|
|
DisplayMsg( MSG_INVALID_PARAMETER, argv[0] );
|
|
DisplayMsg( MSG_USAGE_CREATEUSN );
|
|
ExitCode = EXIT_CODE_FAILURE;
|
|
leave;
|
|
}
|
|
if (_wcsnicmp( argv[1], ARG_ALLOCDELTA, ARG_ALLOCDELTA_LEN)
|
|
|| wcslen( argv[1] ) == ARG_ALLOCDELTA_LEN) {
|
|
DisplayMsg( MSG_INVALID_PARAMETER, argv[1] );
|
|
DisplayMsg( MSG_USAGE_CREATEUSN );
|
|
ExitCode = EXIT_CODE_FAILURE;
|
|
leave;
|
|
}
|
|
|
|
MaxSize = My_wcstoui64( argv[0] + ARG_MAXSIZE_LEN, &EndPtr, 0 );
|
|
if (UnsignedI64NumberCheck( MaxSize, EndPtr )) {
|
|
DisplayMsg( MSG_INVALID_PARAMETER, argv[0] );
|
|
DisplayMsg( MSG_USAGE_CREATEUSN );
|
|
ExitCode = EXIT_CODE_FAILURE;
|
|
leave;
|
|
}
|
|
|
|
AllocDelta = My_wcstoui64( argv[1] + ARG_ALLOCDELTA_LEN, &EndPtr, 0 );
|
|
if (UnsignedI64NumberCheck( AllocDelta, EndPtr )) {
|
|
DisplayMsg( MSG_INVALID_PARAMETER, argv[1] );
|
|
DisplayMsg( MSG_USAGE_CREATEUSN );
|
|
ExitCode = EXIT_CODE_FAILURE;
|
|
leave;
|
|
}
|
|
|
|
InBuffer.MaximumSize = MaxSize;
|
|
InBuffer.AllocationDelta = AllocDelta;
|
|
|
|
Status = DeviceIoControl(
|
|
FileHandle,
|
|
FSCTL_CREATE_USN_JOURNAL,
|
|
&InBuffer,
|
|
sizeof(InBuffer),
|
|
NULL,
|
|
0,
|
|
&BytesReturned,
|
|
(LPOVERLAPPED)NULL
|
|
);
|
|
if (!Status) {
|
|
DisplayError();
|
|
ExitCode = EXIT_CODE_FAILURE;
|
|
leave;
|
|
}
|
|
|
|
} finally {
|
|
|
|
if (FileHandle != INVALID_HANDLE_VALUE) {
|
|
CloseHandle( FileHandle );
|
|
}
|
|
|
|
}
|
|
|
|
return ExitCode;
|
|
}
|
|
|
|
|
|
INT
|
|
QueryUsnJournal(
|
|
IN INT argc,
|
|
IN PWSTR argv[]
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine queries the USN journal for the volume specified.
|
|
|
|
Arguments:
|
|
|
|
argc - The argument count.
|
|
argv - Array of Strings of the form :
|
|
' fscutl queryusnj <volume pathname>'.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
HANDLE FileHandle = INVALID_HANDLE_VALUE;
|
|
WCHAR FileName[MAX_PATH];
|
|
BOOL Status;
|
|
DWORD BytesReturned;
|
|
USN_JOURNAL_DATA UsnJournalData;
|
|
INT ExitCode = EXIT_CODE_SUCCESS;
|
|
|
|
try {
|
|
|
|
if (argc != 1) {
|
|
DisplayMsg( MSG_USAGE_QUERYUSN );
|
|
if (argc != 0) {
|
|
ExitCode = EXIT_CODE_FAILURE;
|
|
}
|
|
leave;
|
|
}
|
|
|
|
if (!IsVolumeLocalNTFS( argv[0][0] )) {
|
|
DisplayMsg( MSG_NTFS_REQUIRED );
|
|
ExitCode = EXIT_CODE_FAILURE;
|
|
leave;
|
|
}
|
|
|
|
if (wcslen( DotPrefix ) + wcslen( argv[0] ) + 1 > MAX_PATH) {
|
|
DisplayMsg( MSG_FILENAME_TOO_LONG );
|
|
ExitCode = EXIT_CODE_FAILURE;
|
|
leave;
|
|
}
|
|
|
|
wcscpy( FileName, DotPrefix );
|
|
wcscat( FileName, argv[0] );
|
|
|
|
FileHandle = CreateFile(
|
|
FileName,
|
|
GENERIC_READ,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL
|
|
);
|
|
if (FileHandle == INVALID_HANDLE_VALUE) {
|
|
DisplayError();
|
|
ExitCode = EXIT_CODE_FAILURE;
|
|
leave;
|
|
}
|
|
|
|
Status = DeviceIoControl(
|
|
FileHandle,
|
|
FSCTL_QUERY_USN_JOURNAL,
|
|
NULL,
|
|
0,
|
|
&UsnJournalData,
|
|
sizeof(USN_JOURNAL_DATA),
|
|
&BytesReturned,
|
|
(LPOVERLAPPED)NULL
|
|
);
|
|
if (!Status) {
|
|
DisplayError();
|
|
ExitCode = EXIT_CODE_FAILURE;
|
|
leave;
|
|
}
|
|
|
|
DisplayMsg(
|
|
MSG_QUERYUSN,
|
|
QuadToPaddedHexText( UsnJournalData.UsnJournalID ),
|
|
QuadToPaddedHexText( UsnJournalData.FirstUsn ),
|
|
QuadToPaddedHexText( UsnJournalData.NextUsn ),
|
|
QuadToPaddedHexText( UsnJournalData.LowestValidUsn ),
|
|
QuadToPaddedHexText( UsnJournalData.MaxUsn ),
|
|
QuadToPaddedHexText( UsnJournalData.MaximumSize ),
|
|
QuadToPaddedHexText( UsnJournalData.AllocationDelta )
|
|
);
|
|
|
|
} finally {
|
|
|
|
if (FileHandle != INVALID_HANDLE_VALUE) {
|
|
CloseHandle( FileHandle );
|
|
}
|
|
|
|
}
|
|
|
|
return ExitCode;
|
|
}
|
|
|
|
|
|
INT
|
|
DeleteUsnJournal(
|
|
IN INT argc,
|
|
IN PWSTR argv[]
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine deletes the USN journal for the volume specified.
|
|
|
|
Arguments:
|
|
|
|
argc - The argument count.
|
|
argv - Array of Strings of the form :
|
|
' fscutl delusnj <flags> <volume pathname>'.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
HANDLE FileHandle = INVALID_HANDLE_VALUE;
|
|
WCHAR FileName[MAX_PATH];
|
|
BOOL Status;
|
|
DWORD BytesReturned;
|
|
DELETE_USN_JOURNAL_DATA DeleteUsnJournalData;
|
|
USN_JOURNAL_DATA UsnJournalData;
|
|
INT i;
|
|
INT ExitCode = EXIT_CODE_SUCCESS;
|
|
|
|
try {
|
|
|
|
if (argc < 2) {
|
|
DisplayMsg( MSG_USAGE_DELETEUSN );
|
|
if (argc != 0) {
|
|
ExitCode = EXIT_CODE_FAILURE;
|
|
}
|
|
leave;
|
|
}
|
|
|
|
if (!IsVolumeLocalNTFS( argv[argc-1][0] )) {
|
|
DisplayMsg( MSG_NTFS_REQUIRED );
|
|
ExitCode = EXIT_CODE_FAILURE;
|
|
leave;
|
|
}
|
|
|
|
if (wcslen( DotPrefix ) + wcslen( argv[argc - 1] ) + 1 > MAX_PATH) {
|
|
DisplayMsg( MSG_FILENAME_TOO_LONG );
|
|
ExitCode = EXIT_CODE_FAILURE;
|
|
leave;
|
|
}
|
|
|
|
wcscpy( FileName, DotPrefix );
|
|
wcscat( FileName, argv[argc - 1] );
|
|
|
|
FileHandle = CreateFile(
|
|
FileName,
|
|
GENERIC_WRITE,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL
|
|
);
|
|
if (FileHandle == INVALID_HANDLE_VALUE) {
|
|
DisplayError();
|
|
ExitCode = EXIT_CODE_FAILURE;
|
|
leave;
|
|
}
|
|
|
|
Status = DeviceIoControl(
|
|
FileHandle,
|
|
FSCTL_QUERY_USN_JOURNAL,
|
|
NULL,
|
|
0,
|
|
&UsnJournalData,
|
|
sizeof(USN_JOURNAL_DATA),
|
|
&BytesReturned,
|
|
(LPOVERLAPPED)NULL
|
|
);
|
|
if (!Status) {
|
|
DisplayError();
|
|
ExitCode = EXIT_CODE_FAILURE;
|
|
leave;
|
|
}
|
|
|
|
DeleteUsnJournalData.DeleteFlags = USN_DELETE_FLAG_DELETE ;
|
|
|
|
for (i = 0; i < argc - 1; i++) {
|
|
if (argv[i][0] == L'/' && wcslen( argv[i] ) == 2) {
|
|
switch (towupper( argv[i][1] ) ) {
|
|
case L'D':
|
|
DeleteUsnJournalData.DeleteFlags |= USN_DELETE_FLAG_DELETE ;
|
|
continue;
|
|
|
|
case L'N':
|
|
DeleteUsnJournalData.DeleteFlags |= USN_DELETE_FLAG_NOTIFY ;
|
|
continue;
|
|
}
|
|
|
|
}
|
|
DisplayMsg( MSG_INVALID_PARAMETER, argv[i] );
|
|
DisplayMsg( MSG_USAGE_DELETEUSN );
|
|
ExitCode = EXIT_CODE_FAILURE;
|
|
leave;
|
|
|
|
}
|
|
|
|
DeleteUsnJournalData.UsnJournalID = UsnJournalData.UsnJournalID;
|
|
|
|
Status = DeviceIoControl(
|
|
FileHandle,
|
|
FSCTL_DELETE_USN_JOURNAL,
|
|
&DeleteUsnJournalData,
|
|
sizeof(DELETE_USN_JOURNAL_DATA),
|
|
NULL,
|
|
0,
|
|
&BytesReturned,
|
|
(LPOVERLAPPED)NULL
|
|
);
|
|
if (!Status) {
|
|
DisplayError();
|
|
ExitCode = EXIT_CODE_FAILURE;
|
|
leave;
|
|
}
|
|
|
|
} finally {
|
|
|
|
if (FileHandle != INVALID_HANDLE_VALUE) {
|
|
CloseHandle( FileHandle );
|
|
}
|
|
|
|
}
|
|
|
|
return ExitCode;
|
|
}
|
|
|
|
INT
|
|
EnumUsnData(
|
|
IN INT argc,
|
|
IN PWSTR argv[]
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine enumerated the USN data associated with the volume
|
|
specified.
|
|
|
|
Arguments:
|
|
|
|
argc - The argument count.
|
|
argv - Array of Strings of the form :
|
|
' fscutl enusndata <file ref#> <lowUsn> <highUsn> <pathname>'.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
HANDLE FileHandle = INVALID_HANDLE_VALUE;
|
|
WCHAR FileName[MAX_PATH];
|
|
BOOL Status;
|
|
DWORD BytesReturned;
|
|
MFT_ENUM_DATA MftEnumData;
|
|
PVOID lpOutBuffer = NULL;
|
|
DWORD nOutBufferSize;
|
|
PUSN_RECORD UsnRecord;
|
|
WORD Index;
|
|
LONG Length;
|
|
PWSTR EndStr;
|
|
INT ExitCode = EXIT_CODE_SUCCESS;
|
|
|
|
try {
|
|
|
|
if (argc != 4) {
|
|
DisplayMsg( MSG_USAGE_ENUMDATA );
|
|
if (argc != 0) {
|
|
ExitCode = EXIT_CODE_FAILURE;
|
|
}
|
|
leave;
|
|
}
|
|
|
|
if (!IsVolumeLocalNTFS( argv[argc-1][0] )) {
|
|
DisplayMsg( MSG_NTFS_REQUIRED );
|
|
ExitCode = EXIT_CODE_FAILURE;
|
|
leave;
|
|
}
|
|
|
|
if (wcslen( DotPrefix ) + wcslen( argv[argc - 1] ) + 1 > MAX_PATH) {
|
|
DisplayMsg( MSG_FILENAME_TOO_LONG );
|
|
ExitCode = EXIT_CODE_FAILURE;
|
|
leave;
|
|
}
|
|
|
|
wcscpy( FileName, DotPrefix );
|
|
wcscat( FileName, argv[argc - 1] );
|
|
|
|
FileHandle = CreateFile(
|
|
FileName,
|
|
GENERIC_READ,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL
|
|
);
|
|
if (FileHandle == INVALID_HANDLE_VALUE) {
|
|
DisplayError();
|
|
ExitCode = EXIT_CODE_FAILURE;
|
|
leave;
|
|
}
|
|
|
|
nOutBufferSize = MAX_USN_DATA;
|
|
lpOutBuffer = (PVOID) malloc ( nOutBufferSize );
|
|
|
|
MftEnumData.StartFileReferenceNumber = My_wcstoui64( argv[0], &EndStr, 0 );
|
|
if (UnsignedI64NumberCheck( MftEnumData.StartFileReferenceNumber, EndStr )) {
|
|
DisplayMsg( MSG_USAGE_ENUMDATA );
|
|
ExitCode = EXIT_CODE_FAILURE;
|
|
leave;
|
|
}
|
|
|
|
MftEnumData.LowUsn = My_wcstoui64( argv[1], &EndStr, 0 );
|
|
if (UnsignedI64NumberCheck( MftEnumData.LowUsn, EndStr )) {
|
|
DisplayMsg( MSG_USAGE_ENUMDATA );
|
|
ExitCode = EXIT_CODE_FAILURE;
|
|
leave;
|
|
}
|
|
|
|
MftEnumData.HighUsn = My_wcstoui64( argv[2], &EndStr, 0 );
|
|
if (UnsignedI64NumberCheck( MftEnumData.HighUsn, EndStr )) {
|
|
DisplayMsg( MSG_USAGE_ENUMDATA );
|
|
ExitCode = EXIT_CODE_FAILURE;
|
|
leave;
|
|
}
|
|
|
|
while (TRUE) {
|
|
Status = DeviceIoControl(
|
|
FileHandle,
|
|
FSCTL_ENUM_USN_DATA,
|
|
&MftEnumData,
|
|
sizeof(MFT_ENUM_DATA),
|
|
lpOutBuffer,
|
|
nOutBufferSize,
|
|
&BytesReturned,
|
|
(LPOVERLAPPED)NULL
|
|
);
|
|
if (!Status) {
|
|
if (GetLastError() != ERROR_HANDLE_EOF) {
|
|
DisplayError();
|
|
ExitCode = EXIT_CODE_FAILURE;
|
|
}
|
|
leave;
|
|
}
|
|
|
|
if ( BytesReturned < sizeof( ULONGLONG ) + sizeof( USN_RECORD )) {
|
|
break;
|
|
}
|
|
|
|
UsnRecord = (PUSN_RECORD) ((PBYTE)lpOutBuffer + sizeof( ULONGLONG ));
|
|
while ((PBYTE)UsnRecord < (PBYTE)lpOutBuffer + BytesReturned) {
|
|
DisplayMsg(
|
|
MSG_ENUMDATA,
|
|
QuadToPaddedHexText( UsnRecord->FileReferenceNumber ),
|
|
QuadToPaddedHexText( UsnRecord->ParentFileReferenceNumber ),
|
|
QuadToPaddedHexText( UsnRecord->Usn ),
|
|
UsnRecord->SecurityId,
|
|
UsnRecord->Reason,
|
|
UsnRecord->FileNameLength,
|
|
UsnRecord->FileNameLength / sizeof(WCHAR),
|
|
UsnRecord->FileName
|
|
);
|
|
UsnRecord = NextUsnRecord( UsnRecord );
|
|
}
|
|
MftEnumData.StartFileReferenceNumber = *(PLONGLONG)lpOutBuffer;
|
|
}
|
|
|
|
} finally {
|
|
|
|
if (FileHandle != INVALID_HANDLE_VALUE) {
|
|
CloseHandle( FileHandle );
|
|
}
|
|
if (lpOutBuffer) {
|
|
free( lpOutBuffer );
|
|
}
|
|
|
|
}
|
|
|
|
return ExitCode;
|
|
}
|
|
|
|
|
|
INT
|
|
ReadFileUsnData(
|
|
IN INT argc,
|
|
IN PWSTR argv[]
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine reads the usn data for the volume specified.
|
|
|
|
Arguments:
|
|
|
|
argc - The argument count.
|
|
argv - Array of Strings of the form :
|
|
' fscutl rdusndata <pathname>'.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
HANDLE FileHandle = INVALID_HANDLE_VALUE;
|
|
WCHAR FileName[MAX_PATH];
|
|
BOOL Status;
|
|
DWORD BytesReturned;
|
|
DWORD nOutBufferSize;
|
|
PUSN_RECORD UsnRecord = NULL;
|
|
PWSTR FullName;
|
|
INT ExitCode = EXIT_CODE_SUCCESS;
|
|
|
|
try {
|
|
|
|
if (argc != 1) {
|
|
DisplayMsg( MSG_USAGE_READDATA );
|
|
if (argc != 0) {
|
|
ExitCode = EXIT_CODE_FAILURE;
|
|
}
|
|
leave;
|
|
}
|
|
|
|
FullName = GetFullPath( argv[0] );
|
|
|
|
if (!FullName) {
|
|
DisplayError();
|
|
ExitCode = EXIT_CODE_FAILURE;
|
|
leave;
|
|
}
|
|
|
|
if (!IsVolumeLocalNTFS( FullName[0] )) {
|
|
DisplayMsg( MSG_NTFS_REQUIRED );
|
|
ExitCode = EXIT_CODE_FAILURE;
|
|
leave;
|
|
}
|
|
|
|
if (wcslen( DotPrefix ) + wcslen( FullName ) + 1 > MAX_PATH) {
|
|
DisplayMsg( MSG_FILENAME_TOO_LONG );
|
|
ExitCode = EXIT_CODE_FAILURE;
|
|
leave;
|
|
}
|
|
|
|
wcscpy( FileName, DotPrefix );
|
|
wcscat( FileName, FullName );
|
|
|
|
FileHandle = CreateFile(
|
|
FileName,
|
|
GENERIC_READ,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL
|
|
);
|
|
if (FileHandle == INVALID_HANDLE_VALUE) {
|
|
DisplayError();
|
|
ExitCode = EXIT_CODE_FAILURE;
|
|
leave;
|
|
}
|
|
|
|
nOutBufferSize = MAX_USN_DATA;
|
|
UsnRecord = (PUSN_RECORD) malloc ( nOutBufferSize );
|
|
|
|
Status = DeviceIoControl(
|
|
FileHandle,
|
|
FSCTL_READ_FILE_USN_DATA,
|
|
NULL,
|
|
0,
|
|
UsnRecord,
|
|
nOutBufferSize,
|
|
&BytesReturned,
|
|
(LPOVERLAPPED)NULL
|
|
);
|
|
if (!Status) {
|
|
DisplayError();
|
|
ExitCode = EXIT_CODE_FAILURE;
|
|
leave;
|
|
}
|
|
|
|
DisplayUsnRecord( UsnRecord );
|
|
|
|
} finally {
|
|
|
|
if (FileHandle != INVALID_HANDLE_VALUE) {
|
|
CloseHandle( FileHandle );
|
|
}
|
|
if (UsnRecord) {
|
|
free( UsnRecord );
|
|
}
|
|
|
|
free( FullName );
|
|
|
|
}
|
|
|
|
return ExitCode;
|
|
}
|