Source code of Windows XP (NT5)
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.

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