//+--------------------------------------------------------------------------- // // 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 #pragma hdrstop void Usage() { printf( "Needs admin privileges to run, usage: usndump , 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; }