280 lines
7.5 KiB
C++
280 lines
7.5 KiB
C++
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Microsoft Windows
|
||
|
// Copyright (C) Microsoft Corporation, 1997-1998.
|
||
|
//
|
||
|
// File: usnvol.cxx
|
||
|
//
|
||
|
// Contents: Usn volume info
|
||
|
//
|
||
|
// History: 07-May-97 SitaramR Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
#include <pch.cxx>
|
||
|
#pragma hdrstop
|
||
|
|
||
|
#include <ntopen.hxx>
|
||
|
|
||
|
#include "usnvol.hxx"
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CUsnVolume::CUsnVolume
|
||
|
//
|
||
|
// Synopsis: Constructor
|
||
|
//
|
||
|
// Arguments: [wcDriveLetter] -- Drive letter
|
||
|
// [volumeId] -- Volume id
|
||
|
//
|
||
|
// History: 07-May-97 SitaramR Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
CUsnVolume::CUsnVolume( WCHAR wcDriveLetter, VOLUMEID volumeId )
|
||
|
: _hVolume(INVALID_HANDLE_VALUE),
|
||
|
_wcDriveLetter(wcDriveLetter),
|
||
|
_usnMaxRead(0),
|
||
|
_volumeId(volumeId),
|
||
|
_fileIdRoot(fileIdInvalid),
|
||
|
_fFsctlPending(FALSE),
|
||
|
_fOnline(TRUE)
|
||
|
{
|
||
|
Win4Assert( volumeId != CI_VOLID_USN_NOT_ENABLED );
|
||
|
|
||
|
//
|
||
|
// Find the file id of root of volume
|
||
|
//
|
||
|
|
||
|
WCHAR wszRootPath[] = L"a:\\.";
|
||
|
wszRootPath[0] = wcDriveLetter;
|
||
|
|
||
|
HANDLE rootHandle = CiNtOpen( wszRootPath,
|
||
|
FILE_READ_ATTRIBUTES | SYNCHRONIZE,
|
||
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||
|
0 );
|
||
|
|
||
|
SHandle xHandle( rootHandle );
|
||
|
|
||
|
IO_STATUS_BLOCK iosb;
|
||
|
ULONGLONG readBuffer[200];
|
||
|
|
||
|
NTSTATUS status = NtFsControlFile( rootHandle,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
&iosb,
|
||
|
FSCTL_READ_FILE_USN_DATA,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
&readBuffer,
|
||
|
sizeof(readBuffer) );
|
||
|
|
||
|
if ( NT_SUCCESS( status ) )
|
||
|
status = iosb.Status;
|
||
|
|
||
|
if ( NT_SUCCESS( status ) )
|
||
|
{
|
||
|
USN_RECORD *pUsnRec = (USN_RECORD *)((PCHAR) &readBuffer);
|
||
|
|
||
|
//
|
||
|
// Root is its own parent
|
||
|
//
|
||
|
Win4Assert( pUsnRec->FileReferenceNumber == pUsnRec->ParentFileReferenceNumber );
|
||
|
|
||
|
_fileIdRoot = pUsnRec->FileReferenceNumber;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ciDebugOut(( DEB_ERROR, "Unable to read usn info of root, 0x%x\n", status ));
|
||
|
|
||
|
THROW( CException( status ) );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Create the volume handle that will be used for usn fsctls
|
||
|
//
|
||
|
|
||
|
WCHAR wszVolumePath[] = L"\\\\.\\a:";
|
||
|
wszVolumePath[4] = wcDriveLetter;
|
||
|
|
||
|
_hVolume = CreateFile( wszVolumePath,
|
||
|
GENERIC_READ | GENERIC_WRITE,
|
||
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||
|
NULL,
|
||
|
OPEN_EXISTING,
|
||
|
FILE_FLAG_OVERLAPPED,
|
||
|
NULL );
|
||
|
|
||
|
if ( _hVolume == INVALID_HANDLE_VALUE )
|
||
|
{
|
||
|
ciDebugOut(( DEB_ERROR, "Usn volume open failed, 0x%x", GetLastError() ));
|
||
|
|
||
|
THROW( CException() );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Get the Journal ID
|
||
|
//
|
||
|
|
||
|
USN_JOURNAL_DATA UsnJournalInfo;
|
||
|
|
||
|
status = NtFsControlFile( _hVolume,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
&iosb,
|
||
|
FSCTL_QUERY_USN_JOURNAL,
|
||
|
0,
|
||
|
0,
|
||
|
&UsnJournalInfo,
|
||
|
sizeof(UsnJournalInfo) );
|
||
|
|
||
|
if ( status == STATUS_PENDING )
|
||
|
{
|
||
|
Win4Assert( !"Synchronous usn read returned status_pending" );
|
||
|
_JournalID = 0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if ( NT_SUCCESS( status ) )
|
||
|
status = iosb.Status;
|
||
|
|
||
|
if ( NT_SUCCESS(status) )
|
||
|
_JournalID = UsnJournalInfo.UsnJournalID;
|
||
|
else
|
||
|
_JournalID = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CUsnVolume::~CUsnVolume
|
||
|
//
|
||
|
// Synopsis: Destructor
|
||
|
//
|
||
|
// History: 07-May-97 SitaramR Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
CUsnVolume::~CUsnVolume()
|
||
|
{
|
||
|
Win4Assert( _hVolume != INVALID_HANDLE_VALUE );
|
||
|
|
||
|
CancelFsctl();
|
||
|
CloseHandle( _hVolume );
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CUsnVolume::CancelFsctl
|
||
|
//
|
||
|
// Synopsis: Cancels any pending fsctls
|
||
|
//
|
||
|
// History: 05-Jul-97 SitaramR Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
void CUsnVolume::CancelFsctl()
|
||
|
{
|
||
|
if ( _fFsctlPending )
|
||
|
{
|
||
|
IO_STATUS_BLOCK iosb;
|
||
|
NTSTATUS status = NtCancelIoFile( _hVolume, &iosb );
|
||
|
|
||
|
if ( STATUS_SUCCESS != status )
|
||
|
{
|
||
|
ciDebugOut(( DEB_ERROR,
|
||
|
"NtCancelIoFile pending usn fsctl failed: %#x\n",
|
||
|
status ));
|
||
|
}
|
||
|
|
||
|
_evtFsctl.Wait( INFINITE );
|
||
|
_fFsctlPending = FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: CUsnVolume::PercentRead, public
|
||
|
//
|
||
|
// Synopsis: Compute current position in USN Journal
|
||
|
//
|
||
|
// Returns: Percentage through readable portion of USN Journal.
|
||
|
//
|
||
|
// History: 22-Jun-98 KyleP Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
ULONG CUsnVolume::PercentRead()
|
||
|
{
|
||
|
USN usnPct;
|
||
|
|
||
|
if ( 0 == _usnMaxRead )
|
||
|
{
|
||
|
usnPct = 0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
USN_JOURNAL_DATA UsnJournalInfo;
|
||
|
IO_STATUS_BLOCK iosb;
|
||
|
|
||
|
NTSTATUS Status = NtFsControlFile( _hVolume,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
&iosb,
|
||
|
FSCTL_QUERY_USN_JOURNAL,
|
||
|
0,
|
||
|
0,
|
||
|
&UsnJournalInfo,
|
||
|
sizeof(UsnJournalInfo) );
|
||
|
|
||
|
if ( Status == STATUS_PENDING )
|
||
|
{
|
||
|
Win4Assert( !"Synchronous usn read returned status_pending" );
|
||
|
usnPct = 0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if ( NT_SUCCESS( Status ) )
|
||
|
Status = iosb.Status;
|
||
|
|
||
|
if ( NT_SUCCESS(Status) )
|
||
|
{
|
||
|
//
|
||
|
// Don't go negative. If we've ran off the end (and will get
|
||
|
// STATUS_JOURNAL_ENTRY_DELETED when reading the journal)
|
||
|
// just report 0%
|
||
|
//
|
||
|
|
||
|
if ( _usnMaxRead >= UsnJournalInfo.FirstUsn )
|
||
|
{
|
||
|
USN usnNum;
|
||
|
usnNum = _usnMaxRead - UsnJournalInfo.FirstUsn;
|
||
|
|
||
|
//
|
||
|
// Add 1 to avoid divide-by-zero errors.
|
||
|
//
|
||
|
|
||
|
USN usnDen = UsnJournalInfo.NextUsn - UsnJournalInfo.FirstUsn + 1;
|
||
|
|
||
|
usnPct = usnNum * 100 / usnDen;
|
||
|
}
|
||
|
else
|
||
|
usnPct = 0;
|
||
|
}
|
||
|
else
|
||
|
usnPct = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Win4Assert( usnPct >= 0 && usnPct <= 100 );
|
||
|
|
||
|
return (ULONG)usnPct;
|
||
|
}
|