Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

770 lines
22 KiB

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1991-2000.
//
// File: PrpStMgr.hxx
//
// Contents: Two-level property store
//
// Classes: CPropStoreManager
//
// History: 22-Oct-97 KrishnaN Created
//
//----------------------------------------------------------------------------
#pragma once
#include <propstor.hxx>
class CCompositePropRecord;
class CCompositePropRecordForWrites;
class CPrimaryPropRecord;
class CPrimaryPropRecordForWrites;
//+-------------------------------------------------------------------------
//
// Class: CPropStoreManager
//
// Purpose: Property store manager.
//
// History: 22-Oct-97 KrishnaN Created
// 01-Nov-98 KLam Added cMegToLeaveOnDisk to constructors
// Added _cMegToLeaveOnDisk private member
//
//--------------------------------------------------------------------------
class CPropStoreManager
{
public:
//
// Two phase construction (to accomadate late-bound storage)
//
CPropStoreManager( ULONG cMegToLeaveOnDisk );
~CPropStoreManager();
void FastInit( CiStorage * pStorage );
void LongInit( BOOL & fWasDirty, ULONG & cInconsistencies,
T_UpdateDoc pfnUpdateCallback, void const *pUserData );
inline BOOL IsDirty();
void Empty();
//
// Schema manipulation
//
inline BOOL CanStore( PROPID pid );
inline unsigned Size( PROPID pid );
inline ULONG Type( PROPID pid );
inline DWORD StoreLevel( PROPID pid );
inline BOOL CanBeModified( PROPID pid );
ULONG_PTR BeginTransaction();
void Setup( PROPID pid, ULONG vt, DWORD cbMaxLen,
ULONG_PTR ulToken, BOOL fCanBeModified = TRUE,
DWORD dwStoreLevel = PRIMARY_STORE);
void EndTransaction( ULONG_PTR ulToken, BOOL fCommit,
PROPID pidFixedPrimary,
PROPID pidFixedSecondary );
//
// Backup/Load
//
void MakeBackupCopy( IProgressNotify * pIProgressNotify,
BOOL & fAbort,
CiStorage & dstStorage,
ICiEnumWorkids * pIWorkIds,
IEnumString **ppFileList);
void Load( WCHAR const * pwszDestDir,
ICiCAdviseStatus * pAdviseStatus,
IEnumString * pFileList,
IProgressNotify * pProgressNotify,
BOOL fCallerOwnsFiles,
BOOL * pfAbort );
//
// Property storage/retrieval.
//
SCODE WriteProperty( WORKID wid, PROPID pid,
CStorageVariant const & var );
SCODE WriteProperty( CCompositePropRecordForWrites & PropRecord, PROPID pid,
CStorageVariant const & var );
SCODE WriteProperty( CPrimaryPropRecordForWrites & PropRecord,
PROPID pid,
CStorageVariant const & var );
SCODE WriteProperty( DWORD dwStoreLevel,
CCompositePropRecordForWrites & PropRecord,
PROPID pid,
CStorageVariant const & var );
SCODE WritePrimaryProperty( WORKID wid, PROPID pid,
CStorageVariant const & var );
SCODE WritePrimaryProperty( CCompositePropRecordForWrites & PropRecord, PROPID pid,
CStorageVariant const & var );
SCODE WritePrimaryProperty( CPrimaryPropRecordForWrites & PropRecord,
PROPID pid,
CStorageVariant const & var );
SCODE WriteSecondaryProperty( CCompositePropRecordForWrites & PropRecord, PROPID pid,
CStorageVariant const & var );
WORKID WritePropertyInNewRecord( PROPID pid,
CStorageVariant const & var );
BOOL ReadProperty( WORKID wid, PROPID pid, PROPVARIANT * pbData, unsigned * pcb);
BOOL ReadProperty( WORKID wid, PROPID pid, PROPVARIANT & var, BYTE * pbExtra, unsigned * pcbExtra );
BOOL ReadProperty( CCompositePropRecord & PropRecord, PROPID pid, PROPVARIANT & var, BYTE * pbExtra, unsigned * pcbExtra );
BOOL ReadProperty( CPrimaryPropRecord & PropRecord, PROPID pid, PROPVARIANT & var, BYTE * pbExtra, unsigned * pcbExtra );
BOOL ReadProperty( CCompositePropRecord & PropRecord, PROPID pid, PROPVARIANT & var );
BOOL ReadProperty( CPrimaryPropRecord & PropRecord, PROPID pid, PROPVARIANT & var );
BOOL ReadProperty( CCompositePropRecord & PropRecord, PROPID pid, PROPVARIANT * pbData, unsigned * pcb);
BOOL ReadProperty( CPrimaryPropRecord & PropRecord, PROPID pid, PROPVARIANT * pbData, unsigned * pcb);
BOOL ReadProperty( WORKID wid, PROPID pid, PROPVARIANT & var );
CCompositePropRecord * OpenRecord( WORKID wid, BYTE * pb );
CPrimaryPropRecord * OpenPrimaryRecord( WORKID wid, BYTE * pb );
void CloseRecord( CCompositePropRecord * pRec );
void CloseRecord( CPrimaryPropRecord * pRec );
CCompositePropRecordForWrites * OpenRecordForWrites( WORKID wid, BYTE * pb );
CPrimaryPropRecordForWrites * OpenPrimaryRecordForWrites( WORKID wid, BYTE * pb );
void CloseRecord( CCompositePropRecordForWrites * pRec );
void CloseRecord( CPrimaryPropRecordForWrites * pRec );
BOOL ReadPrimaryProperty( WORKID wid, PROPID pid, PROPVARIANT & var );
//
// Special path/wid support
//
inline WORKID MaxWorkId();
void DeleteRecord( WORKID wid );
inline ULONG CountRecordsInUse() const;
void Shutdown();
void Flush();
void MarkBackedUpMode()
{
CLock mtxLock( _mtxWrite );
Flush();
_xPrimaryStore->MarkBackedUpMode();
}
void MarkNotBackedUpMode()
{
CLock mtxLock( _mtxWrite );
Flush();
_xPrimaryStore->MarkNotBackedUpMode();
}
BOOL IsBackedUpMode()
{
return _xPrimaryStore->IsBackedUpMode();
}
inline WORKID MaxWorkId() const
{
return _xPrimaryStore->MaxWorkId();
}
//
// get and set parameters
// If incorrect parameter, default to the primary store.
//
void SetBackupSize(ULONG ulBackupSizeInPages, DWORD dwStoreLevel);
ULONG GetBackupSize(DWORD dwStoreLevel);
void SetMappedCacheSize(ULONG ulPSMappedCache, DWORD dwStoreLevel);
ULONG GetMappedCacheSize(DWORD dwStoreLevel);
ULONG GetTotalSizeInKB();
PStorage& GetStorage(DWORD dwStoreLevel);
inline WORKID GetSecondaryTopLevelWid(WORKID wid);
inline WORKID GetSecondaryTopLevelWid(WORKID wid, CPropRecordNoLock & propRec);
//
// Clean Up
//
void ClearNonStorageProperties( CCompositePropRecordForWrites & rec );
private:
friend CPropertyStoreWids;
friend CCompositePropRecord;
friend CCompositePropRecordForWrites;
friend CPrimaryPropRecord;
friend CPrimaryPropRecordForWrites;
CPropStoreManager(CiStorage * pStorage,
CPropertyStore *pPrimary,
CPropertyStore *pSecondary,
ULONG cMegToLeaveOnDisk );
inline CPropertyStore& GetPrimaryStore()
{
return _xPrimaryStore.GetReference();
}
inline CPropertyStore& GetSecondaryStore()
{
return _xSecondaryStore.GetReference();
}
void Transfer( CPropStoreManager & Target, PROPID pidFixedPrimary,
PROPID pidFixedSecondary, BOOL & fAbort,
IProgressNotify * pProgress = 0 );
//
// Data members
//
CMutexSem _mtxWrite; // Taken to add/remove/modify records
XPtr<CPropertyStore> _xPrimaryStore; // primary property store
XPtr<CPropertyStore> _xSecondaryStore; // secondary property store
CiStorage * _pStorage; // Persistent storage object.
XPtr<CPropStoreManager> _xpsNew; // New metadata stored here
DWORD _dwXctionStoreLevel; // tracks the store used in current transaction
ULONG _cMegToLeaveOnDisk; // Number of megabytes to leave on disk
};
//+---------------------------------------------------------------------------
//
// Member: CPropStoreManager::CanStore, public
//
// Arguments: [pid] -- Propid to check.
//
// Returns: TRUE if [pid] can exist in property store (e.g. has been
// registered).
//
// History: 22-Oct-97 KrishnaN Created.
//
//----------------------------------------------------------------------------
inline BOOL CPropStoreManager::CanStore( PROPID pid )
{
return _xPrimaryStore->CanStore( pid ) ||
_xSecondaryStore->CanStore( pid );
}
//+---------------------------------------------------------------------------
//
// Member: CPropStoreManager::Size, public
//
// Arguments: [pid] -- Propid to check.
//
// Returns: Size of property in store, or 0 if it isn't in store.
//
// History: 22-Oct-97 KrishnaN Created.
//
//----------------------------------------------------------------------------
inline unsigned CPropStoreManager::Size( PROPID pid )
{
unsigned size = _xPrimaryStore->Size( pid );
if (size > 0)
{
Win4Assert (0 == _xSecondaryStore->Size( pid ));
}
else
{
size = _xSecondaryStore->Size( pid );
}
return size;
}
//+---------------------------------------------------------------------------
//
// Member: CPropStoreManager::Type, public
//
// Arguments: [pid] -- Propid to check.
//
// Returns: Type of property in store, or VT_EMPTY if it isn't in store.
//
// History: 22-Oct-97 KrishnaN Created.
//
//----------------------------------------------------------------------------
inline ULONG CPropStoreManager::Type( PROPID pid )
{
ULONG type = _xPrimaryStore->Type( pid );
if (VT_EMPTY != type)
{
Win4Assert( VT_EMPTY == _xSecondaryStore->Type(pid) );
}
else
{
type = _xSecondaryStore->Type( pid );
}
return type;
}
//+---------------------------------------------------------------------------
//
// Member: CPropStoreManager::StoreLevel, public
//
// Arguments: [pid] -- Propid to check.
//
// Returns: Primary or secondary store in which the property resides.
//
// History: 22-Oct-97 KrishnaN Created.
//
//----------------------------------------------------------------------------
inline DWORD CPropStoreManager::StoreLevel( PROPID pid )
{
if (_xPrimaryStore->CanStore( pid ))
return PRIMARY_STORE;
else if (_xSecondaryStore->CanStore( pid ))
return SECONDARY_STORE;
else
return INVALID_STORE_LEVEL;
}
//+---------------------------------------------------------------------------
//
// Member: CPropStoreManager::CanBeModified, public
//
// Arguments: [pid] -- Propid to check.
//
// Returns: True or false store depending on if the property can be modified.
//
// History: 22-Oct-97 KrishnaN Created.
//
//----------------------------------------------------------------------------
inline BOOL CPropStoreManager::CanBeModified( PROPID pid )
{
if (_xPrimaryStore->CanStore( pid ))
return _xPrimaryStore->CanBeModified( pid );
else if (_xSecondaryStore->CanStore( pid ))
return _xSecondaryStore->CanBeModified( pid );
else
{ // if it not in the store, it doesn't matter what the
// reply is. But we will return TRUE so clients like Admin know that
// they can allow the property metadata to be modified.
return TRUE;
}
}
//+---------------------------------------------------------------------------
//
// Member: CPropStoreManager::CountRecordsInUse, public
//
// Returns: Count of 'top level' records (correspond to user wids)
//
// History: 22-Oct-97 KrishnaN Created.
//
//----------------------------------------------------------------------------
inline ULONG CPropStoreManager::CountRecordsInUse() const
{
return _xPrimaryStore->CountRecordsInUse();
}
//+---------------------------------------------------------------------------
//
// Member: CPropStoreManager::MaxWorkId, public
//
// Returns: Maximum workid which has been allocated.
//
// History: 22-Oct-97 KrishnaN Created.
//
//----------------------------------------------------------------------------
inline WORKID CPropStoreManager::MaxWorkId()
{
return _xPrimaryStore->MaxWorkId();
}
//+---------------------------------------------------------------------------
//
// Member: CPropStoreManager::GetSecondaryTopLevelWid, private
//
// Synopsis: Returns WORKID of record in secondary property store.
//
// Arguments: [wid] -- WORKID of record in primary store.
//
// Returns: WORKID -- WORKID in secondary store.
//
// Notes:
//
//----------------------------------------------------------------------------
inline WORKID CPropStoreManager::GetSecondaryTopLevelWid(WORKID wid)
{
PROPVARIANT var;
if (!(_xPrimaryStore->ReadProperty(wid, pidSecondaryStorage, var ) && VT_UI4 == var.vt))
{
ciDebugOut((DEB_PROPSTORE, "NOT using CPropRecord. Primary's"
" ReadRecord failed or invalid type for wid0x%x (%d)\n",
wid, wid));
return widInvalid;
}
#if CIDBG == 1
if (VT_UI4 != var.vt || widInvalid == (WORKID) var.ulVal)
{
ciDebugOut((DEB_PROPSTORE, "NOT using CPropRecord. Invalid sec top-level wid.\n"
"Primary wid is 0x%x (%d), type is 0x%x (%d), value is 0x%x (%d)",
wid, wid, var.vt, var.vt, var.ulVal, var.ulVal));
}
#endif
return (WORKID)var.ulVal;
}
//+---------------------------------------------------------------------------
//
// Member: CPropStoreManager::GetSecondaryTopLevelWid, private
//
// Synopsis: Returns WORKID of record in secondary property store.
//
// Arguments: [wid] -- WORKID of record in primary store.
// [propRec] -- Property record
//
// Returns: WORKID -- WORKID in secondary store.
//
// Notes:
//
//----------------------------------------------------------------------------
inline WORKID CPropStoreManager::GetSecondaryTopLevelWid(WORKID wid,
CPropRecordNoLock & propRec)
{
PROPVARIANT var;
unsigned cbSize = sizeof var;
if (!(_xPrimaryStore->ReadProperty(propRec, pidSecondaryStorage, &var, &cbSize ) && VT_UI4 == var.vt))
{
ciDebugOut((DEB_PROPSTORE, "Using CPropRecord. Primary's"
" ReadRecord failed or invalid type for wid0x%x (%d)\n",
wid, wid));
return widInvalid;
}
#if CIDBG == 1
if (VT_UI4 != var.vt || widInvalid == (WORKID) var.ulVal)
{
ciDebugOut((DEB_PROPSTORE,
"Using CPropRecord. Invalid sec top-level wid.\n"
"Primary wid is 0x%x (%d), type is 0x%x (%d), value is 0x%x (%d)",
wid, wid, var.vt, var.vt, var.ulVal, var.ulVal));
}
#endif
return (WORKID)var.ulVal;
}
inline BOOL CPropStoreManager::IsDirty()
{
return _xPrimaryStore->IsDirty() ||
_xSecondaryStore->IsDirty();
}
//+-------------------------------------------------------------------------
//
// Class: CCompositeProgressNotifier
//
// Purpose: Use this class to provide accurate progress reports
// by accounting for the presence of multiple property stores
// instead of one. For example, given a composite property store
// containing two individual stores, when the first store is 100%
// done, we should report that the composite two-level store is
// only 50% done.
//
// History: 22-Oct-97 KrishnaN Created
//
//--------------------------------------------------------------------------
class CCompositeProgressNotifier : public IProgressNotify
{
public:
// constructor
// This class will own aulMaxSizes array and delete it at
// the end. The caller should be aware of that.
CCompositeProgressNotifier(IProgressNotify *pProgressNotify,
DWORD aulMaxSizes[],
short cComponents = 2) :
_aulMaxSizes( aulMaxSizes ),
_cComponents( cComponents ),
_cFinishedComponents( 0 ),
_dwCumMaxSize( 0 ),
_dwTotalMaxSize( 0 )
{
if (pProgressNotify)
{
Win4Assert(aulMaxSizes && cComponents);
_xComponentProgressNotifier.Set(pProgressNotify);
pProgressNotify->AddRef();
XArray<DWORD> _xdwTemp(cComponents);
short i;
// scale all the max values to the 0-1000 range.
for (i = 0; i < cComponents; i++)
{
_xdwTemp[i] = (DWORD) (((DOUBLE)_aulMaxSizes[i] / (DOUBLE)0xFFFFFFFF) * 1000.0);
_dwTotalMaxSize += _xdwTemp[i];
}
// avoid divide by zero
_dwTotalMaxSize = _dwTotalMaxSize ? _dwTotalMaxSize : 1;
RtlCopyMemory(aulMaxSizes, _xdwTemp.GetPointer(), cComponents*sizeof(DWORD));
}
}
// Control progress reporting
void IncrementFinishedComponents()
{
_dwCumMaxSize += _aulMaxSizes[_cFinishedComponents];
_cFinishedComponents++;
Win4Assert(_cFinishedComponents <= _cComponents);
}
//
// IUnknown methods.
//
STDMETHOD(QueryInterface) (THIS_ REFIID riid, void ** ppvObj);
STDMETHOD_(ULONG,AddRef) (THIS);
STDMETHOD_(ULONG,Release) (THIS);
//
// IProgressNotify methods.
//
STDMETHOD(OnProgress) ( DWORD dwProgressCurrent, //Amount of data available
DWORD dwProgressMaximum, //Total amount of data to be downloaded
BOOL fAccurate, //Reliability of notifications
BOOL fOwner //Ownership of blocking behavior
);
private:
XInterface<IProgressNotify> _xComponentProgressNotifier;
DWORD *_aulMaxSizes;
short _cComponents;
short _cFinishedComponents;
LONG _ref;
DWORD _dwCumMaxSize;
DWORD _dwTotalMaxSize;
};
//+-------------------------------------------------------------------------
//
// Class: XWriteCompositeRecord
//
// Purpose: Smart pointer for a writable composite property store record
//
// History: 02-Jan-999 dlee Created
//
//--------------------------------------------------------------------------
class XWriteCompositeRecord
{
public:
XWriteCompositeRecord( CPropStoreManager & mgr, WORKID wid ) :
_mgr( mgr )
{
BYTE * pb = (BYTE *) ( ( (ULONG_PTR) ( _aBuf + 1 ) ) & ( ~7 ) );
_pPropRec = _mgr.OpenRecordForWrites( wid, pb );
}
~XWriteCompositeRecord()
{
Free();
}
void Free()
{
if ( 0 != _pPropRec )
{
_mgr.CloseRecord( _pPropRec );
_pPropRec = 0;
}
}
void Set( CCompositePropRecordForWrites * pPropRec )
{
Win4Assert( 0 == _pPropRec );
_pPropRec = pPropRec;
}
CCompositePropRecordForWrites * Acquire()
{
CCompositePropRecordForWrites * p = _pPropRec;
_pPropRec = 0;
return p;
}
CCompositePropRecordForWrites * Get() { return _pPropRec; }
CCompositePropRecordForWrites & GetReference() { return *_pPropRec; }
private:
CCompositePropRecordForWrites * _pPropRec;
CPropStoreManager & _mgr;
LONGLONG _aBuf[ 1 + ( sizeof_CCompositePropRecord / sizeof( LONGLONG ) ) ];
};
//+-------------------------------------------------------------------------
//
// Class: XWritePrimaryRecord
//
// Purpose: Smart pointer for a writable primary property store record
//
// History: 02-Jan-999 dlee Created
//
//--------------------------------------------------------------------------
class XWritePrimaryRecord
{
public:
XWritePrimaryRecord( CPropStoreManager & mgr, WORKID wid ) :
_mgr( mgr )
{
BYTE * pb = (BYTE *) ( ( (ULONG_PTR) ( _aBuf + 1 ) ) & ( ~7 ) );
_pPropRec = _mgr.OpenPrimaryRecordForWrites( wid, pb );
}
~XWritePrimaryRecord()
{
Free();
}
void Free()
{
if ( 0 != _pPropRec )
{
_mgr.CloseRecord( _pPropRec );
_pPropRec = 0;
}
}
void Set( CPrimaryPropRecordForWrites * pPropRec )
{
Win4Assert( 0 == _pPropRec );
_pPropRec = pPropRec;
}
CPrimaryPropRecordForWrites * Acquire()
{
CPrimaryPropRecordForWrites * p = _pPropRec;
_pPropRec = 0;
return p;
}
CPrimaryPropRecordForWrites * Get() { return _pPropRec; }
CPrimaryPropRecordForWrites & GetReference() { return *_pPropRec; }
private:
CPrimaryPropRecordForWrites * _pPropRec;
CPropStoreManager & _mgr;
LONGLONG _aBuf[ 1 + ( sizeof_CPropRecord / sizeof( LONGLONG ) ) ];
};
//+-------------------------------------------------------------------------
//
// Class: XPrimaryRecord
//
// Purpose: Smart pointer for a primary property store record
//
// History: 02-Jan-999 dlee Created
//
//--------------------------------------------------------------------------
class XPrimaryRecord
{
public:
XPrimaryRecord( CPropStoreManager & mgr, WORKID wid ) :
_mgr( mgr )
{
BYTE * pb = (BYTE *) ( ( (ULONG_PTR) ( _aBuf + 1 ) ) & ( ~7 ) );
//ciDebugOut(( DEB_FORCE, "_aBuf %#x, pb %#x\n", _aBuf, pb ));
Win4Assert( pb >= (BYTE *) &_aBuf );
_pPropRec = _mgr.OpenPrimaryRecord( wid, pb );
}
~XPrimaryRecord()
{
Free();
}
void Free()
{
if ( 0 != _pPropRec )
{
_mgr.CloseRecord( _pPropRec );
_pPropRec = 0;
}
}
void Set( CPrimaryPropRecord * pPropRec )
{
Win4Assert( 0 == _pPropRec );
_pPropRec = pPropRec;
}
CPrimaryPropRecord * Acquire()
{
CPrimaryPropRecord * p = _pPropRec;
_pPropRec = 0;
return p;
}
CPrimaryPropRecord * Get() { return _pPropRec; }
CPrimaryPropRecord & GetReference() { return *_pPropRec; }
private:
CPrimaryPropRecord * _pPropRec;
CPropStoreManager & _mgr;
LONGLONG _aBuf[ 1 + ( sizeof_CPropRecord / sizeof( LONGLONG ) ) ];
};