/****************************************************************************** Copyright (c) 2001 Microsoft Corporation Module Name: FTSWrap.cpp Abstract: Implementation of SearchEngine::WrapperFTS Revision History: Ghim-Sim Chua (gschua) 06/01/2000 created ******************************************************************************/ #include "stdafx.h" #include "msitstg.h" #include "itrs.h" #include "itdb.h" #include "iterror.h" #include "itgroup.h" #include "itpropl.h" #include "itquery.h" #include "itcc.h" #include "ftsobj.h" #include "fs.h" //////////////////////////////////////////////////////////////////////////////// static bool local_ExpandURL( /*[in ]*/ Taxonomy::Updater& updater , /*[in ]*/ const MPC::wstring& strSrc , /*[in ]*/ LPCWSTR szPrefix , /*[out]*/ MPC::wstring& strDst ) { strDst = szPrefix; strDst += strSrc; if(SUCCEEDED(updater.ExpandURL( strDst ))) { if(MPC::FileSystemObject::IsFile( strDst.c_str() )) return true; } return false; } static void local_GenerateFullURL( /*[in ]*/ Taxonomy::Updater& updater , /*[in ]*/ const MPC::wstring& strSrc , /*[out]*/ MPC::wstring& strDst ) { if(strSrc.size()) { if(local_ExpandURL( updater, strSrc, L"%HELP_LOCATION%\\", strDst )) return; if(local_ExpandURL( updater, strSrc, L"%WINDIR%\\Help\\" , strDst )) return; } strDst = L""; } //////////////////////////////////////////////////////////////////////////////// SearchEngine::WrapperFTS::WrapperFTS() { // SEARCH_OBJECT_LIST m_objects; // SEARCH_RESULT_SET m_results; // SEARCH_RESULT_SORTSET m_resultsSorted; MPC::LocalizeString( IDS_HELPSVC_SEMGR_OWNER , m_bstrOwner , /*fMUI*/true ); MPC::LocalizeString( IDS_HELPSVC_SEMGR_FTS_NAME, m_bstrName , /*fMUI*/true ); MPC::LocalizeString( IDS_HELPSVC_SEMGR_FTS_DESC, m_bstrDescription, /*fMUI*/true ); m_bstrHelpURL = L"hcp://system/blurbs/ftshelp.htm"; m_bstrID = L"9A22481C-1795-46f3-8CCA-7D78E9E54112"; } SearchEngine::WrapperFTS::~WrapperFTS() { Thread_Wait(); ReleaseAll(); } HRESULT SearchEngine::WrapperFTS::GetParamDefinition( /*[out]*/ const ParamItem_Definition*& lst, /*[out]*/ int& len ) { static const ParamItem_Definition c_lst[] = { { PARAM_BOOL, VARIANT_FALSE, VARIANT_TRUE , L"TITLEONLY", IDS_HELPSVC_TITLE_ONLY, NULL, L"false" }, { PARAM_BOOL, VARIANT_FALSE, VARIANT_TRUE , L"STEMMING" , IDS_HELPSVC_STEMMING , NULL, L"false" }, { PARAM_BOOL, VARIANT_FALSE, VARIANT_FALSE, L"UI_BULLET", 0 , NULL, L"false" }, }; lst = c_lst; len = ARRAYSIZE(c_lst); return S_OK; } //////////////////////////////////////////////////////////////////////////////// void SearchEngine::WrapperFTS::ReleaseAll() { ReleaseSearchResults(); m_objects.clear(); } void SearchEngine::WrapperFTS::ReleaseSearchResults() { m_results .clear(); m_resultsSorted.clear(); } //////////////////////////////////////////////////////////////////////////////// HRESULT SearchEngine::WrapperFTS::ExecQuery() { __HCP_FUNC_ENTRY( "SearchEngine::WrapperFTS::ExecQuery" ); HRESULT hr; long lCount; long lIndex = 0; MPC::WStringSet wordsSet; MPC::WStringList wordsList; if(m_bEnabled) { CComBSTR bstrName; VARIANT* v; bool bTitle; bool bStemming; __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::LocalizeString( IDS_HELPSVC_SEMGR_FTS_NAME, bstrName, /*fMUI*/true )); if(m_bstrQueryString.Length() == 0) { __MPC_SET_WIN32_ERROR_AND_EXIT(hr, ERROR_INVALID_DATA); } __MPC_EXIT_IF_METHOD_FAILS(hr, Initialize()); // // Check if search in titles only // v = GetParamInternal( L"TITLEONLY" ); bTitle = (v && v->vt == VT_BOOL && v->boolVal) ? true : false; // // Check if stemming is turned on // v = GetParamInternal( L"STEMMING" ); bStemming = (v && v->vt == VT_BOOL && v->boolVal) ? true : false; // // Compute the code page each query, as the user may have changed the language using MUI between queries // UINT cp = CP_ACP; WCHAR wchLocale[10]; if (GetLocaleInfo(m_ths.GetLanguage(), LOCALE_IDEFAULTANSICODEPAGE, wchLocale, ARRAYSIZE(wchLocale))) cp = wcstoul(wchLocale, NULL, 10); else cp = CP_ACP; // // Execute the queries // for(SEARCH_OBJECT_LIST_ITER it = m_objects.begin(); (it != m_objects.end()) && (!Thread_IsAborted()); it++) { (void)it->Query( m_bstrQueryString, bTitle, bStemming, m_results, wordsSet, cp ); } if(Thread_IsAborted()) __MPC_SET_ERROR_AND_EXIT(hr, E_ABORT); for(SEARCH_RESULT_SET_ITER it2 = m_results.begin(); (it2 != m_results.end()) && (!Thread_IsAborted()); it2++) { m_resultsSorted.insert( &(*it2) ); } if(Thread_IsAborted()) __MPC_SET_ERROR_AND_EXIT(hr, E_ABORT); // // Copy the Highlight words from set to list // for(MPC::WStringSetIter itString = wordsSet.begin(); (itString != wordsSet.end()) && (!Thread_IsAborted()); itString++) { wordsList.push_back( *itString ); } if(Thread_IsAborted()) __MPC_SET_ERROR_AND_EXIT(hr, E_ABORT); // // Store Highlight words in safe array // __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::ConvertListToSafeArray( wordsList, m_vKeywords, VT_VARIANT )); } hr = S_OK; __MPC_FUNC_CLEANUP; Thread_Abort(); // // Call the SearchManager's OnComplete // (void)m_pSEMgr->WrapperComplete( hr, this ); __MPC_FUNC_EXIT(hr); } STDMETHODIMP SearchEngine::WrapperFTS::get_SearchTerms( /*[out, retval]*/ VARIANT *pVal ) { MPC::SmartLock<_ThreadModel> lock( this ); return ::VariantCopy( pVal, &m_vKeywords ); } HRESULT SearchEngine::WrapperFTS::Initialize() { __HCP_FUNC_ENTRY( "SearchEngine::WrapperFTS::Initialize" ); HRESULT hr; MPC::SmartLock<_ThreadModel> lock( this ); Taxonomy::Settings ts( m_ths ); JetBlue::SessionHandle handle; JetBlue::Database* db; Taxonomy::Updater updater; Taxonomy::RS_FullTextSearch* rsFTS; Taxonomy::RS_Scope* rsSCOPE; long ID_scope = -1; bool fFound; // // Clean previous search results. // //ReleaseSearchResults(); ReleaseAll(); __MPC_EXIT_IF_METHOD_FAILS(hr, ts .GetDatabase ( handle, db, /*fReadOnly*/true )); __MPC_EXIT_IF_METHOD_FAILS(hr, updater.Init ( ts , db )); __MPC_EXIT_IF_METHOD_FAILS(hr, updater.GetFullTextSearch( &rsFTS )); __MPC_EXIT_IF_METHOD_FAILS(hr, updater.GetScope ( &rsSCOPE )); //////////////////////////////////////// if(m_bstrScope) { __MPC_EXIT_IF_METHOD_FAILS(hr, rsSCOPE->Seek_ByID( m_bstrScope, &fFound )); if(fFound) { ID_scope = rsSCOPE->m_ID_scope; } } if(ID_scope == -1) { __MPC_EXIT_IF_METHOD_FAILS(hr, rsSCOPE->Seek_ByID( L"", &fFound )); if(fFound) { ID_scope = rsSCOPE->m_ID_scope; } } //////////////////////////////////////// // // Create the search objects. // __MPC_EXIT_IF_METHOD_FAILS(hr, rsFTS->Move( 0, JET_MoveFirst, &fFound )); while(fFound) { if(rsFTS->m_ID_scope == ID_scope) { CFTSObject& obj = *(m_objects.insert( m_objects.end() )); CFTSObject::Config& cfg = obj.GetConfig(); local_GenerateFullURL( updater, rsFTS->m_strCHM, cfg.m_strCHMFilename ); local_GenerateFullURL( updater, rsFTS->m_strCHQ, cfg.m_strCHQFilename ); if(cfg.m_strCHQFilename.size()) { cfg.m_fCombined = true; } } __MPC_EXIT_IF_METHOD_FAILS(hr, rsFTS->Move( 0, JET_MoveNext, &fFound )); } hr = S_OK; __MPC_FUNC_CLEANUP; __MPC_FUNC_EXIT(hr); } //////////////////////////////////////////////////////////////////////////////// STDMETHODIMP SearchEngine::WrapperFTS::Result( /*[in]*/ long lStart, /*[in]*/ long lEnd, /*[out,retval]*/ IPCHCollection* *ppC ) { __HCP_FUNC_ENTRY( "SearchEngine::WrapperFTS::Result" ); HRESULT hr; MPC::SmartLock<_ThreadModel> lock( this ); CComPtr pColl; __MPC_PARAMCHECK_BEGIN(hr) __MPC_PARAMCHECK_POINTER_AND_SET(ppC,NULL); __MPC_PARAMCHECK_END(); // // Create the Enumerator and fill it with jobs. // __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &pColl )); if(m_bEnabled) { long lCount = 0; for(SEARCH_RESULT_SORTSET_ITER it = m_resultsSorted.begin(); (lCount < m_lNumResult) && (it != m_resultsSorted.end()); it++, lCount++) { // // if there is a URL // if(lCount >= lStart && lCount < lEnd ) { CComPtr pRIObj; // // Create the item to be inserted into the list // __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &pRIObj )); { ResultItem_Data& data = pRIObj->Data(); SEARCH_RESULT* res = *it; data.m_bstrTitle = res->bstrTopicName; data.m_bstrLocation = res->bstrLocation; data.m_bstrURI = res->bstrTopicURL; } // // Add to enumerator // __MPC_EXIT_IF_METHOD_FAILS(hr, pColl->AddItem( pRIObj )); } } } __MPC_EXIT_IF_METHOD_FAILS(hr, pColl.QueryInterface( ppC )); hr = S_OK; __MPC_FUNC_CLEANUP; __MPC_FUNC_EXIT(hr); } //////////////////////////////////////////////////////////////////////////////// STDMETHODIMP SearchEngine::WrapperFTS::AbortQuery() { // // Abort any threads still running // Thread_Abort(); return S_OK; } STDMETHODIMP SearchEngine::WrapperFTS::ExecAsyncQuery() { __HCP_FUNC_ENTRY( "SearchEngine::WrapperFTS::ExecAsyncQuery" ); HRESULT hr; // // Create a thread to execute the query // __MPC_EXIT_IF_METHOD_FAILS(hr, Thread_Start( this, ExecQuery, NULL )); hr = S_OK; __MPC_FUNC_CLEANUP; __MPC_FUNC_EXIT(hr); } //////////////////////////////////////////////////////////////////////////////// HRESULT SearchEngine::WrapperItem__Create_FullTextSearch( /*[out]*/ CComPtr& pVal ) { __HCP_FUNC_ENTRY( "CPCHSEWrapperItem__Create_FullTextSearch" ); HRESULT hr; CComPtr pFTS; __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &pFTS )); pVal = pFTS; hr = S_OK; __HCP_FUNC_CLEANUP; __HCP_FUNC_EXIT(hr); }