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.

4554 lines
128 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1999 - 1999
  6. //
  7. // File: scopndcb.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. #include "stdafx.h"
  11. #include "scopndcb.h"
  12. #include "oncmenu.h"
  13. #include "util.h"
  14. #include "amcmsgid.h"
  15. #include "multisel.h"
  16. #include "nmutil.h"
  17. #include "nodemgr.h"
  18. #include "copypast.h"
  19. #include "regutil.h"
  20. #include "taskenum.h"
  21. #include "nodepath.h"
  22. #include "rsltitem.h"
  23. #include "bookmark.h"
  24. #include "tasks.h"
  25. #include "viewpers.h"
  26. #include "colwidth.h"
  27. #include "conframe.h"
  28. #include "constatbar.h"
  29. #include "about.h"
  30. #include "conview.h"
  31. #ifdef _DEBUG
  32. #undef THIS_FILE
  33. static char THIS_FILE[] = __FILE__;
  34. #endif
  35. //############################################################################
  36. //############################################################################
  37. //
  38. // Trace Tags
  39. //
  40. //############################################################################
  41. //############################################################################
  42. #ifdef DBG
  43. CTraceTag tagNodeCallback(TEXT("NodeCallback"), TEXT("NodeCallback"));
  44. #endif
  45. void AddSubmenu_CreateNew(IContextMenuProvider* pICMP, BOOL fStaticFolder );
  46. void AddSubmenu_Task(IContextMenuProvider* pICMP );
  47. DEBUG_DECLARE_INSTANCE_COUNTER(CNodeCallback);
  48. #define INVALID_COMPONENTID -9
  49. void DeleteMultiSelData(CNode* pNode)
  50. {
  51. ASSERT(pNode != NULL);
  52. ASSERT(pNode->GetViewData() != NULL);
  53. CMultiSelection* pMultiSel = pNode->GetViewData()->GetMultiSelection();
  54. if (pMultiSel != NULL)
  55. {
  56. pMultiSel->ReleaseMultiSelDataObject();
  57. pMultiSel->Release();
  58. pNode->GetViewData()->SetMultiSelection(NULL);
  59. }
  60. }
  61. CNodeCallback::CNodeCallback()
  62. : m_pCScopeTree(NULL), m_pNodeUnderInit(NULL)
  63. {
  64. DEBUG_INCREMENT_INSTANCE_COUNTER(CNodeCallback);
  65. }
  66. CNodeCallback::~CNodeCallback()
  67. {
  68. DEBUG_DECREMENT_INSTANCE_COUNTER(CNodeCallback);
  69. }
  70. STDMETHODIMP CNodeCallback::Initialize(IScopeTree* pScopeTree)
  71. {
  72. MMC_TRY
  73. IF_NULL_RETURN_INVALIDARG(pScopeTree);
  74. m_pCScopeTree = dynamic_cast<CScopeTree*>(pScopeTree);
  75. ASSERT(m_pCScopeTree != NULL);
  76. return S_OK;
  77. MMC_CATCH
  78. }
  79. STDMETHODIMP CNodeCallback::GetImages(HNODE hNode, int* piImage, int* piSelectedImage)
  80. {
  81. IF_NULL_RETURN_INVALIDARG(hNode);
  82. MMC_TRY
  83. // They should ask for at least one of the images.
  84. if (piImage == NULL && piSelectedImage == NULL)
  85. return E_INVALIDARG;
  86. // convert to real type
  87. CNode* pNode = CNode::FromHandle(hNode);
  88. if (piImage != NULL)
  89. *piImage = pNode->GetMTNode()->GetImage();
  90. if (piSelectedImage != NULL)
  91. *piSelectedImage = pNode->GetMTNode()->GetOpenImage();
  92. return S_OK;
  93. MMC_CATCH
  94. }
  95. STDMETHODIMP CNodeCallback::GetDisplayName(HNODE hNode, tstring& strName)
  96. {
  97. DECLARE_SC (sc, _T("CNodeCallback::GetDisplayName"));
  98. /*
  99. * clear out the output string
  100. */
  101. strName.erase();
  102. // convert to real type
  103. CNode* pNode = CNode::FromHandle(hNode);
  104. sc = ScCheckPointers (pNode);
  105. if (sc)
  106. return (sc.ToHr());
  107. strName = pNode->GetDisplayName();
  108. return (sc.ToHr());
  109. }
  110. STDMETHODIMP CNodeCallback::GetWindowTitle(HNODE hNode, tstring& strTitle)
  111. {
  112. DECLARE_SC (sc, _T("CNodeCallback::GetWindowTitle"));
  113. /*
  114. * clear out the output string
  115. */
  116. strTitle.erase();
  117. // convert to real type
  118. CNode* pNode = CNode::FromHandle(hNode);
  119. sc = ScCheckPointers (pNode);
  120. if (sc)
  121. return (sc.ToHr());
  122. CComponent* pCC = pNode->GetPrimaryComponent();
  123. sc = ScCheckPointers (pCC, E_UNEXPECTED);
  124. if (sc)
  125. return (sc.ToHr());
  126. IDataObjectPtr spdtobj;
  127. sc = pCC->QueryDataObject(MMC_WINDOW_COOKIE, CCT_UNINITIALIZED, &spdtobj);
  128. if (sc)
  129. return (sc.ToHr());
  130. USES_CONVERSION;
  131. static CLIPFORMAT cfWindowTitle =
  132. (CLIPFORMAT) RegisterClipboardFormat(OLE2T(CCF_WINDOW_TITLE));
  133. sc = ExtractString(spdtobj, cfWindowTitle, strTitle);
  134. if (sc)
  135. return (sc.ToHr());
  136. return (sc.ToHr());
  137. }
  138. inline HRESULT CNodeCallback::_InitializeNode(CNode* pNode)
  139. {
  140. ASSERT(pNode != NULL);
  141. m_pNodeUnderInit = pNode;
  142. HRESULT hr = pNode->InitComponents();
  143. m_pNodeUnderInit = NULL;
  144. return hr;
  145. }
  146. STDMETHODIMP CNodeCallback::GetResultPane(HNODE hNode, CResultViewType& rvt, GUID *pGuidTaskpadID)
  147. {
  148. DECLARE_SC(sc, TEXT("CNodeCallback::GetResultPane"));
  149. IF_NULL_RETURN_INVALIDARG(hNode);
  150. MMC_TRY
  151. USES_CONVERSION;
  152. // convert to real type
  153. CNode* pNode = CNode::FromHandle(hNode);
  154. ASSERT(pNode != NULL);
  155. if (pNode->IsInitialized() == FALSE)
  156. {
  157. sc = _InitializeNode(pNode);
  158. if(sc)
  159. return sc.ToHr();
  160. }
  161. sc = pNode->ScGetResultPane(rvt, pGuidTaskpadID);
  162. if(sc)
  163. return sc.ToHr();
  164. return sc.ToHr();
  165. MMC_CATCH
  166. }
  167. //
  168. // 'hNodeSel' is the curreently selected node in the scope pane. 'lDispInfo' is
  169. // the LV disp info struct.
  170. STDMETHODIMP CNodeCallback::GetDispInfo(HNODE hNodeSel, LV_ITEMW* plvi)
  171. {
  172. IF_NULL_RETURN_INVALIDARG2(hNodeSel, plvi);
  173. if (theApp.ProcessingSnapinChanges() == TRUE)
  174. return E_FAIL;
  175. // convert to real types
  176. CNode* pNodeSel = CNode::FromHandle(hNodeSel);
  177. if (IsBadWritePtr (plvi, sizeof(*plvi)))
  178. return E_INVALIDARG;
  179. return pNodeSel->GetDispInfoForListItem(plvi);
  180. }
  181. STDMETHODIMP CNodeCallback::AddCustomFolderImage (HNODE hNode, IImageListPrivate* pImageList)
  182. {
  183. CNode* pNode = CNode::FromHandle(hNode);
  184. if (pNode) {
  185. CSnapInNode* pSINode = dynamic_cast<CSnapInNode*>(pNode);
  186. if (pSINode)
  187. pSINode->SetResultImageList (pImageList);
  188. }
  189. return S_OK;
  190. }
  191. STDMETHODIMP CNodeCallback::GetState(HNODE hNode, UINT* pnState)
  192. {
  193. IF_NULL_RETURN_INVALIDARG2(hNode, pnState);
  194. MMC_TRY
  195. // convert to real type
  196. CNode* pNode = CNode::FromHandle(hNode);
  197. *pnState = pNode->GetMTNode()->GetState();
  198. return S_OK;
  199. MMC_CATCH
  200. }
  201. STDMETHODIMP CNodeCallback::Notify(HNODE hNode, NCLBK_NOTIFY_TYPE event,
  202. LONG_PTR arg, LPARAM param)
  203. {
  204. MMC_TRY
  205. HRESULT hr = S_OK;
  206. if (hNode == NULL)
  207. {
  208. switch (event)
  209. {
  210. case NCLBK_CONTEXTMENU:
  211. // Process further.
  212. break;
  213. case NCLBK_GETHELPDOC:
  214. return OnGetHelpDoc((HELPDOCINFO*)arg, (LPOLESTR*)param);
  215. case NCLBK_UPDATEHELPDOC:
  216. return OnUpdateHelpDoc((HELPDOCINFO*)arg, (HELPDOCINFO*)param);
  217. case NCLBK_DELETEHELPDOC:
  218. return OnDeleteHelpDoc((HELPDOCINFO*)arg);
  219. // When the view is closed and NCLBK_SELECT is sent with HNODE NULL (as
  220. // there is no selected node) handle this case.
  221. case NCLBK_SELECT:
  222. return S_OK;
  223. default:
  224. return E_INVALIDARG;
  225. }
  226. }
  227. // convert to real type
  228. CNode* pNode = CNode::FromHandle(hNode);
  229. if (m_pNodeUnderInit && pNode && (m_pNodeUnderInit == pNode))
  230. return E_FAIL;
  231. // See if snapin-cache is being modified.
  232. if (theApp.ProcessingSnapinChanges() == TRUE)
  233. {
  234. // If it is selection/de-selection of node then do not return error
  235. // after the modifications are done (for snapin-cache) the node will
  236. // be selected.
  237. if ( (event == NCLBK_SELECT) ||
  238. (event == NCLBK_MULTI_SELECT) )
  239. return S_OK;
  240. else
  241. return E_FAIL;
  242. }
  243. switch (event)
  244. {
  245. case NCLBK_ACTIVATE:
  246. hr = OnActvate(pNode, arg);
  247. break;
  248. case NCLBK_CACHEHINT:
  249. pNode->OnCacheHint(arg, param);
  250. break;
  251. case NCLBK_CLICK:
  252. ASSERT(0);
  253. break;
  254. case NCLBK_CONTEXTMENU:
  255. hr = OnContextMenu(pNode, arg, param);
  256. break;
  257. case NCLBK_DBLCLICK:
  258. hr = OnDblClk(pNode, arg);
  259. break;
  260. case NCLBK_CUT:
  261. case NCLBK_COPY:
  262. OnCutCopy(pNode, static_cast<BOOL>(arg), param, (event == NCLBK_CUT));
  263. break;
  264. case NCLBK_DELETE:
  265. {
  266. hr = OnDelete(pNode, arg, param);
  267. // 5. Purge the snapin cache
  268. CSnapInsCache* pSnapInCache = theApp.GetSnapInsCache();
  269. ASSERT(pSnapInCache != NULL);
  270. if (pSnapInCache != NULL)
  271. pSnapInCache->Purge();
  272. }
  273. break;
  274. case NCLBK_EXPAND:
  275. hr = OnExpand(pNode, arg);
  276. break;
  277. case NCLBK_EXPANDED:
  278. hr = OnExpanded(pNode);
  279. break;
  280. case NCLBK_GETEXPANDEDVISUALLY:
  281. hr = (pNode->WasExpandedVisually() == true) ? S_OK : S_FALSE;
  282. break;
  283. case NCLBK_SETEXPANDEDVISUALLY:
  284. pNode->SetExpandedVisually(static_cast<bool>(arg));
  285. break;
  286. case NCLBK_PROPERTIES:
  287. hr = OnProperties(pNode, static_cast<BOOL>(arg), param);
  288. break;
  289. case NCLBK_REFRESH:
  290. hr = OnRefresh(pNode, static_cast<BOOL>(arg), param);
  291. break;
  292. case NCLBK_NEW_TASKPAD_FROM_HERE:
  293. hr = OnNewTaskpadFromHere(pNode);
  294. break;
  295. case NCLBK_EDIT_TASKPAD:
  296. hr = OnEditTaskpad(pNode);
  297. break;
  298. case NCLBK_DELETE_TASKPAD:
  299. hr = OnDeleteTaskpad(pNode);
  300. break;
  301. case NCLBK_PRINT:
  302. hr = OnPrint(pNode, static_cast<BOOL>(arg), param);
  303. break;
  304. case NCLBK_NEW_NODE_UPDATE:
  305. hr = OnNewNodeUpdate(pNode, arg);
  306. break;
  307. case NCLBK_RENAME:
  308. hr = OnRename(pNode, reinterpret_cast<SELECTIONINFO*>(arg),
  309. reinterpret_cast<LPOLESTR>(param));
  310. break;
  311. case NCLBK_MULTI_SELECT:
  312. OnMultiSelect(pNode, static_cast<BOOL>(arg));
  313. break;
  314. case NCLBK_SELECT:
  315. OnSelect(pNode, static_cast<BOOL>(arg),
  316. reinterpret_cast<SELECTIONINFO*>(param));
  317. break;
  318. case NCLBK_FINDITEM:
  319. OnFindResultItem(pNode, reinterpret_cast<RESULTFINDINFO*>(arg),
  320. reinterpret_cast<LRESULT*>(param));
  321. break;
  322. case NCLBK_COLUMN_CLICKED:
  323. hr = OnColumnClicked(pNode, param);
  324. break;
  325. case NCLBK_CONTEXTHELP:
  326. hr = OnContextHelp(pNode, static_cast<BOOL>(arg), param);
  327. break;
  328. case NCLBK_SNAPINHELP:
  329. hr = OnSnapInHelp(pNode, static_cast<BOOL>(arg), param);
  330. break;
  331. case NCLBK_FILTER_CHANGE:
  332. hr = OnFilterChange(pNode, arg, param);
  333. break;
  334. case NCLBK_FILTERBTN_CLICK:
  335. hr = OnFilterBtnClick(pNode, arg, reinterpret_cast<LPRECT>(param));
  336. break;
  337. case NCLBK_TASKNOTIFY:
  338. pNode->OnTaskNotify(arg, param);
  339. break;
  340. case NCLBK_GETPRIMARYTASK:
  341. hr = OnGetPrimaryTask (pNode, param);
  342. break;
  343. case NCLBK_MINIMIZED:
  344. hr = OnMinimize (pNode, arg);
  345. break;
  346. case NCLBK_LISTPAD:
  347. hr = pNode->OnListPad(arg, param);
  348. break;
  349. case NCLBK_WEBCONTEXTMENU:
  350. pNode->OnWebContextMenu();
  351. break;
  352. default:
  353. ASSERT(FALSE);
  354. break;
  355. }
  356. return hr;
  357. MMC_CATCH
  358. }
  359. STDMETHODIMP CNodeCallback::GetMTNode(HNODE hNode, HMTNODE* phMTNode)
  360. {
  361. IF_NULL_RETURN_INVALIDARG2(hNode, phMTNode);
  362. MMC_TRY
  363. // convert to real type
  364. CNode* pNode = CNode::FromHandle(hNode);
  365. *phMTNode = CMTNode::ToHandle(pNode->GetMTNode());
  366. return S_OK;
  367. MMC_CATCH
  368. }
  369. STDMETHODIMP CNodeCallback::SetResultItem(HNODE hNode, HRESULTITEM hri)
  370. {
  371. IF_NULL_RETURN_INVALIDARG(hNode);
  372. MMC_TRY
  373. // convert to real type
  374. CNode* pNode = CNode::FromHandle(hNode);
  375. pNode->SetResultItem(hri);
  376. return S_OK;
  377. MMC_CATCH
  378. }
  379. STDMETHODIMP CNodeCallback::GetResultItem(HNODE hNode, HRESULTITEM* phri)
  380. {
  381. IF_NULL_RETURN_INVALIDARG(hNode);
  382. MMC_TRY
  383. // convert to real type
  384. CNode* pNode = CNode::FromHandle(hNode);
  385. *phri = pNode->GetResultItem();
  386. return S_OK;
  387. MMC_CATCH
  388. }
  389. STDMETHODIMP CNodeCallback::GetMTNodeID(HNODE hNode, MTNODEID* pnID)
  390. {
  391. IF_NULL_RETURN_INVALIDARG(pnID);
  392. MMC_TRY
  393. // convert to real type
  394. CNode* pNode = CNode::FromHandle(hNode);
  395. *pnID = pNode->GetMTNode()->GetID();
  396. return S_OK;
  397. MMC_CATCH
  398. }
  399. /*+-------------------------------------------------------------------------*
  400. *
  401. * CNodeCallback::IsTargetNodeOf
  402. *
  403. * PURPOSE: Is one node a target of another
  404. *
  405. * PARAMETERS:
  406. * HNODE hNode : The node that contains the target
  407. * HNODE hTestNode : The alleged target
  408. *
  409. * RETURNS:
  410. * STDMETHODIMP
  411. * S_OK - yes
  412. * S_FALSE - uses a different target node
  413. * E_FAIL - doesn't use a target node
  414. *
  415. *+-------------------------------------------------------------------------*/
  416. STDMETHODIMP CNodeCallback::IsTargetNodeOf(HNODE hNode, HNODE hTestNode)
  417. {
  418. MMC_TRY
  419. ASSERT(hNode && hTestNode);
  420. CNode* pNode = CNode::FromHandle(hNode);
  421. CNode* pTestNode = CNode::FromHandle(hTestNode);
  422. ASSERT(pNode);
  423. return pNode->IsTargetNode(pTestNode);
  424. MMC_CATCH
  425. }
  426. STDMETHODIMP CNodeCallback::GetPath(HNODE hNode, HNODE hRootNode,
  427. LPBYTE pbm)
  428. {
  429. DECLARE_SC(sc, TEXT("CNodeCallback::GetPath"));
  430. sc = ScCheckPointers((PVOID)hNode, (PVOID)hRootNode, pbm);
  431. if(sc)
  432. return sc.ToHr();
  433. MMC_TRY
  434. // convert to real type
  435. CNode* pNode = CNode::FromHandle(hNode);
  436. CNode* pRootNode = CNode::FromHandle(hRootNode);
  437. CBookmark* pbmOut = reinterpret_cast<CBookmark *>(pbm);
  438. CBookmarkEx bm;
  439. sc = bm.ScInitialize(pNode->GetMTNode(), pRootNode->GetMTNode(), true).ToHr();
  440. if(sc)
  441. return sc.ToHr();
  442. // set the out parameter.
  443. *pbmOut = bm;
  444. return sc.ToHr();
  445. MMC_CATCH
  446. }
  447. STDMETHODIMP CNodeCallback::GetStaticParentID(HNODE hNode, MTNODEID* pnID)
  448. {
  449. IF_NULL_RETURN_INVALIDARG2(hNode, pnID);
  450. MMC_TRY
  451. // convert to real type
  452. CNode* pNode = CNode::FromHandle(hNode);
  453. CMTNode* pMTNode = pNode->GetMTNode();
  454. ASSERT(pMTNode != NULL);
  455. while (pMTNode != NULL && pMTNode->IsStaticNode() == FALSE)
  456. {
  457. pMTNode = pMTNode->Parent();
  458. }
  459. ASSERT(pMTNode != NULL);
  460. if (pMTNode != NULL)
  461. {
  462. *pnID = pMTNode->GetID();
  463. return S_OK;
  464. }
  465. return E_UNEXPECTED;
  466. MMC_CATCH
  467. }
  468. // The path for the node is stored in pphMTNode. The path is an array of
  469. // HMTNODE's starting from the console root, followed by its child node and
  470. // continuing in this fashion till the HMTNODE of the root node.
  471. STDMETHODIMP CNodeCallback::GetMTNodePath(HNODE hNode, HMTNODE** pphMTNode,
  472. long* plLength)
  473. {
  474. IF_NULL_RETURN_INVALIDARG3(hNode, pphMTNode, plLength);
  475. MMC_TRY
  476. // convert to real type
  477. CNode* pNode = CNode::FromHandle(hNode);
  478. CMTNode* pMTNode = pNode->GetMTNode();
  479. pMTNode = pMTNode->Parent(); // skip this node
  480. for (*plLength = 0; pMTNode != NULL; pMTNode = pMTNode->Parent())
  481. ++(*plLength);
  482. if (*plLength != 0)
  483. {
  484. HMTNODE* phMTNode = (HMTNODE*)CoTaskMemAlloc(sizeof(HMTNODE) *
  485. (*plLength));
  486. if (phMTNode == NULL)
  487. {
  488. CHECK_HRESULT(E_OUTOFMEMORY);
  489. return E_OUTOFMEMORY;
  490. }
  491. *pphMTNode = phMTNode;
  492. pMTNode = pNode->GetMTNode();
  493. pMTNode = pMTNode->Parent(); // skip this node
  494. phMTNode = phMTNode + (*plLength - 1);
  495. for (; pMTNode != NULL; pMTNode = pMTNode->Parent(), --phMTNode)
  496. *phMTNode = CMTNode::ToHandle(pMTNode);
  497. ASSERT(++phMTNode == *pphMTNode);
  498. }
  499. else
  500. {
  501. pphMTNode = NULL;
  502. }
  503. return S_OK;
  504. MMC_CATCH
  505. }
  506. /*+-------------------------------------------------------------------------*
  507. *
  508. * CNodeCallback::GetNodeOwnerID
  509. *
  510. * PURPOSE: Get the ID of the snap-in component that owns this node.
  511. * If not a snap-in owned node, TVOWNED_MAGICWORD is returned.
  512. *
  513. * PARAMETERS:
  514. * HNODE hNode : Node to query
  515. * COMPONENTID* : ptr to returned ID
  516. *
  517. * RETURNS:
  518. * STDMETHODIMP
  519. * S_OK - ID returned
  520. * E_INVALIDARG -
  521. * E_FAIL - probably an invalid hNode
  522. *
  523. *+-------------------------------------------------------------------------*/
  524. /*******************************************************************************
  525. * >>>>>>>>>>>>>> READ THIS BEFORE USING GetNodeOwnerID <<<<<<<<<<<<<<<<<<<<<<<
  526. *
  527. * This method differs from the GetOwnerID method exposed by CNode (and CMTNode)
  528. * in that it returns a zero ID for snap-in static nodes, indicating that the
  529. * owner is the snap-in primary component. The CNode method returns
  530. * TVOWNED_MAGICWORD for snap-in static nodes, inidcating MMC ownership. For
  531. * most purposes the zero ID is more appropriate and I think the node method
  532. * should be changed. This requires looking at all uses of the owner ID and
  533. * verifying nothing will break. rswaney 5/5/99
  534. *******************************************************************************/
  535. STDMETHODIMP CNodeCallback::GetNodeOwnerID(HNODE hNode, COMPONENTID* pOwnerID)
  536. {
  537. IF_NULL_RETURN_INVALIDARG2(hNode, pOwnerID);
  538. MMC_TRY
  539. CNode* pNode = CNode::FromHandle(hNode);
  540. if (pNode->IsStaticNode())
  541. *pOwnerID = 0;
  542. else
  543. *pOwnerID = pNode->GetOwnerID();
  544. return S_OK;
  545. MMC_CATCH
  546. }
  547. STDMETHODIMP CNodeCallback::GetNodeCookie(HNODE hNode, MMC_COOKIE* pCookie)
  548. {
  549. IF_NULL_RETURN_INVALIDARG2(hNode, pCookie);
  550. MMC_TRY
  551. // only dynamic nodes have cookies
  552. CNode* pNode = CNode::FromHandle(hNode);
  553. if (!pNode->IsDynamicNode())
  554. return E_FAIL;
  555. *pCookie = pNode->GetUserParam();
  556. return S_OK;
  557. MMC_CATCH
  558. }
  559. /*+-------------------------------------------------------------------------*
  560. *
  561. * CNodeCallback::GetControl
  562. *
  563. * PURPOSE: See if there is a OCX with given CLSID for the given node.
  564. * If so return it.
  565. *
  566. * PARAMETERS:
  567. * HNODE hNode :
  568. * CLSID clsid :
  569. * IUnknown ** ppUnkControl :
  570. *
  571. * RETURNS:
  572. * STDMETHODIMP
  573. *
  574. *+-------------------------------------------------------------------------*/
  575. STDMETHODIMP
  576. CNodeCallback::GetControl(HNODE hNode, CLSID clsid, IUnknown **ppUnkControl)
  577. {
  578. MMC_TRY
  579. DECLARE_SC(sc, TEXT("CNodeCallback::GetControl"));
  580. sc = ScCheckPointers((void *)hNode, ppUnkControl);
  581. if(sc)
  582. return sc.ToHr();
  583. // convert to real type
  584. CNode* pNode = CNode::FromHandle(hNode);
  585. sc = ScCheckPointers(pNode);
  586. if (sc)
  587. return sc.ToHr();
  588. *ppUnkControl = pNode->GetControl(clsid);
  589. if(!*ppUnkControl)
  590. return sc.ToHr();
  591. // addref the interface for the client.
  592. (*ppUnkControl)->AddRef();
  593. return sc.ToHr();
  594. MMC_CATCH
  595. }
  596. /*+-------------------------------------------------------------------------*
  597. *
  598. * CNodeCallback::SetControl
  599. *
  600. * PURPOSE: For the given node & clsid of OCX save the OCX window IUnknown*.
  601. *
  602. * PARAMETERS:
  603. * HNODE hNode :
  604. * CLSID clsid :
  605. * IUnknown* pUnknown :
  606. *
  607. * RETURNS:
  608. * STDMETHODIMP
  609. *
  610. *+-------------------------------------------------------------------------*/
  611. STDMETHODIMP
  612. CNodeCallback::SetControl(HNODE hNode, CLSID clsid, IUnknown* pUnknown)
  613. {
  614. DECLARE_SC(sc, TEXT("CNodeCallback::SetControl"));
  615. sc = ScCheckPointers((void*)hNode, pUnknown);
  616. if (sc)
  617. return sc.ToHr();
  618. // convert to real type
  619. CNode* pNode = CNode::FromHandle(hNode);
  620. sc = ScCheckPointers(pNode);
  621. if (sc)
  622. return sc.ToHr();
  623. pNode->SetControl(clsid, pUnknown);
  624. return sc.ToHr();
  625. }
  626. //+-------------------------------------------------------------------
  627. //
  628. // Member: CNodeCallback::GetControl
  629. //
  630. // Synopsis: For given node & IUnknown* of OCX get the OCX wrapper if one exists.
  631. //
  632. // Arguments: [hNode]
  633. // [pUnkOCX]
  634. // [ppUnkControl]
  635. //
  636. // Returns: HRESULT
  637. //
  638. //--------------------------------------------------------------------
  639. STDMETHODIMP CNodeCallback::GetControl (HNODE hNode, LPUNKNOWN pUnkOCX, IUnknown **ppUnkControl)
  640. {
  641. DECLARE_SC(sc, _T("CNodeCallback::GetControl"));
  642. sc = ScCheckPointers((void*)hNode, pUnkOCX, ppUnkControl);
  643. if (sc)
  644. return sc.ToHr();
  645. CNode *pNode = CNode::FromHandle(hNode);
  646. sc = ScCheckPointers(pNode);
  647. if (sc)
  648. return sc.ToHr();
  649. *ppUnkControl = pNode->GetControl(pUnkOCX);
  650. if(!*ppUnkControl)
  651. return sc.ToHr();
  652. // addref the interface for the client.
  653. (*ppUnkControl)->AddRef();
  654. return (sc.ToHr());
  655. }
  656. //+-------------------------------------------------------------------
  657. //
  658. // Member: SetControl
  659. //
  660. // Synopsis: For given node & IUnknown of OCX save the IUnknown of
  661. // OCX wrapper.
  662. //
  663. // Arguments: [hNode]
  664. // [pUnkOCX]
  665. // [pUnknown]
  666. //
  667. // Returns: HRESULT
  668. //
  669. //--------------------------------------------------------------------
  670. STDMETHODIMP CNodeCallback::SetControl (HNODE hNode, LPUNKNOWN pUnkOCX, IUnknown* pUnknown)
  671. {
  672. DECLARE_SC(sc, _T("SetControl"));
  673. sc = ScCheckPointers((void*) hNode, pUnkOCX, pUnknown);
  674. if (sc)
  675. return sc.ToHr();
  676. CNode *pNode = CNode::FromHandle(hNode);
  677. sc = ScCheckPointers(pNode);
  678. if (sc)
  679. return sc.ToHr();
  680. pNode->SetControl(pUnkOCX, pUnknown);
  681. return (sc.ToHr());
  682. }
  683. STDMETHODIMP
  684. CNodeCallback::InitOCX(HNODE hNode, IUnknown* pUnknown)
  685. {
  686. DECLARE_SC(sc, TEXT("CNodeCallback::InitOCX"));
  687. sc = ScCheckPointers((void *)hNode);
  688. if(sc)
  689. return sc.ToHr();
  690. CNode* pNode = CNode::FromHandle(hNode);
  691. sc = pNode->OnInitOCX(pUnknown);
  692. return sc.ToHr();
  693. }
  694. /////////////////////////////////////////////////////////////////////////////
  695. // Notify handlers
  696. HRESULT CNodeCallback::OnActvate(CNode* pNode, LONG_PTR arg)
  697. {
  698. DECLARE_SC (sc, _T("CNodeCallback::OnActvate"));
  699. sc = ScCheckPointers (pNode);
  700. if (sc)
  701. return (sc.ToHr());
  702. return pNode->OnActvate(arg);
  703. }
  704. HRESULT CNodeCallback::OnMinimize(CNode* pNode, LONG_PTR arg)
  705. {
  706. DECLARE_SC (sc, _T("CNodeCallback::OnMinimize"));
  707. sc = ScCheckPointers (pNode);
  708. if (sc)
  709. return (sc.ToHr());
  710. return pNode->OnMinimize(arg);
  711. }
  712. HRESULT CNodeCallback::OnDelete(CNode* pNode, BOOL bScopePaneSelected, LPARAM lvData)
  713. {
  714. DECLARE_SC(sc, TEXT("CNodeCallback::OnDelete"));
  715. BOOL bScopeItemSelected;
  716. CNode *pSelectedNode = NULL;
  717. MMC_COOKIE cookie = -1;
  718. sc = CNodeCallback::ScExtractLVData(pNode, bScopePaneSelected, lvData,
  719. &pSelectedNode, bScopeItemSelected, cookie);
  720. if (sc)
  721. return sc.ToHr();
  722. sc = ScCheckPointers(pSelectedNode, E_UNEXPECTED);
  723. if (sc)
  724. return sc.ToHr();
  725. // If result-pane cookie should be valid.
  726. ASSERT( (bScopeItemSelected) || cookie != LVDATA_ERROR);
  727. if ( (FALSE == bScopeItemSelected) && (cookie == LVDATA_ERROR) )
  728. return E_FAIL;
  729. HRESULT hr = S_OK;
  730. if (!bScopeItemSelected)
  731. {
  732. CMultiSelection* pMultiSel = pSelectedNode->GetViewData()->GetMultiSelection();
  733. if (pMultiSel != NULL)
  734. {
  735. ASSERT(lvData == LVDATA_MULTISELECT);
  736. pMultiSel->ScVerbInvoked(MMC_VERB_DELETE);
  737. return S_OK;
  738. }
  739. else
  740. {
  741. ASSERT(lvData != LVDATA_MULTISELECT);
  742. CComponent* pCC = pSelectedNode->GetPrimaryComponent();
  743. ASSERT(pCC != NULL);
  744. if (pCC != NULL)
  745. {
  746. if (IS_SPECIAL_LVDATA(lvData))
  747. {
  748. LPDATAOBJECT pdobj = (lvData == LVDATA_CUSTOMOCX) ?
  749. DOBJ_CUSTOMOCX : DOBJ_CUSTOMWEB;
  750. hr = pCC->Notify(pdobj, MMCN_DELETE, 0, 0);
  751. CHECK_HRESULT(hr);
  752. }
  753. else
  754. {
  755. IDataObjectPtr spdtobj;
  756. hr = pCC->QueryDataObject(cookie, CCT_RESULT, &spdtobj);
  757. ASSERT( NULL != pCC->GetIComponent() );
  758. if (SUCCEEDED(hr))
  759. {
  760. hr = pCC->Notify(spdtobj, MMCN_DELETE, 0, 0);
  761. CHECK_HRESULT(hr);
  762. }
  763. }
  764. }
  765. }
  766. }
  767. else
  768. {
  769. CMTNode* pMTNode = pSelectedNode->GetMTNode();
  770. if (pMTNode->Parent() == NULL)
  771. return S_FALSE;
  772. if (pSelectedNode->IsStaticNode() == TRUE) // All static nodes can be deleted
  773. {
  774. ASSERT(m_pCScopeTree != NULL);
  775. if (pMTNode->DoDelete(pSelectedNode->GetViewData()->GetMainFrame()) == false)
  776. return S_FALSE;
  777. // Delete storage
  778. hr = pMTNode->DestroyElements();
  779. ASSERT(SUCCEEDED(hr));
  780. // Delete the node.
  781. m_pCScopeTree->DeleteNode(pMTNode);
  782. }
  783. else // Tell the snapin that put up the dynamic node to delete.
  784. {
  785. CComponentData* pCD = pMTNode->GetPrimaryComponentData();
  786. ASSERT(pCD != NULL);
  787. IDataObjectPtr spDataObject;
  788. hr = pCD->QueryDataObject(pMTNode->GetUserParam(), CCT_SCOPE, &spDataObject);
  789. CHECK_HRESULT(hr);
  790. ASSERT( NULL != pCD->GetIComponentData() );
  791. if (hr == S_OK)
  792. {
  793. hr = pCD->Notify(spDataObject, MMCN_DELETE, 0, 0);
  794. CHECK_HRESULT(hr);
  795. }
  796. }
  797. }
  798. return hr;
  799. }
  800. HRESULT CNodeCallback::OnFindResultItem(CNode* pNode, RESULTFINDINFO* pFindInfo, LRESULT* pResult)
  801. {
  802. IF_NULL_RETURN_INVALIDARG3(pNode, pFindInfo, pResult);
  803. // init result to -1 (item not found)
  804. *pResult = -1;
  805. CComponent* pCC = pNode->GetPrimaryComponent();
  806. ASSERT(pCC != NULL);
  807. if (pCC == NULL)
  808. return E_FAIL;
  809. IResultOwnerDataPtr spIResultOwnerData = pCC->GetIComponent();
  810. if (spIResultOwnerData == NULL)
  811. return S_FALSE;
  812. return spIResultOwnerData->FindItem(pFindInfo, reinterpret_cast<int*>(pResult));
  813. }
  814. HRESULT CNodeCallback::OnRename(CNode* pNode, SELECTIONINFO *pSelInfo,
  815. LPOLESTR pszNewName)
  816. {
  817. HRESULT hr = S_OK;
  818. if (pSelInfo->m_bScope)
  819. {
  820. CMTNode* pMTNode = pNode->GetMTNode();
  821. hr = pMTNode->OnRename(1, pszNewName);
  822. }
  823. else
  824. {
  825. CComponent* pCC = pNode->GetPrimaryComponent();
  826. ASSERT(pCC != NULL);
  827. if (pCC != NULL)
  828. {
  829. IDataObjectPtr spDataObject;
  830. hr = pCC->QueryDataObject(pSelInfo->m_lCookie, CCT_RESULT,
  831. &spDataObject);
  832. if (FAILED(hr))
  833. return hr;
  834. hr = pCC->Notify(spDataObject, MMCN_RENAME, 1,
  835. reinterpret_cast<LPARAM>(pszNewName));
  836. CHECK_HRESULT(hr);
  837. return hr;
  838. }
  839. }
  840. if (hr == S_OK)
  841. {
  842. if (pNode->IsStaticNode() == TRUE) {
  843. USES_CONVERSION;
  844. pNode->SetDisplayName( W2T(pszNewName) );
  845. }
  846. // Now inform the views to modify as needed.
  847. SViewUpdateInfo vui;
  848. // Snapin nodes result pane will be handled by the snapins
  849. vui.flag = VUI_REFRESH_NODE;
  850. pNode->GetMTNode()->CreatePathList(vui.path);
  851. m_pCScopeTree->UpdateAllViews(VIEW_UPDATE_MODIFY,
  852. reinterpret_cast<LPARAM>(&vui));
  853. }
  854. return hr;
  855. }
  856. HRESULT CNodeCallback::OnNewNodeUpdate(CNode* pNode, LONG_PTR lFlags)
  857. {
  858. pNode->GetMTNode()->SetPropertyPageIsDisplayed(FALSE);
  859. // Inform the views to modify.
  860. SViewUpdateInfo vui;
  861. vui.flag = lFlags;
  862. pNode->GetMTNode()->CreatePathList(vui.path);
  863. m_pCScopeTree->UpdateAllViews(VIEW_UPDATE_MODIFY,
  864. reinterpret_cast<LPARAM>(&vui));
  865. return S_OK;
  866. }
  867. HRESULT CNodeCallback::OnExpand(CNode* pNode, BOOL fExpand)
  868. {
  869. HRESULT hr = S_OK;
  870. ASSERT(pNode != 0);
  871. // initialize the node if needed.
  872. if ( fExpand && (pNode->WasExpandedAtLeastOnce() == FALSE) &&
  873. (pNode->IsInitialized() == FALSE))
  874. {
  875. hr = _InitializeNode(pNode);
  876. if ((FAILED(hr)))
  877. {
  878. return hr;
  879. }
  880. }
  881. return pNode->OnExpand(fExpand);
  882. }
  883. HRESULT CNodeCallback::OnExpanded(CNode* pNode)
  884. {
  885. ASSERT(pNode != 0);
  886. pNode->SetExpandedAtLeastOnce();
  887. return S_OK;
  888. }
  889. HRESULT CNodeCallback::OnScopeSelect(CNode* pNode, BOOL bSelect,
  890. SELECTIONINFO* pSelInfo)
  891. {
  892. DECLARE_SC(sc, TEXT("CNodeCallback::OnScopeSelect"));
  893. sc = ScCheckPointers(pNode, pSelInfo);
  894. if (sc)
  895. return sc.ToHr();
  896. // clear out the the status bar text if we're deselecting a node
  897. if (! bSelect)
  898. {
  899. CViewData *pViewData = pNode->GetViewData();
  900. sc = ScCheckPointers(pViewData, E_UNEXPECTED);
  901. if (sc)
  902. return sc.ToHr();
  903. CConsoleStatusBar* pStatusBar = pViewData->GetStatusBar();
  904. if (pStatusBar != NULL)
  905. pStatusBar->ScSetStatusText (NULL);
  906. }
  907. if (pNode->IsInitialized() == FALSE)
  908. {
  909. sc = _InitializeNode(pNode);
  910. if (sc)
  911. return sc.ToHr();
  912. }
  913. sc = pNode->OnScopeSelect(bSelect, pSelInfo);
  914. if(sc)
  915. return sc.ToHr();
  916. #ifdef DBG
  917. if (bSelect)
  918. Dbg(DEB_USER11, _T("Selecting %s node."), pNode->GetDisplayName());
  919. #endif
  920. return sc.ToHr();
  921. }
  922. STDMETHODIMP CNodeCallback::SetTaskPadList(HNODE hNode, LPUNKNOWN pUnknown)
  923. {
  924. IFramePrivate* pFramePrivate = GetIFramePrivateFromNode (hNode);
  925. if (pFramePrivate == NULL)
  926. return E_UNEXPECTED;
  927. return (pFramePrivate->SetTaskPadList(pUnknown));
  928. }
  929. IFramePrivate* GetIFramePrivateFromNode (CNode* pNode)
  930. {
  931. if (pNode == NULL)
  932. return (NULL);
  933. return pNode->GetIFramePrivate();
  934. }
  935. void CNodeCallback::OnMultiSelect(CNode* pNode, BOOL bSelect)
  936. {
  937. Trace(tagNodeCallback, _T("----------------->>>>>>> MULTI_SELECT<%d>\n"), bSelect);
  938. SC sc;
  939. CViewData* pViewData = NULL;
  940. if (NULL == pNode)
  941. {
  942. sc = E_UNEXPECTED;
  943. goto Error;
  944. }
  945. pViewData = pNode->GetViewData();
  946. if (NULL == pViewData)
  947. {
  948. sc = E_UNEXPECTED;
  949. goto Error;
  950. }
  951. if (pViewData->IsVirtualList())
  952. {
  953. if (bSelect == TRUE)
  954. DeleteMultiSelData(pNode);
  955. }
  956. _OnMultiSelect(pNode, bSelect);
  957. if (bSelect == FALSE)
  958. DeleteMultiSelData(pNode);
  959. // Update the std-verb tool-buttons.
  960. sc = pViewData->ScUpdateStdbarVerbs();
  961. if (sc)
  962. goto Error;
  963. pViewData->UpdateToolbars(pViewData->GetToolbarsDisplayed());
  964. Cleanup:
  965. return;
  966. Error:
  967. TraceError (_T("CNodeCallback::OnMultiSelect"), sc);
  968. goto Cleanup;
  969. }
  970. void CNodeCallback::_OnMultiSelect(CNode* pNode, BOOL bSelect)
  971. {
  972. DECLARE_SC(sc, TEXT("CNodeCallback::_OnMultiSelect"));
  973. sc = ScCheckPointers(pNode);
  974. if (sc)
  975. return;
  976. CViewData *pViewData = pNode->GetViewData();
  977. sc = ScCheckPointers(pViewData, E_UNEXPECTED);
  978. if (sc)
  979. return;
  980. CMultiSelection* pMultiSelection = pNode->GetViewData()->GetMultiSelection();
  981. if (pMultiSelection)
  982. {
  983. if (pMultiSelection->IsInUse())
  984. return;
  985. else
  986. {
  987. /*
  988. * If result pane items are selected by dragging a mouse (that forms Marquee)
  989. * or if snapin sets items to selected state then the items are selected one
  990. * by one. That is multi-select for 1 item, multi-select for 2 items and so-on.
  991. * There is no deselect inbetween, so if we already have a multiselection object
  992. * for 2 items then when we get multi-select for 3 items we need to destroy multiselection
  993. * object for 2 items. This is done below.
  994. *
  995. */
  996. DeleteMultiSelData(pNode);
  997. pMultiSelection = NULL;
  998. }
  999. }
  1000. // set standard bars
  1001. CVerbSet* pVerbSet = dynamic_cast<CVerbSet*>(pViewData->GetVerbSet());
  1002. sc = ScCheckPointers(pVerbSet, E_UNEXPECTED);
  1003. if (sc)
  1004. return;
  1005. sc = pVerbSet->ScInitializeForMultiSelection(pNode, bSelect);
  1006. if (sc)
  1007. return;
  1008. if (pMultiSelection == NULL)
  1009. {
  1010. if (bSelect == FALSE)
  1011. return;
  1012. CComponentPtrArray* prgComps = new CComponentPtrArray;
  1013. if (pNode->IsInitialized() == FALSE)
  1014. {
  1015. sc = _InitializeNode(pNode);
  1016. if (sc)
  1017. return;
  1018. }
  1019. // Create CMultiSelection
  1020. pMultiSelection = new CMultiSelection(pNode);
  1021. sc = ScCheckPointers(pMultiSelection, E_OUTOFMEMORY);
  1022. if (sc)
  1023. return;
  1024. sc = pMultiSelection->Init();
  1025. if (sc)
  1026. return;
  1027. pViewData->SetMultiSelection(pMultiSelection);
  1028. }
  1029. pMultiSelection->SetScopeTree(m_pCScopeTree);
  1030. IDataObjectPtr spdobj;
  1031. sc = pMultiSelection->GetMultiSelDataObject(&spdobj);
  1032. if (sc)
  1033. return;
  1034. sc = ScCheckPointers(spdobj, E_UNEXPECTED);
  1035. if (sc)
  1036. return;
  1037. // give the scope item a chance to do any initialization that it needs.
  1038. // For instance, the console taskpad uses this opportunity to gather information
  1039. // about the selected item's context menu.
  1040. SELECTIONINFO SelInfo;
  1041. SelInfo.m_lCookie = LVDATA_MULTISELECT;
  1042. // Inform control bars of selection change.
  1043. CControlbarsCache* pCtrlbarsCache =
  1044. dynamic_cast<CControlbarsCache*>(pNode->GetControlbarsCache());
  1045. sc = ScCheckPointers(pCtrlbarsCache, E_UNEXPECTED);
  1046. if (sc)
  1047. return;
  1048. pCtrlbarsCache->OnMultiSelect(pNode, pMultiSelection, spdobj, bSelect);
  1049. sc = pVerbSet->ScComputeVerbStates();
  1050. if (sc)
  1051. return;
  1052. }
  1053. void CNodeCallback::OnSelect(CNode* pNode, BOOL bSelect, SELECTIONINFO* pSelInfo)
  1054. {
  1055. Trace(tagNodeCallback, _T("----------------->>>>>>> SELECT<%d>\n"), bSelect);
  1056. SC sc;
  1057. CViewData* pViewData = NULL;
  1058. if (pSelInfo == NULL)
  1059. {
  1060. sc = E_UNEXPECTED;
  1061. goto Error;
  1062. }
  1063. Trace(tagNodeCallback, _T("====>> NCLBK_SELECT<%d, %d, %c>\n"), pSelInfo->m_bScope, bSelect, pSelInfo->m_bDueToFocusChange ? _T('F') : _T('S'));
  1064. if (NULL == pNode)
  1065. {
  1066. sc = E_UNEXPECTED;
  1067. goto Error;
  1068. }
  1069. pViewData = pNode->GetViewData();
  1070. if (NULL == pViewData)
  1071. {
  1072. sc = E_UNEXPECTED;
  1073. goto Error;
  1074. }
  1075. DeleteMultiSelData(pNode);
  1076. if (!bSelect)
  1077. {
  1078. // Reset controlbars
  1079. pNode->ResetControlbars(bSelect, pSelInfo);
  1080. // Reset standard verbs
  1081. sc = pNode->ScInitializeVerbs(bSelect, pSelInfo);
  1082. if (sc)
  1083. sc.TraceAndClear();
  1084. }
  1085. // For scoe sel change reset result pane.
  1086. if (pSelInfo->m_bScope == TRUE && pSelInfo->m_bDueToFocusChange == FALSE)
  1087. {
  1088. sc = OnScopeSelect(pNode, bSelect, pSelInfo);
  1089. if (sc)
  1090. goto Error;
  1091. }
  1092. if (bSelect)
  1093. {
  1094. // Reset controlbars
  1095. pNode->ResetControlbars(bSelect, pSelInfo);
  1096. // Reset standard verbs
  1097. sc = pNode->ScInitializeVerbs(bSelect, pSelInfo);
  1098. if (sc)
  1099. sc.TraceAndClear();
  1100. }
  1101. // Update the std-verb tool-buttons.
  1102. sc = pViewData->ScUpdateStdbarVerbs();
  1103. // Dummy block
  1104. {
  1105. // Update the paste button
  1106. LPARAM lvData = pSelInfo->m_lCookie;
  1107. BOOL bScopePaneSelected = pSelInfo->m_bScope || pSelInfo->m_bBackground;
  1108. sc = UpdatePasteButton(CNode::ToHandle(pNode), bScopePaneSelected, lvData);
  1109. if (sc)
  1110. goto Error;
  1111. // Update toolbars.
  1112. pViewData->UpdateToolbars(pViewData->GetToolbarsDisplayed());
  1113. }
  1114. Cleanup:
  1115. return;
  1116. Error:
  1117. TraceError (_T("CNodeCallback::OnSelect"), sc);
  1118. goto Cleanup;
  1119. }
  1120. HRESULT CNodeCallback::OnDblClk(CNode* pNode, LONG_PTR lvData)
  1121. {
  1122. DECLARE_SC(sc, TEXT("CNodeCallback::OnDblClk"));
  1123. sc = ScCheckPointers(pNode);
  1124. if (sc)
  1125. return sc.ToHr();
  1126. BOOL bScopePaneSelected = FALSE;
  1127. BOOL bScopeItemSelected;
  1128. CNode *pSelectedNode = NULL;
  1129. MMC_COOKIE cookie = -1;
  1130. sc = CNodeCallback::ScExtractLVData(pNode, bScopePaneSelected, lvData,
  1131. &pSelectedNode, bScopeItemSelected, cookie);
  1132. if (sc)
  1133. return sc.ToHr();
  1134. sc = ScCheckPointers(pSelectedNode, E_UNEXPECTED);
  1135. if (sc)
  1136. return sc.ToHr();
  1137. // If result-pane cookie should be valid.
  1138. if ( (FALSE == bScopeItemSelected) && (cookie == LVDATA_ERROR) )
  1139. return (sc = E_FAIL).ToHr();
  1140. // Ignore double-click on LV background.
  1141. if (lvData == LVDATA_BACKGROUND)
  1142. return sc.ToHr();
  1143. CComponent* pCC = pSelectedNode->GetPrimaryComponent();
  1144. sc = ScCheckPointers(pCC, E_UNEXPECTED);
  1145. if (sc)
  1146. return sc.ToHr();
  1147. // Get the dataobject of the item which was double-clicked.
  1148. IDataObjectPtr spdtobj;
  1149. if (!bScopeItemSelected) // leaf item
  1150. {
  1151. sc = pCC->QueryDataObject(cookie, CCT_RESULT, &spdtobj);
  1152. if (sc)
  1153. {
  1154. sc.TraceAndClear();
  1155. return sc.ToHr();
  1156. }
  1157. }
  1158. else
  1159. {
  1160. sc = pSelectedNode->QueryDataObject(CCT_SCOPE, &spdtobj);
  1161. if (sc)
  1162. {
  1163. sc.TraceAndClear();
  1164. return sc.ToHr();
  1165. }
  1166. }
  1167. sc = pCC->Notify(spdtobj, MMCN_DBLCLICK, 0, 0);
  1168. if (sc)
  1169. sc.TraceAndClear();
  1170. // Snapin has asked us to do default verb action, so findout default verb.
  1171. if (sc == S_FALSE)
  1172. {
  1173. CViewData *pViewData = pSelectedNode->GetViewData();
  1174. sc = ScCheckPointers(pViewData, E_UNEXPECTED);
  1175. if (sc)
  1176. return sc.ToHr();
  1177. CVerbSet* pVerbSet = dynamic_cast<CVerbSet*>(pViewData->GetVerbSet());
  1178. sc = ScCheckPointers(pVerbSet, E_UNEXPECTED);
  1179. if (sc)
  1180. return sc.ToHr();
  1181. MMC_CONSOLE_VERB defaultVerb = MMC_VERB_NONE;
  1182. pVerbSet->GetDefaultVerb(&defaultVerb);
  1183. if (defaultVerb == MMC_VERB_OPEN)
  1184. {
  1185. return S_FALSE;
  1186. }
  1187. else if (defaultVerb == MMC_VERB_PROPERTIES)
  1188. {
  1189. OnProperties(pNode, bScopePaneSelected, lvData);
  1190. }
  1191. }
  1192. return S_OK;
  1193. }
  1194. HRESULT CNodeCallback::OnContextMenu(CNode* pNode, LONG_PTR arg, LPARAM param)
  1195. {
  1196. DECLARE_SC(sc, TEXT("CNodeCallback::OnContextMenu"));
  1197. ASSERT(param != NULL);
  1198. CContextMenuInfo& contextInfo = *reinterpret_cast<CContextMenuInfo*>(param);
  1199. BOOL b = static_cast<BOOL>(arg);
  1200. if ((pNode != NULL) && !pNode->IsInitialized())
  1201. {
  1202. sc = pNode->InitComponents();
  1203. if(sc)
  1204. return sc.ToHr();
  1205. }
  1206. // Create a CContextMenu and initialize it.
  1207. CContextMenu * pContextMenu = NULL;
  1208. ContextMenuPtr spContextMenu;
  1209. sc = CContextMenu::ScCreateInstance(&spContextMenu, &pContextMenu);
  1210. if(sc)
  1211. return sc.ToHr();
  1212. sc = ScCheckPointers(pContextMenu, spContextMenu.GetInterfacePtr(), E_UNEXPECTED);
  1213. if(sc)
  1214. return sc.ToHr();
  1215. sc = pContextMenu->ScInitialize(pNode, this, m_pCScopeTree, contextInfo);
  1216. if(sc)
  1217. return sc.ToHr();
  1218. sc = pContextMenu->Display(b);
  1219. return sc.ToHr();
  1220. }
  1221. /*+-------------------------------------------------------------------------*
  1222. *
  1223. * CNodeCallback::CreateContextMenu
  1224. *
  1225. * PURPOSE: Creates a context menu for the specified node.
  1226. *
  1227. * PARAMETERS:
  1228. * PNODE pNode :
  1229. * PPCONTEXTMENU ppContextMenu : [OUT]: The context menu structure.
  1230. *
  1231. * RETURNS:
  1232. * HRESULT
  1233. *
  1234. *+-------------------------------------------------------------------------*/
  1235. HRESULT
  1236. CNodeCallback::CreateContextMenu( PNODE pNode, HNODE hNode, PPCONTEXTMENU ppContextMenu)
  1237. {
  1238. DECLARE_SC(sc, TEXT("CNodeCallback::CreateContextMenu"));
  1239. sc = ScCheckPointers(pNode, ppContextMenu);
  1240. if(sc)
  1241. return sc.ToHr();
  1242. sc = CContextMenu::ScCreateContextMenu(pNode, hNode, ppContextMenu, this, m_pCScopeTree);
  1243. return sc.ToHr();
  1244. }
  1245. /*+-------------------------------------------------------------------------*
  1246. *
  1247. * CNodeCallback::CreateSelectionContextMenu
  1248. *
  1249. * PURPOSE: Creates a context menu for the current selection in the result pane.
  1250. *
  1251. * PARAMETERS:
  1252. * HNODE hNodeScope :
  1253. * CContextMenuInfo * pContextInfo :
  1254. * PPCONTEXTMENU ppContextMenu :
  1255. *
  1256. * RETURNS:
  1257. * HRESULT
  1258. *
  1259. *+-------------------------------------------------------------------------*/
  1260. HRESULT
  1261. CNodeCallback::CreateSelectionContextMenu( HNODE hNodeScope, CContextMenuInfo *pContextInfo, PPCONTEXTMENU ppContextMenu)
  1262. {
  1263. DECLARE_SC(sc, TEXT("CNodeCallback::CreateSelectionContextMenu"));
  1264. sc = CContextMenu::ScCreateSelectionContextMenu(hNodeScope, pContextInfo, ppContextMenu, this, m_pCScopeTree);
  1265. return sc.ToHr();
  1266. }
  1267. /*+-------------------------------------------------------------------------*
  1268. *
  1269. * CNodeCallback::GetProperty
  1270. *
  1271. * PURPOSE: Returns the specified property for the specified list item by calling
  1272. * IDataObject::GetData using a STREAM medium on the node's data
  1273. * object.
  1274. *
  1275. * PARAMETERS:
  1276. * HNODE hNodeScope : The parent scope item
  1277. * BOOL bForScopeItem : TRUE if the list item is a scope item in the list.
  1278. * LPARAM resultItemParam : The LPARAM of the result item
  1279. * BSTR bstrPropertyName : The name of the clipboard format.
  1280. * PBSTR pbstrPropertyValue :
  1281. *
  1282. * RETURNS:
  1283. * HRESULT
  1284. *
  1285. *+-------------------------------------------------------------------------*/
  1286. HRESULT
  1287. CNodeCallback::GetProperty(HNODE hNodeScope, BOOL bForScopeItem, LPARAM resultItemParam, BSTR bstrPropertyName, PBSTR pbstrPropertyValue)
  1288. {
  1289. DECLARE_SC(sc, TEXT("CNodeCallback::GetProperty"));
  1290. // check parameters
  1291. sc = ScCheckPointers(bstrPropertyName);
  1292. if(sc)
  1293. return sc.ToHr();
  1294. // initialize out parameter
  1295. *pbstrPropertyValue = NULL;
  1296. // convert the HNODE to a CNode *
  1297. CNode *pNodeScope = CNode::FromHandle(hNodeScope);
  1298. sc = ScCheckPointers(pNodeScope);
  1299. if(sc)
  1300. return sc.ToHr();
  1301. // create a data object for the specified item
  1302. IDataObjectPtr spDataObject;
  1303. bool bScopeItem;
  1304. sc = pNodeScope->ScGetDataObject(bForScopeItem, resultItemParam, bScopeItem, &spDataObject);
  1305. if(sc)
  1306. return sc.ToHr();
  1307. // try to get the propeorty from the INodeProperties interface
  1308. sc = pNodeScope->ScGetPropertyFromINodeProperties(spDataObject, bForScopeItem, resultItemParam, bstrPropertyName, pbstrPropertyValue);
  1309. if( (!sc.IsError()) && (sc.ToHr() != S_FALSE) ) // got it, exit
  1310. return sc.ToHr();
  1311. // didn't find it, continue
  1312. sc.Clear();
  1313. // get the property from data object
  1314. sc = ScGetProperty(spDataObject, bstrPropertyName, pbstrPropertyValue);
  1315. if(sc)
  1316. return sc.ToHr();
  1317. return sc.ToHr();
  1318. }
  1319. /***************************************************************************\
  1320. *
  1321. * METHOD: CNodeCallback::ScGetProperty
  1322. *
  1323. * PURPOSE: Helper (static) method to access snapin property
  1324. *
  1325. * PARAMETERS:
  1326. * IDataObject *pDataObject - [in] data object
  1327. * BSTR bstrPropertyName - [in] property (clipboard fromat) name
  1328. * PBSTR pbstrPropertyValue - [out] resulting value
  1329. *
  1330. * RETURNS:
  1331. * SC - result code. NOTE: no error is returned if the snapin does not
  1332. * support the specified clipboard format. In this case *pbstrPropertyValue
  1333. * is set to NULL.
  1334. *
  1335. \***************************************************************************/
  1336. SC CNodeCallback::ScGetProperty(IDataObject *pDataObject, BSTR bstrPropertyName, PBSTR pbstrPropertyValue)
  1337. {
  1338. DECLARE_SC(sc, TEXT("ScGetProperty"));
  1339. // check parameters
  1340. sc = ScCheckPointers(pDataObject, bstrPropertyName, pbstrPropertyValue);
  1341. if(sc)
  1342. return sc;
  1343. // initialize out parameter
  1344. *pbstrPropertyValue = NULL;
  1345. // create a stream for the data object to use
  1346. IStreamPtr pStm;
  1347. sc = CreateStreamOnHGlobal(NULL, true, &pStm);
  1348. if(sc)
  1349. return sc;
  1350. ULARGE_INTEGER zeroSize = {0, 0};
  1351. sc = pStm->SetSize(zeroSize);
  1352. if(sc)
  1353. return sc;
  1354. USES_CONVERSION;
  1355. CLIPFORMAT cfClipFormat = (CLIPFORMAT)RegisterClipboardFormat(OLE2T(bstrPropertyName));
  1356. // First call ExtractString which uses GetData
  1357. CStr strOutput;
  1358. sc = ExtractString (pDataObject, cfClipFormat, strOutput);
  1359. if(!sc.IsError())
  1360. {
  1361. *pbstrPropertyValue = ::SysAllocStringLen(T2COLE(strOutput), strOutput.GetLength()/*prevents the terminating zero from being added.*/); // allocate the string and return
  1362. return sc;
  1363. }
  1364. // That didn't work, so try using GetDataHere.
  1365. FORMATETC fmt = {cfClipFormat, NULL, DVASPECT_CONTENT, -1, TYMED_ISTREAM};
  1366. STGMEDIUM stgm = {TYMED_ISTREAM, NULL, NULL};
  1367. stgm.pstm = pStm;
  1368. sc = pDataObject->GetDataHere(&fmt, &stgm);
  1369. if(sc)
  1370. {
  1371. // ignore errors and return a blank string
  1372. sc.Clear();
  1373. return sc;
  1374. }
  1375. STATSTG stagStg;
  1376. ZeroMemory(&stagStg, sizeof(stagStg));
  1377. sc = pStm->Stat(&stagStg, STATFLAG_NONAME); // do not need the name in the statistics.
  1378. if(sc)
  1379. return sc;
  1380. if(stagStg.cbSize.HighPart != 0)
  1381. return sc = E_UNEXPECTED;
  1382. // go back to the beginning of the stream
  1383. LARGE_INTEGER dlibMove = {0, 0};
  1384. sc = pStm->Seek(dlibMove, STREAM_SEEK_SET, NULL);
  1385. if(sc)
  1386. return sc;
  1387. BSTR bstrValue = ::SysAllocStringLen(NULL, stagStg.cbSize.LowPart / sizeof(OLECHAR)); // one character is automatically added
  1388. if(!bstrValue)
  1389. return sc = E_OUTOFMEMORY;
  1390. ULONG cbRead = 0;
  1391. sc = pStm->Read(bstrValue, stagStg.cbSize.LowPart, &cbRead);
  1392. if(sc)
  1393. return sc;
  1394. // make sure that the count of characters is what was expected
  1395. if(cbRead != stagStg.cbSize.LowPart)
  1396. {
  1397. ::SysFreeString(bstrValue);
  1398. return sc = E_UNEXPECTED;
  1399. }
  1400. // set the output parameter
  1401. *pbstrPropertyValue = bstrValue;
  1402. return sc;
  1403. }
  1404. /*+-------------------------------------------------------------------------*
  1405. *
  1406. * CNodeCallback::GetNodetypeForListItem
  1407. *
  1408. * PURPOSE: Returns the node type for a list item.
  1409. *
  1410. * PARAMETERS:
  1411. * HNODE hNodeScope :
  1412. * BOOL bForScopeItem :
  1413. * LPARAM resultItemParam :
  1414. * PBSTR pbstrNodetype :
  1415. *
  1416. * RETURNS:
  1417. * HRESULT
  1418. *
  1419. *+-------------------------------------------------------------------------*/
  1420. HRESULT
  1421. CNodeCallback::GetNodetypeForListItem(HNODE hNodeScope, BOOL bForScopeItem, LPARAM resultItemParam, PBSTR pbstrNodetype)
  1422. {
  1423. DECLARE_SC(sc, TEXT("CNodeCallback::GetNodetypeForListItem"));
  1424. // check parameters
  1425. sc = ScCheckPointers(pbstrNodetype);
  1426. if(sc)
  1427. return sc.ToHr();
  1428. // initialize out parameter
  1429. *pbstrNodetype = NULL;
  1430. // convert the HNODE to a CNode *
  1431. CNode *pNodeScope = CNode::FromHandle(hNodeScope);
  1432. sc = ScCheckPointers(pNodeScope);
  1433. if(sc)
  1434. return sc.ToHr();
  1435. IDataObjectPtr spDataObject;
  1436. bool bScopeItem;
  1437. sc = pNodeScope->ScGetDataObject(bForScopeItem, resultItemParam, bScopeItem, &spDataObject);
  1438. if(sc)
  1439. return sc.ToHr();
  1440. // at this point we should have a valid data object
  1441. sc = ScCheckPointers((LPDATAOBJECT)spDataObject);
  1442. if(sc)
  1443. return sc.ToHr();
  1444. sc = ScGetNodetype(spDataObject, pbstrNodetype);
  1445. return sc.ToHr();
  1446. }
  1447. /*+-------------------------------------------------------------------------*
  1448. *
  1449. * CNodeCallback::ScGetNodetype
  1450. *
  1451. * PURPOSE: Static function - returns the nodetype of a data object as a string.
  1452. *
  1453. * PARAMETERS:
  1454. * IDataObject * pDataObject :
  1455. * PBSTR pbstrNodetype :
  1456. *
  1457. * RETURNS:
  1458. * SC
  1459. *
  1460. *+-------------------------------------------------------------------------*/
  1461. SC
  1462. CNodeCallback::ScGetNodetype(IDataObject *pDataObject, PBSTR pbstrNodetype)
  1463. {
  1464. DECLARE_SC(sc, TEXT("CNodeCallback::ScGetNodetype"));
  1465. sc = ScCheckPointers(pDataObject, pbstrNodetype);
  1466. if(sc)
  1467. return sc;
  1468. // init out parameter
  1469. *pbstrNodetype = NULL;
  1470. GUID guidNodetype = GUID_NULL;
  1471. sc = ExtractObjectTypeGUID(pDataObject, &guidNodetype);
  1472. if(sc)
  1473. return sc;
  1474. OLECHAR szSnapInGUID[40];
  1475. int iRet = StringFromGUID2(guidNodetype, szSnapInGUID, countof(szSnapInGUID));
  1476. if(0 == iRet)
  1477. return (sc = E_UNEXPECTED);
  1478. // allocate the string, with the correct length.
  1479. *pbstrNodetype = ::SysAllocString(szSnapInGUID);
  1480. if(!*pbstrNodetype)
  1481. return (sc = E_OUTOFMEMORY);
  1482. return sc;
  1483. }
  1484. HRESULT CNodeCallback::OnSnapInHelp(CNode* pNode, BOOL bScope, MMC_COOKIE cookie)
  1485. {
  1486. if (bScope == FALSE && pNode->GetViewData()->IsVirtualList() == FALSE)
  1487. {
  1488. ASSERT(cookie != NULL);
  1489. CResultItem* pri = CResultItem::FromHandle(cookie);
  1490. if ((pri != NULL) && pri->IsScopeItem())
  1491. {
  1492. pNode = CNode::FromResultItem(pri);
  1493. ASSERT(pNode != NULL);
  1494. }
  1495. }
  1496. CComponent* pCC = pNode->GetPrimaryComponent();
  1497. ASSERT(pCC != NULL);
  1498. HRESULT hr = pCC->Notify(NULL, MMCN_SNAPINHELP, 0, 0);
  1499. CHECK_HRESULT(hr);
  1500. return hr;
  1501. }
  1502. HRESULT CNodeCallback::OnContextHelp(CNode* pNode, BOOL bScope, MMC_COOKIE cookie)
  1503. {
  1504. ASSERT(pNode != NULL);
  1505. if (bScope == FALSE && pNode->GetViewData()->IsVirtualList() == FALSE)
  1506. {
  1507. ASSERT(cookie != NULL);
  1508. if(cookie == NULL || IS_SPECIAL_COOKIE(cookie))
  1509. return E_UNEXPECTED;
  1510. CResultItem* pri = CResultItem::FromHandle(cookie);
  1511. if (pri == NULL)
  1512. return (E_UNEXPECTED);
  1513. cookie = pri->GetSnapinData();
  1514. bScope = pri->IsScopeItem();
  1515. if (bScope == TRUE)
  1516. {
  1517. pNode = CNode::FromResultItem(pri);
  1518. ASSERT(pNode != NULL);
  1519. }
  1520. }
  1521. if (bScope == TRUE)
  1522. {
  1523. IDataObjectPtr spdtobj;
  1524. HRESULT hr = pNode->GetMTNode()->QueryDataObject(CCT_SCOPE, &spdtobj);
  1525. ASSERT(SUCCEEDED(hr));
  1526. if (FAILED(hr))
  1527. return hr;
  1528. CComponent* pCC = pNode->GetPrimaryComponent();
  1529. if ( pCC == NULL )
  1530. return E_UNEXPECTED;
  1531. hr = pCC->Notify(spdtobj, MMCN_CONTEXTHELP, 0, 0);
  1532. CHECK_HRESULT(hr);
  1533. return hr;
  1534. }
  1535. else
  1536. {
  1537. CComponent* pCC = pNode->GetPrimaryComponent();
  1538. ASSERT(pCC != NULL);
  1539. if ( pCC == NULL )
  1540. return E_UNEXPECTED;
  1541. IDataObjectPtr spdtobj;
  1542. HRESULT hr = pCC->QueryDataObject(cookie, CCT_RESULT, &spdtobj);
  1543. ASSERT(SUCCEEDED(hr));
  1544. if (FAILED(hr))
  1545. return hr;
  1546. hr = pCC->Notify(spdtobj, MMCN_CONTEXTHELP, 0, 0);
  1547. CHECK_HRESULT(hr);
  1548. return hr;
  1549. }
  1550. }
  1551. //+-------------------------------------------------------------------
  1552. //
  1553. // Member: CNodeCallback::GetSnapinName
  1554. //
  1555. // Synopsis: Given the node get the snapin name
  1556. //
  1557. // Arguments: [hNode] - [in]
  1558. // [ppszName] - [out] ret val, caller should free using CoTaskMemFree
  1559. // [bValidName] - [out], is the name valid or not
  1560. //
  1561. // Returns: HRESULT
  1562. //
  1563. //--------------------------------------------------------------------
  1564. HRESULT CNodeCallback::GetSnapinName (/*[in]*/HNODE hNode, /*[out]*/LPOLESTR* ppszName, /*[out]*/ bool& bValidName)
  1565. {
  1566. DECLARE_SC(sc, _T("CNodeCallback::GetSnapinName"));
  1567. sc = ScCheckPointers( (void*) hNode, ppszName);
  1568. if (sc)
  1569. return sc.ToHr();
  1570. bValidName = false;
  1571. CNode *pNode = CNode::FromHandle(hNode);
  1572. sc = ScCheckPointers(pNode, E_UNEXPECTED);
  1573. if (sc)
  1574. return sc.ToHr();
  1575. *ppszName = NULL;
  1576. CSnapIn* pSnapIn = pNode->GetPrimarySnapIn();
  1577. sc = ScCheckPointers (pSnapIn, E_UNEXPECTED);
  1578. if (sc)
  1579. return (sc.ToHr());
  1580. WTL::CString strName;
  1581. sc = pSnapIn->ScGetSnapInName(strName);
  1582. if (sc)
  1583. return (sc.ToHr());
  1584. if (strName.IsEmpty())
  1585. return sc.ToHr();
  1586. USES_CONVERSION;
  1587. *ppszName = CoTaskDupString (T2COLE (strName));
  1588. if (*ppszName == NULL)
  1589. return ((sc = E_OUTOFMEMORY).ToHr());
  1590. bValidName = true;
  1591. return (sc.ToHr());
  1592. }
  1593. //+-------------------------------------------------------------------
  1594. //
  1595. // Member: OnColumnClicked
  1596. //
  1597. // Synopsis: Ask snapin if it wants to sort and do so.
  1598. //
  1599. // Arguments: [pNode] - CNode* owner of list view.
  1600. // [nCol] - column that is clicked (to sort on this column).
  1601. //
  1602. // Returns: HRESULT
  1603. //
  1604. // History: 07-27-1999 AnandhaG renamed OnSort to OnColumnClicked
  1605. //--------------------------------------------------------------------
  1606. HRESULT CNodeCallback::OnColumnClicked(CNode* pNode, LONG_PTR nCol)
  1607. {
  1608. ASSERT(pNode != NULL);
  1609. pNode->OnColumnClicked(nCol);
  1610. return S_OK;
  1611. }
  1612. HRESULT CNodeCallback::OnPrint(CNode* pNode, BOOL bScopePane, LPARAM lvData)
  1613. {
  1614. DECLARE_SC(sc, TEXT("CNodeCallback::OnPrint"));
  1615. sc = ScCheckPointers(pNode);
  1616. if (sc)
  1617. return sc.ToHr();
  1618. if ((!bScopePane) && (LVDATA_MULTISELECT == lvData) )
  1619. {
  1620. CViewData *pViewData = pNode->GetViewData();
  1621. sc = ScCheckPointers(pViewData, E_UNEXPECTED);
  1622. if (sc)
  1623. return sc.ToHr();
  1624. CMultiSelection* pMultiSel = pViewData->GetMultiSelection();
  1625. sc = ScCheckPointers(pMultiSel, E_UNEXPECTED);
  1626. if (sc)
  1627. return sc.ToHr();
  1628. sc = pMultiSel->ScVerbInvoked(MMC_VERB_PRINT);
  1629. if (sc)
  1630. return sc.ToHr();
  1631. return sc.ToHr();
  1632. }
  1633. IDataObjectPtr spdtobj;
  1634. IDataObject *pdtobj = NULL;
  1635. bool bScopeItem;
  1636. sc = pNode->ScGetDataObject(bScopePane, lvData, bScopeItem, &pdtobj);
  1637. if (sc)
  1638. return sc.ToHr();
  1639. if (! IS_SPECIAL_DATAOBJECT(pdtobj))
  1640. spdtobj = pdtobj;
  1641. CComponent *pComponent = pNode->GetPrimaryComponent();
  1642. sc = ScCheckPointers(pComponent, pdtobj, E_UNEXPECTED);
  1643. if (sc)
  1644. return sc.ToHr();
  1645. sc = pComponent->Notify(pdtobj, MMCN_PRINT, 0, 0);
  1646. if (sc)
  1647. sc.TraceAndClear();
  1648. return sc.ToHr();
  1649. }
  1650. HRESULT
  1651. CNodeCallback::OnEditTaskpad(CNode *pNode)
  1652. {
  1653. ASSERT(pNode);
  1654. ITaskCallbackPtr spTaskCallback = pNode->GetViewData()->m_spTaskCallback;
  1655. ASSERT(spTaskCallback.GetInterfacePtr());
  1656. return spTaskCallback->OnModifyTaskpad();
  1657. }
  1658. HRESULT
  1659. CNodeCallback::OnDeleteTaskpad(CNode *pNode)
  1660. {
  1661. DECLARE_SC(sc, TEXT("CNodeCallback::OnDeleteTaskpad"));
  1662. ASSERT(pNode);
  1663. sc = ScCheckPointers( pNode );
  1664. if ( sc )
  1665. return sc.ToHr();
  1666. ITaskCallbackPtr spTaskCallback = pNode->GetViewData()->m_spTaskCallback;
  1667. ASSERT(spTaskCallback.GetInterfacePtr());
  1668. // make the node dirty
  1669. CMTNode* pMTNode = pNode->GetMTNode();
  1670. sc = ScCheckPointers( pMTNode, E_UNEXPECTED );
  1671. if(sc)
  1672. return sc.ToHr();
  1673. pMTNode->SetDirty();
  1674. return spTaskCallback->OnDeleteTaskpad();
  1675. }
  1676. /* CNodeCallback::OnNewTaskpadFromHere
  1677. *
  1678. * PURPOSE: Displays property pages for a new taskpad
  1679. *
  1680. * PARAMETERS:
  1681. * CNode* pNode: The node that the taskpad should target to.
  1682. *
  1683. * RETURNS:
  1684. * HRESULT
  1685. */
  1686. HRESULT
  1687. CNodeCallback::OnNewTaskpadFromHere(CNode* pNode)
  1688. {
  1689. DECLARE_SC(sc, TEXT("CNodeCallback::OnNewTaskpadFromHere"));
  1690. sc = ScCheckPointers(pNode, E_UNEXPECTED);
  1691. if (sc)
  1692. return sc.ToHr();
  1693. CConsoleTaskpad taskpad (pNode);
  1694. CTaskpadWizard dlg(pNode, taskpad, TRUE /*fNew*/, 0, FALSE, pNode->GetViewData());
  1695. bool fStartTaskWizard = true;
  1696. sc = dlg.Show(pNode->GetViewData()->GetMainFrame() /*hWndParent*/, &fStartTaskWizard);
  1697. if (sc != S_OK)
  1698. return sc.ToHr();
  1699. sc = ScCheckPointers(m_pCScopeTree, E_UNEXPECTED);
  1700. if (sc)
  1701. return sc.ToHr();
  1702. m_pCScopeTree->InsertConsoleTaskpad (&taskpad, pNode, fStartTaskWizard);
  1703. // modify the view settings for this node to ensure that the taskpad is shown after the reselect.
  1704. sc = pNode->ScSetTaskpadID(taskpad.GetID(), /*bSetViewSettingDirty*/ true);
  1705. if (sc)
  1706. return sc.ToHr();
  1707. m_pCScopeTree->UpdateAllViews(VIEW_RESELECT, 0);
  1708. return sc.ToHr();
  1709. }
  1710. HRESULT CNodeCallback::OnRefresh(CNode* pNode, BOOL bScopePaneSelected, LPARAM lvData)
  1711. {
  1712. DECLARE_SC(sc, TEXT("CNodeCallback::OnRefresh"));
  1713. BOOL bScopeItemSelected;
  1714. CNode *pSelectedNode = NULL;
  1715. MMC_COOKIE cookie = -1;
  1716. sc = CNodeCallback::ScExtractLVData(pNode, bScopePaneSelected, lvData,
  1717. &pSelectedNode, bScopeItemSelected, cookie);
  1718. if (sc)
  1719. return sc.ToHr();
  1720. sc = ScCheckPointers(pSelectedNode, E_UNEXPECTED);
  1721. if (sc)
  1722. return sc.ToHr();
  1723. // If result-pane cookie should be valid.
  1724. ASSERT( (bScopeItemSelected) || cookie != LVDATA_ERROR);
  1725. if ( (FALSE == bScopeItemSelected) && (cookie == LVDATA_ERROR) )
  1726. return E_FAIL;
  1727. // Before refreshing this node, if the user has made
  1728. // changes to list view persist it.
  1729. CViewData* pVD = pSelectedNode->GetViewData();
  1730. ASSERT(pVD != NULL);
  1731. if (bScopeItemSelected)
  1732. {
  1733. ASSERT(pNode != NULL);
  1734. IDataObjectPtr spdtobj;
  1735. HRESULT hr = pSelectedNode->GetMTNode()->QueryDataObject(CCT_SCOPE, &spdtobj);
  1736. ASSERT(SUCCEEDED(hr));
  1737. if (FAILED(hr))
  1738. return hr;
  1739. CMTNode* pMTNode = pSelectedNode->GetMTNode();
  1740. ASSERT(pMTNode != NULL);
  1741. LPARAM lScopeItem = CMTNode::ToScopeItem(pMTNode);
  1742. // Send notify to primary snap-in
  1743. pMTNode->AddRef();
  1744. pSelectedNode->GetPrimaryComponent()->Notify(spdtobj, MMCN_REFRESH, lScopeItem, 0);
  1745. if (pMTNode->Release() == 0)
  1746. return S_OK;
  1747. // If node has been expanded, then also send notify to all namespace
  1748. // extensions for this node
  1749. if (pMTNode->WasExpandedAtLeastOnce())
  1750. {
  1751. do // dummy loop
  1752. {
  1753. // Get the node-type of this node
  1754. GUID guidNodeType;
  1755. HRESULT hr = pMTNode->GetNodeType(&guidNodeType);
  1756. CHECK_HRESULT(hr);
  1757. if (FAILED(hr))
  1758. break;
  1759. // Get list of dynmaic extensions
  1760. LPCLSID pDynExtCLSID;
  1761. int cDynExt = pMTNode->GetDynExtCLSID(&pDynExtCLSID);
  1762. // Create and init namespace extension iterator
  1763. CExtensionsIterator it;
  1764. sc = it.ScInitialize(pMTNode->GetPrimarySnapIn(), guidNodeType, g_szNameSpace, pDynExtCLSID, cDynExt);
  1765. if (sc)
  1766. break;
  1767. CSnapInNode* pSINode = pSelectedNode->GetStaticParent();
  1768. ASSERT(pSINode != NULL);
  1769. // Send refresh to each extension's component
  1770. for (; it.IsEnd() == FALSE; it.Advance())
  1771. {
  1772. CComponent* pCC = pSINode->GetComponent(it.GetCLSID());
  1773. if (pCC == NULL)
  1774. continue;
  1775. HRESULT hr = pCC->Notify(spdtobj, MMCN_REFRESH, lScopeItem, 0);
  1776. CHECK_HRESULT(hr);
  1777. }
  1778. } while (FALSE);
  1779. }
  1780. }
  1781. else
  1782. {
  1783. CComponent* pCC = pSelectedNode->GetPrimaryComponent();
  1784. ASSERT(pCC != NULL);
  1785. if (IS_SPECIAL_LVDATA(lvData))
  1786. {
  1787. LPDATAOBJECT pdobj = (lvData == LVDATA_CUSTOMOCX) ?
  1788. DOBJ_CUSTOMOCX : DOBJ_CUSTOMWEB;
  1789. HRESULT hr = pCC->Notify(pdobj, MMCN_REFRESH, 0, 0);
  1790. CHECK_HRESULT(hr);
  1791. }
  1792. else
  1793. {
  1794. IDataObjectPtr spdtobj;
  1795. HRESULT hr = pCC->QueryDataObject(cookie, CCT_RESULT, &spdtobj);
  1796. ASSERT(SUCCEEDED(hr));
  1797. if (FAILED(hr))
  1798. return hr;
  1799. pCC->Notify(spdtobj, MMCN_REFRESH, 0, 0);
  1800. }
  1801. }
  1802. // Set the view correctly using the persisted data.
  1803. do
  1804. {
  1805. if (NULL == pVD)
  1806. break;
  1807. // After the refresh the snapin could have deleted the pSelectedNode or
  1808. // could have moved the selection. While setting view-data we
  1809. // just need the currently selected node (the owner of the view
  1810. // which is not affected by temp selection) and set the view.
  1811. CNode* pSelNode = pVD->GetSelectedNode();
  1812. if (NULL == pSelNode)
  1813. break;
  1814. sc = pSelNode->ScRestoreSortFromPersistedData();
  1815. if (sc)
  1816. return sc.ToHr();
  1817. } while ( FALSE );
  1818. return S_OK;
  1819. }
  1820. UINT GetRelation(CMTNode* pMTNodeSrc, CMTNode* pMTNodeDest)
  1821. {
  1822. if (pMTNodeSrc == pMTNodeDest)
  1823. return 1;
  1824. for(pMTNodeDest = pMTNodeDest->Parent();
  1825. pMTNodeDest;
  1826. pMTNodeDest = pMTNodeDest->Parent())
  1827. {
  1828. if (pMTNodeSrc == pMTNodeDest)
  1829. return 2;
  1830. }
  1831. return 0;
  1832. }
  1833. STDMETHODIMP CNodeCallback::UpdatePasteButton(HNODE hNode, BOOL bScope, LPARAM lvData)
  1834. {
  1835. DECLARE_SC(sc, TEXT("CNodeCallback::UpdatePasteButton"));
  1836. sc = ScCheckPointers(hNode);
  1837. if (sc)
  1838. return sc.ToHr();
  1839. bool bPasteAllowed = false;
  1840. // Update only when item is being selected.
  1841. sc = QueryPasteFromClipboard(hNode, bScope, lvData, bPasteAllowed);
  1842. if (sc)
  1843. return sc.ToHr();
  1844. CNode *pNode = CNode::FromHandle(hNode);
  1845. sc = ScCheckPointers(pNode, E_UNEXPECTED);
  1846. if (sc)
  1847. return sc.ToHr();
  1848. CViewData *pViewData = pNode->GetViewData();
  1849. sc = ScCheckPointers(pViewData, E_UNEXPECTED);
  1850. if (sc)
  1851. return sc.ToHr();
  1852. sc = pViewData->ScUpdateStdbarVerb (MMC_VERB_PASTE, TBSTATE_ENABLED, bPasteAllowed);
  1853. if (sc)
  1854. return sc.ToHr();
  1855. return sc.ToHr();
  1856. }
  1857. //+-------------------------------------------------------------------
  1858. //
  1859. // Member: CNodeCallback::ScInitializeTempVerbSetForMultiSel
  1860. //
  1861. // Synopsis: For given node, initialize the tempverbset object
  1862. // provided. For this create a multi-selection object
  1863. // initialize it (multiselection object finds out what is
  1864. // selected in resultpane and sends MMCN_SELECT to appropriate
  1865. // snapins) and compute the verb states for the temp-verbset object.
  1866. //
  1867. // Arguments: [pNode] - [in] owner of resultpane.
  1868. // [tempverb] - [in] Temp verb set object which is initialzied.
  1869. //
  1870. // Returns: SC
  1871. //
  1872. //--------------------------------------------------------------------
  1873. SC CNodeCallback::ScInitializeTempVerbSetForMultiSel(CNode *pNode, CTemporaryVerbSet& tempVerb)
  1874. {
  1875. DECLARE_SC(sc, TEXT("CNodeCallback::ScInitializeTempVerbSetForMultiSel"));
  1876. sc = ScCheckPointers(pNode);
  1877. if (sc)
  1878. return sc;
  1879. ASSERT(pNode->IsInitialized() == TRUE);
  1880. // 1. Create a multi-selection object.
  1881. CMultiSelection* pMultiSelection = new CMultiSelection(pNode);
  1882. sc = ScCheckPointers(pMultiSelection, E_OUTOFMEMORY);
  1883. if (sc)
  1884. return sc;
  1885. IDataObjectPtr spdobj;
  1886. // 2. Initialize it, (it finds out what is selected in resultpane
  1887. // gets dataobjects from appropriate snapins and sends snapins
  1888. // MMCN_SELECT notifications).
  1889. sc = pMultiSelection->Init();
  1890. if (sc)
  1891. goto Cleanup;
  1892. pMultiSelection->SetScopeTree(m_pCScopeTree);
  1893. sc = pMultiSelection->GetMultiSelDataObject(&spdobj);
  1894. if (sc)
  1895. goto Cleanup;
  1896. if (spdobj == NULL)
  1897. goto Cleanup;
  1898. // 3. Init the verbset object.
  1899. sc = tempVerb.ScInitializeForMultiSelection(pNode, /*bSelect*/ true);
  1900. if (sc)
  1901. goto Cleanup;
  1902. tempVerb.SetMultiSelection(pMultiSelection);
  1903. // 4. Compute the verbs that are set by snapin along with given context.
  1904. sc = tempVerb.ScComputeVerbStates();
  1905. if (sc)
  1906. goto Cleanup;
  1907. Cleanup:
  1908. pMultiSelection->Release();
  1909. return sc;
  1910. }
  1911. //+-------------------------------------------------------------------
  1912. //
  1913. // Member: CNodeCallback::_ScGetVerbState
  1914. //
  1915. // Synopsis: For given item (dataobject), the owner node see if given
  1916. // verb is set. A temp-verb-set object is created for this purpose.
  1917. //
  1918. // Arguments: [pNode] - [in]
  1919. // [verb] - [in]
  1920. // [pDOSel] - [in] Dataobject of the item whose verb we are interested.
  1921. // [bScopePane] - [in]
  1922. // [lResultCookie] - [in]
  1923. // [bMultiSelect] - [in]
  1924. // [bIsVerbSet] - [out] verb is set or not.
  1925. //
  1926. // Returns: SC
  1927. //
  1928. //--------------------------------------------------------------------
  1929. SC CNodeCallback::_ScGetVerbState( CNode* pNode, MMC_CONSOLE_VERB verb, IDataObject* pDOSel,
  1930. BOOL bScopePane, LPARAM lResultCookie,
  1931. BOOL bMultiSelect, BOOL& bIsVerbSet)
  1932. {
  1933. DECLARE_SC(sc, TEXT("CNodeCallback::_GetVerbState"));
  1934. bIsVerbSet = FALSE;
  1935. sc = ScCheckPointers(pNode, pDOSel);
  1936. if (sc)
  1937. return sc;
  1938. CComObject<CTemporaryVerbSet> stdVerbTemp;
  1939. if (bMultiSelect)
  1940. sc = ScInitializeTempVerbSetForMultiSel(pNode, stdVerbTemp);
  1941. else
  1942. sc = stdVerbTemp.ScInitialize(pDOSel, pNode, bScopePane, lResultCookie);
  1943. if (sc)
  1944. return sc;
  1945. stdVerbTemp.GetVerbState(verb, ENABLED, &bIsVerbSet);
  1946. return sc;
  1947. }
  1948. HRESULT
  1949. CNodeCallback::OnCutCopy(
  1950. CNode* pNode,
  1951. BOOL bScope,
  1952. LPARAM lvData,
  1953. BOOL bCut)
  1954. {
  1955. DECLARE_SC(sc, TEXT("CNodeCallback::OnCutCopy"));
  1956. // parameter check
  1957. sc = ScCheckPointers(pNode);
  1958. if (sc)
  1959. return sc.ToHr();
  1960. // get the object
  1961. IMMCClipboardDataObjectPtr spClipBoardDataObject;
  1962. bool bContainsItems = false;
  1963. sc = CMMCClipBoardDataObject::ScCreate( (bCut ? ACTION_CUT : ACTION_COPY),
  1964. pNode, bScope,
  1965. (lvData == LVDATA_MULTISELECT)/*bMultiSel*/,
  1966. lvData, &spClipBoardDataObject ,
  1967. bContainsItems);
  1968. if (sc)
  1969. return sc.ToHr();
  1970. // If snapin has cut or copy then dataobject should have been added.
  1971. if (! bContainsItems)
  1972. return (sc = E_UNEXPECTED).ToHr();
  1973. // QI for IDataObject
  1974. IDataObjectPtr spDataObject = spClipBoardDataObject;
  1975. sc = ScCheckPointers( spDataObject, E_UNEXPECTED );
  1976. if (sc)
  1977. return sc.ToHr();
  1978. // Put the dataobject on the clipboard.
  1979. sc = OleSetClipboard( spDataObject );
  1980. if (sc)
  1981. return sc.ToHr();
  1982. return sc.ToHr();
  1983. }
  1984. //+-------------------------------------------------------------------
  1985. //
  1986. // Member: CNodeCallback::OnProperties
  1987. //
  1988. // Synopsis: Bring property sheet for given item.
  1989. //
  1990. // Arguments: CNode* - The node that owns result pane.
  1991. // BOOL - If true bring propsheet of above node else use LVData.
  1992. // LPARAM - If bScope = FALSE then use this data to get the LVData
  1993. // and bring its property sheet.
  1994. //
  1995. // Returns: HRESULT
  1996. //
  1997. //--------------------------------------------------------------------
  1998. HRESULT CNodeCallback::OnProperties(CNode* pNode, BOOL bScopePaneSelected, LPARAM lvData)
  1999. {
  2000. DECLARE_SC(sc, _T("CNodeCallback::OnProperties"));
  2001. sc = ScCheckPointers(pNode);
  2002. if (sc)
  2003. return (sc.ToHr());
  2004. // NOTE: All the code below should be moved into the CNode class
  2005. BOOL bScopeItemSelected = FALSE;
  2006. CNode *pSelectedNode = NULL;
  2007. MMC_COOKIE cookie = -1;
  2008. sc = CNodeCallback::ScExtractLVData(pNode, bScopePaneSelected, lvData,
  2009. &pSelectedNode, bScopeItemSelected, cookie);
  2010. if (sc)
  2011. return sc.ToHr();
  2012. sc = ScCheckPointers(pSelectedNode, E_UNEXPECTED);
  2013. if (sc)
  2014. return sc.ToHr();
  2015. // If result-pane cookie should be valid.
  2016. if ( (FALSE == bScopeItemSelected) && (cookie == LVDATA_ERROR) )
  2017. return (sc = E_FAIL).ToHr();
  2018. if (bScopeItemSelected)
  2019. {
  2020. sc = ScDisplaySnapinNodePropertySheet(pSelectedNode);
  2021. if(sc)
  2022. return sc.ToHr();
  2023. }
  2024. else
  2025. {
  2026. CViewData* pViewData = pSelectedNode->GetViewData();
  2027. sc = ScCheckPointers(pViewData, E_UNEXPECTED);
  2028. if (sc)
  2029. return sc.ToHr();
  2030. if (pViewData->HasList())
  2031. {
  2032. if (cookie == LVDATA_MULTISELECT)
  2033. {
  2034. sc = ScDisplayMultiSelPropertySheet(pSelectedNode);
  2035. if(sc)
  2036. return sc.ToHr();
  2037. }
  2038. else
  2039. {
  2040. sc = ScDisplaySnapinLeafPropertySheet(pSelectedNode, cookie);
  2041. if(sc)
  2042. return sc.ToHr();
  2043. }
  2044. }
  2045. else
  2046. {
  2047. LPDATAOBJECT pdobj = (pViewData->HasOCX() ) ? DOBJ_CUSTOMOCX : DOBJ_CUSTOMWEB;
  2048. CComponent* pCC = pSelectedNode->GetPrimaryComponent();
  2049. sc = ScCheckPointers(pCC, E_UNEXPECTED);
  2050. if (sc)
  2051. return sc.ToHr();
  2052. pCC->Notify(pdobj, MMCN_BTN_CLICK, 0, MMC_VERB_PROPERTIES);
  2053. }
  2054. }
  2055. return S_OK;
  2056. }
  2057. HRESULT CNodeCallback::OnFilterChange(CNode* pNode, LONG_PTR nCode, LPARAM nCol)
  2058. {
  2059. IF_NULL_RETURN_INVALIDARG(pNode);
  2060. CComponent* pCC = pNode->GetPrimaryComponent();
  2061. ASSERT(pCC != NULL);
  2062. if (pCC != NULL)
  2063. {
  2064. HRESULT hr = pCC->Notify(DOBJ_NULL, MMCN_FILTER_CHANGE, nCode, nCol);
  2065. return hr;
  2066. }
  2067. return E_FAIL;
  2068. }
  2069. HRESULT CNodeCallback::OnFilterBtnClick(CNode* pNode, LONG_PTR nCol, LPRECT pRect)
  2070. {
  2071. IF_NULL_RETURN_INVALIDARG2(pNode, pRect);
  2072. CComponent* pCC = pNode->GetPrimaryComponent();
  2073. ASSERT(pCC != NULL);
  2074. if (pCC != NULL)
  2075. {
  2076. HRESULT hr = pCC->Notify(DOBJ_NULL, MMCN_FILTERBTN_CLICK, nCol, (LPARAM)pRect);
  2077. return hr;
  2078. }
  2079. return E_FAIL;
  2080. }
  2081. STDMETHODIMP CNodeCallback::IsExpandable(HNODE hNode)
  2082. {
  2083. MMC_TRY
  2084. // convert to real type
  2085. CNode* pNode = CNode::FromHandle(hNode);
  2086. ASSERT(pNode != NULL);
  2087. CMTNode* pMTNode = pNode->GetMTNode();
  2088. ASSERT(pMTNode != NULL);
  2089. return pMTNode->IsExpandable();
  2090. MMC_CATCH
  2091. }
  2092. HRESULT _GetConsoleVerb(CNode* pNode, LPCONSOLEVERB* ppConsoleVerb)
  2093. {
  2094. IF_NULL_RETURN_INVALIDARG2(pNode, ppConsoleVerb);
  2095. HRESULT hr = S_FALSE;
  2096. CComponent* pCC = pNode->GetPrimaryComponent();
  2097. ASSERT(pCC != NULL);
  2098. if (pCC == NULL)
  2099. return E_FAIL;
  2100. IFramePrivate* pIFP = pCC->GetIFramePrivate();
  2101. ASSERT(pIFP != NULL);
  2102. if (pIFP == NULL)
  2103. return E_FAIL;
  2104. IConsoleVerbPtr spConsoleVerb;
  2105. hr = pIFP->QueryConsoleVerb(&spConsoleVerb);
  2106. if (SUCCEEDED(hr))
  2107. {
  2108. *ppConsoleVerb = spConsoleVerb.Detach();
  2109. hr = S_OK;
  2110. }
  2111. return hr;
  2112. }
  2113. STDMETHODIMP CNodeCallback::GetConsoleVerb(HNODE hNode, LPCONSOLEVERB* ppConsoleVerb)
  2114. {
  2115. MMC_TRY
  2116. ASSERT(ppConsoleVerb != NULL);
  2117. return _GetConsoleVerb(CNode::FromHandle(hNode), ppConsoleVerb);
  2118. MMC_CATCH
  2119. }
  2120. // lCookie valid if both bScope & bMultiSel are FALSE.
  2121. // lCookie is the index\lParam for virtual\regular LV
  2122. STDMETHODIMP
  2123. CNodeCallback::GetDragDropDataObject(
  2124. HNODE hNode,
  2125. BOOL bScope,
  2126. BOOL bMultiSel,
  2127. LONG_PTR lvData,
  2128. LPDATAOBJECT* ppDataObject,
  2129. bool& bCopyAllowed,
  2130. bool& bMoveAllowed)
  2131. {
  2132. DECLARE_SC(sc, TEXT("CNodeCallback::GetDragDropDataObject"));
  2133. // init allowed op's to false
  2134. bCopyAllowed = false;
  2135. bMoveAllowed = false;
  2136. // parameter check
  2137. sc = ScCheckPointers(ppDataObject);
  2138. if (sc)
  2139. return sc.ToHr();
  2140. // init out parameter;
  2141. *ppDataObject = NULL;
  2142. // get the object
  2143. IMMCClipboardDataObjectPtr spClipBoardDataObject;
  2144. bool bContainsItems = false;
  2145. sc = CMMCClipBoardDataObject::ScCreate( ACTION_DRAG,
  2146. CNode::FromHandle(hNode),
  2147. bScope, bMultiSel, lvData,
  2148. &spClipBoardDataObject,
  2149. bContainsItems );
  2150. if (sc)
  2151. return sc.ToHr();
  2152. // We asked for drag&drop dataobject. If snapin does not support cut/copy then
  2153. // the dataobjects will not be added which is not an error.
  2154. if (! bContainsItems)
  2155. return sc.ToHr();
  2156. // QI for IDataObject
  2157. IDataObjectPtr spDataObject = spClipBoardDataObject;
  2158. sc = ScCheckPointers( spDataObject, E_UNEXPECTED );
  2159. if (sc)
  2160. return sc.ToHr();
  2161. // inspect data objects included to see what operations are allowed
  2162. // (note: (spDataObject==valid) -> (spClipBoardDataObject==valid) )
  2163. DWORD dwCount = 0;
  2164. sc = spClipBoardDataObject->GetCount( &dwCount );
  2165. for ( DWORD dwIdx = 0; dwIdx < dwCount; dwIdx ++ )
  2166. {
  2167. IDataObjectPtr spSnapinDO;
  2168. DWORD dwOptions = 0;
  2169. sc = spClipBoardDataObject->GetDataObject( dwIdx, &spSnapinDO, &dwOptions );
  2170. if (sc)
  2171. return sc.ToHr();
  2172. // claculate allowed operations
  2173. bCopyAllowed = bCopyAllowed || ( dwOptions & COPY_ALLOWED );
  2174. bMoveAllowed = bMoveAllowed || ( dwOptions & MOVE_ALLOWED );
  2175. // enabling is inclusive, so very few tests are required
  2176. if ( bCopyAllowed && bMoveAllowed )
  2177. break;
  2178. }
  2179. // return data object
  2180. *ppDataObject = spDataObject.Detach();
  2181. return sc.ToHr();
  2182. }
  2183. //+-------------------------------------------------------------------
  2184. //
  2185. // Member: CNodeCallback::ScExtractLVData
  2186. //
  2187. // Synopsis: If listview item is selected, see if it is a scope item
  2188. // in non-virtual listview (virtual listviews cannot have
  2189. // scope items in them). If so extract that scope item else
  2190. // the cookie of result item.
  2191. //
  2192. // Arguments: [pNode] - [in, out] if scope item is selected in resultpane, then
  2193. // will contain this scope item on return.
  2194. // [bScope] - [in, out] Is scope item currently selected item (in scope or
  2195. // result pane).
  2196. // [lvData] - [in] LVDATA
  2197. // [cookie] - [in] lParam of result item.
  2198. //
  2199. // Returns: SC
  2200. //
  2201. //--------------------------------------------------------------------
  2202. SC CNodeCallback::ScExtractLVData(CNode* pNodeViewOwner,
  2203. BOOL bScopePaneSelected,
  2204. LONG_PTR lvData,
  2205. CNode** ppSelectedNode,
  2206. BOOL& bScopeItemSelected,
  2207. MMC_COOKIE& cookie)
  2208. {
  2209. DECLARE_SC(sc, _T("CNodeCallback::ScExtractLVData"));
  2210. sc = ScCheckPointers(pNodeViewOwner, ppSelectedNode);
  2211. if (sc)
  2212. return sc;
  2213. *ppSelectedNode = NULL;
  2214. bScopeItemSelected = bScopePaneSelected;
  2215. *ppSelectedNode = pNodeViewOwner;
  2216. if (bScopePaneSelected)
  2217. {
  2218. cookie = lvData;
  2219. return sc;
  2220. }
  2221. // Scope pane is not selected.
  2222. CViewData *pViewData = pNodeViewOwner->GetViewData();
  2223. sc = ScCheckPointers(pViewData, E_UNEXPECTED);
  2224. if (sc)
  2225. return sc;
  2226. cookie = lvData;
  2227. if (IS_SPECIAL_LVDATA(lvData))
  2228. {
  2229. if (lvData == LVDATA_BACKGROUND)
  2230. bScopeItemSelected = TRUE;
  2231. }
  2232. else if (! pViewData->IsVirtualList())
  2233. {
  2234. CResultItem* pri = CResultItem::FromHandle (lvData);
  2235. sc = ScCheckPointers(pri, E_UNEXPECTED);
  2236. if (sc)
  2237. {
  2238. cookie = LVDATA_ERROR;
  2239. return sc;
  2240. }
  2241. if (pri->IsScopeItem())
  2242. {
  2243. bScopeItemSelected = TRUE;
  2244. *ppSelectedNode = CNode::FromResultItem(pri);
  2245. sc = ScCheckPointers(*ppSelectedNode, E_UNEXPECTED);
  2246. if (sc)
  2247. return sc;
  2248. cookie = -1;
  2249. }
  2250. else
  2251. {
  2252. cookie = pri->GetSnapinData();
  2253. }
  2254. ASSERT(!IS_SPECIAL_LVDATA(lvData) || !bScopeItemSelected);
  2255. }
  2256. return (sc);
  2257. }
  2258. STDMETHODIMP
  2259. CNodeCallback::GetTaskEnumerator(
  2260. HNODE hNode,
  2261. LPCOLESTR pszTaskGroup,
  2262. IEnumTASK** ppEnumTask)
  2263. {
  2264. IF_NULL_RETURN_INVALIDARG3(hNode, pszTaskGroup, ppEnumTask);
  2265. *ppEnumTask = NULL; // init
  2266. // convert to real type
  2267. CNode* pNode = CNode::FromHandle(hNode);
  2268. return pNode->GetTaskEnumerator(CComBSTR(pszTaskGroup), ppEnumTask);
  2269. }
  2270. STDMETHODIMP
  2271. CNodeCallback::GetListPadInfo(HNODE hNode, IExtendTaskPad* pExtendTaskPad,
  2272. LPCOLESTR szTaskGroup, MMC_ILISTPAD_INFO* pIListPadInfo)
  2273. {
  2274. IF_NULL_RETURN_INVALIDARG(hNode);
  2275. CNode* pNode = CNode::FromHandle(hNode);
  2276. return pNode->GetListPadInfo(pExtendTaskPad, CComBSTR(szTaskGroup), pIListPadInfo);
  2277. }
  2278. HRESULT CNodeCallback::OnGetPrimaryTask(CNode* pNode, LPARAM param)
  2279. {
  2280. IF_NULL_RETURN_INVALIDARG(pNode);
  2281. IExtendTaskPad** ppExtendTaskPad = reinterpret_cast<IExtendTaskPad**>(param);
  2282. return pNode->OnGetPrimaryTask(ppExtendTaskPad);
  2283. }
  2284. STDMETHODIMP
  2285. CNodeCallback::UpdateWindowLayout(LONG_PTR lViewData, long lToolbarsDisplayed)
  2286. {
  2287. IF_NULL_RETURN_INVALIDARG(lViewData);
  2288. CViewData* pVD = reinterpret_cast<CViewData*>(lViewData);
  2289. pVD->UpdateToolbars(lToolbarsDisplayed);
  2290. return S_OK;
  2291. }
  2292. HRESULT CNodeCallback::PreLoad(HNODE hNode)
  2293. {
  2294. DECLARE_SC(sc, TEXT("CNodeCallback::PreLoad"));
  2295. // parameter check
  2296. sc = ScCheckPointers( hNode );
  2297. if (sc)
  2298. return sc.ToHr();
  2299. CNode* pNode = CNode::FromHandle (hNode);
  2300. if (pNode->IsStaticNode() == FALSE ||
  2301. pNode->IsInitialized() == TRUE)
  2302. return (sc = S_FALSE).ToHr();
  2303. // if the node is:
  2304. // 1. a snapin node;
  2305. // 2. marked as "PreLoad"; and,
  2306. // 3. not initialized yet.
  2307. // if all three, then send 'em a notify containing their HSCOPEITEM
  2308. CMTNode* pMTNode = pNode->GetMTNode();
  2309. sc = ScCheckPointers( pMTNode, E_FAIL );
  2310. if (sc)
  2311. return sc.ToHr();
  2312. CMTSnapInNode* pMTSnapInNode = dynamic_cast<CMTSnapInNode*>(pMTNode);
  2313. sc = ScCheckPointers( pMTSnapInNode, E_UNEXPECTED );
  2314. if (sc)
  2315. return sc.ToHr();
  2316. if (!pMTSnapInNode->IsPreloadRequired())
  2317. return (sc = S_FALSE).ToHr();
  2318. if (pMTNode->IsInitialized() == FALSE)
  2319. {
  2320. sc = pMTSnapInNode->Init();
  2321. if (sc)
  2322. return sc.ToHr();
  2323. }
  2324. //
  2325. // If the snap-in needs to be preloaded, the IComponent also needs
  2326. // to be init so that the sanpin can insert icons in the result
  2327. // pane if the parent node is selected in the scope pane.
  2328. //
  2329. ASSERT(pNode->IsInitialized() == FALSE);
  2330. sc = _InitializeNode(pNode);
  2331. if (sc)
  2332. return sc.ToHr();
  2333. return sc.ToHr();
  2334. }
  2335. STDMETHODIMP CNodeCallback::SetTaskpad(HNODE hNodeSelected, GUID *pGuidTaskpad)
  2336. {
  2337. ASSERT(hNodeSelected != NULL);
  2338. ASSERT(pGuidTaskpad != NULL);
  2339. CNode *pNode = CNode::FromHandle(hNodeSelected);
  2340. // See ScSetViewExtension for more info on parameters in the call.
  2341. HRESULT hr = pNode->ScSetViewExtension(pGuidTaskpad,
  2342. /*bUseDefaultTaskPad*/ false,
  2343. /*bSetViewSettingDirty*/ true).ToHr();
  2344. return hr;
  2345. }
  2346. STDMETHODIMP CNodeCallback::OnCustomizeView (LONG_PTR lViewData)
  2347. {
  2348. ::OnCustomizeView ((CViewData*) lViewData);
  2349. return (S_OK);
  2350. }
  2351. //+-------------------------------------------------------------------
  2352. //
  2353. // Member: CNodeCallback::SetViewSettings
  2354. //
  2355. // Synopsis: Modify the view settings data that is persisted.
  2356. //
  2357. // Arguments: [nViewID] - [in] the view id.
  2358. // [hbm] - [in] bookmark.
  2359. // [hvs] - [in] view-settings.
  2360. //
  2361. // Returns: HRESULT
  2362. //
  2363. //--------------------------------------------------------------------
  2364. STDMETHODIMP CNodeCallback::SetViewSettings(int nViewID, HBOOKMARK hbm, HVIEWSETTINGS hvs)
  2365. {
  2366. DECLARE_SC(sc, _T("CNodeCallback::SetViewSettings"));
  2367. sc = ScCheckPointers( (void*)hbm, (void*) hvs);
  2368. if (sc)
  2369. return sc.ToHr();
  2370. CViewSettings *pViewSettings = reinterpret_cast<CViewSettings *>(hvs);
  2371. CBookmark *pBookmark = reinterpret_cast<CBookmark*> (hbm);
  2372. sc = CNode::ScSetFavoriteViewSettings(nViewID, *pBookmark, *pViewSettings);
  2373. if (sc)
  2374. return sc.ToHr();
  2375. return sc.ToHr();
  2376. }
  2377. //+-------------------------------------------------------------------
  2378. //
  2379. // Member: CNodeCallback::ExecuteScopeItemVerb
  2380. //
  2381. // Synopsis: Invoke the given verb with given context. Also make sure
  2382. // the verb is enabled by snapin for this context.
  2383. //
  2384. // Arguments: [verb] - The verb to be invoked.
  2385. // [hNode] - The node for which above verb is invoked.
  2386. // [lpszNewName] - For "rename" represents new name.
  2387. //
  2388. // Returns: SC
  2389. //
  2390. //--------------------------------------------------------------------
  2391. HRESULT CNodeCallback::ExecuteScopeItemVerb (MMC_CONSOLE_VERB verb, HNODE hNode, LPOLESTR lpszNewName)
  2392. {
  2393. DECLARE_SC(sc, _T("CNodeCallback::ExecuteScopeItemVerb"));
  2394. CNode* pNode = CNode::FromHandle(hNode);
  2395. sc = ScCheckPointers(pNode);
  2396. if(sc)
  2397. return sc.ToHr();
  2398. // Get data object for the item.
  2399. IDataObjectPtr spDataObject;
  2400. sc = pNode->QueryDataObject(CCT_SCOPE, &spDataObject);
  2401. if (sc)
  2402. return (sc.ToHr());
  2403. BOOL bEnabled = FALSE;
  2404. // see if the verb is enabled by the snapin.
  2405. sc = _ScGetVerbState( pNode, verb, spDataObject,
  2406. /*bScopePane*/TRUE, /*lResultCookie = */ NULL,
  2407. /*bMultiSel*/FALSE, bEnabled);
  2408. if (sc)
  2409. return sc.ToHr();
  2410. if (! bEnabled) // Verb not enabled.
  2411. return (sc = ScFromMMC(MMC_E_TheVerbNotEnabled)).ToHr();
  2412. switch(verb)
  2413. {
  2414. case MMC_VERB_PROPERTIES:
  2415. sc = OnProperties(pNode, /*bScope*/ TRUE, /*LPARAM*/ NULL);
  2416. if (sc)
  2417. return sc.ToHr();
  2418. break;
  2419. case MMC_VERB_DELETE:
  2420. sc = OnDelete(pNode, /*bScope*/ TRUE, /*LPARAM*/ NULL);
  2421. if (sc)
  2422. return sc.ToHr();
  2423. break;
  2424. case MMC_VERB_REFRESH:
  2425. sc = OnRefresh(pNode, /*bScope*/ TRUE, /*LPARAM*/ NULL);
  2426. if (sc)
  2427. return sc.ToHr();
  2428. break;
  2429. case MMC_VERB_RENAME:
  2430. {
  2431. // To call Rename we must first initialize SELECTIONINFO.
  2432. SELECTIONINFO selInfo;
  2433. ZeroMemory(&selInfo, sizeof(selInfo));
  2434. selInfo.m_bScope = TRUE;
  2435. selInfo.m_eCmdID = MMC_VERB_RENAME;
  2436. sc = OnRename(pNode, &selInfo, lpszNewName);
  2437. if (sc)
  2438. return sc.ToHr();
  2439. }
  2440. break;
  2441. case MMC_VERB_COPY:
  2442. sc = OnCutCopy(pNode, /*bScope*/ TRUE, NULL, /*bCut*/ FALSE);
  2443. if (sc)
  2444. return sc.ToHr();
  2445. break;
  2446. default:
  2447. sc = E_UNEXPECTED;
  2448. break;
  2449. }
  2450. return (sc.ToHr());
  2451. }
  2452. //+-------------------------------------------------------------------
  2453. //
  2454. // Member: CNodeCallback::ExecuteResultItemVerb
  2455. //
  2456. // Synopsis: Invoke the given verb with given context. Also make sure
  2457. // the verb is enabled by snapin for this context.
  2458. //
  2459. // Arguments: [verb] - The verb to be invoked.
  2460. // [hNode] - The node that owns result pane now.
  2461. // [lvData] - The list view selection context.
  2462. // [lpszNewName] - For "rename" represents new name else NULL.
  2463. //
  2464. // Returns: SC
  2465. //
  2466. //--------------------------------------------------------------------
  2467. HRESULT CNodeCallback::ExecuteResultItemVerb (MMC_CONSOLE_VERB verb, HNODE hNode, LPARAM lvData, LPOLESTR lpszNewName)
  2468. {
  2469. DECLARE_SC(sc, _T("CNodeCallback::ExecuteResultItemVerb"));
  2470. CNode* pNode = CNode::FromHandle(hNode);
  2471. sc = ScCheckPointers(pNode, E_UNEXPECTED);
  2472. if (sc)
  2473. return (sc.ToHr());
  2474. // We need to see if the given verb is enabled by the snapin. We need
  2475. // dataobject for given context for this. So get the context by calling
  2476. // ScExtractLVData().
  2477. BOOL bScopeItemSelected;
  2478. CNode *pSelectedNode = NULL;
  2479. MMC_COOKIE cookie = -1;
  2480. sc = CNodeCallback::ScExtractLVData(pNode, /*bScopePaneSelected*/ FALSE, lvData,
  2481. &pSelectedNode, bScopeItemSelected, cookie);
  2482. if (sc)
  2483. return sc.ToHr();
  2484. sc = ScCheckPointers(pSelectedNode, E_UNEXPECTED);
  2485. if (sc)
  2486. return sc.ToHr();
  2487. // Cookie should be valid for result pane.
  2488. if ( (FALSE == bScopeItemSelected) && (cookie == LVDATA_ERROR) )
  2489. return (sc = E_FAIL).ToHr();
  2490. BOOL bMultiSelect = (LVDATA_MULTISELECT == lvData);
  2491. if (bMultiSelect)
  2492. cookie = MMC_MULTI_SELECT_COOKIE;
  2493. // Depending on whether this is scope item in result pane or result item
  2494. // ask ComponentData or Component the data object.
  2495. IDataObjectPtr spDataObject;
  2496. if (bScopeItemSelected)
  2497. {
  2498. sc = pSelectedNode->QueryDataObject (CCT_SCOPE, &spDataObject);
  2499. if (sc)
  2500. return sc.ToHr();
  2501. }
  2502. else
  2503. {
  2504. CComponent* pCC = pNode->GetPrimaryComponent();
  2505. sc = ScCheckPointers(pCC, E_UNEXPECTED);
  2506. if (sc)
  2507. return sc.ToHr();
  2508. sc = pCC->QueryDataObject(cookie, CCT_RESULT, &spDataObject);
  2509. if (sc)
  2510. return (sc.ToHr());
  2511. }
  2512. BOOL bEnabled = FALSE;
  2513. // See if the verb is enabled for this selection.
  2514. sc = _ScGetVerbState( pSelectedNode , verb, spDataObject,
  2515. /*bScopePaneSelected*/ FALSE, lvData,
  2516. bMultiSelect, bEnabled);
  2517. if (sc)
  2518. return sc.ToHr();
  2519. if (! bEnabled) // Verb not enabled.
  2520. return (sc = ScFromMMC(MMC_E_TheVerbNotEnabled)).ToHr();
  2521. switch(verb)
  2522. {
  2523. case MMC_VERB_PROPERTIES:
  2524. sc = OnProperties(pNode, /*bScope*/ FALSE, /*LPARAM*/ lvData);
  2525. if (sc)
  2526. return sc.ToHr();
  2527. break;
  2528. case MMC_VERB_DELETE:
  2529. sc = OnDelete(pNode, /*bScope*/ FALSE, /*LPARAM*/ lvData);
  2530. if (sc)
  2531. return sc.ToHr();
  2532. break;
  2533. case MMC_VERB_REFRESH:
  2534. sc = OnRefresh(pNode, /*bScope*/ FALSE, /*LPARAM*/ lvData);
  2535. if (sc)
  2536. return sc.ToHr();
  2537. break;
  2538. case MMC_VERB_RENAME:
  2539. {
  2540. // For Rename we should also call ScExtractLVData before calling OnRename.
  2541. // To call Rename we must first initialize SELECTIONINFO.
  2542. SELECTIONINFO selInfo;
  2543. ZeroMemory(&selInfo, sizeof(selInfo));
  2544. selInfo.m_bScope = bScopeItemSelected;
  2545. selInfo.m_lCookie = cookie;
  2546. selInfo.m_eCmdID = MMC_VERB_RENAME;
  2547. sc = OnRename(pNode, &selInfo, lpszNewName);
  2548. if (sc)
  2549. return sc.ToHr();
  2550. }
  2551. break;
  2552. case MMC_VERB_COPY:
  2553. sc = OnCutCopy(pNode, /*bScope*/ FALSE, lvData, /*bCut*/ FALSE);
  2554. if (sc)
  2555. return sc.ToHr();
  2556. break;
  2557. default:
  2558. sc = E_INVALIDARG;
  2559. break;
  2560. }
  2561. return (sc.ToHr());
  2562. }
  2563. /*+-------------------------------------------------------------------------*
  2564. *
  2565. * FUNCTION: CNodeCallback::QueryCompDataDispatch
  2566. *
  2567. * PURPOSE: Get the disp interface for given scope node object from snapin.
  2568. *
  2569. * PARAMETERS:
  2570. * PNODE - The Node object for which the disp interface is required.
  2571. * PPDISPATCH [out] - Disp interface pointer returned by snapin.
  2572. *
  2573. * RETURNS:
  2574. * HRESULT
  2575. *
  2576. *+-------------------------------------------------------------------------*/
  2577. STDMETHODIMP
  2578. CNodeCallback::QueryCompDataDispatch(PNODE pNode, PPDISPATCH ppScopeNodeObject)
  2579. {
  2580. DECLARE_SC(sc, TEXT("CNodeCallback::QueryCompDataDispInterface"));
  2581. sc = ScCheckPointers(m_pCScopeTree);
  2582. if(sc)
  2583. return sc.ToHr();
  2584. CMTNode *pMTNode = NULL;
  2585. sc = m_pCScopeTree->ScGetNode(pNode, &pMTNode);
  2586. if(sc)
  2587. return sc.ToHr();
  2588. sc = ScCheckPointers(pMTNode, E_UNEXPECTED);
  2589. if (sc)
  2590. return sc.ToHr();
  2591. sc = pMTNode->ScQueryDispatch(CCT_SCOPE, ppScopeNodeObject);
  2592. if (sc)
  2593. return sc.ToHr();
  2594. return sc.ToHr();
  2595. }
  2596. //+-------------------------------------------------------------------
  2597. //
  2598. // Member: CNodeCallback::QueryComponentDispatch
  2599. //
  2600. // Synopsis: Get the disp interface for given item in resultpane from snapin.
  2601. //
  2602. // Arguments:
  2603. // HNODE - The Scope Node which owns result pane.
  2604. // LVDATA - The LVDATA of selected item
  2605. // PPDISPATCH [out] - Disp interface pointer returned by snapin.
  2606. //
  2607. // Returns: HRESULT
  2608. //
  2609. //--------------------------------------------------------------------
  2610. HRESULT CNodeCallback::QueryComponentDispatch (HNODE hNode,
  2611. LPARAM lvData,
  2612. PPDISPATCH SelectedObject)
  2613. {
  2614. DECLARE_SC(sc, _T("CNodeCallback::QueryComponentDispatch"));
  2615. CNode* pNode = CNode::FromHandle(hNode);
  2616. sc = ScCheckPointers(pNode);
  2617. if (sc)
  2618. return sc.ToHr();
  2619. BOOL bScopeItemSelected;
  2620. CNode *pSelectedNode = NULL;
  2621. MMC_COOKIE cookie = -1;
  2622. sc = CNodeCallback::ScExtractLVData(pNode, /*bScopePaneSelected*/ FALSE, lvData,
  2623. &pSelectedNode, bScopeItemSelected, cookie);
  2624. if (sc)
  2625. return sc.ToHr();
  2626. /*
  2627. * In case of multiselection, set cookie to MMC_MULTI_SELECT_COOKIE
  2628. * which snapins can understand.
  2629. */
  2630. BOOL bMultiSelect = (LVDATA_MULTISELECT == lvData);
  2631. if (bMultiSelect)
  2632. {
  2633. cookie = MMC_MULTI_SELECT_COOKIE;
  2634. ASSERT(bScopeItemSelected == false);
  2635. }
  2636. sc = ScCheckPointers(pSelectedNode, E_UNEXPECTED);
  2637. if (sc)
  2638. return sc.ToHr();
  2639. // If result-pane cookie should be valid.
  2640. if ( (FALSE == bScopeItemSelected) && (cookie == LVDATA_ERROR) )
  2641. return (sc = E_FAIL).ToHr();
  2642. // Scope item is selected in result pane.
  2643. if (bScopeItemSelected)
  2644. {
  2645. CMTNode* pMTNode = pSelectedNode->GetMTNode();
  2646. sc = ScCheckPointers(pMTNode, E_UNEXPECTED);
  2647. if (sc)
  2648. return sc.ToHr();
  2649. sc = pMTNode->ScQueryDispatch(CCT_SCOPE, SelectedObject);
  2650. if (sc)
  2651. return sc.ToHr();
  2652. }
  2653. else
  2654. {
  2655. CComponent* pCC = pSelectedNode->GetPrimaryComponent();
  2656. sc = ScCheckPointers(pCC, E_UNEXPECTED);
  2657. if (sc)
  2658. return sc.ToHr();
  2659. sc = pCC->ScQueryDispatch(cookie, CCT_RESULT, SelectedObject);
  2660. if (sc)
  2661. return sc.ToHr();
  2662. }
  2663. return (sc.ToHr());
  2664. }
  2665. /***************************************************************************\
  2666. *
  2667. * METHOD: CNodeCallback::ShowColumn
  2668. *
  2669. * PURPOSE: Shows/hides the column. Implements both UI part as snapin notifications
  2670. * Used as helper implementing functionality for Column com object.
  2671. * [uses CNode to perform the task]
  2672. *
  2673. * PARAMETERS:
  2674. * HNODE hNodeSelected - scope node - oener of the view
  2675. * int iColIndex - column index to perform action on
  2676. * bool bVisible - show/hide flag for operation
  2677. *
  2678. * RETURNS:
  2679. * SC - result code
  2680. *
  2681. \***************************************************************************/
  2682. STDMETHODIMP CNodeCallback::ShowColumn(HNODE hNodeSelected, int iColIndex, bool bShow)
  2683. {
  2684. DECLARE_SC(sc, TEXT("CNodeCallback::ShowColumn"));
  2685. // get CNode pointer
  2686. CNode* pNode = CNode::FromHandle(hNodeSelected);
  2687. sc = ScCheckPointers(pNode, E_UNEXPECTED);
  2688. if (sc)
  2689. return sc.ToHr();
  2690. sc = pNode->ScShowColumn(iColIndex, bShow);
  2691. if (sc)
  2692. return sc.ToHr();
  2693. return sc.ToHr();
  2694. }
  2695. /***************************************************************************\
  2696. *
  2697. * METHOD: CNodeCallback::GetSortColumn
  2698. *
  2699. * PURPOSE: retrieves index of sort column
  2700. * Used as helper implementing functionality for Column com object.
  2701. * [uses CNode to perform the task]
  2702. *
  2703. * PARAMETERS:
  2704. * HNODE hNodeSelected - scope node - oener of the view
  2705. * int *piSortCol - resulting index
  2706. *
  2707. * RETURNS:
  2708. * SC - result code
  2709. *
  2710. \***************************************************************************/
  2711. STDMETHODIMP CNodeCallback::GetSortColumn(HNODE hNodeSelected, int *piSortCol)
  2712. {
  2713. DECLARE_SC(sc, TEXT("CNodeCallback::GetSortColumn"));
  2714. // get CNode pointer
  2715. CNode* pNode = CNode::FromHandle(hNodeSelected);
  2716. sc = ScCheckPointers(pNode, E_UNEXPECTED);
  2717. if (sc)
  2718. return sc.ToHr();
  2719. sc = pNode->ScGetSortColumn(piSortCol);
  2720. if (sc)
  2721. return sc.ToHr();
  2722. return sc.ToHr();
  2723. }
  2724. /***************************************************************************\
  2725. *
  2726. * METHOD: CNodeCallback::SetSortColumn
  2727. *
  2728. * PURPOSE: sorts result data by specified column
  2729. * Used as helper implementing functionality for Column com object.
  2730. * [uses CNode to perform the task]
  2731. *
  2732. * PARAMETERS:
  2733. * HNODE hNodeSelected - scope node - oener of the view
  2734. * int iSortCol - sort column index
  2735. * bool bAscending - sort order
  2736. *
  2737. * RETURNS:
  2738. * HRESULT
  2739. *
  2740. \***************************************************************************/
  2741. STDMETHODIMP CNodeCallback::SetSortColumn(HNODE hNodeSelected, int iSortCol, bool bAscending)
  2742. {
  2743. DECLARE_SC(sc, TEXT("CNodeCallback::SetSortColumn"));
  2744. // get CNode pointer
  2745. CNode* pNode = CNode::FromHandle(hNodeSelected);
  2746. sc = ScCheckPointers(pNode, E_UNEXPECTED);
  2747. if (sc)
  2748. return sc.ToHr();
  2749. sc = pNode->ScSetSortColumn(iSortCol, bAscending);
  2750. if (sc)
  2751. return sc.ToHr();
  2752. return sc.ToHr();
  2753. }
  2754. /***************************************************************************\
  2755. *
  2756. * METHOD: CNodeCallback::RestoreResultView
  2757. *
  2758. * PURPOSE: Called by conui to restore the result view with given data.
  2759. * This method asks snapin (indirectly) to restore the view.
  2760. *
  2761. * PARAMETERS:
  2762. * HNODE hNode - scope node - oener of the view
  2763. * CResultViewType rvt - The resultview type data to be used for restore.
  2764. *
  2765. * RETURNS:
  2766. * HRESULT S_OK if snapin used the data to restore the view
  2767. * S_FALSE if snapin refused to restore.
  2768. *
  2769. \***************************************************************************/
  2770. STDMETHODIMP CNodeCallback::RestoreResultView(HNODE hNode, const CResultViewType& rvt)
  2771. {
  2772. DECLARE_SC(sc, TEXT("CNodeCallback::RestoreResultView"));
  2773. // get CNode pointer
  2774. CNode* pNode = CNode::FromHandle(hNode);
  2775. sc = ScCheckPointers(pNode);
  2776. if (sc)
  2777. return sc.ToHr();
  2778. sc = pNode->ScRestoreResultView(rvt);
  2779. if (sc)
  2780. return sc.ToHr();
  2781. return sc.ToHr();
  2782. }
  2783. /***************************************************************************\
  2784. *
  2785. * METHOD: CNodeCallback::GetNodeViewExtensions
  2786. *
  2787. * PURPOSE: Forwards calls to CNode to collect view extensions
  2788. *
  2789. * PARAMETERS:
  2790. * HNODE hNodeScope
  2791. * CViewExtInsertIterator it
  2792. *
  2793. * RETURNS:
  2794. * HRESULT - result code
  2795. *
  2796. \***************************************************************************/
  2797. STDMETHODIMP CNodeCallback::GetNodeViewExtensions(/*[in]*/ HNODE hNodeScope, /*[out]*/ CViewExtInsertIterator it)
  2798. {
  2799. DECLARE_SC(sc, TEXT("CNodeCallback::GetNodeViewExtensions"));
  2800. // get CNode pointer
  2801. CNode* pNode = CNode::FromHandle(hNodeScope);
  2802. sc = ScCheckPointers(pNode);
  2803. if (sc)
  2804. return sc.ToHr();
  2805. sc = pNode->ScGetViewExtensions(it);
  2806. if (sc)
  2807. return sc.ToHr();
  2808. return sc.ToHr();
  2809. }
  2810. //+-------------------------------------------------------------------
  2811. //
  2812. // Member: CNodeCallback::SaveColumnInfoList
  2813. //
  2814. // Synopsis: The column-data for given node has changed persist the
  2815. // new column data.
  2816. //
  2817. // Arguments: [hNode] - Node that owns result-pane.
  2818. // [columnsList] - The new column-data.
  2819. //
  2820. // Note: The sort-data is not given by this call, so do not change it.
  2821. //
  2822. // Returns: HRESULT
  2823. //
  2824. //--------------------------------------------------------------------
  2825. HRESULT CNodeCallback::SaveColumnInfoList (HNODE hNode, const CColumnInfoList& columnsList)
  2826. {
  2827. DECLARE_SC(sc, _T("CNodeCallback::SaveColumnInfoList"));
  2828. sc = ScCheckPointers(hNode);
  2829. if (sc)
  2830. return sc.ToHr();
  2831. CNode *pNode = CNode::FromHandle(hNode);
  2832. sc = ScCheckPointers(pNode);
  2833. if (sc)
  2834. return sc.ToHr();
  2835. CViewData *pViewData = pNode->GetViewData();
  2836. sc = ScCheckPointers(pViewData, E_UNEXPECTED);
  2837. if (sc)
  2838. return sc.ToHr();
  2839. CLSID guidSnapin;
  2840. CXMLAutoBinary columnID;
  2841. sc = pNode->ScGetSnapinAndColumnDataID(guidSnapin, columnID);
  2842. if (sc)
  2843. return sc.ToHr();
  2844. CXMLBinaryLock sLock(columnID);
  2845. SColumnSetID* pColID = NULL;
  2846. sc = sLock.ScLock(&pColID);
  2847. if (sc)
  2848. return sc.ToHr();
  2849. sc = ScCheckPointers(pColID, E_UNEXPECTED);
  2850. if (sc)
  2851. return sc.ToHr();
  2852. // Get the old persisted column data. This contains width values
  2853. // for hidden columns which is used if the column is un-hidden.
  2854. CColumnSetData columnSetData;
  2855. BOOL bRet = pViewData->RetrieveColumnData(guidSnapin, *pColID, columnSetData);
  2856. if (bRet)
  2857. {
  2858. CColumnInfoList* pColInfoListOld = columnSetData.get_ColumnInfoList();
  2859. if (columnsList.size() == pColInfoListOld->size())
  2860. {
  2861. // Merge the persisted column width for hidden columns
  2862. // to the new list created.
  2863. CColumnInfoList::iterator itColInfo1;
  2864. CColumnInfoList::iterator itColInfo2;
  2865. for (itColInfo1 = pColInfoListOld->begin(), itColInfo2 = columnsList.begin();
  2866. itColInfo1 != pColInfoListOld->end(); ++itColInfo1, ++itColInfo2)
  2867. {
  2868. if (itColInfo2->IsColHidden())
  2869. itColInfo2->SetColWidth(itColInfo1->GetColWidth());
  2870. }
  2871. }
  2872. }
  2873. // Set the new columns list in column-set-data.
  2874. columnSetData.set_ColumnInfoList(columnsList);
  2875. // Save the data.
  2876. sc = pViewData->ScSaveColumnInfoList(guidSnapin, *pColID, columnsList);
  2877. if (sc)
  2878. return sc.ToHr();
  2879. return (sc.ToHr());
  2880. }
  2881. //+-------------------------------------------------------------------
  2882. //
  2883. // Member: CNodeCallback::GetPersistedColumnInfoList
  2884. //
  2885. // Synopsis: The list-view requests the column-data (no sort data) to setup the headers
  2886. // before any items are inserted into the list-view.
  2887. // (Note: Modify headers after all columns are inserted before any list-view
  2888. // items will be inserted to reduce flicker).
  2889. //
  2890. // Arguments: [hNode] - node that owns result-pane for which column-data is needed.
  2891. // [pColumnsList] - [out param], the column-data.
  2892. //
  2893. // Returns: HRESULT
  2894. //
  2895. //--------------------------------------------------------------------
  2896. HRESULT CNodeCallback::GetPersistedColumnInfoList (HNODE hNode, CColumnInfoList *pColumnsList)
  2897. {
  2898. DECLARE_SC(sc, _T("CNodeCallback::GetPersistedColumnInfoList"));
  2899. sc = ScCheckPointers(hNode, pColumnsList);
  2900. if (sc)
  2901. return sc.ToHr();
  2902. CNode *pNode = CNode::FromHandle(hNode);
  2903. sc = ScCheckPointers(pNode);
  2904. if (sc)
  2905. return sc.ToHr();
  2906. CViewData *pViewData = pNode->GetViewData();
  2907. sc = ScCheckPointers(pViewData, E_UNEXPECTED);
  2908. if (sc)
  2909. return sc.ToHr();
  2910. CLSID guidSnapin;
  2911. CXMLAutoBinary columnID;
  2912. sc = pNode->ScGetSnapinAndColumnDataID(guidSnapin, columnID);
  2913. if (sc)
  2914. return sc.ToHr();
  2915. CXMLBinaryLock sLock(columnID);
  2916. SColumnSetID* pColID = NULL;
  2917. sc = sLock.ScLock(&pColID);
  2918. if (sc)
  2919. return sc.ToHr();
  2920. sc = ScCheckPointers(pColID, E_UNEXPECTED);
  2921. if (sc)
  2922. return sc.ToHr();
  2923. // Get the old persisted column data. This contains width values
  2924. // for hidden columns which is used if the column is un-hidden.
  2925. CColumnSetData columnSetData;
  2926. BOOL bRet = pViewData->RetrieveColumnData(guidSnapin, *pColID, columnSetData);
  2927. if (!bRet)
  2928. return (sc = S_FALSE).ToHr();
  2929. CColumnInfoList *pColListOriginal = columnSetData.get_ColumnInfoList();
  2930. if (!pColListOriginal)
  2931. return (sc = S_FALSE).ToHr();
  2932. *pColumnsList = *pColListOriginal;
  2933. return (sc.ToHr());
  2934. }
  2935. //+-------------------------------------------------------------------
  2936. //
  2937. // Member: CNodeCallback::DeletePersistedColumnData
  2938. //
  2939. // Synopsis: The column data for given node is invalid, remove it.
  2940. //
  2941. // Arguments: [hNode] - The node for which the data is invalid.
  2942. //
  2943. // Returns: HRESULT
  2944. //
  2945. //--------------------------------------------------------------------
  2946. HRESULT CNodeCallback::DeletePersistedColumnData(HNODE hNode)
  2947. {
  2948. DECLARE_SC(sc, _T("CNodeCallback::DeletePersistedColumnData"));
  2949. sc = ScCheckPointers(hNode);
  2950. if (sc)
  2951. return sc.ToHr();
  2952. CNode *pNode = CNode::FromHandle(hNode);
  2953. sc = ScCheckPointers(pNode);
  2954. if (sc)
  2955. return sc.ToHr();
  2956. CViewData *pViewData = pNode->GetViewData();
  2957. sc = ScCheckPointers(pViewData, E_UNEXPECTED);
  2958. if (sc)
  2959. return sc.ToHr();
  2960. CLSID guidSnapin;
  2961. CXMLAutoBinary columnID;
  2962. sc = pNode->ScGetSnapinAndColumnDataID(guidSnapin, columnID);
  2963. if (sc)
  2964. return sc.ToHr();
  2965. CXMLBinaryLock sLock(columnID);
  2966. SColumnSetID* pColID = NULL;
  2967. sc = sLock.ScLock(&pColID);
  2968. if (sc)
  2969. return sc.ToHr();
  2970. sc = ScCheckPointers(pColID, E_UNEXPECTED);
  2971. if (sc)
  2972. return sc.ToHr();
  2973. // Get the old persisted column data. This contains width values
  2974. // for hidden columns which is used if the column is un-hidden.
  2975. pViewData->DeleteColumnData(guidSnapin, *pColID);
  2976. return (sc.ToHr());
  2977. }
  2978. //+-------------------------------------------------------------------
  2979. //
  2980. // Member: CNodeCallback::DoesAboutExist
  2981. //
  2982. // Synopsis: See if about information exists for given node's snapin.
  2983. //
  2984. // Arguments: [hNode] -
  2985. // [pbAboutExists] - out param, ptr to bool, true if about exists.
  2986. //
  2987. // Returns: HRESULT
  2988. //
  2989. //--------------------------------------------------------------------
  2990. STDMETHODIMP CNodeCallback::DoesAboutExist (HNODE hNode, bool *pbAboutExists)
  2991. {
  2992. DECLARE_SC(sc, _T("CNodeCallback::DoesAboutExist"));
  2993. sc = ScCheckPointers(hNode, pbAboutExists);
  2994. if (sc)
  2995. return sc.ToHr();
  2996. *pbAboutExists = false;
  2997. CNode *pNode = CNode::FromHandle(hNode);
  2998. sc = ScCheckPointers(pNode);
  2999. if (sc)
  3000. return sc.ToHr();
  3001. // No about for console root eventhough it is a Folder snapin.
  3002. if (pNode->IsConsoleRoot())
  3003. return sc.ToHr();
  3004. CLSID clsidAbout;
  3005. const CLSID& clsidSnapin = pNode->GetPrimarySnapInCLSID();
  3006. SC scNoTrace = ScGetAboutFromSnapinCLSID(clsidSnapin, clsidAbout);
  3007. if (scNoTrace)
  3008. return scNoTrace.ToHr();
  3009. CSnapinAbout snapinAbout;
  3010. snapinAbout.GetSnapinInformation(clsidAbout);
  3011. sc = snapinAbout.GetObjectStatus();
  3012. if (sc)
  3013. return sc.ToHr();
  3014. *pbAboutExists = true;
  3015. return (sc.ToHr());
  3016. }
  3017. //+-------------------------------------------------------------------
  3018. //
  3019. // Member: CNodeCallback::ShowAboutInformation
  3020. //
  3021. // Synopsis: Given the context of currently selected item.
  3022. // Show its about information.
  3023. //
  3024. // Arguments: [hNode] - scope node that owns result pane.
  3025. //
  3026. // Returns: HRESULT
  3027. //
  3028. //--------------------------------------------------------------------
  3029. STDMETHODIMP CNodeCallback::ShowAboutInformation (HNODE hNode)
  3030. {
  3031. DECLARE_SC(sc, _T("CNodeCallback::ShowAboutInformation"));
  3032. sc = ScCheckPointers(hNode);
  3033. if (sc)
  3034. return sc.ToHr();
  3035. CNode *pNode = CNode::FromHandle(hNode);
  3036. sc = ScCheckPointers(pNode);
  3037. if (sc)
  3038. return sc.ToHr();
  3039. CLSID clsidAbout;
  3040. const CLSID& clsidSnapin = pNode->GetPrimarySnapInCLSID();
  3041. sc = ScGetAboutFromSnapinCLSID(clsidSnapin, clsidAbout);
  3042. if (sc)
  3043. return sc.ToHr();
  3044. CSnapinAbout snapinAbout;
  3045. snapinAbout.GetSnapinInformation(clsidAbout);
  3046. USES_CONVERSION;
  3047. tstring szSnapinName;
  3048. if (GetSnapinNameFromCLSID(clsidSnapin, szSnapinName))
  3049. snapinAbout.SetSnapinName(T2COLE(szSnapinName.data()));
  3050. sc = snapinAbout.GetObjectStatus();
  3051. if (sc)
  3052. return sc.ToHr();
  3053. snapinAbout.ShowAboutBox();
  3054. return (sc.ToHr());
  3055. }
  3056. /*+-------------------------------------------------------------------------*
  3057. *
  3058. * CNodeCallback::ExecuteShellCommand
  3059. *
  3060. * PURPOSE: Executes a shell command with the specified parameters in the
  3061. * specified directory with the correct window size
  3062. *
  3063. * PARAMETERS:
  3064. * HNODE hNode :
  3065. * BSTR Command :
  3066. * BSTR Directory :
  3067. * BSTR Parameters :
  3068. * BSTR WindowState :
  3069. *
  3070. * RETURNS:
  3071. * HRESULT
  3072. *
  3073. *+-------------------------------------------------------------------------*/
  3074. HRESULT
  3075. CNodeCallback::ExecuteShellCommand(HNODE hNode, BSTR Command, BSTR Directory, BSTR Parameters, BSTR WindowState)
  3076. {
  3077. DECLARE_SC(sc, TEXT("CNodeCallback::ExecuteShellCommand"));
  3078. sc = ScCheckPointers(hNode);
  3079. if (sc)
  3080. return sc.ToHr();
  3081. CNode *pNode = CNode::FromHandle(hNode);
  3082. sc = ScCheckPointers(pNode);
  3083. if (sc)
  3084. return sc.ToHr();
  3085. sc = pNode->ScExecuteShellCommand(Command, Directory, Parameters, WindowState);
  3086. return sc.ToHr();
  3087. }
  3088. //+-------------------------------------------------------------------
  3089. //
  3090. // Member: CNodeCallback::QueryPasteFromClipboard
  3091. //
  3092. // Synopsis: Given the context of paste target, get the clipboard dataobject
  3093. // and see if target allows paste.
  3094. //
  3095. // Arguments: [hNode] -
  3096. // [bScope] -
  3097. // [lCookie] - All above params describe paste target context.
  3098. // [bPasteAllowed] - [out]
  3099. //
  3100. // Returns: HRESULT
  3101. //
  3102. //--------------------------------------------------------------------
  3103. STDMETHODIMP CNodeCallback::QueryPasteFromClipboard (HNODE hNode, BOOL bScope, LPARAM lCookie, bool& bPasteAllowed)
  3104. {
  3105. DECLARE_SC(sc, _T("CNodeCallback::QueryPasteFromClipboard"));
  3106. sc = ScCheckPointers(hNode);
  3107. if (sc)
  3108. return sc.ToHr();
  3109. // 1. Get the current dataobject from clipboard.
  3110. IDataObjectPtr spDOPaste;
  3111. sc = OleGetClipboard(&spDOPaste);
  3112. if (sc)
  3113. return sc.ToHr();
  3114. sc = ScCheckPointers(spDOPaste, E_UNEXPECTED);
  3115. if (sc)
  3116. return sc.ToHr();
  3117. bool bCopyOperatationIsDefault = false; /*unused*/
  3118. sc = QueryPaste(hNode, bScope, lCookie, spDOPaste, bPasteAllowed, bCopyOperatationIsDefault);
  3119. if (sc)
  3120. return sc.ToHr();
  3121. return (sc.ToHr());
  3122. }
  3123. //+-------------------------------------------------------------------
  3124. //
  3125. // Member: CNodeCallback::QueryPaste
  3126. //
  3127. // Synopsis: Given the context for current selection which is the target
  3128. // for paste (or drop). Find out it can paste given dataobject.
  3129. //
  3130. // Arguments: [hNode] - The node owning the view.
  3131. // [bScope] - Selection on Scope or Result pane.
  3132. // [lCookie] - If result pane selected the cookie for selected result item.
  3133. // [pDataObjectToPaste] - The dataobject to be pasted.
  3134. // [bPasteAllowed] - [out param], paste was permitted or not.
  3135. // [bCopyOperatationIsDefault] - [out param], is copy default operation (for r-click&l-click drag&drop)
  3136. //
  3137. // Returns: HRESULT
  3138. //
  3139. //--------------------------------------------------------------------
  3140. STDMETHODIMP CNodeCallback::QueryPaste (HNODE hNode, BOOL bScopePaneSelected, LPARAM lCookie,
  3141. IDataObject *pDataObjectToPaste,
  3142. bool& bPasteAllowed, bool& bCopyOperatationIsDefault)
  3143. {
  3144. DECLARE_SC(sc, _T("CNodeCallback::NewQueryPaste"));
  3145. bPasteAllowed = false;
  3146. sc = ScCheckPointers(hNode, pDataObjectToPaste);
  3147. if (sc)
  3148. return sc.ToHr();
  3149. CNode *pNode = CNode::FromHandle(hNode);
  3150. sc = ScCheckPointers(pNode, E_UNEXPECTED);
  3151. if (sc)
  3152. return sc.ToHr();
  3153. // If result-pane cookie should be valid.
  3154. BOOL bScopeItemSelected;
  3155. CNode *pSelectedNode = NULL;
  3156. MMC_COOKIE cookie = -1;
  3157. sc = CNodeCallback::ScExtractLVData(pNode, bScopePaneSelected, lCookie,
  3158. &pSelectedNode, bScopeItemSelected, cookie);
  3159. if (sc)
  3160. return sc.ToHr();
  3161. sc = ScCheckPointers(pSelectedNode, E_UNEXPECTED);
  3162. if (sc)
  3163. return sc.ToHr();
  3164. if ( (FALSE == bScopeItemSelected) && (cookie == LVDATA_ERROR) )
  3165. return (sc = E_FAIL).ToHr();
  3166. CViewData *pViewData = pSelectedNode->GetViewData();
  3167. sc = ScCheckPointers(pViewData, E_UNEXPECTED);
  3168. if (sc)
  3169. return sc.ToHr();
  3170. // Do not allow paste into OCX/WEB/Multiselection
  3171. // We can allow paste into OCX/WEB if we expose IMMCClipboardDataObject
  3172. // interface. But paste into Multiselection should not be allowed as
  3173. // it is not intuitive.
  3174. if ( (!bScopeItemSelected) && IS_SPECIAL_COOKIE(lCookie))
  3175. return sc.ToHr();
  3176. /*
  3177. * In MMC1.2 the drop target is always scope node. In MMC2.0
  3178. * it can be any result item. If the snapin has RVTI_LIST_OPTIONS_ALLOWPASTE
  3179. * set, then we need to provide proper parameters to below _GetVerbState.
  3180. */
  3181. if ( (bScopeItemSelected == FALSE) && (! (RVTI_LIST_OPTIONS_ALLOWPASTE & pViewData->GetListOptions())) )
  3182. return sc.ToHr();
  3183. IDataObjectPtr spTargetDataObject;
  3184. sc = pSelectedNode->ScGetDropTargetDataObject(bScopeItemSelected, lCookie, &spTargetDataObject);
  3185. if (sc)
  3186. return sc.ToHr();
  3187. sc = ScCheckPointers(spTargetDataObject, E_UNEXPECTED);
  3188. if (sc)
  3189. return sc.ToHr();
  3190. BOOL bFlag = FALSE;
  3191. sc = _ScGetVerbState(pSelectedNode, MMC_VERB_PASTE, spTargetDataObject,
  3192. bScopeItemSelected, lCookie, /*bMultiSel*/FALSE, bFlag);
  3193. if (sc)
  3194. return sc.ToHr();
  3195. if (!bFlag)
  3196. return sc.ToHr();
  3197. // QI to see if it is MMC's data object
  3198. IMMCClipboardDataObjectPtr spMMCClipboardDataObj = pDataObjectToPaste;
  3199. if (spMMCClipboardDataObj)
  3200. {
  3201. // This is our own dataobject.
  3202. // 3. Get how, where it is created, and how many snapin objects are there.
  3203. DWORD dwSourceProcess = 0;
  3204. sc = spMMCClipboardDataObj->GetSourceProcessId( &dwSourceProcess );
  3205. if (sc)
  3206. return sc.ToHr();
  3207. // If from different process then ask snapin if it can handle out of proc dataobjects.
  3208. BOOL bSourceFromDifferentMMCProcess = ( dwSourceProcess != ::GetCurrentProcessId() );
  3209. DWORD dwNumObjects = 0;
  3210. sc = spMMCClipboardDataObj->GetCount(&dwNumObjects);
  3211. if (sc)
  3212. return sc.ToHr();
  3213. // 4. For each snapin object, get the dataobject and ask target item if
  3214. // it can allow the source to be pasted.
  3215. for (DWORD index = 0; index < dwNumObjects; ++index)
  3216. {
  3217. IDataObjectPtr spSourceDataObject;
  3218. DWORD dwFlags = 0;
  3219. sc = spMMCClipboardDataObj->GetDataObject( index, &spSourceDataObject, &dwFlags );
  3220. if (sc)
  3221. return sc.ToHr();
  3222. sc = ScCheckPointers(spSourceDataObject, E_UNEXPECTED);
  3223. if (sc)
  3224. return sc.ToHr();
  3225. // must have some operation allowed - else it is invalid entry
  3226. if ( dwFlags == 0 )
  3227. return (sc = E_UNEXPECTED).ToHr();
  3228. /*
  3229. * During construction of th MMCClipboardDataObject we have checked if
  3230. * cut/copy is enabled before adding the snapin dataobject.
  3231. * So we are sure now atleast cut or copy is enabled for each snapin
  3232. * object and we dont have to check this again.
  3233. */
  3234. bool bSnapinPasteAllowed = false;
  3235. bool bSnapinWantsCopyAsDefault = false;
  3236. sc = _ScQueryPaste (pSelectedNode, spTargetDataObject, spSourceDataObject,
  3237. bSourceFromDifferentMMCProcess, bSnapinPasteAllowed,
  3238. bSnapinWantsCopyAsDefault);
  3239. if (sc)
  3240. return sc.ToHr();
  3241. bPasteAllowed = bPasteAllowed || bSnapinPasteAllowed;
  3242. bCopyOperatationIsDefault = bCopyOperatationIsDefault || bSnapinWantsCopyAsDefault;
  3243. }
  3244. }
  3245. else
  3246. {
  3247. // We do not recognize the dataobject and we dont know if it is from
  3248. // this MMC process or from any other process. So do not ask snapin if
  3249. // it can handle outofproc dataobjects or not. (This is MMC1.2 legacy case).
  3250. sc = _ScQueryPaste (pSelectedNode, spTargetDataObject, pDataObjectToPaste,
  3251. /*bSourceFromDifferentMMCProcess = */ false,
  3252. bPasteAllowed, bCopyOperatationIsDefault);
  3253. if (sc)
  3254. return sc.ToHr();
  3255. }
  3256. return (sc.ToHr());
  3257. }
  3258. //+-------------------------------------------------------------------
  3259. //
  3260. // Member: CNodeCallback::_ScQueryPaste
  3261. //
  3262. // Synopsis: Send MMCN_QUERY_PASTE(2) to the snapin.
  3263. //
  3264. // Arguments: [pNode] - Owner of result pane.
  3265. // [spTargetDataObject] - Target object where we want to paste.
  3266. // [spSourceDataObject] - The object that we want to paste.
  3267. // [bSourceFromDifferentMMCProcess] -
  3268. // [bPasteAllowed] - out param
  3269. // [bCopyOperationIsDefault] - out param
  3270. //
  3271. // Returns: SC
  3272. //
  3273. //--------------------------------------------------------------------
  3274. SC CNodeCallback::_ScQueryPaste (CNode *pNode,
  3275. IDataObject *pTargetDataObject,
  3276. IDataObject *pSourceDataObject,
  3277. bool bSourceFromDifferentMMCProcess,
  3278. bool& bPasteAllowed,
  3279. bool& bCopyOperatationIsDefault)
  3280. {
  3281. DECLARE_SC(sc, _T("CNodeCallback::_ScQueryPaste"));
  3282. sc = ScCheckPointers(pNode, pTargetDataObject, pSourceDataObject);
  3283. if (sc)
  3284. return sc;
  3285. bCopyOperatationIsDefault = false;
  3286. bPasteAllowed = false;
  3287. CComponent* pCC = pNode->GetPrimaryComponent();
  3288. sc = ScCheckPointers(pCC, E_UNEXPECTED);
  3289. if (sc)
  3290. return sc.ToHr();
  3291. BOOL bCanPasteOutOfProcDataObject = FALSE;
  3292. sc = pCC->Notify(NULL, MMCN_CANPASTE_OUTOFPROC,
  3293. 0, reinterpret_cast<LPARAM>(&bCanPasteOutOfProcDataObject) );
  3294. // Snapins return E_* values so check if they are OK with above notification.
  3295. if ( sc != S_OK)
  3296. {
  3297. bCanPasteOutOfProcDataObject = false;
  3298. sc.Clear();
  3299. }
  3300. // Source from diff MMC process & cannot handle outofproc dataobjects then return.
  3301. if (bSourceFromDifferentMMCProcess && (! bCanPasteOutOfProcDataObject) )
  3302. return sc.ToHr();
  3303. // Send MMCN_QUERY_PASTE
  3304. DWORD dwFlags = 0;
  3305. sc = pCC->Notify(pTargetDataObject, MMCN_QUERY_PASTE,
  3306. reinterpret_cast<LPARAM>(pSourceDataObject),
  3307. reinterpret_cast<LPARAM>(&dwFlags));
  3308. if (sc)
  3309. {
  3310. // Clear any snapin returned errors.
  3311. sc.Clear();
  3312. return sc.ToHr();
  3313. }
  3314. if (sc == SC(S_OK))
  3315. bPasteAllowed = true;
  3316. bCopyOperatationIsDefault = (dwFlags & MMC_DEFAULT_OPERATION_COPY);
  3317. return (sc);
  3318. }
  3319. //+-------------------------------------------------------------------
  3320. //
  3321. // Member: CNodeCallback::Drop
  3322. //
  3323. // Synopsis: Given the drop object context & the source object to
  3324. // be dropped. Do paste operation.
  3325. //
  3326. // Arguments: [hNode] - The node owning the view.
  3327. // [bScope] - Selection on Scope or Result pane.
  3328. // [lCookie] - If result pane selected the cookie for selected result item.
  3329. // [pDataObjectToPaste] - The dataobject to be pasted.
  3330. // [bIsDragOperationMove]- Is the drag operation move or copy.
  3331. //
  3332. // Returns: HRESULT
  3333. //
  3334. //--------------------------------------------------------------------
  3335. STDMETHODIMP CNodeCallback::Drop (HNODE hNode, BOOL bScope, LPARAM lCookie, IDataObject *pDataObjectToPaste, BOOL bIsDragOperationMove)
  3336. {
  3337. DECLARE_SC(sc, _T("CNodeCallback::Drop"));
  3338. sc = ScCheckPointers(hNode, pDataObjectToPaste);
  3339. if (sc)
  3340. return sc.ToHr();
  3341. sc = ScPaste(hNode, bScope, lCookie, pDataObjectToPaste, TRUE, bIsDragOperationMove);
  3342. if (sc)
  3343. return sc.ToHr();
  3344. return (sc.ToHr());
  3345. }
  3346. //+-------------------------------------------------------------------
  3347. //
  3348. // Member: CNodeCallback::Paste
  3349. //
  3350. // Synopsis: Given the target where the clipboard object is to be
  3351. // pasted. Paste the object.
  3352. //
  3353. // Arguments: [hNode] - The node owning the view.
  3354. // [bScope] - Selection on Scope or Result pane.
  3355. // [lCookie] - If result pane selected the cookie for selected result item.
  3356. //
  3357. // Returns: HRESULT
  3358. //
  3359. //--------------------------------------------------------------------
  3360. STDMETHODIMP CNodeCallback::Paste (HNODE hNode, BOOL bScope, LPARAM lCookie)
  3361. {
  3362. DECLARE_SC(sc, _T("CNodeCallback::Paste"));
  3363. sc = ScCheckPointers(hNode);
  3364. if (sc)
  3365. return sc.ToHr();
  3366. IDataObjectPtr spDOPaste;
  3367. sc = OleGetClipboard(&spDOPaste);
  3368. if (sc)
  3369. return sc.ToHr();
  3370. sc = ScCheckPointers(spDOPaste, E_UNEXPECTED);
  3371. if (sc)
  3372. return sc.ToHr();
  3373. sc = ScPaste(hNode, bScope, lCookie, spDOPaste, /*bDragDrop*/FALSE, FALSE);
  3374. if (sc)
  3375. return sc.ToHr();
  3376. return (sc.ToHr());
  3377. }
  3378. //+-------------------------------------------------------------------
  3379. //
  3380. // Member: CNodeCallback::ScPaste
  3381. //
  3382. // Synopsis: Given the current drop target (or paste target) context
  3383. // paste the given data object if it is drag&drop operation
  3384. // else paste the one from clipboard.
  3385. //
  3386. // Arguments: [hNode] - The node owning the view.
  3387. // [bScopePaneSelected] - Selection on Scope or Result pane.
  3388. // [lCookie] - If result pane selected the cookie for selected result item.
  3389. // [pDataObjectToPaste] - The dataobject to be pasted.
  3390. // [bDragDrop] - Is the operation drag & drop operation.
  3391. // [bIsDragOperationMove]- Is the drag operation move or copy.
  3392. //
  3393. // Returns: SC
  3394. //
  3395. //--------------------------------------------------------------------
  3396. SC CNodeCallback::ScPaste (HNODE hNode, BOOL bScopePaneSelected, LPARAM lCookie,
  3397. IDataObject *pDataObjectToPaste, BOOL bDragDrop,
  3398. BOOL bIsDragOperationMove)
  3399. {
  3400. DECLARE_SC(sc, _T("CNodeCallback::Paste"));
  3401. sc = ScCheckPointers(hNode, pDataObjectToPaste);
  3402. if (sc)
  3403. return sc;
  3404. CNode *pNode = CNode::FromHandle(hNode);
  3405. sc = ScCheckPointers(pNode, E_UNEXPECTED);
  3406. if (sc)
  3407. return sc;
  3408. // If result-pane cookie should be valid.
  3409. BOOL bScopeItemSelected;
  3410. CNode *pSelectedNode = NULL;
  3411. MMC_COOKIE cookie = -1;
  3412. sc = CNodeCallback::ScExtractLVData(pNode, bScopePaneSelected, lCookie,
  3413. &pSelectedNode, bScopeItemSelected, cookie);
  3414. if (sc)
  3415. return sc;
  3416. sc = ScCheckPointers(pSelectedNode, E_UNEXPECTED);
  3417. if (sc)
  3418. return sc;
  3419. if ( (FALSE == bScopeItemSelected) && (cookie == LVDATA_ERROR) )
  3420. return (sc = E_FAIL);
  3421. CViewData *pViewData = pSelectedNode->GetViewData();
  3422. sc = ScCheckPointers(pViewData, E_UNEXPECTED);
  3423. if (sc)
  3424. return sc;
  3425. // Do not allow paste into OCX/WEB/Multiselection
  3426. // We can allow paste into OCX/WEB if we expose IMMCClipboardDataObject
  3427. // interface. But paste into Multiselection should not be allowed as
  3428. // it is not intuitive.
  3429. if ( (!bScopeItemSelected) && IS_SPECIAL_COOKIE(lCookie))
  3430. return sc;
  3431. /*
  3432. * In MMC1.2 the drop target is always scope node. In MMC2.0
  3433. * it can be any result item.
  3434. * Make sure if the snapin has RVTI_LIST_OPTIONS_ALLOWPASTE.
  3435. */
  3436. if ( (bScopeItemSelected == FALSE) && (! (RVTI_LIST_OPTIONS_ALLOWPASTE & pViewData->GetListOptions())) )
  3437. {
  3438. ASSERT(0 && "UNEXPECTED: We can paste only into a folder!");
  3439. // We can paste only into a folder.
  3440. return (sc = E_FAIL);
  3441. }
  3442. if (pSelectedNode->IsInitialized() == FALSE)
  3443. {
  3444. sc = _InitializeNode(pSelectedNode);
  3445. if (sc)
  3446. return sc;
  3447. }
  3448. IDataObject* pTargetDataObject = NULL;
  3449. sc = pSelectedNode->ScGetDropTargetDataObject(bScopeItemSelected, lCookie, &pTargetDataObject);
  3450. if (sc)
  3451. return sc;
  3452. IDataObjectPtr spTargetDataObject;
  3453. if (! IS_SPECIAL_DATAOBJECT(pTargetDataObject))
  3454. spTargetDataObject = pTargetDataObject; // Addref the object
  3455. sc = ScCheckPointers(pTargetDataObject, E_UNEXPECTED);
  3456. if (sc)
  3457. return sc;
  3458. // QI to see if it is MMC's data object
  3459. IMMCClipboardDataObjectPtr spMMCClipboardDataObj = pDataObjectToPaste;
  3460. if (spMMCClipboardDataObj)
  3461. {
  3462. // This is our own dataobject.
  3463. // 3. Get how, where it is created, and how many snapin objects are there.
  3464. DATA_SOURCE_ACTION eSourceAction;
  3465. sc = spMMCClipboardDataObj->GetAction( &eSourceAction );
  3466. if (sc)
  3467. return sc;
  3468. BOOL bIsCreatedForCut = FALSE;
  3469. BOOL bIsCreatedForCopy = FALSE;
  3470. if (bDragDrop)
  3471. {
  3472. bIsCreatedForCut = bIsDragOperationMove;
  3473. bIsCreatedForCopy = !bIsDragOperationMove;
  3474. }
  3475. else
  3476. {
  3477. bIsCreatedForCut = ( eSourceAction == ACTION_CUT );
  3478. bIsCreatedForCopy = ( eSourceAction == ACTION_COPY );
  3479. }
  3480. DWORD dwNumObjects = 0;
  3481. sc = spMMCClipboardDataObj->GetCount(&dwNumObjects);
  3482. if (sc)
  3483. return sc;
  3484. BOOL bDoCutOperation = FALSE;
  3485. BOOL bDoCopyOperation = FALSE;
  3486. // 4. For each snapin object, get the dataobject and ask target to paste it.
  3487. // need to form the array of copy objects, so that we do not delete them while
  3488. // processing - this invalidates data object and prevents accessing the rest of
  3489. // items
  3490. std::vector<IDataObjectPtr> vecObjectsToCopy;
  3491. std::vector<DWORD> vecObjectFlags;
  3492. vecObjectsToCopy.reserve(dwNumObjects); // small optimization
  3493. vecObjectFlags.reserve(dwNumObjects); // small optimization
  3494. // fill with data objects to copy
  3495. for (DWORD index = 0; index < dwNumObjects; ++index)
  3496. {
  3497. IDataObjectPtr spSourceDataObject;
  3498. DWORD dwFlags = 0;
  3499. sc = spMMCClipboardDataObj->GetDataObject( index, &spSourceDataObject, &dwFlags );
  3500. if (sc)
  3501. return sc;
  3502. vecObjectsToCopy.push_back( spSourceDataObject );
  3503. vecObjectFlags.push_back( dwFlags );
  3504. }
  3505. // perform action on the data
  3506. for (index = 0; index < dwNumObjects; ++index)
  3507. {
  3508. IDataObjectPtr spSourceDataObject = vecObjectsToCopy[index];
  3509. DWORD dwFlags = vecObjectFlags[index];
  3510. sc = ScCheckPointers(spSourceDataObject, E_UNEXPECTED);
  3511. if (sc)
  3512. return sc;
  3513. BOOL bHasCutEnabled = ( dwFlags & MOVE_ALLOWED );
  3514. BOOL bHasCopyEnabled = ( dwFlags & COPY_ALLOWED );
  3515. /*
  3516. * In case of multiselection even if one of the selected
  3517. * object enables cut, the cut operation can be performed.
  3518. *
  3519. * But when we paste the objects we need to see if source
  3520. * enabled cut or not. If it did not enable then do nothing.
  3521. *
  3522. * Below is a table for this.
  3523. *
  3524. * Source object enables (only)
  3525. * -------------------------------------------
  3526. * |Operation | Cut | Copy |
  3527. * -------------------------------------------
  3528. * | | | |
  3529. * | Cut | Cut | Do nothing |
  3530. * Current | | | |
  3531. * Operation|-----------------------------------------
  3532. * | | | |
  3533. * | Copy | Do nothing | Copy |
  3534. * | | | |
  3535. * -------------------------------------------
  3536. */
  3537. bDoCutOperation = (bIsCreatedForCut && bHasCutEnabled);
  3538. bDoCopyOperation = (bIsCreatedForCopy && bHasCopyEnabled);
  3539. // See above table: this is "Do nothing".
  3540. if ( (!bDoCutOperation) && (!bDoCopyOperation) )
  3541. continue;
  3542. IDataObjectPtr spCutDataObject;
  3543. sc = _ScPaste (pSelectedNode, pTargetDataObject,
  3544. spSourceDataObject, &spCutDataObject,
  3545. bDoCutOperation );
  3546. if (sc)
  3547. return sc;
  3548. // remove cut items when required
  3549. if (bDoCutOperation && spCutDataObject != NULL)
  3550. {
  3551. sc = spMMCClipboardDataObj->RemoveCutItems( index, spCutDataObject );
  3552. if (sc)
  3553. return sc;
  3554. }
  3555. }
  3556. // If this is cut operation that is initiated by cut/copy/paste and
  3557. // not by drag & drop operation then the dataobject in clipboard is
  3558. // ours. So clear the clipboard so that we dont use that dataobject.
  3559. if ( eSourceAction == ACTION_CUT )
  3560. OleSetClipboard(NULL);
  3561. }
  3562. else
  3563. {
  3564. // We do not recognize the dataobject and we dont know if it is from
  3565. // this MMC process or from any other process. We cannot decode this
  3566. // dataobject so we just send MMCN_PASTE and ignore any dataobject
  3567. // retuned by snapin for cut operation (this is legacy case).
  3568. // for drag operation we can give a hint to snapin
  3569. // what operation (copy/move) was attempted.
  3570. // however we are not ensuring deletion of source items
  3571. bool bCutOrMove = (bDragDrop && bIsDragOperationMove);
  3572. IDataObjectPtr spCutDataObject;
  3573. sc = _ScPaste (pSelectedNode, pTargetDataObject,
  3574. pDataObjectToPaste, &spCutDataObject,
  3575. bCutOrMove );
  3576. if (sc)
  3577. return sc;
  3578. }
  3579. return sc;
  3580. }
  3581. //+-------------------------------------------------------------------
  3582. //
  3583. // Member: CNodeCallback::_ScPaste
  3584. //
  3585. // Synopsis: Send MMCN_PASTE to snapin.
  3586. //
  3587. // Arguments: [pNode] - Owner of resultpane.
  3588. // [pTargetDataObject] - target where we need to paste.
  3589. // [pSourceDataObject] - source to be pasted.
  3590. // [ppCutDataObject] - (out) cut items
  3591. // [bCutOrMove]
  3592. //
  3593. // Returns: SC
  3594. //
  3595. //--------------------------------------------------------------------
  3596. SC CNodeCallback::_ScPaste (CNode *pNode,
  3597. IDataObject *pTargetDataObject,
  3598. IDataObject *pSourceDataObject,
  3599. IDataObject **ppCutDataObject,
  3600. bool bCutOrMove)
  3601. {
  3602. DECLARE_SC(sc, _T("CNodeCallback::_ScSendPasteNotification"));
  3603. sc = ScCheckPointers(pNode, pTargetDataObject, pSourceDataObject, ppCutDataObject);
  3604. if (sc)
  3605. return sc;
  3606. // init out param
  3607. *ppCutDataObject = NULL;
  3608. CComponent* pComponent = pNode->GetPrimaryComponent();
  3609. sc = ScCheckPointers(pComponent, E_UNEXPECTED);
  3610. if (sc)
  3611. return sc;
  3612. IDataObject* pDataObjectToBeCutBySource = NULL;
  3613. sc = pComponent->Notify(pTargetDataObject, MMCN_PASTE,
  3614. reinterpret_cast<LPARAM>(pSourceDataObject),
  3615. bCutOrMove ? reinterpret_cast<LPARAM>(&pDataObjectToBeCutBySource) : NULL);
  3616. if (sc)
  3617. return sc;
  3618. if (! bCutOrMove)
  3619. return sc;
  3620. // Exchange returns NULL dataobject. Do not trace error to be compatible with MMC1.2
  3621. if ( (pDataObjectToBeCutBySource) && (IS_SPECIAL_DATAOBJECT(pDataObjectToBeCutBySource) ) )
  3622. return (sc = E_UNEXPECTED);
  3623. // transfer control to the client ( no addref nor release in neaded )
  3624. *ppCutDataObject = pDataObjectToBeCutBySource;
  3625. return (sc);
  3626. }
  3627. //+-------------------------------------------------------------------
  3628. //
  3629. // Member: CNodeCallback::QueryViewSettingsPersistor
  3630. //
  3631. // Synopsis: Get the IPersistStream interface of CViewSettingsPersistor
  3632. // object to load the viewsettings (will not be asked for
  3633. // storing as saving is always XML format).
  3634. //
  3635. // Arguments: [ppStream] - [out]
  3636. //
  3637. // Returns: HRESULT
  3638. //
  3639. //--------------------------------------------------------------------
  3640. STDMETHODIMP CNodeCallback::QueryViewSettingsPersistor (IPersistStream** ppStream)
  3641. {
  3642. DECLARE_SC(sc, _T("CNodeCallback::QueryViewSettingsPersistor"));
  3643. sc = ScCheckPointers(ppStream);
  3644. if (sc)
  3645. return sc.ToHr();
  3646. *ppStream = NULL;
  3647. // Call CNode static method to get IPersistStream interface.
  3648. sc = CNode::ScQueryViewSettingsPersistor(ppStream);
  3649. if (sc)
  3650. return sc.ToHr();
  3651. return (sc.ToHr());
  3652. }
  3653. //+-------------------------------------------------------------------
  3654. //
  3655. // Member: CNodeCallback::QueryViewSettingsPersistor
  3656. //
  3657. // Synopsis: Get the CXMLObject interface of CViewSettingsPersistor
  3658. // object to save/load the viewsettings from XML console file.
  3659. //
  3660. // Arguments: [ppXMLObject] - [out]
  3661. //
  3662. // Returns: HRESULT
  3663. //
  3664. //--------------------------------------------------------------------
  3665. STDMETHODIMP CNodeCallback::QueryViewSettingsPersistor (CXMLObject** ppXMLObject)
  3666. {
  3667. DECLARE_SC(sc, _T("CNodeCallback::QueryViewSettingsPersistor"));
  3668. sc = ScCheckPointers(ppXMLObject);
  3669. if (sc)
  3670. return sc.ToHr();
  3671. *ppXMLObject = NULL;
  3672. // Call CNode static method to get CXMLObject interface.
  3673. sc = CNode::ScQueryViewSettingsPersistor(ppXMLObject);
  3674. if (sc)
  3675. return sc.ToHr();
  3676. return (sc.ToHr());
  3677. }
  3678. //+-------------------------------------------------------------------
  3679. //
  3680. // Member: CNodeCallback::DocumentClosing
  3681. //
  3682. // Synopsis: The document is to be closed, so release any document
  3683. // related objects. (CViewSettingsPersistor).
  3684. //
  3685. // Arguments: None
  3686. //
  3687. // Returns: HRESULT
  3688. //
  3689. //--------------------------------------------------------------------
  3690. STDMETHODIMP CNodeCallback::DocumentClosing ()
  3691. {
  3692. DECLARE_SC(sc, _T("CNodeCallback::DocumentClosing"));
  3693. // 1. Call CNode static method informing document closing.
  3694. sc = CNode::ScOnDocumentClosing();
  3695. if (sc)
  3696. return sc.ToHr();
  3697. return (sc.ToHr());
  3698. }