Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

506 lines
16 KiB

  1. /********************************************************************
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. NetSW.cpp
  5. Abstract:
  6. Implements the class SearchEngine::WrapperNetSearch that contains methods for executing
  7. the search query and returning the results back to the UI. Also
  8. contains methods for dynamic update of parameter list and dynamic
  9. generation of parameters.
  10. Revision History:
  11. a-prakac created 10/24/2000
  12. ********************************************************************/
  13. #include "stdafx.h"
  14. #include <Utility.h>
  15. /////////////////////////////////////////////////////////////////////////////
  16. // SearchEngine::WrapperNetSearch : IPCHSEWrapperItem
  17. SearchEngine::WrapperNetSearch::WrapperNetSearch()
  18. {
  19. // CParamList m_ParamList;
  20. // CSearchResultList m_resConfig;
  21. // MPC::XmlUtil m_xmlQuery;
  22. // CComBSTR m_bstrLCID;
  23. // CComBSTR m_bstrSKU;
  24. m_bOfflineError = false; // bool m_bOfflineError;
  25. // CComBSTR m_bstrPrevQuery;
  26. }
  27. SearchEngine::WrapperNetSearch::~WrapperNetSearch()
  28. {
  29. AbortQuery();
  30. Thread_Wait();
  31. }
  32. /************
  33. Method - SearchEngine::WrapperNetSearch::Result( long lStart, long lEnd, IPCHCollection** ppC )
  34. Description - This method returns items from lStart to lEnd. If there are else then (lEnd - lStart)
  35. items then only those many are returned. If an error had occured during results retrieval then the
  36. error info is returned as a result item (CONTENTTYPE_ERROR).
  37. ************/
  38. STDMETHODIMP SearchEngine::WrapperNetSearch::Result( /*[in]*/ long lStart, /*[in]*/ long lEnd, /*[out, retval]*/ IPCHCollection** ppC )
  39. {
  40. __HCP_FUNC_ENTRY( "SearchEngine::WrapperNetSearch::Result" );
  41. HRESULT hr;
  42. MPC::SmartLock<_ThreadModel> lock( this );
  43. CComPtr<CPCHCollection> pColl;
  44. __MPC_PARAMCHECK_BEGIN(hr)
  45. __MPC_PARAMCHECK_POINTER_AND_SET(ppC, NULL);
  46. __MPC_PARAMCHECK_END();
  47. //
  48. // Create the collection object and fill it with result items
  49. //
  50. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &pColl ));
  51. if(m_bEnabled)
  52. {
  53. long lIndex = lStart;
  54. // Check for retrieval errors
  55. if(m_bOfflineError)
  56. {
  57. CComPtr<SearchEngine::ResultItem> pRIObj;
  58. //
  59. // Create the result item, initialize it, and add it to the collection
  60. //
  61. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &pRIObj ));
  62. {
  63. ResultItem_Data& data = pRIObj->Data();
  64. data.m_lContentType = CONTENTTYPE_ERROR_OFFLINE;
  65. }
  66. __MPC_EXIT_IF_METHOD_FAILS(hr, pColl->AddItem( pRIObj ));
  67. }
  68. else
  69. {
  70. //
  71. // Return only m_lNumResult number of results
  72. //
  73. if(lEnd > m_lNumResult) lEnd = m_lNumResult;
  74. //
  75. // The results have already been loaded in m_resConfig - populate the pRIObj using this.
  76. // SetResultItemIterator returns E_FAIL if lIndex is out of range
  77. //
  78. __MPC_EXIT_IF_METHOD_FAILS(hr, m_resConfig.SetResultItemIterator( lIndex ));
  79. while((lIndex++ < lEnd) && (m_resConfig.IsCursorValid()))
  80. {
  81. CComPtr<SearchEngine::ResultItem> pRIObj;
  82. //
  83. // Create the result item, initialize it, and add it to the collection
  84. //
  85. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &pRIObj ));
  86. __MPC_EXIT_IF_METHOD_FAILS(hr, m_resConfig.InitializeResultObject( pRIObj ));
  87. __MPC_EXIT_IF_METHOD_FAILS(hr, pColl->AddItem( pRIObj ));
  88. m_resConfig.MoveNext();
  89. }
  90. }
  91. }
  92. __MPC_EXIT_IF_METHOD_FAILS(hr, pColl.QueryInterface( ppC ));
  93. hr = S_OK;
  94. __HCP_FUNC_CLEANUP;
  95. __HCP_FUNC_EXIT(hr);
  96. }
  97. /////////////////////////////////////////////////////////////////////////////
  98. // SearchEngine::WrapperNetSearch : IPCHSEWrapperInternal
  99. STDMETHODIMP SearchEngine::WrapperNetSearch::AbortQuery()
  100. {
  101. m_xmlQuery .Abort();
  102. m_objRemoteConfig.Abort();
  103. Thread_Abort();
  104. return S_OK;
  105. }
  106. /************
  107. Method - SearchEngine::WrapperNetSearch::ExecQuery()
  108. Description - This method calls the search engine (webservice) URL to execute the user typed query and
  109. retrieve the results. The parameters required for the query for read from the parameter list file - except
  110. for the "QueryString" parameter which is hardcoded. The retrieved results are loaded using CSearchResultList
  111. and checked for errors.
  112. ************/
  113. HRESULT SearchEngine::WrapperNetSearch::ExecQuery()
  114. {
  115. __HCP_FUNC_ENTRY( "SearchEngine::WrapperNetSearch::ExecQuery" );
  116. HRESULT hr;
  117. MPC::SmartLock<_ThreadModel> lock( this );
  118. MPC::wstring wszQuery;
  119. MPC::URL urlQuery;
  120. CComBSTR bstrParam;
  121. bool fLoaded;
  122. bool fFound;
  123. WCHAR wszNumResult[20];
  124. try
  125. {
  126. if(m_bEnabled)
  127. {
  128. m_bOfflineError = false;
  129. //
  130. // Check to see if the network is alive
  131. //
  132. {
  133. VARIANT_BOOL vtNetwork;
  134. if(FAILED(m_pSEMgr->IsNetworkAlive( &vtNetwork )) || vtNetwork == VARIANT_FALSE)
  135. {
  136. // If the user is not online then set the error and exit
  137. m_bOfflineError = true;
  138. __MPC_SET_ERROR_AND_EXIT(hr, S_OK);
  139. }
  140. if(Thread_IsAborted()) __MPC_SET_ERROR_AND_EXIT(hr, E_ABORT);
  141. }
  142. //
  143. // If Remote Configuration (dynamic update of parameters) is required then create another thread
  144. // to fetch the updated list of parameters
  145. //
  146. if(m_ParamList.RemoteConfig())
  147. {
  148. CComBSTR bstrRemoteServerUrl;
  149. CComBSTR bstrConfigFilePath;
  150. long lUpdateFrequency;
  151. //
  152. // Get the remote server url, config file path and get the updated config file
  153. //
  154. m_ParamList.get_RemoteServerUrl( bstrRemoteServerUrl );
  155. m_ParamList.get_ConfigFilePath ( bstrConfigFilePath );
  156. m_ParamList.get_UpdateFrequency( lUpdateFrequency );
  157. if(Thread_IsAborted()) __MPC_SET_ERROR_AND_EXIT(hr, E_ABORT);
  158. __MPC_EXIT_IF_METHOD_FAILS(hr, m_objRemoteConfig.RetrieveList( bstrRemoteServerUrl, m_bstrLCID, m_bstrSKU, bstrConfigFilePath, lUpdateFrequency ) );
  159. }
  160. //
  161. // Clear the contents of the results of the old query before proceeding
  162. //
  163. m_resConfig.ClearResults();
  164. //
  165. // Get the parameters to form the query string - note that MPC::URL checks to see if the URL is in right format
  166. //
  167. {
  168. CComBSTR bstrQuery;
  169. __MPC_EXIT_IF_METHOD_FAILS(hr, m_ParamList.get_ServerUrl( bstrQuery ));
  170. __MPC_EXIT_IF_METHOD_FAILS(hr, urlQuery.put_URL ( bstrQuery ));
  171. }
  172. //
  173. // Read the configuration XML file to get the parameter names
  174. //
  175. // Add the other 'hardcoded' parameters
  176. _ltow(m_lNumResult, wszNumResult, 10);
  177. // If not a standard search then add the PrevQuery parameter
  178. if(!m_ParamList.IsStandardSearch())
  179. {
  180. // If this is a search within results then change the value of QueryString and retain PrevQuery value
  181. CComVariant vValue;
  182. if((SUCCEEDED(GetParam( NSW_PARAM_SUBQUERY, &vValue ))) && (vValue.vt == VT_BOOL) && (vValue.boolVal == VARIANT_TRUE))
  183. {
  184. if((SUCCEEDED(GetParam( NSW_PARAM_CURRENTQUERY, &vValue ))) && (vValue.vt == VT_BSTR))
  185. {
  186. m_bstrQueryString = SAFEBSTR(vValue.bstrVal);
  187. }
  188. }
  189. else
  190. {
  191. // If not a subquery then discard the contents of the old PrevQuery
  192. m_bstrPrevQuery.Empty();
  193. }
  194. __MPC_EXIT_IF_METHOD_FAILS(hr, urlQuery.AppendQueryParameter( NSW_PARAM_PREVQUERY, SAFEBSTR(m_bstrPrevQuery) ));
  195. }
  196. __MPC_EXIT_IF_METHOD_FAILS(hr, urlQuery.AppendQueryParameter( NSW_PARAM_QUERYSTRING, m_bstrQueryString ));
  197. __MPC_EXIT_IF_METHOD_FAILS(hr, urlQuery.AppendQueryParameter( NSW_PARAM_LCID , m_bstrLCID ));
  198. __MPC_EXIT_IF_METHOD_FAILS(hr, urlQuery.AppendQueryParameter( NSW_PARAM_SKU , m_bstrSKU ));
  199. __MPC_EXIT_IF_METHOD_FAILS(hr, urlQuery.AppendQueryParameter( NSW_PARAM_MAXRESULTS , wszNumResult ));
  200. m_ParamList.MoveFirst();
  201. while(m_ParamList.IsCursorValid())
  202. {
  203. __MPC_EXIT_IF_METHOD_FAILS(hr, m_ParamList.get_Name( bstrParam ));
  204. __MPC_EXIT_IF_METHOD_FAILS(hr, AppendParameter( bstrParam, urlQuery ));
  205. m_ParamList.MoveNext();
  206. }
  207. __MPC_EXIT_IF_METHOD_FAILS(hr, urlQuery.get_URL( wszQuery ));
  208. __MPC_EXIT_IF_METHOD_FAILS(hr, m_xmlQuery.SetTimeout( NSW_TIMEOUT_QUERY ));
  209. if(Thread_IsAborted()) __MPC_SET_ERROR_AND_EXIT(hr, E_ABORT);
  210. __MPC_EXIT_IF_METHOD_FAILS(hr, m_xmlQuery.Load( wszQuery.c_str(), NULL, fLoaded, &fFound ));
  211. if(fLoaded)
  212. {
  213. CComPtr<IXMLDOMNode> xdn;
  214. CComBSTR bstrName;
  215. // Check to see if the root node is "ResultList" or "string"
  216. __MPC_EXIT_IF_METHOD_FAILS(hr, m_xmlQuery.GetRoot( &xdn ));
  217. __MPC_EXIT_IF_METHOD_FAILS(hr, xdn->get_nodeName ( &bstrName ));
  218. // If it is a webservice, then the root node returned is "string". In this case, get the value of
  219. // this node
  220. if(MPC::StrCmp( bstrName, NSW_TAG_STRING ) == 0)
  221. {
  222. CComVariant vVar;
  223. __MPC_EXIT_IF_METHOD_FAILS(hr, m_xmlQuery.GetValue( NULL, vVar, fFound, NULL ));
  224. __MPC_EXIT_IF_METHOD_FAILS(hr, m_xmlQuery.LoadAsString( vVar.bstrVal, NSW_TAG_RESULTLIST, fLoaded, &fFound ));
  225. if(!fLoaded)
  226. {
  227. __MPC_SET_ERROR_AND_EXIT(hr, S_OK);
  228. }
  229. }
  230. // If not the results were retrieved succesfully - load it
  231. {
  232. CComPtr<IStream> stream;
  233. __MPC_EXIT_IF_METHOD_FAILS(hr, m_xmlQuery.SaveAsStream( (IUnknown**)&stream ));
  234. __MPC_EXIT_IF_METHOD_FAILS(hr, m_resConfig.LoadResults( stream ));
  235. m_bstrPrevQuery = m_resConfig.PrevQuery();
  236. }
  237. }
  238. }
  239. }
  240. catch(...)
  241. {
  242. __MPC_SET_ERROR_AND_EXIT(hr, E_FAIL);
  243. }
  244. hr = S_OK;
  245. __HCP_FUNC_CLEANUP;
  246. hr = m_pSEMgr->WrapperComplete( hr, this );
  247. Thread_Abort();
  248. __HCP_FUNC_EXIT(hr);
  249. }
  250. /************
  251. Method - SearchEngine::WrapperNetSearch::AppendQueryParameter(CComBSTR bstrParam, MPC::URL& urlQueryString )
  252. Description - Small routine that gets the parameter value for the parameter passed in (NULL if it
  253. could not be retrieved) and then calls the MPC::URL's AppendQueryParameter to append the parameter
  254. and its value to the URL.
  255. ************/
  256. HRESULT SearchEngine::WrapperNetSearch::AppendParameter (/*[in]*/ BSTR bstrParam, /*[in, out]*/ MPC::URL& urlQueryString )
  257. {
  258. __HCP_FUNC_ENTRY( "SearchEngine::WrapperNetSearch::AppendParameter " );
  259. HRESULT hr;
  260. CComVariant vValue;
  261. MPC::wstring wszParamValue;
  262. // GetParam fetches the value if the user has changed it - else get the default value
  263. if(SUCCEEDED(GetParam( bstrParam, &vValue )))
  264. {
  265. __MPC_EXIT_IF_METHOD_FAILS(hr, ::VariantChangeType( &vValue, &vValue, VARIANT_ALPHABOOL, VT_BSTR ));
  266. wszParamValue = SAFEBSTR( vValue.bstrVal );
  267. }
  268. else
  269. {
  270. __MPC_EXIT_IF_METHOD_FAILS(hr, m_ParamList.GetDefaultValue( bstrParam, wszParamValue ));
  271. }
  272. __MPC_EXIT_IF_METHOD_FAILS(hr, urlQueryString.AppendQueryParameter( bstrParam, wszParamValue.c_str() ));
  273. hr = S_OK;
  274. __HCP_FUNC_CLEANUP;
  275. __HCP_FUNC_EXIT(hr);
  276. }
  277. /************
  278. Method - SearchEngine::WrapperNetSearch::ExecAsyncQuery()
  279. Description - This method is called by the Search Engine Manager to execute the query. Here a seperate thread
  280. is spun off to execute the query and retrieve the results. After this, it checks to if the remote configuration
  281. is enabled (dynamic update of parameter list) and if it then another thread is spun off to retrieve the updated list.
  282. ************/
  283. STDMETHODIMP SearchEngine::WrapperNetSearch::ExecAsyncQuery()
  284. {
  285. __HCP_FUNC_ENTRY( "SearchEngine::WrapperNetSearch::ExecAsyncQuery" );
  286. HRESULT hr;
  287. //
  288. // Create a thread to execute the query and fetch the results
  289. //
  290. __MPC_EXIT_IF_METHOD_FAILS(hr, Thread_Start( this, ExecQuery, NULL ) );
  291. hr = S_OK;
  292. __HCP_FUNC_CLEANUP;
  293. __HCP_FUNC_EXIT(hr);
  294. }
  295. /************
  296. Method - SearchEngine::WrapperNetSearch::Initialize( BSTR bstrID, BSTR bstrSKU, long lLCID, BSTR bstrData )
  297. Description - This method is called by the Search Engine Manager to initialize the wrapper. ID is the id of
  298. this instance of the NetSearch Wrapper, SKU is ignored, and bstrData is data provided during the registration
  299. process. Data is an XML file that should contain the location of the config file path, the name and description
  300. of the Search Engine, the owner and finally the LCID. This method loads this data and also loads the config file.
  301. ************/
  302. STDMETHODIMP SearchEngine::WrapperNetSearch::Initialize( /*[in]*/ BSTR bstrID, /*[in]*/ BSTR bstrSKU, /*[in]*/ long lLCID, /*[in]*/ BSTR bstrData )
  303. {
  304. __HCP_FUNC_ENTRY( "SearchEngine::WrapperNetSearch::Initialize" );
  305. HRESULT hr;
  306. WCHAR wstrLCID[20];
  307. CComBSTR bstrConfigFilePath;
  308. // Initialize the ID, LCID, and SKU member variables
  309. m_bstrID = bstrID;
  310. _ltow(lLCID, wstrLCID, 10);
  311. m_bstrLCID = wstrLCID;
  312. m_bstrSKU = bstrSKU;
  313. // Load the rest of the configuration data
  314. __MPC_EXIT_IF_METHOD_FAILS(hr, m_ParamList.Load( m_bstrLCID, bstrID, bstrData ));
  315. m_ParamList.get_SearchEngineName ( m_bstrName );
  316. m_ParamList.get_SearchEngineOwner ( m_bstrOwner );
  317. m_ParamList.get_SearchEngineDescription( m_bstrDescription );
  318. hr = S_OK;
  319. __HCP_FUNC_CLEANUP;
  320. __HCP_FUNC_EXIT(hr);
  321. }
  322. STDMETHODIMP SearchEngine::WrapperNetSearch::get_SearchTerms( /*[out, retval]*/ VARIANT *pvTerms )
  323. {
  324. __HCP_FUNC_ENTRY( "SearchEngine::WrapperNetSearch::get_SearchTerms" );
  325. HRESULT hr;
  326. MPC::SmartLock<_ThreadModel> lock( this );
  327. MPC::WStringList strList;
  328. __MPC_PARAMCHECK_BEGIN(hr)
  329. __MPC_PARAMCHECK_NOTNULL(pvTerms);
  330. __MPC_PARAMCHECK_END();
  331. // Get all the search terms
  332. __MPC_EXIT_IF_METHOD_FAILS(hr, m_resConfig.GetSearchTerms( strList ));
  333. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::ConvertListToSafeArray( strList, *pvTerms, VT_BSTR ));
  334. hr = S_OK;
  335. __HCP_FUNC_CLEANUP;
  336. __HCP_FUNC_EXIT(hr);
  337. }
  338. ////////////////////////////////////////////////////////////////////////////////
  339. HRESULT SearchEngine::WrapperNetSearch::CreateListOfParams( /*[in]*/ CPCHCollection* coll )
  340. {
  341. __HCP_FUNC_ENTRY( "SearchEngine::WrapperNetSearch::CreateListOfParams" );
  342. HRESULT hr;
  343. m_ParamList.MoveFirst();
  344. while(m_ParamList.IsCursorValid())
  345. {
  346. ParamItem_Definition2 def;
  347. __MPC_EXIT_IF_METHOD_FAILS(hr, m_ParamList.InitializeParamObject( def ) );
  348. __MPC_EXIT_IF_METHOD_FAILS(hr, CreateParam( coll, &def ));
  349. m_ParamList.MoveNext();
  350. }
  351. hr = S_OK;
  352. __HCP_FUNC_CLEANUP;
  353. __HCP_FUNC_EXIT(hr);
  354. }