//+--------------------------------------------------------------------------- // // 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 #pragma hdrstop // for definition of CRequestQueue #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include 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 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 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 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 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 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 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 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 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; }