//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1991 - 2000. // // File: VMap.hxx // // Contents: Virtual <--> physical path map. // // Classes: CVMap // // History: 05-Feb-96 KyleP Created // //---------------------------------------------------------------------------- #pragma once #include #include #include #include const unsigned INVALID_VMAP_INDEX = 0xFFFFFFFF; //+------------------------------------------------------------------------- // // Class: CVMapDesc // // Purpose: Description of single scope mapping // // History: 05-Feb-96 KyleP Created // //-------------------------------------------------------------------------- class CVMapDesc { public: inline CVMapDesc(); void Init( WCHAR const * pVRoot, ULONG ccVRoot, WCHAR const * pPRoot, ULONG ccPRoot, ULONG idParent, BOOL fAutomatic, CiVRootTypeEnum eType, BOOL fIsIndexed, BOOL fNonIndexedVDir ); inline unsigned PhysicalMatchLen( WCHAR const * path ) const; inline BOOL IsInPhysicalScope( WCHAR const * root, unsigned cc ) const; BOOL IsVirtualMatch( WCHAR const * pVPath, unsigned ccVPath ) const; BOOL IsPhysicalMatch( WCHAR const * pVPath, unsigned ccVPath ) const; inline ULONG Parent() const { return _idParent; } inline void SetParent( ULONG idParent ) { _idParent = idParent; } inline BOOL IsFree() { return (0 == _ccVScope); } inline void Delete() { _ccVScope = 0; } inline WCHAR const * PhysicalPath() const { return _wcPScope; } inline ULONG PhysicalLength() const { return _ccPScope; } inline WCHAR const * VirtualPath() const { return _wcVScope; } inline ULONG VirtualLength() const { return _ccVScope; } inline void SetAutomatic() { _Type |= PCatalog::AutomaticRoot; } inline void ClearAutomatic() { _Type &= ~PCatalog::AutomaticRoot; } inline BOOL IsAutomatic() const { return (_Type & PCatalog::AutomaticRoot); } inline void SetManual() { _Type |= PCatalog::ManualRoot; } inline void ClearManual() { _Type &= ~PCatalog::ManualRoot; } inline BOOL IsManual() const { return (_Type & PCatalog::ManualRoot); } inline void ClearInUse() { _Type &= ~PCatalog::UsedRoot; } inline BOOL IsInUse() const { return (_Type & PCatalog::UsedRoot); } inline BOOL IsNNTP() const { return 0 != (_Type & PCatalog::NNTPRoot); } inline BOOL IsIMAP() const { return 0 != (_Type & PCatalog::IMAPRoot); } inline BOOL IsW3() const { return !IsNNTP() && !IsIMAP(); } inline BOOL IsNonIndexedVDir() const { return 0 != (_Type & PCatalog::NonIndexedVDir); } inline void SetNonIndexedVDir() { _Type |= PCatalog::NonIndexedVDir; } inline void ClearNonIndexedVDir() { _Type &= ~PCatalog::NonIndexedVDir; } inline ULONG RootType() { return _Type; } private: ULONG _ccVScope; WCHAR _wcVScope[MAX_PATH]; // Virtual scope // IIS currently doesn't allow paths greater // than MAX_PATH. This is not a good reason for we to also not // support, but there are lot of complications right now, like // in place serialization of variable data, so currently we have the // MAX_PATH restriction of VPaths and for scopes. ULONG _ccPScope; WCHAR _wcPScope[MAX_PATH]; // Physical scope ULONG _idParent; // Link to parent (INVALID_VMAP_INDEX --> top level) ULONG _Type; }; //+------------------------------------------------------------------------- // // Class: CVMap // // Purpose: Virtual/Physical path map // // History: 05-Feb-96 KyleP Created // //-------------------------------------------------------------------------- class CVMap { public: CVMap(); BOOL Init( PRcovStorageObj * obj ); void Empty(); BOOL Add( WCHAR const * vroot, WCHAR const * root, BOOL fAutomatic, ULONG & idNew, CiVRootTypeEnum eType, BOOL fVRoot, BOOL fIsIndexed ); BOOL Remove( WCHAR const * vroot, BOOL fOnlyIfAutomatic, ULONG & idOld, ULONG & idNew, CiVRootTypeEnum eType, BOOL fVRoot ); void MarkClean(); BOOL IsClean() const { return !_fDirty; } inline BOOL IsInPhysicalScope( ULONG id, WCHAR const * root, unsigned cc ); ULONG PhysicalPathToId( WCHAR const * path ); BOOL VirtualToPhysicalRoot( WCHAR const * pwcVRoot, unsigned ccVRoot, CLowerFunnyPath & lcaseFunnyPRoot, unsigned & ccPRoot ); BOOL VirtualToPhysicalRoot( WCHAR const * pwcVPath, unsigned ccVPath, XGrowable & xwcsVRoot, unsigned & ccVRoot, CLowerFunnyPath & lcaseFunnyPRoot, unsigned & ccPRoot, unsigned & iBmk ); BOOL VirtualToAllPhysicalRoots( WCHAR const * pwcVPath, unsigned ccVPath, XGrowable & xwcsVRoot, unsigned & ccVRoot, CLowerFunnyPath & lcaseFunnyPRoot, unsigned & ccPRoot, ULONG & ulType, unsigned & iBmk ); ULONG EnumerateRoot( XGrowable & xwcVRoot, unsigned & ccVRoot, CLowerFunnyPath & lcaseFunnyPRoot, unsigned & ccPRoot, unsigned & iBmk ); BOOL DoesPhysicalRootExist( WCHAR const * pwcPRoot ); inline CVMapDesc const & GetDesc( ULONG id ) const; // // Path chaining. // inline ULONG Parent( ULONG id ) const; inline ULONG FindNthRemoved( ULONG id, unsigned cSkip ) const; BOOL IsNonIndexedVDir( ULONG id ) const { if ( INVALID_VMAP_INDEX == id ) return FALSE; return _aMap[id].IsNonIndexedVDir(); } ULONG GetExcludeParent( ULONG id ) const { Win4Assert( id < _aExcludeParent.Count() ); return _aExcludeParent[ id ]; } BOOL IsAnExcludeParent( ULONG id ) const { if ( INVALID_VMAP_INDEX == id ) return FALSE; for ( unsigned x = 0; x < _aExcludeParent.Count(); x++ ) if ( _aExcludeParent[x] == id ) return TRUE; return FALSE; } private: ULONG PhysicalPathToId( WCHAR const * path, BOOL fNonIndexedVDirs ); void DumpVMap(); void RecomputeNonIndexedInfo(); BOOL _fDirty; // TRUE if vmap went down dirty CMutexSem _mutex; CDynArrayInPlace _aMap; CDynArrayInPlace _aExcludeParent; XPtr _xrsoMap; }; //+------------------------------------------------------------------------- // // Member: CVMapDesc::PhysicalMatchLen, private // // Synopsis: Compares input with physical path // // Arguments: [pPPath] -- Physical path. // // Returns: 0 if [pPPath] does not match physical path complete to // the end of the short of the two. On success returns // length of physical path. // // History: 07-Feb-96 KyleP Created. // //-------------------------------------------------------------------------- inline unsigned CVMapDesc::PhysicalMatchLen( WCHAR const * pPPath ) const { Win4Assert( *pPPath ); // // Compare strings. // unsigned i = 0; while ( *pPPath && i < _ccPScope && *pPPath == _wcPScope[i] ) { i++; pPPath++; } // // Adjust for possible lack of terminating backslash. // if ( 0 == *pPPath ) { if ( *(pPPath - 1) == L'\\' ) return _ccPScope; else { if ( _wcPScope[i] == L'\\' ) return _ccPScope; else return 0; } } else { if ( i >= _ccPScope ) return _ccPScope; else return 0; } } //+------------------------------------------------------------------------- // // Member: CVMapDesc::CVMapDesc, private // // Synopsis: Constructor // // History: 07-Feb-96 KyleP Created. // //-------------------------------------------------------------------------- inline CVMapDesc::CVMapDesc() : _ccVScope( 0 ), _ccPScope( 0 ) { } //+------------------------------------------------------------------------- // // Member: CVMapDesc::IsInPhysicalScope, public // // Synopsis: Compares input with physical path // // Arguments: [root] -- Physical path. // [cc] -- Size, in chars, of [root] // // Returns: TRUE if [root] is within physical scope. // // History: 07-Feb-96 KyleP Created. // //-------------------------------------------------------------------------- inline BOOL CVMapDesc::IsInPhysicalScope( WCHAR const * root, unsigned cc ) const { Win4Assert( root[cc-1] != L'\\' ); CScopeMatch Match( _wcPScope, _ccPScope ); // // Be careful not to match root of scope. // return Match.IsInScope( root, cc ) && (_ccPScope != cc + 1); } //+------------------------------------------------------------------------- // // Member: CVMap::IsInPhysicalScope, public // // Synopsis: Compares input with physical path // // Arguments: [id] -- Id of virtual/physical scope // [root] -- Physical path. // [cc] -- Size, in chars, of [root] // // Returns: TRUE if [root] is within physical scope. // // History: 07-Feb-96 KyleP Created. // //-------------------------------------------------------------------------- inline BOOL CVMap::IsInPhysicalScope( ULONG id, WCHAR const * root, unsigned cc ) { CLock lock(_mutex); Win4Assert( id < _aMap.Count() ); return _aMap[id].IsInPhysicalScope( root, cc ); } //+------------------------------------------------------------------------- // // Member: CVMap::Parent, public // // Arguments: [id] -- Id of virtual/physical scope // // Returns: Virtual/physical id of parent. // // History: 07-Feb-96 KyleP Created. // //-------------------------------------------------------------------------- inline ULONG CVMap::Parent( ULONG id ) const { Win4Assert( id < _aMap.Count() ); return _aMap[id].Parent(); } //+------------------------------------------------------------------------- // // Member: CVMap::FindNthRemoved, public // // Synopsis: Walks up virtual root chain to the Nth link. // // Arguments: [id] -- Id of starting virtual/physical scope // [cSkip] -- Number of links to skip // // Returns: Virtual/physical id of Nth parent. // // History: 07-Feb-96 KyleP Created. // //-------------------------------------------------------------------------- inline ULONG CVMap::FindNthRemoved( ULONG id, unsigned cSkip ) const { Win4Assert( id == INVALID_VMAP_INDEX || id < _aMap.Count() ); while ( id != INVALID_VMAP_INDEX && !_aMap[id].IsFree() && cSkip > 0 ) { id = _aMap[id].Parent(); cSkip--; } if ( INVALID_VMAP_INDEX != id && _aMap[id].IsFree() ) id = INVALID_VMAP_INDEX; return id; } //+------------------------------------------------------------------------- // // Member: CVMap::GetDesc, public // // Arguments: [id] -- Id of virtual/physical scope // // Returns: Scope descriptor for [id] // // History: 07-Feb-96 KyleP Created. // //-------------------------------------------------------------------------- inline CVMapDesc const & CVMap::GetDesc( ULONG id ) const { Win4Assert( id < _aMap.Count() ); return _aMap[id]; }