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.

755 lines
22 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. /*++
  3. Copyright (c) 1997 Microsoft Corporation
  4. Module Name:
  5. snpres.h
  6. Abstract:
  7. This is the header file for CNodeWithResultChildrenList, a class which
  8. implements a node that has a list of scope pane children.
  9. This is an inline template class.
  10. Include NodeWithScopeChildrenList.cpp in the .cpp files
  11. of the classes in which you use this template.
  12. Author:
  13. Original: Michael A. Maguire
  14. Modifications: RaphiR
  15. Changes:
  16. Support for Extension snapins
  17. Jun 14 1999 roytal used UNREFERENCED_PARAMETER to fix build wrn
  18. // //
  19. // Sep 22 1999 yossg welcome To Fax Server //
  20. --*/
  21. //////////////////////////////////////////////////////////////////////////////
  22. #if !defined(_NODE_WITH_RESULT_CHILDREN_LIST_H_)
  23. #define _NODE_WITH_RESULT_CHILDREN_LIST_H_
  24. //////////////////////////////////////////////////////////////////////////////
  25. // BEGIN INCLUDES
  26. //
  27. // where we can find what this class derives from:
  28. //
  29. #include "snpnode.h"
  30. //
  31. //
  32. // where we can find what this class has or uses:
  33. //
  34. //
  35. // END INCLUDES
  36. //////////////////////////////////////////////////////////////////////////////
  37. template < class T, class CChildNode, class TArray, BOOL bIsExtension>
  38. class CNodeWithResultChildrenList : public CSnapinNode< T, bIsExtension>
  39. {
  40. // Constructor/Destructor
  41. public:
  42. CNodeWithResultChildrenList(CSnapInItem * pParentNode, CSnapin * pComponentData);
  43. ~CNodeWithResultChildrenList();
  44. // Child list management.
  45. public:
  46. // Flag indicating whether list has been initially populated
  47. BOOL m_bResultChildrenListPopulated;
  48. protected:
  49. // Override these in your derived classes
  50. virtual HRESULT InsertColumns( IHeaderCtrl* pHeaderCtrl );
  51. virtual HRESULT OnUnSelect( IHeaderCtrl* pHeaderCtrl );
  52. virtual HRESULT PopulateResultChildrenList(void );
  53. // Stuff which must be accessible to subclasses. These methods shouldn't need to be overidden.
  54. // zvib moved to public
  55. //virtual HRESULT RepopulateResultChildrenList(void);
  56. // virtual HRESULT AddChildToList( CChildNode * pChildNode );
  57. //virtual HRESULT EnumerateResultChildren( IResultData * pResultData );
  58. // zvib
  59. // Array of pointers to children nodes.
  60. // This is protected so that it can be visible in the derived classes.
  61. TArray m_ResultChildrenList;
  62. // Overrides for standard MMC functionality.
  63. public:
  64. virtual HRESULT RepopulateResultChildrenList(void);
  65. virtual HRESULT EnumerateResultChildren( IResultData * pResultData );
  66. virtual HRESULT AddChildToList( CChildNode * pChildNode );
  67. //////////////////////////////////////////////////////////////////////////////
  68. /*++
  69. CNodeWithScopeChildrenList::RemoveChild
  70. Removes a child from the list of children.
  71. This has to be public so that child nodes can ask their parent to be deleted
  72. from the list of children when they receive the MMCN_DELETE notification.
  73. --*/
  74. //////////////////////////////////////////////////////////////////////////////
  75. virtual HRESULT RemoveChild( CChildNode * pChildNode );
  76. virtual HRESULT OnShow(
  77. LPARAM arg
  78. , LPARAM param
  79. , IComponentData * pComponentData
  80. , IComponent * pComponent
  81. , DATA_OBJECT_TYPES type
  82. );
  83. virtual HRESULT OnRefresh(
  84. LPARAM arg
  85. , LPARAM param
  86. , IComponentData * pComponentData
  87. , IComponent * pComponent
  88. , DATA_OBJECT_TYPES type
  89. );
  90. virtual HRESULT DoRefresh(CSnapInObjectRootBase *pRoot);
  91. };
  92. //////////////////////////////////////////////////////////////////////////////
  93. /*++
  94. CNodeWithResultChildrenList::InsertColumns
  95. Override this in your derived class.
  96. This method is called by OnShow when it needs you to set the appropriate
  97. column headers to be displayed in the result pane for this node.
  98. --*/
  99. //////////////////////////////////////////////////////////////////////////////
  100. template <class T, class CChildNode, class TArray, BOOL bIsExtension>
  101. HRESULT CNodeWithResultChildrenList<T,CChildNode,TArray,bIsExtension>::InsertColumns( IHeaderCtrl* pHeaderCtrl )
  102. {
  103. DEBUG_FUNCTION_NAME(
  104. _T("CNodeWithResultChildrenList::InsertColumns -- override in your derived class"));
  105. // Check for preconditions:
  106. _ASSERTE( pHeaderCtrl );
  107. HRESULT hr;
  108. // override in your derived class and do something like:
  109. hr = pHeaderCtrl->InsertColumn( 0, L"@Column 1 -- override CNodeWithResultChildrenList::OnShowInsertColumns", 0, 120 );
  110. _ASSERT( S_OK == hr );
  111. hr = pHeaderCtrl->InsertColumn( 1, L"@Column 2 -- override CNodeWithResultChildrenList::OnShowInsertColumns", 0, 300 );
  112. _ASSERT( S_OK == hr );
  113. return hr;
  114. }
  115. //////////////////////////////////////////////////////////////////////////////
  116. /*++
  117. CNodeWithResultChildrenList::OnUnSelect
  118. Override this in your derived class.
  119. This method is called by OnShow when the node is unselected.
  120. Useful to overidde this if you want to retreive columns header width for example
  121. --*/
  122. //////////////////////////////////////////////////////////////////////////////
  123. template <class T, class CChildNode, class TArray, BOOL bIsExtension>
  124. HRESULT CNodeWithResultChildrenList<T,CChildNode,TArray,bIsExtension>::OnUnSelect( IHeaderCtrl* pHeaderCtrl )
  125. {
  126. DEBUG_FUNCTION_NAME(
  127. _T("CNodeWithResultChildrenList::OnUnSelect -- override in your derived class"));
  128. UNREFERENCED_PARAMETER (pHeaderCtrl);
  129. // Check for preconditions:
  130. _ASSERTE( pHeaderCtrl != NULL );
  131. HRESULT hr = S_OK;
  132. return hr;
  133. }
  134. //////////////////////////////////////////////////////////////////////////////
  135. /*++
  136. CNodeWithResultChildrenList::PopulateResultChildrenList
  137. Override this in your derived class.
  138. This is called by EnumerateResultChildren which is called by OnShow when
  139. you need to populate the list of children of this node.
  140. --*/
  141. //////////////////////////////////////////////////////////////////////////////
  142. template <class T, class CChildNode, class TArray, BOOL bIsExtension>
  143. HRESULT CNodeWithResultChildrenList<T,CChildNode,TArray,bIsExtension>::PopulateResultChildrenList( void )
  144. {
  145. DEBUG_FUNCTION_NAME(
  146. _T("CNodeWithResultChildrenList::PopulateResultChildrenList -- override in your derived class"));
  147. // Check for preconditions:
  148. // None.
  149. // override in your derived class and do something like:
  150. /*
  151. CSomeChildNode *myChild1 = new CSomeChildNode();
  152. AddChildToList(myChild1);
  153. CSomeChildNode *myChild2 = new CSomeChildNode();
  154. AddChildToList(myChild2);
  155. CSomeChildNode *myChild3 = new CSomeChildNode();
  156. AddChildToList(myChild3);
  157. */
  158. return S_OK;
  159. }
  160. //////////////////////////////////////////////////////////////////////////////
  161. /*++
  162. CNodeWithResultChildrenList::RepopulateResultChildrenList
  163. DON'T Override this in your derived class.
  164. Call this to empty the list of children and repopulate it.
  165. This method will call PopulateResultChildrenList, which you should override.
  166. --*/
  167. //////////////////////////////////////////////////////////////////////////////
  168. template <class T, class CChildNode, class TArray, BOOL bIsExtension>
  169. HRESULT CNodeWithResultChildrenList<T,CChildNode,TArray,bIsExtension>::RepopulateResultChildrenList(void)
  170. {
  171. DEBUG_FUNCTION_NAME( _T("CNodeWithResultChildrenList<..>::RepopulateResultChildrenList"));
  172. HRESULT hr;
  173. // Check for preconditions:
  174. // None.
  175. //
  176. // Clear our node list [Michael A. Maguire]
  177. //
  178. // Get rid of what we had.
  179. // Delete each node in the list of children
  180. CChildNode* pChildNode;
  181. int iSize = m_ResultChildrenList.GetSize();
  182. for (int i = 0; i < iSize; i++)
  183. {
  184. pChildNode = m_ResultChildrenList[i];
  185. delete pChildNode;
  186. }
  187. // Empty the list
  188. m_ResultChildrenList.RemoveAll();
  189. //
  190. // Update the views after the children removal
  191. //
  192. _ASSERTE( m_pComponentData != NULL );
  193. _ASSERTE( m_pComponentData->m_spConsole != NULL );
  194. m_pComponentData->m_spConsole->UpdateAllViews( NULL,(LPARAM) this, NULL);
  195. // We no longer have a populated list.
  196. m_bResultChildrenListPopulated = FALSE;
  197. // Repopulate the list.
  198. hr = PopulateResultChildrenList();
  199. // We've already loaded our children ClientNode objects with
  200. // data necessary to populate the result pane.
  201. m_bResultChildrenListPopulated = TRUE; // We only want to do this once.
  202. return hr;
  203. }
  204. //////////////////////////////////////////////////////////////////////////////
  205. /*++
  206. CNodeWithResultChildrenList::CNodeWithResultChildrenList
  207. Constructor
  208. --*/
  209. //////////////////////////////////////////////////////////////////////////////
  210. template <class T, class CChildNode, class TArray, BOOL bIsExtension>
  211. CNodeWithResultChildrenList<T,CChildNode, TArray,bIsExtension>::CNodeWithResultChildrenList(CSnapInItem * pParentNode, CSnapin * pComponentData): CSnapinNode<T,bIsExtension>(pParentNode, pComponentData)
  212. {
  213. DEBUG_FUNCTION_NAME(
  214. _T("CNodeWithResultChildrenList::CNodeWithResultChildrenList"));
  215. // Check for preconditions:
  216. // None.
  217. // We have not yet loaded the child nodes' data
  218. m_bResultChildrenListPopulated = FALSE;
  219. }
  220. //////////////////////////////////////////////////////////////////////////////
  221. /*++
  222. CNodeWithResultChildrenList::~CNodeWithResultChildrenList
  223. Destructor
  224. --*/
  225. //////////////////////////////////////////////////////////////////////////////
  226. template <class T, class CChildNode, class TArray, BOOL bIsExtension>
  227. CNodeWithResultChildrenList<T,CChildNode,TArray,bIsExtension>::~CNodeWithResultChildrenList()
  228. {
  229. DEBUG_FUNCTION_NAME(
  230. _T("CNodeWithResultChildrenList::~CNodeWithResultChildrenList"));
  231. // Check for preconditions:
  232. // None.
  233. // Delete each node in the list of children
  234. CChildNode* pChildNode;
  235. int iSize = m_ResultChildrenList.GetSize();
  236. for (int i = 0; i < iSize; i++)
  237. {
  238. pChildNode = m_ResultChildrenList[i];
  239. delete pChildNode;
  240. }
  241. // Empty the list
  242. m_ResultChildrenList.RemoveAll();
  243. }
  244. //////////////////////////////////////////////////////////////////////////////
  245. /*++
  246. CNodeWithResultChildrenList::AddChildToList
  247. Adds a child to the list of children. Does not cause a view update.
  248. Use this in your PopulateResultChildrenList method.
  249. --*/
  250. //////////////////////////////////////////////////////////////////////////////
  251. template <class T, class CChildNode, class TArray, BOOL bIsExtension>
  252. HRESULT CNodeWithResultChildrenList<T,CChildNode, TArray, bIsExtension>::AddChildToList( CChildNode * pChildNode )
  253. {
  254. // Check for preconditions:
  255. // None.
  256. HRESULT hr = S_OK;
  257. if( m_ResultChildrenList.Add(pChildNode ) )
  258. {
  259. hr = S_OK;
  260. }
  261. else
  262. {
  263. // Failed to add => out of memory
  264. hr = E_OUTOFMEMORY;
  265. }
  266. return hr;
  267. }
  268. //////////////////////////////////////////////////////////////////////////////
  269. /*++
  270. CNodeWithResultChildrenList::OnShow
  271. Don't override this in your derived class. Instead, override methods
  272. which it calls: InsertColumns and (indirectly) PopulateResultChildrenList
  273. This method is an override of CSnapinNode::OnShow. When MMC passes the
  274. MMCN_SHOW method for this node, we are to add children into the
  275. result pane. In this class we add them from a list we maintain.
  276. For more information, see CSnapinNode::OnShow.
  277. --*/
  278. //////////////////////////////////////////////////////////////////////////////
  279. template <class T, class CChildNode, class TArray, BOOL bIsExtension>
  280. HRESULT CNodeWithResultChildrenList<T,CChildNode,TArray,bIsExtension>::OnShow(
  281. LPARAM arg
  282. , LPARAM param
  283. , IComponentData * pComponentData
  284. , IComponent * pComponent
  285. , DATA_OBJECT_TYPES type
  286. )
  287. {
  288. DEBUG_FUNCTION_NAME(
  289. _T("CNodeWithResultChildrenList::OnShow"));
  290. UNREFERENCED_PARAMETER (param);
  291. UNREFERENCED_PARAMETER (type);
  292. // Check for preconditions:
  293. _ASSERTE( pComponentData != NULL || pComponent != NULL );
  294. HRESULT hr = S_FALSE;
  295. T * pT = static_cast<T*>( this );
  296. // Need IHeaderCtrl.
  297. // But to get that, first we need IConsole
  298. CComPtr<IConsole> spConsole;
  299. if( pComponentData != NULL )
  300. {
  301. spConsole = ((CSnapin*)pComponentData)->m_spConsole;
  302. }
  303. else
  304. {
  305. // We should have a non-null pComponent
  306. spConsole = ((CSnapinComponent*)pComponent)->m_spConsole;
  307. }
  308. _ASSERTE( spConsole != NULL );
  309. CComQIPtr<IHeaderCtrl, &IID_IHeaderCtrl> spHeaderCtrl(spConsole);
  310. _ASSERT( spHeaderCtrl != NULL );
  311. if( arg )
  312. {
  313. // arg <> 0 => we are being selected.
  314. // Note: This method will only get called with
  315. // arg <> 0 (i.e. selected) if you responded appropriately to
  316. // the MMCN_ADD_IMAGES method
  317. // We have been asked to display result pane nodes belonging under this node.
  318. // It appears we must do IResultData->InsertItems each time we receive
  319. // the MMCN_SHOW message -- MMC doesn't remember what nodes
  320. // we have previously inserted.
  321. // Set the column headers in the results pane
  322. // Note: if you don't set these, MMC will never
  323. // bother to put up your result-pane only items
  324. // When this Notify method is called from IComponentDataImpl, we
  325. // get pHeader (and pToolbar) passed in as NULL, so we aren't
  326. // going to bother using it and will instead always
  327. // QI pConsole for this pointer
  328. hr = pT->InsertColumns( spHeaderCtrl );
  329. _ASSERT( S_OK == hr );
  330. // Display our list of children in the result pane
  331. // Need IResultData
  332. CComQIPtr<IResultData, &IID_IResultData> spResultData(spConsole);
  333. _ASSERT( spResultData != NULL );
  334. hr = pT->EnumerateResultChildren(spResultData );
  335. }
  336. else
  337. {
  338. //
  339. // We are unselected
  340. //
  341. hr = OnUnSelect(spHeaderCtrl);
  342. _ASSERT( S_OK == hr );
  343. }
  344. return hr;
  345. }
  346. //////////////////////////////////////////////////////////////////////////////
  347. template <class T, class CChildNode, class TArray, BOOL bIsExtension>
  348. HRESULT CNodeWithResultChildrenList<T,CChildNode,TArray,bIsExtension>::DoRefresh(CSnapInObjectRootBase *pRoot)
  349. {
  350. CComPtr<IConsole> spConsole;
  351. //
  352. // Repopulate childs
  353. //
  354. RepopulateResultChildrenList();
  355. if (pRoot)
  356. {
  357. //
  358. // Get the console pointer
  359. //
  360. ATLASSERT(pRoot->m_nType == 1 || pRoot->m_nType == 2);
  361. if (pRoot->m_nType == 1)
  362. {
  363. //
  364. // m_ntype == 1 means the IComponentData implementation
  365. //
  366. CSnapin *pCComponentData = static_cast<CSnapin *>(pRoot);
  367. spConsole = pCComponentData->m_spConsole;
  368. }
  369. else
  370. {
  371. //
  372. // m_ntype == 2 means the IComponent implementation
  373. //
  374. CSnapinComponent *pCComponent = static_cast<CSnapinComponent *>(pRoot);
  375. spConsole = pCComponent->m_spConsole;
  376. }
  377. }
  378. else
  379. {
  380. ATLASSERT(m_pComponentData);
  381. spConsole = m_pComponentData->m_spConsole;
  382. }
  383. ATLASSERT(spConsole);
  384. spConsole->UpdateAllViews(NULL, NULL, NULL);
  385. return S_OK;
  386. }
  387. /////////////////////////////////////////////////////////////////////////////
  388. /*++
  389. CNodeWithResultChildrenList::OnRefresh
  390. You shouldn't need to override this in your derived method. Simply
  391. enable the MMC_VERB_REFRESH for your node.
  392. In our implementation, this method gets called when the MMCN_REFRESH
  393. Notify message is sent for this node.
  394. For more information, see CSnapinNode::OnRefresh.
  395. --*/
  396. //////////////////////////////////////////////////////////////////////////////
  397. template <class T, class CChildNode, class TArray, BOOL bIsExtension>
  398. HRESULT CNodeWithResultChildrenList<T,CChildNode,TArray,bIsExtension>::OnRefresh(
  399. LPARAM arg
  400. , LPARAM param
  401. , IComponentData * pComponentData
  402. , IComponent * pComponent
  403. , DATA_OBJECT_TYPES type
  404. )
  405. {
  406. DEBUG_FUNCTION_NAME(
  407. _T("CNodeWithResultChildrenList::OnRefresh"));
  408. UNREFERENCED_PARAMETER (arg);
  409. UNREFERENCED_PARAMETER (param);
  410. UNREFERENCED_PARAMETER (pComponentData);
  411. UNREFERENCED_PARAMETER (pComponent);
  412. UNREFERENCED_PARAMETER (type);
  413. HRESULT hr;
  414. // Rebuild our list of nodes from the uderlying data source.
  415. T * pT = static_cast<T*> (this);
  416. hr = pT->RepopulateResultChildrenList();
  417. // Update the views.
  418. // We weren't passed an IConsole pointer here, so
  419. // we use the one we saved in out CComponentData object.
  420. _ASSERTE( m_pComponentData != NULL );
  421. _ASSERTE( m_pComponentData->m_spConsole != NULL );
  422. // We pass in a pointer to 'this' because we want each
  423. // of our CComponent objects to update its result pane
  424. // view if 'this' node is the same as the saved currently
  425. // selected node.
  426. m_pComponentData->m_spConsole->UpdateAllViews( NULL,(LPARAM) this, NULL);
  427. return hr;
  428. }
  429. //////////////////////////////////////////////////////////////////////////////
  430. /*++
  431. CNodeWithResultChildrenList::EnumerateResultChildren
  432. Don't override this in your derived class. Instead, override the method
  433. it calls, PopulateResultChildrenList.
  434. This is called by the OnShow method.
  435. --*/
  436. //////////////////////////////////////////////////////////////////////////////
  437. template <class T, class CChildNode, class TArray, BOOL bIsExtension>
  438. HRESULT CNodeWithResultChildrenList<T,CChildNode,TArray,bIsExtension>::EnumerateResultChildren( IResultData * pResultData )
  439. {
  440. DEBUG_FUNCTION_NAME(
  441. _T("CNodeWithResultChildrenList::EnumerateResultChildren"));
  442. // Check for preconditions:
  443. _ASSERTE( pResultData != NULL );
  444. HRESULT hr = S_OK;
  445. T * pT = static_cast<T*> (this);
  446. if ( FALSE == m_bResultChildrenListPopulated )
  447. {
  448. // We have not yet loaded all of our children into our list.
  449. // This call will add items to the list from whatever data source.
  450. hr = pT->PopulateResultChildrenList();
  451. if( FAILED(hr) )
  452. {
  453. return( hr );
  454. }
  455. // We've already loaded our children ClientNode objects with
  456. // data necessary to populate the result pane.
  457. m_bResultChildrenListPopulated = TRUE; // We only want to do this once.
  458. }
  459. // From MeanGene's Step4 -- need to first remove all items from result pane
  460. hr = pResultData->DeleteAllRsltItems();
  461. if( FAILED(hr) )
  462. {
  463. return hr;
  464. }
  465. // The ResultChildrenList is already populated, so we
  466. // just need to show the CChildNode objects to the world
  467. // by populating the result pane.
  468. CChildNode* pChildNode;
  469. for (int i = 0; i < m_ResultChildrenList.GetSize(); i++)
  470. {
  471. pChildNode = m_ResultChildrenList[i];
  472. if ( NULL == pChildNode )
  473. {
  474. continue;
  475. }
  476. // Insert the item into the result pane.
  477. hr = pResultData->InsertItem( &(pChildNode->m_resultDataItem) );
  478. if (FAILED(hr))
  479. {
  480. return hr;
  481. }
  482. // Check: On return, the itemID member of 'm_resultDataItem'
  483. // contains the handle to the newly inserted item.
  484. _ASSERT( NULL != pChildNode->m_resultDataItem.itemID );
  485. }
  486. return hr;
  487. }
  488. //////////////////////////////////////////////////////////////////////////////
  489. /*++
  490. CNodeWithResultChildrenList::RemoveChild
  491. Removes a child from the list of children.
  492. This is declared public because it must be accessed from a child node when that
  493. node receives the MMCN_DELETE message and tries to delete itself.
  494. --*/
  495. //////////////////////////////////////////////////////////////////////////////
  496. template <class T, class CChildNode, class TArray, BOOL bIsExtension>
  497. HRESULT CNodeWithResultChildrenList<T,CChildNode,TArray,bIsExtension>::RemoveChild( CChildNode * pChildNode )
  498. {
  499. DEBUG_FUNCTION_NAME(
  500. _T("CNodeWithResultChildrenList::RemoveChild"));
  501. // Check for preconditions:
  502. // None.
  503. HRESULT hr = S_OK;
  504. if( m_ResultChildrenList.Remove( pChildNode ) )
  505. {
  506. // We don't remove the item directly from the result pane now
  507. // using IResultData->RemoveItem, as we have no way of
  508. // removing it from all the possible views.
  509. // Instead, we call IConsole->UpdateAllViews which will
  510. // cause MMC to call Notify on each of our IComponent objects
  511. // with the MMCN_VIEW_CHANGE notification, and we will
  512. // repopulate the result view when we handle that notification.
  513. // We weren't passed an IConsole pointer here, so
  514. // we use the one we saved in out CComponentData object.
  515. _ASSERTE( m_pComponentData != NULL );
  516. _ASSERTE( m_pComponentData->m_spConsole != NULL );
  517. // We pass in a pointer to 'this' because we want each
  518. // of our CComponent objects to update its result pane
  519. // view if 'this' node is the same as the saved currently
  520. // selected node.
  521. m_pComponentData->m_spConsole->UpdateAllViews( NULL,(LPARAM) this, NULL);
  522. }
  523. else
  524. {
  525. // If we failed to remove, probably the child was never in the list
  526. // ISSUE: determine what do here -- this should never happen
  527. _ASSERTE( FALSE );
  528. hr = S_FALSE;
  529. }
  530. return hr;
  531. }
  532. #endif // _NODE_WITH_RESULT_CHILDREN_LIST_H_