348 lines
12 KiB
C++
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;
|
||
|
}
|