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.
1518 lines
51 KiB
1518 lines
51 KiB
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1991 - 2002.
|
|
//
|
|
// File: PrpStMgr.cxx
|
|
//
|
|
// Contents: A two-level property store.
|
|
//
|
|
// Classes: CPropStoreManager
|
|
//
|
|
// History: 24-Oct-1997 KrishnaN Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include <pch.cxx>
|
|
#pragma hdrstop
|
|
|
|
#include <prpstmgr.hxx>
|
|
#include <propobj.hxx>
|
|
#include <eventlog.hxx>
|
|
#include <catalog.hxx>
|
|
#include <imprsnat.hxx>
|
|
#include <propiter.hxx>
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CPropStoreManager::CPropStoreManager, public
|
|
//
|
|
// Synopsis: Constructs the class.
|
|
//
|
|
// History: 24-Oct-97 KrishnaN Created.
|
|
// 01-Nov-98 KLam Added cMegToLeaveOnDisk to constructor
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CPropStoreManager::CPropStoreManager( ULONG cMegToLeaveOnDisk )
|
|
: _pStorage( 0 ),
|
|
_xPrimaryStore( 0 ),
|
|
_xSecondaryStore( 0 ),
|
|
_dwXctionStoreLevel( INVALID_STORE_LEVEL ),
|
|
_cMegToLeaveOnDisk( cMegToLeaveOnDisk )
|
|
{
|
|
_xPrimaryStore.Set(new CPropertyStore(*this, PRIMARY_STORE));
|
|
_xSecondaryStore.Set(new CPropertyStore(*this, SECONDARY_STORE));
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CPropStoreManager::CPropStoreManager, public
|
|
//
|
|
// Synopsis: Constructs the class.
|
|
//
|
|
// History: 24-Oct-97 KrishnaN Created.
|
|
// 01-Nov-98 KLam Added cMegToLeaveOnDisk to constructor
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CPropStoreManager::CPropStoreManager(CiStorage * pStorage,
|
|
CPropertyStore *pPrimaryStore,
|
|
CPropertyStore *pSecondaryStore,
|
|
ULONG cMegToLeaveOnDisk )
|
|
: _pStorage( pStorage ),
|
|
_dwXctionStoreLevel( INVALID_STORE_LEVEL ),
|
|
_cMegToLeaveOnDisk( cMegToLeaveOnDisk )
|
|
{
|
|
_xPrimaryStore.Set( pPrimaryStore );
|
|
_xSecondaryStore.Set( pSecondaryStore );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CPropStoreManager::~CPropStoreManager, public
|
|
//
|
|
// Synopsis: Destructs the class.
|
|
//
|
|
// History: 24-Oct-97 KrishnaN Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CPropStoreManager::~CPropStoreManager()
|
|
{
|
|
if ( !_xpsNew.IsNull() )
|
|
{
|
|
//
|
|
// The property stores in xpsnew are owned by the property stores
|
|
// in this instance (the one being destructed) of the property
|
|
// stores. They're in smart pointers but you can't delete them.
|
|
//
|
|
|
|
_xpsNew->_xPrimaryStore.Acquire();
|
|
_xpsNew->_xSecondaryStore.Acquire();
|
|
_xpsNew.Free();
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CPropStoreManager::Empty
|
|
//
|
|
// Synopsis: Empties out the intitialized members and prepares for a
|
|
// re-init.
|
|
//
|
|
// History: 22-Oct-97 KrishnaN Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CPropStoreManager::Empty()
|
|
{
|
|
_xPrimaryStore->Empty();
|
|
_xSecondaryStore->Empty();
|
|
_pStorage = 0;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CPropStoreManager::FastInit, public
|
|
//
|
|
// Synopsis: Initialize property store (two-phase construction)
|
|
//
|
|
// Arguments: [pStorage] -- Storage object.
|
|
//
|
|
// History: 22-Oct-97 KrishnaN Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CPropStoreManager::FastInit( CiStorage * pStorage )
|
|
{
|
|
_pStorage = pStorage;
|
|
_xPrimaryStore->FastInit(pStorage);
|
|
_xSecondaryStore->FastInit(pStorage);
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CPropStoreManager::LongInit
|
|
//
|
|
// Synopsis: If the propstore was dirty when shut down, run the recovery
|
|
// operation.
|
|
//
|
|
// Arguments: [fWasDirty] -- dirty flag is returned here
|
|
// [cInconsistencies] -- returns number of inconsistencies found
|
|
// [pfnUpdateCallback]-- Callback to be called to update docs during
|
|
// recovery. the prop store has no knowledge of
|
|
// doc store, so this callback is needed.
|
|
// [pUserData] -- will be echoed back through callback.
|
|
//
|
|
// Returns:
|
|
//
|
|
// History: 22-Oct-97 KrishnaN Created
|
|
//
|
|
// Notes: The propstore is locked for write during recovery, but
|
|
// reads are still permitted.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CPropStoreManager::LongInit( BOOL & fWasDirty, ULONG & cInconsistencies,
|
|
T_UpdateDoc pfnUpdateCallback, void const *pUserData )
|
|
{
|
|
//
|
|
// If at least one of the two stores is dirty, consider both to be dirty
|
|
// and recover from both.
|
|
//
|
|
|
|
ciDebugOut(( DEB_ITRACE, "is primary dirty: %d, is secondary dirty %d\n",
|
|
_xPrimaryStore->IsDirty(), _xSecondaryStore->IsDirty() ));
|
|
|
|
ciDebugOut(( DEB_ITRACE, "is backedup mode: %d\n", IsBackedUpMode() ));
|
|
|
|
if (IsDirty())
|
|
{
|
|
_xPrimaryStore->_PropStoreInfo.MarkDirty();
|
|
_xSecondaryStore->_PropStoreInfo.MarkDirty();
|
|
}
|
|
|
|
//
|
|
// If at least one of them recovered with inconsistencies, both should be
|
|
// considered to be corrupt!
|
|
//
|
|
|
|
_xPrimaryStore->LongInit(fWasDirty, cInconsistencies, pfnUpdateCallback, pUserData);
|
|
|
|
ciDebugOut(( DEB_ITRACE, "fWas, cIncon: %d, %d\n", fWasDirty, cInconsistencies ));
|
|
|
|
if (fWasDirty && cInconsistencies)
|
|
{
|
|
// Propstore is considered corrupt. No point attempting recovery on
|
|
// secondary.
|
|
|
|
return;
|
|
}
|
|
|
|
_xSecondaryStore->LongInit(fWasDirty, cInconsistencies, pfnUpdateCallback, pUserData);
|
|
|
|
ciDebugOut(( DEB_ITRACE, "2nd: fWas, cIncon: %d, %d\n", fWasDirty, cInconsistencies ));
|
|
|
|
if (fWasDirty && cInconsistencies)
|
|
{
|
|
// Propstore is still corrupt.
|
|
return;
|
|
}
|
|
|
|
// Are both the stores in sync
|
|
|
|
// First line defense
|
|
if (_xPrimaryStore->CountRecordsInUse() != _xSecondaryStore->CountRecordsInUse())
|
|
{
|
|
Win4Assert(fWasDirty);
|
|
cInconsistencies = abs((LONG)_xPrimaryStore->CountRecordsInUse() -
|
|
(LONG)_xSecondaryStore->CountRecordsInUse());
|
|
return;
|
|
}
|
|
|
|
// We have done our best to recover from a dirty shutdown. However, in at least one
|
|
// case (bug 132655), it was detected that there was an inconsistency between the
|
|
// two stores. Ensure that we catch such inconsistencies.
|
|
|
|
if (IsDirty())
|
|
{
|
|
CPropertyStoreWids iter(*this);
|
|
|
|
ULONG iRec = 0;
|
|
const ULONG cTotal = _xPrimaryStore->CountRecordsInUse();
|
|
|
|
for ( WORKID wid = iter.WorkId();
|
|
!cInconsistencies && wid != widInvalid;
|
|
wid = iter.LokNextWorkId() )
|
|
{
|
|
iRec++;
|
|
// get the physical store pointed to by the primary top-level record
|
|
CBorrowed BorrowedTopLevel( *(_xSecondaryStore->PhysStore()),
|
|
GetSecondaryTopLevelWid(wid),
|
|
_xSecondaryStore->RecordsPerPage(),
|
|
_xSecondaryStore->RecordSize() );
|
|
|
|
COnDiskPropertyRecord * prec = BorrowedTopLevel.Get();
|
|
if (!prec->IsInUse())
|
|
cInconsistencies++;
|
|
}
|
|
|
|
if (cInconsistencies)
|
|
return;
|
|
}
|
|
|
|
#if 0 // this is really expensive... CIDBG == 1
|
|
|
|
else
|
|
{
|
|
ULONG iRec = 0;
|
|
const ULONG cTotal = _xPrimaryStore->CountRecordsInUse();
|
|
|
|
CPropertyStoreWids iter(*this);
|
|
|
|
for ( WORKID wid = iter.WorkId(); wid != widInvalid; wid = iter.LokNextWorkId() )
|
|
{
|
|
iRec++;
|
|
// get the physical store pointed to by the primary top-level record
|
|
CBorrowed BorrowedTopLevel( *(_xSecondaryStore->PhysStore()),
|
|
GetSecondaryTopLevelWid(wid),
|
|
_xSecondaryStore->RecordsPerPage(),
|
|
_xSecondaryStore->RecordSize() );
|
|
|
|
COnDiskPropertyRecord * prec = BorrowedTopLevel.Get();
|
|
Win4Assert(prec->IsInUse());
|
|
}
|
|
}
|
|
|
|
#endif // CIDBG
|
|
|
|
// All is well. Flush and get on with the business of indexing and searching
|
|
Flush();
|
|
} //LongInit
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CPropStoreManager::BeginTransaction, public
|
|
//
|
|
// Synopsis: Begins a schema transaction. Any existing transaction will be
|
|
// aborted.
|
|
//
|
|
// Returns: Token representing transaction.
|
|
//
|
|
// History: 24-Oct-97 KrishnaN Created.
|
|
// 02-Nov-98 KLam Passed _cMegToLeaveOnDisk to
|
|
// CPropStoreManager
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
ULONG_PTR CPropStoreManager::BeginTransaction()
|
|
{
|
|
CLock lock( _mtxWrite );
|
|
|
|
// we are not committing, so the fixed pids are ignored.
|
|
if ( !_xpsNew.IsNull() )
|
|
EndTransaction( (ULONG_PTR)_xpsNew.Acquire(), FALSE, pidInvalid, pidInvalid);
|
|
|
|
ULONG_PTR ulPrimaryXctionToken = _xPrimaryStore->BeginTransaction();
|
|
ULONG_PTR ulSecondaryXctionToken = _xSecondaryStore->BeginTransaction();
|
|
|
|
_xpsNew.Set( new CPropStoreManager( _pStorage,
|
|
(CPropertyStore *)ulPrimaryXctionToken,
|
|
(CPropertyStore *)ulSecondaryXctionToken,
|
|
_cMegToLeaveOnDisk ) );
|
|
|
|
// init storelevel used in transaction to unknown.
|
|
_dwXctionStoreLevel = INVALID_STORE_LEVEL;
|
|
return (ULONG_PTR)_xpsNew.GetPointer();
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CPropStoreManager::Setup, public
|
|
//
|
|
// Synopsis: Setup a property description. Property may already exist
|
|
// in the cache.
|
|
//
|
|
// Arguments: [pid] -- Propid
|
|
// [vt] -- Datatype of property. VT_VARIANT if unknown.
|
|
// [cbMaxLen] -- Soft-maximum length for variable length
|
|
// properties. This much space is pre-allocated
|
|
// in original record.
|
|
// [ulToken] -- Token of transaction
|
|
// [fCanBeModified]-- Can the prop meta info be modified once set?
|
|
//
|
|
// History: 22-Oct-97 KrishnaN Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CPropStoreManager::Setup( PROPID pid,
|
|
ULONG vt,
|
|
DWORD cbMaxLen,
|
|
ULONG_PTR ulToken,
|
|
BOOL fCanBeModified,
|
|
DWORD dwStoreLevel )
|
|
{
|
|
if ( ulToken != (ULONG_PTR)_xpsNew.GetPointer() )
|
|
{
|
|
ciDebugOut(( DEB_ERROR, "Transaction mismatch: 0x%x vs. 0x%x\n", ulToken, _xpsNew.GetPointer() ));
|
|
THROW( CException( STATUS_TRANSACTION_NO_MATCH ) );
|
|
}
|
|
|
|
//
|
|
// Currently we only allow operations on one store during a transaction.
|
|
// Remember that or enforce that, as appropriate.
|
|
//
|
|
|
|
if (INVALID_STORE_LEVEL == _dwXctionStoreLevel)
|
|
_dwXctionStoreLevel = dwStoreLevel;
|
|
else
|
|
{
|
|
Win4Assert(PRIMARY_STORE == dwStoreLevel || SECONDARY_STORE == dwStoreLevel);
|
|
|
|
// should be primary or secondary
|
|
if (PRIMARY_STORE != dwStoreLevel && SECONDARY_STORE != dwStoreLevel)
|
|
{
|
|
THROW( CException( STATUS_TRANSACTION_INVALID_TYPE ) );
|
|
}
|
|
|
|
// should be the same as the first store used in the transaction
|
|
if (_dwXctionStoreLevel != dwStoreLevel)
|
|
{
|
|
THROW( CException( STATUS_TRANSACTION_NO_MATCH ) );
|
|
}
|
|
}
|
|
|
|
// Before placing the pid in a store, assert that it doesn't
|
|
// exist in the other store.
|
|
|
|
CLock lock( _mtxWrite );
|
|
|
|
CPropStoreManager *pStoreMgr = (CPropStoreManager *)ulToken;
|
|
|
|
if (PRIMARY_STORE == dwStoreLevel)
|
|
{
|
|
Win4Assert(_xSecondaryStore->CanStore(pid) == FALSE);
|
|
|
|
if (_xSecondaryStore->CanStore(pid))
|
|
{
|
|
THROW( CException( STATUS_TRANSACTION_NO_MATCH ) );
|
|
}
|
|
|
|
_xPrimaryStore->Setup(pid, vt, cbMaxLen,
|
|
(ULONG_PTR)pStoreMgr->_xPrimaryStore.GetPointer(),
|
|
fCanBeModified);
|
|
}
|
|
else
|
|
{
|
|
Win4Assert(_xPrimaryStore->CanStore(pid) == FALSE);
|
|
|
|
if (_xPrimaryStore->CanStore(pid))
|
|
{
|
|
THROW( CException( STATUS_TRANSACTION_NO_MATCH ) );
|
|
}
|
|
|
|
_xSecondaryStore->Setup(pid, vt, cbMaxLen,
|
|
(ULONG_PTR)pStoreMgr->_xSecondaryStore.GetPointer(),
|
|
fCanBeModified);
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CPropStoreManager::EndTransaction, public
|
|
//
|
|
// Synopsis: End property transaction, and maybe commit changes.
|
|
//
|
|
// Arguments: [ulToken] -- Token of transaction
|
|
// [fCommit] -- TRUE --> Commit transaction
|
|
// [pidFixedPrimary] -- Every workid with this pid will move to the
|
|
// same workid in the new property cache.
|
|
// [pidFixedSecondary] -- Every workid with this pid will move to the
|
|
// same workid in the new property cache.
|
|
//
|
|
// History: 22-Oct-97 KrishnaN Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CPropStoreManager::EndTransaction( ULONG_PTR ulToken, BOOL fCommit,
|
|
PROPID pidFixedPrimary,
|
|
PROPID pidFixedSecondary )
|
|
{
|
|
Win4Assert(ulToken);
|
|
|
|
CLock lock( _mtxWrite );
|
|
|
|
if ( ulToken != (ULONG_PTR)_xpsNew.GetPointer() )
|
|
{
|
|
ciDebugOut(( DEB_ERROR,
|
|
"PropStMgr: Transaction mismatch: 0x%x vs. 0x%x\n",
|
|
ulToken, _xpsNew.GetPointer() ));
|
|
THROW( CException( STATUS_TRANSACTION_NO_MATCH ) );
|
|
}
|
|
|
|
_xPrimaryStore->EndTransaction((ULONG_PTR)_xpsNew->_xPrimaryStore.GetPointer(),
|
|
fCommit, pidFixedPrimary);
|
|
_xSecondaryStore->EndTransaction((ULONG_PTR)_xpsNew->_xSecondaryStore.GetPointer(),
|
|
fCommit, pidFixedSecondary);
|
|
|
|
// The primary and secondary ptrs are already deleted in EndTransaction
|
|
// calls. Cleanup to reflect them prior to deleting _xpsNew.
|
|
|
|
_xpsNew->_xPrimaryStore.Acquire();
|
|
_xpsNew->_xSecondaryStore.Acquire();
|
|
|
|
_xpsNew.Free();
|
|
} //EndTransaction
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CPropStoreManager::MakeBackupCopy
|
|
//
|
|
// Synopsis: Makes a backup copy of the property storage. It makes a
|
|
// full copy if the pIEnumWorkids is NULL. Otherwise, it makes
|
|
// a copy of only the changed workids.
|
|
//
|
|
// Arguments: [pIProgressEnum] - Progress indication
|
|
// [pfAbort] - Caller initiated abort flag
|
|
// [dstStorage] - Destination storage to use
|
|
// [pIEnumWorkids] - List of workids to copy. If null, all the
|
|
// workids are copied.
|
|
// [ppFileList] - List of propstore files copied.
|
|
//
|
|
// History: 22-Oct-97 KrishnaN Created
|
|
//
|
|
// Notes: Incremental not implemented yet
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
|
|
void CPropStoreManager::MakeBackupCopy( IProgressNotify * pIProgressEnum,
|
|
BOOL & fAbort,
|
|
CiStorage & dstStorage,
|
|
ICiEnumWorkids * pIEnumWorkids,
|
|
IEnumString **ppFileList )
|
|
{
|
|
CLock lock( _mtxWrite );
|
|
|
|
Flush();
|
|
|
|
// fill in an array of sizes to pass into CCompositeProgressNotifier
|
|
DWORD *pdwStoreSizes = new DWORD[2];
|
|
pdwStoreSizes[0] = _xPrimaryStore->GetTotalSizeInKB();
|
|
pdwStoreSizes[1] = _xSecondaryStore->GetTotalSizeInKB();
|
|
|
|
CCompositeProgressNotifier ProgressNotifier( pIProgressEnum, pdwStoreSizes );
|
|
|
|
_xPrimaryStore->MakeBackupCopy(&ProgressNotifier, fAbort, dstStorage,
|
|
pIEnumWorkids, ppFileList);
|
|
ProgressNotifier.IncrementFinishedComponents();
|
|
|
|
ICiEnumWorkids *pIEnumSecondaryWorkids = pIEnumWorkids;
|
|
|
|
_xSecondaryStore->MakeBackupCopy(&ProgressNotifier, fAbort, dstStorage,
|
|
pIEnumSecondaryWorkids, ppFileList);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CPropStoreManager::WriteProperty, public
|
|
//
|
|
// Synopsis: Write a property to the cache.
|
|
//
|
|
// Arguments: [wid] -- Workid
|
|
// [pid] -- Propid
|
|
// [var] -- Value
|
|
//
|
|
// Returns: Scode propagated from underlying store.
|
|
//
|
|
// History: 24-Oct-97 KrishnaN Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE CPropStoreManager::WriteProperty( WORKID wid,
|
|
PROPID pid,
|
|
CStorageVariant const & var )
|
|
{
|
|
if ( _xPrimaryStore->CanStore( pid ) )
|
|
{
|
|
return WritePrimaryProperty( wid, pid, var );
|
|
}
|
|
else
|
|
{
|
|
CCompositePropRecordForWrites PropRecord( wid, *this, _mtxWrite );
|
|
|
|
return _xSecondaryStore->WriteProperty( PropRecord.GetSecondaryPropRecord(),
|
|
pid,
|
|
var,
|
|
IsBackedUpMode() );
|
|
}
|
|
} //WriteProperty
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CPropStoreManager::WriteProperty, public
|
|
//
|
|
// Synopsis: Write a property to the specified cache.
|
|
//
|
|
// Arguments: [dwStoreLevle] -- level of the property store to write to
|
|
// [PropRecord] -- Previously opened property record.
|
|
// [pid] -- Propid
|
|
// [var] -- Value
|
|
//
|
|
// Returns: SCODE propagated from underlying store.
|
|
//
|
|
// History: 23-Oct-2000 KitmanH Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE CPropStoreManager::WriteProperty( DWORD dwStoreLevel,
|
|
CCompositePropRecordForWrites & PropRecord,
|
|
PROPID pid,
|
|
CStorageVariant const & var )
|
|
{
|
|
Win4Assert( PRIMARY_STORE == dwStoreLevel || SECONDARY_STORE == dwStoreLevel );
|
|
|
|
if ( PRIMARY_STORE == dwStoreLevel )
|
|
{
|
|
if ( _xPrimaryStore->CanStore( pid ) )
|
|
return WritePrimaryProperty( PropRecord, pid, var );
|
|
}
|
|
else
|
|
{
|
|
if ( _xSecondaryStore->CanStore( pid ) )
|
|
return WriteSecondaryProperty( PropRecord, pid, var );
|
|
}
|
|
|
|
return E_INVALIDARG;
|
|
|
|
} //WriteProperty
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CPropStoreManager::WritePrimaryProperty, public
|
|
//
|
|
// Synopsis: Write a property from the cache. Triggers CoTaskMemAlloc
|
|
//
|
|
// Arguments: [wid] -- Workid
|
|
// [pid] -- Propid
|
|
// [var] -- Place to return the value
|
|
//
|
|
// History: 22-Oct-97 KrishnaN Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE CPropStoreManager::WritePrimaryProperty( WORKID wid,
|
|
PROPID pid,
|
|
CStorageVariant const & var )
|
|
{
|
|
CPrimaryPropRecordForWrites PropRecord( wid, *this, _mtxWrite );
|
|
|
|
return WritePrimaryProperty( PropRecord, pid, var );
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CPropStoreManager::WriteProperty, public
|
|
//
|
|
// Synopsis: Write a property to the cache.
|
|
//
|
|
// Arguments: [PropRecord] -- Previously opened property record.
|
|
// [pid] -- Propid
|
|
// [var] -- Value
|
|
//
|
|
// Returns: Scode propagated from underlying store.
|
|
//
|
|
// History: 24-Oct-97 KrishnaN Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE CPropStoreManager::WriteProperty( CCompositePropRecordForWrites & PropRecord,
|
|
PROPID pid, CStorageVariant const & var )
|
|
{
|
|
ciDebugOut(( DEB_PROPSTORE, "WRITE: proprecord = 0x%x, pid = 0x%x, type = %d\n", &PropRecord, pid, var.Type() ));
|
|
|
|
if (_xPrimaryStore->CanStore(pid))
|
|
return _xPrimaryStore->WriteProperty(PropRecord.GetPrimaryPropRecord(), pid, var, IsBackedUpMode() );
|
|
else
|
|
return _xSecondaryStore->WriteProperty(PropRecord.GetSecondaryPropRecord(), pid, var, IsBackedUpMode() );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CPropStoreManager::WritePrimaryProperty, public
|
|
//
|
|
// Synopsis: Write a property from the cache. Triggers CoTaskMemAlloc
|
|
//
|
|
// Arguments: [PropRecord] -- Previously opened property record
|
|
// [pid] -- Propid
|
|
// [var] -- Place to return the value
|
|
//
|
|
// History: 17-Mar-98 KrishnaN Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE CPropStoreManager::WritePrimaryProperty( CCompositePropRecordForWrites & PropRecord,
|
|
PROPID pid, CStorageVariant const & var )
|
|
{
|
|
// Has to be used only to Write pids in the primary store.
|
|
Win4Assert(_xPrimaryStore->CanStore(pid) == TRUE);
|
|
|
|
return _xPrimaryStore->WriteProperty( PropRecord.GetPrimaryPropRecord(), pid, var, IsBackedUpMode() );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CPropStoreManager::WritePrimaryProperty, public
|
|
//
|
|
// Synopsis: Write a property from the cache. Triggers CoTaskMemAlloc
|
|
//
|
|
// Arguments: [PropRecord] -- Previously opened property record
|
|
// [pid] -- Propid
|
|
// [var] -- Place to return the value
|
|
//
|
|
// History: 17-Mar-98 KrishnaN Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE CPropStoreManager::WritePrimaryProperty( CPrimaryPropRecordForWrites & PropRecord,
|
|
PROPID pid,
|
|
CStorageVariant const & var )
|
|
{
|
|
// Has to be used only to Write pids in the primary store.
|
|
Win4Assert(_xPrimaryStore->CanStore(pid) == TRUE);
|
|
|
|
return _xPrimaryStore->WriteProperty( PropRecord.GetPrimaryPropRecord(), pid, var, IsBackedUpMode() );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CPropStoreManager::WriteSecondaryProperty, public
|
|
//
|
|
// Synopsis: Write a property from the cache. Triggers CoTaskMemAlloc
|
|
//
|
|
// Arguments: [PropRecord] -- Previously opened property record
|
|
// [pid] -- Propid
|
|
// [var] -- Place to return the value
|
|
//
|
|
// History: 23-Oct-2000 KitmanH Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE CPropStoreManager::WriteSecondaryProperty( CCompositePropRecordForWrites & PropRecord,
|
|
PROPID pid, CStorageVariant const & var )
|
|
{
|
|
Win4Assert(_xSecondaryStore->CanStore(pid) == TRUE);
|
|
|
|
return _xSecondaryStore->WriteProperty( PropRecord.GetSecondaryPropRecord(), pid, var, IsBackedUpMode() );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CPropStoreManager::ReadProperty, public
|
|
//
|
|
// Synopsis: Read a property from the cache.
|
|
//
|
|
// Arguments: [wid] -- Workid
|
|
// [pid] -- Propid
|
|
// [pbData] -- Place to return the value
|
|
// [pcb] -- On input, the maximum number of bytes to
|
|
// write at pbData. On output, the number of
|
|
// bytes written if the call was successful,
|
|
// else the number of bytes required.
|
|
//
|
|
// History: 22-Oct-97 KrishnaN Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL CPropStoreManager::ReadProperty( WORKID wid, PROPID pid,
|
|
PROPVARIANT * pbData, unsigned * pcb )
|
|
{
|
|
unsigned cb = *pcb - sizeof (PROPVARIANT);
|
|
BOOL fOk = ReadProperty( wid, pid, *pbData, (BYTE *)(pbData + 1), &cb );
|
|
*pcb = cb + sizeof (PROPVARIANT);
|
|
|
|
return fOk;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CPropStoreManager::ReadProperty, public
|
|
//
|
|
// Synopsis: Read a property from the cache. Version which uses property
|
|
// record.
|
|
//
|
|
// Arguments: [PropRec] -- Pre-opened property record
|
|
// [pid] -- Propid
|
|
// [pbData] -- Place to return the value
|
|
// [pcb] -- On input, the maximum number of bytes to
|
|
// write at pbData. On output, the number of
|
|
// bytes written if the call was successful,
|
|
// else the number of bytes required.
|
|
//
|
|
// History: 22-Oct-97 KrishnaN Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL CPropStoreManager::ReadProperty( CCompositePropRecord & PropRec,
|
|
PROPID pid,
|
|
PROPVARIANT * pbData,
|
|
unsigned * pcb )
|
|
{
|
|
unsigned cb = *pcb - sizeof (PROPVARIANT);
|
|
BOOL fOk = ReadProperty( PropRec, pid, *pbData, (BYTE *)(pbData + 1), &cb );
|
|
*pcb = cb + sizeof (PROPVARIANT);
|
|
|
|
return fOk;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CPropStoreManager::ReadProperty, public
|
|
//
|
|
// Synopsis: Read a property from the cache. Version which uses property
|
|
// record.
|
|
//
|
|
// Arguments: [PropRec] -- Pre-opened property record
|
|
// [pid] -- Propid
|
|
// [var] -- Place to return the value
|
|
//
|
|
// History: 19-Dec-97 dlee Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL CPropStoreManager::ReadProperty(
|
|
CCompositePropRecord & PropRec,
|
|
PROPID pid,
|
|
PROPVARIANT & var )
|
|
{
|
|
unsigned cb = 0xFFFFFFFF;
|
|
return ReadProperty( PropRec, pid, var, 0, &cb );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CPropStoreManager::ReadProperty, public
|
|
//
|
|
// Synopsis: Read a property from the cache. Version which uses property
|
|
// record.
|
|
//
|
|
// Arguments: [PropRec] -- Pre-opened property record
|
|
// [pid] -- Propid
|
|
// [var] -- Place to return the value
|
|
//
|
|
// History: 19-Dec-97 dlee Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL CPropStoreManager::ReadProperty(
|
|
CPrimaryPropRecord & PropRec,
|
|
PROPID pid,
|
|
PROPVARIANT & var )
|
|
{
|
|
unsigned cb = 0xFFFFFFFF;
|
|
return ReadProperty( PropRec, pid, var, 0, &cb );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CPropStoreManager::ReadProperty, public
|
|
//
|
|
// Synopsis: Read a property from the cache. Triggers CoTaskMemAlloc
|
|
//
|
|
// Arguments: [wid] -- Workid
|
|
// [pid] -- Propid
|
|
// [var] -- Place to return the value
|
|
//
|
|
// History: 22-Oct-97 KrishnaN Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL CPropStoreManager::ReadProperty(
|
|
WORKID wid,
|
|
PROPID pid,
|
|
PROPVARIANT & var )
|
|
{
|
|
unsigned cb = 0xFFFFFFFF;
|
|
return ReadProperty( wid, pid, var, 0, &cb );
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CPropStoreManager::ReadProperty, public
|
|
//
|
|
// Synopsis: Read a property from the cache. Triggers CoTaskMemAlloc
|
|
//
|
|
// Arguments: [wid] -- Workid
|
|
// [pid] -- Propid
|
|
// [var] -- Place to return the value
|
|
//
|
|
// History: 22-Oct-97 KrishnaN Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL CPropStoreManager::ReadPrimaryProperty( WORKID wid, PROPID pid, PROPVARIANT & var )
|
|
{
|
|
// Has to be used only to read pids in the primary store.
|
|
Win4Assert(_xPrimaryStore->CanStore(pid) == TRUE);
|
|
|
|
unsigned cb = 0xFFFFFFFF;
|
|
BOOL fOk = _xPrimaryStore->ReadProperty( wid, pid, var, 0, &cb );
|
|
|
|
return fOk;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CPropStoreManager::ReadProperty, public
|
|
//
|
|
// Synopsis: Read a property from the cache. Separate variable buffer.
|
|
//
|
|
// Arguments: [wid] -- Workid
|
|
// [pid] -- Propid
|
|
// [var] -- Variant written here
|
|
// [pbExtra] -- Place to store additional pointer(s).
|
|
// [pcbExtra] -- On input, the maximum number of bytes to
|
|
// write at pbExtra. On output, the number of
|
|
// bytes written if the call was successful,
|
|
// else the number of bytes required.
|
|
//
|
|
// History: 24-Oct-97 KrishnaN Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL CPropStoreManager::ReadProperty( WORKID wid,
|
|
PROPID pid,
|
|
PROPVARIANT & var,
|
|
BYTE * pbExtra,
|
|
unsigned * pcbExtra )
|
|
{
|
|
if ( _xPrimaryStore->CanStore( pid ) )
|
|
{
|
|
CPrimaryPropRecord PropRecord( wid, *this );
|
|
return ReadProperty( PropRecord, pid, var, pbExtra, pcbExtra );
|
|
}
|
|
else
|
|
{
|
|
// the constructor seeds the constituent proprecords
|
|
// with the right wid, based on the wid we pass in.
|
|
|
|
CCompositePropRecord PropRecord( wid, *this );
|
|
|
|
return _xSecondaryStore->ReadProperty( PropRecord.GetSecondaryPropRecord(),
|
|
pid, var, pbExtra, pcbExtra);
|
|
}
|
|
} //ReadProperty
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CPropStoreManager::ReadProperty, public
|
|
//
|
|
// Synopsis: Read a property from the cache. Separate variable buffer.
|
|
// Uses pre-opened property record.
|
|
//
|
|
// Arguments: [PropRec] -- Pre-opened property record.
|
|
// [pid] -- Propid
|
|
// [var] -- Variant written here
|
|
// [pbExtra] -- Place to store additional pointer(s).
|
|
// [pcbExtra] -- On input, the maximum number of bytes to
|
|
// write at pbExtra. On output, the number of
|
|
// bytes written if the call was successful,
|
|
// else the number of bytes required.
|
|
//
|
|
// History: 03-Apr-96 KyleP Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL CPropStoreManager::ReadProperty( CCompositePropRecord & PropRecord,
|
|
PROPID pid,
|
|
PROPVARIANT & var,
|
|
BYTE * pbExtra,
|
|
unsigned * pcbExtra )
|
|
{
|
|
if (_xPrimaryStore->CanStore(pid))
|
|
{
|
|
return _xPrimaryStore->ReadProperty(PropRecord.GetPrimaryPropRecord(),
|
|
pid, var, pbExtra, pcbExtra);
|
|
}
|
|
else
|
|
{
|
|
return _xSecondaryStore->ReadProperty(PropRecord.GetSecondaryPropRecord(),
|
|
pid, var, pbExtra, pcbExtra);
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CPropStoreManager::ReadProperty, public
|
|
//
|
|
// Synopsis: Read a property from the cache. Separate variable buffer.
|
|
// Uses pre-opened property record.
|
|
//
|
|
// Arguments: [PropRec] -- Pre-opened property record.
|
|
// [pid] -- Propid
|
|
// [var] -- Variant written here
|
|
// [pbExtra] -- Place to store additional pointer(s).
|
|
// [pcbExtra] -- On input, the maximum number of bytes to
|
|
// write at pbExtra. On output, the number of
|
|
// bytes written if the call was successful,
|
|
// else the number of bytes required.
|
|
//
|
|
// History: 03-Apr-96 KyleP Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL CPropStoreManager::ReadProperty( CPrimaryPropRecord & PropRecord,
|
|
PROPID pid,
|
|
PROPVARIANT & var,
|
|
BYTE * pbExtra,
|
|
unsigned * pcbExtra )
|
|
{
|
|
Win4Assert( _xPrimaryStore->CanStore(pid) );
|
|
return _xPrimaryStore->ReadProperty(PropRecord.GetPrimaryPropRecord(),
|
|
pid, var, pbExtra, pcbExtra);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CPropStoreManager::OpenRecord, public
|
|
//
|
|
// Synopsis: Opens record (for multiple reads)
|
|
//
|
|
// Arguments: [wid] -- Workid
|
|
// [pb] -- Storage for record
|
|
//
|
|
// Returns: Pointer to open property record. Owned by caller.
|
|
//
|
|
// History: 03-Apr-96 KyleP Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CCompositePropRecord * CPropStoreManager::OpenRecord( WORKID wid, BYTE * pb )
|
|
{
|
|
Win4Assert( sizeof(CCompositePropRecord) <= sizeof_CCompositePropRecord );
|
|
return new( pb ) CCompositePropRecord( wid, *this );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CPropStoreManager::CloseRecord, public
|
|
//
|
|
// Synopsis: Closes record.
|
|
//
|
|
// Arguments: [pRec] -- Property record
|
|
//
|
|
// History: 03-Apr-96 KyleP Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CPropStoreManager::CloseRecord( CCompositePropRecord * pRec )
|
|
{
|
|
delete pRec;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CPropStoreManager::OpenPrimaryRecord, public
|
|
//
|
|
// Synopsis: Opens record (for multiple reads)
|
|
//
|
|
// Arguments: [wid] -- Workid
|
|
// [pb] -- Storage for record
|
|
//
|
|
// Returns: Pointer to open property record. Owned by caller.
|
|
//
|
|
// History: 03-Apr-96 KyleP Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CPrimaryPropRecord * CPropStoreManager::OpenPrimaryRecord( WORKID wid, BYTE * pb )
|
|
{
|
|
Win4Assert( sizeof(CPrimaryPropRecord) <= sizeof_CPropRecord );
|
|
return new( pb ) CPrimaryPropRecord( wid, *this );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CPropStoreManager::CloseRecord, public
|
|
//
|
|
// Synopsis: Closes record.
|
|
//
|
|
// Arguments: [pRec] -- Property record
|
|
//
|
|
// History: 03-Apr-96 KyleP Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CPropStoreManager::CloseRecord( CPrimaryPropRecord * pRec )
|
|
{
|
|
delete pRec;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CPropStoreManager::OpenRecordForWrites, public
|
|
//
|
|
// Synopsis: Opens record (for multiple writes)
|
|
//
|
|
// Arguments: [wid] -- Workid
|
|
// [pb] -- Storage for record
|
|
//
|
|
// Returns: Pointer to open property record. Owned by caller.
|
|
//
|
|
// History: 17-Mar-98 KrishnaN Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CCompositePropRecordForWrites * CPropStoreManager::OpenRecordForWrites( WORKID wid, BYTE * pb )
|
|
{
|
|
Win4Assert( sizeof(CCompositePropRecordForWrites) <= sizeof_CCompositePropRecord );
|
|
return new( pb ) CCompositePropRecordForWrites( wid, *this, _mtxWrite );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CPropStoreManager::OpenPrimaryRecordForWrites, public
|
|
//
|
|
// Synopsis: Opens record (for multiple writes)
|
|
//
|
|
// Arguments: [wid] -- Workid
|
|
// [pb] -- Storage for record
|
|
//
|
|
// Returns: Pointer to open property record. Owned by caller.
|
|
//
|
|
// History: 17-Mar-98 KrishnaN Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CPrimaryPropRecordForWrites * CPropStoreManager::OpenPrimaryRecordForWrites( WORKID wid, BYTE * pb )
|
|
{
|
|
Win4Assert( sizeof(CPrimaryPropRecordForWrites) <= sizeof_CPropRecord );
|
|
return new( pb ) CPrimaryPropRecordForWrites( wid, *this, _mtxWrite );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CPropStoreManager::CloseRecord, public
|
|
//
|
|
// Synopsis: Closes record.
|
|
//
|
|
// Arguments: [pRec] -- Property record
|
|
//
|
|
// History: 17-Mar-98 KrishnaN Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CPropStoreManager::CloseRecord( CCompositePropRecordForWrites * pRec )
|
|
{
|
|
delete pRec;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CPropStoreManager::CloseRecord, public
|
|
//
|
|
// Synopsis: Closes record.
|
|
//
|
|
// Arguments: [pRec] -- Property record
|
|
//
|
|
// History: 17-Mar-98 KrishnaN Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CPropStoreManager::CloseRecord( CPrimaryPropRecordForWrites * pRec )
|
|
{
|
|
delete pRec;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CPropStoreManager::DeleteRecord, public
|
|
//
|
|
// Synopsis: Free a record and any records chained off it.
|
|
//
|
|
// Arguments: [wid] -- Workid
|
|
//
|
|
// History: 24-Oct-97 KrishnaN Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CPropStoreManager::DeleteRecord( WORKID wid )
|
|
{
|
|
CLock lock( _mtxWrite );
|
|
|
|
ciDebugOut(( DEB_PROPSTORE, "DELETE: wid = 0x%x\n", wid ));
|
|
|
|
//
|
|
// Get the secondary store's top-level wid before getting rid
|
|
// of the wid in the primary store.
|
|
//
|
|
|
|
//
|
|
// The secondary wid can certainly be bogus if we couldn't write
|
|
// it to the primary store after allocating it when creating the
|
|
// records.
|
|
//
|
|
|
|
WORKID widSec = GetSecondaryTopLevelWid(wid);
|
|
|
|
if ( widInvalid != widSec && 0 != widSec )
|
|
_xSecondaryStore->DeleteRecord( widSec,
|
|
IsBackedUpMode() );
|
|
|
|
_xPrimaryStore->DeleteRecord( wid, IsBackedUpMode() );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CPropStoreManager::Flush
|
|
//
|
|
// Synopsis: Flushes the data in the property store and marks it clean.
|
|
//
|
|
// History: 3-20-96 srikants Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CPropStoreManager::Flush()
|
|
{
|
|
CLock mtxLock( _mtxWrite );
|
|
|
|
// Flush both the stores. Only when both are successful
|
|
// do we consider the entire flush to be successful.
|
|
// Don't reset the backup streams until the flush is
|
|
// completely successful.
|
|
|
|
BOOL fFlushOK = _xPrimaryStore->Flush();
|
|
if (fFlushOK)
|
|
fFlushOK = _xSecondaryStore->Flush();
|
|
|
|
// Reset the primary and the secondary backup stores
|
|
if (fFlushOK)
|
|
{
|
|
if (_xPrimaryStore->BackupStream())
|
|
_xPrimaryStore->BackupStream()->Reset(_xPrimaryStore->GetDesiredBackupSize());
|
|
|
|
if (_xSecondaryStore->BackupStream())
|
|
_xSecondaryStore->BackupStream()->Reset(_xSecondaryStore->GetDesiredBackupSize());
|
|
}
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CPropStoreManager::WritePropertyInNewRecord, public
|
|
//
|
|
// Synopsis: Like WriteProperty, but also allocates record.
|
|
//
|
|
// Arguments: [pid] -- Propid to write.
|
|
// [var] -- Property value
|
|
//
|
|
// Returns: Workid of new record.
|
|
//
|
|
// History: 22-Oct-97 KrishnaN Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
WORKID CPropStoreManager::WritePropertyInNewRecord( PROPID pid,
|
|
CStorageVariant const & var )
|
|
{
|
|
CLock lock( _mtxWrite );
|
|
|
|
//
|
|
// Get new wids from the primary and the secondary store.
|
|
// Write the property.
|
|
// Increment records in use for both the stores.
|
|
//
|
|
|
|
WORKID widPrimary = widInvalid;
|
|
WORKID widSecondary = widInvalid;
|
|
|
|
TRY
|
|
{
|
|
widPrimary = _xPrimaryStore->NewWorkId( 1, IsBackedUpMode() );
|
|
widSecondary = _xSecondaryStore->NewWorkId( 1, IsBackedUpMode() );
|
|
}
|
|
CATCH(CException, e)
|
|
{
|
|
// cleanup if widSecondary is invalid
|
|
if (widInvalid == widSecondary && widInvalid != widPrimary)
|
|
_xPrimaryStore->DeleteRecord( widPrimary, IsBackedUpMode() );
|
|
|
|
// Let the caller do what it normally does to handle exceptions
|
|
RETHROW();
|
|
}
|
|
END_CATCH
|
|
|
|
ciDebugOut(( DEB_PROPSTORE, "New record at primary: %d, secondary: %d\n",
|
|
widPrimary, widSecondary ));
|
|
|
|
//
|
|
// The primary's top-level record has a pointer to the
|
|
// top-level record in the secondary store. Fill that now!
|
|
//
|
|
|
|
VARIANT newVar;
|
|
newVar.vt = VT_UI4;
|
|
newVar.ulVal = widSecondary;
|
|
CStorageVariant *pVar = CastToStorageVariant(newVar);
|
|
SCODE sc;
|
|
|
|
sc = WritePrimaryProperty( widPrimary, pidSecondaryStorage, *pVar );
|
|
if (FAILED(sc))
|
|
THROW(CException(sc));
|
|
|
|
sc = WriteProperty( widPrimary, pid, var );
|
|
|
|
//
|
|
// DLee add this assert to find out why this is failing sometimes.
|
|
// Did the caller pass a bogus variant?
|
|
//
|
|
|
|
Win4Assert( HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER ) != sc );
|
|
|
|
if (FAILED(sc))
|
|
THROW(CException(sc));
|
|
|
|
_xPrimaryStore->IncRecordsInUse();
|
|
_xSecondaryStore->IncRecordsInUse();
|
|
|
|
// To the outside world, the primary wid is the one that matters.
|
|
return widPrimary;
|
|
}
|
|
|
|
//
|
|
// get and set parameters
|
|
// If incorrect parameter, default to the primary store.
|
|
//
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CPropStoreManager::SetBackupSize, public
|
|
//
|
|
// Synopsis: Sets backup size for a given property store.
|
|
//
|
|
// Arguments: [ulBackupSizeInPages] -- Size of the backup file.
|
|
// [dwStoreLevel] -- Primary or secondary store?
|
|
//
|
|
// History: 22-Oct-97 KrishnaN Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CPropStoreManager::SetBackupSize(ULONG ulBackupSizeInPages,
|
|
DWORD dwStoreLevel)
|
|
{
|
|
if (SECONDARY_STORE == dwStoreLevel)
|
|
_xSecondaryStore->SetBackupSize(ulBackupSizeInPages);
|
|
else
|
|
{
|
|
Win4Assert(PRIMARY_STORE == dwStoreLevel);
|
|
_xPrimaryStore->SetBackupSize(ulBackupSizeInPages);
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CPropStoreManager::GetBackupSize, public
|
|
//
|
|
// Synopsis: Gets backup size of a given property store.
|
|
//
|
|
// Arguments: [dwStoreLevel] -- Primary or secondary store?
|
|
//
|
|
// History: 22-Oct-97 KrishnaN Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
ULONG CPropStoreManager::GetBackupSize(DWORD dwStoreLevel)
|
|
{
|
|
if ( SECONDARY_STORE == dwStoreLevel)
|
|
return _xSecondaryStore->GetActualBackupSize();
|
|
else
|
|
{
|
|
Win4Assert( PRIMARY_STORE == dwStoreLevel);
|
|
return _xPrimaryStore->GetActualBackupSize();
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CPropStoreManager::SetMappedCacheSize, public
|
|
//
|
|
// Synopsis: Gets backup size of a given property store.
|
|
//
|
|
// Arguments: [dwStoreLevel] -- Primary or secondary store?
|
|
//
|
|
// History: 22-Oct-97 KrishnaN Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CPropStoreManager::SetMappedCacheSize(ULONG ulPSMappedCache,
|
|
DWORD dwStoreLevel)
|
|
{
|
|
if ( SECONDARY_STORE == dwStoreLevel)
|
|
_xSecondaryStore->SetMappedCacheSize(ulPSMappedCache);
|
|
else
|
|
{
|
|
Win4Assert( PRIMARY_STORE== dwStoreLevel);
|
|
_xPrimaryStore->SetMappedCacheSize(ulPSMappedCache);
|
|
}
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CPropStoreManager::GetMappedCacheSize, public
|
|
//
|
|
// Synopsis: Gets mapped cache size of a given property store.
|
|
//
|
|
// Arguments: [dwStoreLevel] -- Primary or secondary store?
|
|
//
|
|
// History: 22-Oct-97 KrishnaN Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
ULONG CPropStoreManager::GetMappedCacheSize(DWORD dwStoreLevel)
|
|
{
|
|
if (SECONDARY_STORE == dwStoreLevel)
|
|
return _xSecondaryStore->GetMappedCacheSize();
|
|
else
|
|
{
|
|
Win4Assert(PRIMARY_STORE == dwStoreLevel);
|
|
return _xPrimaryStore->GetMappedCacheSize();
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CPropStoreManager::GetTotalSizeInKB, public
|
|
//
|
|
// Synopsis: Gets total size of the property store.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// History: 22-Oct-97 KrishnaN Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
ULONG CPropStoreManager::GetTotalSizeInKB()
|
|
{
|
|
return _xPrimaryStore->GetTotalSizeInKB() +
|
|
_xSecondaryStore->GetTotalSizeInKB();
|
|
}
|
|
|
|
PStorage& CPropStoreManager::GetStorage(DWORD dwStoreLevel)
|
|
{
|
|
Win4Assert(&(_xPrimaryStore->GetStorage()) == _pStorage);
|
|
Win4Assert(&(_xSecondaryStore->GetStorage()) == _pStorage);
|
|
|
|
return *_pStorage;
|
|
}
|
|
|
|
void CPropStoreManager::Shutdown()
|
|
{
|
|
Flush();
|
|
_xPrimaryStore->Shutdown();
|
|
_xSecondaryStore->Shutdown();
|
|
}
|
|
|
|
void CPropStoreManager::ClearNonStorageProperties( CCompositePropRecordForWrites & rec )
|
|
{
|
|
_xPrimaryStore->ClearNonStorageProperties( rec );
|
|
_xSecondaryStore->ClearNonStorageProperties( rec );
|
|
}
|
|
|
|
// CSvcQuery methods
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Member: CCompositeProgressNotifier::QueryInterface, public
|
|
//
|
|
// Arguments: [ifid] -- Interface id
|
|
// [ppiuk] -- Interface return pointer
|
|
//
|
|
// Returns: Error. No rebind from this class is supported.
|
|
//
|
|
// History: Nov-14-97 KrishnaN Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CCompositeProgressNotifier::QueryInterface(
|
|
REFIID ifid,
|
|
void ** ppiuk )
|
|
{
|
|
if ( IID_IUnknown == ifid )
|
|
{
|
|
AddRef();
|
|
*ppiuk = (void *)((IUnknown *)this);
|
|
return S_OK;
|
|
}
|
|
else
|
|
{
|
|
*ppiuk = 0;
|
|
return E_NOINTERFACE;
|
|
}
|
|
} //QueryInterface
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Member: CCompositeProgressNotifier::AddRef, public
|
|
//
|
|
// Synopsis: Reference the virtual table.
|
|
//
|
|
// History: Nov-14-97 KrishnaN Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP_(ULONG) CCompositeProgressNotifier::AddRef()
|
|
{
|
|
InterlockedIncrement( &_ref );
|
|
return (ULONG)_ref;
|
|
} //AddRef
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Member: CCompositeProgressNotifier::Release, public
|
|
//
|
|
// Synopsis: De-Reference the virtual table.
|
|
//
|
|
// Effects: If the ref count goes to 0 then the table is deleted.
|
|
//
|
|
// History: Nov-14-97 KrishnaN Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP_(ULONG) CCompositeProgressNotifier::Release()
|
|
{
|
|
unsigned long uTmp = InterlockedDecrement( &_ref );
|
|
|
|
if ( 0 == uTmp )
|
|
delete this;
|
|
|
|
return(uTmp);
|
|
} //Release
|
|
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Member: CCompositeProgressNotifier::OnProgress, public
|
|
//
|
|
// Synopsis: Report progress.
|
|
//
|
|
// Effects: Progress reporting accounts for the presence of multiple
|
|
// independently operating constituents in the property store.
|
|
//
|
|
// History: Nov-14-97 KrishnaN Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CCompositeProgressNotifier::OnProgress
|
|
(
|
|
DWORD dwProgressCurrent,
|
|
DWORD dwProgressMaximum,
|
|
BOOL fAccurate,
|
|
BOOL fOwner
|
|
)
|
|
{
|
|
if (0 == _xComponentProgressNotifier.GetPointer())
|
|
return S_OK;
|
|
|
|
Win4Assert(_cFinishedComponents < _cComponents);
|
|
Win4Assert(dwProgressMaximum == _aulMaxSizes[_cFinishedComponents]);
|
|
|
|
//
|
|
// Present a unified view of progress reports. The composite progress
|
|
// report is 100% done only when all components are 100% done.
|
|
//
|
|
|
|
return _xComponentProgressNotifier->OnProgress
|
|
(dwProgressCurrent*1000/dwProgressMaximum + _dwCumMaxSize,
|
|
_dwTotalMaxSize,
|
|
fAccurate,
|
|
fOwner);
|
|
|
|
} //OnProgress
|
|
|
|
|