WindowsXP/Source/XPSP1/NT/inetsrv/query/cicat/usnvol.cxx
2024-08-03 16:30:48 +02:00

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;
}