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.

551 lines
17 KiB

  1. /******************************************************************************
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. Behav_TREE.cpp
  5. Abstract:
  6. This file contains the implementation of the CPCHBehavior_TREE class.
  7. Revision History:
  8. Davide Massarenti (dmassare) 08/15/2000
  9. created
  10. ******************************************************************************/
  11. #include "stdafx.h"
  12. ////////////////////////////////////////////////////////////////////////////////
  13. static const WCHAR s_nodetype_FRAME1 [] = L"FRAME1" ;
  14. static const WCHAR s_nodetype_FRAME2 [] = L"FRAME2" ;
  15. static const WCHAR s_nodetype_FRAME3 [] = L"FRAME3" ;
  16. static const WCHAR s_nodetype_FRAME1_EXPAND[] = L"FRAME1_EXPAND";
  17. static const WCHAR s_nodetype_FRAME2_EXPAND[] = L"FRAME2_EXPAND";
  18. static const WCHAR s_nodetype_FRAME3_EXPAND[] = L"FRAME3_EXPAND";
  19. static const WCHAR s_nodetype_EXPANDO [] = L"EXPANDO" ;
  20. static const WCHAR s_nodetype_EXPANDO_LINK [] = L"EXPANDO_LINK" ;
  21. static const WCHAR s_nodetype_GROUP [] = L"GROUP" ;
  22. static const WCHAR s_nodetype_LINK [] = L"LINK" ;
  23. static const WCHAR s_nodetype_SPACER [] = L"SPACER" ;
  24. ////////////////////////////////////////////////////////////////////////////////
  25. CPCHBehavior_TREE::TreeNode::TreeNode()
  26. {
  27. // CComBSTR m_bstrTitle;
  28. // CComBSTR m_bstrDescription;
  29. // CComBSTR m_bstrIcon;
  30. // CComBSTR m_bstrURL;
  31. }
  32. CPCHBehavior_TREE::TreeNode::~TreeNode()
  33. {
  34. ;
  35. }
  36. ////////////////////////////////////////////////////////////////////////////////
  37. HRESULT CPCHBehavior_TREE::TreeNode::CreateInstance( /*[in]*/ CPCHBehavior_BasicTree* owner, /*[in]*/ Node* parent, /*[out]*/ Node*& subnode )
  38. {
  39. return CreateInstance_TreeNode( owner, parent, subnode );
  40. }
  41. HRESULT CPCHBehavior_TREE::TreeNode::CreateInstance_TreeNode( /*[in]*/ CPCHBehavior_BasicTree* owner, /*[in]*/ Node* parent, /*[out]*/ Node*& subnode )
  42. {
  43. __HCP_FUNC_ENTRY( "CPCHBehavior_TREE::TreeNode::CreateInstance_TreeNode" );
  44. HRESULT hr;
  45. TreeNode* node;
  46. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &node ));
  47. node->m_owner = owner;
  48. node->m_parent = parent;
  49. hr = S_OK;
  50. __HCP_FUNC_CLEANUP;
  51. subnode = node;
  52. __HCP_FUNC_EXIT(hr);
  53. }
  54. HRESULT CPCHBehavior_TREE::TreeNode::PopulateSelf()
  55. {
  56. m_fLoaded_Self = true;
  57. return S_OK;
  58. }
  59. HRESULT CPCHBehavior_TREE::TreeNode::PopulateChildren()
  60. {
  61. m_fLoaded_Children = true;
  62. return S_OK;
  63. }
  64. ////////////////////////////////////////////////////////////////////////////////
  65. HRESULT CPCHBehavior_TREE::TreeNode::GenerateSelf()
  66. {
  67. __HCP_FUNC_ENTRY( "CPCHBehavior_TREE::TreeNode::GenerateSelf" );
  68. HRESULT hr;
  69. if(!m_fLoaded_Self || !m_fLoaded_Children)
  70. {
  71. __MPC_SET_WIN32_ERROR_AND_EXIT(hr, ERROR_NOT_READY);
  72. }
  73. ////////////////////
  74. __MPC_EXIT_IF_METHOD_FAILS(hr, GenerateHTML( m_bstrTitle, m_bstrDescription, m_bstrIcon, m_bstrURL ));
  75. hr = S_OK;
  76. __HCP_FUNC_CLEANUP;
  77. __HCP_FUNC_EXIT(hr);
  78. }
  79. ////////////////////////////////////////////////////////////////////////////////
  80. HRESULT CPCHBehavior_TREE::TreeNode::Load( /*[in]*/ MPC::Serializer& stream )
  81. {
  82. __HCP_FUNC_ENTRY( "CPCHBehavior_TREE::TreeNode::Load" );
  83. HRESULT hr;
  84. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> m_bstrTitle );
  85. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> m_bstrDescription);
  86. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> m_bstrIcon );
  87. __MPC_EXIT_IF_METHOD_FAILS(hr, stream >> m_bstrURL );
  88. __MPC_EXIT_IF_METHOD_FAILS(hr, Node::Load( stream ));
  89. hr = S_OK;
  90. __HCP_FUNC_CLEANUP;
  91. __HCP_FUNC_EXIT(hr);
  92. }
  93. HRESULT CPCHBehavior_TREE::TreeNode::Save( /*[in]*/ MPC::Serializer& stream, /*[in]*/ bool fSaveChildren )
  94. {
  95. __HCP_FUNC_ENTRY( "CPCHBehavior_TREE::TreeNode::Save" );
  96. HRESULT hr;
  97. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << m_bstrTitle );
  98. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << m_bstrDescription);
  99. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << m_bstrIcon );
  100. __MPC_EXIT_IF_METHOD_FAILS(hr, stream << m_bstrURL );
  101. __MPC_EXIT_IF_METHOD_FAILS(hr, Node::Save( stream, /*fSaveChildren*/true ));
  102. hr = S_OK;
  103. __HCP_FUNC_CLEANUP;
  104. __HCP_FUNC_EXIT(hr);
  105. }
  106. ////////////////////////////////////////////////////////////////////////////////
  107. HRESULT CPCHBehavior_TREE::TreeNode::PopulateFromXML( /*[in]*/ CPCHBehavior_TREE* owner ,
  108. /*[in]*/ TreeNode* parent ,
  109. /*[in]*/ IXMLDOMNode* xdnNode )
  110. {
  111. __HCP_FUNC_ENTRY( "CPCHBehavior_TREE::TreeNode::PopulateFromXML" );
  112. HRESULT hr;
  113. MPC::XmlUtil xmlutil( xdnNode );
  114. TreeNode* node = NULL;
  115. MPC::wstring strKey;
  116. CComBSTR bstrNodeType;
  117. long lExpanded;
  118. bool fFound;
  119. __MPC_EXIT_IF_METHOD_FAILS(hr, xmlutil.GetAttribute( NULL, L"Key" , strKey , fFound ));
  120. __MPC_EXIT_IF_METHOD_FAILS(hr, xmlutil.GetAttribute( NULL, L"NodeType", bstrNodeType, fFound ));
  121. __MPC_EXIT_IF_METHOD_FAILS(hr, xmlutil.GetAttribute( NULL, L"Expanded", lExpanded , fFound )); if(!fFound) lExpanded = 0;
  122. __MPC_EXIT_IF_METHOD_FAILS(hr, TreeNode::CreateInstance_TreeNode( owner, parent, (Node*&)node ));
  123. __MPC_EXIT_IF_METHOD_FAILS(hr, node->Init( strKey.c_str(), LookupType( bstrNodeType ) ));
  124. if(node->m_iType == NODETYPE__EXPANDO && lExpanded)
  125. {
  126. node->m_fExpanded = true;
  127. }
  128. __MPC_EXIT_IF_METHOD_FAILS(hr, xmlutil.GetAttribute( NULL, L"Title" , node->m_bstrTitle , fFound ));
  129. __MPC_EXIT_IF_METHOD_FAILS(hr, xmlutil.GetAttribute( NULL, L"Description", node->m_bstrDescription, fFound ));
  130. __MPC_EXIT_IF_METHOD_FAILS(hr, xmlutil.GetAttribute( NULL, L"Icon" , node->m_bstrIcon , fFound ));
  131. __MPC_EXIT_IF_METHOD_FAILS(hr, xmlutil.GetAttribute( NULL, L"URL" , node->m_bstrURL , fFound ));
  132. {
  133. CComPtr<IXMLDOMNodeList> xdnlChildren;
  134. CComPtr<IXMLDOMNode> xdnChild;
  135. __MPC_EXIT_IF_METHOD_FAILS(hr, xmlutil.GetNodes( L"NODE", &xdnlChildren ));
  136. for(;SUCCEEDED(hr = xdnlChildren->nextNode( &xdnChild )) && xdnChild != NULL; xdnChild.Release())
  137. {
  138. __MPC_EXIT_IF_METHOD_FAILS(hr, PopulateFromXML( owner, node, xdnChild ));
  139. }
  140. }
  141. if(parent)
  142. {
  143. parent->m_lstSubnodes.push_back( node );
  144. }
  145. else
  146. {
  147. node->m_parentElement = owner->m_elem;
  148. owner->m_nTopNode = node;
  149. }
  150. node = NULL;
  151. hr = S_OK;
  152. __HCP_FUNC_CLEANUP;
  153. MPC::Release( node );
  154. __HCP_FUNC_EXIT(hr);
  155. }
  156. ////////////////////////////////////////////////////////////////////////////////
  157. ////////////////////////////////////////////////////////////////////////////////
  158. CPCHBehavior_TREE::NodeType CPCHBehavior_TREE::LookupType( /*[in]*/ LPCWSTR szNodeType )
  159. {
  160. if(szNodeType)
  161. {
  162. if(!_wcsicmp( szNodeType, s_nodetype_FRAME1 )) return NODETYPE__FRAME1 ;
  163. if(!_wcsicmp( szNodeType, s_nodetype_FRAME2 )) return NODETYPE__FRAME2 ;
  164. if(!_wcsicmp( szNodeType, s_nodetype_FRAME3 )) return NODETYPE__FRAME3 ;
  165. if(!_wcsicmp( szNodeType, s_nodetype_FRAME1_EXPAND)) return NODETYPE__FRAME1_EXPAND;
  166. if(!_wcsicmp( szNodeType, s_nodetype_FRAME2_EXPAND)) return NODETYPE__FRAME2_EXPAND;
  167. if(!_wcsicmp( szNodeType, s_nodetype_FRAME3_EXPAND)) return NODETYPE__FRAME3_EXPAND;
  168. if(!_wcsicmp( szNodeType, s_nodetype_EXPANDO )) return NODETYPE__EXPANDO ;
  169. if(!_wcsicmp( szNodeType, s_nodetype_EXPANDO_LINK )) return NODETYPE__EXPANDO_LINK ;
  170. if(!_wcsicmp( szNodeType, s_nodetype_GROUP )) return NODETYPE__GROUP ;
  171. if(!_wcsicmp( szNodeType, s_nodetype_LINK )) return NODETYPE__LINK ;
  172. if(!_wcsicmp( szNodeType, s_nodetype_SPACER )) return NODETYPE__SPACER ;
  173. }
  174. return NODETYPE__EXPANDO;
  175. }
  176. LPCWSTR CPCHBehavior_TREE::LookupType( /*[in]*/ NodeType iNodeType )
  177. {
  178. switch(iNodeType)
  179. {
  180. case NODETYPE__FRAME1 : return s_nodetype_FRAME1 ;
  181. case NODETYPE__FRAME2 : return s_nodetype_FRAME2 ;
  182. case NODETYPE__FRAME3 : return s_nodetype_FRAME3 ;
  183. case NODETYPE__FRAME1_EXPAND: return s_nodetype_FRAME1_EXPAND;
  184. case NODETYPE__FRAME2_EXPAND: return s_nodetype_FRAME2_EXPAND;
  185. case NODETYPE__FRAME3_EXPAND: return s_nodetype_FRAME3_EXPAND;
  186. case NODETYPE__EXPANDO : return s_nodetype_EXPANDO ;
  187. case NODETYPE__EXPANDO_LINK : return s_nodetype_EXPANDO_LINK ;
  188. case NODETYPE__GROUP : return s_nodetype_GROUP ;
  189. case NODETYPE__LINK : return s_nodetype_LINK ;
  190. case NODETYPE__SPACER : return s_nodetype_SPACER ;
  191. }
  192. return NULL;
  193. }
  194. ////////////////////////////////////////////////////////////////////////////////
  195. HRESULT CPCHBehavior_TREE::RefreshThread_Enter()
  196. {
  197. Thread_Signal(); // This forces a refresh of the state.
  198. return S_OK;
  199. }
  200. void CPCHBehavior_TREE::RefreshThread_Leave()
  201. {
  202. }
  203. ////////////////////////////////////////////////////////////////////////////////
  204. STDMETHODIMP CPCHBehavior_TREE::Invoke( DISPID dispidMember ,
  205. REFIID riid ,
  206. LCID lcid ,
  207. WORD wFlags ,
  208. DISPPARAMS* pdispparams ,
  209. VARIANT* pvarResult ,
  210. EXCEPINFO* pexcepinfo ,
  211. UINT* puArgErr )
  212. {
  213. if(SUCCEEDED(InterceptInvoke( dispidMember, pdispparams ))) return S_OK;
  214. return CPCHBehavior__IDispatch_Tree::Invoke( dispidMember ,
  215. riid ,
  216. lcid ,
  217. wFlags ,
  218. pdispparams ,
  219. pvarResult ,
  220. pexcepinfo ,
  221. puArgErr );
  222. }
  223. /////////////////////////////////////////////////////////////////////////////
  224. STDMETHODIMP CPCHBehavior_TREE::Init( /*[in]*/ IElementBehaviorSite* pBehaviorSite )
  225. {
  226. __HCP_FUNC_ENTRY( "CPCHBehavior_TREE::Init" );
  227. HRESULT hr;
  228. __MPC_EXIT_IF_METHOD_FAILS(hr, CPCHBehavior_BasicTree::Init( pBehaviorSite ));
  229. __MPC_EXIT_IF_METHOD_FAILS(hr, Thread_Start( this, RefreshThread, this ));
  230. hr = S_OK;
  231. __HCP_FUNC_CLEANUP;
  232. __HCP_FUNC_EXIT(hr);
  233. }
  234. ////////////////////////////////////////////////////////////////////////////////
  235. HRESULT CPCHBehavior_TREE::Load( /*[in]*/ MPC::Serializer& stream )
  236. {
  237. __HCP_FUNC_ENTRY( "CPCHBehavior_TREE::Load" );
  238. HRESULT hr;
  239. //
  240. // Create top level node.
  241. //
  242. __MPC_EXIT_IF_METHOD_FAILS(hr, TreeNode::CreateInstance_TreeNode( this, NULL, m_nTopNode ));
  243. __MPC_EXIT_IF_METHOD_FAILS(hr, m_nTopNode->Init( NULL ));
  244. m_nTopNode->m_parentElement = m_elem;
  245. __MPC_EXIT_IF_METHOD_FAILS(hr, CPCHBehavior_BasicTree::Load( stream ));
  246. hr = S_OK;
  247. __HCP_FUNC_CLEANUP;
  248. __HCP_FUNC_EXIT(hr);
  249. }
  250. HRESULT CPCHBehavior_TREE::Save( /*[in]*/ MPC::Serializer& stream )
  251. {
  252. __HCP_FUNC_ENTRY( "CPCHBehavior_TREE::Save" );
  253. HRESULT hr;
  254. __MPC_EXIT_IF_METHOD_FAILS(hr, CPCHBehavior_BasicTree::Save( stream ));
  255. hr = S_OK;
  256. __HCP_FUNC_CLEANUP;
  257. __HCP_FUNC_EXIT(hr);
  258. }
  259. ////////////////////////////////////////////////////////////////////////////////
  260. HRESULT CPCHBehavior_TREE::WrapData( /*[in]*/ TreeNode* node, /*[out, retval]*/ VARIANT* pVal )
  261. {
  262. __HCP_FUNC_ENTRY( "CPCHBehavior_TREE::WrapData" );
  263. HRESULT hr;
  264. CPCHBehavior_TREENODE* obj = NULL;
  265. if(node)
  266. {
  267. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &obj ));
  268. MPC::Attach( obj->m_data, node );
  269. }
  270. __MPC_EXIT_IF_METHOD_FAILS(hr, GetAsVARIANT( obj, pVal ));
  271. hr = S_OK;
  272. __HCP_FUNC_CLEANUP;
  273. MPC::Release( obj );
  274. __HCP_FUNC_EXIT(hr);
  275. }
  276. STDMETHODIMP CPCHBehavior_TREE::get_data( /*[out, retval]*/ VARIANT* pVal )
  277. {
  278. MPC::SmartLock<_ThreadModel> lock( this ); WaitForRefreshing( lock );
  279. return WrapData( (TreeNode*)(m_nCurrent ? m_nCurrent : m_nSelected), pVal );
  280. }
  281. STDMETHODIMP CPCHBehavior_TREE::get_element( /*[out, retval]*/ IDispatch* *pVal )
  282. {
  283. MPC::SmartLock<_ThreadModel> lock( this ); WaitForRefreshing( lock );
  284. TreeNode* node = (TreeNode*)(m_nCurrent ? m_nCurrent : m_nSelected);
  285. return GetAsIDISPATCH( node ? node->m_DIV : NULL, pVal );
  286. }
  287. STDMETHODIMP CPCHBehavior_TREE::Load( /*[in]*/ BSTR newVal )
  288. {
  289. __HCP_FUNC_ENTRY( "CPCHBehavior_TREE::Load" );
  290. HRESULT hr;
  291. MPC::SmartLock<_ThreadModel> lock( this ); WaitForRefreshing( lock );
  292. __MPC_EXIT_IF_METHOD_FAILS(hr, Persist_Load( newVal )); Thread_Signal();
  293. hr = S_OK;
  294. __HCP_FUNC_CLEANUP;
  295. __HCP_FUNC_EXIT(hr);
  296. }
  297. STDMETHODIMP CPCHBehavior_TREE::Save( /*[out, retval]*/ BSTR *pVal )
  298. {
  299. __HCP_FUNC_ENTRY( "CPCHBehavior_TREE::Save" );
  300. HRESULT hr;
  301. MPC::SmartLock<_ThreadModel> lock( this ); WaitForRefreshing( lock );
  302. __MPC_PARAMCHECK_BEGIN(hr)
  303. __MPC_PARAMCHECK_POINTER_AND_SET(pVal,NULL);
  304. __MPC_PARAMCHECK_END();
  305. __MPC_EXIT_IF_METHOD_FAILS(hr, Persist_Save( pVal ));
  306. hr = S_OK;
  307. __HCP_FUNC_CLEANUP;
  308. __HCP_FUNC_EXIT(hr);
  309. }
  310. STDMETHODIMP CPCHBehavior_TREE::Locate( /*[in ]*/ BSTR bstrKey ,
  311. /*[out, retval]*/ VARIANT *pVal )
  312. {
  313. MPC::SmartLock<_ThreadModel> lock( this ); WaitForRefreshing( lock );
  314. Node* node = NodeFromKey( bstrKey );
  315. return WrapData( (TreeNode*)node, pVal );
  316. }
  317. STDMETHODIMP CPCHBehavior_TREE::Unselect()
  318. {
  319. __HCP_FUNC_ENTRY( "CPCHBehavior_TREE::Load" );
  320. HRESULT hr;
  321. MPC::SmartLock<_ThreadModel> lock( this ); WaitForRefreshing( lock );
  322. __MPC_EXIT_IF_METHOD_FAILS(hr, ChangeSelection( NULL, /*fNotify*/true ));
  323. hr = S_OK;
  324. __HCP_FUNC_CLEANUP;
  325. __HCP_FUNC_EXIT(hr);
  326. }
  327. ////////////////////
  328. STDMETHODIMP CPCHBehavior_TREE::Populate( /*[in]*/ VARIANT newVal )
  329. {
  330. __HCP_FUNC_ENTRY( "CPCHBehavior_TREE::Populate" );
  331. HRESULT hr;
  332. CComPtr<IXMLDOMNode> xdnRoot;
  333. MPC::SmartLock<_ThreadModel> lock( this ); WaitForRefreshing( lock );
  334. Empty();
  335. if(newVal.vt == VT_BSTR)
  336. {
  337. MPC::XmlUtil xmlutil;
  338. bool fLoaded;
  339. __MPC_EXIT_IF_METHOD_FAILS(hr, xmlutil.LoadAsString( newVal.bstrVal, L"NODE", fLoaded ));
  340. __MPC_EXIT_IF_METHOD_FAILS(hr, xmlutil.GetRoot( &xdnRoot ));
  341. }
  342. else if(newVal.vt == VT_UNKNOWN && newVal.punkVal)
  343. {
  344. __MPC_EXIT_IF_METHOD_FAILS(hr, newVal.punkVal->QueryInterface( __uuidof(xdnRoot), (void**)&xdnRoot ));
  345. }
  346. else if(newVal.vt == VT_DISPATCH && newVal.pdispVal)
  347. {
  348. __MPC_EXIT_IF_METHOD_FAILS(hr, newVal.punkVal->QueryInterface( __uuidof(xdnRoot), (void**)&xdnRoot ));
  349. }
  350. if(xdnRoot)
  351. {
  352. __MPC_EXIT_IF_METHOD_FAILS(hr, CPCHBehavior_TREE::TreeNode::PopulateFromXML( this, NULL, xdnRoot ));
  353. }
  354. Thread_Signal();
  355. hr = S_OK;
  356. __HCP_FUNC_CLEANUP;
  357. __HCP_FUNC_EXIT(hr);
  358. }
  359. ////////////////////////////////////////////////////////////////////////////////
  360. ////////////////////////////////////////////////////////////////////////////////
  361. CPCHBehavior_TREENODE::CPCHBehavior_TREENODE()
  362. {
  363. m_data = NULL; // CPCHBehavior_TREE::TreeNode* m_data;
  364. }
  365. CPCHBehavior_TREENODE::~CPCHBehavior_TREENODE()
  366. {
  367. MPC::Release( m_data );
  368. }
  369. STDMETHODIMP CPCHBehavior_TREENODE::get_Type ( /*[out, retval]*/ BSTR *pVal ) { return MPC::GetBSTR( CPCHBehavior_TREE::LookupType( m_data->m_iType ), pVal ); }
  370. STDMETHODIMP CPCHBehavior_TREENODE::get_Key ( /*[out, retval]*/ BSTR *pVal ) { return MPC::GetBSTR( m_data->m_bstrNode , pVal ); }
  371. STDMETHODIMP CPCHBehavior_TREENODE::get_Title ( /*[out, retval]*/ BSTR *pVal ) { return MPC::GetBSTR( m_data->m_bstrTitle , pVal ); }
  372. STDMETHODIMP CPCHBehavior_TREENODE::get_Description( /*[out, retval]*/ BSTR *pVal ) { return MPC::GetBSTR( m_data->m_bstrDescription , pVal ); }
  373. STDMETHODIMP CPCHBehavior_TREENODE::get_Icon ( /*[out, retval]*/ BSTR *pVal ) { return MPC::GetBSTR( m_data->m_bstrIcon , pVal ); }
  374. STDMETHODIMP CPCHBehavior_TREENODE::get_URL ( /*[out, retval]*/ BSTR *pVal ) { return MPC::GetBSTR( m_data->m_bstrURL , pVal ); }