567 lines
15 KiB
C++
567 lines
15 KiB
C++
//+------------------------------------------------------------------
|
|
//
|
|
// Copyright (C) 1991-1997 Microsoft Corporation.
|
|
//
|
|
// File: idxentry.cxx
|
|
//
|
|
// Contents: Document filter interface
|
|
//
|
|
// Classes: CIndexNotificationEntry
|
|
//
|
|
// History: 24-Feb-97 SitaramR Created
|
|
//
|
|
// Notes: The implementation uses the regular memory allocator,
|
|
// and it makes a copy of every text string and property
|
|
// that is added. A better approach may be to define a
|
|
// custom memory allocator that allocates portions as
|
|
// needed from say a 4K block of memory.
|
|
//
|
|
//-------------------------------------------------------------------
|
|
|
|
#include <pch.cxx>
|
|
#pragma hdrstop
|
|
|
|
#include <cifrmcom.hxx>
|
|
|
|
#include "idxentry.hxx"
|
|
#include "cimanger.hxx"
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CChunkEntry::CChunkEntry
|
|
//
|
|
// Synopsis: Constructor
|
|
//
|
|
// Arguments: [pStatChunk] -- Pointer to stat chunk
|
|
// [pwszText] -- Text
|
|
//
|
|
// History: 24-Feb-97 SitaramR Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CChunkEntry::CChunkEntry( STAT_CHUNK const * pStatChunk, WCHAR const *pwszText )
|
|
: _pChunkEntryNext( 0 )
|
|
{
|
|
_statChunk = *pStatChunk;
|
|
|
|
XPtrST<WCHAR> xPropString;
|
|
if ( _statChunk.attribute.psProperty.ulKind == PRSPEC_LPWSTR )
|
|
{
|
|
//
|
|
// Make own copy of property string
|
|
//
|
|
ULONG cwcLen = wcslen( pStatChunk->attribute.psProperty.lpwstr ) + 1;
|
|
_statChunk.attribute.psProperty.lpwstr = new WCHAR[cwcLen];
|
|
RtlCopyMemory( _statChunk.attribute.psProperty.lpwstr,
|
|
pStatChunk->attribute.psProperty.lpwstr,
|
|
cwcLen * sizeof( WCHAR ) );
|
|
|
|
xPropString.Set( _statChunk.attribute.psProperty.lpwstr );
|
|
}
|
|
|
|
ULONG cwcLen = wcslen( pwszText ) + 1;
|
|
_pwszText = new WCHAR[cwcLen];
|
|
RtlCopyMemory( _pwszText, pwszText, cwcLen * sizeof(WCHAR) );
|
|
|
|
xPropString.Acquire(); // Pass ownership to CChunkEntry
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CChunkEntry::CChunkEntry
|
|
//
|
|
// Synopsis: Constructor
|
|
//
|
|
// Arguments: [pStatChunk] -- Pointer to stat chunk
|
|
// [pPropVar] -- Property
|
|
//
|
|
// History: 24-Feb-97 SitaramR Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CChunkEntry::CChunkEntry( STAT_CHUNK const * pStatChunk, PROPVARIANT const * pPropVar )
|
|
: _pChunkEntryNext( 0 )
|
|
{
|
|
_statChunk = *pStatChunk;
|
|
|
|
XPtrST<WCHAR> xPropString;
|
|
if ( _statChunk.attribute.psProperty.ulKind == PRSPEC_LPWSTR )
|
|
{
|
|
//
|
|
// Make own copy of property string
|
|
//
|
|
ULONG cwcLen = wcslen( pStatChunk->attribute.psProperty.lpwstr ) + 1;
|
|
_statChunk.attribute.psProperty.lpwstr = new WCHAR[cwcLen];
|
|
RtlCopyMemory( _statChunk.attribute.psProperty.lpwstr,
|
|
pStatChunk->attribute.psProperty.lpwstr,
|
|
cwcLen * sizeof( WCHAR ) );
|
|
|
|
xPropString.Set( _statChunk.attribute.psProperty.lpwstr );
|
|
}
|
|
|
|
_pStgVariant = new CStorageVariant( *(PROPVARIANT *)pPropVar );
|
|
if ( _pStgVariant == 0 )
|
|
THROW( CException( E_OUTOFMEMORY ) );
|
|
|
|
xPropString.Acquire(); // Pass ownership to CChunkEntry
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CChunkEntry::~CChunkEntry
|
|
//
|
|
// Synopsis: Destructor
|
|
//
|
|
// History: 24-Feb-97 SitaramR Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CChunkEntry::~CChunkEntry()
|
|
{
|
|
if ( _statChunk.attribute.psProperty.ulKind == PRSPEC_LPWSTR )
|
|
delete _statChunk.attribute.psProperty.lpwstr;
|
|
|
|
if ( _statChunk.flags == CHUNK_TEXT )
|
|
delete _pwszText;
|
|
else
|
|
delete _pStgVariant;
|
|
}
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CIndexNotificationEntry::CIndexNotificationEntry
|
|
//
|
|
// Synopsis: Constructor
|
|
//
|
|
// History: 24-Feb-97 SitaramR Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CIndexNotificationEntry::CIndexNotificationEntry(
|
|
WORKID wid,
|
|
CI_UPDATE_TYPE eUpdateType,
|
|
XInterface<CIndexNotificationTable> & xNotifTable,
|
|
XInterface<ICiCIndexNotificationStatus> & xNotifStatus,
|
|
CCiManager * pCiManager,
|
|
USN usn )
|
|
: _xNotifTable( xNotifTable.Acquire() ),
|
|
_xNotifStatus( xNotifStatus.Acquire() ),
|
|
_pCiManager( pCiManager ),
|
|
_wid( wid ),
|
|
_eUpdateType( eUpdateType ),
|
|
_fAddCompleted( FALSE ),
|
|
_fShutdown( FALSE ),
|
|
_fFilterDataPurged( FALSE ),
|
|
_usn( usn ),
|
|
_pChunkEntryHead( 0 ),
|
|
_pChunkEntryTail( 0 ),
|
|
_pChunkEntryIter( 0 ),
|
|
_cRefs( 1 )
|
|
{
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CIndexNotificationEntry::~CIndexNotificationEntry
|
|
//
|
|
// Synopsis: Destructor
|
|
//
|
|
// History: 24-Feb-97 SitaramR Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CIndexNotificationEntry::~CIndexNotificationEntry()
|
|
{
|
|
PurgeFilterData();
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Method: CIndexNotificationEntry::AddRef
|
|
//
|
|
// Synopsis: Increments refcount
|
|
//
|
|
// History: 24-Feb-1997 SitaramR Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
ULONG STDMETHODCALLTYPE CIndexNotificationEntry::AddRef()
|
|
{
|
|
return InterlockedIncrement( (long *) &_cRefs );
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Method: CIndexNotificationEntry::Release
|
|
//
|
|
// Synopsis: Decrement refcount. Delete if necessary.
|
|
//
|
|
// History: 24-Feb-1997 SitaramR Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
ULONG STDMETHODCALLTYPE CIndexNotificationEntry::Release()
|
|
{
|
|
Win4Assert( _cRefs > 0 );
|
|
|
|
ULONG uTmp = InterlockedDecrement( (long *) &_cRefs );
|
|
|
|
if ( 0 == uTmp )
|
|
delete this;
|
|
|
|
return uTmp;
|
|
}
|
|
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Method: CIndexNotificationEntry::QueryInterface
|
|
//
|
|
// Synopsis: Rebind to other interface
|
|
//
|
|
// Arguments: [riid] -- IID of new interface
|
|
// [ppvObject] -- New interface * returned here
|
|
//
|
|
// Returns: S_OK if bind succeeded, E_NOINTERFACE if bind failed
|
|
//
|
|
// History: 24-Feb-1997 SitaramR Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
SCODE STDMETHODCALLTYPE CIndexNotificationEntry::QueryInterface( REFIID riid,
|
|
void ** ppvObject)
|
|
{
|
|
Win4Assert( 0 != ppvObject );
|
|
|
|
if ( riid == IID_ICiIndexNotificationEntry )
|
|
*ppvObject = (void *)(ICiIndexNotificationEntry *) this;
|
|
else if ( riid == IID_IUnknown )
|
|
*ppvObject = (void *)(IUnknown *) this;
|
|
else
|
|
{
|
|
*ppvObject = 0;
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
AddRef();
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Method: CIndexNotificationEntry::AddText
|
|
//
|
|
// Synopsis: Adds a text chunk
|
|
//
|
|
// Arguments: [pStatChunk] -- Pointer to stat chunk
|
|
// [pwszText] -- Text
|
|
//
|
|
// History: 24-Feb-1997 SitaramR Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
SCODE STDMETHODCALLTYPE CIndexNotificationEntry::AddText( STAT_CHUNK const * pStatChunk,
|
|
WCHAR const * pwszText )
|
|
{
|
|
if ( _fShutdown )
|
|
return CI_E_SHUTDOWN;
|
|
|
|
if ( _fAddCompleted )
|
|
{
|
|
Win4Assert( !"Adding text after AddCompleted was signalled" );
|
|
|
|
return E_FAIL;
|
|
}
|
|
|
|
Win4Assert( pStatChunk->flags == CHUNK_TEXT );
|
|
|
|
SCODE sc = S_OK;
|
|
|
|
TRY
|
|
{
|
|
CChunkEntry *pEntry = new CChunkEntry( pStatChunk, pwszText );
|
|
if ( _pChunkEntryTail )
|
|
{
|
|
_pChunkEntryTail->SetNextChunkEntry( pEntry ); // does not fail
|
|
_pChunkEntryTail = pEntry;
|
|
}
|
|
|
|
else
|
|
{
|
|
_pChunkEntryTail = pEntry;
|
|
_pChunkEntryHead = pEntry;
|
|
}
|
|
}
|
|
CATCH( CException, e )
|
|
{
|
|
sc = e.GetErrorCode();
|
|
|
|
ciDebugOut(( DEB_ERROR,
|
|
"CIndexNotificationEntry::AddText - Exception caught 0x%x\n",
|
|
sc ));
|
|
}
|
|
END_CATCH;
|
|
|
|
return sc;
|
|
}
|
|
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Method: CIndexNotificationEntry::AddProperty
|
|
//
|
|
// Synopsis: Adds a property chunk
|
|
//
|
|
// Arguments: [pStatChunk] -- Pointer to stat chunk
|
|
// [pPropVar] -- Property
|
|
//
|
|
// History: 24-Feb-1997 SitaramR Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
SCODE STDMETHODCALLTYPE CIndexNotificationEntry::AddProperty( STAT_CHUNK const * pStatChunk,
|
|
PROPVARIANT const *pPropVar )
|
|
{
|
|
if ( _fShutdown )
|
|
return CI_E_SHUTDOWN;
|
|
|
|
if ( _fAddCompleted )
|
|
{
|
|
Win4Assert( !"Adding property after AddCompleted was signalled" );
|
|
|
|
return E_FAIL;
|
|
}
|
|
|
|
Win4Assert( pStatChunk->flags == CHUNK_VALUE );
|
|
|
|
SCODE sc = S_OK;
|
|
|
|
TRY
|
|
{
|
|
CChunkEntry *pEntry = new CChunkEntry( pStatChunk, pPropVar );
|
|
if ( _pChunkEntryTail )
|
|
{
|
|
_pChunkEntryTail->SetNextChunkEntry( pEntry ); // does not fail
|
|
_pChunkEntryTail = pEntry;
|
|
}
|
|
else
|
|
{
|
|
_pChunkEntryTail = pEntry;
|
|
_pChunkEntryHead = pEntry;
|
|
}
|
|
}
|
|
CATCH( CException, e )
|
|
{
|
|
sc = e.GetErrorCode();
|
|
|
|
ciDebugOut(( DEB_ERROR,
|
|
"CIndexNotificationEntry::AddProperty - Exception caught 0x%x\n",
|
|
sc ));
|
|
}
|
|
END_CATCH;
|
|
|
|
return sc;
|
|
}
|
|
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Method: CIndexNotificationEntry::AddCompleted
|
|
//
|
|
// Synopsis: Signifies end of chunks. At this time the notification is
|
|
// propagated to CCiManager.
|
|
//
|
|
// Arguments: [fAbort] -- If true, then the notification should not be
|
|
// propagted to ICiManager. Also, all resources
|
|
// need to be released
|
|
//
|
|
// History: 24-Feb-1997 SitaramR Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
SCODE STDMETHODCALLTYPE CIndexNotificationEntry::AddCompleted( ULONG fAbort )
|
|
{
|
|
if ( _fAddCompleted )
|
|
{
|
|
Win4Assert( !"AddCompleted being called for the second time" );
|
|
|
|
return E_FAIL;
|
|
}
|
|
|
|
SCODE sc = S_OK;
|
|
|
|
TRY
|
|
{
|
|
CIndexNotificationEntry *pNotifEntry;
|
|
_fAddCompleted = TRUE;
|
|
|
|
if ( fAbort || _fShutdown )
|
|
{
|
|
SCODE scode = _xNotifStatus->Abort();
|
|
|
|
//
|
|
// We don't have retry logic on failures
|
|
//
|
|
Win4Assert( SUCCEEDED( scode ) );
|
|
|
|
//
|
|
// Free entry from hash table, which should be ourself
|
|
//
|
|
XInterface<CIndexNotificationEntry> xIndexNotifEntry;
|
|
_xNotifTable->Remove( _wid, xIndexNotifEntry );
|
|
|
|
Win4Assert( this == xIndexNotifEntry.GetPointer() );
|
|
|
|
//
|
|
// xIndexNotifEntry is released when it goes out of scope
|
|
//
|
|
}
|
|
else
|
|
{
|
|
CDocumentUpdateInfo info( _wid, CI_VOLID_USN_NOT_ENABLED, _usn, FALSE );
|
|
sc = _pCiManager->UpdDocumentNoThrow( &info );
|
|
|
|
if ( FAILED( sc ) )
|
|
{
|
|
SCODE scode = _xNotifStatus->Abort();
|
|
|
|
//
|
|
// We don't have retry logic on failures
|
|
//
|
|
Win4Assert( SUCCEEDED( scode ) );
|
|
|
|
//
|
|
// Free entry from hash table, which should be ourself
|
|
//
|
|
XInterface<CIndexNotificationEntry> xIndexNotifEntry;
|
|
_xNotifTable->Remove( _wid, xIndexNotifEntry );
|
|
|
|
Win4Assert( this == xIndexNotifEntry.GetPointer() );
|
|
|
|
//
|
|
// xIndexNotifEntry is released when it goes out of scope
|
|
//
|
|
}
|
|
}
|
|
}
|
|
CATCH( CException, e )
|
|
{
|
|
sc = e.GetErrorCode();
|
|
|
|
ciDebugOut(( DEB_ERROR,
|
|
"CIndexNotificationEntry::AddCompleted - Exception caught 0x%x\n",
|
|
sc ));
|
|
//
|
|
// Not clear why AddCompleted can ever fail
|
|
//
|
|
Win4Assert( !"AddCompleted failed" );
|
|
}
|
|
END_CATCH;
|
|
|
|
return sc;
|
|
}
|
|
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Method: CIndexNotificationEntry::GetFirstChunk
|
|
//
|
|
// Synopsis: Returns first entry in list of chunks
|
|
//
|
|
// History: 24-Feb-1997 SitaramR Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
CChunkEntry *CIndexNotificationEntry::GetFirstChunk()
|
|
{
|
|
if ( _fFilterDataPurged )
|
|
{
|
|
Win4Assert( !"Re-filtering is not allowed in push filtering" );
|
|
|
|
return 0;
|
|
}
|
|
_pChunkEntryIter = _pChunkEntryHead;
|
|
return _pChunkEntryIter;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Method: CIndexNotificationEntry::GetNextChunk
|
|
//
|
|
// Synopsis: Returns next entry in list of chunks. The state of iterator
|
|
// is maintained in _pChunkEntryIter, which can be reset by
|
|
// GetFirstChunk.
|
|
//
|
|
// History: 24-Feb-1997 SitaramR Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
CChunkEntry *CIndexNotificationEntry::GetNextChunk()
|
|
{
|
|
if ( _fFilterDataPurged )
|
|
{
|
|
Win4Assert( !"Re-filtering is not allowed in push filtering" );
|
|
|
|
return 0;
|
|
}
|
|
|
|
if ( _pChunkEntryIter == 0 )
|
|
return 0;
|
|
else
|
|
{
|
|
_pChunkEntryIter = _pChunkEntryIter->GetNextChunkEntry();
|
|
return _pChunkEntryIter;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Method: CIndexNotificationEntry::PurgeFilterData
|
|
//
|
|
// Synopsis: Deletes filter data, because wids are filtered only once
|
|
// in push filtering.
|
|
//
|
|
// History: 17-Jun-1997 SitaramR Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
void CIndexNotificationEntry::PurgeFilterData()
|
|
{
|
|
_fFilterDataPurged = TRUE;
|
|
|
|
//
|
|
// Clean up all chunks
|
|
//
|
|
if ( _pChunkEntryHead != 0 )
|
|
{
|
|
CChunkEntry *pEntryPrev = _pChunkEntryHead;
|
|
CChunkEntry *pEntryNext = pEntryPrev->GetNextChunkEntry();
|
|
|
|
while ( pEntryNext != 0 )
|
|
{
|
|
delete pEntryPrev;
|
|
pEntryPrev = pEntryNext;
|
|
pEntryNext = pEntryNext->GetNextChunkEntry();
|
|
}
|
|
|
|
delete pEntryPrev;
|
|
|
|
_pChunkEntryHead = 0;
|
|
}
|
|
}
|