windows-nt/Source/XPSP1/NT/inetsrv/query/fsci/indexing/docstore.cxx
2020-09-26 16:20:57 +08:00

2878 lines
80 KiB
C++

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1996 - 2002.
//
// File: docstore.cxx
//
// Contents: Deals with the client side document store implementation.
//
// Classes: CClientDocStore
//
// History: 12-03-96 srikants Created
//
//----------------------------------------------------------------------------
#include <pch.cxx>
#pragma hdrstop
// for definition of CRequestQueue
#include <query.hxx>
#include <srequest.hxx>
#include <regacc.hxx>
#include <docstore.hxx>
#include <docname.hxx>
#include <qsession.hxx>
#include <cicat.hxx>
#include <cinulcat.hxx>
#include <seccache.hxx>
#include <dmnstart.hxx>
#include <propmap.hxx>
#include <notifyev.hxx>
#include <catalog.hxx>
#include <catarray.hxx>
#include <glbconst.hxx>
#include <cisvcex.hxx>
#include <cisvcfrm.hxx>
#include <cistore.hxx>
#include <enumstr.hxx>
#include <filterob.hxx>
#include <catadmin.hxx>
#include <fsci.hxx>
extern CCatArray Catalogs;
CRequestQueue * g_pFSCIRequestQueue = 0;
extern "C" const GUID clsidStorageFilterObject =
{ 0xaa205a4d, 0x681f, 0x11d0, { 0xa2, 0x43, 0x8, 0x0, 0x2b, 0x36, 0xfc, 0xa4 } };
extern "C" const GUID guidStorageDocStoreLocatorObject;
//+---------------------------------------------------------------------------
//
// Member: CClientDocStore::QueryInterface
//
// Synopsis: Supports IID_IUnknown
// IID_ICiCDocStore
// IID_ICiCDocStoreEx
// IID_ICiCPropertyStorage
// IID_ICiCDocNameToWorkidTranslator
// IID_ICiCDocNameToWorkidTranslatorEx
// IID_ICiCAdviseStatus
// IID_IFsCiAdmin
// IID_ICiCLangRes
//
// History: 12-03-96 srikants Created
// 2-14-97 mohamedn ICiCLangRes
//
//----------------------------------------------------------------------------
STDMETHODIMP CClientDocStore::QueryInterface( REFIID riid, void **ppvObject )
{
Win4Assert( 0 != ppvObject );
if ( IID_ICiCDocStore == riid )
*ppvObject = (void *)((ICiCDocStore *)this);
else if ( IID_ICiCPropertyStorage == riid )
*ppvObject = (void *)((ICiCPropertyStorage *)this);
else if ( IID_ICiCDocNameToWorkidTranslator == riid )
*ppvObject = (void *)((ICiCDocNameToWorkidTranslator *)this);
else if ( IID_ICiCDocNameToWorkidTranslatorEx == riid )
*ppvObject = (void *)((ICiCDocNameToWorkidTranslatorEx *)this);
else if ( IID_ICiCAdviseStatus == riid )
*ppvObject = (void *)((ICiCAdviseStatus *)this);
else if ( IID_IFsCiAdmin == riid )
*ppvObject = (void *)((IFsCiAdmin *)this);
else if ( IID_ICiCLangRes == riid )
*ppvObject = (void *) ((ICiCLangRes *)this);
else if ( IID_ICiCDocStoreEx == riid )
*ppvObject = (void *)((IUnknown *) (ICiCDocStoreEx *)this);
else if ( IID_ICiCResourceMonitor == riid )
*ppvObject = (void *)((IUnknown *) (ICiCResourceMonitor *)this);
else if ( IID_IUnknown == riid )
*ppvObject = (void *)((IUnknown *) (ICiCDocStore *)this);
else
{
*ppvObject = 0;
return E_NOINTERFACE;
}
AddRef();
return S_OK;
} //QueryInterface
//+---------------------------------------------------------------------------
//
// Member: CClientDocStore::AddRef
//
// History: 12-03-96 srikants Created
//
//----------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CClientDocStore::AddRef()
{
return InterlockedIncrement(&_refCount);
} //AddRef
//+---------------------------------------------------------------------------
//
// Member: CClientDocStore::Release
//
// History: 12-03-96 srikants Created
//
//----------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CClientDocStore::Release()
{
Win4Assert( _refCount > 0 );
LONG refCount = InterlockedDecrement(&_refCount);
if ( refCount <= 0 )
delete this;
return (ULONG) refCount;
} //Release
//+---------------------------------------------------------------------------
//
// Member: CClientDocStore::CClientDocStore
//
// Synopsis: Constructor of the NULL CiCDocStore object.
//
// Arguments: None
//
// History: Jul-09-97 KrishnaN Created
// 01-Nov-98 KLam Need to instantiate a CDiskFreeStatus
//
//----------------------------------------------------------------------------
CClientDocStore::CClientDocStore()
: _sigClientDocStore(eSigClientDocStore),
_refCount(1),
_fNoQuery( FALSE ),
_state(eUpdatesDisabled),
_pCiCat(0),
_pCiNullCat(0)
{
// Create the CiNullCat object.
_pCiNullCat = new CiNullCat( *this );
XPtr<CiNullCat> xCat( _pCiNullCat );
// Map std props only (second param)
_xPropMapper.Set( new CFwPropertyMapper( _pCiNullCat->GetPidLookupTable(), TRUE ) );
// Create CI Manager object.
_CreateCiManager();
_pCiNullCat->StartupCiFrameWork( _xCiManager.GetPointer() );
//
// Startup content index.
//
ICiStartup * pCiStartup;
SCODE sc = _xCiManager->QueryInterface( IID_ICiStartup, (void **) &pCiStartup );
XInterface<ICiStartup> xStartup( pCiStartup );
if ( S_OK != sc )
{
THROW( CException(sc) );
}
CI_STARTUP_INFO startupInfo;
RtlZeroMemory( &startupInfo, sizeof(startupInfo) );
startupInfo.clsidDaemonClientMgr = clsidStorageFilterObject;
startupInfo.startupFlags = CI_CONFIG_ENABLE_QUERYING ;
BOOL fAbort = FALSE;
sc = pCiStartup->StartupNullContentIndex( &startupInfo,0, &fAbort );
if ( FAILED(sc) )
{
THROW( CException(sc) );
}
xCat->SetAdviseStatus();
xCat.Acquire();
}
//+---------------------------------------------------------------------------
//
// Member: CClientDocStore::CClientDocStore
//
// Synopsis: Constructor of the CiCDocStore object.
//
// Arguments: [pwszPath] - Path of the directory where the files must be
// created.
// [pwszName] - Name of the Content Index.
//
// History: 12-03-96 srikants Created
// 02-17-98 kitmanh Added code to deal with read-only
// catalogs (the readOnly flag is
// passed down from CiCat to startupInfo)
// 07-Jan-99 klam Logged and event that initialization failed
//
//----------------------------------------------------------------------------
CClientDocStore::CClientDocStore( WCHAR const * pwszPath,
BOOL fOpenForReadOnly,
CDrvNotifArray & DrvNotifArray,
WCHAR const * pwszName )
: _sigClientDocStore(eSigClientDocStore),
_refCount(1),
_state(eUpdatesDisabled),
_pCiCat(0),
_pCiNullCat(0),
_fNoQuery( FALSE ),
_pDrvNotifArray( &DrvNotifArray )
{
ciDebugOut(( DEB_ITRACE, "CClientDocStore::CClinetDocStore.. fOpenForReadOnly == %d\n", fOpenForReadOnly ));
ciDebugOut(( DEB_ITRACE, "CClientDocStore::CClinetDocStore.. pwszPath == %ws\n", pwszPath ));
ciDebugOut(( DEB_ITRACE, "CClientDocStore::CClinetDocStore.. pwszName == %ws\n", pwszName ));
// Check if the catalog directory exists
if ( ( wcslen( pwszPath ) + wcslen( CAT_DIR ) ) >= MAX_PATH )
THROW( CException( STATUS_INVALID_PARAMETER ) );
WCHAR awcCatDir[ MAX_PATH ];
wcscpy( awcCatDir, pwszPath );
wcscat( awcCatDir, CAT_DIR );
WIN32_FILE_ATTRIBUTE_DATA fData;
if ( GetFileAttributesEx( awcCatDir, GetFileExInfoStandard, &fData ) )
{
// Is the catalog path a file or a directory?
if ( 0 == ( fData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) )
THROW( CException( HRESULT_FROM_WIN32( ERROR_PATH_NOT_FOUND ) ) );
}
else
{
//
// You can get back both errors depending on what parts of the
// directory tree currently exist.
//
if ( ( ERROR_FILE_NOT_FOUND == GetLastError() ) ||
( ERROR_PATH_NOT_FOUND == GetLastError() ) )
{
// create the catalog directory with proper acls
CMachineAdmin admin;
admin.CreateSubdirs( pwszPath );
}
else
THROW( CException() );
}
BOOL fLeaveCorruptCatalog;
{
// By default, delete corrupt catalogs.
CRegAccess reg( RTL_REGISTRY_CONTROL, wcsRegAdmin );
fLeaveCorruptCatalog = reg.Read( wcsLeaveCorruptCatalog, (ULONG) FALSE );
}
//
// Create the CiCat object.
//
BOOL fVersionChange = FALSE;
_pCiCat = new CiCat( *this,
_workMan,
pwszPath,
fVersionChange,
fOpenForReadOnly,
*_pDrvNotifArray,
pwszName,
fLeaveCorruptCatalog );
XPtr<CiCat> xCat( _pCiCat );
// Create a CDiskFreeStatus object
_xDiskStatus.Set( new CDiskFreeStatus( pwszPath,
xCat->GetRegParams()->GetMinDiskSpaceToLeave() ) );
// Map std props AND others (second param set to false)
_xPropMapper.Set( new CFwPropertyMapper( xCat->GetPidLookupTable(), FALSE ) );
//
// Create the perform counters object. This must be done before
// starting up rest of the content index.
//
Win4Assert( 0 != xCat->GetCatalogName() );
CPerfMon * pPerfMon = new CPerfMon( xCat->GetCatalogName() );
_xPerfMon.Set( pPerfMon );
//
// Create CI Manager object.
//
_CreateCiManager();
xCat->StartupCiFrameWork( _xCiManager.GetPointer() );
//
// Startup content index.
//
ICiStartup * pCiStartup;
SCODE sc = _xCiManager->QueryInterface( IID_ICiStartup,
(void **) &pCiStartup );
XInterface<ICiStartup> xStartup( pCiStartup );
if ( S_OK != sc )
THROW( CException(sc) );
BOOL fFullScanNeeded = FALSE;
CI_STARTUP_INFO startupInfo;
RtlZeroMemory( &startupInfo, sizeof(startupInfo) );
startupInfo.clsidDaemonClientMgr = clsidStorageFilterObject;
startupInfo.startupFlags = CI_CONFIG_ENABLE_INDEXING |
CI_CONFIG_ENABLE_QUERYING ;
if ( xCat->IsReadOnly() )
startupInfo.startupFlags |= CI_CONFIG_READONLY;
if ( xCat->IsCiDataCorrupt() || xCat->IsFsCiDataCorrupt() || fVersionChange )
{
if ( fLeaveCorruptCatalog )
{
Win4Assert( !"leaving corrupt catalog" );
THROW( CException( CI_CORRUPT_CATALOG ) );
}
if ( xCat->IsCiDataCorrupt() ||
xCat->IsFsCiDataCorrupt() )
{
ciDebugOut(( DEB_ERROR, "Persistent CI/FSCI Data Corruption. It will be emptied \n" ));
//Win4Assert( !"Persistent CI/FSCI Data Corruption" );
}
startupInfo.startupFlags |= (ULONG) CI_CONFIG_EMPTY_DATA;
xCat->LogEvent( CCiStatusMonitor::eCiRemoved );
fFullScanNeeded = TRUE;
}
BOOL fAbort = FALSE;
#if CIDBG==1
#if 0
_FillLoadFilesInfo( startupInfo );
#endif // 0
#endif // CIDBG==1
sc = pCiStartup->StartupContentIndex( xCat->GetCatDir(), &startupInfo,0, &fAbort );
#if CIDBG==1
#if 0
if ( SUCCEEDED(sc) )
{
WCHAR wszBackupPath[MAX_PATH];
wcscpy( wszBackupPath, xCat->GetCatDir() );
wcscat( wszBackupPath, L"\\backup");
ICiPersistIncrFile * pIPersist = 0;
sc = _xCiManager->QueryInterface( IID_ICiPersistIncrFile,
(void **) &pIPersist );
Win4Assert( SUCCEEDED(sc) );
_xSaveTest.Set( new CCiSaveTest( wszBackupPath,
pIPersist,
xCat.GetReference() ) );
pIPersist->Release();
}
_ClearLoadFilesInfo( startupInfo );
#endif // 0
#endif // CIDBG==1
if ( FAILED(sc) )
{
if ( !IsCiCorruptStatus( sc ) && sc != CI_INCORRECT_VERSION )
{
ciDebugOut(( DEB_ERROR, "Failed to startupci. Error 0x%X\n", sc ));
xCat->LogEvent ( CCiStatusMonitor::eCiError, sc );
THROW( CException(sc) );
}
if ( fLeaveCorruptCatalog )
{
Win4Assert( !"leaving corrupt catalog" );
THROW( CException( sc ) );
}
ciDebugOut(( DEB_ERROR, "ContentIndex is corrupt. It will be emptied\n" ));
//Win4Assert( !"Startup CI Data Corruption" );
xCat->LogEvent( CCiStatusMonitor::eCiRemoved );
//
// Content Index is corrupt. Ask CI to delete the contentIndex and
// start afresh.
//
startupInfo.startupFlags |= CI_CONFIG_EMPTY_DATA;
sc = pCiStartup->StartupContentIndex( xCat->GetCatDir(),
&startupInfo,
0,
&fAbort );
if ( FAILED(sc) )
{
THROW( CException(sc) );
}
fFullScanNeeded = TRUE;
}
xCat->ClearCiDataCorrupt();
xCat->InitIf( fLeaveCorruptCatalog );
//
// Optimization - we may want to just force an "add" of the documents in the
// property store rather than a full scan of the corpus.
//
if ( fFullScanNeeded )
xCat->MarkFullScanNeeded();
xCat.Acquire();
}
//+---------------------------------------------------------------------------
//
// Member: CClientDocStore::_CreateCiManager
//
// Synopsis: Creates the CI manager by doing a CoCreateInstance of the
// ICiControl.
//
// History: 1-31-97 srikants Created
//
//----------------------------------------------------------------------------
void CClientDocStore::_CreateCiManager()
{
//
// We have to create the ICiManager also now.
//
ICiControl * pICiControl = 0;
GUID clsIdCiControl = CLSID_CiControl;
SCODE sc = CoCreateInstance( clsIdCiControl,
NULL,
CLSCTX_INPROC_SERVER,
IID_ICiControl,
(void **) &pICiControl );
if ( 0 == pICiControl )
{
ciDebugOut(( DEB_ERROR, "Cannot CoCreateInstance IID_ICiControl. Error (0x%X)\n",
sc ));
THROW( CException(sc) );
}
XInterface<ICiControl> xCiControl( pICiControl );
ICiManager * pICiManager = 0;
sc = xCiControl->CreateContentIndex( this, &pICiManager );
if ( 0 == pICiManager )
{
ciDebugOut(( DEB_ERROR, "Cannot Get ContentIndex. Error 0x%X\n",
sc ));
THROW( CException(sc) );
}
_xCiManager.Set( pICiManager );
} //_CreateCiManager
//+---------------------------------------------------------------------------
//
// Member: CClientDocStore::~CClientDocStore
//
// Synopsis: Destructor of the client document store.
//
// History: 12-03-96 srikants Created
//
//----------------------------------------------------------------------------
CClientDocStore::~CClientDocStore()
{
delete _pCiCat;
delete _pCiNullCat;
}
//+---------------------------------------------------------------------------
//
// Member: CClientDocStore::IsPropertyCached
//
// Synopsis: Tests if the given property is cached in the property
// store or not.
//
// Arguments: [pPropSpec] - Property to test.
// [pfValue] - Set to TRUE if cached; FALSE o/w
//
// Returns: S_OK if successful;
// Some other error code if not in a valid state.
//
// History: 12-03-96 srikants Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CClientDocStore::IsPropertyCached(
const FULLPROPSPEC * pPropSpec,
BOOL * pfValue )
{
Win4Assert( 0 != pfValue );
Win4Assert( 0 != pPropSpec );
Win4Assert( 0 != _pCiCat );
CFullPropSpec const & ps = *((CFullPropSpec const *) pPropSpec);
SCODE sc = S_OK;
TRY
{
*pfValue = _pCiCat->IsPropertyCached( ps );
}
CATCH( CException, e )
{
sc = e.GetErrorCode();
}
END_CATCH
return sc;
}
//+---------------------------------------------------------------------------
//
// Function: StoreProperty
//
// Synopsis: Stores the given property for the workid.
//
// Arguments: [workid] - WorkId of the document
// [pPropSpec] - Property to be stored
// [pPropVariant] - Value of the property
//
// Returns: S_OK if successful
// CI_E_PROPERTY_NOT_CACHED if it is not a cached property.
// Other error code
//
// History: 12-03-96 srikants Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CClientDocStore::StoreProperty(
WORKID workid,
const FULLPROPSPEC * pPropSpec,
const PROPVARIANT * pPropVariant )
{
Win4Assert( 0 != pPropSpec );
Win4Assert( 0 != pPropVariant );
Win4Assert( 0 != _pCiCat );
CFullPropSpec const & ps = *((CFullPropSpec const *) pPropSpec);
CStorageVariant const & var = *(ConvertToStgVariant( pPropVariant ));
SCODE sc = S_OK;
TRY
{
BOOL fStored = _pCiCat->StoreValue( workid, ps, var );
if ( !fStored )
sc = CI_E_PROPERTY_NOT_CACHED;
}
CATCH( CException, e )
{
sc = e.GetErrorCode();
}
END_CATCH
return sc;
}
//+---------------------------------------------------------------------------
//
// Member: CClientDocStore::FlushPropertyStore
//
// Synopsis: Causes the property store to flush.
//
// History: 06-30-97 KrishnaN Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CClientDocStore::FlushPropertyStore (void)
{
SCODE sc = S_OK;
Win4Assert(_pCiCat);
TRY
{
//
// Flushing the property store at this point (just before a shadow
// merge) is necessary for Push model filtering, but not for clients
// like fsci that do Pull model filtering. The changelog,
// scopetable, and property store are already tightly linked and
// flushed appropriately.
//
// _pCiCat->FlushPropertyStore();
}
CATCH( CException, e)
{
sc = e.GetErrorCode();
}
END_CATCH
return sc;
}
//+---------------------------------------------------------------------------
//
// Member: CClientDocStore::GetClientStatus
//
// Synopsis: Retrieves the client status information
//
// Arguments: [pStatus] - Will have the status information on output.
//
// History: 12-05-96 srikants Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CClientDocStore::GetClientStatus(
CI_CLIENT_STATUS * pStatus )
{
Win4Assert( 0 != pStatus );
SCODE sc = S_OK;
TRY
{
ULONG cPendingScans, state;
if (_pCiNullCat)
_pCiNullCat->CatalogState( pStatus->cDocuments,
cPendingScans,
state );
else
_pCiCat->CatalogState( pStatus->cDocuments,
cPendingScans,
state );
}
CATCH( CException,e )
{
sc = e.GetErrorCode();
}
END_CATCH
return sc;
}
//+---------------------------------------------------------------------------
//
// Member: CClientDocStore::GetContentIndex
//
// Synopsis: Returns the ICiManager if there is one and we are not
// in a shutdown sequence.
//
// Arguments: [ppICiManager] - ICiManager pointer
//
//
// Returns: S_OK if successful
// CI_E_SHUTDOWN if shutdown
// CI_E_NOT_INITIALIZED if not yet initialized
//
// History: 12-10-96 srikants Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CClientDocStore::GetContentIndex(
ICiManager ** ppICiManager)
{
Win4Assert( 0 != ppICiManager );
SCODE sc = S_OK;
CLock lock(_mutex);
if ( !_IsShutdown() && _xCiManager.GetPointer() )
{
_xCiManager->AddRef();
*ppICiManager = _xCiManager.GetPointer();
}
else
{
*ppICiManager = 0;
if ( _IsShutdown() )
sc = CI_E_SHUTDOWN;
else sc = CI_E_NOT_INITIALIZED;
}
return sc;
}
//+---------------------------------------------------------------------------
//
// Member: CClientDocStore::EnableUpdates
//
// Synopsis: Enables updates from document store.
//
// History: 12-09-96 srikants Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CClientDocStore::EnableUpdates()
{
SCODE sc = S_OK;
Win4Assert(_pCiCat);
BOOL fEnableUpdateNotifies = FALSE;
TRY
{
// =============================================================
{
CLock lock(_mutex);
if ( _IsShutdown() )
{
ciDebugOut(( DEB_ERROR,
"CClientDocStore::EnableUpdates called after shutdown\n" ));
THROW( CException( CI_E_SHUTDOWN ) );
}
fEnableUpdateNotifies = _AreUpdatesDisabled();
_state = eUpdatesEnabled;
}
// =============================================================
//
// Notifications are not disabled on DisableUpdates and so only scans/usns
// need to be scheduled, which is done by NoLokClearDiskFull
//
if ( fEnableUpdateNotifies )
_pCiCat->NoLokClearDiskFull();
}
CATCH( CException, e )
{
ciDebugOut(( DEB_ERROR,
"CClientDocStore::EnableUpdates caught error (0x%X)\n",
e.GetErrorCode() ));
sc = e.GetErrorCode();
}
END_CATCH
if ( S_OK != sc && fEnableUpdateNotifies )
{
//
// There was a failure while enabling udpates. We must set
// the state back to indicate that updates are not enabled.
//
CLock lock(_mutex);
_LokDisableUpdates();
}
return sc;
}
//+---------------------------------------------------------------------------
//
// Member: CClientDocStore::DisableUpdates
//
// Synopsis: Disables further updates and prevents update notifications
// until enabled via the "EnableUpdates" call.
//
// History: 12-31-96 srikants Created
//
//----------------------------------------------------------------------------
STDMETHODIMP
CClientDocStore::DisableUpdates( BOOL fIncremental,
CI_DISABLE_UPDATE_REASON dwReason )
{
Win4Assert(_pCiCat);
if ( _IsShutdown() )
return CI_E_SHUTDOWN;
SCODE sc = S_OK;
TRY
{
{
CLock lock(_mutex);
_LokDisableUpdates();
}
if ( fIncremental )
{
_pCiCat->MarkIncrScanNeeded();
_pCiCat->NoLokProcessDiskFull();
}
else
{
if ( dwReason == CI_CORRUPT_INDEX )
_pCiCat->HandleError( CI_CORRUPT_DATABASE );
else
{
_pCiCat->MarkFullScanNeeded();
_pCiCat->NoLokProcessDiskFull();
}
}
}
CATCH( CException, e )
{
sc = e.GetErrorCode();
ciDebugOut(( DEB_ERROR,
"Error (0x%X) while disabling updates\n",
sc ));
}
END_CATCH
return sc;
}
//+---------------------------------------------------------------------------
//
// Member: CClientDocStore::ProcessCiDaemonTermination
//
// Synopsis: Processes the death of CiDaemon. Creates a work item to
// restart the filter daemon.
//
// History: 12-23-96 srikants Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CClientDocStore::ProcessCiDaemonTermination( DWORD dwStatus )
{
//
// The CiDaemon process is dead; Just start filtering again.
//
SCODE sc = S_OK;
TRY
{
CStartFilterDaemon * pWorkItem = new CStartFilterDaemon( *this, _workMan );
_workMan.AddToWorkList( pWorkItem );
pWorkItem->AddToWorkQueue();
pWorkItem->Release();
}
CATCH( CException, e)
{
ciDebugOut(( DEB_ERROR,
"Failed to create a work item for start filter daemon. Error 0x%X\n",
e.GetErrorCode() ));
sc = e.GetErrorCode();
}
END_CATCH
return sc;
}
//+---------------------------------------------------------------------------
//
// Member: CClientDocStore::CheckPointChangesFlushed
//
// Synopsis: Processes a changelog flush.
//
// History: 12-23-96 srikants Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CClientDocStore::CheckPointChangesFlushed(
FILETIME ftFlushed,
ULONG cEntries,
USN_FLUSH_INFO const * const *ppUsnEntries)
{
SCODE sc = S_OK;
Win4Assert(_pCiCat);
TRY
{
_pCiCat->ProcessChangesFlush( ftFlushed, cEntries, ppUsnEntries );
}
CATCH( CException,e )
{
ciDebugOut(( DEB_ERROR,
"CheckPointChangesFlushed failed. Error 0x%X\n",
e.GetErrorCode() ));
sc = e.GetErrorCode();
}
END_CATCH
return sc;
}
//+---------------------------------------------------------------------------
//
// Member: CClientDocStore::MarkDocUnReachable
//
// Synopsis: Marks that the document was not reachable when an attempt
// was made to filter it.
//
// Arguments: [wid] - The WORKID which could not be reached.
//
// History: 12-10-96 srikants Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CClientDocStore::MarkDocUnReachable(
WORKID wid )
{
SCODE sc = S_OK;
Win4Assert(_pCiCat);
TRY
{
_pCiCat->MarkUnReachable( wid );
}
CATCH( CException, e )
{
ciDebugOut(( DEB_ERROR,
"CClientDocStore::MarkDocUnReachable caught exception (0x%X)\n",
e.GetErrorCode() ));
sc = e.GetErrorCode();
}
END_CATCH
return sc;
}
//+---------------------------------------------------------------------------
//
// Member: CClientDocStore::StoreSecurity
//
// Synopsis: Stores the given security data for the workid.
//
// Arguments: [wid] - WorkId of the document
// [pbData] - Security data buffer
// [cbData] - NUmber of bytes in the security data buffer
//
// History: 1-15-97 srikants Created
//
// Notes: We may want to eliminate this call and instead have the
// security be stored as a special property.
//
//----------------------------------------------------------------------------
STDMETHODIMP CClientDocStore::StoreSecurity(
WORKID wid,
BYTE const * pbData,
ULONG cbData )
{
SCODE sc = S_OK;
Win4Assert(_pCiCat);
TRY
{
_pCiCat->StoreSecurity( wid, (PSECURITY_DESCRIPTOR) pbData, cbData );
}
CATCH( CException, e )
{
ciDebugOut(( DEB_ERROR,
"CClientDocStore::MarkDocUnReachable caught exception (0x%X)\n",
e.GetErrorCode() ));
sc = e.GetErrorCode();
}
END_CATCH
return sc;
}
//+---------------------------------------------------------------------------
//
// Member: CClientDocStore::IsNoQuery
//
// Synopsis: Check if the docstore is set to NoQuery
//
// Arguments: [fNoQuery] - Output
//
// History: 05-26-98 kitmanh Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CClientDocStore::IsNoQuery(
BOOL * fNoQuery )
{
SCODE sc = S_OK;
if ( !fNoQuery )
sc = STATUS_INVALID_PARAMETER;
else
*fNoQuery = _fNoQuery;
return sc;
}
//+---------------------------------------------------------------------------
//
// Member: CClientDocStore::GetPropertyMapper
//
// Synopsis: Retrieves the interface to IPropertyMapper.
//
// Arguments: [ppIPropertyMapper] - On output, will have the IPropertyMapper.
//
// Returns: S_OK if successful;
// E_NOTIMPL if property mapper is not supported by doc store.
// Other error code if there is a failure.
// Modifies:
//
// History: 12-31-96 srikants Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CClientDocStore::GetPropertyMapper(
IPropertyMapper ** ppIPropertyMapper)
{
SCODE sc = S_OK;
TRY
{
Win4Assert( 0 != _xPropMapper.GetPointer() );
*ppIPropertyMapper = _xPropMapper.GetPointer();
_xPropMapper->AddRef();
}
CATCH( CException, e )
{
ciDebugOut(( DEB_ERROR,
"CClientDocStore::MarkDocUnReachable caught exception (0x%X)\n",
e.GetErrorCode() ));
sc = e.GetErrorCode();
}
END_CATCH
return sc;
}
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// ICiCDocNameToWorkidTranslatorEx methods.
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//+---------------------------------------------------------------------------
//
// Member: CClientDocStore::QueryDocName
//
// Synopsis: Creates a new doc name object and returns its interface.
//
// Arguments: [ppICiCDocName] - [out] Will have a pointer to the
// ICiCDocName object filled in.
//
// History: 12-05-96 srikants Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CClientDocStore::QueryDocName(
ICiCDocName ** ppICiCDocName )
{
Win4Assert( 0 != ppICiCDocName );
SCODE sc = S_OK;
TRY
{
*ppICiCDocName = new CCiCDocName;
}
CATCH( CException,e )
{
sc = e.GetErrorCode();
}
END_CATCH
return sc;
}
//+---------------------------------------------------------------------------
//
// Member: CClientDocStore::WorkIdToDocName
//
// Synopsis: Translates a WorkId to a document name.
//
// Arguments: [workid] - [in] WorkId to translate
// [pICiCDocName] - [out] Will be filled in with the document
// name on output.
//
// Returns: S_OK if successfully converted.
// CI_E_BUFFERTOOSMALL if the buffer is not big enough
// Other error code.
//
// History: 12-05-96 srikants Created
//
// Notes: This method may be one of the most frequently called methods.
// Look for optimizations (esp. can the TRY/CATCH be avoided?)
//
//----------------------------------------------------------------------------
STDMETHODIMP CClientDocStore::WorkIdToDocName(
WORKID workid,
ICiCDocName * pICiCDocName )
{
return InternalWorkIdToDocName( workid, pICiCDocName, FALSE );
}
//+---------------------------------------------------------------------------
//
// Member: CClientDocStore::DocNameToWorkId
//
// Synopsis: Converts a document name to a WorkId.
//
// Arguments: [pICiCDocName] - Document Name
// [pWorkid] - [out] Will have the workid on output.
//
// Returns: S_OK if successful; Error code otherwise.
//
// History: 12-05-96 srikants Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CClientDocStore::DocNameToWorkId(
ICiCDocName const * pICiCDocName,
WORKID * pWorkid )
{
SCODE sc = S_OK;
Win4Assert( 0 != pICiCDocName );
Win4Assert( 0 != pWorkid );
TRY
{
CCiCDocName const * pDocName = (CCiCDocName const *) pICiCDocName;
*pWorkid = _pCiCat->PathToWorkId( pDocName->GetPath(), TRUE );
}
CATCH( CException, e )
{
sc = e.GetErrorCode();
}
END_CATCH
return sc;
}
//+---------------------------------------------------------------------------
//
// Member: CClientDocStore::WorkIdToAccurateDocName
//
// Synopsis: Translates a WorkId 'accurately' to a document name.
//
// Arguments: [workid] - [in] WorkId to translate
// [pICiCDocName] - [out] Will be filled in with the document
// name on output.
//
// Returns: S_OK if successfully converted.
// CI_E_BUFFERTOOSMALL if the buffer is not big enough
// Other error code.
//
// History: 31-Dec-1998 KyleP Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CClientDocStore::WorkIdToAccurateDocName(
WORKID workid,
ICiCDocName * pICiCDocName )
{
return InternalWorkIdToDocName( workid, pICiCDocName, TRUE );
}
//+---------------------------------------------------------------------------
//
// Member: CClientDocStore::_GetPerfIndex
//
// Synopsis: An internal helper function to get the offset of the perfmon
// counter in the perfmon shared memory.
//
// Arguments: [name] - Name of the counter.
// [index] - Index of the name
//
// Returns: TRUE if successfully looked up; FALSE on failure.
//
// History: 12-06-96 srikants Created
//
//----------------------------------------------------------------------------
BOOL CClientDocStore::_GetPerfIndex( CI_PERF_COUNTER_NAME name, ULONG & index )
{
BOOL fOk= TRUE;
ULONG offset = 0;
switch ( name )
{
case CI_PERF_NUM_WORDLIST:
offset = NUM_WORDLIST;
break;
case CI_PERF_NUM_PERSISTENT_INDEXES:
offset = NUM_PERSISTENT_INDEX;
break;
case CI_PERF_INDEX_SIZE:
offset = INDEX_SIZE;
break;
case CI_PERF_FILES_TO_BE_FILTERED:
offset = FILES_TO_BE_FILTERED;
break;
case CI_PERF_NUM_UNIQUE_KEY:
offset = NUM_UNIQUE_KEY;
break;
case CI_PERF_RUNNING_QUERIES:
offset = RUNNING_QUERIES;
break;
case CI_PERF_MERGE_PROGRESS:
offset = MERGE_PROGRESS;
break;
case CI_PERF_DOCUMENTS_FILTERED:
offset = DOCUMENTS_FILTERED;
break;
case CI_PERF_NUM_DOCUMENTS:
offset = NUM_DOCUMENTS;
break;
case CI_PERF_TOTAL_QUERIES:
offset = TOTAL_QUERIES;
break;
case CI_PERF_DEFERRED_FILTER_FILES:
offset = DEFERRED_FILTER_FILES;
break;
default:
fOk = FALSE;
}
if ( fOk )
index = offset + KERNEL_USER_INDEX;
return fOk;
}
//+---------------------------------------------------------------------------
//
// Member: CClientDocStore::SetPerfCounterValue
//
// Synopsis: Sets the value of the perfmon counter.
//
// Arguments: [name] - Name of the counter
// [value] - Value to be set.
//
// Returns: S_OK if a valid perfmon name; E_INVALIDARG if the perfmon
// name is not correct.
//
// History: 12-06-96 srikants Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CClientDocStore::SetPerfCounterValue(
CI_PERF_COUNTER_NAME name,
long value )
{
// true for the NULL catalog
if ( _xPerfMon.IsNull() )
return S_OK;
SCODE sc = S_OK;
ULONG index;
//
// CPerfMon::Update must not throw.
//
if ( _GetPerfIndex( name, index ) )
_xPerfMon->Update( index, value );
else
sc = E_INVALIDARG;
return sc;
}
//+---------------------------------------------------------------------------
//
// Member: CClientDocStore::IncrementPerfCounterValue
//
// Synopsis: Increments the value of the perfmon counter.
//
// Arguments: [name] - Name of the counter
//
// Returns: S_OK if a valid perfmon name; E_INVALIDARG if the perfmon
// name is not correct.
//
// History: 1-15-97 dlee Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CClientDocStore::IncrementPerfCounterValue(
CI_PERF_COUNTER_NAME name )
{
// true for the NULL catalog
if ( _xPerfMon.IsNull() )
return S_OK;
SCODE sc = S_OK;
ULONG index;
//
// CPerfMon::Update must not throw.
//
if ( _GetPerfIndex( name, index ) )
_xPerfMon->Increment( index );
else
sc = E_INVALIDARG;
return sc;
}
//+---------------------------------------------------------------------------
//
// Member: CClientDocStore::DecrementPerfCounterValue
//
// Synopsis: Decrements the value of the perfmon counter.
//
// Arguments: [name] - Name of the counter
//
// Returns: S_OK if a valid perfmon name; E_INVALIDARG if the perfmon
// name is not correct.
//
// History: 1-15-97 dlee Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CClientDocStore::DecrementPerfCounterValue(
CI_PERF_COUNTER_NAME name )
{
// true for the NULL catalog
if ( _xPerfMon.IsNull() )
return S_OK;
SCODE sc = S_OK;
ULONG index;
//
// CPerfMon::Update must not throw.
//
if ( _GetPerfIndex( name, index ) )
_xPerfMon->Decrement( index );
else
sc = E_INVALIDARG;
return sc;
} //DecrementPerfCounterValue
//+---------------------------------------------------------------------------
//
// Member: CClientDocStore::GetPerfCounterValue
//
// Synopsis: Retrieves the value of the perfmon counter.
//
// Arguments: [name] - [see SetPerfCounterValue]
// [pValue] - "
//
// History: 12-06-96 srikants Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CClientDocStore::GetPerfCounterValue(
CI_PERF_COUNTER_NAME name,
long * pValue )
{
// true for the NULL catalog
if ( _xPerfMon.IsNull() )
return S_OK;
Win4Assert( pValue );
ULONG index;
SCODE sc = S_OK;
if ( _GetPerfIndex( name, index ) )
*pValue = _xPerfMon->GetCurrValue( index );
else
sc = E_INVALIDARG;
return sc;
}
//+------------------------------------------------------
//
// Member: CClientDocStore::NotifyEvent
//
// Synopsis: Reports the passed in event and arguments to eventlog
//
// Arguments: [fType ] - Type of event
// [eventId] - Message file event identifier
// [nParams] - Number of substitution arguments being passed
// [aParams] - pointer to PROPVARIANT array of substitution args.
// [cbData ] - number of bytes in supplemental raw data.
// [data ] - pointer to block of supplemental data.
//
// Returns: S_OK upon success, value of the exception if an exception
// is thrown.
//
// History: 12-30-96 mohamedn Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CClientDocStore::NotifyEvent( WORD fType,
DWORD eventId,
ULONG nParams,
const PROPVARIANT *aParams,
ULONG cbData,
void* data)
{
SCODE sc = S_OK;
TRY
{
CClientNotifyEvent notifyEvent(fType,eventId,nParams,aParams,cbData,data);
}
CATCH( CException,e )
{
ciDebugOut(( DEB_ERROR, "Exception 0x%X in CClientDocStore::NotifyEvent()\n",
e.GetErrorCode() ));
sc = e.GetErrorCode();
}
END_CATCH
return sc;
}
//+---------------------------------------------------------------------------
//
// Member: CClientDocStore::NotifyStatus
//
// Synopsis: When a special status is being notified.
//
// Returns: S_OK always.
//
// History: 12-05-96 srikants Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CClientDocStore::NotifyStatus(
CI_NOTIFY_STATUS_VALUE status,
ULONG nParams,
const PROPVARIANT * aParams )
{
SCODE sc = S_OK;
switch ( status )
{
case CI_NOTIFY_FILTERING_FAILURE:
Win4Assert( nParams == 1 );
Win4Assert( aParams[0].vt == VT_I4 || aParams[0].vt == VT_UI4 );
if ( 1 == nParams )
_ReportFilteringFailure( aParams[0].ulVal );
break;
case CI_NOTIFY_FILTER_TOO_MANY_BLOCKS:
case CI_NOTIFY_FILTER_EMBEDDING_FAILURE:
//
// This is possible in the in-proc filtering because
// the advise status is provided by docstore for filtering
// also.
//
{
CStorageFilterObjNotifyStatus notify( this );
sc = notify.NotifyStatus( status, nParams, aParams );
}
break;
default:
Win4Assert( !"Invalid Case Stmt" );
break;
};
return sc;
}
//
// IFsCiAdmin methods.
//
//+---------------------------------------------------------------------------
//
// Member: CClientDocStore::ForceMerge
//
// Synopsis: Forces a master merge on the given partition id.
//
// History: 2-12-97 srikants Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CClientDocStore::ForceMerge( PARTITIONID partId )
{
SCODE sc = S_OK;
TRY
{
if ( 0 == _pCiCat )
THROW( CException( E_INVALIDARG ) );
sc = _pCiCat->ForceMerge( partId );
}
CATCH( CException,e )
{
ciDebugOut(( DEB_ERROR, "Error 0x%X in CClientDocStore::ForceMerge\n",
e.GetErrorCode() ));
sc = e.GetErrorCode();
}
END_CATCH
return sc;
}
//+---------------------------------------------------------------------------
//
// Member: CClientDocStore::AbortMerge
//
// Synopsis: Aborts any in-progress merge on the given partition id.
//
// History: 2-12-97 srikants Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CClientDocStore::AbortMerge( PARTITIONID partId )
{
SCODE sc = S_OK;
TRY
{
if ( 0 == _pCiCat )
THROW( CException( E_INVALIDARG ) );
sc = _pCiCat->AbortMerge( partId );
}
CATCH( CException,e )
{
ciDebugOut(( DEB_ERROR, "Error 0x%X in CClientDocStore::AbortMerge\n",
e.GetErrorCode() ));
sc = e.GetErrorCode();
}
END_CATCH
return sc;
}
//+---------------------------------------------------------------------------
//
// Member: CClientDocStore::CiState
//
// Synopsis: Retrieves the CI_STATE information.
//
// Arguments: [pCiState] - On output, will contain the cistate data.
//
// History: 2-12-97 srikants Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CClientDocStore::CiState( CI_STATE * pCiState )
{
SCODE sc = S_OK;
TRY
{
if (_pCiNullCat)
sc = _pCiNullCat->CiState( *pCiState );
else
sc = _pCiCat->CiState( *pCiState );
}
CATCH( CException,e )
{
ciDebugOut(( DEB_ERROR, "Error 0x%X in CClientDocStore::CiState\n",
e.GetErrorCode() ));
sc = e.GetErrorCode();
}
END_CATCH
return sc;
}
//+---------------------------------------------------------------------------
//
// Member: CClientDocStore::UpdateDocuments
//
// Synopsis: Forces a scan on the given root.
//
// Arguments: [rootPath] - Root to force a scan on.
// [flag] - Indicating if this is a full scan or a partial
// scan.
//
// History: 2-12-97 srikants Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CClientDocStore::UpdateDocuments(
const WCHAR *rootPath,
ULONG flag )
{
SCODE sc = S_OK;
TRY
{
if ( 0 == _pCiCat )
THROW( CException( E_INVALIDARG ) );
_pCiCat->UpdateDocuments( rootPath, flag);
}
CATCH( CException,e )
{
ciDebugOut(( DEB_ERROR, "Error 0x%X in CClientDocStore::UpdateDocuments\n",
e.GetErrorCode() ));
sc = e.GetErrorCode();
}
END_CATCH
return sc;
}
//+---------------------------------------------------------------------------
//
// Member: CClientDocStore::AddScopeToCI
//
// Synopsis: Adds the given scope to ContentIndex for indexing.
//
// Arguments: [rootPath] - Path to add
//
// History: 2-12-97 srikants Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CClientDocStore::AddScopeToCI(
const WCHAR *rootPath )
{
SCODE sc = S_OK;
TRY
{
if ( 0 == _pCiCat )
THROW( CException( E_INVALIDARG ) );
_pCiCat->AddScopeToCI( rootPath );
}
CATCH( CException,e )
{
ciDebugOut(( DEB_ERROR, "Error 0x%X in CClientDocStore::AddScopeToCI\n",
e.GetErrorCode() ));
sc = e.GetErrorCode();
}
END_CATCH
return sc;
}
//+---------------------------------------------------------------------------
//
// Member: CClientDocStore::RemoveScopeFromCI
//
// Synopsis: Removes the given scope from CI.
//
// Arguments: [rootPath] - Scope to remove.
//
// History: 2-12-97 srikants Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CClientDocStore::RemoveScopeFromCI(
const WCHAR *rootPath )
{
SCODE sc = S_OK;
TRY
{
if ( 0 == _pCiCat )
THROW( CException( E_INVALIDARG ) );
_pCiCat->RemoveScopeFromCI( rootPath, FALSE );
}
CATCH( CException,e )
{
ciDebugOut(( DEB_ERROR, "Error 0x%X in CClientDocStore::RemoveScopeFromCI\n",
e.GetErrorCode() ));
sc = e.GetErrorCode();
}
END_CATCH
return sc;
}
//+---------------------------------------------------------------------------
//
// Member: CClientDocStore::BeginCacheTransaction
//
// Synopsis: Begins a property cache transaction.
//
// Arguments: [pulToken] - Output - Transaction "cookie".
//
// History: 2-12-97 srikants Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CClientDocStore::BeginCacheTransaction(
ULONG_PTR * pulToken )
{
SCODE sc = S_OK;
TRY
{
if ( 0 == _pCiCat )
THROW( CException( E_INVALIDARG ) );
*pulToken = _pCiCat->BeginCacheTransaction();
}
CATCH( CException,e )
{
ciDebugOut(( DEB_ERROR, "Error 0x%X in CClientDocStore::BeginCacheTransaction\n",
e.GetErrorCode() ));
sc = e.GetErrorCode();
}
END_CATCH
return sc;
}
//+---------------------------------------------------------------------------
//
// Member: CClientDocStore::SetupCache
//
// Synopsis: Sets up the property for storing the property cache.
//
// Arguments: [ps] -
// [vt] -
// [cbMaxLen] -
// [ulToken] -
//
// History: 2-12-97 srikants Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CClientDocStore::SetupCache(
const FULLPROPSPEC *ps,
ULONG vt,
ULONG cbMaxLen,
ULONG_PTR ulToken,
BOOL fCanBeModified,
DWORD dwStoreLevel)
{
Win4Assert(PRIMARY_STORE == dwStoreLevel ||
SECONDARY_STORE == dwStoreLevel);
SCODE sc = S_OK;
TRY
{
if ( 0 == _pCiCat )
THROW( CException( E_INVALIDARG ) );
CFullPropSpec * pFullPropSpec = (CFullPropSpec *)ps;
_pCiCat->SetupCache( *pFullPropSpec,
vt,
cbMaxLen,
ulToken,
fCanBeModified,
dwStoreLevel );
}
CATCH( CException,e )
{
ciDebugOut(( DEB_ERROR, "Error 0x%X in CClientDocStore::RemoveVirtualScope\n",
e.GetErrorCode() ));
sc = e.GetErrorCode();
}
END_CATCH
return sc;
}
//+---------------------------------------------------------------------------
//
// Member: CClientDocStore::EndCacheTransaction
//
// Synopsis: Ends the property cache transaction.
//
// Arguments: [ulToken] -
// [fCommit] -
//
// History: 2-12-97 srikants Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CClientDocStore::EndCacheTransaction(
ULONG_PTR ulToken,
BOOL fCommit )
{
SCODE sc = S_OK;
TRY
{
if ( 0 == _pCiCat )
THROW( CException( E_INVALIDARG ) );
_pCiCat->EndCacheTransaction( ulToken, fCommit );
}
CATCH( CException,e )
{
ciDebugOut(( DEB_ERROR, "Error 0x%X in CClientDocStore::RemoveVirtualScope\n",
e.GetErrorCode() ));
sc = e.GetErrorCode();
}
END_CATCH
return sc;
}
//+-------------------------------------------------------------------------
//
// Method: CClientDocStore::IsIoHigh, public
//
// Returns: S_OK if system is in a high i/o state, S_FALSE if it is not.
//
// History: 21-Jul-1998 KyleP Created
//
//--------------------------------------------------------------------------
SCODE CClientDocStore::IsIoHigh( BOOL * pfAbort )
{
// Windows XP removed support for the IOCTL we used to measure disk
// usage.
return S_FALSE;
} //IsIoHigh
//
// Non-Interface methods.
//
//+---------------------------------------------------------------------------
//
// Member: CClientDocStore::_StartFiltering
//
// Synopsis: Asks the CiManager to start filter daemon and resume
// filtering.
//
// History: 12-09-96 srikants Created
//
//----------------------------------------------------------------------------
void CClientDocStore::_StartFiltering()
{
XInterface<ICiManager> xManager;
// =============================================
{
CLock lock(_mutex);
if ( !_IsShutdown() && _xCiManager.GetPointer() )
{
_xCiManager->AddRef();
xManager.Set( _xCiManager.GetPointer() );
}
else
{
ciDebugOut(( DEB_WARN,
"Already Shutdown or CI not started. Cannot start filtering\n" ));
return;
}
}
// =============================================
//
// Get the startup data and serialize it.
//
WCHAR const * pwszName = _pCiCat->GetName();
WCHAR const * pwszCatDir = _pCiCat->GetDriveName();
CDaemonStartupData startupData( pwszCatDir,
pwszName );
ULONG cbData;
BYTE * pbData = startupData.Serialize( cbData );
XArray<BYTE> xBuf;
xBuf.Set(cbData,pbData);
xManager->StartFiltering( cbData, pbData );
//
// Note: Should we be worried about StartFiltering failing ??
//
}
//+---------------------------------------------------------------------------
//
// Member: CClientDocStore::Shutdown
//
// Synopsis: Intiates a shutdown of the document store and the
// CiManager associated with the document store.
//
// History: 12-05-96 srikants Created
//
//----------------------------------------------------------------------------
void CClientDocStore::Shutdown()
{
TRY
{
Win4Assert( !_IsShutdown() );
// =============================================
{
CLock lock(_mutex);
_LokMarkShutdown();
}
// =============================================
#if CIDBG==1
if ( !_xSaveTest.IsNull() )
_xSaveTest->InitiateShutdown();
#endif // CIDBG==1
if (_pCiNullCat)
_pCiNullCat->ShutdownPhase1();
else
_pCiCat->ShutdownPhase1();
if ( _xCiManager.GetPointer() )
{
_xCiManager->Shutdown();
_xCiManager.Free();
}
#if CIDBG==1
if ( !_xSaveTest.IsNull() )
_xSaveTest->WaitForDeath();
#endif //CIDBG==1
if (_pCiNullCat)
_pCiNullCat->ShutdownPhase2();
else
_pCiCat->ShutdownPhase2();
}
CATCH( CException, e)
{
ciDebugOut(( DEB_ERROR, "Error (0x%X) in CClientDocStore::Shutdown\n",
e.GetErrorCode() ));
}
END_CATCH
}
//+---------------------------------------------------------------------------
//
// Member: CClientDocStore::GetName
//
// Synopsis: Gets the catalog name (if any)
//
// History: 12-05-96 srikants Created
//
//----------------------------------------------------------------------------
WCHAR const * CClientDocStore::GetName()
{
if (_pCiNullCat)
return _pCiNullCat->GetName();
else
return _pCiCat->GetName();
}
//+---------------------------------------------------------------------------
//
// Member: CClientDocStore::_SetCiCatRecovered
//
// Synopsis: Sets that the CiCat is recovered and if updates were
// enabled by Content Index, it asks CiCat to start scans
// and notifications.
//
// History: 12-09-96 srikants Created
// 02-25-98 kitmanh if catalog is read-only, don't filter
//
// Notes: This method MUST be called in SYSTEM context only. This
// starts filtering which in turn creates the filter daemon
// proxy thread and that must be in SYSTEM context.
//
//----------------------------------------------------------------------------
void CClientDocStore::_SetCiCatRecovered()
{
Win4Assert( 0 != _pCiCat );
Win4Assert( !CImpersonateSystem::IsImpersonated() );
BOOL fEnableFilering = FALSE;
//don't start filtering if catalog is read-only
if ( !_pCiCat->IsReadOnly() )
{
// ==================================================
{
CLock lock(_mutex);
fEnableFilering = _AreUpdatesEnabled();
}
// ==================================================
//
// Since CiCat has been recovered fully, filtering can be started
// if we are running with "indexing" enabled.
//
_StartFiltering();
if ( fEnableFilering )
_pCiCat->EnableUpdateNotifies();
}
}
//+---------------------------------------------------------------------------
//
// Member: CClientDocStore::IsLowOnDiskSpace
//
// Synopsis: Returns the status of free space on the disk used by
// docstore (client) based on the last check.
//
// Returns: TRUE if low on free disk space; FALSE o/w
//
// History: 12-10-96 srikants Created
//
// Notes: This does not actually make an I/O. Just returns an in-memory
// status.
//
//----------------------------------------------------------------------------
BOOL CClientDocStore::IsLowOnDiskSpace() const
{
Win4Assert ( !_xDiskStatus.IsNull() );
return _xDiskStatus->IsLow();
}
//+---------------------------------------------------------------------------
//
// Member: CClientDocStore::VerifyIfLowOnDiskSpace
//
// Synopsis: Verifies the free disk space situation by making an I/O call
// to the O/S.
//
// Returns: TRUE if disk is getting to be full; FALSE o/w
//
// History: 12-10-96 srikants Created
//
//----------------------------------------------------------------------------
BOOL CClientDocStore::VerifyIfLowOnDiskSpace()
{
Win4Assert ( !_xDiskStatus.IsNull() );
_xDiskStatus->UpdateDiskLowInfo();
return _xDiskStatus->IsLow();
}
//+---------------------------------------------------------------------------
//
// Member: CClientDocStore::_ReportFilteringFailure
//
// Synopsis: Reports that there was filtering failure on the given wid.
//
// Arguments: [wid] - Workid which failed to filter.
//
// History: 1-24-97 srikants Created
//
//----------------------------------------------------------------------------
void CClientDocStore::_ReportFilteringFailure( WORKID wid )
{
ciDebugOut(( DEB_IWARN,
"Warning: unsuccessful attempts to filter workid 0x%X; "
"cancelling\n", wid ));
}
//+---------------------------------------------------------------------------
//
// Member: CClientDocStore::GetQuerySession
//
// Synopsis: Returns a query session object
//
// Returns: [ppICiCQuerySession] -- Session object is returned here
//
// History: 22-Jan-97 SitaramR Created
//
//----------------------------------------------------------------------------
SCODE STDMETHODCALLTYPE CClientDocStore::GetQuerySession( ICiCQuerySession **ppICiCQuerySession)
{
SCODE sc = S_OK;
TRY
{
CQuerySession *pQuerySession = _pCiNullCat ? new CQuerySession(*_pCiNullCat) :
new CQuerySession(*_pCiCat );
XInterface<CQuerySession> xSession( pQuerySession );
sc = pQuerySession->QueryInterface( IID_ICiCQuerySession, (void **) ppICiCQuerySession );
if ( FAILED(sc) ) {
vqDebugOut(( DEB_ERROR, "GetQuerySession - QI failed 0x%x\n", sc ));
}
}
CATCH( CException,e )
{
sc = e.GetErrorCode();
vqDebugOut(( DEB_ERROR,
"CClientDocStore::GetQuerySession - Exception caught 0x%x\n",
sc ));
}
END_CATCH
return sc;
} //GetQuerySession
//+-------------------------------------------------------------------------
//
// Function: RegisterDLL
//
// Synopsis: Calls DllRegisterServer on the fully qualified path
//
// History: 19-Jun-97
//
//--------------------------------------------------------------------------
DWORD RegisterDLL( WCHAR const * pwcDLL )
{
// All Index Server dlls are currently in system32
DWORD dwErr = NO_ERROR;
HINSTANCE hDll = LoadLibraryEx( pwcDLL,
0,
LOAD_WITH_ALTERED_SEARCH_PATH );
if( 0 != hDll )
{
SCODE (STDAPICALLTYPE *pfnDllRegisterServer)();
pfnDllRegisterServer = (HRESULT (STDAPICALLTYPE *)())
GetProcAddress(hDll, "DllRegisterServer");
if ( 0 != pfnDllRegisterServer )
{
TRY
{
SCODE sc = (*pfnDllRegisterServer)();
if ( S_OK != sc )
{
// no way to map a scode to a win32 error
dwErr = ERROR_INVALID_FUNCTION;
}
}
CATCH( CException, e )
{
Win4Assert( !"DllRegisterServer threw an exception" );
ciDebugOut(( DEB_ERROR, "caught 0x%x registering '%ws'\n",
e.GetErrorCode(), pwcDLL ));
}
END_CATCH;
}
else
dwErr = GetLastError();
FreeLibrary( hDll );
}
else
{
dwErr = GetLastError();
}
return dwErr;
} //RegisterDll
//+-------------------------------------------------------------------------
//
// Function: RegisterKnownDlls
//
// Synopsis: Gets the value of the DLL's from the registry and then
// registers all of them if not done so already.
//
// History: 19-Jun-97 t-elainc Created
//
//--------------------------------------------------------------------------
void RegisterKnownDlls()
{
static fKnownDllsRegistered = FALSE;
if ( fKnownDllsRegistered )
return;
fKnownDllsRegistered = TRUE;
TRY
{
// get registry value
HKEY hkey;
int errorcode = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
wcsRegAdminSubKey,
0,
KEY_QUERY_VALUE |
KEY_ENUMERATE_SUB_KEYS,
&hkey );
if (NO_ERROR == errorcode)
{
SRegKey xKey( hkey );
WCHAR awcPath[4000];
DWORD cwcPath = sizeof awcPath / sizeof WCHAR;
int anothererrorcode = RegQueryValueEx( hkey,
L"DLLsToRegister",
0,
0,
(BYTE *)awcPath,
&cwcPath );
if (NO_ERROR == anothererrorcode)
{
// parse the string
WCHAR* pwcCurrFile = awcPath;
//for each file call RegisterDLL
while ( 0 != *pwcCurrFile )
{
RegisterDLL(pwcCurrFile);
pwcCurrFile += wcslen( pwcCurrFile) + 1;
}
}
}
}
CATCH( CException, ex )
{
ciDebugOut(( DEB_FORCE, "exception %#x registering dlls\n",
ex.GetErrorCode() ));
}
END_CATCH;
} //RegisterKnownDlls
//+-------------------------------------------------------------------------
//
// Function: OpenCatalogsOnRemovableDrives
//
// Synopsis: Opens the catalogs found on the roots of removable drives
// that are not yet opened.
//
// History: 28-Apr-99 dlee Created.
//
//--------------------------------------------------------------------------
void OpenCatalogsOnRemovableDrives()
{
CRegAccess reg( RTL_REGISTRY_CONTROL, wcsRegAdmin );
if ( 0 == reg.Read( wcsMountRemovableCatalogs,
CI_AUTO_MOUNT_CATALOGS_DEFAULT ) )
return;
// Determine which drives exist in this bitmask
DWORD dwDriveMask = GetLogicalDrives();
dwDriveMask >>= 2;
WCHAR awcPath[5];
wcscpy( awcPath, L"c:\\" );
// loop through all the drives c-z
for ( WCHAR wc = L'C'; wc <= L'Z'; wc++ )
{
DWORD dwTemp = ( dwDriveMask & 1 );
dwDriveMask >>= 1;
if ( 0 != dwTemp )
{
if ( IsRemovableDrive( wc ) )
{
awcPath[0] = wc;
if ( 0 == Catalogs.GetDocStore( awcPath ) )
Catalogs.TryToStartCatalogOnRemovableVol( wc, g_pFSCIRequestQueue );
}
}
}
} //OpenCatalogsOnRemovableDrives
//+-------------------------------------------------------------------------
//
// Function: OpenCatalogsInRegistry
//
// Synopsis: Opens the catalogs listed in the registry. If there are
// problems opening a catalog, it is skipped -- no sense
// bringing down the service over a messed-up registry entry.
//
// History: 10-Oct-96 dlee Created.
//
//--------------------------------------------------------------------------
void OpenCatalogsInRegistry( BOOL fOpenForReadOnly = FALSE )
{
//
// Side effect of starting up -- register dlls
//
RegisterKnownDlls();
ciDebugOut(( DEB_ITRACE, "OpenCatalogsInRegistry: fOpenForReadOnly == %d\n",
fOpenForReadOnly ));
HKEY hKey;
if ( ERROR_SUCCESS == RegOpenKeyEx( HKEY_LOCAL_MACHINE,
wcsRegCatalogsSubKey,
0,
KEY_QUERY_VALUE |
KEY_ENUMERATE_SUB_KEYS,
&hKey ) )
{
SRegKey xKey( hKey );
DWORD iSubKey = 0;
do
{
FILETIME ft;
WCHAR awcName[MAX_PATH];
DWORD cwcName = sizeof awcName / sizeof WCHAR;
LONG err = RegEnumKeyEx( hKey,
iSubKey,
awcName,
&cwcName,
0, 0, 0, &ft );
// either error or end of enumeration
if ( ERROR_SUCCESS != err )
break;
iSubKey++;
HKEY hCatName;
if ( ERROR_SUCCESS == RegOpenKeyEx( hKey,
awcName,
0,
KEY_QUERY_VALUE,
&hCatName ) )
{
SRegKey xCatNameKey( hCatName );
WCHAR awcPath[MAX_PATH];
DWORD cbPath = sizeof awcPath;
if ( ERROR_SUCCESS == RegQueryValueEx( hCatName,
wcsCatalogLocation,
0,
0,
(BYTE *)awcPath,
&cbPath ) )
{
Catalogs.GetNamedOne( awcPath, awcName, fOpenForReadOnly );
}
}
} while ( TRUE );
}
OpenCatalogsOnRemovableDrives();
} //OpenCatalogsInRegistry
//+-------------------------------------------------------------------------
//
// Function: OpenOneCatalog
//
// Synopsis: Opens the catalog specified for R/W or R/O.
// set the fNoQuery flag in the docstore if fNoQuery (passed in)
// is TRUE
//
// Arguments: [wcCatName] -- name of the catalog
// [fReadOnly] -- opening for readOnly
// [fNoQuery] -- opening the catalog as NoQuery
//
// History: 27-Apr-98 kitmanh Created.
// 12-May-98 kitmanh Added fNoQuery
//
//--------------------------------------------------------------------------
void OpenOneCatalog( WCHAR const * wcCatName, BOOL fReadOnly, BOOL fNoQuery = FALSE )
{
ciDebugOut(( DEB_ITRACE, "OpenOneCatalog\n" ));
ciDebugOut(( DEB_ITRACE, "fNoQuery is %d\n", fNoQuery ));
HKEY hKey;
WCHAR wcsKey[MAX_PATH];
if ( ( wcslen( wcsRegCatalogsSubKey ) + wcslen( wcCatName ) + 1 ) >= MAX_PATH )
THROW( CException( STATUS_INVALID_PARAMETER ) );
wcscpy( wcsKey, wcsRegCatalogsSubKey );
wcscat( wcsKey, L"\\" );
wcscat( wcsKey, wcCatName );
if ( ERROR_SUCCESS == RegOpenKeyEx( HKEY_LOCAL_MACHINE,
wcsKey,
0,
KEY_QUERY_VALUE,
&hKey ) )
{
SRegKey xKey( hKey );
WCHAR awcPath[MAX_PATH];
DWORD cwcPath = sizeof awcPath / sizeof WCHAR;
if ( ERROR_SUCCESS == RegQueryValueEx( hKey,
wcsCatalogLocation,
0,
0,
(BYTE *)awcPath,
&cwcPath ) )
{
Catalogs.GetNamedOne( awcPath, wcCatName, fReadOnly, fNoQuery );
}
}
} //OpenOneCatalog
// Mutex and Event to synchronize start, stop, pause and continue
CStaticMutexSem g_mtxStartStop;
CEventSem * g_pevtPauseContinue = 0;
//+-------------------------------------------------------------------------
//
// Function: StartCiSvcWork
//
// Synopsis: Entry point for doing the CI service work. The thread does
// not exit until StopCiSvcWork is called.
//
// Argument: [DrvNotifArray] -- reference to the only one
// DriveNotificationArray
//
// History: 16-Sep-96 dlee Created.
// 16-Sep-98 kitmanh Added parameter DrvNotifArray
//
//--------------------------------------------------------------------------
void StartCiSvcWork( CDrvNotifArray & DrvNotifArray )
{
TRY
{
//
// This lock is released when cisvc is initialized enough that
// StopCiSvcWork can safely be called.
//
CReleasableLock lock( g_mtxStartStop );
ciDebugOut(( DEB_ITRACE, "StartCiSvcWork got the lock\n" ));
Catalogs.Init();
TheFrameworkClientWorkQueue.Init();
XCom xcom;
// Create the CRequestQueue here, so it'll stay around for
// the whole time
ULONG cMaxCachedServerItems, cMaxSimultaneousRequests,
cmsDefaultClientTimeout, cMinClientIdleTime, cmsStartupDelay;
BOOL fMinimizeWorkingSet;
{
CRegAccess reg( RTL_REGISTRY_CONTROL, wcsRegAdmin );
cMaxCachedServerItems = reg.Read( wcsMaxCachedPipes,
CI_MAX_CACHED_PIPES_DEFAULT,
CI_MAX_CACHED_PIPES_MIN,
CI_MAX_CACHED_PIPES_MAX );
cMaxSimultaneousRequests = reg.Read( wcsMaxSimultaneousRequests,
CI_MAX_SIMULTANEOUS_REQUESTS_DEFAULT,
CI_MAX_SIMULTANEOUS_REQUESTS_MIN,
CI_MAX_SIMULTANEOUS_REQUESTS_MAX );
cmsDefaultClientTimeout = reg.Read( wcsRequestTimeout,
CI_REQUEST_TIMEOUT_DEFAULT,
CI_REQUEST_TIMEOUT_MIN,
CI_REQUEST_TIMEOUT_MAX );
fMinimizeWorkingSet = reg.Read( wcsMinimizeWorkingSet,
(DWORD)CI_MINIMIZE_WORKINGSET_DEFAULT );
// convert seconds to milliseconds
cMinClientIdleTime = 1000 * reg.Read( wcsMinClientIdleTime,
CI_MIN_CLIENT_IDLE_TIME );
cmsStartupDelay = reg.Read( wcsStartupDelay,
CI_STARTUP_DELAY_DEFAULT,
CI_STARTUP_DELAY_MIN,
CI_STARTUP_DELAY_MAX );
}
Catalogs.SetDrvNotifArray( &DrvNotifArray );
// Create the CRequestQueue here, so it'll stay around for the
// whole time.
CRequestQueue queue( cMaxCachedServerItems,
cMaxSimultaneousRequests,
cmsDefaultClientTimeout,
fMinimizeWorkingSet,
cMinClientIdleTime,
cmsStartupDelay,
guidStorageDocStoreLocatorObject );
g_pFSCIRequestQueue = &queue;
while ( TRUE )
{
// request lock to prevent problems of sequence of
// net pause, net stop and net start (in any order
// and combo.)
if ( !lock.IsHeld() )
lock.Request();
ciDebugOut(( DEB_ITRACE, "About to call StartFWCiSvcWork\n" ));
StartFWCiSvcWork( lock, &queue, *g_pevtPauseContinue);
ciDebugOut(( DEB_ITRACE, "StartCiSvcWork:: fell out from StartFWCiSvcWork\n" ));
// In the case where a net pause happened
// instead of checking IsNetPause and IsNetcontinue, loop thru the
// dynarray to reopen docstores. and clear the SCarry when done
// note if array.count == 0, work as normal.
SCWorkItem * WorkItem;
WCHAR wcCatName[MAX_PATH];
if ( !queue.IsShutdown() )
{
// something is on the _stateChangeArray to be handled
for ( unsigned i = 0; i < queue.SCArrayCount(); i++ )
{
WorkItem = queue.GetSCItem(i);
if ( WorkItem->StoppedCat ) {
wcsncpy( wcCatName, WorkItem->StoppedCat, sizeof wcCatName / sizeof WCHAR );
wcCatName[ (sizeof wcCatName / sizeof WCHAR) - 1 ] = 0;
}
else if ( eNoCatWork != WorkItem->type ) {
wcsncpy( wcCatName, ( (CClientDocStore *)(WorkItem->pDocStore) )->GetName(), sizeof wcCatName / sizeof WCHAR );
wcCatName[ (sizeof wcCatName / sizeof WCHAR) - 1 ] = 0;
}
switch ( WorkItem->type )
{
case eCatRO:
//flush cat
if ( !WorkItem->StoppedCat )
Catalogs.FlushOne( WorkItem->pDocStore );
else
Catalogs.RmFromStopArray( wcCatName );
OpenOneCatalog( wcCatName, TRUE );
break;
case eCatW:
if ( !WorkItem->StoppedCat )
Catalogs.FlushOne( WorkItem->pDocStore );
else
Catalogs.RmFromStopArray( wcCatName );
OpenOneCatalog( wcCatName, FALSE );
break;
case eStopCat:
if ( !WorkItem->StoppedCat )
{
Catalogs.FlushOne( WorkItem->pDocStore );
ciDebugOut(( DEB_ITRACE, "Catalogs.IsCatStopped( %ws ) == %d\n",
wcCatName, Catalogs.IsCatStopped( wcCatName ) ));
}
break;
case eNoQuery:
if ( !WorkItem->StoppedCat )
Catalogs.FlushOne( WorkItem->pDocStore );
else
Catalogs.RmFromStopArray( wcCatName );
OpenOneCatalog( wcCatName, !(WorkItem->fNoQueryRW), TRUE );
break;
case eNetPause:
case eNetContinue:
case eNetStop:
case eNoCatWork:
// These cases are handled later
break;
default:
Win4Assert( !"The eCisvcActionType specified is unknown" );
}
}
}
if ( queue.IsNetPause() )
{
Win4Assert( !queue.IsNetContinue() );
Catalogs.ClearStopArray();
// reset the queue
queue.ReStart();
//closecatalog
Catalogs.Flush();
OpenCatalogsInRegistry( TRUE ); //reopen catalogs for r/o
//Win4Assert( !"Done Pausing" );
}
// a net continue happened
else if ( queue.IsNetContinue() )
{
Win4Assert( !queue.IsNetPause() );
Catalogs.ClearStopArray();
// reset the queue
queue.ReStart();
ciDebugOut(( DEB_ITRACE, "YES, net continued*********\n" ));
ciDebugOut(( DEB_ITRACE, "About to flush catalogs.\n" ));
//closecatalog
Catalogs.Flush();
ciDebugOut(( DEB_ITRACE, "About to OpenCatalogsInRegistry for r/w \n" ));
OpenCatalogsInRegistry( FALSE ); //reopen catalogs for r/w
ciDebugOut(( DEB_ITRACE, "Done opening catalogs in registry\n" ));
//Win4Assert( !"Done Continuing" );
}
else
{
if ( !( queue.IsShutdown() || queue.IsNetStop() ) )
queue.ReStart();
else
{
ciDebugOut(( DEB_ITRACE, "StartCisvcWork: Breaking out of the loop and ready to shutdown the service\n" ));
Catalogs.ClearStopArray();
break;
}
}
}
}
CATCH( CException, ex )
{
ciDebugOut(( DEB_WARN, "StartCiSvcWork2 exception error 0x%x\n",
ex.GetErrorCode() ));
}
END_CATCH;
} //StartCiSvcWork
//+-------------------------------------------------------------------------
//
// Function: StopCiSvcWork
//
// Synopsis: Entry point for stopping the CI service work.
//
// Arguments: [type] -- type of work to do
// [wcVol] -- volume letter (for eLockVol only)
//
// History: 16-Sep-96 dlee Created.
// 12-Aug-98 kitmanh Returned an SCODE
//
//--------------------------------------------------------------------------
SCODE StopCiSvcWork( ECiSvcActionType type, WCHAR wcVol )
{
ciDebugOut(( DEB_ITRACE, "StopCiSvcWork is trying to get the lock\n" ));
CReleasableLock lock( g_mtxStartStop );
ciDebugOut(( DEB_ITRACE, "StopCiSvcWork got the lock\n" ));
// If the main SCM thread didn't get very far, this will be the case.
if ( 0 == g_pevtPauseContinue )
return S_OK;
g_pevtPauseContinue->Reset();
SCODE sc = StopFWCiSvcWork( type, &lock, g_pevtPauseContinue, wcVol );
lock.Release();
ciDebugOut(( DEB_ITRACE, "StopCiSvcWork.. After StopFwCiSvcWork has returned. type == %d\n", type ));
// Do not block if shutdown has intialized
if ( STATUS_TOO_LATE == sc )
return S_OK;
// block if pausing or continuing
if ( eNetStop != type )
{
ciDebugOut(( DEB_ITRACE, "StopCiSvcWork.. After StopFwCiSvcWork has returned. Block on g_pevtPauseContinue\n" ));
g_pevtPauseContinue->Wait();
lock.Request();
g_pevtPauseContinue->Reset();
lock.Release();
ciDebugOut(( DEB_ITRACE, "StopCiSvcWork.. After StopFwCiSvcWork has returned. Reusme on g_pevtPauseContinue\n" ));
}
return sc;
} //StopCiSvcWork
//+---------------------------------------------------------------------------
//
// Member: CClientDocStore::InternalWorkIdToDocName
//
// Synopsis: Translates a WorkId to a document name.
//
// Arguments: [workid] - [in] WorkId to translate
// [pICiCDocName] - [out] Will be filled in with the document
// name on output.
// [fAccurate] - Use the slow and accurate call
//
// Returns: S_OK if successfully converted.
// CI_E_BUFFERTOOSMALL if the buffer is not big enough
// Other error code.
//
// History: 31-Dec-1998 KyleP Created
//
//----------------------------------------------------------------------------
SCODE CClientDocStore::InternalWorkIdToDocName( WORKID workid,
ICiCDocName * pICiCDocName,
BOOL fAccurate )
{
Win4Assert( 0 != pICiCDocName );
Win4Assert(_pCiCat);
CCiCDocName * pDocName = (CCiCDocName *) pICiCDocName;
CLowerFunnyPath funnyPath;
SCODE sc = S_OK;
TRY
{
//
// We should avoid a memory copy here. Copy into the CCiCDocName
// directly. If this turns out to be a performance problem fix
// it. It isn't now.
//
unsigned cwc;
if ( fAccurate )
cwc = _pCiCat->WorkIdToAccuratePath( workid, funnyPath );
else
cwc = _pCiCat->WorkIdToPath( workid, funnyPath );
//
// CiCat::WorkIdToPath makes an EMPTY string when a doc
// is deleted.
//
if ( cwc > 1 )
{
// this is not a deleted file.
pDocName->SetPath( funnyPath.GetActualPath(), cwc );
}
else
{
// this is a deleted file.
sc = CI_S_WORKID_DELETED;
}
}
CATCH( CException, e )
{
sc = e.GetErrorCode();
}
END_CATCH
return sc;
}
//+---------------------------------------------------------------------------
//
// Member: CClientDocStore::ClearNonStoragePropertiesForWid
//
// Synopsis: Clear non-storage properties from the property storage for wid
//
// Arguments: [wid] - workid
//
// Returns: S_OK if successful;
//
// History: 10-06-2000 kitmanh Created
//
//----------------------------------------------------------------------------
STDMETHODIMP CClientDocStore::ClearNonStoragePropertiesForWid( WORKID wid )
{
SCODE sc = S_OK;
TRY
{
_pCiCat->ClearNonStoragePropertiesForWid( wid );
}
CATCH( CException, e )
{
sc = e.GetErrorCode();
}
END_CATCH
return sc;
}