//+------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1998 - 1999. // // File: usnmon.cxx // // Contents: USN monitor // // History: 18 Nov 1998 DLee Created // //-------------------------------------------------------------------------- #ifndef _WIN32_WINNT #define _WIN32_WINNT 0x0500 #endif extern "C" { #include #include #include #include #include } #include #include #include #define MAX_PATH_WCHARS (MAX_PATH * 4 ) BOOL fVerbose = FALSE; void usage() { printf( "usage: usnmon x: [-verbose]\n" ); printf( "You must be an administrator to run this application.\n" ); exit( 1 ); } //usage void IdToPath( HANDLE hVol, LONGLONG ll, WCHAR wcVol, WCHAR * pwcPath ) { *pwcPath = 0; UNICODE_STRING uScope; uScope.Buffer = (WCHAR *) ≪ uScope.Length = sizeof ll; uScope.MaximumLength = sizeof ll; OBJECT_ATTRIBUTES ObjectAttr; InitializeObjectAttributes( &ObjectAttr, // Structure &uScope, // Name OBJ_CASE_INSENSITIVE, // Attributes hVol, // Root 0 ); // Security IO_STATUS_BLOCK IoStatus; HANDLE h = INVALID_HANDLE_VALUE; NTSTATUS Status = NtOpenFile( &h, FILE_READ_ATTRIBUTES, &ObjectAttr, &IoStatus, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN_BY_FILE_ID ); if ( NT_ERROR( Status ) ) return; static BYTE abFileNameInformation[ MAX_PATH_WCHARS * sizeof WCHAR + sizeof FILE_NAME_INFORMATION ]; ULONG cbMax = sizeof abFileNameInformation; PFILE_NAME_INFORMATION FileName = (PFILE_NAME_INFORMATION) abFileNameInformation; FileName->FileNameLength = cbMax - sizeof FILE_NAME_INFORMATION; Status = NtQueryInformationFile( h, &IoStatus, FileName, cbMax, FileNameInformation ); NtClose( h ); if ( NT_ERROR( Status ) ) return; // This is actually the full path, not the filename FileName->FileName[ FileName->FileNameLength / sizeof WCHAR ] = 0; pwcPath[0] = wcVol; pwcPath[1] = ':'; wcscpy( pwcPath + 2, FileName->FileName ); } //IdToPath USN PrintUsnRecords( HANDLE hVol, WCHAR wcVol, IO_STATUS_BLOCK * pIoSB, void * pBuffer, USN usnPrev ) { USN usnNextStart; USN_RECORD * pUsnRec; ULONG_PTR dwByteCount = pIoSB->Information; if ( 0 != dwByteCount ) { usnNextStart = *(USN *)pBuffer; pUsnRec = (USN_RECORD *)((PCHAR)pBuffer + sizeof(USN)); dwByteCount -= sizeof(USN); } else { usnNextStart = usnPrev; } while ( 0 != dwByteCount ) { if ( fVerbose ) printf( "usn %#I64x id %#I64x ", pUsnRec->Usn, pUsnRec->FileReferenceNumber ); static WCHAR awcPath[ MAX_PATH_WCHARS ]; IdToPath( hVol, pUsnRec->FileReferenceNumber, wcVol, awcPath ); ULONG r = pUsnRec->Reason; if ( 0 == awcPath[0] || ( r & USN_REASON_RENAME_OLD_NAME ) ) { IdToPath( hVol, pUsnRec->ParentFileReferenceNumber, wcVol, awcPath ); // If the parent directory has already been deleted, just // print the filename. if ( 0 == awcPath[0] ) printf( "(%.*ws) ", pUsnRec->FileNameLength / sizeof WCHAR, &pUsnRec->FileName ); else printf( "%ws\\%.*ws ", awcPath, pUsnRec->FileNameLength / sizeof WCHAR, &pUsnRec->FileName ); } else printf( "%ws ", awcPath ); if ( r & USN_REASON_DATA_OVERWRITE ) printf( "DATA_OVERWRITE " ); if ( r & USN_REASON_DATA_EXTEND ) printf( "DATA_EXTEND " ); if ( r & USN_REASON_DATA_TRUNCATION ) printf( "DATA_TRUNCATION " ); if ( r & USN_REASON_NAMED_DATA_OVERWRITE ) printf( "NAMED_DATA_OVERWRITE " ); if ( r & USN_REASON_NAMED_DATA_EXTEND ) printf( "NAMED_DATA_EXTEND " ); if ( r & USN_REASON_NAMED_DATA_TRUNCATION ) printf( "NAMED_DATA_TRUNCATION " ); if ( r & USN_REASON_FILE_CREATE ) printf( "FILE_CREATE " ); if ( r & USN_REASON_FILE_DELETE ) printf( "FILE_DELETE " ); if ( r & USN_REASON_EA_CHANGE ) printf( "EA_CHANGE " ); if ( r & USN_REASON_SECURITY_CHANGE ) printf( "SECURITY_CHANGE " ); if ( r & USN_REASON_RENAME_OLD_NAME ) printf( "RENAME_OLD_NAME " ); if ( r & USN_REASON_RENAME_NEW_NAME ) printf( "RENAME_NEW_NAME " ); if ( r & USN_REASON_INDEXABLE_CHANGE ) printf( "INDEXABLE_CHANGE " ); if ( r & USN_REASON_BASIC_INFO_CHANGE ) printf( "BASIC_INFO_CHANGE " ); if ( r & USN_REASON_HARD_LINK_CHANGE ) printf( "HARD_LINK_CHANGE " ); if ( r & USN_REASON_COMPRESSION_CHANGE ) printf( "COMPRESSION_CHANGE " ); if ( r & USN_REASON_ENCRYPTION_CHANGE ) printf( "ENCRYPTION_CHANGE " ); if ( r & USN_REASON_OBJECT_ID_CHANGE ) printf( "OBJECT_ID_CHANGE " ); if ( r & USN_REASON_REPARSE_POINT_CHANGE ) printf( "REPARSE_POINT_CHANGE " ); if ( r & USN_REASON_STREAM_CHANGE ) printf( "STREAM_CHANGE " ); if ( r & USN_REASON_CLOSE ) printf( "CLOSE " ); printf( "\n" ); if ( pUsnRec->RecordLength <= dwByteCount ) { dwByteCount -= pUsnRec->RecordLength; pUsnRec = (USN_RECORD *) ((PCHAR) pUsnRec + pUsnRec->RecordLength ); } else { printf( "Usn read fsctl returned bogus dwByteCount %#x\n", dwByteCount ); exit( -1 ); } } return usnNextStart; } //PrintUsnRecords int __cdecl main( int argc, char * argv[] ) { if ( 2 != argc && 3 != argc ) usage(); if ( 3 == argc && argv[2][1] == 'v' ) fVerbose = TRUE; WCHAR wcVol = argv[1][0]; WCHAR wszVolumePath[] = L"\\\\.\\a:"; wszVolumePath[4] = wcVol; HANDLE hVolume = CreateFile( wszVolumePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL ); if ( INVALID_HANDLE_VALUE == hVolume ) { printf( "Usn volume open failed %d, check for admin privileges\n", GetLastError() ); usage(); } HANDLE hEvent = CreateEvent( 0, TRUE, FALSE, 0 ); // // Get the Journal ID // USN_JOURNAL_DATA UsnJournalInfo; IO_STATUS_BLOCK IoSB; NTSTATUS status = NtFsControlFile( hVolume, hEvent, 0, 0, &IoSB, FSCTL_QUERY_USN_JOURNAL, 0, 0, &UsnJournalInfo, sizeof UsnJournalInfo ); if ( STATUS_PENDING == status ) WaitForSingleObject( hEvent, INFINITE ); if ( !NT_SUCCESS(status) || !NT_SUCCESS(IoSB.Status) ) { printf( "Error %#x / %#x returned from QUERY_USN_JOURNAL\n", status, IoSB.Status ); return -1; } USN usnMax = UsnJournalInfo.NextUsn; do { READ_USN_JOURNAL_DATA usnData = { usnMax, MAXULONG, 0, 0, 1, UsnJournalInfo.UsnJournalID }; static ULONGLONG readBuffer[2048]; status = NtFsControlFile( hVolume, hEvent, 0, 0, &IoSB, FSCTL_READ_USN_JOURNAL, &usnData, sizeof usnData, &readBuffer, sizeof readBuffer ); if ( STATUS_PENDING == status ) WaitForSingleObject( hEvent, INFINITE ); if ( NT_SUCCESS( status ) ) status = IoSB.Status; if ( !NT_SUCCESS( status ) ) { printf( "FSCTL_READ_USN_JOURNAL failed %#x\n", status ); return -1; } usnMax = PrintUsnRecords( hVolume, wcVol, &IoSB, readBuffer, usnMax ); } while ( TRUE ); return 0; } //main