windows-nt/Source/XPSP1/NT/inetsrv/query/apps/usndump/usndump.cxx
2020-09-26 16:20:57 +08:00

348 lines
12 KiB
C++

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation 1997-1998
//
// File: usndump.cxx
//
// Contents: Usn dump utility. Needs admin privileges to run.
//
// History: 05-Jul-97 SitaramR Created
//
//----------------------------------------------------------------------------
#include <pch.cxx>
#pragma hdrstop
void Usage()
{
printf( "Needs admin privileges to run, usage: usndump <drive_letter>, e.g. usndump c\n" );
}
DECLARE_INFOLEVEL(ci)
//+---------------------------------------------------------------------------
//
// Function: PrintUsnRecords
//
// Purpose: Prints usn records from buffer
//
// History: 05-Jul-97 SitaramR Created
// 21-May-98 KLam Added SourceInfo as output
//
//----------------------------------------------------------------------------
void PrintUsnRecords( IO_STATUS_BLOCK *iosb, void *pBuffer )
{
USN usnNextStart;
USN_RECORD * pUsnRec;
ULONG_PTR dwByteCount = iosb->Information;
if ( dwByteCount != 0 )
{
usnNextStart = *(USN *)pBuffer;
pUsnRec = (USN_RECORD *)((PCHAR)pBuffer + sizeof(USN));
dwByteCount -= sizeof(USN);
}
while ( dwByteCount != 0 )
{
if ( pUsnRec->MajorVersion != 2 || pUsnRec->MinorVersion != 0 )
{
printf( "Unrecognized USN version, Major=%u, Minor=%u\n",
pUsnRec->MajorVersion, pUsnRec->MinorVersion );
break;
}
if ( 0 != pUsnRec->SourceInfo )
printf( "FileId=%#I64x, ParentFileId=%#I64x, Usn=%#I64x, Reason=%#x, SourceInfo=%#x, FileAttr=%#x, FileName=%.*ws\n",
pUsnRec->FileReferenceNumber,
pUsnRec->ParentFileReferenceNumber,
pUsnRec->Usn,
pUsnRec->Reason,
pUsnRec->SourceInfo,
pUsnRec->FileAttributes,
pUsnRec->FileNameLength / sizeof WCHAR ,
&pUsnRec->FileName );
else
printf( "FileId=%#I64x, ParentFileId=%#I64x, Usn=%#I64x, Reason=%#x, FileAttr=%#x, FileName=%.*ws\n",
pUsnRec->FileReferenceNumber,
pUsnRec->ParentFileReferenceNumber,
pUsnRec->Usn,
pUsnRec->Reason,
pUsnRec->FileAttributes,
pUsnRec->FileNameLength / sizeof WCHAR,
&pUsnRec->FileName );
if ( pUsnRec->RecordLength <= dwByteCount )
{
dwByteCount -= pUsnRec->RecordLength;
pUsnRec = (USN_RECORD *) ((PCHAR) pUsnRec + pUsnRec->RecordLength );
}
else
{
printf( "***--- Usn read fsctl returned bogus dwByteCount 0x%x ---***\n", dwByteCount );
THROW( CException( STATUS_UNSUCCESSFUL ) );
}
}
}
//+---------------------------------------------------------------------------
//
// Function: main
//
// Purpose: Main dump routine
//
// History: 05-Jul-97 SitaramR Created
//
//----------------------------------------------------------------------------
int __cdecl main( int argc, char * argv[] )
{
if ( argc != 2 )
{
Usage();
return 0;
}
WCHAR wcDriveLetter = argv[1][0];
TRY
{
//
// Looking at a file?
//
if ( strlen(argv[1]) > 2 )
{
int ccUnicodeStr = strlen( argv[1] ) + 1;
WCHAR * pUnicodeStr = new WCHAR[ccUnicodeStr];
if ( !MultiByteToWideChar( CP_ACP, 0, argv[1], -1, pUnicodeStr, ccUnicodeStr ) )
{
printf("MultiByteToWideChar failed.\n");
delete [] pUnicodeStr;
return 0;
}
CFunnyPath funnyPath( pUnicodeStr );
delete [] pUnicodeStr;
HANDLE hFile = CreateFile( funnyPath.GetPath(),
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS,
NULL );
if ( INVALID_HANDLE_VALUE == hFile && ERROR_ACCESS_DENIED == GetLastError() )
hFile = CreateFile( funnyPath.GetPath(),
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL );
if ( hFile == INVALID_HANDLE_VALUE )
{
printf( "***--- Usn file open failed 0x%x, check for admin privileges ---***\n", GetLastError() );
THROW( CException( HRESULT_FROM_WIN32( GetLastError() ) ) );
}
NTSTATUS status;
SHandle xFile( hFile );
IO_STATUS_BLOCK iosb;
ULONGLONG readBuffer[100];
for ( unsigned i = 0; i < sizeof(readBuffer)/sizeof(readBuffer[0]); i++ )
readBuffer[i] = 0xFFFFFFFFFFFFFFFFi64;
USN_RECORD *pUsnRec;
status = NtFsControlFile( hFile,
NULL,
NULL,
NULL,
&iosb,
FSCTL_READ_FILE_USN_DATA,
NULL,
NULL,
&readBuffer,
sizeof(readBuffer) );
if ( !NT_SUCCESS(status) || !NT_SUCCESS(iosb.Status) )
{
printf( "***--- Error 0x%x / 0x%x returned from READ_FILE_USN_DATA ---***\n", status, iosb.Status );
return 0;
}
pUsnRec = (USN_RECORD *) &readBuffer;
if ( pUsnRec->MajorVersion != 2 || pUsnRec->MinorVersion != 0 )
printf( "Unrecognized USN version, Major=%u, Minor=%u\n",
pUsnRec->MajorVersion, pUsnRec->MinorVersion );
else
printf( "FileId=%#I64x, ParentFileId=%#I64x, Usn=%#I64x, FileAttr=%#x, FileName=%.*ws\n",
pUsnRec->FileReferenceNumber,
pUsnRec->ParentFileReferenceNumber,
(ULONG)(pUsnRec->Usn>>32),
(ULONG)pUsnRec->Usn,
pUsnRec->FileAttributes,
pUsnRec->FileNameLength / sizeof(WCHAR),
&pUsnRec->FileName );
}
else
{
//
// Create the volume handle that will be used for usn fsctls
//
WCHAR wszVolumePath[] = L"\\\\.\\a:";
wszVolumePath[4] = wcDriveLetter;
HANDLE hVolume = CreateFile( wszVolumePath,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL );
if ( hVolume == INVALID_HANDLE_VALUE )
{
printf( "***--- Usn volume open failed 0x%x, check for admin privileges ---***\n", GetLastError() );
THROW( CException( HRESULT_FROM_WIN32( GetLastError() ) ) );
}
SWin32Handle xHandleVolume( hVolume );
IO_STATUS_BLOCK iosb;
//
// Get the Journal ID
//
USN_JOURNAL_DATA UsnJournalInfo;
NTSTATUS status = NtFsControlFile( hVolume,
NULL,
NULL,
NULL,
&iosb,
FSCTL_QUERY_USN_JOURNAL,
0,
0,
&UsnJournalInfo,
sizeof(UsnJournalInfo) );
if ( status == STATUS_PENDING )
{
printf( "***--- Status_pending returned for synchronous read fsctl ---***\n" );
return 0;
}
if ( !NT_SUCCESS(status) || !NT_SUCCESS(iosb.Status) )
{
printf( "***--- Error 0x%x / 0x%x returned from QUERY_USN_JOURNAL ---***\n", status, iosb.Status );
return 0;
}
READ_USN_JOURNAL_DATA usnData = {0, MAXULONG, 0, 0, 0, UsnJournalInfo.UsnJournalID};
ULONGLONG readBuffer[2048];
status = NtFsControlFile( hVolume,
NULL,
NULL,
NULL,
&iosb,
FSCTL_READ_USN_JOURNAL,
&usnData,
sizeof(usnData),
&readBuffer,
sizeof(readBuffer) );
if ( status == STATUS_PENDING )
{
printf( "***--- Status_pending returned for synchronous read fsctl ---***\n" );
return 0;
}
if ( NT_SUCCESS( status ) )
{
status = iosb.Status;
if ( STATUS_KEY_DELETED == status ||
STATUS_JOURNAL_ENTRY_DELETED == status )
{
printf( "***--- Status key deleted, rerun ---***\n" );
return 0;
}
PrintUsnRecords( &iosb, readBuffer );
//
// Read usn records until the end of usn journal
//
USN usnStart = 0;
while ( NT_SUCCESS( status ) )
{
ULONG_PTR dwByteCount = iosb.Information;
if ( dwByteCount <= sizeof(USN) )
return 0;
else
{
usnStart = *(USN *)&readBuffer;
usnData.StartUsn = usnStart;
status = NtFsControlFile( hVolume,
NULL,
NULL,
NULL,
&iosb,
FSCTL_READ_USN_JOURNAL,
&usnData,
sizeof(usnData),
&readBuffer,
sizeof(readBuffer) );
if ( NT_SUCCESS( status ) )
status = iosb.Status;
else
{
printf( "***--- Error 0x%x returned from read fsctl ---***\n", status );
return 0;
}
if ( STATUS_KEY_DELETED == status ||
STATUS_JOURNAL_ENTRY_DELETED == status )
{
printf( "***--- Status key deleted, rerun usndump ---***\n" );
return 0;
}
PrintUsnRecords( &iosb, readBuffer );
}
}
return 0;
}
else
printf( "***--- Usn read fsctl returned 0x%x, check if usn journal has created on that volume ---***\n",
status );
}
return 0;
}
CATCH( CException, e )
{
printf( "***--- Caught exception 0x%x ---***\n", e.GetErrorCode() );
}
END_CATCH
return 0;
}