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.

3769 lines
102 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1999 - 1999
  6. //
  7. // File: scoptree.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. #include "stdafx.h"
  11. #include "scopiter.h"
  12. #include "scopndcb.h"
  13. #include "addsnpin.h"
  14. #include "ScopImag.h"
  15. #include "NodeMgr.h"
  16. #include "amcmsgid.h"
  17. #include "regutil.h"
  18. #include "copypast.h"
  19. #include "multisel.h"
  20. #include "nodepath.h"
  21. #include "tasks.h"
  22. #include "colwidth.h"
  23. #include "viewpers.h"
  24. #include <comdbg.h>
  25. #include "conframe.h"
  26. #include "siprop.h"
  27. #include "fldrsnap.h"
  28. #include "variant.h"
  29. #include "condoc.h"
  30. #include "oncmenu.h"
  31. #include "conview.h"
  32. #include "eventlock.h"
  33. #ifdef _DEBUG
  34. #undef THIS_FILE
  35. static char THIS_FILE[] = __FILE__;
  36. #endif
  37. #ifdef DBG
  38. CTraceTag tagScopeTreeAddSnapin(TEXT("CScopeTree"), TEXT("ScAddSnapIn"));
  39. #endif
  40. //############################################################################
  41. //############################################################################
  42. //
  43. // Implementation of class CSnapIns
  44. //
  45. //############################################################################
  46. //############################################################################
  47. /*+-------------------------------------------------------------------------*
  48. * class CSnapIns
  49. *
  50. *
  51. * PURPOSE: Implements the SnapIns automation interface.
  52. *
  53. *+-------------------------------------------------------------------------*/
  54. class _CSnapIns :
  55. public CMMCIDispatchImpl<SnapIns>,
  56. public CTiedComObject<CScopeTree>
  57. {
  58. public:
  59. typedef CScopeTree CMyTiedObject;
  60. public:
  61. BEGIN_MMC_COM_MAP(_CSnapIns)
  62. END_MMC_COM_MAP()
  63. // SnapIns interface
  64. public:
  65. MMC_METHOD4(Add, BSTR /*bstrSnapinNameOrCLSID*/, VARIANT /*varParentSnapinNode*/, VARIANT /*varProperties*/, PPSNAPIN /*ppSnapIn*/);
  66. MMC_METHOD2(Item, long /*Index*/, PPSNAPIN /*ppSnapIn*/);
  67. MMC_METHOD1(Remove, PSNAPIN /*pSnapIn*/)
  68. MMC_METHOD1(get_Count, PLONG /*pCount*/);
  69. IUnknown *STDMETHODCALLTYPE get__NewEnum() {return NULL;}
  70. };
  71. // this typedefs the real CSnapIns class. Implements get__NewEnum using CMMCEnumerator and a CSnapIns_Positon object
  72. typedef CMMCNewEnumImpl<_CSnapIns, CScopeTree::CSnapIns_Positon> CSnapIns;
  73. //############################################################################
  74. //############################################################################
  75. //
  76. // Implementation of class CScopeNamespace
  77. //
  78. //############################################################################
  79. //############################################################################
  80. /*+-------------------------------------------------------------------------*
  81. * class CScopeNamespace
  82. *
  83. *
  84. * PURPOSE: Implements the ScopeNamespace automation interface.
  85. *
  86. *+-------------------------------------------------------------------------*/
  87. class CScopeNamespace :
  88. public CMMCIDispatchImpl<ScopeNamespace>,
  89. public CTiedComObject<CScopeTree>
  90. {
  91. protected:
  92. typedef CScopeTree CMyTiedObject;
  93. public:
  94. BEGIN_MMC_COM_MAP(CScopeNamespace)
  95. END_MMC_COM_MAP()
  96. // ScopeNamespace interface
  97. public:
  98. MMC_METHOD2(GetParent, PNODE /*pNode*/, PPNODE /*ppParent*/);
  99. MMC_METHOD2(GetChild, PNODE /*pNode*/, PPNODE /*ppChild*/);
  100. MMC_METHOD2(GetNext, PNODE /*pNode*/, PPNODE /*ppNext*/);
  101. MMC_METHOD1(GetRoot, PPNODE /*ppRoot*/);
  102. MMC_METHOD1(Expand, PNODE /*pNode*/);
  103. };
  104. //############################################################################
  105. //############################################################################
  106. //
  107. // Implementation of class CMMCScopeNode
  108. //
  109. //############################################################################
  110. //############################################################################
  111. /*+-------------------------------------------------------------------------*
  112. *
  113. * CMMCScopeNode::~CMMCScopeNode
  114. *
  115. * PURPOSE: Destructor
  116. *
  117. * PARAMETERS:
  118. *
  119. * RETURNS:
  120. *
  121. *+-------------------------------------------------------------------------*/
  122. CMMCScopeNode::~CMMCScopeNode()
  123. {
  124. DECLARE_SC(sc, TEXT("CMMCScopeNode::~CMMCScopeNode"));
  125. CScopeTree *pScopeTree = CScopeTree::GetScopeTree();
  126. sc = ScCheckPointers(pScopeTree, E_UNEXPECTED);
  127. if (!sc)
  128. {
  129. sc = pScopeTree->ScUnadviseMMCScopeNode(this);
  130. }
  131. }
  132. /*+-------------------------------------------------------------------------*
  133. *
  134. * CMMCScopeNode::ScIsValid
  135. *
  136. * PURPOSE: Returns an error if the COM object is no longer valid.
  137. *
  138. * RETURNS:
  139. * SC
  140. *
  141. *+-------------------------------------------------------------------------*/
  142. SC
  143. CMMCScopeNode::ScIsValid()
  144. {
  145. DECLARE_SC(sc, TEXT("CMMCScopeNode::ScIsValid"));
  146. if(!GetMTNode())
  147. return (sc = E_INVALIDARG);
  148. return sc;
  149. }
  150. /*+-------------------------------------------------------------------------*
  151. *
  152. * CMMCScopeNode::get_Name
  153. *
  154. * PURPOSE: Returns the display name of the node.
  155. *
  156. * PARAMETERS:
  157. * PBSTR pbstrName :
  158. *
  159. * RETURNS:
  160. * STDMETHODIMP
  161. *
  162. *+-------------------------------------------------------------------------*/
  163. STDMETHODIMP
  164. CMMCScopeNode::get_Name( PBSTR pbstrName)
  165. {
  166. DECLARE_SC(sc, TEXT("CMMCScopeNode::get_Name"));
  167. // check parameters
  168. if (!pbstrName)
  169. return ((sc = E_INVALIDARG).ToHr());
  170. CMTNode* pMTNode = GetMTNode();
  171. sc = ScCheckPointers (pMTNode, E_UNEXPECTED);
  172. if (sc)
  173. return (sc.ToHr());
  174. tstring strName = pMTNode->GetDisplayName();
  175. USES_CONVERSION;
  176. *pbstrName = ::SysAllocString (T2COLE(strName.data())); // caller frees
  177. return sc.ToHr();
  178. }
  179. /*+-------------------------------------------------------------------------*
  180. *
  181. * CMMCScopeNode::ScGetDataObject
  182. *
  183. * PURPOSE: Returns the data object for a scope node.
  184. *
  185. * PARAMETERS:
  186. * IDataObject ** ppDataObject :
  187. *
  188. * RETURNS:
  189. * SC
  190. *
  191. *+-------------------------------------------------------------------------*/
  192. SC
  193. CMMCScopeNode::ScGetDataObject(IDataObject **ppDataObject)
  194. {
  195. DECLARE_SC(sc, TEXT("CMMCScopeNode::ScGetDataObject"));
  196. sc = ScCheckPointers(ppDataObject);
  197. if(sc)
  198. return sc;
  199. // init out parameter
  200. *ppDataObject = NULL;
  201. // get the MT node
  202. CMTNode *pMTNode = GetMTNode();
  203. sc = ScCheckPointers( pMTNode, E_UNEXPECTED );
  204. if(sc)
  205. return sc;
  206. CComponentData* pCCD = pMTNode->GetPrimaryComponentData();
  207. sc = ScCheckPointers( pCCD, E_NOTIMPL ); // no component data -> no property...
  208. if(sc)
  209. return sc;
  210. // ensure node is expanded before requesting data object
  211. if (pMTNode->WasExpandedAtLeastOnce() == FALSE)
  212. pMTNode->Expand();
  213. // Get the data object for the cookie from the owner snap-in
  214. sc = pCCD->QueryDataObject(pMTNode->GetUserParam(), CCT_SCOPE, ppDataObject);
  215. return sc;
  216. }
  217. /***************************************************************************\
  218. *
  219. * METHOD: CMMCScopeNode::get_Property
  220. *
  221. * PURPOSE: returns snapins property for scope node
  222. *
  223. * PARAMETERS:
  224. * BSTR bstrPropertyName -[in] property name (clipboard format)
  225. * PBSTR pbstrPropertyValue -[out] property value
  226. *
  227. * RETURNS:
  228. * HRESULT - result code
  229. *
  230. \***************************************************************************/
  231. STDMETHODIMP
  232. CMMCScopeNode::get_Property( BSTR bstrPropertyName, PBSTR pbstrPropertyValue )
  233. {
  234. DECLARE_SC(sc, TEXT("CMMCScopeNode::get_Property"));
  235. // parameter check
  236. sc = ScCheckPointers(bstrPropertyName, pbstrPropertyValue);
  237. if (sc)
  238. return sc.ToHr();
  239. // init out parameter
  240. *pbstrPropertyValue = NULL;
  241. IDataObjectPtr spDataObject;
  242. sc = ScGetDataObject(&spDataObject);
  243. if(sc)
  244. return sc.ToHr();
  245. // get the MT node
  246. CMTNode *pMTNode = GetMTNode();
  247. sc = ScCheckPointers( pMTNode, E_UNEXPECTED );
  248. if(sc)
  249. return sc.ToHr();
  250. // try to get the property from the INodeProperties interface
  251. sc = pMTNode->ScGetPropertyFromINodeProperties(spDataObject, bstrPropertyName, pbstrPropertyValue);
  252. if( (!sc.IsError()) && (sc != S_FALSE) ) // got it, exit
  253. return sc.ToHr();
  254. // didn't find it, continue
  255. sc.Clear();
  256. // get the property from data object
  257. sc = CNodeCallback::ScGetProperty(spDataObject, bstrPropertyName, pbstrPropertyValue);
  258. if(sc)
  259. return sc.ToHr();
  260. return sc.ToHr();
  261. }
  262. /*+-------------------------------------------------------------------------*
  263. *
  264. * CMMCScopeNode::get_Bookmark
  265. *
  266. * PURPOSE: Returns the bookmark of the node (XML format).
  267. *
  268. * PARAMETERS:
  269. * PBSTR pbstrBookmark :
  270. *
  271. * RETURNS:
  272. * STDMETHODIMP
  273. *
  274. *+-------------------------------------------------------------------------*/
  275. STDMETHODIMP
  276. CMMCScopeNode::get_Bookmark( PBSTR pbstrBookmark )
  277. {
  278. DECLARE_SC(sc, TEXT("CMMCScopeNode::get_Bookmark"));
  279. // parameter checking
  280. sc = ScCheckPointers( pbstrBookmark );
  281. if(sc)
  282. return sc.ToHr();
  283. // cleanup result
  284. *pbstrBookmark = NULL;
  285. // get the MT node
  286. CMTNode *pMTNode = GetMTNode();
  287. sc = ScCheckPointers( pMTNode, E_FAIL );
  288. if(sc)
  289. return sc.ToHr();
  290. // get the pointer to bookmark
  291. CBookmark* pBookmark = pMTNode->GetBookmark();
  292. sc = ScCheckPointers( pBookmark, E_UNEXPECTED );
  293. if(sc)
  294. return sc.ToHr();
  295. std::wstring xml_contents;
  296. sc = pBookmark->ScSaveToString(&xml_contents);
  297. if(sc)
  298. return sc.ToHr();
  299. // store the result
  300. CComBSTR bstrBuff(xml_contents.c_str());
  301. *pbstrBookmark = bstrBuff.Detach();
  302. sc = ScCheckPointers( *pbstrBookmark, E_OUTOFMEMORY );
  303. if(sc)
  304. return sc.ToHr();
  305. return sc.ToHr();
  306. }
  307. /*+-------------------------------------------------------------------------*
  308. *
  309. * CMMCScopeNode::IsScopeNode
  310. *
  311. * PURPOSE: Returns TRUE indicating that the node is a scope node.
  312. *
  313. * PARAMETERS:
  314. * PBOOL pbIsScopeNode :
  315. *
  316. * RETURNS:
  317. * STDMETHODIMP
  318. *
  319. *+-------------------------------------------------------------------------*/
  320. STDMETHODIMP
  321. CMMCScopeNode::IsScopeNode(PBOOL pbIsScopeNode)
  322. {
  323. DECLARE_SC(sc, TEXT("CMMCScopeNode::IsScopeNode"));
  324. // check parameters
  325. if(!pbIsScopeNode)
  326. {
  327. sc = E_UNEXPECTED;
  328. return sc.ToHr();
  329. }
  330. *pbIsScopeNode = TRUE;
  331. return sc.ToHr();
  332. }
  333. /*+-------------------------------------------------------------------------*
  334. *
  335. * CMMCScopeNode::get_Nodetype
  336. *
  337. * PURPOSE: Returns the nodetype of a scope node.
  338. *
  339. * PARAMETERS:
  340. * PBSTR Nodetype :
  341. *
  342. * RETURNS:
  343. * STDMETHODIMP
  344. *
  345. *+-------------------------------------------------------------------------*/
  346. STDMETHODIMP
  347. CMMCScopeNode::get_Nodetype(PBSTR Nodetype)
  348. {
  349. DECLARE_SC(sc, TEXT("CMMCScopeNode::get_Nodetype"));
  350. // parameter check
  351. sc = ScCheckPointers(Nodetype);
  352. if (sc)
  353. return sc.ToHr();
  354. // init out parameter
  355. *Nodetype = NULL;
  356. // get the data object
  357. IDataObjectPtr spDataObject;
  358. sc = ScGetDataObject(&spDataObject);
  359. if(sc)
  360. return sc.ToHr();
  361. // get the nodetype from the data object
  362. sc = CNodeCallback::ScGetNodetype(spDataObject, Nodetype);
  363. if(sc)
  364. return sc.ToHr();
  365. return sc.ToHr();
  366. }
  367. ///////////////////////////////////////////////////////////////////////////////
  368. //
  369. // Forward declaration of local function
  370. //
  371. static SC
  372. ScCreateMTNodeTree(PNEWTREENODE pNew, CMTNode* pmtnParent,
  373. CMTNode** ppNodeCreated);
  374. HRESULT AmcNodeWizard(MID_LIST NewNodeType, CMTNode* pNode, HWND hWnd);
  375. //////////////////////////////////////////////////////////////////////////////
  376. //
  377. // Public variables
  378. //
  379. const wchar_t* AMCSnapInCacheStreamName = L"cash";
  380. const wchar_t* AMCTaskpadListStreamName = L"TaskpadList";
  381. ///////////////////////////////////////////////////////////////////////////////
  382. //
  383. // Implementation of CScopeTree class
  384. //
  385. DEBUG_DECLARE_INSTANCE_COUNTER(CScopeTree);
  386. bool CScopeTree::m_fRequireSyncExpand = false;
  387. CScopeTree* CScopeTree::m_pScopeTree = NULL;
  388. IStringTablePrivatePtr CScopeTree::m_spStringTable;
  389. CScopeTree::CScopeTree()
  390. : m_pMTNodeRoot(NULL),
  391. m_pImageCache(NULL),
  392. m_pConsoleData(NULL),
  393. m_pConsoleTaskpads(NULL),
  394. m_pDefaultTaskpads(NULL)
  395. {
  396. DEBUG_INCREMENT_INSTANCE_COUNTER(CScopeTree);
  397. ASSERT (m_pScopeTree == NULL);
  398. m_pScopeTree = this;
  399. }
  400. CScopeTree::~CScopeTree()
  401. {
  402. /*
  403. * Clear out the string table interface (before Cleanup!) to keep
  404. * CMTNode dtors from removing their names from the string table.
  405. */
  406. m_spStringTable = NULL;
  407. Cleanup();
  408. ASSERT (m_pScopeTree == this);
  409. if (m_pScopeTree == this)
  410. m_pScopeTree = NULL;
  411. DEBUG_DECREMENT_INSTANCE_COUNTER(CScopeTree);
  412. }
  413. HRESULT CScopeTree::SetConsoleData(LPARAM lConsoleData)
  414. {
  415. m_pConsoleData = reinterpret_cast<SConsoleData*>(lConsoleData);
  416. return (S_OK);
  417. }
  418. extern const CLSID CLSID_FolderSnapin;
  419. /*+-------------------------------------------------------------------------*
  420. *
  421. * CScopeTree::GetRoot
  422. *
  423. * PURPOSE: Creates the root node if necessary, and returns it. The root node
  424. * is created using the built-in folder snap-in.
  425. *
  426. * PARAMETERS:
  427. * voi d :
  428. *
  429. * RETURNS:
  430. * CMTNode*. If unable to create the root node, the application will exit.
  431. *
  432. *+-------------------------------------------------------------------------*/
  433. CMTNode*
  434. CScopeTree::GetRoot(void)
  435. {
  436. DECLARE_SC(sc, TEXT("CScopeTree::GetRoot"));
  437. if (m_pMTNodeRoot == NULL)
  438. {
  439. CSnapInPtr spSI;
  440. IComponentDataPtr spIComponentData;
  441. CComponentData* pCCD = NULL;
  442. CStr rootName;
  443. // create a new CMTSnapInNode.
  444. // TODO: move this down below the CoCreateInstance and QI for
  445. // ISnapinProperties; if supported, create and pass CSnapinProperties
  446. // to CMTSnapInNode ctor.
  447. CMTSnapInNode *pMTSINodeRoot = new CMTSnapInNode(NULL);
  448. if(NULL == pMTSINodeRoot)
  449. {
  450. sc = E_OUTOFMEMORY;
  451. goto Error;
  452. }
  453. // Create an instance of the snapin
  454. sc = theApp.GetSnapInsCache()->ScGetSnapIn(CLSID_FolderSnapin, &spSI);
  455. if(sc)
  456. goto Error;
  457. sc = CoCreateInstance(CLSID_FolderSnapin, NULL, CLSCTX_INPROC_SERVER, IID_IComponentData, (void **)&spIComponentData);
  458. if(sc)
  459. goto Error;
  460. if(spIComponentData == NULL)
  461. {
  462. sc = E_OUTOFMEMORY;
  463. goto Error;
  464. }
  465. pMTSINodeRoot->SetPrimarySnapIn(spSI);
  466. pCCD = pMTSINodeRoot->GetPrimaryComponentData();
  467. if(!pCCD)
  468. {
  469. sc = E_UNEXPECTED;
  470. goto Error;
  471. }
  472. pCCD->SetIComponentData(spIComponentData);
  473. USES_CONVERSION;
  474. rootName.LoadString(GetStringModule(), IDS_ROOTFOLDER_NAME);
  475. //The code that follows makes use of knowledge of the Folder snapin internals.
  476. //There seems to be no easier way of doing this.
  477. // Need to prevent MMC from putting up the "Save File?" dialog every time.
  478. pMTSINodeRoot->OnRename(true, (LPOLESTR)T2COLE(rootName)); // clever, huh? This just renames the node to Console Root!
  479. pMTSINodeRoot->SetDisplayName(rootName); // this sets the dirty flag
  480. pMTSINodeRoot->SetDirty(false); // this clears it.
  481. // need to tell the snapin to reset its dirty flag - there seems to be no way to avoid this dynamic cast.
  482. CFolderSnapinData *pFolderSnapinpData = dynamic_cast<CFolderSnapinData *>(pCCD->GetIComponentData());
  483. if(!pFolderSnapinpData)
  484. {
  485. sc = E_UNEXPECTED;
  486. goto Error;
  487. }
  488. pMTSINodeRoot->SetPreloadRequired(true); // this is also part of the dirty flag check.
  489. pFolderSnapinpData->SetDirty(false); // clear the dirty flag on the snapin.
  490. theApp.GetSnapInsCache()->SetDirty(false); // need to clear the dirty bit on the snapin cache too.
  491. m_pMTNodeRoot = pMTSINodeRoot;
  492. }
  493. Cleanup:
  494. return m_pMTNodeRoot;
  495. Error:
  496. MMCErrorBox(sc);
  497. exit(1); // Fatal error - cannot continue.
  498. goto Cleanup;
  499. }
  500. STDMETHODIMP CScopeTree::Initialize(HWND hwndFrame, IStringTablePrivate* pStringTable)
  501. {
  502. CSnapInsCache* pSnapInsCache = NULL;
  503. /*
  504. * assume invalid argument
  505. */
  506. SC sc = E_INVALIDARG;
  507. if (hwndFrame == 0)
  508. goto Error;
  509. /*
  510. * assume out of memory from here on
  511. */
  512. sc = E_OUTOFMEMORY;
  513. pSnapInsCache = new CSnapInsCache;
  514. if (pSnapInsCache == NULL)
  515. goto Error;
  516. theApp.SetSnapInsCache(pSnapInsCache);
  517. m_pImageCache = new CSPImageCache();
  518. if (m_pImageCache == NULL)
  519. goto Error;
  520. ASSERT (pStringTable != NULL);
  521. ASSERT (m_spStringTable == NULL);
  522. m_spStringTable = pStringTable;
  523. // create the ctp list and default ctp list.
  524. ASSERT (m_pConsoleTaskpads == NULL);
  525. m_pConsoleTaskpads = new CConsoleTaskpadList;
  526. if (m_pConsoleTaskpads == NULL)
  527. goto Error;
  528. ASSERT (m_pDefaultTaskpads == NULL);
  529. m_pDefaultTaskpads = new CDefaultTaskpadList;
  530. if (m_pDefaultTaskpads == NULL)
  531. goto Error;
  532. /*
  533. * success!
  534. */
  535. return (S_OK);
  536. Error:
  537. /*
  538. * clean up everything that might have been allocated
  539. */
  540. theApp.SetSnapInsCache (NULL);
  541. m_spStringTable = NULL;
  542. delete m_pDefaultTaskpads; m_pDefaultTaskpads = NULL;
  543. delete m_pConsoleTaskpads; m_pConsoleTaskpads = NULL;
  544. SAFE_RELEASE (m_pImageCache);
  545. delete pSnapInsCache;
  546. TraceError (_T("CScopeTree::Initialize"), sc);
  547. return (sc.ToHr());
  548. }
  549. STDMETHODIMP CScopeTree::QueryIterator(IScopeTreeIter** ppIter)
  550. {
  551. if (ppIter == NULL)
  552. return E_POINTER;
  553. CComObject<CScopeTreeIterator>* pObject;
  554. CComObject<CScopeTreeIterator>::CreateInstance(&pObject);
  555. return pObject->QueryInterface(IID_IScopeTreeIter,
  556. reinterpret_cast<void**>(ppIter));
  557. }
  558. STDMETHODIMP CScopeTree::QueryNodeCallback(INodeCallback** ppNodeCallback)
  559. {
  560. if (ppNodeCallback == NULL)
  561. return E_POINTER;
  562. CComObject<CNodeCallback>* pObject;
  563. CComObject<CNodeCallback>::CreateInstance(&pObject);
  564. HRESULT hr = pObject->QueryInterface(IID_INodeCallback,
  565. reinterpret_cast<void**>(ppNodeCallback));
  566. if (*ppNodeCallback != NULL)
  567. (*ppNodeCallback)->Initialize(this);
  568. return hr;
  569. }
  570. STDMETHODIMP CScopeTree::CreateNode(HMTNODE hMTNode, LONG_PTR lViewData,
  571. BOOL fRootNode, HNODE* phNode)
  572. {
  573. if (hMTNode == NULL)
  574. return E_INVALIDARG;
  575. if (phNode == NULL)
  576. return E_POINTER;
  577. CViewData* pViewData = reinterpret_cast<CViewData*>(lViewData);
  578. ASSERT(IsBadReadPtr(pViewData, sizeof(*pViewData)) == 0);
  579. CMTNode* pMTNode = CMTNode::FromHandle(hMTNode);
  580. CNode* pNode = NULL;
  581. if (pMTNode != NULL)
  582. {
  583. pNode = pMTNode->GetNode(pViewData, fRootNode);
  584. *phNode = CNode::ToHandle(pNode);
  585. return S_OK;
  586. }
  587. return E_FAIL;
  588. }
  589. HRESULT CScopeTree::CloseView(int viewID)
  590. {
  591. if (m_pMTNodeRoot == NULL)
  592. return S_OK;
  593. HRESULT hr = m_pMTNodeRoot->CloseView(viewID);
  594. ASSERT(hr == S_OK);
  595. // Garbage collect view related column persistence data.
  596. CColumnPersistInfo* pColPersInfo = NULL;
  597. if ( (NULL != m_pConsoleData) && (NULL != m_pConsoleData->m_spPersistStreamColumnData) )
  598. {
  599. pColPersInfo = dynamic_cast<CColumnPersistInfo*>(
  600. static_cast<IPersistStream*>(m_pConsoleData->m_spPersistStreamColumnData));
  601. if (pColPersInfo)
  602. pColPersInfo->DeleteColumnDataOfView(viewID);
  603. }
  604. // Ask the CViewSettingsPersistor to cleanup data for this view.
  605. hr = CNode::ScDeleteViewSettings(viewID).ToHr();
  606. return hr == S_OK ? S_OK : E_FAIL;
  607. }
  608. HRESULT CScopeTree::DeleteView(int viewID)
  609. {
  610. if (m_pMTNodeRoot == NULL)
  611. return S_OK;
  612. HRESULT hr = m_pMTNodeRoot->DeleteView(viewID);
  613. ASSERT(hr == S_OK);
  614. return hr == S_OK ? S_OK : E_FAIL;
  615. }
  616. STDMETHODIMP CScopeTree::DestroyNode(HNODE hNode)
  617. {
  618. // convert to real type
  619. CNode* pNode = CNode::FromHandle(hNode);
  620. delete pNode;
  621. return S_OK;
  622. }
  623. HRESULT CScopeTree::HandsOffStorage()
  624. {
  625. // obsolete method.
  626. // this method is left here since we use IPersistStorage to export
  627. // persistence to CONUI side and we need to implement it.
  628. // But this interface will never be called to save data
  629. // [we will use CPersistor-based XML saving instead]
  630. // so the method will always fail.
  631. ASSERT(FALSE && "Should never come here");
  632. return E_NOTIMPL;
  633. }
  634. static const wchar_t* AMCSignatureStreamName = L"signature";
  635. static const long double dOldVersion10 = 0.00000015; // MMC version 1.0
  636. static const long double dOldVersion11 = 1.1; // MMC version 1.1
  637. static const BYTE byStreamVersionMagic = 0xFF;
  638. HRESULT CScopeTree::InitNew(IStorage *pStg)
  639. {
  640. ASSERT(m_spPersistData == NULL);
  641. ASSERT(pStg != NULL);
  642. if (pStg == NULL)
  643. return E_INVALIDARG;
  644. // Create the perist data interface and attach it to the storage
  645. CComObject<PersistData>* pPersistData;
  646. HRESULT hr = CComObject<PersistData>::CreateInstance(&pPersistData);
  647. m_spPersistData = pPersistData;
  648. ASSERT(SUCCEEDED(hr) && m_spPersistData != NULL);
  649. if (FAILED(hr))
  650. return hr;
  651. hr = m_spPersistData->Create(pStg);
  652. ASSERT(SUCCEEDED(hr));
  653. if (FAILED(hr))
  654. return hr;
  655. CMTNode* const pRoot = GetRoot();
  656. ASSERT(pRoot != NULL);
  657. if (pRoot == NULL)
  658. return E_POINTER;
  659. hr = pRoot->InitNew(m_spPersistData);
  660. ASSERT(SUCCEEDED(hr));
  661. if (FAILED(hr))
  662. return hr;
  663. return S_OK;
  664. }
  665. HRESULT CScopeTree::IsDirty()
  666. {
  667. /*
  668. * check for dirty taskpads
  669. */
  670. CConsoleTaskpadList::iterator itDirty =
  671. std::find_if (m_pConsoleTaskpads->begin(),
  672. m_pConsoleTaskpads->end(),
  673. const_mem_fun_ref (&CConsoleTaskpad::IsDirty));
  674. if (itDirty != m_pConsoleTaskpads->end())
  675. {
  676. TraceDirtyFlag(TEXT("CScopeTree"), true);
  677. return (S_OK);
  678. }
  679. /*
  680. * check for dirty nodes
  681. */
  682. HRESULT hr;
  683. if (m_pMTNodeRoot != NULL)
  684. {
  685. hr = m_pMTNodeRoot->IsDirty();
  686. ASSERT(SUCCEEDED(hr));
  687. if (hr != S_FALSE)
  688. {
  689. TraceDirtyFlag(TEXT("CScopeTree"), true);
  690. return hr;
  691. }
  692. }
  693. /*
  694. * check for dirty snap-in cache
  695. */
  696. SC sc = theApp.GetSnapInsCache()->ScIsDirty();
  697. ASSERT(!sc.IsError());
  698. if(sc)
  699. return sc.ToHr();
  700. TraceDirtyFlag(TEXT("CScopeTree"), (sc==SC(S_OK)) ? true : false);
  701. return sc.ToHr();
  702. }
  703. HRESULT CScopeTree::GetFileVersion (IStorage* pstgRoot, int* pnVersion)
  704. {
  705. ASSERT(pstgRoot != NULL);
  706. if (pstgRoot == NULL)
  707. return MMC_E_INVALID_FILE;
  708. // Open the stream containing the signature
  709. IStreamPtr spStream;
  710. HRESULT hr = OpenDebugStream(pstgRoot, AMCSignatureStreamName,
  711. STGM_SHARE_EXCLUSIVE | STGM_READ, L"\\signature", &spStream);
  712. ASSERT(SUCCEEDED(hr) && spStream != NULL);
  713. if (FAILED(hr))
  714. return MMC_E_INVALID_FILE;
  715. /*
  716. * read the signature (stream extraction operators will throw
  717. * _com_error's, so we need an exception block here)
  718. */
  719. try
  720. {
  721. /*
  722. * MMC v1.2 and later write a marker as the first
  723. * byte of the signature stream.
  724. */
  725. BYTE byMagic;
  726. *spStream >> byMagic;
  727. /*
  728. * if this file was written by v1.2 or later,
  729. * read the console file version (int)
  730. */
  731. if (byMagic == byStreamVersionMagic)
  732. {
  733. *spStream >> *pnVersion;
  734. ASSERT (*pnVersion >= FileVer_0120);
  735. }
  736. /*
  737. * Otherwise, the file was written by v1.0 or v1.1.
  738. * Back up to re-read the marker byte, and read the old-style
  739. * file version (long double), then map it to a new-style version
  740. */
  741. else
  742. {
  743. LARGE_INTEGER pos = {0, 0};
  744. spStream->Seek (pos, STREAM_SEEK_SET, NULL);
  745. long double dVersion;
  746. *spStream >> dVersion;
  747. // v1.1?
  748. if (dVersion == dOldVersion11)
  749. *pnVersion = FileVer_0110;
  750. // v1.0?
  751. else if (dVersion == dOldVersion10)
  752. {
  753. /*
  754. * If we got a v1.0 signature, we still may have a v1.1 file.
  755. * There was a period of time where MMC v1.1 wrote a v1.0
  756. * signature, but the file format had in fact changed. We
  757. * can determine this by checking the \FrameData stream in
  758. * the file. If the first DWORD in the \FrameData stream is
  759. * sizeof(WINDOWPLACEMENT), we have a true v1.0 file, otherwise
  760. * it's a funky v1.1 file.
  761. */
  762. IStreamPtr spFrameDataStm;
  763. hr = OpenDebugStream (pstgRoot, L"FrameData",
  764. STGM_SHARE_EXCLUSIVE | STGM_READ,
  765. &spFrameDataStm);
  766. if (FAILED(hr))
  767. return MMC_E_INVALID_FILE;
  768. DWORD dw;
  769. *spFrameDataStm >> dw;
  770. if (dw == sizeof (WINDOWPLACEMENT))
  771. *pnVersion = FileVer_0100;
  772. else
  773. *pnVersion = FileVer_0110;
  774. }
  775. // unexpected version
  776. else
  777. {
  778. ASSERT (false && "Unexpected old-style signature");
  779. hr = MMC_E_INVALID_FILE;
  780. }
  781. }
  782. }
  783. catch (_com_error& err)
  784. {
  785. hr = err.Error();
  786. ASSERT (false && "Caught _com_error");
  787. return (hr);
  788. }
  789. return (hr);
  790. }
  791. STDMETHODIMP
  792. CScopeTree::GetIDPath(
  793. MTNODEID id,
  794. MTNODEID** ppIDs,
  795. long* pLength)
  796. {
  797. ASSERT(ppIDs);
  798. ASSERT(pLength);
  799. if (!ppIDs || !pLength)
  800. return E_POINTER;
  801. CMTNode* pMTNode = NULL;
  802. HRESULT hr = Find(id, &pMTNode);
  803. ASSERT(pMTNode);
  804. if (!pMTNode)
  805. return E_POINTER;
  806. ASSERT(pMTNode->GetID() == id);
  807. long len = 0;
  808. for (CMTNode* pMTNodeTemp = pMTNode;
  809. pMTNodeTemp;
  810. pMTNodeTemp = pMTNodeTemp->Parent())
  811. {
  812. ++len;
  813. }
  814. if (!len)
  815. {
  816. *pLength = 0;
  817. *ppIDs = 0;
  818. return E_FAIL;
  819. }
  820. MTNODEID* pIDs = (MTNODEID*) CoTaskMemAlloc (len * sizeof (MTNODEID));
  821. if (pIDs == NULL)
  822. {
  823. *pLength = 0;
  824. *ppIDs = 0;
  825. return E_OUTOFMEMORY;
  826. }
  827. *pLength = len;
  828. *ppIDs = pIDs;
  829. for (pMTNodeTemp = pMTNode;
  830. pMTNodeTemp;
  831. pMTNodeTemp = pMTNodeTemp->Parent())
  832. {
  833. ASSERT(len != NULL);
  834. pIDs[--len] = pMTNodeTemp->GetID();
  835. }
  836. return S_OK;
  837. }
  838. /*+-------------------------------------------------------------------------*
  839. *
  840. * CScopeTree::GetNodeIDFromStream
  841. *
  842. * PURPOSE: Reads in a bookmark from the stream, and returns the NodeID of
  843. * the node it represents.
  844. *
  845. * PARAMETERS:
  846. * IStream * pStm :
  847. * MTNODEID* pID :
  848. *
  849. * RETURNS:
  850. * STDMETHODIMP
  851. *
  852. *+-------------------------------------------------------------------------*/
  853. STDMETHODIMP
  854. CScopeTree::GetNodeIDFromStream(IStream *pStm, MTNODEID* pID)
  855. {
  856. DECLARE_SC(sc, TEXT("CScopeTree::GetIDFromPath"));
  857. // check parameters
  858. sc = ScCheckPointers(pStm, pID);
  859. if(sc)
  860. return sc.ToHr();
  861. CBookmarkEx bm;
  862. *pStm >> bm;
  863. bool bExactMatchFound = false; // out value from GetNodeIDFromBookmark.
  864. return GetNodeIDFromBookmark(bm, pID, bExactMatchFound);
  865. }
  866. /*+-------------------------------------------------------------------------*
  867. *
  868. * CScopeTree::GetNodeIDFromBookmark
  869. *
  870. * PURPOSE: Returns the node ID of the MTNode represented by a bookmark.
  871. *
  872. * PARAMETERS:
  873. * HBOOKMARK hbm : [in] bookmark
  874. * MTNODEID* pID : [out] node-id
  875. * bool& bExactMatchFound : [out] Is the exact match found or not.
  876. *
  877. * RETURNS:
  878. * STDMETHODIMP
  879. *
  880. *+-------------------------------------------------------------------------*/
  881. STDMETHODIMP
  882. CScopeTree::GetNodeIDFromBookmark(HBOOKMARK hbm, MTNODEID* pID, bool& bExactMatchFound)
  883. {
  884. DECLARE_SC(sc, TEXT("CScopeTree::GetNodeIDFromBookmark"));
  885. CBookmark *pbm = CBookmark::GetBookmark(hbm);
  886. bExactMatchFound = false;
  887. sc = ScCheckPointers(pID, pbm);
  888. if(sc)
  889. return sc.ToHr();
  890. CBookmarkEx bm = *pbm;
  891. ASSERT (bm.IsValid());
  892. CMTNode *pMTNode = NULL;
  893. sc = bm.ScGetMTNode(false /*bExactMatchRequired*/, &pMTNode, bExactMatchFound);
  894. if(sc)
  895. return sc.ToHr();
  896. if(!pMTNode)
  897. {
  898. sc = E_UNEXPECTED;
  899. return sc.ToHr();
  900. }
  901. *pID = pMTNode->GetID();
  902. return sc.ToHr();
  903. }
  904. /*+-------------------------------------------------------------------------*
  905. *
  906. * CScopeTree::GetNodeFromBookmark
  907. *
  908. * PURPOSE: Returns a Node object corresponding to the scope node whose
  909. * Bookmark is passed in.
  910. *
  911. * PARAMETERS:
  912. * HBOOKMARK hbm : [in] the given bookmark
  913. * CConsoleView *pConsoleView : [in]
  914. * PPNODE ppNode : [out] the node corresponding to the bookmark.
  915. * bool bExactMatchFound : [out] did we find exactly matching node?
  916. *
  917. * RETURNS:
  918. * STDMETHODIMP
  919. *
  920. *+-------------------------------------------------------------------------*/
  921. STDMETHODIMP
  922. CScopeTree::GetNodeFromBookmark(HBOOKMARK hbm, CConsoleView *pConsoleView, PPNODE ppNode, bool& bExactMatchFound)
  923. {
  924. DECLARE_SC(sc, TEXT("CScopeTree::GetNodeFromBookmark"));
  925. sc = ScCheckPointers(pConsoleView, ppNode);
  926. if(sc)
  927. return sc.ToHr();
  928. // Get the node id
  929. MTNODEID id = 0;
  930. bExactMatchFound = false; // out value from GetNodeIDFromBookmark.
  931. sc = GetNodeIDFromBookmark(hbm, &id, bExactMatchFound);
  932. if(sc)
  933. return sc.ToHr();
  934. // find the node
  935. CMTNode *pMTNode = NULL;
  936. sc = Find(id, &pMTNode);
  937. if(sc)
  938. return sc.ToHr();
  939. // make sure that the node is available
  940. sc = pConsoleView->ScExpandNode(id, true /*bExpand*/, false /*bExpandVisually*/);
  941. if(sc)
  942. return sc.ToHr();
  943. // Create a Node object
  944. sc = ScGetNode(pMTNode, ppNode);
  945. return sc.ToHr();
  946. }
  947. HRESULT CScopeTree::GetPathString(HMTNODE hmtnRoot, HMTNODE hmtnLeaf, LPOLESTR* ppszPath)
  948. {
  949. DECLARE_SC(sc, TEXT("CScopeTree::GetPathString"));
  950. sc = ScCheckPointers(hmtnLeaf, ppszPath);
  951. if(sc)
  952. return sc.ToHr();
  953. CMTNode* pmtnLeaf = CMTNode::FromHandle(hmtnLeaf);
  954. CMTNode* pmtnRoot = (hmtnRoot == NULL) ? m_pMTNodeRoot : CMTNode::FromHandle(hmtnRoot);
  955. CStr strPath;
  956. _GetPathString(pmtnRoot, pmtnLeaf, strPath);
  957. if (!strPath.IsEmpty())
  958. {
  959. int cchPath = strPath.GetLength()+1;
  960. *ppszPath = reinterpret_cast<LPOLESTR>(CoTaskMemAlloc(cchPath * sizeof(OLECHAR)));
  961. if (*ppszPath == NULL)
  962. return (sc = E_OUTOFMEMORY).ToHr();
  963. USES_CONVERSION;
  964. sc = StringCchCopyW(*ppszPath, cchPath, T2COLE(strPath));
  965. if(sc)
  966. return sc.ToHr();
  967. return S_OK;
  968. }
  969. return (sc = E_FAIL).ToHr();
  970. }
  971. void CScopeTree::_GetPathString(CMTNode* pmtnRoot, CMTNode* pmtnCur, CStr& strPath)
  972. {
  973. ASSERT(pmtnRoot != NULL && pmtnCur != NULL);
  974. // if haven't reached the root node yet, recursively get path from
  975. // root to current node's parent
  976. if (pmtnCur != pmtnRoot)
  977. {
  978. _GetPathString(pmtnRoot, pmtnCur->Parent(), strPath);
  979. strPath += _T('\\');
  980. }
  981. // now append the name for the current node
  982. strPath += pmtnCur->GetDisplayName().data();
  983. }
  984. /*+-------------------------------------------------------------------------*
  985. *
  986. * CScopeTree::ScAddSnapin
  987. *
  988. * PURPOSE: Adds the specified snapin to the console file beneath console root.
  989. *
  990. * TODO: 1) Allow the caller to specify the parent snapin.
  991. * 2) Right now specifying snapins by name does not work. Add this.
  992. *
  993. * PARAMETERS:
  994. * LPCTSTR szSnapinNameOrCLSID : The name or GUID of the snapin.
  995. *
  996. * RETURNS:
  997. * SC
  998. *
  999. *+-------------------------------------------------------------------------*/
  1000. SC
  1001. CScopeTree::ScAddSnapin (
  1002. LPCWSTR szSnapinNameOrCLSID, /* I:name or CLSID of the snapin */
  1003. SnapIn* pParentSnapinNode, /* I:Parent snapin under which this snapin is added (optional)*/
  1004. Properties* pProperties, /* I:props to init with (optional) */
  1005. SnapIn*& rpSnapIn) /* O:the snap-in that was created */
  1006. {
  1007. DECLARE_SC(sc, TEXT("CScopeTree::ScAddSnapin"));
  1008. CSnapinManager snapinMgr(GetRoot());
  1009. Trace(tagScopeTreeAddSnapin, TEXT("CScopeTree::ScAddSnapin"));
  1010. // adding the snapin below this node.
  1011. sc = snapinMgr.ScAddSnapin(szSnapinNameOrCLSID, pParentSnapinNode, pProperties);
  1012. if(sc)
  1013. return sc;
  1014. // get the "list" of one node to add
  1015. NewNodeList* pNewNodes = snapinMgr.GetNewNodes();
  1016. if (pNewNodes == NULL)
  1017. return (sc = E_UNEXPECTED);
  1018. // the list should have an item in it
  1019. CNewTreeNode* pNewNode = pNewNodes->GetHead();
  1020. if (pNewNode == NULL)
  1021. return (sc = E_UNEXPECTED);
  1022. // Update the scope tree with changes made by snapin manager.
  1023. sc = ScAddOrRemoveSnapIns(snapinMgr.GetDeletedNodesList(),
  1024. pNewNodes);
  1025. if(sc)
  1026. return sc;
  1027. // if ScAddOrRemoveSnapIns succeeded, it better have created a CMTSnapInNode for us
  1028. CMTSnapInNode* pNewSnapInNode = pNewNode->m_pmtNewSnapInNode;
  1029. if (pNewSnapInNode == NULL)
  1030. return (sc = E_UNEXPECTED);
  1031. // get the SnapIn interface for the client
  1032. sc = pNewSnapInNode->ScGetSnapIn (&rpSnapIn);
  1033. if (sc)
  1034. return (sc);
  1035. return sc;
  1036. }
  1037. /*+-------------------------------------------------------------------------*
  1038. *
  1039. * CScopeTree::QuerySnapIns
  1040. *
  1041. * PURPOSE: Creates, AddRefs, and returns a SnapIns object.
  1042. *
  1043. * PARAMETERS:
  1044. * SnapIns ** ppSnapIns :
  1045. *
  1046. * RETURNS:
  1047. * HRESULT
  1048. *
  1049. *+-------------------------------------------------------------------------*/
  1050. HRESULT
  1051. CScopeTree::QuerySnapIns(SnapIns **ppSnapIns)
  1052. {
  1053. DECLARE_SC(sc, TEXT("CScopeTree::QuerySnapIns"));
  1054. // parameter check
  1055. sc = ScCheckPointers(ppSnapIns);
  1056. if (sc)
  1057. return sc.ToHr();
  1058. // init out parameter
  1059. *ppSnapIns = NULL;
  1060. // create a CSnapIns object if needed.
  1061. sc = CTiedComObjectCreator<CSnapIns>::ScCreateAndConnect(*this, m_spSnapIns);
  1062. if(sc)
  1063. return sc.ToHr();
  1064. if(m_spSnapIns == NULL)
  1065. {
  1066. sc = E_UNEXPECTED;
  1067. return sc.ToHr();
  1068. }
  1069. // addref the pointer for the client.
  1070. m_spSnapIns->AddRef();
  1071. *ppSnapIns = m_spSnapIns;
  1072. return sc.ToHr();
  1073. }
  1074. /*+-------------------------------------------------------------------------*
  1075. *
  1076. * CScopeTree::QueryScopeNamespace
  1077. *
  1078. * PURPOSE: Creates, AddRefs, and returns a ScopeNamespace object.
  1079. *
  1080. * PARAMETERS:
  1081. * ScopeNamespace ** ppScopeNamespace :
  1082. *
  1083. * RETURNS:
  1084. * HRESULT
  1085. *
  1086. *+-------------------------------------------------------------------------*/
  1087. HRESULT
  1088. CScopeTree::QueryScopeNamespace(ScopeNamespace **ppScopeNamespace)
  1089. {
  1090. DECLARE_SC(sc, TEXT("CScopeTree::QueryScopeNamespace"));
  1091. // parameter check
  1092. sc = ScCheckPointers(ppScopeNamespace);
  1093. if (sc)
  1094. return sc.ToHr();
  1095. // init out parameter
  1096. *ppScopeNamespace = NULL;
  1097. // create a CScopeNamespace object if needed.
  1098. sc = CTiedComObjectCreator<CScopeNamespace>::ScCreateAndConnect(*this, m_spScopeNamespace);
  1099. if(sc)
  1100. return sc.ToHr();
  1101. if(m_spScopeNamespace == NULL)
  1102. {
  1103. sc = E_UNEXPECTED;
  1104. return sc.ToHr();
  1105. }
  1106. // addref the pointer for the client.
  1107. m_spScopeNamespace->AddRef();
  1108. *ppScopeNamespace = m_spScopeNamespace;
  1109. return sc.ToHr();
  1110. }
  1111. /*+-------------------------------------------------------------------------*
  1112. * CScopeTree::CreateProperties
  1113. *
  1114. * Creates a new, empty Properties object. This function does the work
  1115. * behind _Document::CreateProperties.
  1116. *--------------------------------------------------------------------------*/
  1117. HRESULT CScopeTree::CreateProperties (Properties** ppProperties)
  1118. {
  1119. DECLARE_SC (sc, _T("CScopeTree::CreateProperties"));
  1120. /*
  1121. * validate parameters
  1122. */
  1123. sc = ScCheckPointers (ppProperties);
  1124. if (sc)
  1125. return (sc.ToHr());
  1126. /*
  1127. * create a new properties collection
  1128. */
  1129. CComObject<CSnapinProperties> *pProperties = NULL;
  1130. sc = CComObject<CSnapinProperties>::CreateInstance (&pProperties);
  1131. if (sc)
  1132. return (sc.ToHr());
  1133. if (pProperties == NULL)
  1134. return ((sc = E_UNEXPECTED).ToHr());
  1135. /*
  1136. * put a ref on for the client
  1137. */
  1138. (*ppProperties) = pProperties;
  1139. (*ppProperties)->AddRef();
  1140. return (sc.ToHr());
  1141. }
  1142. //+-------------------------------------------------------------------
  1143. //
  1144. // Member: CScopeTree::QueryRootNode
  1145. //
  1146. // Synopsis: Returns COM object to the Root Node.
  1147. //
  1148. // Arguments: [ppRootNode] - Ptr in which root node will be returned.
  1149. //
  1150. // Returns: HRESULT
  1151. //
  1152. //--------------------------------------------------------------------
  1153. HRESULT CScopeTree::QueryRootNode (PPNODE ppRootNode)
  1154. {
  1155. DECLARE_SC(sc, _T("CScopeTree::QueryRootNode"));
  1156. sc = ScGetRootNode(ppRootNode);
  1157. return (sc.ToHr());
  1158. }
  1159. HRESULT CScopeTree::Load(IStorage *pStg)
  1160. {
  1161. ASSERT(m_spPersistData == NULL);
  1162. if (m_spPersistData != NULL)
  1163. return E_UNEXPECTED;
  1164. ASSERT(pStg != NULL);
  1165. if (pStg == NULL)
  1166. return E_INVALIDARG;
  1167. // Create the perist data interface and attach it to the storage
  1168. CComObject<PersistData>* pPersistData;
  1169. HRESULT hr = CComObject<PersistData>::CreateInstance(&pPersistData);
  1170. m_spPersistData = pPersistData;
  1171. ASSERT(SUCCEEDED(hr) && m_spPersistData != NULL);
  1172. if (FAILED(hr))
  1173. return hr;
  1174. hr = m_spPersistData->Open(pStg);
  1175. ASSERT(SUCCEEDED(hr));
  1176. if (FAILED(hr))
  1177. return hr;
  1178. // Open the stream for the cache
  1179. IStreamPtr spStream;
  1180. hr = OpenDebugStream(pStg, AMCSnapInCacheStreamName,
  1181. STGM_SHARE_EXCLUSIVE | STGM_READWRITE, L"SnapInCache", &spStream);
  1182. ASSERT(SUCCEEDED(hr));
  1183. if (FAILED(hr))
  1184. return hr;
  1185. SC sc = theApp.GetSnapInsCache()->ScLoad(spStream);
  1186. ASSERT(!sc.IsError());
  1187. if (sc)
  1188. return sc.ToHr();
  1189. ASSERT(m_pMTNodeRoot == NULL);
  1190. sc = CMTNode::ScLoad (m_spPersistData, &m_pMTNodeRoot);
  1191. ASSERT(!sc.IsError() && m_pMTNodeRoot != NULL);
  1192. if (sc)
  1193. return sc.ToHr();
  1194. hr = LoadTaskpadList(pStg);
  1195. return hr;
  1196. }
  1197. /*+-------------------------------------------------------------------------*
  1198. *
  1199. * CScopeTree::Persist
  1200. *
  1201. * PURPOSE: Persists the CScopeTree to the specified persistor.
  1202. *
  1203. * PARAMETERS:
  1204. * HPERSISTOR pPersistor:
  1205. *
  1206. * RETURNS:
  1207. * HRESULT
  1208. *
  1209. *+-------------------------------------------------------------------------*/
  1210. HRESULT CScopeTree::Persist(HPERSISTOR hPersistor)
  1211. {
  1212. DECLARE_SC(sc, TEXT("CScopeTree::Persist"));
  1213. try
  1214. {
  1215. sc = ScCheckPointers((void *)hPersistor,theApp.GetSnapInsCache());
  1216. if (sc)
  1217. sc.Throw();
  1218. CPersistor &persistor = *reinterpret_cast<CPersistor *>(hPersistor);
  1219. CPersistor persistorScopeTree(persistor, XML_TAG_SCOPE_TREE);
  1220. // persist the snapin cache.
  1221. persistorScopeTree.Persist(*theApp.GetSnapInsCache());
  1222. // persist the MTNode hierarchy.
  1223. CPersistor persistorMTNodes(persistorScopeTree, XML_TAG_SCOPE_TREE_NODES);
  1224. if (persistor.IsStoring())
  1225. {
  1226. if(!m_pMTNodeRoot)
  1227. sc.Throw(E_POINTER);
  1228. persistorMTNodes.Persist(*m_pMTNodeRoot);
  1229. }
  1230. else
  1231. {
  1232. // here we imitate how the collection fixes on the element
  1233. // despite we only have one, CMTNode::PersistNewNode thinks else
  1234. CPersistor persistor1Node(persistorMTNodes, XML_TAG_MT_NODE);
  1235. CPersistor persistor1NodeLocked(persistor1Node,persistor1Node.GetCurrentElement(),true);
  1236. CMTNode::PersistNewNode(persistor1NodeLocked, &m_pMTNodeRoot);
  1237. sc = ScCheckPointers(m_pMTNodeRoot,E_FAIL);
  1238. if (sc)
  1239. sc.Throw();
  1240. }
  1241. // persist all taskpads
  1242. if(m_pConsoleTaskpads)
  1243. {
  1244. persistor.Persist(*m_pConsoleTaskpads);
  1245. }
  1246. }
  1247. catch (SC e_sc)
  1248. {
  1249. sc = e_sc;
  1250. }
  1251. catch (_com_error e_com)
  1252. {
  1253. sc = e_com.Error();
  1254. }
  1255. catch (HRESULT e_hr)
  1256. {
  1257. sc = e_hr;
  1258. }
  1259. return sc.ToHr();
  1260. }
  1261. HRESULT CScopeTree::Save(IStorage *pStg, BOOL fSameAsLoad)
  1262. {
  1263. // obsolete method.
  1264. // this method is left here since we use IPersistStorage to export
  1265. // persistence to CONUI side and we need to implement it.
  1266. // But this interface will never be called to save data
  1267. // [we will use CPersistor-based XML saving instead]
  1268. // so the method will always fail.
  1269. ASSERT(FALSE && "Should never come here");
  1270. return E_NOTIMPL;
  1271. }
  1272. HRESULT CScopeTree::LoadTaskpadList(IStorage *pStg)
  1273. {
  1274. HRESULT hr = S_OK;
  1275. m_pConsoleTaskpads->clear();
  1276. m_pDefaultTaskpads->clear();
  1277. // Open the stream for the cache
  1278. IStreamPtr spStream;
  1279. hr = OpenDebugStream(pStg, AMCTaskpadListStreamName,
  1280. STGM_SHARE_EXCLUSIVE | STGM_READWRITE, L"TaskpadList", &spStream);
  1281. if (FAILED(hr))
  1282. return S_OK; // might be pre-MMC1.2, so if we don't find the stream just exit normally.
  1283. hr = m_pConsoleTaskpads->Read(*(spStream.GetInterfacePtr()));
  1284. if(FAILED(hr))
  1285. return hr;
  1286. // Read the list of default taskpads.
  1287. hr = m_pDefaultTaskpads->Read(*(spStream.GetInterfacePtr()));
  1288. if(FAILED(hr))
  1289. return hr;
  1290. return hr;
  1291. }
  1292. HRESULT CScopeTree::SaveCompleted(IStorage *pStg)
  1293. {
  1294. // obsolete method.
  1295. // this method is left here since we use IPersistStorage to export
  1296. // persistence to CONUI side and we need to implement it.
  1297. // But this interface will never be called to save data
  1298. // [we will use CPersistor-based XML saving instead]
  1299. // so the method will always fail.
  1300. ASSERT(FALSE && "Should never come here");
  1301. return E_NOTIMPL;
  1302. }
  1303. /*+-------------------------------------------------------------------------*
  1304. *
  1305. * CScopeTree::Find
  1306. *
  1307. * PURPOSE:
  1308. *
  1309. * PARAMETERS:
  1310. * MTNODEID mID :
  1311. * CMTNode** ppMTNode :
  1312. *
  1313. * RETURNS:
  1314. * HRESULT
  1315. *
  1316. *+-------------------------------------------------------------------------*/
  1317. HRESULT CScopeTree::Find(MTNODEID mID, CMTNode** ppMTNode)
  1318. {
  1319. if (ppMTNode == NULL)
  1320. return E_POINTER;
  1321. *ppMTNode = NULL;
  1322. CMTNode* pMTRootNode = GetRoot();
  1323. if (pMTRootNode == NULL)
  1324. return (E_FAIL);
  1325. *ppMTNode = pMTRootNode->Find(mID);
  1326. return ((*ppMTNode == NULL) ? E_FAIL : S_OK);
  1327. }
  1328. HRESULT CScopeTree::Find(MTNODEID mID, HMTNODE* phMTNode)
  1329. {
  1330. if (phMTNode == NULL)
  1331. return E_POINTER;
  1332. *phMTNode = NULL;
  1333. CMTNode* pMTNode;
  1334. HRESULT hr = Find (mID, &pMTNode);
  1335. if (FAILED (hr))
  1336. return (hr);
  1337. *phMTNode = CMTNode::ToHandle (pMTNode);
  1338. return ((*phMTNode == NULL) ? E_FAIL : S_OK);
  1339. }
  1340. HRESULT CScopeTree::GetClassID(CLSID *pClassID)
  1341. {
  1342. if (pClassID == NULL)
  1343. return E_INVALIDARG;
  1344. *pClassID = CLSID_ScopeTree;
  1345. return S_OK;
  1346. }
  1347. #define SDI_RELATIVEID_MASK (SDI_PARENT | SDI_PREVIOUS | SDI_NEXT)
  1348. SC
  1349. CScopeTree::ScInsert(LPSCOPEDATAITEM pSDI, COMPONENTID nID,
  1350. CMTNode** ppMTNodeNew)
  1351. {
  1352. DECLARE_SC(sc, TEXT("CScopeTree::ScInsert"));
  1353. // check parameters
  1354. if (m_pMTNodeRoot == NULL)
  1355. {
  1356. sc = E_INVALIDARG;
  1357. return sc;
  1358. }
  1359. try
  1360. {
  1361. *ppMTNodeNew = NULL;
  1362. HMTNODE hMTNodePrev = (HMTNODE) TVI_LAST;
  1363. CMTNode* pMTNodeRelative = CMTNode::FromScopeItem(pSDI->relativeID);
  1364. CMTNode* pMTNodeParent = NULL;
  1365. if (pSDI->mask & SDI_RELATIVEID_MASK)
  1366. {
  1367. if (pMTNodeRelative->GetOwnerID() != nID)
  1368. {
  1369. sc = E_INVALIDARG;
  1370. return sc;
  1371. }
  1372. pMTNodeParent = pMTNodeRelative->Parent();
  1373. }
  1374. else
  1375. {
  1376. pMTNodeParent = pMTNodeRelative;
  1377. }
  1378. if (pMTNodeParent == NULL)
  1379. {
  1380. sc = E_INVALIDARG;
  1381. return sc;
  1382. }
  1383. ASSERT(pMTNodeParent->WasExpandedAtLeastOnce() == TRUE);
  1384. if (pMTNodeParent->WasExpandedAtLeastOnce() == FALSE)
  1385. {
  1386. sc = E_POINTER;
  1387. return sc;
  1388. }
  1389. if (IsBadWritePtr(pMTNodeParent, sizeof(CMTNode*)) != 0)
  1390. {
  1391. sc = E_POINTER;
  1392. return sc;
  1393. }
  1394. CMTSnapInNode* pMTSINode = pMTNodeParent->GetStaticParent();
  1395. CComponentData* pCCD = pMTSINode->GetComponentData(nID);
  1396. ASSERT(pCCD != NULL);
  1397. CMTNode* pMTNode = new CMTNode;
  1398. if (pMTNode == NULL)
  1399. return (sc = E_OUTOFMEMORY);
  1400. /* Determine the node to Insert after */
  1401. CMTNode* pInsertAfter = NULL;
  1402. if (pSDI->mask & SDI_PREVIOUS)
  1403. {
  1404. pInsertAfter = pMTNodeRelative;
  1405. }
  1406. else if (pSDI->mask & SDI_NEXT)
  1407. {
  1408. pInsertAfter = pMTNodeRelative->Prev();
  1409. }
  1410. else if (pSDI->mask & SDI_FIRST)
  1411. {
  1412. pInsertAfter = NULL;
  1413. }
  1414. else
  1415. {
  1416. pInsertAfter = pMTNodeParent->LastChild();
  1417. }
  1418. hMTNodePrev = (pInsertAfter==NULL ? (HMTNODE)TVI_FIRST : CMTNode::ToHandle(pInsertAfter));
  1419. /* Insert as child after pInsertAfter. If the latter is NULL, insert as
  1420. ** the first child
  1421. */
  1422. sc = pMTNodeParent->ScInsertChild(pMTNode, pInsertAfter);
  1423. if(sc)
  1424. {
  1425. pMTNode->Release();
  1426. return sc;
  1427. }
  1428. pMTNode->SetPrimaryComponentData(pCCD);
  1429. pMTNode->SetOwnerID(nID);
  1430. pMTNode->SetUserParam(pSDI->lParam);
  1431. if (pSDI->mask & SDI_STATE)
  1432. pMTNode->SetState(pSDI->nState);
  1433. if (pSDI->mask & SDI_IMAGE)
  1434. pMTNode->SetImage(pSDI->nImage);
  1435. if (pSDI->mask & SDI_OPENIMAGE)
  1436. pMTNode->SetOpenImage(pSDI->nOpenImage);
  1437. if ((pSDI->mask & SDI_CHILDREN) && (pSDI->cChildren == 0))
  1438. pMTNode->SetNoPrimaryChildren();
  1439. pSDI->ID = reinterpret_cast<HSCOPEITEM>(pMTNode);
  1440. *ppMTNodeNew = pMTNode;
  1441. // Now inform the views to add as needed.
  1442. SViewUpdateInfo vui;
  1443. vui.newNode = CMTNode::ToHandle(pMTNode);
  1444. vui.insertAfter = hMTNodePrev;
  1445. pMTNode->Parent()->CreatePathList(vui.path);
  1446. UpdateAllViews(VIEW_UPDATE_ADD, reinterpret_cast<LPARAM>(&vui));
  1447. }
  1448. catch( std::bad_alloc )
  1449. {
  1450. sc = E_OUTOFMEMORY;
  1451. return sc;
  1452. }
  1453. return sc;
  1454. }
  1455. typedef CArray<COMPONENTID, COMPONENTID> CComponentIDArray;
  1456. //---------------------------------------------------------------------------------------
  1457. // NotifyExtensionsOfNodeDeletion
  1458. //
  1459. // This method enumerated the children of a node, building a list of all the snap-in
  1460. // components that have added children. It then sends a REMOVE_CHILDREN notification to
  1461. // each of the components.
  1462. //
  1463. // The component that owns the node is treated in a special way. It is only notified if
  1464. // the node is staic or the bNotifyRoot param is TRUE. This is because we don't want
  1465. // to send notifications for nodes that belong to a subtree rooted at a node owned by
  1466. // the same component (see InformSnapinsOfDeletion).
  1467. //---------------------------------------------------------------------------------------
  1468. void NotifyExtensionsOfNodeDeletion(CMTNode* pMTNode, CComponentIDArray& rgID,
  1469. BOOL bNotifyRoot = FALSE)
  1470. {
  1471. if (pMTNode == NULL)
  1472. return;
  1473. CMTSnapInNode* pMTSINode = pMTNode->GetStaticParent();
  1474. ASSERT(pMTSINode != NULL);
  1475. if (pMTSINode == NULL)
  1476. return;
  1477. COMPONENTID idOwner = pMTNode->GetPrimaryComponentID();
  1478. int nTemp = pMTSINode->GetNumberOfComponentDatas() + 1;
  1479. rgID.SetSize(nTemp);
  1480. for (int i=0; i < nTemp; ++i)
  1481. rgID[i] = -1;
  1482. // Build list of all component ID's that have added children to this node
  1483. // except for component that owns the node.
  1484. BOOL bOwnerChildren = FALSE;
  1485. CMTNode* pMTNodeTemp = pMTNode->Child();
  1486. for (int iMax = -1; pMTNodeTemp != NULL; pMTNodeTemp = pMTNodeTemp->Next())
  1487. {
  1488. COMPONENTID id = pMTNodeTemp->GetPrimaryComponentID();
  1489. // if owner ID just note it, else add ID to list
  1490. if (id == idOwner)
  1491. {
  1492. bOwnerChildren = TRUE;
  1493. }
  1494. else
  1495. {
  1496. // search list for ID
  1497. for (int j=0; j <= iMax; ++j)
  1498. {
  1499. if (rgID[j] == id)
  1500. break;
  1501. }
  1502. // if not found, add to list
  1503. if (j > iMax)
  1504. rgID[++iMax] = id;
  1505. }
  1506. }
  1507. // Include owner conponent only if it needs to be notified
  1508. if (bOwnerChildren && (bNotifyRoot == TRUE || pMTNode->IsStaticNode()))
  1509. rgID[++iMax] = idOwner;
  1510. if (!pMTNode->IsInitialized())
  1511. return;
  1512. IDataObjectPtr spDataObject;
  1513. HRESULT hr = pMTNode->QueryDataObject(CCT_SCOPE, &spDataObject);
  1514. ASSERT(SUCCEEDED(hr));
  1515. if (FAILED(hr))
  1516. return;
  1517. LPARAM lScopeItem = CMTNode::ToScopeItem(pMTNode);
  1518. pMTNode->SetRemovingChildren(true);
  1519. for (i = 0; i <= iMax; ++i)
  1520. {
  1521. ASSERT(rgID[i] != -1);
  1522. CComponentData* pCD = pMTSINode->GetComponentData(rgID[i]);
  1523. ASSERT(pCD != NULL);
  1524. Dbg(DEB_TRACE, _T("Remove Children - node = %s, ID = %d\n"), pMTNode->GetDisplayName(), rgID[i]);
  1525. hr = pCD->Notify(spDataObject, MMCN_REMOVE_CHILDREN, lScopeItem, 0);
  1526. CHECK_HRESULT(hr);
  1527. }
  1528. pMTNode->SetRemovingChildren(false);
  1529. }
  1530. //-----------------------------------------------------------------------------------------------
  1531. // InformSnapinsOfDeletion
  1532. //
  1533. // This function traverse the node subtree rooted at pMTNode and sends a REMOVE_CHILDREN to all
  1534. // snap-in components that have added children to the tree. A component is sent one notification
  1535. // for each node it has extended that belongs to another component. No notification is sent where
  1536. // a component has extended one of its own nodes. There are two exceptions to this rule. Owners
  1537. // of static nodes are always notified. Also the owner of the top node is notified if bNotifyRoot
  1538. // is TRUE.
  1539. //
  1540. // Another way to look at this is that MMC searches the tree for subtrees of nodes provided by
  1541. // a single component. It sends a notification to the component to delete the top node of the
  1542. // subtree. The component is responsible for identifying and deleting the rest of its nodes in
  1543. // the subtree.
  1544. //
  1545. // This method just handles the recursion and iteration required to traverse the whole tree. It
  1546. // calls NotifyExtensionsOfNodeDeletion to enumerate the children of a node and send notifications
  1547. // to the right components.
  1548. //
  1549. //------------------------------------------------------------------------------------------------
  1550. void InformSnapinsOfDeletion(CMTNode* pMTNode, BOOL fNext,
  1551. CComponentIDArray& rgID, BOOL bNotifyRoot = FALSE)
  1552. {
  1553. if (pMTNode == NULL)
  1554. return;
  1555. if (pMTNode->Child() != NULL)
  1556. {
  1557. // Recursively clear nodes's subtree first
  1558. InformSnapinsOfDeletion(pMTNode->Child(), TRUE, rgID, FALSE);
  1559. // Notify extensions of node itself
  1560. NotifyExtensionsOfNodeDeletion(pMTNode, rgID, bNotifyRoot);
  1561. }
  1562. // If requested, handle all siblings of this node
  1563. // (iteratively rather than recursively to avoid deep stack use)
  1564. if (fNext == TRUE)
  1565. {
  1566. CMTNode* pMTNodeNext = pMTNode->Next();
  1567. while (pMTNodeNext != NULL)
  1568. {
  1569. InformSnapinsOfDeletion(pMTNodeNext, FALSE, rgID, FALSE);
  1570. pMTNodeNext = pMTNodeNext->Next();
  1571. }
  1572. }
  1573. }
  1574. /*+-------------------------------------------------------------------------*
  1575. * CScopeTree::Delete
  1576. *
  1577. * PURPOSE: Deletes a tree rooted at a node. Also sends a notification to
  1578. * the selected item in each view asking them whether they need to
  1579. * be reselected once the item is deleted.
  1580. *
  1581. * Called by CNodeInitObject::DeleteItem
  1582. *
  1583. * PARAMETERS:
  1584. * CMTNode* pmtn: The root of the tree to be deleted
  1585. * BOOL fDeleteThis: Whether the root itself requires deletion as well
  1586. * COMPONENTID nID:
  1587. *
  1588. * RETURNS:
  1589. * void
  1590. /*+-------------------------------------------------------------------------*/
  1591. SC
  1592. CScopeTree::ScDelete(CMTNode* pmtn, BOOL fDeleteThis, COMPONENTID nID)
  1593. {
  1594. DECLARE_SC(sc, TEXT("CScopeTree::Delete"));
  1595. // check parameters
  1596. if (pmtn == NULL)
  1597. {
  1598. sc = E_INVALIDARG;
  1599. return sc;
  1600. }
  1601. // Is this call a result of sending MMCN_REMOVE_CHILDREN to a parent node?
  1602. // If so return immediately since MMC does delete all the child nodes.
  1603. if (pmtn->AreChildrenBeingRemoved() == true)
  1604. return sc;
  1605. // if deleting node and children, just do one call to delete the
  1606. // whole subtree.
  1607. if (fDeleteThis)
  1608. {
  1609. // can't delete static root node OR nodes put up by other components!
  1610. if ( ( pmtn->GetOwnerID() == TVOWNED_MAGICWORD) || (pmtn->GetOwnerID() != nID) )
  1611. {
  1612. sc = E_INVALIDARG;
  1613. return sc;
  1614. }
  1615. #ifdef DBG
  1616. CMTNode* pmtnParent = pmtn->Parent();
  1617. CMTNode* pmtnPrev = NULL;
  1618. CMTNode* pmtnNext = pmtn->Next();
  1619. if (pmtnParent->Child() != pmtn)
  1620. {
  1621. pmtnPrev = pmtnParent->Child();
  1622. while (pmtnPrev->Next() != pmtn)
  1623. pmtnPrev = pmtnPrev->Next();
  1624. ASSERT(pmtnPrev != NULL);
  1625. }
  1626. #endif
  1627. DeleteNode(pmtn);
  1628. #ifdef DBG
  1629. if (pmtnParent != NULL)
  1630. {
  1631. ASSERT(pmtnParent != NULL);
  1632. if (pmtnPrev == NULL)
  1633. {
  1634. ASSERT(pmtnParent->Child() == pmtnNext);
  1635. }
  1636. else
  1637. {
  1638. ASSERT(pmtnPrev->Next() == pmtnNext);
  1639. }
  1640. }
  1641. #endif
  1642. }
  1643. // else we have to enum the children and delete only the ones
  1644. // created by the calling snap-in
  1645. else
  1646. {
  1647. CMTNode* pMTNode = pmtn->Child();
  1648. // Enum children and delete those that are owned by the
  1649. // requesting component (i.e., with matching ID)
  1650. while(pMTNode != NULL)
  1651. {
  1652. CMTNode *pMTNodeNext = pMTNode->Next();
  1653. if (!pMTNode->IsStaticNode() &&
  1654. (pMTNode->GetPrimaryComponentID() == nID))
  1655. {
  1656. DeleteNode(pMTNode);
  1657. }
  1658. pMTNode = pMTNodeNext;
  1659. }
  1660. }
  1661. return sc;
  1662. }
  1663. void CScopeTree::DeleteNode(CMTNode* pmtn)
  1664. {
  1665. if (pmtn == NULL)
  1666. return;
  1667. // always update the views
  1668. SViewUpdateInfo vui;
  1669. vui.flag = VUI_DELETE_THIS;
  1670. pmtn->CreatePathList (vui.path);
  1671. // We are changing selection, so snapin may call delete
  1672. // on this node during this process (MMCN_SELECT, MMCN_SHOW...),
  1673. // Do an AddRef and Release to protect ourself from such deletes.
  1674. pmtn->AddRef();
  1675. UpdateAllViews (VIEW_UPDATE_SELFORDELETE, reinterpret_cast<LPARAM>(&vui));
  1676. if (pmtn->Release() == 0)
  1677. return; // The object was already deleted during selection change.
  1678. UpdateAllViews (VIEW_UPDATE_DELETE, reinterpret_cast<LPARAM>(&vui));
  1679. CComponentIDArray rgID;
  1680. rgID.SetSize(20, 10);
  1681. InformSnapinsOfDeletion(pmtn, FALSE, rgID, (pmtn->IsStaticNode() == FALSE));
  1682. CMTNode* pmtnParent = pmtn->Parent();
  1683. _DeleteNode(pmtn);
  1684. pmtnParent->OnChildrenChanged();
  1685. UpdateAllViews (VIEW_UPDATE_DELETE_EMPTY_VIEW, 0);
  1686. }
  1687. void CScopeTree::_DeleteNode(CMTNode* pmtn)
  1688. {
  1689. DECLARE_SC(sc, TEXT("CScopeTree::_DeleteNode"));
  1690. //
  1691. // Delete from the scope tree.
  1692. //
  1693. sc = ScCheckPointers(pmtn);
  1694. if (sc)
  1695. return;
  1696. if (m_pMTNodeRoot == pmtn)
  1697. {
  1698. m_pMTNodeRoot->Release();
  1699. m_pMTNodeRoot = NULL;
  1700. return;
  1701. }
  1702. CMTNode* pmtnParent = pmtn->Parent();
  1703. sc = (pmtnParent ? sc : E_UNEXPECTED);
  1704. if(sc)
  1705. return;
  1706. sc = pmtnParent->ScDeleteChild(pmtn);
  1707. if(sc)
  1708. return;
  1709. pmtnParent->SetDirty();
  1710. }
  1711. void CScopeTree::UpdateAllViews(LONG lHint, LPARAM lParam)
  1712. {
  1713. CConsoleFrame* pFrame = GetConsoleFrame();
  1714. ASSERT (pFrame != NULL);
  1715. if (pFrame == NULL)
  1716. return;
  1717. SC sc = pFrame->ScUpdateAllScopes (lHint, lParam);
  1718. if (sc)
  1719. goto Error;
  1720. Cleanup:
  1721. return;
  1722. Error:
  1723. TraceError (_T("CScopeTree::UpdateAllViews"), sc);
  1724. goto Cleanup;
  1725. }
  1726. void CScopeTree::DeleteDynamicNodes(CMTNode* pMTNode)
  1727. {
  1728. ASSERT(pMTNode != NULL);
  1729. ASSERT(pMTNode->IsStaticNode() == TRUE);
  1730. if (pMTNode == NULL)
  1731. return;
  1732. CMTSnapInNode* pMTSINode = dynamic_cast<CMTSnapInNode*>(pMTNode);
  1733. ASSERT(pMTSINode != NULL);
  1734. if (pMTSINode == NULL)
  1735. return;
  1736. for (CMTNode* pMTNodeTemp = pMTNode->Child(); pMTNodeTemp != NULL;
  1737. pMTNodeTemp = pMTNodeTemp->Next())
  1738. {
  1739. if (pMTNodeTemp->IsDynamicNode())
  1740. {
  1741. CComponentIDArray rgID;
  1742. rgID.SetSize(20, 10);
  1743. InformSnapinsOfDeletion(pMTNodeTemp, FALSE, rgID, FALSE);
  1744. }
  1745. }
  1746. CComponentIDArray rgID;
  1747. NotifyExtensionsOfNodeDeletion(pMTSINode, rgID, FALSE);
  1748. CMTNode* pMTNodeNext = pMTNode->Child();
  1749. while (pMTNodeNext != NULL)
  1750. {
  1751. pMTNodeTemp = pMTNodeNext;
  1752. pMTNodeNext = pMTNodeNext->Next();
  1753. if (pMTNodeTemp->IsStaticNode() == FALSE)
  1754. _DeleteNode(pMTNodeTemp);
  1755. }
  1756. }
  1757. inline BOOL CScopeTree::ExtensionsHaveChanged(CMTSnapInNode* pMTSINode)
  1758. {
  1759. CSnapIn* pSnapIn = pMTSINode->GetPrimarySnapIn();
  1760. ASSERT(pSnapIn != NULL);
  1761. return pSnapIn->HasNameSpaceChanged();
  1762. }
  1763. void CScopeTree::HandleExtensionChanges(CMTNode* pMTNode)
  1764. {
  1765. if (pMTNode == NULL)
  1766. return;
  1767. HandleExtensionChanges(pMTNode->Next());
  1768. if (pMTNode->IsStaticNode() == TRUE)
  1769. {
  1770. HandleExtensionChanges(pMTNode->Child());
  1771. if (ExtensionsHaveChanged(dynamic_cast<CMTSnapInNode*>(pMTNode)) == TRUE)
  1772. {
  1773. SViewUpdateInfo vui;
  1774. vui.flag = VUI_DELETE_SETAS_EXPANDABLE;
  1775. pMTNode->CreatePathList(vui.path);
  1776. UpdateAllViews(VIEW_UPDATE_SELFORDELETE, reinterpret_cast<LPARAM>(&vui));
  1777. UpdateAllViews(VIEW_UPDATE_DELETE, reinterpret_cast<LPARAM>(&vui));
  1778. vui.path.RemoveAll();
  1779. DeleteDynamicNodes(pMTNode);
  1780. m_MTNodesToBeReset.AddHead(pMTNode);
  1781. UpdateAllViews(VIEW_UPDATE_DELETE_EMPTY_VIEW, 0);
  1782. }
  1783. }
  1784. }
  1785. /*+-------------------------------------------------------------------------*
  1786. *
  1787. * CScopeTree::RunSnapIn
  1788. *
  1789. * PURPOSE: Runs the Snap-In Manager to prompt the user to add and remove snap-ins.
  1790. *
  1791. * PARAMETERS:
  1792. * HWND hwndParent :
  1793. *
  1794. * RETURNS:
  1795. * STDMETHODIMP
  1796. *
  1797. *+-------------------------------------------------------------------------*/
  1798. STDMETHODIMP CScopeTree::RunSnapIn(HWND hwndParent)
  1799. {
  1800. DECLARE_SC(sc, TEXT("CScopeTree::RunSnapIn"));
  1801. CSnapinManager dlg(GetRoot());
  1802. if (dlg.DoModal() == IDOK)
  1803. {
  1804. sc = ScAddOrRemoveSnapIns(dlg.GetDeletedNodesList(), dlg.GetNewNodes());
  1805. if(sc)
  1806. return sc.ToHr();
  1807. }
  1808. return sc.ToHr();
  1809. }
  1810. /*+-------------------------------------------------------------------------*
  1811. * class CEnableProcessingSnapinCacheChanges
  1812. *
  1813. *
  1814. * PURPOSE: A class that sets/re-sets ProcessingSnapinChanges so that
  1815. * the ProcessingSnapinChanges is re-set automatically when
  1816. * this object is destroyed.
  1817. *
  1818. *+-------------------------------------------------------------------------*/
  1819. class CEnableProcessingSnapinCacheChanges
  1820. {
  1821. public:
  1822. CEnableProcessingSnapinCacheChanges()
  1823. {
  1824. theApp.SetProcessingSnapinChanges(TRUE);
  1825. }
  1826. ~CEnableProcessingSnapinCacheChanges()
  1827. {
  1828. theApp.SetProcessingSnapinChanges(FALSE);
  1829. }
  1830. };
  1831. /*+-------------------------------------------------------------------------*
  1832. *
  1833. * CScopeTree::ScAddOrRemoveSnapIns
  1834. *
  1835. * PURPOSE: Called after a snapin is added/removed (extension is enabled/disabled)
  1836. * to update scopetree with those changes.
  1837. *
  1838. * PARAMETERS:
  1839. * MTNodesList * pmtnDeletedList : The list of nodes to remove. Can be NULL.
  1840. * NewNodeList * pnnList : The list of nodes to add. Can be NULL.
  1841. *
  1842. * RETURNS:
  1843. * SC
  1844. *
  1845. *+-------------------------------------------------------------------------*/
  1846. SC
  1847. CScopeTree::ScAddOrRemoveSnapIns(MTNodesList * pmtnDeletedList, NewNodeList * pnnList)
  1848. {
  1849. DECLARE_SC(sc, TEXT("CScopeTree::ScAddOrRemoveSnapIns"));
  1850. sc = ScCheckPointers(m_pConsoleData, m_pConsoleData->m_pConsoleDocument, E_UNEXPECTED);
  1851. if (sc)
  1852. return sc;
  1853. CConsoleDocument *pConsoleDoc = m_pConsoleData->m_pConsoleDocument;
  1854. ASSERT(NULL != pConsoleDoc);
  1855. // 1. Prevent access to snapin data while processing changes.
  1856. CEnableProcessingSnapinCacheChanges processSnapinChanges;
  1857. // when notifications are suspended MMC & snapins get into the weirld states
  1858. // it is safer not to let scripts to be informed about the changes as well.
  1859. // this is there to fix windows bugs #474627 & 475801 ( 10/03/2001 )
  1860. LockComEventInterface(AppEvents);
  1861. // 2. Delete static nodes.
  1862. {
  1863. CMTNode * pmtnTemp;
  1864. POSITION pos;
  1865. if (pmtnDeletedList)
  1866. {
  1867. pos = pmtnDeletedList->GetHeadPosition();
  1868. while (pos)
  1869. {
  1870. pmtnTemp = pmtnDeletedList->GetNext(pos);
  1871. CMTSnapInNode * pMTSINode = dynamic_cast<CMTSnapInNode*>(pmtnTemp);
  1872. // forward to the document to generate the script event
  1873. if (pMTSINode)
  1874. {
  1875. SnapInPtr spSnapIn;
  1876. // construct snapin com object
  1877. sc = pMTSINode->ScGetSnapIn(&spSnapIn);
  1878. if (sc)
  1879. sc.TraceAndClear(); // it's only events. Should not affect main functionality
  1880. else
  1881. {
  1882. // emit the event
  1883. sc = pConsoleDoc->ScOnSnapinRemoved(spSnapIn);
  1884. if (sc)
  1885. sc.TraceAndClear(); // it's only events. Should not affect main functionality
  1886. }
  1887. }
  1888. DeleteNode(pmtnTemp);
  1889. }
  1890. }
  1891. }
  1892. // 3. Handle extension changes
  1893. HandleExtensionChanges(m_pMTNodeRoot->Child());
  1894. CSnapInsCache* pSnapInCache = theApp.GetSnapInsCache();
  1895. sc = ScCheckPointers(pSnapInCache, E_UNEXPECTED);
  1896. if (sc)
  1897. goto Error;
  1898. // 4. Purge the snapin cache
  1899. // (duplicates what is done in ~CSnapinManager, since doing it here is too early
  1900. // - snapin manager still has a reference to the snapins)
  1901. // but some code relies in this to remove the snapin from cache
  1902. // look at windows bug #276340 (ntbug9, 1/10/2001).
  1903. pSnapInCache->Purge();
  1904. // 5. Re-Init
  1905. {
  1906. POSITION pos = m_MTNodesToBeReset.GetHeadPosition();
  1907. while (pos)
  1908. {
  1909. CMTNode* pMTNode = m_MTNodesToBeReset.GetNext(pos);
  1910. ASSERT(pMTNode != NULL);
  1911. if (pMTNode != NULL)
  1912. pMTNode->Reset();
  1913. }
  1914. m_MTNodesToBeReset.RemoveAll();
  1915. // Re-set processing changes explicitly eventhough the
  1916. // dtor for CEnableProcessingSnapinCacheChanges will do this.
  1917. theApp.SetProcessingSnapinChanges(FALSE);
  1918. }
  1919. // 6. Cleanup controlbar cache and reselect currently selected node.
  1920. UpdateAllViews(VIEW_RESELECT, 0);
  1921. // 7. Add new static nodes
  1922. if (pnnList)
  1923. {
  1924. PNEWTREENODE pNew;
  1925. CMTNode * pmtnTemp;
  1926. POSITION pos = pnnList->GetHeadPosition();
  1927. while (pos)
  1928. {
  1929. pNew = pnnList->GetNext(pos);
  1930. sc = ScCheckPointers(pNew, E_UNEXPECTED);
  1931. if (sc)
  1932. goto Error;
  1933. pmtnTemp = NULL;
  1934. sc = ScCreateMTNodeTree(pNew, pNew->m_pmtNode, &pmtnTemp);
  1935. if (sc)
  1936. goto Error;
  1937. sc = ScCheckPointers(pmtnTemp, E_UNEXPECTED);
  1938. if (sc)
  1939. goto Error;
  1940. pmtnTemp->NotifyAddedToTree ();
  1941. SViewUpdateInfo vui;
  1942. pmtnTemp->Parent()->CreatePathList(vui.path);
  1943. vui.newNode = CMTNode::ToHandle(pmtnTemp);
  1944. UpdateAllViews(VIEW_UPDATE_ADD, reinterpret_cast<LPARAM>(&vui));
  1945. vui.path.RemoveAll();
  1946. CMTSnapInNode * pMTSINode = dynamic_cast<CMTSnapInNode*>(pmtnTemp);
  1947. // forward to the document to generate the script event
  1948. if (pMTSINode)
  1949. {
  1950. SnapInPtr spSnapIn;
  1951. // construct snapin com object
  1952. sc = pMTSINode->ScGetSnapIn(&spSnapIn);
  1953. if (sc)
  1954. sc.TraceAndClear(); // it's only events. Should not affect main functionality
  1955. else
  1956. {
  1957. // emit the event
  1958. sc = pConsoleDoc->ScOnSnapinAdded(spSnapIn);
  1959. if (sc)
  1960. sc.TraceAndClear(); // it's only events. Should not affect main functionality
  1961. }
  1962. }
  1963. }
  1964. UpdateAllViews(VIEW_RESELECT, 0);
  1965. }
  1966. if (pSnapInCache->IsHelpCollectionDirty())
  1967. {
  1968. sc = ScSetHelpCollectionInvalid();
  1969. if (sc)
  1970. goto Error;
  1971. }
  1972. Cleanup:
  1973. sc.Clear();
  1974. return sc;
  1975. Error:
  1976. sc.Trace_();
  1977. goto Cleanup;
  1978. }
  1979. //+-------------------------------------------------------------------
  1980. //
  1981. // Name: ScCreateMTNodeTree
  1982. //
  1983. // Synopsis: Creates the tree of CMTNodes described by the CNewTreeNode tree
  1984. // rooted at pNew. Attaches this subtree by inserting its root as
  1985. // the last child of pmtnParent.
  1986. //
  1987. // Arguments: pNew: [IN]: Non-Null pointer to the root of the describing tree.
  1988. // pmtnParent: [IN]: Non-Null pointer to node under which the
  1989. // subtree is to be attached
  1990. // ppNodeCreated: [OUT]: Non-null pointer to the pointer for the
  1991. // subtree to be created.
  1992. //
  1993. // Returns: SC
  1994. //
  1995. //--------------------------------------------------------------------
  1996. SC
  1997. ScCreateMTNodeTree(PNEWTREENODE pNew, CMTNode* pmtnParent,
  1998. CMTNode** ppNodeCreated )
  1999. {
  2000. DECLARE_SC(sc, TEXT("ScCreateMTNodeTree"));
  2001. sc = ScCheckPointers(ppNodeCreated);
  2002. if (sc)
  2003. return sc;
  2004. *ppNodeCreated = NULL;
  2005. sc = ScCheckPointers(pNew, pmtnParent);
  2006. if (sc)
  2007. return sc;
  2008. CMTNode* pmtnFirst = NULL;
  2009. CMTNode* pmtnCur = NULL;
  2010. while (pNew != NULL)
  2011. {
  2012. if (pNew->m_pmtNewNode == NULL)
  2013. {
  2014. CSnapInPtr spSI;
  2015. SC sc = theApp.GetSnapInsCache()->ScGetSnapIn(pNew->m_clsidSnapIn, &spSI);
  2016. if (sc)
  2017. goto finally;
  2018. CMTSnapInNode* pmtn = new CMTSnapInNode(pNew->m_spSnapinProps);
  2019. if (pmtn == NULL)
  2020. {
  2021. sc = E_OUTOFMEMORY;
  2022. goto finally;
  2023. }
  2024. // get hold on the node:
  2025. // it either will be connected or deleted (on failure)
  2026. pmtnCur = pmtn;
  2027. pmtn->SetPrimarySnapIn(spSI);
  2028. sc = ScCheckPointers(pNew->m_spIComponentData, E_UNEXPECTED);
  2029. if (sc)
  2030. goto finally;
  2031. CComponentData* pCCD = pmtn->GetPrimaryComponentData();
  2032. sc = ScCheckPointers(pCCD, E_UNEXPECTED);
  2033. if (sc)
  2034. goto finally;
  2035. pCCD->SetIComponentData(pNew->m_spIComponentData);
  2036. sc = pmtn->Init();
  2037. if (sc)
  2038. {
  2039. TraceError (_T("CScopeTree::ScCreateMTNodeTree"), sc);
  2040. // continue even on error
  2041. sc.Clear();
  2042. }
  2043. if (pNew->m_spIComponentData != NULL)
  2044. {
  2045. CStr strBuf;
  2046. sc = LoadRootDisplayName(pNew->m_spIComponentData, strBuf);
  2047. if (sc)
  2048. {
  2049. TraceError (_T("CScopeTree::ScCreateMTNodeTree"), sc);
  2050. // continue even on error
  2051. sc.Clear();
  2052. }
  2053. else
  2054. {
  2055. pmtn->SetDisplayName(strBuf);
  2056. }
  2057. }
  2058. pNew->m_pmtNewSnapInNode = pmtn;
  2059. }
  2060. else
  2061. {
  2062. pmtnCur = pNew->m_pmtNewNode;
  2063. pmtnCur->AddRef();
  2064. }
  2065. if (pNew->m_pChild != NULL)
  2066. {
  2067. // Recursively add children
  2068. CMTNode* pNodeCreated = NULL;
  2069. sc = ScCreateMTNodeTree(pNew->m_pChild, pmtnCur, &pNodeCreated);
  2070. if (sc)
  2071. goto finally;
  2072. sc = ScCheckPointers(pNodeCreated, E_UNEXPECTED);
  2073. if (sc)
  2074. goto finally;
  2075. }
  2076. /* Insert Current Node after the last child. If last child is NULL,
  2077. ** insert as the first and only child
  2078. */
  2079. sc = pmtnParent->ScInsertChild(pmtnCur, pmtnParent->LastChild());
  2080. if(sc)
  2081. goto finally;
  2082. if (pmtnFirst == NULL)
  2083. {
  2084. pmtnFirst = pmtnCur;
  2085. }
  2086. pmtnCur = NULL;
  2087. pNew = pNew->m_pNext;
  2088. }
  2089. finally:
  2090. if (sc)
  2091. {
  2092. // error - cleanup before return
  2093. if(pmtnFirst)
  2094. {
  2095. // Ignore returned status code: Already in error
  2096. pmtnParent->ScDeleteTrailingChildren(pmtnFirst);
  2097. }
  2098. if (pmtnCur)
  2099. {
  2100. pmtnCur->Release();
  2101. }
  2102. }
  2103. else
  2104. {
  2105. // assign the tree to be returned
  2106. *ppNodeCreated = pmtnFirst;
  2107. }
  2108. return sc;
  2109. }
  2110. void CScopeTree::Cleanup(void)
  2111. {
  2112. Dbg(DEB_USER1, "CScopeTree::CleanUp\n");
  2113. // Reset the MT node IDs to ROOTNODEID (e.g 1) so the new scope tree
  2114. // can start over correctly with new numbers
  2115. CMTNode::ResetID();
  2116. CComponentIDArray rgID;
  2117. rgID.SetSize(20, 10);
  2118. InformSnapinsOfDeletion(m_pMTNodeRoot, FALSE, rgID);
  2119. SAFE_RELEASE(m_pMTNodeRoot);
  2120. SAFE_RELEASE(m_pImageCache);
  2121. delete m_pDefaultTaskpads; m_pDefaultTaskpads = NULL;
  2122. delete m_pConsoleTaskpads; m_pConsoleTaskpads = NULL;
  2123. }
  2124. STDMETHODIMP CScopeTree::GetImageList(PLONG_PTR pImageList)
  2125. {
  2126. if (pImageList == NULL)
  2127. return E_POINTER;
  2128. HIMAGELIST* phiml = reinterpret_cast<HIMAGELIST *>(pImageList);
  2129. *phiml = GetImageList();
  2130. return ((*phiml) ? S_OK : E_FAIL);
  2131. }
  2132. HIMAGELIST CScopeTree::GetImageList () const
  2133. {
  2134. ASSERT(m_pImageCache != NULL);
  2135. if (m_pImageCache == NULL)
  2136. return NULL;
  2137. return (m_pImageCache->GetImageList()->m_hImageList);
  2138. }
  2139. HRESULT CScopeTree::InsertConsoleTaskpad (CConsoleTaskpad *pConsoleTaskpad,
  2140. CNode *pNodeTarget, bool bStartTaskWizard)
  2141. {
  2142. DECLARE_SC (sc, _T("CScopeTree::InsertConsoleTaskpad"));
  2143. ASSERT(pConsoleTaskpad);
  2144. m_pConsoleTaskpads->push_back(*pConsoleTaskpad);
  2145. // make sure the taskpad now points to the one that is inside the list.
  2146. CConsoleTaskpad & consoleTaskpad = m_pConsoleTaskpads->back();
  2147. pConsoleTaskpad = &consoleTaskpad;
  2148. // reselect all nodes.
  2149. UpdateAllViews(VIEW_RESELECT, 0);
  2150. if(bStartTaskWizard)
  2151. {
  2152. typedef CComObject<CConsoleTaskCallbackImpl> t_TaskCallbackImpl;
  2153. t_TaskCallbackImpl* pTaskCallbackImpl;
  2154. sc = t_TaskCallbackImpl::CreateInstance(&pTaskCallbackImpl);
  2155. if (sc)
  2156. return (sc.ToHr());
  2157. ITaskCallbackPtr spTaskCallback = pTaskCallbackImpl; // addrefs/releases the object.
  2158. sc = pTaskCallbackImpl->ScInitialize(pConsoleTaskpad, this, pNodeTarget);
  2159. if (sc)
  2160. return (sc.ToHr());
  2161. pTaskCallbackImpl->OnNewTask();
  2162. UpdateAllViews(VIEW_RESELECT, 0);
  2163. }
  2164. return (sc.ToHr());
  2165. }
  2166. HRESULT CScopeTree::IsSynchronousExpansionRequired()
  2167. {
  2168. return (_IsSynchronousExpansionRequired() ? S_OK : S_FALSE);
  2169. }
  2170. HRESULT CScopeTree::RequireSynchronousExpansion(BOOL fRequireSyncExpand)
  2171. {
  2172. _RequireSynchronousExpansion (fRequireSyncExpand ? true : false);
  2173. return (S_OK);
  2174. }
  2175. //############################################################################
  2176. //############################################################################
  2177. //
  2178. // CScopeTree Object model methods - SnapIns collection methods
  2179. //
  2180. //############################################################################
  2181. //############################################################################
  2182. /*+-------------------------------------------------------------------------*
  2183. *
  2184. * CScopeTree::ScAdd
  2185. *
  2186. * PURPOSE: Adds a snap-in with the supplied CLSID or PROGID to the console.
  2187. *
  2188. * PARAMETERS:
  2189. * BSTR bstrSnapinNameOrCLSID :
  2190. * VARIANT varProperties
  2191. * SnapIn** ppSnapIn
  2192. *
  2193. * RETURNS:
  2194. * SC
  2195. *
  2196. *+-------------------------------------------------------------------------*/
  2197. SC
  2198. CScopeTree::ScAdd(
  2199. BSTR bstrSnapinNameOrCLSID, /* I:what snap-in? */
  2200. VARIANT varParentSnapinNode, /* I:Snapin under which this new snapin will be added (optional)*/
  2201. VARIANT varProperties, /* I:props to create with (optional)*/
  2202. SnapIn** ppSnapIn) /* O:created snap-in */
  2203. {
  2204. DECLARE_SC(sc, TEXT("CScopeTree::ScAdd"));
  2205. /*
  2206. * dereference VT_BYREF VARIANTs that VBScript might have passed us
  2207. */
  2208. VARIANT* pProperties = ConvertByRefVariantToByValue (&varProperties);
  2209. VARIANT* pParentSnapinNode = ConvertByRefVariantToByValue (&varParentSnapinNode);
  2210. /*
  2211. * validate the parameters
  2212. */
  2213. sc = ScCheckPointers(ppSnapIn, pProperties, pParentSnapinNode);
  2214. if (sc)
  2215. return (sc);
  2216. /*
  2217. * Get the properties for the new snap-in. This is an optional
  2218. * parameter, so VT_ERROR with DISP_E_PARAMNOTFOUND is OK
  2219. */
  2220. PropertiesPtr spProperties;
  2221. if (!IsOptionalParamMissing (*pProperties))
  2222. {
  2223. /*
  2224. * Assign from the VARIANT (ain't smart pointers great?).
  2225. * If the QI returned E_NOINTERFACE, the smart pointer will be
  2226. * assigned NULL. If the QI failed in some other way, operator=
  2227. * will throw a _com_error containing the failure HRESULT.
  2228. */
  2229. try
  2230. {
  2231. if ((spProperties = _variant_t(*pProperties)) == NULL)
  2232. sc = E_NOINTERFACE;
  2233. }
  2234. catch (_com_error& err)
  2235. {
  2236. sc = err.Error();
  2237. }
  2238. if (sc)
  2239. return (sc.ToHr());
  2240. }
  2241. /*
  2242. * Get the parent snapin node for the new snap-in. This is an optional
  2243. * parameter, so VT_ERROR with DISP_E_PARAMNOTFOUND is OK
  2244. */
  2245. SnapInPtr spParentSnapIn;
  2246. if (!IsOptionalParamMissing (*pParentSnapinNode))
  2247. {
  2248. /*
  2249. * Assign from the VARIANT (ain't smart pointers great?).
  2250. * If the QI returned E_NOINTERFACE, the smart pointer will be
  2251. * assigned NULL. If the QI failed in some other way, operator=
  2252. * will throw a _com_error containing the failure HRESULT.
  2253. */
  2254. try
  2255. {
  2256. if ((spParentSnapIn = _variant_t(*pParentSnapinNode)) == NULL)
  2257. sc = E_NOINTERFACE;
  2258. }
  2259. catch (_com_error& err)
  2260. {
  2261. sc = err.Error();
  2262. }
  2263. if (sc)
  2264. return (sc.ToHr());
  2265. }
  2266. sc = ScAddSnapin(bstrSnapinNameOrCLSID, spParentSnapIn, spProperties, *ppSnapIn);
  2267. return sc.ToHr();
  2268. }
  2269. //+-------------------------------------------------------------------
  2270. //
  2271. // Member: CScopeTree:ScRemove
  2272. //
  2273. // Synopsis: Remove given snapin.
  2274. //
  2275. // Arguments: [pSnapIn] - the snapin (disp) interface.
  2276. //
  2277. // Returns: SC
  2278. //
  2279. //--------------------------------------------------------------------
  2280. SC CScopeTree::ScRemove (PSNAPIN pSnapIn)
  2281. {
  2282. DECLARE_SC(sc, _T("CScopeTree:ScRemove"));
  2283. sc = ScCheckPointers(pSnapIn);
  2284. if (sc)
  2285. return sc;
  2286. // Get the MTNode for this snapin root.
  2287. CMTSnapInNode *pMTSnapinNode = NULL;
  2288. sc = CMTSnapInNode::ScGetCMTSnapinNode(pSnapIn, &pMTSnapinNode);
  2289. if (sc)
  2290. return sc;
  2291. CSnapinManager snapinMgr(GetRoot());
  2292. // Ask snapin mgr to add this snapin to deletednodes list.
  2293. sc = snapinMgr.ScRemoveSnapin(pMTSnapinNode);
  2294. if (sc)
  2295. return sc;
  2296. // Update the scope tree with changes made by snapin manager.
  2297. sc = ScAddOrRemoveSnapIns(snapinMgr.GetDeletedNodesList(),
  2298. snapinMgr.GetNewNodes());
  2299. if (sc)
  2300. return sc;
  2301. return (sc);
  2302. }
  2303. /*+-------------------------------------------------------------------------*
  2304. *
  2305. * CScopeTree::GetNextStaticNode
  2306. *
  2307. * PURPOSE: Returns the next static node (either the child or sibling) of the supplied node.
  2308. * This is slightly different from CMTNode::NextStaticNode(), which includes the node
  2309. * itself in the search.
  2310. *
  2311. * PARAMETERS:
  2312. * CMTNode *pMTNode : The supplied node.
  2313. *
  2314. * RETURNS:
  2315. * CMTSnapInNode *
  2316. *
  2317. *+-------------------------------------------------------------------------*/
  2318. CMTSnapInNode *
  2319. CScopeTree::GetNextStaticNode(CMTNode *pMTNode)
  2320. {
  2321. CMTSnapInNode *pMTSnapInNode = NULL;
  2322. if(!pMTNode)
  2323. return NULL;
  2324. // go thru all the children, then thru all the siblings.
  2325. CMTNode *pMTNodeChild = pMTNode->Child();
  2326. CMTNode *pMTNodeNext = pMTNode->Next();
  2327. CMTNode *pMTNodeParent= pMTNode->Parent();
  2328. // see if the child is a snapin
  2329. pMTSnapInNode = dynamic_cast<CMTSnapInNode*>(pMTNodeChild);
  2330. if(pMTSnapInNode)
  2331. return pMTSnapInNode;
  2332. // the child wasn't a snap-in node. Try its children.
  2333. if(pMTNodeChild)
  2334. {
  2335. pMTSnapInNode = GetNextStaticNode(pMTNodeChild);
  2336. if(pMTSnapInNode)
  2337. return pMTSnapInNode;
  2338. }
  2339. // That didn't work either. Check to see if the next node is a snapin
  2340. pMTSnapInNode = dynamic_cast<CMTSnapInNode*>(pMTNodeNext);
  2341. if(pMTSnapInNode)
  2342. return pMTSnapInNode;
  2343. // the next node wasn't a snap-in node. Try its children.
  2344. if(pMTNodeNext)
  2345. {
  2346. pMTSnapInNode = GetNextStaticNode(pMTNodeNext);
  2347. if(pMTSnapInNode)
  2348. return pMTSnapInNode;
  2349. }
  2350. // nothing was found in the next node's tree. Go to the next node of the parent.
  2351. if(pMTNodeParent)
  2352. {
  2353. CMTNode *pMTNodeParentNext = pMTNodeParent->Next();
  2354. if(pMTNodeParentNext)
  2355. {
  2356. pMTSnapInNode = dynamic_cast<CMTSnapInNode*>(pMTNodeParentNext);
  2357. if(pMTSnapInNode)
  2358. return pMTSnapInNode;
  2359. // the parent's next node was not a snapin node. Try its children
  2360. return GetNextStaticNode(pMTNodeParentNext);
  2361. }
  2362. }
  2363. // nothing left.
  2364. return NULL;
  2365. }
  2366. /*+-------------------------------------------------------------------------*
  2367. *
  2368. * CScopeTree::ScItem
  2369. *
  2370. * PURPOSE: Returns a pointer to the i'th snap-in object.
  2371. *
  2372. * PARAMETERS:
  2373. * long Index : 1-based.
  2374. * PPSNAPIN ppSnapIn :
  2375. *
  2376. * RETURNS:
  2377. * SC
  2378. *
  2379. *+-------------------------------------------------------------------------*/
  2380. SC
  2381. CScopeTree::ScItem(long Index, PPSNAPIN ppSnapIn)
  2382. {
  2383. DECLARE_SC(sc, TEXT("CScopeTree::ScItem"));
  2384. // check parameters.
  2385. if( (Index <= 0) || (!ppSnapIn) )
  2386. return (sc = E_INVALIDARG);
  2387. CMTNode * pMTNode = GetRoot();
  2388. if(!pMTNode)
  2389. return (sc = E_UNEXPECTED);
  2390. CMTSnapInNode * pMTSINode = dynamic_cast<CMTSnapInNode*>(pMTNode);
  2391. // This should not be true as console root is a snapin.
  2392. sc = ScCheckPointers(pMTSINode, E_UNEXPECTED);
  2393. if (sc)
  2394. return sc;
  2395. while(--Index)
  2396. {
  2397. pMTSINode = GetNextStaticNode(pMTSINode);
  2398. if(!pMTSINode)
  2399. return (sc = E_INVALIDARG); // no more snap-ins. Argument was out of bounds.
  2400. }
  2401. if(!pMTSINode)
  2402. return (sc = E_UNEXPECTED); // defensive. Should never happen.
  2403. sc = pMTSINode->ScGetSnapIn(ppSnapIn);
  2404. return sc;
  2405. }
  2406. /*+-------------------------------------------------------------------------*
  2407. *
  2408. * CScopeTree::Scget_Count
  2409. *
  2410. * PURPOSE: Returns the number of stand alone snapins in the collection.
  2411. *
  2412. * PARAMETERS:
  2413. * PLONG Ptr to count.
  2414. *
  2415. * RETURNS:
  2416. * SC
  2417. *
  2418. *+-------------------------------------------------------------------------*/
  2419. SC
  2420. CScopeTree::Scget_Count(PLONG pCount)
  2421. {
  2422. DECLARE_SC(sc, TEXT("CScopeTree::Scget_Count"));
  2423. sc = ScCheckPointers(pCount);
  2424. if (sc)
  2425. return sc;
  2426. *pCount = 0;
  2427. CMTNode * pMTNode = GetRoot();
  2428. if(!pMTNode)
  2429. return (sc = E_UNEXPECTED);
  2430. CMTSnapInNode * pMTSINode = dynamic_cast<CMTSnapInNode*>(pMTNode);
  2431. // This should not be true as console root is a snapin.
  2432. sc = ScCheckPointers(pMTSINode, E_UNEXPECTED);
  2433. if (sc)
  2434. return sc;
  2435. // Count all the static nodes (that are snapins).
  2436. do
  2437. {
  2438. (*pCount)++;
  2439. } while( (pMTSINode = GetNextStaticNode(pMTSINode)) != NULL);
  2440. return sc;
  2441. }
  2442. //############################################################################
  2443. //############################################################################
  2444. //
  2445. // CScopeTree Object model methods - SnapIns enumerator
  2446. //
  2447. //############################################################################
  2448. //############################################################################
  2449. /*+-------------------------------------------------------------------------*
  2450. *
  2451. * CScopeTree::ScGetNextSnapInPos
  2452. *
  2453. * PURPOSE: Returns the next snap-in in position.
  2454. *
  2455. * PARAMETERS:
  2456. * CSnapIns_Positon & pos : [in, out]: Must be non-NULL.
  2457. *
  2458. *
  2459. *
  2460. * RETURNS:
  2461. * SC: S_FALSE if there are no more items in the collection
  2462. *
  2463. *+-------------------------------------------------------------------------*/
  2464. SC
  2465. CScopeTree::ScGetNextSnapInPos(CSnapIns_Positon &pos)
  2466. {
  2467. DECLARE_SC(sc, TEXT("CScopeTree::ScGetNextSnapInPos"));
  2468. if(pos == NULL)
  2469. return (sc = S_FALSE);
  2470. // for safety, copy the value and zero the output
  2471. CSnapIns_Positon posIn = pos;
  2472. pos = NULL;
  2473. ASSERT(posIn != NULL); //sanity check, already checked above.
  2474. CMTNode * pMTNode = GetRoot();
  2475. if(!pMTNode)
  2476. {
  2477. return (sc = E_UNEXPECTED);
  2478. }
  2479. CMTSnapInNode * pMTSINode = dynamic_cast<CMTSnapInNode*>(pMTNode);
  2480. if(!pMTSINode)
  2481. return (sc = S_FALSE);
  2482. // If we're not starting at the beginning, look for the current position.
  2483. // walk down the tree looking for the snap-in.
  2484. // although the position pointer is simply the pointer, we cannot dereference
  2485. // it because it may not be valid anymore.
  2486. while(pMTSINode != NULL)
  2487. {
  2488. CMTSnapInNode *pMTSINodeNext = GetNextStaticNode(pMTSINode);
  2489. if(posIn == pMTSINode) // found the position. Return the next one
  2490. {
  2491. pos = pMTSINodeNext;
  2492. return (sc = (pos == NULL) ? S_FALSE : S_OK);
  2493. }
  2494. pMTSINode = pMTSINodeNext;
  2495. }
  2496. return (sc = S_FALSE);
  2497. }
  2498. /*+-------------------------------------------------------------------------*
  2499. *
  2500. * CScopeTree::ScEnumNext
  2501. *
  2502. * PURPOSE: Returns the next snapin object pointer.
  2503. *
  2504. * PARAMETERS:
  2505. * _Position & pos :
  2506. * PDISPATCH & pDispatch :
  2507. *
  2508. * RETURNS:
  2509. * SC
  2510. *
  2511. *+-------------------------------------------------------------------------*/
  2512. SC
  2513. CScopeTree::ScEnumNext(CSnapIns_Positon &pos, PDISPATCH & pDispatch)
  2514. {
  2515. DECLARE_SC(sc, TEXT("CScopeTree::ScEnumNext"));
  2516. if( NULL==pos )
  2517. {
  2518. sc = S_FALSE;
  2519. return sc;
  2520. }
  2521. // at this point, we have a valid position.
  2522. SnapInPtr spSnapIn;
  2523. sc = pos->ScGetSnapIn(&spSnapIn);
  2524. if(sc)
  2525. return sc;
  2526. if(spSnapIn == NULL)
  2527. {
  2528. sc = E_UNEXPECTED; // should never happen.
  2529. return sc;
  2530. }
  2531. /*
  2532. * return the IDispatch for the object and leave a ref on it for the client
  2533. */
  2534. pDispatch = spSnapIn.Detach();
  2535. //ignore this error
  2536. ScGetNextSnapInPos(pos); // this gets the correct pointer without dereferencing the present one.
  2537. return sc;
  2538. }
  2539. /*+-------------------------------------------------------------------------*
  2540. *
  2541. * CScopeTree::ScEnumSkip
  2542. *
  2543. * PURPOSE: Skips the next celt items
  2544. *
  2545. * PARAMETERS:
  2546. * unsigned long :
  2547. * CSnapIns_Positon & pos :
  2548. *
  2549. * RETURNS:
  2550. * SC
  2551. *
  2552. *+-------------------------------------------------------------------------*/
  2553. SC
  2554. CScopeTree::ScEnumSkip(unsigned long celt, unsigned long& celtSkipped, CSnapIns_Positon &pos)
  2555. {
  2556. DECLARE_SC(sc, TEXT("CScopeTree::ScEnumSkip"));
  2557. // skip celt positions, don't check the last skip.
  2558. for(celtSkipped =0; celtSkipped<celt; celt++)
  2559. {
  2560. if (pos == NULL)
  2561. {
  2562. sc = S_FALSE;
  2563. return sc;
  2564. }
  2565. // go to the next view
  2566. sc = ScGetNextSnapInPos(pos);
  2567. if(sc.IsError() || sc == SC(S_FALSE))
  2568. return sc;
  2569. }
  2570. return sc;
  2571. }
  2572. /*+-------------------------------------------------------------------------*
  2573. *
  2574. * CScopeTree::ScEnumReset
  2575. *
  2576. * PURPOSE: Sets the position to the first item
  2577. *
  2578. * PARAMETERS:
  2579. * CSnapIns_Positon & pos :
  2580. *
  2581. * RETURNS:
  2582. * SC
  2583. *
  2584. *+-------------------------------------------------------------------------*/
  2585. SC
  2586. CScopeTree::ScEnumReset(CSnapIns_Positon &pos)
  2587. {
  2588. DECLARE_SC(sc, TEXT("CScopeTree::ScEnumReset"));
  2589. // initial case. Return Console Root.
  2590. pos = dynamic_cast<CMTSnapInNode*>(CScopeTree::GetScopeTree()->GetRoot());
  2591. return sc;
  2592. }
  2593. //############################################################################
  2594. //############################################################################
  2595. //
  2596. // CScopeTree Object model methods - ScopeNamespace methods
  2597. //
  2598. //############################################################################
  2599. //############################################################################
  2600. /*+-------------------------------------------------------------------------*
  2601. *
  2602. * ScCheckInputs
  2603. *
  2604. * PURPOSE: little helper for the following three functions.
  2605. *
  2606. * PARAMETERS:
  2607. * PNODE pNode : Checked for NULL, and that it is a CMMCScopeNode.
  2608. * Also pNode->m_pMTNode is checked for NULL.
  2609. * PPNODE ppNode : Checked for NULL.
  2610. * PMTNODE pMTNode: [out]: pNode->m_pMTNode;
  2611. *
  2612. * RETURNS:
  2613. * inline SC
  2614. *
  2615. *+-------------------------------------------------------------------------*/
  2616. inline SC
  2617. ScCheckInputs(PNODE pNode, PPNODE ppNode, PMTNODE & pMTNode)
  2618. {
  2619. SC sc; // don't need DECLARE_SC here.
  2620. // check parameters
  2621. if( (NULL == pNode) || (NULL == ppNode) )
  2622. {
  2623. sc = E_INVALIDARG;
  2624. return sc;
  2625. }
  2626. // make sure we have a scope node
  2627. CMMCScopeNode *pScopeNode = dynamic_cast<CMMCScopeNode *>(pNode);
  2628. if(!pScopeNode)
  2629. {
  2630. sc = E_INVALIDARG;
  2631. return sc;
  2632. }
  2633. // make sure it's node pointer is good
  2634. if(!pScopeNode->GetMTNode())
  2635. {
  2636. sc = E_UNEXPECTED;
  2637. return sc;
  2638. }
  2639. pMTNode = pScopeNode->GetMTNode();
  2640. return sc;
  2641. }
  2642. /*+-------------------------------------------------------------------------*
  2643. *
  2644. * CScopeTree::ScGetParent
  2645. *
  2646. * PURPOSE:
  2647. *
  2648. * PARAMETERS:
  2649. * PNODE pNode :
  2650. * PPNODE ppParent :
  2651. *
  2652. * RETURNS:
  2653. * SC
  2654. *
  2655. *+-------------------------------------------------------------------------*/
  2656. SC
  2657. CScopeTree::ScGetParent(PNODE pNode, PPNODE ppParent)
  2658. {
  2659. DECLARE_SC(sc, TEXT("CScopeTree::ScGetParent"));
  2660. PMTNODE pMTNode = NULL;
  2661. // check parameters
  2662. sc = ScCheckInputs(pNode, ppParent, pMTNode);
  2663. if(sc)
  2664. return sc;
  2665. sc = ScGetNode(pMTNode->Parent(), ppParent);
  2666. return sc;
  2667. }
  2668. /*+-------------------------------------------------------------------------*
  2669. *
  2670. * CScopeTree::ScGetChild
  2671. *
  2672. * PURPOSE:
  2673. *
  2674. * PARAMETERS:
  2675. * PNODE pNode :
  2676. * PPNODE ppChild :
  2677. *
  2678. * RETURNS:
  2679. * SC
  2680. *
  2681. *+-------------------------------------------------------------------------*/
  2682. SC
  2683. CScopeTree::ScGetChild(PNODE pNode, PPNODE ppChild)
  2684. {
  2685. DECLARE_SC(sc, TEXT("CScopeTree::ScGetChild"));
  2686. PMTNODE pMTNode = NULL;
  2687. // check parameters
  2688. sc = ScCheckInputs(pNode, ppChild, pMTNode);
  2689. if(sc)
  2690. return sc;
  2691. sc = ScGetNode(pMTNode->Child(), ppChild);
  2692. return sc;
  2693. }
  2694. /*+-------------------------------------------------------------------------*
  2695. *
  2696. * CScopeTree::ScGetNext
  2697. *
  2698. * PURPOSE:
  2699. *
  2700. * PARAMETERS:
  2701. * PNODE pNode :
  2702. * PPNODE ppNext :
  2703. *
  2704. * RETURNS:
  2705. * SC
  2706. *
  2707. *+-------------------------------------------------------------------------*/
  2708. SC
  2709. CScopeTree::ScGetNext(PNODE pNode, PPNODE ppNext)
  2710. {
  2711. DECLARE_SC(sc, TEXT("CScopeTree::ScGetNext"));
  2712. PMTNODE pMTNode = NULL;
  2713. // check parameters
  2714. sc = ScCheckInputs(pNode, ppNext, pMTNode);
  2715. if(sc)
  2716. return sc;
  2717. sc = ScGetNode(pMTNode->Next(), ppNext);
  2718. return sc;
  2719. }
  2720. /*+-------------------------------------------------------------------------*
  2721. *
  2722. * CScopeTree::ScGetRoot
  2723. *
  2724. * PURPOSE: Returns a COM object for the Root the Root node.
  2725. *
  2726. * PARAMETERS:
  2727. * PPNODE ppRoot :
  2728. *
  2729. * RETURNS:
  2730. * SC
  2731. *
  2732. *+-------------------------------------------------------------------------*/
  2733. SC
  2734. CScopeTree::ScGetRoot(PPNODE ppRoot)
  2735. {
  2736. DECLARE_SC(sc, TEXT("CScopeTree::ScGetRoot"));
  2737. sc = ScGetRootNode(ppRoot);
  2738. return sc;
  2739. }
  2740. //+-------------------------------------------------------------------
  2741. //
  2742. // Member: CScopeTree::ScGetRootNode
  2743. //
  2744. // Synopsis: Helper that returns a COM object for the Root node.
  2745. //
  2746. // Arguments: [ppRootNode] - The root node ptr.
  2747. //
  2748. // Returns: SC
  2749. //
  2750. //--------------------------------------------------------------------
  2751. SC CScopeTree::ScGetRootNode (PPNODE ppRootNode)
  2752. {
  2753. DECLARE_SC(sc, _T("CScopeTree::ScGetRootNode"));
  2754. sc = ScCheckPointers(ppRootNode);
  2755. if (sc)
  2756. return sc;
  2757. CMTNode* pMTRootNode = GetRoot();
  2758. sc = ScCheckPointers(pMTRootNode, E_UNEXPECTED);
  2759. if (sc)
  2760. return sc;
  2761. sc = ScGetNode(pMTRootNode, ppRootNode);
  2762. if (sc)
  2763. return sc;
  2764. return (sc);
  2765. }
  2766. /*+-------------------------------------------------------------------------*
  2767. *
  2768. * CScopeTree::ScExpand
  2769. *
  2770. * PURPOSE: Implements ScopeNameSpace::Expand. Expands the specified node.
  2771. *
  2772. * PARAMETERS:
  2773. * PNODE pNode :
  2774. *
  2775. * RETURNS:
  2776. * SC
  2777. *
  2778. *+-------------------------------------------------------------------------*/
  2779. SC
  2780. CScopeTree::ScExpand(PNODE pNode)
  2781. {
  2782. DECLARE_SC(sc, TEXT("CScopeTree::ScExpand"));
  2783. // check parameters
  2784. sc = ScCheckPointers(pNode);
  2785. if(sc)
  2786. return sc;
  2787. // make sure we have a scope node
  2788. CMMCScopeNode *pScopeNode = dynamic_cast<CMMCScopeNode *>(pNode);
  2789. if(!pScopeNode)
  2790. {
  2791. sc = E_INVALIDARG;
  2792. return sc;
  2793. }
  2794. // make sure it's node pointer is good
  2795. CMTNode* pMTNode = pScopeNode->GetMTNode();
  2796. if(!pMTNode)
  2797. {
  2798. sc = E_UNEXPECTED;
  2799. return sc;
  2800. }
  2801. if ( !pMTNode->WasExpandedAtLeastOnce() )
  2802. {
  2803. sc = pMTNode->Expand();
  2804. if (sc)
  2805. return sc;
  2806. }
  2807. return sc;
  2808. }
  2809. SC
  2810. CScopeTree::ScGetNode(CMTNode *pMTNode, PPNODE ppOut)
  2811. {
  2812. DECLARE_SC(sc, TEXT("CScopeTree::ScGetNode"));
  2813. sc = ScCheckPointers(pMTNode, ppOut);
  2814. if(sc)
  2815. return sc;
  2816. *ppOut = NULL;
  2817. CMapMTNodeToMMCNode::iterator it = m_mapMTNodeToMMCNode.find(pMTNode);
  2818. if (it == m_mapMTNodeToMMCNode.end())
  2819. {
  2820. // not found - got to create one
  2821. typedef CComObject<CMMCScopeNode> CScopeNode;
  2822. CScopeNode *pScopeNode = NULL;
  2823. CScopeNode::CreateInstance(&pScopeNode);
  2824. sc = ScCheckPointers(pScopeNode, E_OUTOFMEMORY);
  2825. if(sc)
  2826. return sc;
  2827. // set up the internal pointer.
  2828. pScopeNode->m_pMTNode = pMTNode;
  2829. m_mapMTNodeToMMCNode.insert(CMapMTNodeToMMCNode::value_type(pMTNode, pScopeNode));
  2830. *ppOut = pScopeNode;
  2831. }
  2832. else
  2833. {
  2834. #ifdef DBG
  2835. CMMCScopeNode *pScopeNode = dynamic_cast<CMMCScopeNode *>(it->second);
  2836. // just doublecheck the pointers
  2837. ASSERT(pScopeNode && pScopeNode->GetMTNode() == pMTNode);
  2838. #endif // DBG
  2839. *ppOut = it->second;
  2840. }
  2841. (*ppOut)->AddRef(); // addref the object for the client.
  2842. return sc;
  2843. }
  2844. /*+-------------------------------------------------------------------------*
  2845. *
  2846. * CScopeTree::ScGetNode
  2847. *
  2848. * PURPOSE: Returns the CMTNode encapsulated by a Node.
  2849. *
  2850. * PARAMETERS:
  2851. * PNODE pNode :
  2852. * CMTNode * ppMTNodeOut : The return value.
  2853. *
  2854. * RETURNS:
  2855. * SC
  2856. *
  2857. *+-------------------------------------------------------------------------*/
  2858. SC
  2859. CScopeTree::ScGetNode(PNODE pNode, CMTNode **ppMTNodeOut)
  2860. {
  2861. DECLARE_SC(sc, TEXT("CScopeTree::ScGetNode"));
  2862. sc = ScCheckPointers(pNode, ppMTNodeOut);
  2863. if (sc)
  2864. return sc;
  2865. // make sure we have a scope node
  2866. CMMCScopeNode *pScopeNode = dynamic_cast<CMMCScopeNode *>(pNode);
  2867. if(!pScopeNode)
  2868. return (sc =E_FAIL);
  2869. *ppMTNodeOut = pScopeNode->GetMTNode();
  2870. return sc;
  2871. }
  2872. /*+-------------------------------------------------------------------------*
  2873. *
  2874. * CScopeTree::GetHMTNode
  2875. *
  2876. * PURPOSE: returns the HMTNode for a node object
  2877. *
  2878. * PARAMETERS:
  2879. * PNODE pNode :
  2880. * HMTNODE * phMTNode :
  2881. *
  2882. * RETURNS:
  2883. * HRESULT
  2884. *
  2885. *+-------------------------------------------------------------------------*/
  2886. HRESULT
  2887. CScopeTree::GetHMTNode(PNODE pNode, HMTNODE *phMTNode)
  2888. {
  2889. DECLARE_SC(sc, TEXT("CScopeTree::GetHMTNode"));
  2890. sc = ScCheckPointers(pNode, phMTNode);
  2891. if (sc)
  2892. return sc.ToHr();
  2893. // initialize output
  2894. *phMTNode = NULL;
  2895. // make sure we have a scope node
  2896. CMMCScopeNode *pScopeNode = dynamic_cast<CMMCScopeNode *>(pNode);
  2897. if(!pScopeNode)
  2898. {
  2899. // Not a valid node - that's expected. Do not assert nor trace
  2900. return E_FAIL;
  2901. }
  2902. CMTNode *pMTNode = pScopeNode->GetMTNode();
  2903. sc = ScCheckPointers(pMTNode, E_UNEXPECTED);
  2904. if (sc)
  2905. return sc.ToHr();
  2906. *phMTNode = CMTNode::ToHandle(pMTNode);
  2907. return sc.ToHr();
  2908. }
  2909. /*+-------------------------------------------------------------------------*
  2910. *
  2911. * CScopeTree::GetNodeID
  2912. *
  2913. * PURPOSE: returns node id for Node object
  2914. *
  2915. * PARAMETERS:
  2916. *
  2917. * RETURNS:
  2918. * SC
  2919. *
  2920. *+-------------------------------------------------------------------------*/
  2921. HRESULT CScopeTree::GetNodeID(PNODE pNode, MTNODEID *pID)
  2922. {
  2923. DECLARE_SC(sc, TEXT("CScopeTree::GetNodeID"));
  2924. sc = ScCheckPointers(pNode, pID);
  2925. if (sc)
  2926. return sc.ToHr();
  2927. // make sure we have a scope node
  2928. CMMCScopeNode *pScopeNode = dynamic_cast<CMMCScopeNode *>(pNode);
  2929. if(!pScopeNode)
  2930. {
  2931. // Not a valid node - that's expected. Do not assert nor trace
  2932. return E_FAIL;
  2933. }
  2934. CMTNode *pMTNode = pScopeNode->GetMTNode();
  2935. sc = ScCheckPointers(pMTNode, E_UNEXPECTED);
  2936. if (sc)
  2937. return sc.ToHr();
  2938. *pID = pMTNode->GetID();
  2939. return sc.ToHr();
  2940. }
  2941. /*+-------------------------------------------------------------------------*
  2942. *
  2943. * CScopeTree::GetNode
  2944. *
  2945. * PURPOSE: returns Node object referencing the specified node id
  2946. *
  2947. * PARAMETERS:
  2948. *
  2949. * RETURNS:
  2950. * SC
  2951. *
  2952. *+-------------------------------------------------------------------------*/
  2953. HRESULT CScopeTree::GetMMCNode(HMTNODE hMTNode, PPNODE ppNode)
  2954. {
  2955. DECLARE_SC(sc, TEXT("CScopeTree::GetMMCNode"));
  2956. // parameter checking
  2957. sc = ScCheckPointers((LPVOID)hMTNode);
  2958. if (sc)
  2959. return sc.ToHr();
  2960. // get the node
  2961. sc = ScGetNode(CMTNode::FromHandle(hMTNode), ppNode);
  2962. if (sc)
  2963. return sc.ToHr();
  2964. return sc.ToHr();
  2965. }
  2966. /*+-------------------------------------------------------------------------*
  2967. *
  2968. * CCScopeTree::ScUnadviseMTNode
  2969. *
  2970. * PURPOSE: informs Node objects about MTNode going down
  2971. *
  2972. * PARAMETERS:
  2973. *
  2974. * RETURNS:
  2975. * SC
  2976. *
  2977. *+-------------------------------------------------------------------------*/
  2978. SC CScopeTree::ScUnadviseMTNode(CMTNode* pMTNode)
  2979. {
  2980. DECLARE_SC(sc, TEXT("CScopeTree::ScUnadviseMTNode"));
  2981. sc = ScCheckPointers(pMTNode);
  2982. if (sc)
  2983. return sc;
  2984. CMapMTNodeToMMCNode::iterator it = m_mapMTNodeToMMCNode.find(pMTNode);
  2985. // need to tell the com object [if we have one] this is the end of MTNode
  2986. if (it != m_mapMTNodeToMMCNode.end())
  2987. {
  2988. // make sure we have a scope node
  2989. CMMCScopeNode *pScopeNode = dynamic_cast<CMMCScopeNode *>(it->second);
  2990. sc = ScCheckPointers(pScopeNode, E_UNEXPECTED);
  2991. if (sc)
  2992. return sc;
  2993. ASSERT(pScopeNode->GetMTNode() == pMTNode);
  2994. // can forget about the object from now on
  2995. pScopeNode->ResetMTNode();
  2996. m_mapMTNodeToMMCNode.erase(it);
  2997. }
  2998. return sc;
  2999. }
  3000. /*+-------------------------------------------------------------------------*
  3001. *
  3002. * CScopeTree::ScUnadviseMMCScopeNode
  3003. *
  3004. * PURPOSE: informs Scope tree about Node object about to be destroyed
  3005. *
  3006. * PARAMETERS:
  3007. *
  3008. * RETURNS:
  3009. * SC
  3010. *
  3011. *+-------------------------------------------------------------------------*/
  3012. SC CScopeTree::ScUnadviseMMCScopeNode(PNODE pNode)
  3013. {
  3014. DECLARE_SC(sc, TEXT("CScopeTree::ScUnadviseMMCScopeNode"));
  3015. sc = ScCheckPointers(pNode);
  3016. if (sc)
  3017. return sc;
  3018. CMMCScopeNode *pScopeNode = dynamic_cast<CMMCScopeNode *>(pNode);
  3019. sc = ScCheckPointers(pScopeNode, E_UNEXPECTED);
  3020. if (sc)
  3021. return sc;
  3022. CMTNode* pMTNode = pScopeNode->GetMTNode();
  3023. if (!pMTNode)
  3024. {
  3025. // orphan entry - ignore
  3026. #ifdef DBG
  3027. // to detect leaks in keeping the registry
  3028. CMapMTNodeToMMCNode::iterator it = m_mapMTNodeToMMCNode.begin();
  3029. while (it != m_mapMTNodeToMMCNode.end())
  3030. {
  3031. ASSERT(it->second != pNode);
  3032. ++it;
  3033. }
  3034. #endif
  3035. return sc;
  3036. }
  3037. CMapMTNodeToMMCNode::iterator it = m_mapMTNodeToMMCNode.find(pMTNode);
  3038. // need to tell the com object [i.e. itself] this is the end of relationship with MTNode
  3039. if (it == m_mapMTNodeToMMCNode.end())
  3040. return sc = E_UNEXPECTED;
  3041. // make sure we really talking to itself
  3042. ASSERT(pScopeNode->GetMTNode() == pMTNode);
  3043. // can forget about the MTNode from now on
  3044. pScopeNode->ResetMTNode();
  3045. m_mapMTNodeToMMCNode.erase(it);
  3046. return sc;
  3047. }
  3048. /***************************************************************************\
  3049. *
  3050. * METHOD: CScopeTree::IsSnapinInUse
  3051. *
  3052. * PURPOSE: checks if snapin is in use by MMC.
  3053. * (check is done by examining snapin cache)
  3054. *
  3055. * PARAMETERS:
  3056. * REFCLSID refClsidSnapIn - [in] - snapin to examine
  3057. * PBOOL pbInUse - [out] - verification result
  3058. *
  3059. * RETURNS:
  3060. * SC - result code
  3061. *
  3062. \***************************************************************************/
  3063. STDMETHODIMP CScopeTree::IsSnapinInUse(/*[in]*/ REFCLSID refClsidSnapIn, /*[out]*/ PBOOL pbInUse)
  3064. {
  3065. DECLARE_SC(sc, TEXT("CScopeTree::IsSnapinInUse"));
  3066. // parameter check
  3067. sc = ScCheckPointers(pbInUse);
  3068. if (sc)
  3069. return sc.ToHr();
  3070. // out parameter initialization
  3071. *pbInUse = FALSE;
  3072. // getting the cache
  3073. CSnapInsCache* pCache = theApp.GetSnapInsCache();
  3074. sc = ScCheckPointers(pCache, E_UNEXPECTED);
  3075. if (sc)
  3076. return sc.ToHr();
  3077. // assume it exists
  3078. *pbInUse = TRUE;
  3079. // looup snapin
  3080. CSnapInPtr spSnapIn;
  3081. sc = pCache->ScFindSnapIn(refClsidSnapIn, &spSnapIn);
  3082. if(sc)
  3083. {
  3084. // if failed to find - assume one does not exist
  3085. *pbInUse = FALSE;
  3086. // no trace if not found
  3087. sc.Clear();
  3088. }
  3089. return sc.ToHr();
  3090. }
  3091. //+-------------------------------------------------------------------
  3092. //
  3093. // Member: CScopeTree::ScSetHelpCollectionInvalid
  3094. //
  3095. // Synopsis: Inform the document that help collection is invalid
  3096. //
  3097. // Arguments:
  3098. //
  3099. // Returns: SC
  3100. //
  3101. //--------------------------------------------------------------------
  3102. SC CScopeTree::ScSetHelpCollectionInvalid ()
  3103. {
  3104. DECLARE_SC(sc, _T("CScopeTree::ScSetHelpCollectionInvalid"));
  3105. sc = ScCheckPointers(m_pConsoleData, m_pConsoleData->m_pConsoleDocument, E_UNEXPECTED);
  3106. if (sc)
  3107. return sc;
  3108. sc = m_pConsoleData->m_pConsoleDocument->ScSetHelpCollectionInvalid();
  3109. return (sc);
  3110. }