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.

1250 lines
38 KiB

  1. //____________________________________________________________________________
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997 - 1999
  5. //
  6. // File: verbs.cpp
  7. //
  8. // Contents:
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 4/9/1997 RaviR Created
  15. //____________________________________________________________________________
  16. //
  17. #include "stdafx.h"
  18. #include "multisel.h"
  19. #include "tasks.h"
  20. #include "scopndcb.h"
  21. #ifdef _DEBUG
  22. #undef THIS_FILE
  23. static char THIS_FILE[] = __FILE__;
  24. #endif
  25. #ifdef DBG
  26. CTraceTag tagVerbs(TEXT("Verbs"), TEXT("Verbs"));
  27. #endif
  28. //############################################################################
  29. //############################################################################
  30. //
  31. // Implementation of class CConsoleVerbImpl
  32. //
  33. //############################################################################
  34. //############################################################################
  35. BYTE GetTBSTATE(MMC_BUTTON_STATE mmcState)
  36. {
  37. switch (mmcState)
  38. {
  39. case ENABLED: return TBSTATE_ENABLED;
  40. case CHECKED: return TBSTATE_CHECKED;
  41. case HIDDEN: return TBSTATE_HIDDEN;
  42. case INDETERMINATE: return TBSTATE_INDETERMINATE;
  43. case BUTTONPRESSED: return TBSTATE_PRESSED;
  44. default:
  45. ASSERT(0);
  46. return TBSTATE_ENABLED;
  47. }
  48. }
  49. EVerb GetEVerb(MMC_CONSOLE_VERB cVerb)
  50. {
  51. switch (cVerb)
  52. {
  53. case MMC_VERB_OPEN: return evOpen;
  54. case MMC_VERB_CUT: return evCut;
  55. case MMC_VERB_COPY: return evCopy;
  56. case MMC_VERB_PASTE: return evPaste;
  57. case MMC_VERB_DELETE: return evDelete;
  58. case MMC_VERB_PROPERTIES: return evProperties;
  59. case MMC_VERB_RENAME: return evRename;
  60. case MMC_VERB_REFRESH: return evRefresh;
  61. case MMC_VERB_PRINT: return evPrint;
  62. default:
  63. ASSERT(0 && "UNexpected");
  64. return evOpen;
  65. }
  66. }
  67. MMC_CONSOLE_VERB GetConsoleVerb(EVerb eVerb)
  68. {
  69. switch (eVerb)
  70. {
  71. case evOpen: return MMC_VERB_OPEN;
  72. case evCopy: return MMC_VERB_COPY;
  73. case evCut: return MMC_VERB_CUT;
  74. case evPaste: return MMC_VERB_PASTE;
  75. case evDelete: return MMC_VERB_DELETE;
  76. case evProperties: return MMC_VERB_PROPERTIES;
  77. case evRename: return MMC_VERB_RENAME;
  78. case evRefresh: return MMC_VERB_REFRESH;
  79. case evPrint: return MMC_VERB_PRINT;
  80. default:
  81. ASSERT(0 && "UNexpected");
  82. return MMC_VERB_OPEN;
  83. }
  84. }
  85. DEBUG_DECLARE_INSTANCE_COUNTER(CConsoleVerbImpl);
  86. CConsoleVerbImpl::CConsoleVerbImpl()
  87. : m_DefaultVerb(MMC_VERB_OPEN), m_pVerbSet(NULL), m_bCutVerbDisabledBySnapin(false)
  88. {
  89. #ifdef DBG
  90. DEBUG_INCREMENT_INSTANCE_COUNTER(CConsoleVerbImpl);
  91. dbg_cRef_CConsoleVerbImpl = 0;
  92. #endif
  93. }
  94. #ifdef DBG
  95. ULONG CConsoleVerbImpl::InternalAddRef()
  96. {
  97. ++dbg_cRef_CConsoleVerbImpl;
  98. return CComObjectRoot::InternalAddRef();
  99. }
  100. ULONG CConsoleVerbImpl::InternalRelease()
  101. {
  102. --dbg_cRef_CConsoleVerbImpl;
  103. return CComObjectRoot::InternalRelease();
  104. }
  105. #endif // DBG
  106. CConsoleVerbImpl::~CConsoleVerbImpl()
  107. {
  108. DEBUG_DECREMENT_INSTANCE_COUNTER(CConsoleVerbImpl);
  109. }
  110. STDMETHODIMP
  111. CConsoleVerbImpl::GetVerbState(
  112. MMC_CONSOLE_VERB eCmdID,
  113. MMC_BUTTON_STATE nState,
  114. BOOL* pbState)
  115. {
  116. DECLARE_SC(sc, TEXT("CConsoleVerbImpl::GetVerbState"));
  117. sc = ScCheckPointers(pbState);
  118. if (sc)
  119. return sc.ToHr();
  120. LPCONSOLE_VERB_STATE pCS = GetConsoleVerbState(eCmdID);
  121. sc = ScCheckPointers(pCS, E_UNEXPECTED);
  122. if (sc)
  123. return sc.ToHr();
  124. /*
  125. * Special case for cut verb:
  126. *
  127. * Pre MMC2.0 : Snapin never called IConsoleVerb::SetVerbState with cut verb
  128. * except with (cut, disable) state, to enable cut the Snapin has to enable
  129. * copy & delete verbs.
  130. *
  131. * MMC2.0 : snapin can enable/disable cut verb just like any other verb.
  132. * Then if hidden hide it.
  133. *
  134. * If snapin has enabled or disabled the cut verb then below BLOCK1 is
  135. * irrelevant, the BLOCK2 will override the value.
  136. * If snapin did not enable the cut verb but enabled copy & delete then
  137. * the block BLOCK2. set the cut verb appropriately.
  138. */
  139. // BLOCK1. Special case for MMC1.2 cut verb.
  140. if ( (eCmdID == MMC_VERB_CUT) && (!m_bCutVerbDisabledBySnapin) )
  141. {
  142. // Pre MMC2.0
  143. LPCONSOLE_VERB_STATE pCSDelete = GetConsoleVerbState(MMC_VERB_DELETE);
  144. LPCONSOLE_VERB_STATE pCSCopy = GetConsoleVerbState(MMC_VERB_COPY);
  145. sc = ScCheckPointers(pCSDelete, pCSCopy, E_UNEXPECTED);
  146. if (sc)
  147. return sc.ToHr();
  148. if (TBSTATE_ENABLED & pCSCopy->GetState() & pCSDelete->GetState())
  149. {
  150. // Set Cut verb to be not hidden & enabled.
  151. pCS->SetState(pCS->GetState() & ~GetTBSTATE(HIDDEN));
  152. pCS->SetState(pCS->GetState() | GetTBSTATE(ENABLED));
  153. }
  154. }
  155. // BLOCK2. Get the given verbs state.
  156. *pbState = (pCS->GetState() & GetTBSTATE(nState)) ? TRUE : FALSE;
  157. return sc.ToHr();
  158. }
  159. STDMETHODIMP
  160. CConsoleVerbImpl::SetVerbState(
  161. MMC_CONSOLE_VERB eCmdID,
  162. MMC_BUTTON_STATE nState,
  163. BOOL bState)
  164. {
  165. MMC_TRY
  166. LPCONSOLE_VERB_STATE pCS = GetConsoleVerbState(eCmdID);
  167. ASSERT(pCS != NULL);
  168. if (pCS == NULL)
  169. return E_FAIL;
  170. // If snapin has enabled/disabled cut verb note it.
  171. // Used by CConsoleVerbImpl::GetVerbState.
  172. if ( (MMC_VERB_CUT == eCmdID) && (nState & ENABLED) )
  173. m_bCutVerbDisabledBySnapin = (bState == FALSE);
  174. if (bState)
  175. pCS->SetState(pCS->GetState() | GetTBSTATE(nState));
  176. else
  177. pCS->SetState(pCS->GetState() & ~GetTBSTATE(nState));
  178. if (nState == HIDDEN && bState == TRUE)
  179. {
  180. pCS->SetHiddenBySnapin(true);
  181. }
  182. /*
  183. * If we're enabling, make sure the verb is not hidden.
  184. * We do this for compatibility. For v1.0, the default state
  185. * for a verb was disabled and visible when it actually should
  186. * have been disabled and hidden. Therefore, v1.0 snap-ins could
  187. * have written
  188. *
  189. * pConsoleVerb->SetVerbState (verb, ENABLED, TRUE);
  190. *
  191. * and had an enabled, visible verb. Now that we've fixed the
  192. * default state (bug 150874), we need to make sure v1.0 snap-ins
  193. * that wrote code like the above will still work as they used to.
  194. */
  195. if ((nState == ENABLED) && (bState == TRUE) && (!pCS->IsHiddenBySnapin()))
  196. pCS->SetState(pCS->GetState() & ~GetTBSTATE(HIDDEN));
  197. ASSERT(GetVerbSet() != NULL);
  198. if (GetVerbSet() != NULL)
  199. GetVerbSet()->Notify(this, eCmdID);
  200. return S_OK;
  201. MMC_CATCH
  202. }
  203. HRESULT CConsoleVerbImpl::SetDisabledAll(void)
  204. {
  205. for(int i=0; i< evMax; i++)
  206. m_rgConsoleVerbStates[i].Disable();
  207. m_bCutVerbDisabledBySnapin = false;
  208. return S_OK;
  209. }
  210. STDMETHODIMP CConsoleVerbImpl::SetDefaultVerb(MMC_CONSOLE_VERB eCmdID)
  211. {
  212. m_DefaultVerb = eCmdID;
  213. return S_OK;
  214. }
  215. LPCONSOLE_VERB_STATE CConsoleVerbImpl::GetConsoleVerbState(MMC_CONSOLE_VERB eCmdID)
  216. {
  217. if( (eCmdID < MMC_VERB_FIRST) || (eCmdID > MMC_VERB_LAST) )
  218. return NULL;
  219. else
  220. return &m_rgConsoleVerbStates[eCmdID- MMC_VERB_FIRST];
  221. }
  222. //############################################################################
  223. //############################################################################
  224. //
  225. // Implementation of class CVerbSet
  226. //
  227. //############################################################################
  228. //############################################################################
  229. DEBUG_DECLARE_INSTANCE_COUNTER(CVerbSet);
  230. /*+-------------------------------------------------------------------------*
  231. *
  232. * _QueryConsoleVerb
  233. *
  234. * PURPOSE:
  235. *
  236. * PARAMETERS:
  237. * CNode* pNode :
  238. * LPCONSOLEVERB* ppConsoleVerb :
  239. *
  240. * RETURNS:
  241. * HRESULT
  242. *
  243. *+-------------------------------------------------------------------------*/
  244. HRESULT _QueryConsoleVerb(CNode* pNode, LPCONSOLEVERB* ppConsoleVerb)
  245. {
  246. DECLARE_SC(sc, TEXT("::_QueryConsoleVerb"));
  247. sc = ScCheckPointers(pNode, ppConsoleVerb);
  248. if (sc)
  249. return sc.ToHr();
  250. *ppConsoleVerb = NULL;
  251. CComponent *pComponent = pNode->GetPrimaryComponent();
  252. sc = ScCheckPointers(pComponent, E_UNEXPECTED);
  253. if (sc)
  254. return sc.ToHr();
  255. IFramePrivate *pFrame = pComponent->GetIFramePrivate();
  256. sc = ScCheckPointers(pFrame, E_UNEXPECTED);
  257. if (sc)
  258. return sc.ToHr();
  259. sc = pFrame->QueryConsoleVerb(ppConsoleVerb);
  260. if (sc)
  261. return sc.ToHr();
  262. return sc.ToHr();
  263. }
  264. /*+-------------------------------------------------------------------------*
  265. *
  266. * CVerbSetBase::_GetVerbState
  267. *
  268. * PURPOSE: Return the state of given verb. The state is in current
  269. * IConsoleVerb ptr. Translate the states from this object
  270. * into the SVerbState array.
  271. *
  272. * PARAMETERS:
  273. * EVerb ev :
  274. *
  275. * RETURNS:
  276. * BYTE
  277. *
  278. *+-------------------------------------------------------------------------*/
  279. BYTE CVerbSetBase::_GetVerbState(EVerb ev)
  280. {
  281. if (m_rbVerbState[ev].bAskSnapin != 1)
  282. return m_rbVerbState[ev].nState;
  283. if (m_spConsoleVerbCurr == NULL)
  284. return 0;
  285. m_rbVerbState[ev].nState = 0; // reset
  286. MMC_CONSOLE_VERB verb = ::GetConsoleVerb(ev);
  287. BOOL bReturn = FALSE;
  288. m_spConsoleVerbCurr->GetVerbState(verb, ENABLED, &bReturn);
  289. if (bReturn == TRUE)
  290. m_rbVerbState[ev].nState |= TBSTATE_ENABLED;
  291. m_spConsoleVerbCurr->GetVerbState(verb, HIDDEN, &bReturn);
  292. if (bReturn == TRUE)
  293. m_rbVerbState[ev].nState |= TBSTATE_HIDDEN;
  294. m_rbVerbState[ev].bAskSnapin = 2;
  295. return m_rbVerbState[ev].nState;
  296. }
  297. /*+-------------------------------------------------------------------------*
  298. *
  299. * CVerbSetBase::ScComputeVerbStates
  300. *
  301. * PURPOSE: With given context like scope or result, if result is it background
  302. * or ocx or web or multiselection compute the verbstates.
  303. *
  304. * Eventhough snapin can set any verb for its items certain verbs are
  305. * not valid in some circumstances. This method takes care of that.
  306. *
  307. * RETURNS:
  308. * SC
  309. *
  310. *+-------------------------------------------------------------------------*/
  311. SC CVerbSetBase::ScComputeVerbStates()
  312. {
  313. DECLARE_SC(sc, TEXT("CVerbSetBase::ScComputeVerbStates"));
  314. // reset
  315. m_spConsoleVerbCurr = NULL;
  316. for (int i=0; i<evMax; ++i)
  317. {
  318. m_rbVerbState[i].nState = TBSTATE_HIDDEN;
  319. m_rbVerbState[i].bAskSnapin = 0;
  320. }
  321. // If the verb context data is invalid, we have already hidden the
  322. // verbs above so just return .
  323. if (! m_bVerbContextDataValid)
  324. return sc;
  325. sc = ScCheckPointers(m_pNode, E_UNEXPECTED);
  326. if (sc)
  327. return sc;
  328. BOOL bScopeItemSelected;
  329. CNode *pSelectedNode = NULL;
  330. MMC_COOKIE cookie = -1;
  331. sc = CNodeCallback::ScExtractLVData(m_pNode, m_bScopePaneSelected, m_lResultCookie,
  332. &pSelectedNode, bScopeItemSelected, cookie);
  333. if (sc)
  334. return sc.ToHr();
  335. sc = ScCheckPointers(pSelectedNode, E_UNEXPECTED);
  336. if (sc)
  337. return sc;
  338. // Handle background separately (not same as scope item selected
  339. // which is the default handling of background).
  340. if (m_lResultCookie == LVDATA_BACKGROUND)
  341. {
  342. // ask snapin for PASTE, PROPERTIES & REFRESH.
  343. sc = _QueryConsoleVerb(pSelectedNode, &m_spConsoleVerbCurr);
  344. if (sc)
  345. return sc;
  346. _AskSnapin(evPaste);
  347. _AskSnapin(evProperties);
  348. _AskSnapin(evRefresh);
  349. _AskSnapin(evPrint);
  350. return sc;
  351. }
  352. else if (bScopeItemSelected)
  353. {
  354. if (pSelectedNode->IsStaticNode())
  355. {
  356. if (pSelectedNode->IsConsoleRoot())
  357. {
  358. // CONSOLE ROOT is selected
  359. _EnableVerb(evRename);
  360. _HideVerb(evOpen);
  361. _HideVerb(evCut);
  362. _HideVerb(evCopy);
  363. _HideVerb(evDelete);
  364. _HideVerb(evRefresh);
  365. _HideVerb(evPaste);
  366. _HideVerb(evPrint);
  367. return sc;
  368. }
  369. else
  370. {
  371. _EnableVerb(evOpen);
  372. // Ask the snapin if paste should be
  373. // enabled for its root node.
  374. _AskSnapin(evPaste);
  375. _HideVerb(evCut);
  376. _HideVerb(evCopy);
  377. _HideVerb(evDelete);
  378. }
  379. // Static-Snapin node
  380. // Ask snapin for RENAME, REFRESH & PROPERTIES
  381. sc = _QueryConsoleVerb(pSelectedNode, &m_spConsoleVerbCurr);
  382. if (sc)
  383. return sc;
  384. _AskSnapin(evOpen);
  385. _AskSnapin(evRefresh);
  386. _AskSnapin(evRename);
  387. _AskSnapin(evPrint);
  388. _AskSnapin(evProperties);
  389. }
  390. else
  391. {
  392. // ask snapin for all the verbs.
  393. sc = _QueryConsoleVerb(pSelectedNode, &m_spConsoleVerbCurr);
  394. if (sc)
  395. return sc;
  396. _AskSnapin(evOpen);
  397. _AskSnapin(evCut);
  398. _AskSnapin(evCopy);
  399. _AskSnapin(evPaste);
  400. _AskSnapin(evDelete);
  401. _AskSnapin(evRename);
  402. _AskSnapin(evRefresh);
  403. _AskSnapin(evPrint);
  404. _AskSnapin(evProperties);
  405. }
  406. }
  407. else if (m_lResultCookie == LVDATA_MULTISELECT)
  408. {
  409. ASSERT(!bScopeItemSelected);
  410. if (! m_pMultiSelection)
  411. {
  412. CViewData *pViewData = pSelectedNode->GetViewData();
  413. sc = ScCheckPointers(pViewData, E_UNEXPECTED);
  414. if (sc)
  415. return sc;
  416. m_pMultiSelection = pViewData->GetMultiSelection();
  417. sc = ScCheckPointers(m_pMultiSelection, E_UNEXPECTED);
  418. if (sc)
  419. return sc;
  420. }
  421. // if selectedf items are from the primary snapin ask the snapin for all the verbs.
  422. // Does all the selected items belong to the primary snapin?
  423. if (m_pMultiSelection->IsSingleSnapinSelection())
  424. {
  425. // If so ask the snapin for properties
  426. sc = _QueryConsoleVerb(pSelectedNode, &m_spConsoleVerbCurr);
  427. if (sc)
  428. return sc;
  429. _AskSnapin(evCut);
  430. _AskSnapin(evCopy);
  431. _AskSnapin(evDelete);
  432. _AskSnapin(evProperties);
  433. _AskSnapin(evPrint);
  434. }
  435. else
  436. {
  437. // Multiple snapin items are selected. Even if one item
  438. // supports cut/copy/delete then enable the verb.
  439. BOOL bEnable = false;
  440. sc = m_pMultiSelection->ScIsVerbEnabledInclusively(MMC_VERB_CUT, bEnable);
  441. if (sc)
  442. return sc;
  443. _EnableVerb(evCut, bEnable);
  444. bEnable = false;
  445. sc = m_pMultiSelection->ScIsVerbEnabledInclusively(MMC_VERB_COPY, bEnable);
  446. if (sc)
  447. return sc;
  448. _EnableVerb(evCopy, bEnable);
  449. bEnable = false;
  450. sc = m_pMultiSelection->ScIsVerbEnabledInclusively(MMC_VERB_DELETE, bEnable);
  451. if (sc)
  452. return sc;
  453. _EnableVerb(evDelete, bEnable);
  454. }
  455. } else if ( (m_lResultCookie == LVDATA_CUSTOMOCX) ||
  456. (m_lResultCookie == LVDATA_CUSTOMWEB) )
  457. {
  458. // ask snapin for all the verbs.
  459. sc = _QueryConsoleVerb(pSelectedNode, &m_spConsoleVerbCurr);
  460. if (sc)
  461. return sc;
  462. _AskSnapin(evOpen);
  463. _AskSnapin(evCut);
  464. _AskSnapin(evCopy);
  465. _AskSnapin(evPaste);
  466. _AskSnapin(evDelete);
  467. _AskSnapin(evRename);
  468. _AskSnapin(evRefresh);
  469. _AskSnapin(evPrint);
  470. _AskSnapin(evProperties);
  471. return sc;
  472. }
  473. else
  474. {
  475. // ask snapin for all the verbs.
  476. sc = _QueryConsoleVerb(pSelectedNode, &m_spConsoleVerbCurr);
  477. if (sc)
  478. return sc;
  479. _AskSnapin(evOpen);
  480. _AskSnapin(evCut);
  481. _AskSnapin(evCopy);
  482. _AskSnapin(evPaste);
  483. _AskSnapin(evDelete);
  484. _AskSnapin(evRename);
  485. _AskSnapin(evRefresh);
  486. _AskSnapin(evPrint);
  487. _AskSnapin(evProperties);
  488. }
  489. return sc;
  490. }
  491. /*+-------------------------------------------------------------------------*
  492. *
  493. * CVerbSetBase::GetVerbState
  494. *
  495. * PURPOSE:
  496. *
  497. * PARAMETERS:
  498. * MMC_CONSOLE_VERB cVerb :
  499. * MMC_BUTTON_STATE nState :
  500. * BOOL* pbState :
  501. *
  502. * RETURNS:
  503. * STDMETHODIMP
  504. *
  505. *+-------------------------------------------------------------------------*/
  506. STDMETHODIMP
  507. CVerbSetBase::GetVerbState(
  508. MMC_CONSOLE_VERB cVerb,
  509. MMC_BUTTON_STATE nState,
  510. BOOL* pbState)
  511. {
  512. *pbState = (_GetVerbState(GetEVerb(cVerb)) & GetTBSTATE(nState)) ? TRUE : FALSE;
  513. return S_OK;
  514. }
  515. STDMETHODIMP
  516. CVerbSetBase::GetDefaultVerb(
  517. MMC_CONSOLE_VERB* peCmdID)
  518. {
  519. DECLARE_SC(sc, TEXT("CVerbSetBase::GetDefaultVerb"));
  520. sc = ScCheckPointers(peCmdID);
  521. if (sc)
  522. return sc.ToHr();
  523. *peCmdID = MMC_VERB_NONE;
  524. if ( (m_bVerbContextDataValid) && (m_lResultCookie == LVDATA_MULTISELECT) )
  525. return sc.ToHr();
  526. if (m_spConsoleVerbCurr == NULL) // Not an error, default verb is requested when the verbset is reset.
  527. return sc.ToHr();
  528. sc = m_spConsoleVerbCurr->GetDefaultVerb(peCmdID);
  529. if (sc)
  530. return sc.ToHr();
  531. return sc.ToHr();
  532. }
  533. /*+-------------------------------------------------------------------------*
  534. *
  535. * CVerbSet::Notify
  536. *
  537. * PURPOSE: Update the verb state changes to standard toolbar.
  538. *
  539. * PARAMETERS:
  540. * IConsoleVerb* pCVIn :
  541. * MMC_CONSOLE_VERB cVerb :
  542. *
  543. * RETURNS:
  544. * void
  545. *
  546. *+-------------------------------------------------------------------------*/
  547. void
  548. CVerbSet::Notify(
  549. IConsoleVerb* pCVIn,
  550. MMC_CONSOLE_VERB cVerb)
  551. {
  552. /*
  553. * MMC creates temporary verb to findout verb state for another node or item
  554. * and mmc also needs verb states for determining drop targets which are not
  555. * currently selected node. In these cases toolbar should not be changed.
  556. */
  557. if (!IsChangesToStdbarEnabled() || m_spConsoleVerbCurr != pCVIn)
  558. return;
  559. EVerb ev = GetEVerb(cVerb);
  560. if (m_rbVerbState[ev].bAskSnapin != 0)
  561. {
  562. m_rbVerbState[ev].bAskSnapin = 1;
  563. CNode *pNode = m_pNode;
  564. ASSERT(pNode != NULL);
  565. if (NULL == pNode)
  566. return;
  567. CViewData* pViewData = pNode->GetViewData();
  568. ASSERT(NULL != pViewData);
  569. if (NULL == pViewData)
  570. return;
  571. pViewData->ScUpdateStdbarVerb(cVerb);
  572. }
  573. }
  574. //+-------------------------------------------------------------------
  575. //
  576. // Member: CVerbSet::ScInitialize
  577. //
  578. // Synopsis: Given the selection context initialize the verbs by
  579. // sending MMCN_SELECT or MMCN_DESELECALL to snapin's
  580. // IComponent::Notify and computing the verbs.
  581. //
  582. // Arguments: [pNode] - [in] that owns view.
  583. // [bScope] - [in] Scope or result item.
  584. // [bSelect] - [in] Select or Deselect.
  585. // [bLVBackgroundSelected] - [in]
  586. // [lResultCookie] - [in] If resultpane item then
  587. // this is LVDATA of the item.
  588. //
  589. // Returns: SC
  590. //
  591. //--------------------------------------------------------------------
  592. SC CVerbSet::ScInitialize (CNode *pNode, bool bScopePaneSelected,
  593. bool bSelect, bool bLVBackgroundSelected,
  594. LPARAM lResultCookie)
  595. {
  596. DECLARE_SC(sc, _T("CVerbSet::ScInitialize"));
  597. sc = ScCheckPointers(pNode);
  598. if (sc)
  599. return sc;
  600. if (lResultCookie == LVDATA_MULTISELECT)
  601. return (sc = E_INVALIDARG);
  602. if (bLVBackgroundSelected)
  603. {
  604. ASSERT(lResultCookie == LVDATA_BACKGROUND);
  605. bScopePaneSelected = true;
  606. }
  607. /*
  608. * 1. Store the selection context information in the verb-set for resending
  609. * MMCN_SELECT after temporary selection notifications.
  610. */
  611. CViewData *pViewData = pNode->GetViewData();
  612. sc = ScCheckPointers(pViewData, E_UNEXPECTED);
  613. if (sc)
  614. return sc;
  615. CComponent *pCC = NULL;
  616. // sanity check - if it is a result item then we need to have the valid cookie.
  617. // but for virtual list - cookie is just an index - it is always valid.
  618. // see bug #143401 why IsVirtual is needed
  619. if ( (! bScopePaneSelected) && (!pViewData->IsVirtualList()) &&(lResultCookie == 0))
  620. return (sc = E_INVALIDARG);
  621. /*
  622. * Need to send MMCN_SELECT or MMCN_DESELECTALL notification. Calculate
  623. * this notification now.
  624. */
  625. BOOL bListPadItem = pViewData->HasListPad() && !IS_SPECIAL_LVDATA(lResultCookie);
  626. MMC_NOTIFY_TYPE eNotify = MMCN_SELECT;
  627. // On deselect of a virtual listview item, the underlying list-view sends deselect
  628. // with cookie of -1. So we send MMCN_DESELECT_ALL with NULL dataobject as the
  629. // index of de-selected item is not known.
  630. if (bSelect == FALSE && lResultCookie == -1 && pViewData->IsVirtualList() == TRUE )
  631. {
  632. eNotify = MMCN_DESELECT_ALL;
  633. pCC = pNode->GetPrimaryComponent();
  634. sc = ScCheckPointers(pCC, E_UNEXPECTED);
  635. if (sc)
  636. return sc;
  637. }
  638. else if (pViewData->HasOCX() || (pViewData->HasWebBrowser() && !bListPadItem) )
  639. {
  640. // Select/Deselect Web or OCX. (except if item is in MMC List control)
  641. eNotify = bSelect ? MMCN_SELECT : MMCN_DESELECT_ALL;
  642. pCC = pNode->GetPrimaryComponent();
  643. sc = ScCheckPointers(pCC, E_UNEXPECTED);
  644. if (sc)
  645. return sc;
  646. }
  647. bool bScopeItem = bScopePaneSelected;
  648. IDataObjectPtr spDataObject = NULL;
  649. LPDATAOBJECT lpDataObject = NULL;
  650. // 2. Get the dataobject & CComponent for given context.
  651. // only if event is MMCN_SELECT.
  652. if (eNotify != MMCN_DESELECT_ALL)
  653. {
  654. sc = pNode->ScGetDataObject(bScopePaneSelected, lResultCookie, bScopeItem, &lpDataObject, &pCC);
  655. if (sc)
  656. return sc;
  657. sc = ScCheckPointers(lpDataObject, pCC, E_UNEXPECTED);
  658. if (sc)
  659. return sc;
  660. if (! IS_SPECIAL_DATAOBJECT(lpDataObject) )
  661. spDataObject.Attach(lpDataObject, false/*fAddRef*/);
  662. }
  663. // Before sending select reset the console verb states.
  664. sc = pCC->ScResetConsoleVerbStates();
  665. if (sc)
  666. return sc;
  667. #ifdef DBG
  668. Trace(tagVerbs, _T("Sent (MMCN_SELECT %s %s) for permanent verb to snapin with node name %s\n"),
  669. bScopeItem ? _T("Scope") : _T("Result"),
  670. bSelect ? _T("Select") : _T("De-select"),
  671. pNode->GetDisplayName().data());
  672. #endif
  673. SC scNoTrace = pCC->Notify(lpDataObject, eNotify, MAKELONG((WORD)bScopeItem, (WORD)bSelect), 0);
  674. if (scNoTrace)
  675. {
  676. TraceSnapinError(TEXT("Snapin has returned error from IComponent::Notify with MMCN_SELECT event"), scNoTrace);
  677. }
  678. Reset();
  679. m_bScopePaneSelected = bScopePaneSelected;
  680. m_bVerbContextDataValid = bSelect;
  681. m_lResultCookie = lResultCookie;
  682. m_pNode = pNode;
  683. sc = ScComputeVerbStates();
  684. if (sc)
  685. return sc;
  686. // If the item is deselected then the cached context information should be nuked.
  687. if (! bSelect)
  688. Reset();
  689. return (sc);
  690. }
  691. //+-------------------------------------------------------------------
  692. //
  693. // Member: CVerbSetBase::ScInitializeForMultiSelection
  694. //
  695. // Synopsis: Initialize the verbset object for multiselection. Unlike
  696. // single selection in which above CVerbSet::ScInitialize is
  697. // used, in case of multiselect, the CMultiSelection object
  698. // knows what is selected in resultpane. It then gets dataobjects
  699. // for those selections from snapins and sends MMCN_SELECT to those
  700. // snapins to set verbs.
  701. //
  702. // Arguments: [pNode] - [in] owner of resultpane.
  703. // [bSelect] - [in] select or deselect.
  704. //
  705. // Returns: SC
  706. //
  707. //--------------------------------------------------------------------
  708. SC CVerbSetBase::ScInitializeForMultiSelection (CNode *pNode, bool bSelect)
  709. {
  710. DECLARE_SC(sc, _T("CVerbSetBase::ScInitializeForMultiSelection"));
  711. sc = ScCheckPointers(pNode);
  712. if (sc)
  713. return sc;
  714. /*
  715. * Store the selection context information in the verb-set for resending
  716. * MMCN_SELECT after temporary selection notifications.
  717. */
  718. Reset();
  719. m_bScopePaneSelected = false;
  720. m_bVerbContextDataValid = bSelect;
  721. m_lResultCookie = LVDATA_MULTISELECT;
  722. m_pNode = pNode;
  723. return (sc);
  724. }
  725. /*+-------------------------------------------------------------------------*
  726. * class CDisableStandardToolbarChanges
  727. *
  728. *
  729. * PURPOSE: A class that disables changes to standard toolbar due to
  730. * temp-verb MMCN_SELECTs and enables when destructed (goes out of scope).
  731. *
  732. *+-------------------------------------------------------------------------*/
  733. class CDisableStandardToolbarChanges
  734. {
  735. public:
  736. CDisableStandardToolbarChanges(CVerbSet* pVerbSet) : m_pVerbSet(pVerbSet)
  737. {
  738. ASSERT(pVerbSet != NULL);
  739. if (pVerbSet)
  740. pVerbSet->DisableChangesToStdbar();
  741. }
  742. ~CDisableStandardToolbarChanges()
  743. {
  744. ASSERT(m_pVerbSet != NULL);
  745. if (m_pVerbSet)
  746. m_pVerbSet->EnableChangesToStdbar();
  747. }
  748. private:
  749. CVerbSet *m_pVerbSet;
  750. };
  751. //+-------------------------------------------------------------------
  752. //
  753. // Member: CTemporaryVerbSet::ScInitialize
  754. //
  755. // Synopsis: Initialize the temp verb set,
  756. //
  757. // Since we are sending MMCN_SELECT notifications to the snapin
  758. // to calculate temp verbs,
  759. //
  760. // 1. first send de-select to the item for which we sent
  761. // (MMCN_SELECT, true) last time.
  762. // (If last one is (MMCN_SELECT,false) then skip this and 4th step)
  763. //
  764. // 2. Send (MMCN_SELECT, true) for temp verb calculation.
  765. // 3. Send (MMCN_SELECT, false) for temp verb calculation.
  766. //
  767. // 4. Now send (MMCN_SELECT, true) to select original item (in step 1).
  768. //
  769. // So we need to compute the dataobject for temp-selected item (from
  770. // given parameters) and for originally selected item (ask the viewdata).
  771. //
  772. // Arguments: [pNode] - [in] bScope = true, the node that will be temp selected else
  773. // the node that owns the result pane item that is temp selected.
  774. // [lResultCookie] - [in] If result-item, the LPARAM (can be scope item in result pane).
  775. // [bScopePaneSel] - [in]
  776. //
  777. // Returns: SC
  778. //
  779. //--------------------------------------------------------------------
  780. SC CTemporaryVerbSet::ScInitialize (CNode *pNode, LPARAM lResultCookie, bool bScopePaneSel)
  781. {
  782. DECLARE_SC(sc, _T("CTemporaryVerbSet::ScInitialize"));
  783. sc = ScCheckPointers(pNode);
  784. if (sc)
  785. return sc;
  786. bool bScopeItem;
  787. LPDATAOBJECT pDataObject = NULL;
  788. sc = pNode->ScGetDataObject(bScopePaneSel, lResultCookie, bScopeItem, &pDataObject);
  789. if (sc)
  790. return sc;
  791. sc = ScCheckPointers(pDataObject, E_UNEXPECTED);
  792. if (sc)
  793. return sc;
  794. // take ownership & release it on time!!!
  795. IDataObjectPtr spDataObject( IS_SPECIAL_DATAOBJECT(pDataObject) ? NULL : pDataObject, false/*fAddRef*/);
  796. sc = ScInitialize(pDataObject, pNode, bScopePaneSel, lResultCookie);
  797. if (sc)
  798. return sc;
  799. return (sc);
  800. }
  801. //+-------------------------------------------------------------------
  802. //
  803. // Member: CTemporaryVerbSet::ScInitializePermanentVerbSet
  804. //
  805. // Synopsis: Send de-select or select notification to snapin for
  806. // the permanent verb-set object.
  807. //
  808. // Arguments: [pNode] - [in] owner of the result pane.
  809. // [bSelect] - [in] true - send select notification to snapin
  810. // informing it to initialize the verbs
  811. //
  812. // false - send de-select notification to snapin
  813. // informing it to uninitialize the verbs.
  814. //
  815. // Returns: SC
  816. //
  817. //--------------------------------------------------------------------
  818. SC CTemporaryVerbSet::ScInitializePermanentVerbSet (CNode *pNode, bool bSelect)
  819. {
  820. DECLARE_SC(sc, _T("CTemporaryVerbSet::ScInitializePermanentVerbSet"));
  821. sc = ScCheckPointers(pNode);
  822. if (sc)
  823. return sc;
  824. CViewData *pViewData = pNode->GetViewData();
  825. sc = ScCheckPointers(pViewData, E_UNEXPECTED);
  826. if (sc)
  827. return sc;
  828. // 1. SEND (de)selection to permananet verb set.
  829. IDataObject* pOriginalSelDataObject = NULL;
  830. CComponent *pCCOriginalSel = NULL;
  831. bool bOriginalScopeSel;
  832. bool bOriginallySelected;
  833. LPCTSTR lpszNodeName = NULL;
  834. bool bMultiSelection = false;
  835. SC scNoTrace = pViewData->ScIsVerbSetContextForMultiSelect(bMultiSelection);
  836. if (scNoTrace)
  837. return scNoTrace;
  838. /*
  839. * See if verb context is for multiselection.
  840. * If multiselection we do not send any de-select to be compatible
  841. * with MMC1.2, just return.
  842. */
  843. if (bMultiSelection)
  844. return sc;
  845. scNoTrace = pViewData->ScGetVerbSetData(&pOriginalSelDataObject, &pCCOriginalSel,
  846. bOriginalScopeSel, bOriginallySelected
  847. #ifdef DBG
  848. , &lpszNodeName
  849. #endif
  850. );
  851. if (scNoTrace)
  852. return sc;
  853. // Before sending select reset the console verb states.
  854. sc = pCCOriginalSel->ScResetConsoleVerbStates();
  855. if (sc)
  856. return sc;
  857. // take ownership & release it on time!!!
  858. IDataObjectPtr spDataObject( IS_SPECIAL_DATAOBJECT(pOriginalSelDataObject) ? NULL : pOriginalSelDataObject, false/*fAddRef*/);
  859. // If we sent MMCN_SELECT, true then send de-select else nothing.
  860. if ( (pOriginalSelDataObject != NULL) && (pCCOriginalSel != NULL) && (bOriginallySelected) )
  861. {
  862. #ifdef DBG
  863. Trace(tagVerbs, _T("Sent (MMCN_SELECT %s %sselect) for permanent-verb-restore to snapin with node name %s\n"),
  864. bOriginalScopeSel ? _T("Scope") : _T("Result"),
  865. bSelect ? _T("") : _T("De-"),
  866. lpszNodeName);
  867. #endif
  868. scNoTrace = pCCOriginalSel->Notify(pOriginalSelDataObject, MMCN_SELECT,
  869. MAKELONG(bOriginalScopeSel, bSelect), 0);
  870. if (scNoTrace)
  871. {
  872. TraceSnapinError(TEXT("Snapin has returned error from IComponent::Notify with MMCN_SELECT event"), scNoTrace);
  873. }
  874. // Verbs were initialized, therefore recompute verbstates.
  875. if (bSelect)
  876. {
  877. // get the verbset
  878. CVerbSet* pVerbSet = dynamic_cast<CVerbSet*>( pViewData->GetVerbSet() );
  879. sc = ScCheckPointers( pVerbSet, E_UNEXPECTED );
  880. if (sc)
  881. return sc;
  882. /*
  883. * The selection context information stored in this object is
  884. * invalid upon de-selection of that item.
  885. */
  886. m_bVerbContextDataValid = bSelect;
  887. sc = pVerbSet->ScComputeVerbStates();
  888. if (sc)
  889. return sc;
  890. }
  891. }
  892. return (sc);
  893. }
  894. //+-------------------------------------------------------------------
  895. //
  896. // Member: CTemporaryVerbSet::ScInitialize
  897. //
  898. // Synopsis: Initialize the temp verb set,
  899. //
  900. // Since we are sending MMCN_SELECT notifications to the snapin
  901. // to calculate temp verbs,
  902. //
  903. // 1. first send de-select to the item for which we sent
  904. // (MMCN_SELECT, true) last time.
  905. // (If last one is MMCN_SELECT,false then skip this and 4th step)
  906. //
  907. // 2. Send (MMCN_SELECT, true) for temp verb calculation.
  908. // 3. Send (MMCN_SELECT, false) for temp verb calculation.
  909. //
  910. // 4. Now send (MMCN_SELECT, true) to select original item (in step 1).
  911. //
  912. // So we need to compute the dataobject for temp-selected item (from
  913. // given parameters) and for originally selected item (ask the viewdata).
  914. //
  915. // Arguments: [lpDataObjectForTempSel] - [in] dataobject of the temp selected object.
  916. // [pNodeForTempSel] - [in] bScope = true, the node that will be temp selected else
  917. // the node that owns the result pane item that is temp selected.
  918. // [bTempScopePaneSel] - [in]
  919. // [lResultCookie] - [in]
  920. //
  921. // Returns: SC
  922. //
  923. //--------------------------------------------------------------------
  924. SC CTemporaryVerbSet::ScInitialize (LPDATAOBJECT lpDataObjectForTempSel,
  925. CNode *pNodeForTempSel,
  926. bool bTempScopePaneSel,
  927. LPARAM lResultCookie)
  928. {
  929. DECLARE_SC(sc, _T("CTemporaryVerbSet::ScInitialize"));
  930. sc = ScCheckPointers(lpDataObjectForTempSel, pNodeForTempSel);
  931. if (sc)
  932. return sc;
  933. // get view data
  934. CViewData *pViewData = pNodeForTempSel->GetViewData();
  935. sc = ScCheckPointers( pViewData, E_UNEXPECTED );
  936. if (sc)
  937. return sc;
  938. // get the verbset
  939. CVerbSet* pVerbSet = dynamic_cast<CVerbSet*>( pViewData->GetVerbSet() );
  940. sc = ScCheckPointers( pVerbSet, E_UNEXPECTED );
  941. if (sc)
  942. return sc;
  943. if (! pNodeForTempSel->IsInitialized())
  944. {
  945. sc = pNodeForTempSel->InitComponents();
  946. if (sc)
  947. return sc.ToHr();
  948. }
  949. CComponent *pCCTempSel = pNodeForTempSel->GetPrimaryComponent();
  950. sc = ScCheckPointers(pCCTempSel, E_UNEXPECTED);
  951. if (sc)
  952. return sc;
  953. /*
  954. * We create a temporary verb to get given verb's state. So inform
  955. * the original verb object that there is a temporary verb
  956. * so that standard-toolbars are not applied the temporary verb.
  957. */
  958. CDisableStandardToolbarChanges standardbarChanges(pVerbSet);
  959. bool bTempSelected = true; // always compute verb for selection of an item.
  960. Reset();
  961. m_bScopePaneSelected = bTempScopePaneSel;
  962. m_pNode = pNodeForTempSel;
  963. m_lResultCookie = lResultCookie;
  964. // sanity check - if it is a result item then we need to have the valid cookie.
  965. // but for virtual list - cookie is just an index - it is always valid.
  966. // see bug #143401 why IsVirtual is needed
  967. if ( (! m_bScopePaneSelected) && (!pViewData->IsVirtualList()) && (m_lResultCookie == 0))
  968. return (sc = E_INVALIDARG);
  969. // Ignore the return values from IComponent::Notify
  970. // 1. SEND de-selection to permananet verb set.
  971. sc = ScInitializePermanentVerbSet (pNodeForTempSel, /*bSelect*/ false);
  972. if (sc)
  973. return sc;
  974. // 2. SEND selection to temporary verb set.
  975. #ifdef DBG
  976. Trace(tagVerbs, _T("Sent (MMCN_SELECT %s Select) for tempverbs to snapin with node name %s\n"),
  977. m_bScopePaneSelected ? _T("Scope") : _T("Result"),
  978. pNodeForTempSel->GetDisplayName().data());
  979. #endif
  980. // Before sending select reset the console verb states.
  981. sc = pCCTempSel->ScResetConsoleVerbStates();
  982. if (sc)
  983. return sc;
  984. SC scNoTrace = pCCTempSel->Notify(lpDataObjectForTempSel, MMCN_SELECT, MAKELONG(m_bScopePaneSelected, bTempSelected), 0);
  985. if (scNoTrace)
  986. {
  987. TraceSnapinError(TEXT("Snapin has returned error from IComponent::Notify with MMCN_SELECT event"), scNoTrace);
  988. }
  989. // 2.a) Compute the verbs.
  990. /*
  991. * The selection context information stored in this object is
  992. * invalid upon de-selection of that item.
  993. */
  994. m_bVerbContextDataValid = bTempSelected;
  995. sc = ScComputeVerbStates();
  996. if (sc)
  997. sc.TraceAndClear();
  998. // 3. SEND de-selection to temporary verb set.
  999. #ifdef DBG
  1000. Trace(tagVerbs, _T("Sent (MMCN_SELECT %s De-select) for tempverbs to snapin with node name %s\n"),
  1001. m_bScopePaneSelected ? _T("Scope") : _T("Result"),
  1002. pNodeForTempSel->GetDisplayName().data());
  1003. #endif
  1004. // Before sending select reset the console verb states.
  1005. sc = pCCTempSel->ScResetConsoleVerbStates();
  1006. if (sc)
  1007. return sc;
  1008. scNoTrace = pCCTempSel->Notify(lpDataObjectForTempSel, MMCN_SELECT, MAKELONG(m_bScopePaneSelected, !bTempSelected), 0);
  1009. if (scNoTrace)
  1010. {
  1011. TraceSnapinError(TEXT("Snapin has returned error from IComponent::Notify with MMCN_SELECT event"), scNoTrace);
  1012. }
  1013. // 4. SEND select to permanent verb set.
  1014. sc = ScInitializePermanentVerbSet (pNodeForTempSel, /*bSelect*/ true);
  1015. if (sc)
  1016. return sc;
  1017. return (sc);
  1018. }
  1019. //+-------------------------------------------------------------------
  1020. //
  1021. // Member: CTemporaryVerbSet::ScComputeVerbStates
  1022. //
  1023. // Synopsis: Since this is temp verb set, we need to get the states
  1024. // of all verbs from CConsoleVerbImpl object immediately after
  1025. // we sent MMCN_SELECT with item seelcted. Otherwise they will
  1026. // be overwritten by subsequent SetVerbState (due to restore MMCN_SELECT
  1027. // notifications).
  1028. //
  1029. // Arguments:
  1030. //
  1031. // Returns: SC
  1032. //
  1033. //--------------------------------------------------------------------
  1034. SC CTemporaryVerbSet::ScComputeVerbStates ()
  1035. {
  1036. DECLARE_SC(sc, _T("CTemporaryVerbSet::ScComputeVerbStates"));
  1037. sc = CVerbSetBase::ScComputeVerbStates();
  1038. if (sc)
  1039. return sc;
  1040. // _GetVerbState gets the state of the verb from CConsoleVerbImpl
  1041. // and fills it in this object's members which will be used later.
  1042. for (int verb=evNone; verb < evMax; ++verb)
  1043. _GetVerbState((EVerb)verb);
  1044. // Get the default verb and store it.
  1045. CVerbSetBase::GetDefaultVerb(&m_DefaultVerb);
  1046. return (sc);
  1047. }
  1048. //+-------------------------------------------------------------------
  1049. //
  1050. // Member: CTemporaryVerbSet::GetDefaultVerb
  1051. //
  1052. // Synopsis: Get the default verb for the temp sel.
  1053. //
  1054. // Arguments: [peCmdID] - [out] ptr to default verb.
  1055. //
  1056. // Returns: SC
  1057. //
  1058. //--------------------------------------------------------------------
  1059. HRESULT CTemporaryVerbSet::GetDefaultVerb (MMC_CONSOLE_VERB* peCmdID)
  1060. {
  1061. DECLARE_SC(sc, _T("CTemporaryVerbSet::GetDefaultVerb"));
  1062. sc = ScCheckPointers(peCmdID);
  1063. if (sc)
  1064. return sc.ToHr();
  1065. *peCmdID = m_DefaultVerb;
  1066. return (sc.ToHr());
  1067. }