Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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