windows-nt/Source/XPSP1/NT/com/svcdlls/trksvcs/trkwks/loghead.cxx
2020-09-26 16:20:57 +08:00

382 lines
10 KiB
C++

// Copyright (c) 1996-1999 Microsoft Corporation
//+============================================================================
//
// File: LogHead.cxx
//
// Classes: CLogFileHeader
//
// This class represents the header (the first sector) of the Tracking
// (Workstation) Service's log file.
//
//+============================================================================
#include "pch.cxx"
#pragma hdrstop
#include "trkwks.hxx"
//+----------------------------------------------------------------------------
//
// Method: Initialize
//
// Synopsis: Initialize the header class. We allocate a buffer here to
// hold sectors. This is the only allocation we perform
// in this class.
//
// Inputs: [cbSector] (in)
// The size of the file sectors.
//
// Output: None
//
//+----------------------------------------------------------------------------
void
CLogFileHeader::Initialize( ULONG cbSector )
{
TrkAssert( 0 != cbSector );
TrkAssert( NULL == _hFile );
// Initialize flags
_fDirty = FALSE;
// Store the input
if( sizeof(*_plogheader) + CB_EXTENDED_HEADER > cbSector )
{
TrkLog(( TRKDBG_ERROR, TEXT("Sector size isn't large enough for log header") ));
TrkRaiseWin32Error( ERROR_BAD_CONFIGURATION );
}
_cbSector = cbSector;
// Allocate a buffer to hold the header sector
if( NULL != _plogheader && _cbSector != cbSector )
{
delete [] _plogheader;
_plogheader = NULL;
}
if( NULL == _plogheader )
{
_plogheader = reinterpret_cast<LogHeader*>( new BYTE[ cbSector ] );
if( NULL == _plogheader )
{
TrkLog((TRKDBG_ERROR, TEXT("Couldn't alloc %d bytes in CLogFileHeader::Initialize"), cbSector ));
TrkRaiseWin32Error( ERROR_NOT_ENOUGH_MEMORY );
}
}
// The "extended header" is that portion beyond the regular header
_pextendedheader = &_plogheader[1];
} // CLogFileHeader::Initialize
//+----------------------------------------------------------------------------
//
// Method: UnInitialize
//
// Synopsis: Free the sector buffer.
//
// Inputs: None
//
// Output: None
//
//+----------------------------------------------------------------------------
void
CLogFileHeader::UnInitialize()
{
if( NULL != _plogheader )
{
if( IsOpen() )
OnClose();
LogHeader *plogheader = _plogheader;
_plogheader = NULL;
delete [] plogheader;
}
} // CLogFileHeader::UnInitialize()
//+----------------------------------------------------------------------------
//
// Method: LoadHeader
//
// Synopsis: Load the header sector from the log file.
//
// Inputs: None
//
// Output: None
//
//+----------------------------------------------------------------------------
void
CLogFileHeader::LoadHeader( HANDLE hFile )
{
NTSTATUS status;
LARGE_INTEGER liOffset;
IO_STATUS_BLOCK IoStatusBlock;
// _hFile must not be set until we've successfully loaded the header.
TrkAssert( NULL == _hFile );
// Read the header sector from the file
liOffset.QuadPart = 0;
status = NtReadFile( hFile, NULL, NULL, NULL,
&IoStatusBlock, _plogheader, _cbSector,
&liOffset, NULL );
if ( STATUS_PENDING == status )
{
// Wait for the operation to complete. The resulting status
// will be put in the IOSB
status = NtWaitForSingleObject( hFile, FALSE, NULL );
if( NT_SUCCESS(status) )
status = IoStatusBlock.Status;
}
// Validate the results of the read
if ( !NT_SUCCESS(status) )
{
TrkLog((TRKDBG_ERROR, TEXT("Failed NtReadFile (%08x)"), status ));
if(STATUS_VOLUME_DISMOUNTED == status)
{
TrkRaiseNtStatus(status);
}
else
{
TrkRaiseException( TRK_E_CORRUPT_LOG );
}
}
if( NULL != g_ptrkwks ) // NULL when called by dltadmin.exe
g_ptrkwks->_entropy.Put();
if( _cbSector != IoStatusBlock.Information )
{
TrkLog((TRKDBG_ERROR, TEXT("Couldn't read header from log") ));
TrkRaiseException( TRK_E_CORRUPT_LOG );
}
_hFile = hFile;
} // CLogFileHeader::LoadHeader()
//+----------------------------------------------------------------------------
//
// Method: ReadExtended
//
// Synopsis: Read bytes from the extended header to the caller's
// buffer.
//
// Inputs: [iOffset] (in)
// 0-relative offset into the extended header.
// [pv] (out)
// Buffer to receive the extended header bytes
// [cb] (in)
// Size of this extended header segment.
//
// Outputs: None
//
//+----------------------------------------------------------------------------
void
CLogFileHeader::ReadExtended( ULONG iOffset, void *pv, ULONG cb )
{
TrkAssert( NULL != _plogheader );
RaiseIfNotOpen();
// Validate the request
if( sizeof(*_plogheader) + iOffset + cb > _cbSector )
{
TrkLog((TRKDBG_ERROR, TEXT("Attempt to read too much data from the extended log header (%d bytes at %d)\n"),
iOffset, cb ));
TrkAssert( !TEXT("Invalid parameters to CLogFileHeader::ReadExtended") );
TrkRaiseException( TRK_E_CORRUPT_LOG );
}
// Read the bytes
memcpy( pv, &static_cast<BYTE*>(_pextendedheader)[ iOffset ], cb );
} // CLogFileHeader::ReadExtended()
//+----------------------------------------------------------------------------
//
// Method: WriteExtended
//
// Synopsis: Writes bytes to the caller-specified portion of the log's
// extended header area.
//
// Inputs: [iOffset] (in)
// 0-relative index into the extended header
// [pv] (in)
// The bytes to write.
// [cb] (in)
// The number of bytes to write.
//
// Output: None
//
//+----------------------------------------------------------------------------
void
CLogFileHeader::WriteExtended( ULONG iOffset, const void *pv, ULONG cb )
{
TrkAssert( NULL != _plogheader );
TrkAssert( sizeof(*_plogheader) + iOffset + cb <= 512 );
RaiseIfNotOpen();
// Validate the request
if( sizeof(*_plogheader) + iOffset + cb > _cbSector )
{
TrkLog((TRKDBG_ERROR, TEXT("Attempt to read too much data from the extended log header (%d bytes at %d)\n"),
iOffset, cb ));
TrkAssert( !TEXT("Invalid parameters to CLogFileHeader::WriteExtended") );
TrkRaiseException( TRK_E_CORRUPT_LOG );
}
// Write the bytes
memcpy( &static_cast<BYTE*>(_pextendedheader)[ iOffset ], pv, cb );
SetDirty();
} // CLogFileHeader::WriteExtended
//+----------------------------------------------------------------------------
//
// Method: SetExpansionData
//
// Synopsis: Write information about an expansion to the log header.
//
// Inputs: [cbLogFile] (in)
// The current size of the file.
// [ilogStart] (in)
// The index of the current starting point in the circular
// linked-list.
// [ilogEnd] (in)
// The index of the current ending point in the circular
// linked-list.
//
// Outputs: None
//
//+----------------------------------------------------------------------------
void
CLogFileHeader::SetExpansionData( ULONG cbLogFile, ULONG ilogStart, ULONG ilogEnd )
{
TrkAssert( NULL != _plogheader );
RaiseIfNotOpen();
// Save the expansion data
_plogheader->expand.cbFile = cbLogFile;
_plogheader->expand.ilogStart = ilogStart;
_plogheader->expand.ilogEnd = ilogEnd;
// Flush straight to disk
Flush( );
} // CLogFileHeader::SetExpansionData()
//+----------------------------------------------------------------------------
//
// Method: Flush
//
// Synopsis: Flush the current header sector to the underlying file.
//
// Inputs: [FlushFlags] (in)
// From the FLUSH_* defines. Used to indicate if we
// should flush regardless of the dirty flag, and if
// we should flush to cache or to disk.
//
// Outputs: None
//
//+----------------------------------------------------------------------------
void
CLogFileHeader::Flush( )
{
NTSTATUS status = STATUS_SUCCESS;
RaiseIfNotOpen();
// Is there anything loaded to even flush?
if( NULL != _hFile )
{
IO_STATUS_BLOCK IoStatusBlock;
TrkAssert( NULL != _plogheader );
// Is the in-memory header dirty?
if( _fDirty )
{
LARGE_INTEGER liOffset;
TrkAssert( NULL != _hFile );
// Write the header sector to the file
liOffset.QuadPart = 0;
status = NtWriteFile( _hFile, NULL, NULL, NULL,
&IoStatusBlock, _plogheader, _cbSector,
&liOffset, NULL );
if ( STATUS_PENDING == status )
{
// Wait for the operation to complete. The resulting status
// will be put in the IOSB
status = NtWaitForSingleObject( _hFile, FALSE, NULL );
if( NT_SUCCESS(status) )
status = IoStatusBlock.Status;
}
// Validate the results of the write
if ( !NT_SUCCESS(status) )
{
TrkLog((TRKDBG_ERROR, TEXT("Couldn't write the log file header")));
TrkRaiseNtStatus( status );
}
if( NULL != g_ptrkwks ) // NULL when called by dltadmin.exe
g_ptrkwks->_entropy.Put();
if( _cbSector != IoStatusBlock.Information )
{
TrkLog((TRKDBG_ERROR, TEXT("Couldn't write all of the log file header (%d)"),
IoStatusBlock.Information ));
TrkRaiseException( TRK_E_CORRUPT_LOG );
}
SetDirty( FALSE );
} // if( _fDirty || FLUSH_UNCONDITIONALLY == flush_type )
} // if( NULL != _hFile )
} // CLogFileHeader::Flush