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.

705 lines
18 KiB

  1. /******************************************************************************
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. Behav_SUBSITE.cpp
  5. Abstract:
  6. This file contains the implementation of the CPCHBehavior_SUBSITE class.
  7. Revision History:
  8. Davide Massarenti (dmassare) 08/15/2000
  9. created
  10. ******************************************************************************/
  11. #include "stdafx.h"
  12. ////////////////////////////////////////////////////////////////////////////////
  13. CPCHBehavior_SUBSITE::QueryNode::QueryNode()
  14. {
  15. // CComPtr<IPCHQueryResult> m_qrNode;
  16. m_fQueryDone = false; // bool m_fQueryDone;
  17. m_fTopic = false; // bool m_fTopic;
  18. };
  19. CPCHBehavior_SUBSITE::QueryNode::~QueryNode()
  20. {
  21. ;
  22. }
  23. HRESULT CPCHBehavior_SUBSITE::QueryNode::Init( /*[in]*/ LPCWSTR szNode ,
  24. /*[in]*/ NodeType iType ,
  25. /*[in]*/ CPCHQueryResult* qr ,
  26. /*[in]*/ bool fTopic )
  27. {
  28. m_fTopic = fTopic;
  29. if(qr)
  30. {
  31. m_qrNode = qr;
  32. m_fQueryDone = true;
  33. m_fLoaded_Self = true;
  34. if(fTopic)
  35. {
  36. m_fLoaded_Children = true;
  37. }
  38. }
  39. return Node::Init( szNode, iType );
  40. }
  41. ////////////////////////////////////////////////////////////////////////////////
  42. HRESULT CPCHBehavior_SUBSITE::QueryNode::ProcessRefreshRequest()
  43. {
  44. __HCP_FUNC_ENTRY( "CPCHBehavior_SUBSITE::QueryNode::ProcessRefreshRequest" );
  45. HRESULT hr;
  46. bool fNotify = false;
  47. NodeToSelect* nts;
  48. if(m_fLoaded_Self && m_fLoaded_Children && (nts = m_owner->GetNodeToSelect()))
  49. {
  50. bool fSelect = false;
  51. if(m_fTopic)
  52. {
  53. if(nts->m_bstrURL && MPC::StrICmp( m_bstrNode, nts->m_bstrURL ) == 0)
  54. {
  55. nts->m_bstrURL .Empty();
  56. nts->m_bstrNode.Empty();
  57. fSelect = true;
  58. }
  59. }
  60. else
  61. {
  62. if(nts->m_bstrNode && m_bstrNode)
  63. {
  64. int iSize = m_bstrNode.Length();
  65. if(_wcsnicmp( m_bstrNode, nts->m_bstrNode, iSize ) == 0)
  66. {
  67. switch(nts->m_bstrNode[iSize])
  68. {
  69. case 0: // Full match.
  70. nts->m_bstrNode.Empty();
  71. m_fExpanded = true;
  72. fSelect = true;
  73. break;
  74. case '/': // Partial match, expand node.
  75. if(m_fExpanded == false)
  76. {
  77. m_fExpanded = true;
  78. fNotify = true;
  79. }
  80. break;
  81. }
  82. }
  83. }
  84. }
  85. if(fSelect)
  86. {
  87. Node* node = m_parent;
  88. //
  89. // Reset all the NEXTACTIVE flags for the parents, also expanding them.
  90. //
  91. while(node)
  92. {
  93. if(node->m_iSelection == SELECTION__NEXTACTIVE ||
  94. node->m_iSelection == SELECTION__NEXTACTIVE_NOTIFY )
  95. {
  96. node->m_iSelection = SELECTION__NONE;
  97. }
  98. node->m_fExpanded = true; node->NotifyMainThread();
  99. node = node->m_parent;
  100. }
  101. m_iSelection = nts->m_fNotify ? SELECTION__NEXTACTIVE_NOTIFY : SELECTION__NEXTACTIVE;
  102. fNotify = true;
  103. }
  104. }
  105. __MPC_EXIT_IF_METHOD_FAILS(hr, CPCHBehavior_BasicTree::Node::ProcessRefreshRequest());
  106. hr = S_OK;
  107. __HCP_FUNC_CLEANUP;
  108. if(fNotify) NotifyMainThread();
  109. __HCP_FUNC_EXIT(hr);
  110. }
  111. HRESULT CPCHBehavior_SUBSITE::QueryNode::CreateInstance( /*[in]*/ CPCHBehavior_BasicTree* owner, /*[in]*/ Node* parent, /*[out]*/ Node*& subnode )
  112. {
  113. return CreateInstance_QueryNode( owner, parent, subnode );
  114. }
  115. HRESULT CPCHBehavior_SUBSITE::QueryNode::CreateInstance_QueryNode( /*[in]*/ CPCHBehavior_BasicTree* owner, /*[in]*/ Node* parent, /*[out]*/ Node*& subnode )
  116. {
  117. __HCP_FUNC_ENTRY( "CPCHBehavior_SUBSITE::QueryNode::CreateInstance_QueryNode" );
  118. HRESULT hr;
  119. QueryNode* node;
  120. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &node ));
  121. node->m_owner = owner;
  122. node->m_parent = parent;
  123. hr = S_OK;
  124. __HCP_FUNC_CLEANUP;
  125. subnode = node;
  126. __HCP_FUNC_EXIT(hr);
  127. }
  128. HRESULT CPCHBehavior_SUBSITE::QueryNode::PopulateSelf()
  129. {
  130. __HCP_FUNC_ENTRY( "CPCHBehavior_SUBSITE::QueryNode::PopulateSelf" );
  131. HRESULT hr;
  132. CPCHProxy_IPCHTaxonomyDatabase* db = (m_owner ? ((CPCHBehavior_SUBSITE*)m_owner)->m_db : NULL);
  133. if(m_fLoaded_Self == false && db)
  134. {
  135. //
  136. // Load self.
  137. //
  138. if(m_fTopic == false)
  139. {
  140. CComPtr<CPCHQueryResultCollection> pColl;
  141. if(SUCCEEDED(db->ExecuteQuery( OfflineCache::ET_NODE, m_bstrNode, &pColl )))
  142. {
  143. m_qrNode.Release();
  144. if(SUCCEEDED(pColl->GetItem( 0, &m_qrNode )))
  145. {
  146. if(m_parent == NULL)
  147. {
  148. m_owner->SetNavModel( m_qrNode->GetData().m_lNavModel );
  149. }
  150. }
  151. }
  152. m_fQueryDone = true;
  153. }
  154. else
  155. {
  156. m_fLoaded_Children = true;
  157. }
  158. m_fLoaded_Self = true;
  159. }
  160. hr = S_OK;
  161. __HCP_FUNC_EXIT(hr);
  162. }
  163. HRESULT CPCHBehavior_SUBSITE::QueryNode::PopulateChildren()
  164. {
  165. __HCP_FUNC_ENTRY( "CPCHBehavior_SUBSITE::QueryNode::PopulateChildren" );
  166. HRESULT hr;
  167. CPCHProxy_IPCHTaxonomyDatabase* db = (m_owner ? ((CPCHBehavior_SUBSITE*)m_owner)->m_db : NULL);
  168. if(m_fLoaded_Children == false && db)
  169. {
  170. //
  171. // Load sub nodes.
  172. //
  173. if(m_fTopic == false)
  174. {
  175. CComPtr<CPCHQueryResultCollection> pColl;
  176. int iType;
  177. iType = (m_owner->GetNavModel() == QR_DESKTOP ? OfflineCache::ET_SUBNODES_VISIBLE : OfflineCache::ET_NODESANDTOPICS_VISIBLE);
  178. if(SUCCEEDED(db->ExecuteQuery( iType, m_bstrNode, &pColl )))
  179. {
  180. long lPos;
  181. long lCount;
  182. MPC_SCRIPTHELPER_GET__DIRECT(lCount, pColl, Count);
  183. for(lPos=0; lPos<lCount; lPos++)
  184. {
  185. CComPtr<CPCHQueryResult> qr;
  186. CComBSTR bstrNode;
  187. CComBSTR bstrEntry;
  188. QueryNode* node;
  189. bool fTopic;
  190. __MPC_EXIT_IF_METHOD_FAILS(hr, pColl->GetItem( lPos, &qr ));
  191. {
  192. const CPCHQueryResult::Payload& pl = qr->GetData();
  193. __MPC_EXIT_IF_METHOD_FAILS(hr, CreateInstance_QueryNode( m_owner, this, (Node*&)node ));
  194. m_lstSubnodes.push_back( node );
  195. if(pl.m_bstrEntry.Length() > 0) // It's a node.
  196. {
  197. MPC_SCRIPTHELPER_GET__DIRECT(bstrNode, qr, FullPath);
  198. fTopic = false;
  199. }
  200. else
  201. {
  202. bstrNode = pl.m_bstrTopicURL;
  203. fTopic = true;
  204. }
  205. }
  206. __MPC_EXIT_IF_METHOD_FAILS(hr, node->Init( bstrNode, fTopic ? NODETYPE__EXPANDO_TOPIC : NODETYPE__EXPANDO, qr, fTopic ));
  207. }
  208. }
  209. }
  210. m_fLoaded_Children = true;
  211. }
  212. hr = S_OK;
  213. __HCP_FUNC_CLEANUP;
  214. if(FAILED(hr))
  215. {
  216. MPC::CallDestructorForAll( m_lstSubnodes );
  217. m_fInvalid = true;
  218. m_fLoaded_Children = true;
  219. hr = S_OK;
  220. }
  221. __HCP_FUNC_EXIT(hr);
  222. }
  223. ////////////////////////////////////////////////////////////////////////////////
  224. HRESULT CPCHBehavior_SUBSITE::QueryNode::GenerateSelf()
  225. {
  226. __HCP_FUNC_ENTRY( "CPCHBehavior_SUBSITE::QueryNode::GenerateSelf" );
  227. HRESULT hr;
  228. if(!m_fInvalid)
  229. {
  230. if(!m_fLoaded_Self || !m_fLoaded_Children || !m_fQueryDone)
  231. {
  232. m_owner->Thread_Signal(); // Tell the worker thread to process something...
  233. }
  234. if(!m_fLoaded_Self || !m_fQueryDone)
  235. {
  236. __MPC_SET_WIN32_ERROR_AND_EXIT(hr, ERROR_NOT_READY);
  237. }
  238. }
  239. ////////////////////
  240. if(m_qrNode)
  241. {
  242. const CPCHQueryResult::Payload& pl = m_qrNode->GetData();
  243. LPCWSTR szTitle = pl.m_bstrTitle ? pl.m_bstrTitle : pl.m_bstrCategory;
  244. LPCWSTR szDesc = pl.m_bstrDescription;
  245. LPCWSTR szIcon = pl.m_bstrIconURL;
  246. LPCWSTR szURL = pl.m_bstrTopicURL;
  247. __MPC_EXIT_IF_METHOD_FAILS(hr, GenerateHTML( szTitle, szDesc, szIcon, szURL ));
  248. }
  249. else
  250. {
  251. MPC::wstring strTitle; MPC::LocalizeString( IDS_HELPCTR_TAXO_UNKNOWN_NODE, strTitle );
  252. __MPC_EXIT_IF_METHOD_FAILS(hr, GenerateHTML( strTitle.c_str(), NULL, NULL, NULL ));
  253. }
  254. hr = S_OK;
  255. __HCP_FUNC_CLEANUP;
  256. __HCP_FUNC_EXIT(hr);
  257. }
  258. ////////////////////////////////////////////////////////////////////////////////
  259. HRESULT CPCHBehavior_SUBSITE::QueryNode::Load( /*[in]*/ MPC::Serializer& stream )
  260. {
  261. __HCP_FUNC_ENTRY( "CPCHBehavior_SUBSITE::QueryNode::Load" );
  262. HRESULT hr;
  263. bool fSavedNode;
  264. __MPC_EXIT_IF_METHOD_FAILS(hr, Node::Load( stream ));
  265. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> m_fLoaded_Self);
  266. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> m_fTopic );
  267. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> fSavedNode );
  268. if(fSavedNode)
  269. {
  270. m_qrNode.Release();
  271. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &m_qrNode ));
  272. __MPC_EXIT_IF_METHOD_FAILS(hr, m_qrNode->Load( stream ));
  273. m_fQueryDone = true;
  274. }
  275. hr = S_OK;
  276. __HCP_FUNC_CLEANUP;
  277. __HCP_FUNC_EXIT(hr);
  278. }
  279. HRESULT CPCHBehavior_SUBSITE::QueryNode::Save( /*[in]*/ MPC::Serializer& stream, /*[in]*/ bool fSaveChildren )
  280. {
  281. __HCP_FUNC_ENTRY( "CPCHBehavior_SUBSITE::QueryNode::Save" );
  282. HRESULT hr;
  283. bool fSaveNode = (m_fLoaded_Self && m_qrNode);
  284. if(m_fExpanded == false) fSaveChildren = false;
  285. __MPC_EXIT_IF_METHOD_FAILS(hr, Node::Save( stream, fSaveChildren ));
  286. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << m_fLoaded_Self);
  287. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << m_fTopic );
  288. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << fSaveNode );
  289. if(fSaveNode)
  290. {
  291. __MPC_EXIT_IF_METHOD_FAILS(hr, m_qrNode->Save( stream ));
  292. }
  293. hr = S_OK;
  294. __HCP_FUNC_CLEANUP;
  295. __HCP_FUNC_EXIT(hr);
  296. }
  297. ////////////////////////////////////////////////////////////////////////////////
  298. ////////////////////////////////////////////////////////////////////////////////
  299. CPCHBehavior_SUBSITE::CPCHBehavior_SUBSITE()
  300. {
  301. m_db = NULL; // CPCHProxy_IPCHTaxonomyDatabase* m_db;
  302. // CComBSTR m_bstrRoot;
  303. m_fExpand = false; // bool m_fExpand;
  304. }
  305. HRESULT CPCHBehavior_SUBSITE::RefreshThread_Enter()
  306. {
  307. __HCP_FUNC_ENTRY( "CPCHBehavior_SUBSITE::RefreshThread_Enter" );
  308. HRESULT hr;
  309. __MPC_EXIT_IF_METHOD_FAILS(hr, m_parent->Utility()->GetDatabase( &m_db ));
  310. if(m_nTopNode == NULL)
  311. {
  312. //
  313. // Generate the outer UI.
  314. //
  315. __MPC_EXIT_IF_METHOD_FAILS(hr, QueryNode::CreateInstance_QueryNode( this, NULL, m_nTopNode ));
  316. {
  317. QueryNode* node = (QueryNode*)m_nTopNode;
  318. __MPC_EXIT_IF_METHOD_FAILS(hr, node->Init ( m_bstrRoot, m_fExpand ? NODETYPE__FRAME1_EXPAND : NODETYPE__FRAME2, NULL, /*fTopic*/false ));
  319. __MPC_EXIT_IF_METHOD_FAILS(hr, node->PopulateSelf ( ));
  320. __MPC_EXIT_IF_METHOD_FAILS(hr, node->PopulateChildren( ));
  321. node->m_parentElement = m_elem;
  322. }
  323. }
  324. m_nTopNode->NotifyMainThread();
  325. hr = S_OK;
  326. __HCP_FUNC_CLEANUP;
  327. __HCP_FUNC_EXIT(hr);
  328. }
  329. void CPCHBehavior_SUBSITE::RefreshThread_Leave()
  330. {
  331. MPC::Release2<IPCHTaxonomyDatabase>( m_db );
  332. }
  333. ////////////////////////////////////////////////////////////////////////////////
  334. STDMETHODIMP CPCHBehavior_SUBSITE::Invoke( DISPID dispidMember ,
  335. REFIID riid ,
  336. LCID lcid ,
  337. WORD wFlags ,
  338. DISPPARAMS* pdispparams ,
  339. VARIANT* pvarResult ,
  340. EXCEPINFO* pexcepinfo ,
  341. UINT* puArgErr )
  342. {
  343. if(SUCCEEDED(InterceptInvoke( dispidMember, pdispparams ))) return S_OK;
  344. return CPCHBehavior__IDispatch_SubSite::Invoke( dispidMember ,
  345. riid ,
  346. lcid ,
  347. wFlags ,
  348. pdispparams ,
  349. pvarResult ,
  350. pexcepinfo ,
  351. puArgErr );
  352. }
  353. STDMETHODIMP CPCHBehavior_SUBSITE::Init( /*[in]*/ IElementBehaviorSite* pBehaviorSite )
  354. {
  355. __HCP_FUNC_ENTRY( "CPCHBehavior_SUBSITE::Init" );
  356. HRESULT hr;
  357. CComVariant v;
  358. __MPC_EXIT_IF_METHOD_FAILS(hr, CPCHBehavior_BasicTree::Init( pBehaviorSite ));
  359. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::COMUtil::GetPropertyByName( m_elem, L"expand", v ));
  360. if(SUCCEEDED(v.ChangeType( VT_BOOL )) && v.boolVal == VARIANT_TRUE) m_fExpand = true;
  361. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::COMUtil::GetPropertyByName( m_elem, L"root", m_bstrRoot ));
  362. if(m_bstrRoot.Length())
  363. {
  364. __MPC_EXIT_IF_METHOD_FAILS(hr, Thread_Start( this, RefreshThread, this ));
  365. }
  366. hr = S_OK;
  367. __HCP_FUNC_CLEANUP;
  368. __HCP_FUNC_EXIT(hr);
  369. }
  370. /////////////////////////////////////////////////////////////////////////////
  371. HRESULT CPCHBehavior_SUBSITE::Load( /*[in]*/ MPC::Serializer& stream )
  372. {
  373. __HCP_FUNC_ENTRY( "CPCHBehavior_SUBSITE::Load" );
  374. HRESULT hr;
  375. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> m_bstrRoot );
  376. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> m_lNavModel);
  377. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> m_fExpand );
  378. //
  379. // Create top level node.
  380. //
  381. __MPC_EXIT_IF_METHOD_FAILS(hr, QueryNode::CreateInstance_QueryNode( this, NULL, m_nTopNode ));
  382. {
  383. QueryNode* node = (QueryNode*)m_nTopNode;
  384. __MPC_EXIT_IF_METHOD_FAILS(hr, node->Init( m_bstrRoot, m_fExpand ? NODETYPE__FRAME1_EXPAND : NODETYPE__FRAME2, NULL, /*fTopic*/false ));
  385. node->m_parentElement = m_elem;
  386. }
  387. __MPC_EXIT_IF_METHOD_FAILS(hr, CPCHBehavior_BasicTree::Load( stream ));
  388. hr = S_OK;
  389. __HCP_FUNC_CLEANUP;
  390. __HCP_FUNC_EXIT(hr);
  391. }
  392. HRESULT CPCHBehavior_SUBSITE::Save( /*[in]*/ MPC::Serializer& stream )
  393. {
  394. __HCP_FUNC_ENTRY( "CPCHBehavior_SUBSITE::Save" );
  395. HRESULT hr;
  396. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << m_bstrRoot );
  397. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << m_lNavModel);
  398. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << m_fExpand );
  399. __MPC_EXIT_IF_METHOD_FAILS(hr, CPCHBehavior_BasicTree::Save( stream ));
  400. hr = S_OK;
  401. __HCP_FUNC_CLEANUP;
  402. __HCP_FUNC_EXIT(hr);
  403. }
  404. ////////////////////////////////////////////////////////////////////////////////
  405. STDMETHODIMP CPCHBehavior_SUBSITE::get_data( /*[out, retval]*/ VARIANT *pVal )
  406. {
  407. MPC::SmartLock<_ThreadModel> lock( this ); WaitForRefreshing( lock );
  408. QueryNode* node = (QueryNode*)(m_nCurrent ? m_nCurrent : m_nSelected);
  409. return GetAsVARIANT( node ? node->m_qrNode : NULL, pVal );
  410. }
  411. STDMETHODIMP CPCHBehavior_SUBSITE::get_element( /*[out, retval]*/ IDispatch* *pVal )
  412. {
  413. MPC::SmartLock<_ThreadModel> lock( this ); WaitForRefreshing( lock );
  414. QueryNode* node = (QueryNode*)(m_nCurrent ? m_nCurrent : m_nSelected);
  415. return GetAsIDISPATCH( node ? node->m_DIV : NULL, pVal );
  416. }
  417. STDMETHODIMP CPCHBehavior_SUBSITE::Load( /*[in]*/ BSTR newVal )
  418. {
  419. __HCP_FUNC_ENTRY( "CPCHBehavior_SUBSITE::Load" );
  420. HRESULT hr;
  421. Thread_Wait();
  422. __MPC_EXIT_IF_METHOD_FAILS(hr, Persist_Load( newVal ));
  423. __MPC_EXIT_IF_METHOD_FAILS(hr, Thread_Start( this, RefreshThread, this ));
  424. hr = S_OK;
  425. __HCP_FUNC_CLEANUP;
  426. __HCP_FUNC_EXIT(hr);
  427. }
  428. STDMETHODIMP CPCHBehavior_SUBSITE::Save( /*[out, retval]*/ BSTR *pVal )
  429. {
  430. __HCP_FUNC_ENTRY( "CPCHBehavior_SUBSITE::Save" );
  431. HRESULT hr;
  432. MPC::SmartLock<_ThreadModel> lock( this ); WaitForRefreshing( lock );
  433. __MPC_PARAMCHECK_BEGIN(hr)
  434. __MPC_PARAMCHECK_POINTER_AND_SET(pVal,NULL);
  435. __MPC_PARAMCHECK_END();
  436. __MPC_EXIT_IF_METHOD_FAILS(hr, Persist_Save( pVal ));
  437. hr = S_OK;
  438. __HCP_FUNC_CLEANUP;
  439. __HCP_FUNC_EXIT(hr);
  440. }
  441. STDMETHODIMP CPCHBehavior_SUBSITE::Locate( /*[in ]*/ BSTR bstrKey ,
  442. /*[out, retval]*/ VARIANT *pVal )
  443. {
  444. MPC::SmartLock<_ThreadModel> lock( this ); WaitForRefreshing( lock );
  445. QueryNode* node = (QueryNode*)NodeFromKey( bstrKey );
  446. return GetAsVARIANT( node ? node->m_qrNode : NULL, pVal );
  447. }
  448. STDMETHODIMP CPCHBehavior_SUBSITE::Unselect()
  449. {
  450. __HCP_FUNC_ENTRY( "CPCHBehavior_SUBSITE::Unselect" );
  451. HRESULT hr;
  452. MPC::SmartLock<_ThreadModel> lock( this ); WaitForRefreshing( lock );
  453. __MPC_EXIT_IF_METHOD_FAILS(hr, ChangeSelection( NULL, /*fNotify*/true ));
  454. hr = S_OK;
  455. __HCP_FUNC_CLEANUP;
  456. __HCP_FUNC_EXIT(hr);
  457. }
  458. ////////////////////////////////////////////////////////////////////////////////
  459. STDMETHODIMP CPCHBehavior_SUBSITE::get_root( /*[out, retval]*/ BSTR *pVal )
  460. {
  461. return MPC::GetBSTR( m_bstrRoot, pVal );
  462. }
  463. STDMETHODIMP CPCHBehavior_SUBSITE::put_root( /*[in]*/ BSTR pVal )
  464. {
  465. __HCP_FUNC_ENTRY( "CPCHBehavior_SUBSITE::put_root" );
  466. HRESULT hr;
  467. Thread_Wait();
  468. Empty();
  469. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::PutBSTR( m_bstrRoot, pVal ));
  470. __MPC_EXIT_IF_METHOD_FAILS(hr, Thread_Start( this, RefreshThread, this ));
  471. hr = S_OK;
  472. __HCP_FUNC_CLEANUP;
  473. __HCP_FUNC_EXIT(hr);
  474. }
  475. STDMETHODIMP CPCHBehavior_SUBSITE::Select( /*[in]*/ BSTR bstrNode ,
  476. /*[in]*/ BSTR bstrURL ,
  477. /*[in]*/ VARIANT_BOOL fNotify )
  478. {
  479. __HCP_FUNC_ENTRY( "CPCHBehavior_SUBSITE::Select" );
  480. HRESULT hr;
  481. MPC::SmartLock<_ThreadModel> lock( this ); WaitForRefreshing( lock );
  482. delete m_nToSelect; __MPC_EXIT_IF_ALLOC_FAILS(hr, m_nToSelect, new NodeToSelect);
  483. m_nToSelect->m_bstrNode = bstrNode;
  484. m_nToSelect->m_bstrURL = bstrURL;
  485. m_nToSelect->m_fNotify = fNotify == VARIANT_TRUE;
  486. Thread_Signal();
  487. hr = S_OK;
  488. __HCP_FUNC_CLEANUP;
  489. __HCP_FUNC_EXIT(hr);
  490. }