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.

1393 lines
37 KiB

  1. //____________________________________________________________________________
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997 - 1999
  5. //
  6. // File: ctrlbar.cpp
  7. //
  8. // Contents:
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History:
  15. //____________________________________________________________________________
  16. //
  17. #include "stdafx.h"
  18. #include "menubtn.h"
  19. #include "viewdata.h"
  20. #include "amcmsgid.h"
  21. #include "regutil.h"
  22. #include "commctrl.h"
  23. #include "multisel.h"
  24. #include "rsltitem.h"
  25. #include "conview.h"
  26. #include "util.h"
  27. #include "nodemgrdebug.h"
  28. #ifdef _DEBUG
  29. #undef THIS_FILE
  30. static char THIS_FILE[] = __FILE__;
  31. #endif
  32. // Snapin name needed for debug information.
  33. inline void Debug_SetControlbarSnapinName(const CLSID& clsidSnapin, CControlbar* pControlbar)
  34. {
  35. #ifdef DBG
  36. tstring tszSnapinName;
  37. bool bRet = GetSnapinNameFromCLSID(clsidSnapin, tszSnapinName);
  38. if (bRet)
  39. pControlbar->SetSnapinName(tszSnapinName.data());
  40. #endif
  41. }
  42. //////////////////////////////////////////////////////////////////////////////
  43. // IControlbar implementation
  44. DEBUG_DECLARE_INSTANCE_COUNTER(CControlbar);
  45. CControlbar::CControlbar()
  46. : m_pCache(NULL)
  47. {
  48. TRACE(_T("CControlbar::CControlbar()\n"));
  49. DEBUG_INCREMENT_INSTANCE_COUNTER(CControlbar);
  50. m_pMenuButton=NULL;
  51. m_ToolbarsList.clear();
  52. #ifdef DBG
  53. dbg_cRef = 0;
  54. #endif
  55. }
  56. CControlbar::~CControlbar()
  57. {
  58. DECLARE_SC(sc, _T("CControlbar::~CControlbar"));
  59. DEBUG_DECREMENT_INSTANCE_COUNTER(CControlbar);
  60. // Remove the toolbars & menubuttons references.
  61. sc = ScCleanup();
  62. // sc dtor will trace error if there is one.
  63. // release reference prior to m_ToolbarsList destruction
  64. // The destructor of CToolbar will try to remove itself from the list!
  65. m_spExtendControlbar = NULL;
  66. }
  67. //+-------------------------------------------------------------------
  68. //
  69. // Member: Create
  70. //
  71. // Synopsis: Create a toolbar or menubutton object
  72. //
  73. // Arguments:
  74. // [nType] - Type of object to be created (Toolbar or Menubutton).
  75. // [pExtendControlbar] - IExtendControlbar associated with this IControlbar.
  76. // [ppUnknown] - IUnknown* of the object created.
  77. //
  78. // Returns: HR
  79. //
  80. //--------------------------------------------------------------------
  81. STDMETHODIMP CControlbar::Create(MMC_CONTROL_TYPE nType,
  82. LPEXTENDCONTROLBAR pExtendControlbar,
  83. LPUNKNOWN* ppUnknown)
  84. {
  85. DECLARE_SC_FOR_PUBLIC_INTERFACE(sc, _T("IControlbar::Create"));
  86. if (ppUnknown == NULL || pExtendControlbar == NULL)
  87. {
  88. sc = E_INVALIDARG;
  89. TraceSnapinError(_T("Invalid Arguments"), sc);
  90. return sc.ToHr();
  91. }
  92. *ppUnknown = NULL;
  93. switch (nType)
  94. {
  95. case TOOLBAR:
  96. sc = ScCreateToolbar(pExtendControlbar, ppUnknown);
  97. break;
  98. case MENUBUTTON:
  99. sc = ScCreateMenuButton(pExtendControlbar, ppUnknown);
  100. break;
  101. default:
  102. sc = E_NOTIMPL;
  103. break;
  104. }
  105. if (sc)
  106. return sc.ToHr();
  107. return (sc.ToHr());
  108. }
  109. HRESULT CControlbar::ControlbarNotify(MMC_NOTIFY_TYPE event, LPARAM arg, LPARAM param)
  110. {
  111. ASSERT(m_spExtendControlbar != NULL);
  112. if (m_spExtendControlbar == NULL)
  113. return E_FAIL;
  114. HRESULT hr;
  115. // Deactivate if theming (fusion or V6 common-control) context before calling snapins.
  116. ULONG_PTR ulpCookie;
  117. if (! MmcDownlevelActivateActCtx(NULL, &ulpCookie))
  118. return E_FAIL;
  119. __try
  120. {
  121. hr = m_spExtendControlbar->ControlbarNotify(event, arg, param);
  122. MmcDownlevelDeactivateActCtx(0, ulpCookie);
  123. }
  124. __except (EXCEPTION_EXECUTE_HANDLER)
  125. {
  126. hr = E_FAIL;
  127. TraceSnapinException(m_clsidSnapin, TEXT("IExtendControlbar::ControlbarNotify"), event);
  128. MmcDownlevelDeactivateActCtx(0, ulpCookie);
  129. }
  130. return hr;
  131. }
  132. //+-------------------------------------------------------------------
  133. //
  134. // Member: Attach
  135. //
  136. // Synopsis: Attach given toolbar or menubutton object
  137. //
  138. // Arguments:
  139. // [nType] - Toolbar or Menubutton.
  140. // [lpUnknown] - IUnknown* of the object to be attached.
  141. //
  142. // Returns: HR
  143. //
  144. //--------------------------------------------------------------------
  145. STDMETHODIMP CControlbar::Attach(MMC_CONTROL_TYPE nType, LPUNKNOWN lpUnknown)
  146. {
  147. DECLARE_SC_FOR_PUBLIC_INTERFACE(sc, _T("IControlbar::Attach"));
  148. if (lpUnknown == NULL)
  149. {
  150. sc = E_INVALIDARG;
  151. TraceSnapinError(_T("Invalid Arguments"), sc);
  152. return sc.ToHr();
  153. }
  154. switch (nType)
  155. {
  156. case TOOLBAR:
  157. sc = ScAttachToolbar(lpUnknown);
  158. break;
  159. case MENUBUTTON:
  160. sc = ScAttachMenuButtons(lpUnknown);
  161. break;
  162. case COMBOBOXBAR:
  163. sc = E_NOTIMPL;
  164. break;
  165. }
  166. if (sc)
  167. return sc.ToHr();
  168. return (sc.ToHr());
  169. }
  170. //+-------------------------------------------------------------------
  171. //
  172. // Member: Detach
  173. //
  174. // Synopsis: Detach given toolbar or menubutton object
  175. //
  176. // Arguments: [lpUnknown] - IUnknown* of the object to be detached
  177. //
  178. // Returns: HR
  179. //
  180. //--------------------------------------------------------------------
  181. STDMETHODIMP CControlbar::Detach(LPUNKNOWN lpUnknown)
  182. {
  183. DECLARE_SC_FOR_PUBLIC_INTERFACE(sc, _T("IControlbar::Detach"));
  184. if (lpUnknown == NULL)
  185. {
  186. sc = E_INVALIDARG;
  187. TraceSnapinError(_T("Invalid Arguments"), sc);
  188. return sc.ToHr();
  189. }
  190. // Is it a toolbar
  191. IToolbarPtr spToolbar = lpUnknown;
  192. if (spToolbar != NULL)
  193. {
  194. sc = ScDetachToolbar(spToolbar);
  195. return sc.ToHr();
  196. }
  197. // Is it a menu button
  198. IMenuButtonPtr spMenuButton = lpUnknown;
  199. if (spMenuButton != NULL)
  200. {
  201. sc = ScDetachMenuButton(spMenuButton);
  202. return sc.ToHr();
  203. }
  204. // The passed lpUnknown is neither toolbar nor menubutton.
  205. // The Snapin has passed invalid object.
  206. sc = E_INVALIDARG;
  207. TraceSnapinError(_T("lpUnknown passed is neither toolbar nor menubutton"), sc);
  208. return sc.ToHr();
  209. }
  210. //+-------------------------------------------------------------------
  211. //
  212. // Member: ScDetachToolbar
  213. //
  214. // Synopsis: Detach given toolbar object
  215. //
  216. // Arguments: [lpToolbar] - IToolbar* of the object to be detached
  217. //
  218. // Returns: SC
  219. //
  220. //--------------------------------------------------------------------
  221. SC CControlbar::ScDetachToolbar(LPTOOLBAR lpToolbar)
  222. {
  223. DECLARE_SC(sc, _T("CControlbar::SCDetachToolbar"));
  224. if (NULL == lpToolbar)
  225. return (sc = E_UNEXPECTED);
  226. // Get the CToolbar object.
  227. CToolbar* pToolbar = dynamic_cast<CToolbar*>(lpToolbar);
  228. if (NULL == pToolbar)
  229. return (sc = E_UNEXPECTED);
  230. // Get the CMMCToolbarIntf interface.
  231. CMMCToolbarIntf* pToolbarIntf = pToolbar->GetMMCToolbarIntf();
  232. if (NULL == pToolbarIntf)
  233. return (sc = E_UNEXPECTED);
  234. // Detach the toolbar from UI.
  235. sc = pToolbarIntf->ScDetach(pToolbar);
  236. if (sc)
  237. return sc;
  238. // Remove the CControlbar reference.
  239. pToolbar->SetControlbar(NULL);
  240. // Remove the reference to the toolbar.
  241. m_ToolbarsList.remove(pToolbar);
  242. return sc;
  243. }
  244. //+-------------------------------------------------------------------
  245. //
  246. // Member: ScDetachMenuButton
  247. //
  248. // Synopsis: Detach given toolbar or menubutton object
  249. //
  250. // Arguments: [lpUnknown] - IUnknown* of the object to be detached
  251. //
  252. // Returns: HR
  253. //
  254. //--------------------------------------------------------------------
  255. SC CControlbar::ScDetachMenuButton(LPMENUBUTTON lpMenuButton)
  256. {
  257. DECLARE_SC(sc, _T("CControlbar::ScDetachMenuButton"));
  258. if (NULL == lpMenuButton)
  259. return (sc = E_UNEXPECTED);
  260. CMenuButton* pMenuButton = dynamic_cast<CMenuButton*>(lpMenuButton);
  261. if (NULL == pMenuButton)
  262. return (sc = E_UNEXPECTED);
  263. sc = pMenuButton->ScDetach();
  264. if (sc)
  265. return sc;
  266. // If this is same as the cached menubutton object
  267. // then remove the (cached) ref.
  268. if (m_pMenuButton == pMenuButton)
  269. m_pMenuButton = NULL;
  270. else
  271. {
  272. // The IControlbar implementation is supposed to
  273. // have only one CMenuButton obj. How come it is
  274. // not same as one we have cached.
  275. sc = E_UNEXPECTED;
  276. }
  277. return sc;
  278. }
  279. //+-------------------------------------------------------------------
  280. //
  281. // Member: ScCreateToolbar
  282. //
  283. // Synopsis: Create a toolbar for the given snapin (IExtendControlbar).
  284. //
  285. // Arguments: [pExtendControlbar] - IExtendControlbar of the snapin.
  286. // [ppUnknown] - IUnknown* (IToolbar) of created toolbar.
  287. //
  288. // Returns: SC
  289. //
  290. //--------------------------------------------------------------------
  291. SC CControlbar::ScCreateToolbar(LPEXTENDCONTROLBAR pExtendControlbar,
  292. LPUNKNOWN* ppUnknown)
  293. {
  294. DECLARE_SC(sc, _T("CControlbar::ScCreateToolbar"));
  295. if ( (NULL == pExtendControlbar) ||
  296. (NULL == ppUnknown) )
  297. return (sc = E_INVALIDARG);
  298. ASSERT(m_spExtendControlbar == NULL ||
  299. m_spExtendControlbar == pExtendControlbar);
  300. // Create the new CToolbar object.
  301. CComObject<CToolbar>* pToolbar = NULL;
  302. sc = CComObject<CToolbar>::CreateInstance(&pToolbar);
  303. if (sc)
  304. return sc;
  305. if (NULL == pToolbar)
  306. return (sc = E_FAIL);
  307. sc = pToolbar->QueryInterface(IID_IToolbar,
  308. reinterpret_cast<void**>(ppUnknown));
  309. if (sc)
  310. return sc;
  311. CMMCToolbarIntf* pToolbarIntf = NULL;
  312. // Get the toolbars mgr.
  313. CAMCViewToolbarsMgr* pAMCViewToolbarsMgr = GetAMCViewToolbarsMgr();
  314. if (NULL == pAMCViewToolbarsMgr)
  315. {
  316. sc = E_UNEXPECTED;
  317. goto ToolbarUICreateError;
  318. }
  319. // Ask it to create the toolbar UI.
  320. sc = pAMCViewToolbarsMgr->ScCreateToolBar(&pToolbarIntf);
  321. if (sc)
  322. goto ToolbarUICreateError;
  323. // Let the IToolbar imp be aware of toolbar UI interface.
  324. pToolbar->SetMMCToolbarIntf(pToolbarIntf);
  325. Cleanup:
  326. return(sc);
  327. ToolbarUICreateError:
  328. // Destroy the CToolbar object created.
  329. if (*ppUnknown)
  330. (*ppUnknown)->Release();
  331. *ppUnknown = NULL;
  332. goto Cleanup;
  333. }
  334. //+-------------------------------------------------------------------
  335. //
  336. // Member: ScCreateMenuButton
  337. //
  338. // Synopsis: Create a menu button object.
  339. //
  340. // Arguments: [pExtendControlbar] - IExtendControlbar of the snapin
  341. // that is creating MenuButton object.
  342. // [ppUnknown] - IUnknown if MenuButton object.
  343. //
  344. // Returns: SC
  345. //
  346. //--------------------------------------------------------------------
  347. SC CControlbar::ScCreateMenuButton(LPEXTENDCONTROLBAR pExtendControlbar,
  348. LPUNKNOWN* ppUnknown)
  349. {
  350. DECLARE_SC(sc, _T("CControlbar::ScCreateMenuButton"));
  351. if ( (NULL == pExtendControlbar) ||
  352. (NULL == ppUnknown) )
  353. return (sc = E_INVALIDARG);
  354. ASSERT(m_spExtendControlbar == NULL ||
  355. m_spExtendControlbar == pExtendControlbar);
  356. // Create the new IMenuButton object
  357. CComObject<CMenuButton>* pMenuButton;
  358. sc = CComObject<CMenuButton>::CreateInstance(&pMenuButton);
  359. if (sc)
  360. return sc;
  361. if (NULL == pMenuButton)
  362. return (sc = E_FAIL);
  363. sc = pMenuButton->QueryInterface(IID_IMenuButton,
  364. reinterpret_cast<void**>(ppUnknown));
  365. if (sc)
  366. return sc;
  367. pMenuButton->SetControlbar(this);
  368. return sc;
  369. }
  370. //+-------------------------------------------------------------------
  371. //
  372. // Member: ScNotifySnapinOfToolBtnClick
  373. //
  374. // Synopsis: Notify the snapin about a tool button is click.
  375. //
  376. // Arguments: [hNode] - Node that owns result pane.
  377. // [bScopePane] - Scope or Result.
  378. // [lResultItemCookie] - If Result pane is selected the item param.
  379. // [nID] - Command ID of the tool button clicked.
  380. //
  381. // Returns: SC
  382. //
  383. //--------------------------------------------------------------------
  384. SC CControlbar::ScNotifySnapinOfToolBtnClick(HNODE hNode, bool bScopePane,
  385. LPARAM lResultItemCookie,
  386. UINT nID)
  387. {
  388. DECLARE_SC(sc, _T("CControlbar::ScNotifySnapinOfToolBtnClick"));
  389. LPDATAOBJECT pDataObject = NULL;
  390. CNode* pNode = CNode::FromHandle(hNode);
  391. if (NULL == pNode)
  392. return (sc = E_UNEXPECTED);
  393. bool bScopeItem = bScopePane;
  394. // Get the data object of the currently selected item.
  395. sc = pNode->ScGetDataObject(bScopePane, lResultItemCookie, bScopeItem, &pDataObject);
  396. if (sc)
  397. return sc;
  398. ASSERT(m_spExtendControlbar != NULL);
  399. // Notify the snapin
  400. sc = ControlbarNotify(MMCN_BTN_CLICK, reinterpret_cast<LPARAM>(pDataObject),
  401. static_cast<LPARAM>(nID));
  402. // Release the dataobject if it is not special dataobject.
  403. RELEASE_DATAOBJECT(pDataObject);
  404. if (sc)
  405. return sc;
  406. return sc;
  407. }
  408. //+-------------------------------------------------------------------
  409. //
  410. // Member: ScNotifySnapinOfMenuBtnClick
  411. //
  412. // Synopsis: Notify the snapin about a menu button is click.
  413. //
  414. // Arguments: [hNode] - Node that owns result pane.
  415. // [bScopePane] - Scope or Result.
  416. // [lResultItemCookie] - If Result pane is selected the item param.
  417. // [lpmenuButtonData] - MENUBUTTONDATA
  418. //
  419. // Returns: SC
  420. //
  421. //--------------------------------------------------------------------
  422. SC CControlbar::ScNotifySnapinOfMenuBtnClick(HNODE hNode, bool bScopePane,
  423. LPARAM lResultItemCookie,
  424. LPMENUBUTTONDATA lpmenuButtonData)
  425. {
  426. DECLARE_SC(sc, _T("CControlbar::ScNotifySnapinOfMenuBtnClick"));
  427. LPDATAOBJECT pDataObject = NULL;
  428. CNode* pNode = CNode::FromHandle(hNode);
  429. if (NULL == pNode)
  430. return (sc = E_UNEXPECTED);
  431. bool bScopeItem = bScopePane;
  432. // Get the data object of the currently selected item.
  433. sc = pNode->ScGetDataObject(bScopePane, lResultItemCookie, bScopeItem, &pDataObject);
  434. if (sc)
  435. return sc;
  436. ASSERT(m_spExtendControlbar != NULL);
  437. // Notify the snapin
  438. sc = ControlbarNotify(MMCN_MENU_BTNCLICK, reinterpret_cast<LPARAM>(pDataObject),
  439. reinterpret_cast<LPARAM>(lpmenuButtonData));
  440. // Release the dataobject if it is not special dataobject.
  441. RELEASE_DATAOBJECT(pDataObject);
  442. if (sc)
  443. return sc;
  444. return sc;
  445. }
  446. //+-------------------------------------------------------------------
  447. //
  448. // Member: ScAttachToolbar
  449. //
  450. // Synopsis: Attach given toolbar object
  451. //
  452. // Arguments: [lpUnknown] - IUnknown* of the object to be attached
  453. //
  454. // Returns: SC
  455. //
  456. //--------------------------------------------------------------------
  457. SC CControlbar::ScAttachToolbar(LPUNKNOWN lpUnknown)
  458. {
  459. DECLARE_SC(sc, _T("CControlbar::ScAttachToolbar"));
  460. ASSERT(NULL != lpUnknown);
  461. IToolbarPtr spToolbar = lpUnknown;
  462. if (NULL == spToolbar)
  463. return (sc = E_UNEXPECTED);
  464. // Get the toolbar object (IToolbar implementation).
  465. CToolbar* pToolbarC = dynamic_cast<CToolbar*>(spToolbar.GetInterfacePtr());
  466. if (NULL == pToolbarC)
  467. return (sc = E_UNEXPECTED);
  468. // Get the toolbar UI interface.
  469. CMMCToolbarIntf* pToolbarIntf = pToolbarC->GetMMCToolbarIntf();
  470. if (NULL == pToolbarIntf)
  471. return (sc = E_UNEXPECTED);
  472. // Attach the toolbar.
  473. sc = pToolbarIntf->ScAttach(pToolbarC);
  474. if (sc)
  475. return sc;
  476. // Make the CToolbar aware of this IControlbar.
  477. pToolbarC->SetControlbar(this);
  478. // Add this CToolbar to our list of toolbars.
  479. ToolbarsList::iterator itToolbar = std::find(m_ToolbarsList.begin(), m_ToolbarsList.end(), pToolbarC);
  480. if (m_ToolbarsList.end() == itToolbar)
  481. {
  482. m_ToolbarsList.push_back(pToolbarC);
  483. }
  484. return sc;
  485. }
  486. //+-------------------------------------------------------------------
  487. //
  488. // Member: ScAttachMenuButtons
  489. //
  490. // Synopsis: Attach a menu button object.
  491. //
  492. // Arguments: [lpUnknown] - IUnknown if MenuButton object.
  493. //
  494. // Returns: HRESULT
  495. //
  496. // Note: Only one CMenuButton object per Controlbar/snapin.
  497. // Snapins can create many menu buttons using a
  498. // single CMenuButton object.
  499. //--------------------------------------------------------------------
  500. SC CControlbar::ScAttachMenuButtons(LPUNKNOWN lpUnknown)
  501. {
  502. DECLARE_SC(sc, _T("CControlbar::ScAttachMenuButtons"));
  503. ASSERT(NULL != lpUnknown);
  504. CMenuButton* pMenuButton = dynamic_cast<CMenuButton*>(lpUnknown);
  505. if (pMenuButton == NULL)
  506. return (sc = E_INVALIDARG);
  507. if (m_pMenuButton == pMenuButton)
  508. {
  509. // Already attached.
  510. sc = S_FALSE;
  511. TraceNodeMgrLegacy(_T("The menubutton is already attached"), sc);
  512. return sc;
  513. }
  514. else if (m_pMenuButton != NULL)
  515. {
  516. // There is already a CMenuButton object attached by this
  517. // Controlbar (Snapin). Detach that before attaching this
  518. // CMenuButton Object (See the note above).
  519. sc = m_pMenuButton->ScDetach();
  520. if (sc)
  521. return sc;
  522. }
  523. // Cache the ref to CMenuButton object.
  524. // Used when selection moves away from the snapin.
  525. // MMC has to remove the menubutton put by this snapin.
  526. m_pMenuButton = pMenuButton;
  527. if (pMenuButton->GetControlbar() != this)
  528. pMenuButton->SetControlbar(this);
  529. sc = pMenuButton->ScAttach();
  530. if (sc)
  531. return sc;
  532. return sc;
  533. }
  534. //+-------------------------------------------------------------------
  535. //
  536. // Member: ScCleanup
  537. //
  538. // Synopsis: Remove all the toolbars and menu buttons owned
  539. // by this controlbar.
  540. //
  541. // Arguments: None
  542. //
  543. // Returns: SC
  544. //
  545. //--------------------------------------------------------------------
  546. SC CControlbar::ScCleanup()
  547. {
  548. DECLARE_SC(sc, _T("CControlbar::ScCleanup"));
  549. ASSERT(m_spExtendControlbar != NULL);
  550. if (m_spExtendControlbar != NULL)
  551. m_spExtendControlbar->SetControlbar(NULL);
  552. sc = ScDetachToolbars();
  553. if (sc)
  554. return sc;
  555. // If there is a menu button, detach (remove it
  556. // from the UI).
  557. if (m_pMenuButton)
  558. {
  559. sc = m_pMenuButton->ScDetach();
  560. m_pMenuButton = NULL;
  561. }
  562. return sc;
  563. }
  564. //+-------------------------------------------------------------------
  565. //
  566. // Member: ScDetachToolbars
  567. //
  568. // Synopsis: Detach all the toolbars.
  569. //
  570. // Arguments: None.
  571. //
  572. // Returns: SC
  573. //
  574. //--------------------------------------------------------------------
  575. SC CControlbar::ScDetachToolbars()
  576. {
  577. DECLARE_SC(sc, _T("CControlbar::ScDetachToolbars"));
  578. ToolbarsList::iterator itToolbar = m_ToolbarsList.begin();
  579. while (itToolbar != m_ToolbarsList.end())
  580. {
  581. CToolbar* pToolbar = (*itToolbar);
  582. if (NULL == pToolbar)
  583. return (sc = E_UNEXPECTED);
  584. CMMCToolbarIntf* pToolbarIntf = pToolbar->GetMMCToolbarIntf();
  585. if (NULL == pToolbarIntf)
  586. return (sc = E_UNEXPECTED);
  587. // Detach the toolbar UI.
  588. sc = pToolbarIntf->ScDetach(pToolbar);
  589. if (sc)
  590. return sc;
  591. // Detach the controlbar from toolbar.
  592. pToolbar->SetControlbar(NULL);
  593. // Remove the toolbar reference from the list.
  594. itToolbar = m_ToolbarsList.erase(itToolbar);
  595. }
  596. return (sc);
  597. }
  598. //+-------------------------------------------------------------------
  599. //
  600. // Member: ScShowToolbars
  601. //
  602. // Synopsis: Show/Hide all the toolbars.
  603. //
  604. // Arguments: [bool] - Show or Hide.
  605. //
  606. // Returns: SC
  607. //
  608. //--------------------------------------------------------------------
  609. SC CControlbar::ScShowToolbars(bool bShow)
  610. {
  611. DECLARE_SC(sc, _T("CControlbar::ScShowToolbars"));
  612. ToolbarsList::iterator itToolbar = m_ToolbarsList.begin();
  613. for (; itToolbar != m_ToolbarsList.end(); ++itToolbar)
  614. {
  615. CToolbar* pToolbar = (*itToolbar);
  616. if (NULL == pToolbar)
  617. return (sc = E_UNEXPECTED);
  618. CMMCToolbarIntf* pToolbarIntf = pToolbar->GetMMCToolbarIntf();
  619. if (NULL == pToolbarIntf)
  620. return (sc = E_UNEXPECTED);
  621. sc = pToolbarIntf->ScShow(pToolbar, bShow);
  622. if (sc)
  623. return sc;
  624. }
  625. return sc;
  626. }
  627. CViewData* CControlbar::GetViewData()
  628. {
  629. ASSERT(m_pCache != NULL);
  630. return m_pCache->GetViewData();
  631. }
  632. ///////////////////////////////////////////////////////////////////////////
  633. //
  634. // CSelData implementation
  635. //
  636. DEBUG_DECLARE_INSTANCE_COUNTER(CSelData);
  637. //+-------------------------------------------------------------------
  638. //
  639. // Member: ScReset
  640. //
  641. // Synopsis: Init all the data members.
  642. //
  643. // Arguments: None
  644. //
  645. // Returns: SC
  646. //
  647. //--------------------------------------------------------------------
  648. SC CSelData::ScReset()
  649. {
  650. DECLARE_SC(sc, _T("CSelData::ScReset"));
  651. if (m_pCtrlbarPrimary != NULL)
  652. {
  653. sc = ScDestroyPrimaryCtrlbar();
  654. if (sc)
  655. return sc;
  656. }
  657. sc = ScDestroyExtensionCtrlbars();
  658. if (sc)
  659. return sc;
  660. m_bScopeSel = false;
  661. m_bSelect = false;
  662. m_pNodeScope = NULL;
  663. m_pMS = NULL;
  664. m_pCtrlbarPrimary = NULL;
  665. m_lCookie = -1;
  666. m_pCompPrimary = NULL;
  667. m_spDataObject = NULL;
  668. return sc;
  669. }
  670. //+-------------------------------------------------------------------
  671. //
  672. // Member: ScShowToolbars
  673. //
  674. // Synopsis: Show/Hide primary & extension toolbars.
  675. //
  676. // Arguments: [bool] - Show/Hide.
  677. //
  678. // Returns: SC
  679. //
  680. //--------------------------------------------------------------------
  681. SC CSelData::ScShowToolbars(bool bShow)
  682. {
  683. DECLARE_SC(sc, _T("CSelData::ScShowToolbars"));
  684. if (m_pCtrlbarPrimary != NULL)
  685. {
  686. sc = m_pCtrlbarPrimary->ScShowToolbars(bShow);
  687. if (sc)
  688. return sc;
  689. }
  690. POSITION pos = m_listExtCBs.GetHeadPosition();
  691. bool bReturn = true;
  692. while (pos != NULL)
  693. {
  694. CControlbar* pControlbar = m_listExtCBs.GetNext(pos);
  695. if (pControlbar)
  696. {
  697. sc = pControlbar->ScShowToolbars(bShow);
  698. if (sc)
  699. return sc;
  700. }
  701. }
  702. return sc;
  703. }
  704. CControlbar* CSelData::GetControlbar(const CLSID& clsidSnapin)
  705. {
  706. POSITION pos = m_listExtCBs.GetHeadPosition();
  707. while (pos)
  708. {
  709. CControlbar* pControlbar = m_listExtCBs.GetNext(pos);
  710. if (pControlbar && pControlbar->IsSameSnapin(clsidSnapin) == TRUE)
  711. return pControlbar;
  712. }
  713. return NULL;
  714. }
  715. //+-------------------------------------------------------------------
  716. //
  717. // Member: ScDestroyPrimaryCtrlbar
  718. //
  719. // Synopsis: Ask primary controlbar to release its toolbar/menubutton
  720. // ref and cleanup our reference to the controlbar.
  721. //
  722. // Arguments: None
  723. //
  724. // Returns: SC
  725. //
  726. //--------------------------------------------------------------------
  727. SC CSelData::ScDestroyPrimaryCtrlbar()
  728. {
  729. DECLARE_SC(sc, _T("CSelData::ScDestroyPrimaryCtrlbar"));
  730. if (NULL == m_pCtrlbarPrimary)
  731. return (sc = E_UNEXPECTED);
  732. sc = m_pCtrlbarPrimary->ScCleanup();
  733. if (sc)
  734. return sc;
  735. /*
  736. * In CreateControlbar we had a ref on IControlbar
  737. * (detaching smart ptr). Let us now undo that ref.
  738. */
  739. m_pCtrlbarPrimary->Release();
  740. m_pCtrlbarPrimary = NULL;
  741. return sc;
  742. }
  743. //+-------------------------------------------------------------------
  744. //
  745. // Member: ScDestroyExtensionCtrlbars
  746. //
  747. // Synopsis: Ask extension controlbars to release their toolbar/menubutton
  748. // ref and cleanup our reference to the controlbars.
  749. //
  750. // Arguments: None
  751. //
  752. // Returns: SC
  753. //
  754. //--------------------------------------------------------------------
  755. SC CSelData::ScDestroyExtensionCtrlbars()
  756. {
  757. DECLARE_SC(sc, _T("CSelData::ScDestroyExtensionCtrlbars"));
  758. POSITION pos = m_listExtCBs.GetHeadPosition();
  759. while (pos != NULL)
  760. {
  761. CControlbar* pControlbar = m_listExtCBs.GetNext(pos);
  762. if (pControlbar)
  763. {
  764. sc = pControlbar->ScCleanup();
  765. if (sc)
  766. return sc;
  767. /*
  768. * In CreateControlbar we had a ref on IControlbar
  769. * (detaching smart ptr). Let us now undo that ref.
  770. */
  771. pControlbar->Release();
  772. }
  773. }
  774. m_listExtCBs.RemoveAll();
  775. return sc;
  776. }
  777. ///////////////////////////////////////////////////////////////////////////
  778. //
  779. // CControlbarsCache implementation
  780. //
  781. DEBUG_DECLARE_INSTANCE_COUNTER(CControlbarsCache);
  782. void CControlbarsCache::SetViewData(CViewData* pViewData)
  783. {
  784. ASSERT(pViewData != 0);
  785. m_pViewData = pViewData;
  786. }
  787. CViewData* CControlbarsCache::GetViewData()
  788. {
  789. ASSERT(m_pViewData != NULL);
  790. return m_pViewData;
  791. }
  792. CControlbar* CControlbarsCache::CreateControlbar(IExtendControlbarPtr& spECB,
  793. const CLSID& clsidSnapin)
  794. {
  795. DECLARE_SC(sc, _T("CControlbarsCache::CreateControlbar"));
  796. CComObject<CControlbar>* pControlbar;
  797. sc = CComObject<CControlbar>::CreateInstance(&pControlbar);
  798. if (sc)
  799. return NULL;
  800. IControlbarPtr spControlbar = pControlbar;
  801. if (NULL == spControlbar)
  802. {
  803. ASSERT(NULL != pControlbar); // QI fails but object is created how?
  804. sc = E_UNEXPECTED;
  805. return NULL;
  806. }
  807. pControlbar->SetCache(this);
  808. pControlbar->SetExtendControlbar(spECB, clsidSnapin);
  809. sc = spECB->SetControlbar(spControlbar);
  810. if (sc)
  811. return NULL; // spControlbar smart ptr (object will be destroyed).
  812. // Snapin must return S_OK to be valid
  813. if (S_OK == sc.ToHr())
  814. {
  815. // Detach, thus hold a ref count on the Controlbar object
  816. // CSelData holds this reference & releases the ref in
  817. // ScDestroyPrimaryCtrlbar() or ScDestroyExtensionCtrlbars().
  818. spControlbar.Detach();
  819. // This is for debug info.
  820. Debug_SetControlbarSnapinName(clsidSnapin, pControlbar);
  821. return pControlbar;
  822. }
  823. return NULL;
  824. }
  825. HRESULT
  826. CControlbarsCache::OnMultiSelect(
  827. CNode* pNodeScope,
  828. CMultiSelection* pMultiSelection,
  829. IDataObject* pDOMultiSel,
  830. BOOL bSelect)
  831. {
  832. ASSERT(pNodeScope != NULL);
  833. ASSERT(pMultiSelection != NULL);
  834. ASSERT(pDOMultiSel != NULL);
  835. if (pNodeScope == NULL || pMultiSelection == NULL || pDOMultiSel == NULL)
  836. return E_FAIL;
  837. CSelData selData(false, (bool)bSelect);
  838. selData.m_pMS = pMultiSelection;
  839. if (selData == m_SelData)
  840. return S_FALSE;
  841. if (!bSelect)
  842. return _OnDeSelect(selData);
  843. selData.m_pCompPrimary = pMultiSelection->GetPrimarySnapinComponent();
  844. CList<GUID, GUID&> extnSnapins;
  845. HRESULT hr = pMultiSelection->GetExtensionSnapins(g_szToolbar, extnSnapins);
  846. CHECK_HRESULT(hr);
  847. selData.m_spDataObject.Attach(pDOMultiSel, TRUE);
  848. return _ProcessSelection(selData, extnSnapins);
  849. }
  850. HRESULT
  851. CControlbarsCache::OnResultSelChange(
  852. CNode* pNode,
  853. MMC_COOKIE cookie,
  854. BOOL bSelected)
  855. {
  856. DECLARE_SC(sc, TEXT("CControlbarsCache::OnResultSelChange"));
  857. sc = ScCheckPointers (pNode);
  858. if (sc)
  859. return (sc.ToHr());
  860. CSelData selData(false, (bool)bSelected);
  861. selData.m_lCookie = cookie;
  862. if (selData == m_SelData)
  863. return (sc = S_FALSE).ToHr();
  864. if (!bSelected)
  865. {
  866. sc = _OnDeSelect(selData);
  867. return sc.ToHr();
  868. }
  869. IDataObjectPtr spDataObject = NULL;
  870. CComponent* pCCResultItem = NULL;
  871. CList<CLSID, CLSID&> extnSnapins;
  872. BOOL bListPadItem = GetViewData()->HasListPad() && !IS_SPECIAL_LVDATA(cookie);
  873. if (GetViewData()->IsVirtualList())
  874. {
  875. pCCResultItem = pNode->GetPrimaryComponent();
  876. sc = ScCheckPointers(pCCResultItem, E_UNEXPECTED);
  877. if (sc)
  878. return sc.ToHr();
  879. sc = pCCResultItem->QueryDataObject(cookie, CCT_RESULT, &spDataObject);
  880. if (sc)
  881. return sc.ToHr();
  882. }
  883. else if ( (GetViewData()->HasOCX()) || (GetViewData()->HasWebBrowser() && !bListPadItem) )
  884. {
  885. selData.m_pCompPrimary = pNode->GetPrimaryComponent();
  886. sc = _ProcessSelection(selData, extnSnapins);
  887. return sc.ToHr();
  888. }
  889. else
  890. {
  891. CResultItem* pri = CResultItem::FromHandle(cookie);
  892. sc = ScCheckPointers(pri, E_UNEXPECTED);
  893. if (sc)
  894. return sc.ToHr();
  895. if (pri->IsScopeItem())
  896. {
  897. // Get the data object from IComponentData
  898. pNode = CNode::FromResultItem (pri);
  899. sc = ScCheckPointers(pNode, E_UNEXPECTED);
  900. if (sc)
  901. return sc.ToHr();
  902. if (pNode->IsInitialized() == FALSE)
  903. {
  904. sc = pNode->InitComponents();
  905. if (sc)
  906. return sc.ToHr();
  907. }
  908. pCCResultItem = pNode->GetPrimaryComponent();
  909. sc = pNode->QueryDataObject(CCT_SCOPE, &spDataObject);
  910. if (sc)
  911. return sc.ToHr();
  912. }
  913. else // Must be a leaf item inserted by a snapin
  914. {
  915. pCCResultItem = pNode->GetComponent(pri->GetOwnerID());
  916. sc = ScCheckPointers(pCCResultItem, E_UNEXPECTED);
  917. if (sc)
  918. return sc.ToHr();
  919. sc = pCCResultItem->QueryDataObject(pri->GetSnapinData(), CCT_RESULT,
  920. &spDataObject);
  921. if (sc)
  922. return sc.ToHr();
  923. }
  924. }
  925. // Create extension snapin list
  926. if (spDataObject != NULL)
  927. {
  928. ASSERT(pCCResultItem != NULL);
  929. GUID guidObjType;
  930. sc = ::ExtractObjectTypeGUID(spDataObject, &guidObjType);
  931. if (sc)
  932. return sc.ToHr();
  933. CSnapIn* pSnapIn = pNode->GetPrimarySnapIn();
  934. CMTNode* pmtNode = pNode->GetMTNode();
  935. sc = ScCheckPointers(pmtNode, E_UNEXPECTED);
  936. if (sc)
  937. return sc.ToHr();
  938. CArray<GUID, GUID&> DynExtens;
  939. ExtractDynExtensions(spDataObject, DynExtens);
  940. CExtensionsIterator it;
  941. sc = it.ScInitialize(pSnapIn, guidObjType, g_szToolbar, DynExtens.GetData(), DynExtens.GetSize());
  942. if (!sc.IsError())
  943. {
  944. for (; !it.IsEnd(); it.Advance())
  945. {
  946. extnSnapins.AddHead(const_cast<GUID&>(it.GetCLSID()));
  947. }
  948. }
  949. selData.m_pCompPrimary = pCCResultItem;
  950. selData.m_spDataObject.Attach(spDataObject.Detach());
  951. }
  952. // Finally process selection
  953. sc = _ProcessSelection(selData, extnSnapins);
  954. if (sc)
  955. return sc.ToHr();
  956. return sc.ToHr();
  957. }
  958. HRESULT CControlbarsCache::OnScopeSelChange(CNode* pNode, BOOL bSelected)
  959. {
  960. DECLARE_SC(sc, TEXT("CControlbarsCache::OnScopeSelChange"));
  961. CSelData selData(true, (bool)bSelected);
  962. selData.m_pNodeScope = pNode;
  963. if (selData == m_SelData)
  964. return S_FALSE;
  965. if (!bSelected)
  966. return _OnDeSelect(selData);
  967. HRESULT hr = S_OK;
  968. IDataObjectPtr spDataObject;
  969. CComponent* pCCPrimary = NULL;
  970. CList<CLSID, CLSID&> extnSnapins;
  971. hr = pNode->QueryDataObject(CCT_SCOPE, &spDataObject);
  972. if (FAILED(hr))
  973. return hr;
  974. pCCPrimary = pNode->GetPrimaryComponent();
  975. GUID guidObjType;
  976. hr = ::ExtractObjectTypeGUID(spDataObject, &guidObjType);
  977. ASSERT(SUCCEEDED(hr));
  978. if (FAILED(hr))
  979. return hr;
  980. CSnapIn* pSnapIn = pNode->GetPrimarySnapIn();
  981. CArray<GUID, GUID&> DynExtens;
  982. ExtractDynExtensions(spDataObject, DynExtens);
  983. CExtensionsIterator it;
  984. sc = it.ScInitialize(pSnapIn, guidObjType, g_szToolbar, DynExtens.GetData(), DynExtens.GetSize());
  985. if (!sc.IsError())
  986. {
  987. for (; it.IsEnd() == FALSE; it.Advance())
  988. {
  989. extnSnapins.AddHead(const_cast<GUID&>(it.GetCLSID()));
  990. }
  991. }
  992. // Finally process selection
  993. selData.m_pCompPrimary = pCCPrimary;
  994. selData.m_spDataObject.Attach(spDataObject.Detach());
  995. return _ProcessSelection(selData, extnSnapins);
  996. }
  997. HRESULT CControlbarsCache::_OnDeSelect(CSelData& selData)
  998. {
  999. ASSERT(!selData.IsSelect());
  1000. if (selData.m_bScopeSel != m_SelData.m_bScopeSel)
  1001. return S_FALSE;
  1002. if ( (m_SelData.m_pCtrlbarPrimary != NULL &&
  1003. m_SelData.m_spDataObject == NULL) &&
  1004. (!GetViewData()->HasOCX() ||
  1005. !GetViewData()->HasWebBrowser()) &&
  1006. m_SelData.IsScope())
  1007. {
  1008. return E_UNEXPECTED;
  1009. }
  1010. MMC_NOTIFY_TYPE eNotifyCode = MMCN_SELECT;
  1011. LPARAM lDataObject;
  1012. if (GetViewData()->IsVirtualList())
  1013. {
  1014. eNotifyCode = MMCN_DESELECT_ALL;
  1015. // Must use NULL data object for MMCN_DESELECT_ALL.
  1016. lDataObject = 0;
  1017. }
  1018. else if ((GetViewData()->HasOCX()) && (!m_SelData.IsScope()))
  1019. lDataObject = reinterpret_cast<LPARAM>(DOBJ_CUSTOMOCX);
  1020. else if ((GetViewData()->HasWebBrowser()) && (!m_SelData.IsScope()))
  1021. {
  1022. if (GetViewData()->HasListPad() && m_SelData.m_spDataObject != NULL)
  1023. {
  1024. lDataObject = reinterpret_cast<LPARAM>(
  1025. static_cast<IDataObject*>(m_SelData.m_spDataObject));
  1026. }
  1027. else
  1028. {
  1029. lDataObject = reinterpret_cast<LPARAM>(DOBJ_CUSTOMWEB);
  1030. }
  1031. }
  1032. else
  1033. {
  1034. lDataObject = reinterpret_cast<LPARAM>(
  1035. static_cast<IDataObject*>(m_SelData.m_spDataObject));
  1036. }
  1037. WORD wScope = static_cast<WORD>(m_SelData.IsScope());
  1038. LPARAM arg = MAKELONG(wScope, FALSE);
  1039. if (m_SelData.m_pCtrlbarPrimary != NULL)
  1040. {
  1041. m_SelData.m_pCtrlbarPrimary->ControlbarNotify(eNotifyCode, arg,
  1042. lDataObject);
  1043. }
  1044. POSITION pos = m_SelData.m_listExtCBs.GetHeadPosition();
  1045. while (pos)
  1046. {
  1047. CControlbar* pCbar = m_SelData.m_listExtCBs.GetNext(pos);
  1048. pCbar->ControlbarNotify(eNotifyCode, arg, lDataObject);
  1049. }
  1050. m_SelData.m_bSelect = false;
  1051. m_SelData.m_spDataObject = NULL; // Release & set to NULL
  1052. return S_OK;
  1053. }
  1054. HRESULT
  1055. CControlbarsCache::_ProcessSelection(
  1056. CSelData& selData,
  1057. CList<CLSID, CLSID&>& extnSnapins)
  1058. {
  1059. LPARAM lDataObject = reinterpret_cast<LPARAM>(
  1060. static_cast<IDataObject*>(selData.m_spDataObject));
  1061. if (NULL == lDataObject)
  1062. {
  1063. if ( (GetViewData()->HasOCX()) && (!selData.IsScope()) )
  1064. lDataObject = reinterpret_cast<LPARAM>(DOBJ_CUSTOMOCX);
  1065. else if ( (GetViewData()->HasWebBrowser()) && (!selData.IsScope()) )
  1066. lDataObject = reinterpret_cast<LPARAM>(DOBJ_CUSTOMWEB);
  1067. }
  1068. WORD wScope = static_cast<WORD>(selData.IsScope());
  1069. long arg = MAKELONG(wScope, TRUE);
  1070. m_SelData.m_bScopeSel = selData.m_bScopeSel;
  1071. m_SelData.m_bSelect = selData.m_bSelect;
  1072. m_SelData.m_pNodeScope = selData.m_pNodeScope;
  1073. m_SelData.m_lCookie = selData.m_lCookie;
  1074. m_SelData.m_spDataObject.Attach(selData.m_spDataObject.Detach());
  1075. // Handle primary controlbar first
  1076. if (m_SelData.m_pCompPrimary != selData.m_pCompPrimary)
  1077. {
  1078. if (m_SelData.m_pCtrlbarPrimary != NULL)
  1079. {
  1080. // Ask controlbar to destroy its ref & destroy our ref
  1081. // to controlbar.
  1082. m_SelData.ScDestroyPrimaryCtrlbar();
  1083. }
  1084. m_SelData.m_pCompPrimary = selData.m_pCompPrimary;
  1085. if (m_SelData.m_pCompPrimary != NULL &&
  1086. m_SelData.m_pCtrlbarPrimary == NULL)
  1087. {
  1088. IExtendControlbarPtr spECBPrimary =
  1089. m_SelData.m_pCompPrimary->GetIComponent();
  1090. if (spECBPrimary != NULL)
  1091. {
  1092. m_SelData.m_pCtrlbarPrimary =
  1093. CreateControlbar(spECBPrimary,
  1094. m_SelData.m_pCompPrimary->GetCLSID());
  1095. }
  1096. }
  1097. }
  1098. if (m_SelData.m_pCtrlbarPrimary != NULL)
  1099. {
  1100. m_SelData.m_pCtrlbarPrimary->ControlbarNotify(MMCN_SELECT, arg,
  1101. lDataObject);
  1102. }
  1103. // Handle extension controlbars
  1104. CControlbarsList newCBs;
  1105. POSITION pos = extnSnapins.GetHeadPosition();
  1106. while (pos)
  1107. {
  1108. CControlbar* pCbar = NULL;
  1109. CLSID& clsid = extnSnapins.GetNext(pos);
  1110. POSITION pos2 = m_SelData.m_listExtCBs.GetHeadPosition();
  1111. POSITION pos2Prev = 0;
  1112. while (pos2)
  1113. {
  1114. pos2Prev = pos2;
  1115. pCbar = m_SelData.m_listExtCBs.GetNext(pos2);
  1116. ASSERT(pCbar != NULL);
  1117. if (pCbar->IsSameSnapin(clsid) == TRUE)
  1118. break;
  1119. pCbar = NULL;
  1120. }
  1121. if (pCbar != NULL)
  1122. {
  1123. ASSERT(pos2Prev != 0);
  1124. m_SelData.m_listExtCBs.RemoveAt(pos2Prev);
  1125. }
  1126. else
  1127. {
  1128. IExtendControlbarPtr spECB;
  1129. HRESULT hr = spECB.CreateInstance(clsid, NULL, MMC_CLSCTX_INPROC);
  1130. CHECK_HRESULT(hr);
  1131. if (SUCCEEDED(hr))
  1132. pCbar = CreateControlbar(spECB, clsid);
  1133. }
  1134. if (pCbar != NULL)
  1135. newCBs.AddHead(pCbar);
  1136. }
  1137. m_SelData.ScDestroyExtensionCtrlbars();
  1138. pos = newCBs.GetHeadPosition();
  1139. while (pos)
  1140. {
  1141. CControlbar* pCbar = newCBs.GetNext(pos);
  1142. m_SelData.m_listExtCBs.AddHead(pCbar);
  1143. pCbar->ControlbarNotify(MMCN_SELECT, arg, lDataObject);
  1144. }
  1145. newCBs.RemoveAll();
  1146. return S_OK;
  1147. }