420 lines
14 KiB
C++
420 lines
14 KiB
C++
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1991 - 1998.
|
|
//
|
|
// File: Strings.hxx
|
|
//
|
|
// Contents: Fast (hashed) access to paths for downlevel ci.
|
|
//
|
|
// History: 09-Mar-92 BartoszM Created
|
|
// 15-Mar-93 BartoszM Converted to memory mapped streams
|
|
// 03-Jan-96 KyleP Integrate with property cache
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#pragma once
|
|
|
|
#include <prpstmgr.hxx>
|
|
#include <propobj.hxx>
|
|
#include <smatch.hxx>
|
|
|
|
#include "pershash.hxx"
|
|
#include "vmap.hxx"
|
|
|
|
class CiCat;
|
|
|
|
class CCompositePropRecord;
|
|
|
|
#define SEEN_NOT 0
|
|
#define SEEN_YES 1
|
|
#define SEEN_NEW 2
|
|
#define SEEN_IGNORE 3
|
|
|
|
#define SEEN_MASK 3
|
|
#define SEEN_BITS 2
|
|
#define SEEN_PER_BYTE 4
|
|
|
|
inline void SET_SEEN( CDynArrayInPlace<BYTE> * parray, WORKID wid, ULONG value )
|
|
{
|
|
(*parray)[wid/SEEN_PER_BYTE] &= ~(SEEN_MASK << ((wid % SEEN_PER_BYTE) * SEEN_BITS));
|
|
(*parray)[wid/SEEN_PER_BYTE] |= value << ((wid % SEEN_PER_BYTE) * SEEN_BITS);
|
|
}
|
|
|
|
inline ULONG GET_SEEN( CDynArrayInPlace<BYTE> * parray, WORKID wid )
|
|
{
|
|
return ( (*parray)[wid/SEEN_PER_BYTE] >> ((wid % SEEN_PER_BYTE) * SEEN_BITS) ) & SEEN_MASK;
|
|
}
|
|
|
|
enum ESeenArrayType {eScansArray, eUsnsArray};
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Class: CStrings
|
|
//
|
|
// Purpose: Provides for quick (hashed) lookup of strings
|
|
//
|
|
// History: 28-Dec-95 KyleP Created
|
|
//
|
|
// Notes: This class is a bit odd. In manages the hash table, but
|
|
// does not control the memory used to store it. This strange
|
|
// behaviour allows the hash table to be stored persistently.
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
class CStrings : public CPersHash
|
|
{
|
|
|
|
public:
|
|
|
|
//
|
|
// Two-phase construction.
|
|
//
|
|
|
|
CStrings( CPropStoreManager & PropStoreMgr, CiCat & cicat );
|
|
void Abort() { _fAbort = TRUE; }
|
|
|
|
virtual BOOL FastInit ( CiStorage * pStorage,ULONG version );
|
|
virtual void LongInit ( ULONG version, BOOL fDirtyShutdown );
|
|
virtual void Empty();
|
|
|
|
//
|
|
// Lookup
|
|
//
|
|
|
|
WORKID LokFind( WCHAR const * buf );
|
|
inline WORKID LokFind( const CLowerFunnyPath & lcaseFunnyPath, BOOL fUsnVolume );
|
|
BOOL Find( WORKID wid, FILETIME & ftLastSeen );
|
|
unsigned Find( WORKID wid, XGrowable<WCHAR> & xBuf );
|
|
unsigned Find( CCompositePropRecord & PropRec, XGrowable<WCHAR> & xBuf );
|
|
unsigned Find( WORKID wid, CFunnyPath & funnyPath );
|
|
unsigned Find( CCompositePropRecord & PropRec, CFunnyPath & funnyPath );
|
|
unsigned Find( WORKID wid, CLowerFunnyPath & lcaseFunnyPath );
|
|
unsigned Find( CCompositePropRecord & PropRec, CLowerFunnyPath & lcaseFunnyPath );
|
|
|
|
//
|
|
// Modification
|
|
//
|
|
|
|
WORKID LokAdd( WCHAR const * pwcPath,
|
|
FILEID fileId,
|
|
BOOL fUsnVolume,
|
|
WORKID widParent,
|
|
ULONG ulAttrib = 0,
|
|
FILETIME const * pftLastWrite = 0 );
|
|
|
|
void LokDelete( WCHAR const * pwcPath, // Note: Has to be lowercase
|
|
WORKID wid,
|
|
BOOL fDisableDeletionCheck=FALSE,
|
|
BOOL fUsnVolume = FALSE );
|
|
|
|
void LokRenameFile( const WCHAR * pwcsOldFileName,
|
|
const WCHAR * pwcsNewFileName,
|
|
WORKID wid,
|
|
ULONG ulFileAttrib,
|
|
VOLUMEID volumeId,
|
|
WORKID widParent = widInvalid );
|
|
|
|
//
|
|
// 'Seen' processing.
|
|
//
|
|
|
|
void BeginSeen( WCHAR const * pwcsRoot,
|
|
CMutexSem & mutex,
|
|
ESeenArrayType eType );
|
|
inline void LokEndSeen( ESeenArrayType eType );
|
|
|
|
inline void LokSetSeen ( WORKID wid, ESeenArrayType eType );
|
|
inline BOOL LokNotSeen(WORKID wid, ESeenArrayType eType);
|
|
inline BOOL LokSeenNew(WORKID wid, ESeenArrayType eType);
|
|
|
|
//
|
|
// Virtual path changes.
|
|
//
|
|
|
|
BOOL AddVirtualScope( WCHAR const * vroot,
|
|
WCHAR const * root,
|
|
BOOL fAutomatic = FALSE,
|
|
CiVRootTypeEnum eType = W3VRoot,
|
|
BOOL fVRoot = FALSE,
|
|
BOOL fIsIndexed = FALSE );
|
|
|
|
BOOL RemoveVirtualScope( WCHAR const * vroot,
|
|
BOOL fOnlyIfAutomatic,
|
|
CiVRootTypeEnum eType,
|
|
BOOL fVRoot,
|
|
BOOL fForceVPathFixing );
|
|
|
|
unsigned FindVirtual( WORKID wid, unsigned cSkip, XGrowable<WCHAR> & xBuf );
|
|
unsigned FindVirtual( CCompositePropRecord & PropRec, unsigned cSkip, XGrowable<WCHAR> & xBuf );
|
|
|
|
inline BOOL VirtualToPhysicalRoot( WCHAR const * pwcVRoot,
|
|
unsigned ccVRoot,
|
|
CLowerFunnyPath & lcaseFunnyPRoot,
|
|
unsigned & ccPRoot );
|
|
|
|
inline BOOL VirtualToPhysicalRoot( WCHAR const * pwcVPath,
|
|
unsigned ccVPath,
|
|
XGrowable<WCHAR> & xwcsVRoot,
|
|
unsigned & ccVRoot,
|
|
CLowerFunnyPath & lcaseFunnyPRoot,
|
|
unsigned & ccPRoot,
|
|
unsigned & iBmk );
|
|
|
|
inline BOOL VirtualToAllPhysicalRoots( WCHAR const * pwcVPath,
|
|
unsigned ccVPath,
|
|
XGrowable<WCHAR> & xwcsVRoot,
|
|
unsigned & ccVRoot,
|
|
CLowerFunnyPath & lcaseFunnyPRoot,
|
|
unsigned & ccPRoot,
|
|
ULONG & ulType,
|
|
unsigned & iBmk );
|
|
|
|
inline ULONG EnumerateVRoot( XGrowable<WCHAR> & xwcVRoot,
|
|
unsigned & ccVRoot,
|
|
CLowerFunnyPath & lcaseFunnyPRoot,
|
|
unsigned & ccPRoot,
|
|
unsigned & iBmk );
|
|
|
|
BOOL DoesPhysicalRootExist( WCHAR const * pwcPRoot )
|
|
{
|
|
return _vmap.DoesPhysicalRootExist( pwcPRoot );
|
|
}
|
|
|
|
#ifdef CI_USE_JET
|
|
//
|
|
// To allocate a free workid
|
|
//
|
|
WORKID AllocWorkid( WCHAR const * pwszPath = 0 ); // virtual method of PWidGenerator
|
|
#endif // CI_USE_JET
|
|
|
|
|
|
private:
|
|
|
|
WORKID LokParentWorkId( WCHAR const *pwcsFileName, BOOL fUsnVolume );
|
|
|
|
static unsigned HashFun ( WCHAR const * str );
|
|
|
|
void ReVirtualize();
|
|
|
|
void _Find( CCompositePropRecord & PropRec, WCHAR * buf, unsigned & cc );
|
|
|
|
//
|
|
// Error recovery.
|
|
//
|
|
virtual BOOL ReInit( ULONG version );
|
|
virtual void HashAll();
|
|
|
|
CDynArrayInPlace<BYTE> _afSeenScans; // 'Seen' bytes for scans
|
|
CDynArrayInPlace<BYTE> _afSeenUsns; // 'Seen' bytes for usns
|
|
|
|
FILETIME _ftSeen; // Start of current 'seen' processing.
|
|
|
|
CVMap _vmap; // Virtual/Physical path map
|
|
CiCat & _cicat; // Catalog
|
|
};
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CStrings::LokEndSeen, public
|
|
//
|
|
// Synopsis: Complete the 'seen' process.
|
|
//
|
|
// Arguments: [eType] -- Seen array type
|
|
//
|
|
// History: 11-Jan-96 KyleP Added header.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
inline void CStrings::LokEndSeen( ESeenArrayType eType )
|
|
{
|
|
ciDebugOut(( DEB_ITRACE, "EndSeen 0x%x\n", eType ));
|
|
|
|
if ( eScansArray == eType )
|
|
{
|
|
_afSeenScans.Clear();
|
|
|
|
FILETIME * pft = (FILETIME *)_pStreamHash->Get();
|
|
*pft = _ftSeen;
|
|
}
|
|
else
|
|
{
|
|
_afSeenUsns.Clear();
|
|
}
|
|
} //LokEndSeen
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CStrings::LokSetSeen, public
|
|
//
|
|
// Synopsis: Mark a workid as seen.
|
|
//
|
|
// Arguments: [wid] -- Workid
|
|
// [eType] -- Seen array type
|
|
//
|
|
// History: 11-Jan-96 KyleP Added header.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
inline void CStrings::LokSetSeen( WORKID wid, ESeenArrayType eType )
|
|
{
|
|
Win4Assert( wid != widInvalid );
|
|
|
|
CDynArrayInPlace<BYTE> *pafSeen;
|
|
if ( eType == eScansArray )
|
|
pafSeen = &_afSeenScans;
|
|
else
|
|
pafSeen = &_afSeenUsns;
|
|
|
|
if ( 0 != pafSeen->Size() )
|
|
SET_SEEN( pafSeen, wid, SEEN_YES );
|
|
} //LokSetSeen
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CStrings::LokNotSeen, public
|
|
//
|
|
// Arguments: [wid] -- Workid
|
|
// [eType] -- Seen array type
|
|
//
|
|
// Returns: TRUE if [wid] has not been seen.
|
|
//
|
|
// History: 11-Jan-96 KyleP Added header.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
inline BOOL CStrings::LokNotSeen( WORKID wid, ESeenArrayType eType )
|
|
{
|
|
Win4Assert( wid != widInvalid );
|
|
|
|
CDynArrayInPlace<BYTE> *pafSeen;
|
|
if ( eType == eScansArray )
|
|
pafSeen = &_afSeenScans;
|
|
else
|
|
pafSeen = &_afSeenUsns;
|
|
|
|
Win4Assert( 0 != pafSeen->Size() );
|
|
|
|
if ( _fAbort )
|
|
THROW( CException(STATUS_TOO_LATE) );
|
|
|
|
return GET_SEEN( pafSeen, wid ) == SEEN_NOT;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CStrings::LokSeenNew, public
|
|
//
|
|
// Arguments: [wid] -- Workid
|
|
// [eType] -- Seen array type
|
|
//
|
|
// Returns: TRUE if [wid] is new (added since beginning of seen processing)
|
|
//
|
|
// History: 11-Jan-96 KyleP Added header.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
inline BOOL CStrings::LokSeenNew(WORKID wid, ESeenArrayType eType )
|
|
{
|
|
Win4Assert( wid != widInvalid );
|
|
|
|
CDynArrayInPlace<BYTE> *pafSeen;
|
|
if ( eType == eScansArray )
|
|
pafSeen = &_afSeenScans;
|
|
else
|
|
pafSeen = &_afSeenUsns;
|
|
|
|
Win4Assert( 0 != pafSeen->Size() );
|
|
|
|
if ( _fAbort )
|
|
THROW( CException(STATUS_TOO_LATE) );
|
|
|
|
return GET_SEEN( pafSeen, wid ) == SEEN_NEW;
|
|
}
|
|
|
|
inline BOOL CStrings::VirtualToPhysicalRoot( WCHAR const * pwcVRoot,
|
|
unsigned ccVRoot,
|
|
CLowerFunnyPath & lcaseFunnyPRoot,
|
|
unsigned & ccPRoot )
|
|
{
|
|
return _vmap.VirtualToPhysicalRoot( pwcVRoot,
|
|
ccVRoot,
|
|
lcaseFunnyPRoot,
|
|
ccPRoot );
|
|
}
|
|
|
|
inline BOOL CStrings::VirtualToPhysicalRoot( WCHAR const * pwcVPath,
|
|
unsigned ccVPath,
|
|
XGrowable<WCHAR> & xwcsVRoot,
|
|
unsigned & ccVRoot,
|
|
CLowerFunnyPath & lcaseFunnyPRoot,
|
|
unsigned & ccPRoot,
|
|
unsigned & iBmk )
|
|
{
|
|
return _vmap.VirtualToPhysicalRoot( pwcVPath,
|
|
ccVPath,
|
|
xwcsVRoot,
|
|
ccVRoot,
|
|
lcaseFunnyPRoot,
|
|
ccPRoot,
|
|
iBmk );
|
|
}
|
|
|
|
inline BOOL CStrings::VirtualToAllPhysicalRoots( WCHAR const * pwcVPath,
|
|
unsigned ccVPath,
|
|
XGrowable<WCHAR> & xwcsVRoot,
|
|
unsigned & ccVRoot,
|
|
CLowerFunnyPath & lcaseFunnyPRoot,
|
|
unsigned & ccPRoot,
|
|
ULONG & ulType,
|
|
unsigned & iBmk )
|
|
{
|
|
return _vmap.VirtualToAllPhysicalRoots( pwcVPath,
|
|
ccVPath,
|
|
xwcsVRoot,
|
|
ccVRoot,
|
|
lcaseFunnyPRoot,
|
|
ccPRoot,
|
|
ulType,
|
|
iBmk );
|
|
}
|
|
|
|
|
|
inline ULONG CStrings::EnumerateVRoot( XGrowable<WCHAR> & xwcVRoot,
|
|
unsigned & ccVRoot,
|
|
CLowerFunnyPath & lcaseFunnyPRoot,
|
|
unsigned & ccPRoot,
|
|
unsigned & iBmk )
|
|
{
|
|
return _vmap.EnumerateRoot( xwcVRoot,
|
|
ccVRoot,
|
|
lcaseFunnyPRoot,
|
|
ccPRoot,
|
|
iBmk );
|
|
}
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Member: CStrings::FindVirtual, private
|
|
//
|
|
// Synopsis: Given workid, find virtual path.
|
|
//
|
|
// Arguments: [wid] -- Workid to locate
|
|
// [cSkip] -- Count of paths to skip.
|
|
// [buf] -- String returned here
|
|
// [cc] -- On input: size in WCHARs of [buf]. On output,
|
|
// size required or 0 if string not found.
|
|
//
|
|
// History: 07-Feb-96 KyleP Created.
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
inline unsigned CStrings::FindVirtual( WORKID wid, unsigned cSkip, XGrowable<WCHAR> & xBuf )
|
|
{
|
|
CCompositePropRecord PropRec( wid, _PropStoreMgr );
|
|
|
|
return FindVirtual( PropRec, cSkip, xBuf );
|
|
}
|
|
|
|
|