|
|
//+-------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1996.
//
// File: fat.hxx
//
// Contents: Header file for fat classes
//
// Classes: CFatSect - sector sized array of sector info
// CFatVector - resizable array of CFatSect
// CFat - Grouping of FatSect
//
//--------------------------------------------------------------------
#ifndef __FAT_HXX__
#define __FAT_HXX__
#include "vect.hxx"
#define DEB_FAT (DEB_ITRACE|0x00010000)
//+----------------------------------------------------------------------
//
// Class: CFatSect (fs)
//
// Purpose: Holds one sector worth of FAT data
//
// Interface: getsize - Returns the size of the FAT (in sectors)
// contents - Returns contents of any given FAT entry
//
// Notes:
//
//-----------------------------------------------------------------------
class CFatSect { public: SCODE Init(FSOFFSET uEntries); SCODE InitCopy(USHORT uSize, CFatSect& fsOld); inline SECT GetSect(const FSOFFSET sect) const; inline void SetSect(const FSOFFSET sect,const SECT sectNew); inline SECT GetNextFat(USHORT uSize) const; inline void SetNextFat(USHORT uSize, const SECT sect); inline void ByteSwap(USHORT cbSector); private:
#ifdef _MSC_VER
#pragma warning(disable: 4200)
SECT _asectEntry[]; #pragma warning(default: 4200)
#endif
#ifdef __GNUC__
SECT _asectEntry[0]; #endif
};
inline SECT CFatSect::GetSect(const FSOFFSET sect) const { return _asectEntry[sect]; }
inline void CFatSect::SetSect(const FSOFFSET sect, const SECT sectNew) { _asectEntry[sect] = sectNew; }
inline SECT CFatSect::GetNextFat(USHORT uSize) const { return _asectEntry[uSize]; }
inline void CFatSect::SetNextFat(USHORT uSize, const SECT sect) { _asectEntry[uSize] = sect; }
inline void CFatSect::ByteSwap(FSOFFSET cbSector) { // swap all sectors in the sector
for (FSOFFSET i=0; i < cbSector; i++) ::ByteSwap(&(_asectEntry[i])); }
//+-------------------------------------------------------------------------
//
// Class: CFatVector (fv)
//
// Purpose: *finish this*
//
// Interface:
//
// Notes:
//
//--------------------------------------------------------------------------
class CFatVector: public CPagedVector { public: inline CFatVector( const SID sid, FSOFFSET csectBlock, FSOFFSET csectTable); SCODE InitPage(FSINDEX iPage); inline FSOFFSET GetSectBlock() const; inline FSOFFSET GetSectTable() const; inline SCODE GetTable( const FSINDEX iTable, const DWORD dwFlags, CFatSect **pfs); private: FSOFFSET const _csectTable; FSOFFSET const _csectBlock; inline void operator = (const CFatVector &that); #ifdef _MSC_VER
#pragma warning(disable:4512)
// since there is a const member, there should be no assignment operator
#endif // _MSC_VER
}; #ifdef _MSC_VER
#pragma warning(default:4512)
#endif // _MSC_VER
inline CFatVector::CFatVector( const SID sid, FSOFFSET csectBlock, FSOFFSET csectTable) : CPagedVector(sid), _csectTable(csectTable), _csectBlock(csectBlock) { }
//+-------------------------------------------------------------------------
//
// Method: CFatVector::GetSectTable, public
//
// Synopsis: Returns count of sector entries per table
//
// Returns: count of sector entries per table
//
//--------------------------------------------------------------------------
inline FSOFFSET CFatVector::GetSectTable() const { return _csectTable; }
//+-------------------------------------------------------------------------
//
// Method: CFatVector::GetSectTable, public
//
// Synopsis: Returns count of sector entries per block
//
// Returns: count of sector entries per block
//
//--------------------------------------------------------------------------
inline FSOFFSET CFatVector::GetSectBlock() const { return _csectBlock; }
//+-------------------------------------------------------------------------
//
// Method: CFatVector::GetTable, public
//
// Synopsis: Return a pointer to a FatSect for the given index
// into the vector.
//
// Arguments: [iTable] -- index into vector
//
// Returns: Pointer to CFatSect indicated by index
//
// Notes:
//
//--------------------------------------------------------------------------
inline SCODE CFatVector::GetTable( const FSINDEX iTable, const DWORD dwFlags, CFatSect **ppfs) { SCODE sc; sc = CPagedVector::GetTable(iTable, dwFlags, (void **)ppfs); if (sc == STG_S_NEWPAGE) { (*ppfs)->Init(_csectBlock); } return sc; }
//CSEG determines the maximum number of segments that will be
//returned by a single Contig call.
#define CSEG 32
//+-------------------------------------------------------------------------
//
// Class: SSegment (seg)
//
// Purpose: Used for contiguity tables for multi-sector reads and
// writes.
//
// Interface: None.
//
// Notes:
//
//--------------------------------------------------------------------------
struct SSegment { public: SECT sectStart; ULONG cSect; };
class CMStream;
//+----------------------------------------------------------------------
//
// Class: CFat (fat)
//
// Purpose: Main interface to allocation routines
//
// Interface: Allocate - allocates new chain in the FAT
// Extend - Extends an existing FAT chain
// GetNext - Returns next sector in a chain
// GetSect - Returns nth sector in a chain
// GetESect - Returns nth sector in a chain, extending
// if necessary
// GetLength - Returns the # of sectors in a chain
// setup - Initializes for an existing stream
// setupnew - Initializes for a new stream
//
// checksanity - Debugging routine
//
// Notes:
//
//-----------------------------------------------------------------------
class CFat { public: CFat(SID sid, USHORT cbSector, USHORT uSectorShift); ~CFat();
VOID Empty(VOID); inline SCODE Allocate(ULONG ulSize, SECT *psectFirst); SCODE GetNext(const SECT sect, SECT * psRet); SCODE GetSect( SECT sectStart, ULONG ulOffset, SECT *psectReturn); SCODE GetESect( SECT sectStart, ULONG ulOffset, SECT *psectReturn); SCODE SetNext(SECT sectFirst, SECT sectNext); SCODE GetFree(ULONG ulCount, SECT *sect); SCODE GetLength(SECT sect, ULONG * pulRet); SCODE SetChainLength(SECT,ULONG); SCODE Init( CMStream *pmsParent, FSINDEX cFatSect, BOOL fConvert); SCODE InitNew(CMStream *pmsParent); SCODE InitConvert( CMStream *pmsParent, ULONG cbSize); SCODE FindLast(SECT *psectRet); SCODE FindMaxSect(SECT *psectRet); inline SCODE GetMaxSect(SECT *psectRet); SCODE Contig( SSegment STACKBASED *aseg, SECT sect, ULONG ulLength); inline SCODE Flush(VOID); inline void SetParent(CMStream *pms); inline BOOL IsRangeLocksSector (SECT sect); private: CFatVector _fv; CMStream * _pmsParent; const SID _sid; const USHORT _uFatShift; const USHORT _uFatMask; FSINDEX _cfsTable; ULONG _ulFreeSects; SECT _sectFirstFree; SECT _sectMax;
FSINDEX _ipfsRangeLocks; FSOFFSET _isectRangeLocks;
SCODE CountFree(ULONG * ulRet); SCODE Resize(ULONG); SCODE Extend(SECT,ULONG); inline VOID SectToPair( SECT sect, FSINDEX *pipfs, FSOFFSET *pisect) const; inline SECT PairToSect(FSINDEX ipfs, FSOFFSET isect) const; friend class CDIFat;
inline void InitRangeLocksSector();
#ifdef _MSC_VER
#pragma warning(disable:4512)
// since there is a const member, there should be no assignment operator
#endif // _MSC_VER
};
#ifdef _MSC_VER
#pragma warning(default:4512)
#endif // _MSC_VER
inline VOID CFat::SectToPair(SECT sect,FSINDEX *pipfs,FSOFFSET *pisect) const { *pipfs = (FSINDEX)(sect >> _uFatShift); *pisect = (FSOFFSET)(sect & _uFatMask); }
inline SECT CFat::PairToSect(FSINDEX ipfs, FSOFFSET isect) const { return (ipfs << _uFatShift) + isect; }
inline SCODE CFat::GetMaxSect(SECT *psectRet) { SCODE sc; msfChk(FindMaxSect(&_sectMax)); *psectRet = _sectMax; Err: return sc; }
inline void CFat::SetParent(CMStream *pms) { _pmsParent = pms; _fv.SetParent(pms); }
//+-------------------------------------------------------------------------
//
// Member: CFat::Flush, public
//
// Synposis: Write all modified FatSects out to stream
//
// Effects: Resets all dirty bit fields on FatSects
//
// Arguments: Void
//
// Returns: S_OK if call completed OK.
// Error code of parent write otherwise.
//
// Algorithm: Linearly scan through FatSects, writing any sector
// that has the dirty bit set. Reset all dirty bits.
//
// Notes:
//
//---------------------------------------------------------------------------
inline SCODE CFat::Flush(VOID) { return _fv.Flush(); }
//+-------------------------------------------------------------------------
//
// Member: CFat::Allocate, public
//
// Synposis: Allocates a chain within a FAT
//
// Effects: Modifies a single sector within the fat. Causes a
// one sector stream write.
//
// Arguments: [ulSize] -- Number of sectors to allocate in chain
//
// Returns: Sector ID of first sector in chain
//
// Algorithm: Use repetitive calls to GetFree to construct a new chain
//
// Notes:
//
//---------------------------------------------------------------------------
inline SCODE CFat::Allocate(ULONG ulSize, SECT * psectFirst) { return GetFree(ulSize, psectFirst); }
inline void CFat::InitRangeLocksSector () { const ULONG ulHeaderSize = 1 << (_uFatShift + 2); SECT sect = (OLOCKREGIONEND - ulHeaderSize) >> (_uFatShift + 2); SectToPair (sect, &_ipfsRangeLocks, &_isectRangeLocks); }
inline BOOL CFat::IsRangeLocksSector (SECT sect) { FSINDEX ipfs; FSOFFSET isect;
SectToPair(sect, &ipfs, &isect); return (ipfs == _ipfsRangeLocks && isect == _isectRangeLocks); }
#endif //__FAT_HXX__
|