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.

1345 lines
35 KiB

  1. /**********************************************************************/
  2. /** Microsoft Windows/NT **/
  3. /** Copyright(c) Microsoft Corporation, 1997 - 1999 **/
  4. /**********************************************************************/
  5. /*
  6. Winshand.cpp
  7. WINS specifc handler base classes
  8. FILE HISTORY:
  9. */
  10. #include "stdafx.h"
  11. #include "winshand.h"
  12. #include "snaputil.h"
  13. MMC_CONSOLE_VERB g_ConsoleVerbs[] =
  14. {
  15. MMC_VERB_OPEN,
  16. MMC_VERB_COPY,
  17. MMC_VERB_PASTE,
  18. MMC_VERB_DELETE,
  19. MMC_VERB_PROPERTIES,
  20. MMC_VERB_RENAME,
  21. MMC_VERB_REFRESH,
  22. MMC_VERB_PRINT
  23. };
  24. #define HI HIDDEN
  25. #define EN ENABLED
  26. // StatusRemove
  27. MMC_BUTTON_STATE g_ConsoleVerbStates[WINSSNAP_NODETYPE_MAX][ARRAYLEN(g_ConsoleVerbs)] =
  28. {
  29. {HI, HI, HI, HI, EN, HI, HI, HI}, // WINSSNAP_ROOT
  30. {HI, HI, HI, EN, EN, HI, EN, HI}, // WINSSNAP_SERVER
  31. {HI, HI, HI, HI, HI, HI, EN, HI}, // WINSSNAP_ACTIVEREG
  32. {HI, HI, HI, HI, EN, HI, EN, HI}, // WINSSNAP_REPLICATION_PARTNERS
  33. {HI, HI, HI, HI, EN, HI, EN, HI}, // WINSSNAP_SERVER_STATUS
  34. {HI, HI, HI, EN, EN, HI, HI, HI}, // WINSSNAP_REGISTRATION
  35. {HI, HI, HI, EN, EN, HI, HI, HI}, // WINSSNAP_REPLICATION_PARTNER
  36. {HI, HI, HI, HI, HI, HI, HI, HI} // WINSSNAP_STATUS_LEAF_NODE
  37. };
  38. //Status Remove
  39. MMC_BUTTON_STATE g_ConsoleVerbStatesMultiSel[WINSSNAP_NODETYPE_MAX][ARRAYLEN(g_ConsoleVerbs)] =
  40. {
  41. {HI, HI, HI, HI, HI, HI, HI, HI}, // WINSSNAP_ROOT
  42. {HI, HI, HI, HI, HI, HI, HI, HI}, // WINSSNAP_SERVER
  43. {HI, HI, HI, HI, HI, HI, EN, HI}, // WINSSNAP_ACTIVEREG
  44. {HI, HI, HI, EN, HI, HI, HI, HI}, // WINSSNAP_REPLICATION_PARTNERS
  45. {HI, HI, HI, HI, HI, HI, HI, HI}, // WINSSNAP_SERVER_STATUS
  46. {HI, HI, HI, EN, HI, HI, HI, HI}, // WINSSNAP_REGISTRATION
  47. {HI, HI, HI, EN, HI, HI, HI, HI}, // WINSSNAP_REPLICATION_PARTNER
  48. {HI, HI, HI, HI, HI, HI, HI, HI} // WINSSNAP_STATUS_LEAF_NODE
  49. };
  50. // Help ID array for help on scope items
  51. DWORD g_dwMMCHelp[WINSSNAP_NODETYPE_MAX] =
  52. {
  53. WINSSNAP_HELP_ROOT, // WINSSNAP_ROOT
  54. WINSSNAP_HELP_SERVER, // WINSSNAP_SERVER
  55. WINSSNAP_HELP_ACT_REG_NODE, // WINSSNAP_ACTIVEREG
  56. WINSSNAP_HELP_REP_PART_NODE, // WINSSNAP_REPLICATION_PARTNERS
  57. WINSSNAP_HELP_ACTREG_ENTRY, // WINSSNAP_SCOPE
  58. WINSSNAP_HELP_REP_PART_ENTRY // WINSSNAP_REPLICATION_PARTNER
  59. };
  60. /*---------------------------------------------------------------------------
  61. Class: CMTWinsHandler
  62. ---------------------------------------------------------------------------*/
  63. //
  64. // Called by the result handler when a command comes in that isn't handled
  65. // by the result handler. If appropriate it passes it to the scope pane hander.
  66. //
  67. HRESULT
  68. CMTWinsHandler::HandleScopeCommand
  69. (
  70. MMC_COOKIE cookie,
  71. int nCommandID,
  72. LPDATAOBJECT pDataObject
  73. )
  74. {
  75. HRESULT hr = hrOK;
  76. SPITFSNode spNode;
  77. DATA_OBJECT_TYPES dwType = CCT_RESULT;
  78. if (IS_SPECIAL_DATAOBJECT(pDataObject))
  79. {
  80. dwType = CCT_SCOPE;
  81. }
  82. else
  83. {
  84. if (pDataObject)
  85. {
  86. SPINTERNAL spInternal;
  87. spInternal = ::ExtractInternalFormat(pDataObject);
  88. if (spInternal)
  89. dwType = spInternal->m_type;
  90. }
  91. }
  92. if (dwType == CCT_SCOPE)
  93. {
  94. // call the handler to take care of this
  95. CORg (m_spNodeMgr->FindNode(cookie, &spNode));
  96. hr = OnCommand(spNode, nCommandID, dwType, pDataObject, (ULONG) spNode->GetData(TFS_DATA_TYPE));
  97. }
  98. Error:
  99. return hr;
  100. }
  101. //
  102. // Called by the result handler to add the scope pane menu items to the menu
  103. // where appropriate. Puts scope pane menu items in when action menu is clicked
  104. // and the message view has focus as well as when a right click happens in the white
  105. // space of the result pane.
  106. //
  107. HRESULT
  108. CMTWinsHandler::HandleScopeMenus
  109. (
  110. MMC_COOKIE cookie,
  111. LPDATAOBJECT pDataObject,
  112. LPCONTEXTMENUCALLBACK pContextMenuCallback,
  113. long * pInsertionAllowed
  114. )
  115. {
  116. HRESULT hr = hrOK;
  117. SPITFSNode spNode;
  118. DATA_OBJECT_TYPES dwType = CCT_RESULT;
  119. if (IS_SPECIAL_DATAOBJECT(pDataObject))
  120. {
  121. dwType = CCT_SCOPE;
  122. }
  123. else
  124. {
  125. if (pDataObject)
  126. {
  127. SPINTERNAL spInternal;
  128. spInternal = ::ExtractInternalFormat(pDataObject);
  129. if (spInternal)
  130. dwType = spInternal->m_type;
  131. }
  132. }
  133. if (dwType == CCT_SCOPE)
  134. {
  135. // call the normal handler to put up the menu items
  136. CORg (m_spNodeMgr->FindNode(cookie, &spNode));
  137. hr = OnAddMenuItems(spNode, pContextMenuCallback, pDataObject, CCT_SCOPE, (ULONG) spNode->GetData(TFS_DATA_TYPE), pInsertionAllowed);
  138. }
  139. Error:
  140. return hr;
  141. }
  142. /*---------------------------------------------------------------------------
  143. CMTWinsHandler::OnChangeState
  144. Description
  145. Author: EricDav
  146. ---------------------------------------------------------------------------*/
  147. void CMTWinsHandler::OnChangeState
  148. (
  149. ITFSNode * pNode
  150. )
  151. {
  152. // Increment the state to the next position
  153. switch (m_nState)
  154. {
  155. case notLoaded:
  156. case loaded:
  157. case unableToLoad:
  158. {
  159. m_nState = loading;
  160. m_dwErr = 0;
  161. }
  162. break;
  163. case loading:
  164. {
  165. m_nState = (m_dwErr != 0) ? unableToLoad : loaded;
  166. if (m_dwErr)
  167. {
  168. CString strTitle, strBody;
  169. IconIdentifier icon;
  170. GetErrorInfo(strTitle, strBody, &icon);
  171. ShowMessage(pNode, strTitle, strBody, icon);
  172. }
  173. else
  174. {
  175. ClearMessage(pNode);
  176. }
  177. m_fSilent = FALSE;
  178. }
  179. break;
  180. default:
  181. ASSERT(FALSE);
  182. }
  183. // check to make sure we are still the visible node in the UI
  184. if (m_bSelected)
  185. {
  186. UpdateStandardVerbs(pNode, pNode->GetData(TFS_DATA_TYPE));
  187. }
  188. // Now check and see if there is a new image for this state for this handler
  189. int nImage, nOpenImage;
  190. nImage = GetImageIndex(FALSE);
  191. nOpenImage = GetImageIndex(TRUE);
  192. if (nImage >= 0)
  193. pNode->SetData(TFS_DATA_IMAGEINDEX, nImage);
  194. if (nOpenImage >= 0)
  195. pNode->SetData(TFS_DATA_OPENIMAGEINDEX, nOpenImage);
  196. VERIFY(SUCCEEDED(pNode->ChangeNode(SCOPE_PANE_CHANGE_ITEM_ICON)));
  197. }
  198. /*!--------------------------------------------------------------------------
  199. CMTWinsHandler::UpdateStandardVerbs
  200. Tells the IComponent to update the verbs for this node
  201. Author: EricDav
  202. ---------------------------------------------------------------------------*/
  203. void
  204. CMTWinsHandler::UpdateStandardVerbs
  205. (
  206. ITFSNode * pNode,
  207. LONG_PTR dwNodeType
  208. )
  209. {
  210. HRESULT hr = hrOK;
  211. SPIComponentData spCompData;
  212. SPIConsole spConsole;
  213. IDataObject* pDataObject;
  214. m_spNodeMgr->GetComponentData(&spCompData);
  215. CORg ( spCompData->QueryDataObject(NULL, CCT_RESULT, &pDataObject) );
  216. CORg ( m_spNodeMgr->GetConsole(&spConsole) );
  217. CORg ( spConsole->UpdateAllViews(pDataObject,
  218. dwNodeType,
  219. RESULT_PANE_UPDATE_VERBS) );
  220. pDataObject->Release();
  221. Error:
  222. return;
  223. }
  224. /*---------------------------------------------------------------------------
  225. CMTWinsHandler::OnResultDelete
  226. Description
  227. Author: EricDav
  228. ---------------------------------------------------------------------------*/
  229. HRESULT
  230. CMTWinsHandler::OnResultDelete
  231. (
  232. ITFSComponent * pComponent,
  233. LPDATAOBJECT pDataObject,
  234. MMC_COOKIE cookie,
  235. LPARAM arg,
  236. LPARAM lParam
  237. )
  238. {
  239. HRESULT hr = hrOK;
  240. Trace0("CMTWinsHandler::OnResultDelete received\n");
  241. // translate this call to the parent and let it handle deletion
  242. // of result pane items
  243. SPITFSNode spNode, spParent;
  244. SPITFSResultHandler spParentRH;
  245. CORg (m_spNodeMgr->FindNode(cookie, &spNode));
  246. CORg (spNode->GetParent(&spParent));
  247. if (spParent == NULL)
  248. return hr;
  249. CORg (spParent->GetResultHandler(&spParentRH));
  250. CORg (spParentRH->Notify(pComponent, spParent->GetData(TFS_DATA_COOKIE), pDataObject, MMCN_DELETE, arg, lParam));
  251. Error:
  252. return hr;
  253. }
  254. /*!--------------------------------------------------------------------------
  255. CMTWinsHandler::UpdateConsoleVerbs
  256. Updates the standard verbs depending upon the state of the node
  257. Author: EricDav
  258. ---------------------------------------------------------------------------*/
  259. void
  260. CMTWinsHandler::UpdateConsoleVerbs
  261. (
  262. IConsoleVerb * pConsoleVerb,
  263. LONG_PTR dwNodeType,
  264. BOOL bMultiSelect
  265. )
  266. {
  267. BOOL bStates[ARRAYLEN(g_ConsoleVerbs)];
  268. MMC_BUTTON_STATE * ButtonState;
  269. int i;
  270. if (bMultiSelect)
  271. {
  272. ButtonState = g_ConsoleVerbStatesMultiSel[dwNodeType];
  273. for (i = 0; i < ARRAYLEN(g_ConsoleVerbs); bStates[i++] = TRUE);
  274. }
  275. else
  276. {
  277. ButtonState = g_ConsoleVerbStates[dwNodeType];
  278. for (i = 0; i < ARRAYLEN(g_ConsoleVerbs); bStates[i++] = TRUE);
  279. switch (m_nState)
  280. {
  281. case loaded:
  282. for (i = 0; i < ARRAYLEN(g_ConsoleVerbs); bStates[i++] = TRUE);
  283. break;
  284. case notLoaded:
  285. case loading:
  286. for (i = 0; i < ARRAYLEN(g_ConsoleVerbs); bStates[i++] = FALSE);
  287. break;
  288. case unableToLoad:
  289. for (i = 0; i < ARRAYLEN(g_ConsoleVerbs); bStates[i++] = FALSE);
  290. bStates[MMC_VERB_REFRESH & 0x000F] = TRUE;
  291. bStates[MMC_VERB_DELETE & 0x000F] = TRUE;
  292. break;
  293. }
  294. }
  295. EnableVerbs(pConsoleVerb, ButtonState, bStates);
  296. }
  297. /*!--------------------------------------------------------------------------
  298. CMTWinsHandler::EnableVerbs
  299. Enables the toolbar buttons
  300. Author: EricDav
  301. ---------------------------------------------------------------------------*/
  302. void
  303. CMTWinsHandler::EnableVerbs
  304. (
  305. IConsoleVerb * pConsoleVerb,
  306. MMC_BUTTON_STATE ButtonState[],
  307. BOOL bState[]
  308. )
  309. {
  310. if (pConsoleVerb == NULL)
  311. {
  312. Assert(FALSE);
  313. return;
  314. }
  315. for (int i=0; i < ARRAYLEN(g_ConsoleVerbs); ++i)
  316. {
  317. if (ButtonState[i] == ENABLED)
  318. {
  319. // unhide this button before enabling
  320. pConsoleVerb->SetVerbState(g_ConsoleVerbs[i],
  321. HIDDEN,
  322. FALSE);
  323. pConsoleVerb->SetVerbState(g_ConsoleVerbs[i],
  324. ButtonState[i],
  325. bState[i]);
  326. }
  327. else
  328. {
  329. // hide this button
  330. pConsoleVerb->SetVerbState(g_ConsoleVerbs[i],
  331. HIDDEN,
  332. TRUE);
  333. }
  334. }
  335. pConsoleVerb->SetDefaultVerb(m_verbDefault);
  336. }
  337. /*!--------------------------------------------------------------------------
  338. CMTWinsHandler::ExpandNode
  339. Expands/compresses this node
  340. Author: EricDav
  341. ---------------------------------------------------------------------------*/
  342. void
  343. CMTWinsHandler::ExpandNode
  344. (
  345. ITFSNode * pNode,
  346. BOOL fExpand
  347. )
  348. {
  349. SPIComponentData spCompData;
  350. SPIDataObject spDataObject;
  351. LPDATAOBJECT pDataObject;
  352. SPIConsole spConsole;
  353. HRESULT hr = hrOK;
  354. // don't expand the node if we are handling the EXPAND_SYNC message,
  355. // this screws up the insertion of item, getting duplicates.
  356. if (!m_fExpandSync)
  357. {
  358. m_spNodeMgr->GetComponentData(&spCompData);
  359. CORg ( spCompData->QueryDataObject((MMC_COOKIE) pNode, CCT_SCOPE, &pDataObject) );
  360. spDataObject = pDataObject;
  361. CORg ( m_spNodeMgr->GetConsole(&spConsole) );
  362. CORg ( spConsole->UpdateAllViews(pDataObject, TRUE, RESULT_PANE_EXPAND) );
  363. }
  364. Error:
  365. return;
  366. }
  367. /*!--------------------------------------------------------------------------
  368. CMTWinsHandler::OnExpandSync
  369. Handles the MMCN_EXPANDSYNC notifcation
  370. We need to do syncronous enumeration. We'll fire off the background
  371. thread like before, but we'll wait for it to exit before we return.
  372. Author: EricDav
  373. ---------------------------------------------------------------------------*/
  374. HRESULT
  375. CMTWinsHandler::OnExpandSync
  376. (
  377. ITFSNode * pNode,
  378. LPDATAOBJECT pDataObject,
  379. LPARAM arg,
  380. LPARAM lParam
  381. )
  382. {
  383. HRESULT hr = hrOK;
  384. MSG msg;
  385. m_fExpandSync = TRUE;
  386. hr = OnExpand(pNode, pDataObject, CCT_SCOPE, arg, lParam);
  387. // wait for the background thread to exit
  388. WaitForSingleObject(m_hThread, INFINITE);
  389. // The background thread posts messages to a hidden window to
  390. // pass data back to the main thread. The messages won't go through since we are
  391. // blocking the main thread. The data goes on a queue in the query object
  392. // which the handler has a pointer to so we can just fake the notification.
  393. if (m_spQuery.p)
  394. OnNotifyHaveData((LPARAM) m_spQuery.p);
  395. // Tell MMC we handled this message
  396. MMC_EXPANDSYNC_STRUCT * pES = reinterpret_cast<MMC_EXPANDSYNC_STRUCT *>(lParam);
  397. if (pES)
  398. pES->bHandled = TRUE;
  399. m_fExpandSync = FALSE;
  400. return hr;
  401. }
  402. /*!--------------------------------------------------------------------------
  403. CMTWinsHandler::OnResultSelect
  404. Handles the MMCN_SELECT notifcation
  405. Author: EricDav
  406. ---------------------------------------------------------------------------*/
  407. HRESULT
  408. CMTWinsHandler::OnResultSelect
  409. (
  410. ITFSComponent * pComponent,
  411. LPDATAOBJECT pDataObject,
  412. MMC_COOKIE cookie,
  413. LPARAM arg,
  414. LPARAM lParam
  415. )
  416. {
  417. HRESULT hr = hrOK;
  418. SPIConsoleVerb spConsoleVerb;
  419. SPITFSNode spNode;
  420. SPINTERNAL spInternal;
  421. BOOL bMultiSelect = FALSE;
  422. BOOL bScope = (BOOL) LOWORD(arg);
  423. BOOL bSelect = (BOOL) HIWORD(arg);
  424. m_bSelected = bSelect;
  425. CORg (pComponent->GetConsoleVerb(&spConsoleVerb));
  426. spInternal = ::ExtractInternalFormat(pDataObject);
  427. if (spInternal &&
  428. spInternal->m_cookie == MMC_MULTI_SELECT_COOKIE)
  429. {
  430. CORg (pComponent->GetSelectedNode(&spNode));
  431. bMultiSelect = TRUE;
  432. }
  433. else
  434. {
  435. CORg (m_spNodeMgr->FindNode(cookie, &spNode));
  436. }
  437. UpdateConsoleVerbs(spConsoleVerb, spNode->GetData(TFS_DATA_TYPE), bMultiSelect);
  438. Error:
  439. return hr;
  440. }
  441. /*!--------------------------------------------------------------------------
  442. CMTWinsHandler::OnCreateDataObject
  443. -
  444. Author: EricDav
  445. ---------------------------------------------------------------------------*/
  446. STDMETHODIMP
  447. CMTWinsHandler::OnCreateDataObject
  448. (
  449. ITFSComponent * pComponent,
  450. MMC_COOKIE cookie,
  451. DATA_OBJECT_TYPES type,
  452. IDataObject ** ppDataObject
  453. )
  454. {
  455. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  456. Assert(ppDataObject != NULL);
  457. CDataObject * pObject = NULL;
  458. SPIDataObject spDataObject;
  459. long lViewOptions;
  460. LPOLESTR pViewType;
  461. BOOL bVirtual;
  462. pObject = new CDataObject;
  463. spDataObject = pObject; // do this so that it gets released correctly
  464. Assert(pObject != NULL);
  465. if (cookie == MMC_MULTI_SELECT_COOKIE)
  466. {
  467. OnGetResultViewType(pComponent, cookie, &pViewType, &lViewOptions);
  468. bVirtual = (lViewOptions & MMC_VIEW_OPTIONS_OWNERDATALIST) ? TRUE : FALSE;
  469. CreateMultiSelectData(pComponent, pObject, bVirtual);
  470. }
  471. // Save cookie and type for delayed rendering
  472. pObject->SetType(type);
  473. pObject->SetCookie(cookie);
  474. // Store the coclass with the data object
  475. pObject->SetClsid(*(m_spTFSComponentData->GetCoClassID()));
  476. pObject->SetTFSComponentData(m_spTFSComponentData);
  477. return pObject->QueryInterface(IID_IDataObject,
  478. reinterpret_cast<void**>(ppDataObject));
  479. }
  480. /*!--------------------------------------------------------------------------
  481. CMTWinsHandler::CreateMultiSelectData
  482. -
  483. Author: EricDav
  484. ---------------------------------------------------------------------------*/
  485. HRESULT
  486. CMTWinsHandler::CreateMultiSelectData
  487. (
  488. ITFSComponent * pComponent,
  489. CDataObject * pObject,
  490. BOOL bVirtual
  491. )
  492. {
  493. HRESULT hr = hrOK;
  494. // build the list of selected nodes
  495. CTFSNodeList listSelectedNodes;
  496. CVirtualIndexArray arraySelectedIndicies;
  497. CGUIDArray rgGuids;
  498. UINT cb;
  499. GUID* pGuid;
  500. const GUID * pcGuid;
  501. int i;
  502. COM_PROTECT_TRY
  503. {
  504. if (bVirtual)
  505. {
  506. // build a list of the selected indicies in the virtual listbox
  507. CORg (BuildVirtualSelectedItemList(pComponent, &arraySelectedIndicies));
  508. // now call and get the GUIDs for each one
  509. for (i = 0; i < arraySelectedIndicies.GetSize(); i++)
  510. {
  511. pcGuid = GetVirtualGuid(arraySelectedIndicies[i]);
  512. if (pcGuid)
  513. rgGuids.AddUnique(*pcGuid);
  514. }
  515. }
  516. else
  517. {
  518. CORg (BuildSelectedItemList(pComponent, &listSelectedNodes));
  519. // collect all of the unique guids
  520. while (listSelectedNodes.GetCount() > 0)
  521. {
  522. SPITFSNode spCurNode;
  523. spCurNode = listSelectedNodes.RemoveHead();
  524. pcGuid = spCurNode->GetNodeType();
  525. rgGuids.AddUnique(*pcGuid);
  526. }
  527. }
  528. // now put the information in the data object
  529. cb = (UINT)(rgGuids.GetSize() * sizeof(GUID));
  530. if (cb > 0)
  531. {
  532. pObject->SetMultiSelDobj();
  533. pGuid = new GUID[(size_t)rgGuids.GetSize()];
  534. CopyMemory(pGuid, rgGuids.GetData(), cb);
  535. pObject->SetMultiSelData((BYTE*)pGuid, cb);
  536. }
  537. COM_PROTECT_ERROR_LABEL;
  538. }
  539. COM_PROTECT_CATCH
  540. return hr;
  541. }
  542. /*!--------------------------------------------------------------------------
  543. CMTWinsHandler::OnResultUpdateView
  544. Implementation of ITFSResultHandler::OnResultUpdateView
  545. Author: EricDav
  546. ---------------------------------------------------------------------------*/
  547. HRESULT CMTWinsHandler::OnResultUpdateView
  548. (
  549. ITFSComponent *pComponent,
  550. LPDATAOBJECT pDataObject,
  551. LPARAM data,
  552. LPARAM hint
  553. )
  554. {
  555. HRESULT hr = hrOK;
  556. if (hint == RESULT_PANE_UPDATE_VERBS)
  557. {
  558. SPIConsoleVerb spConsoleVerb;
  559. SPITFSNode spNode;
  560. CORg (pComponent->GetConsoleVerb(&spConsoleVerb));
  561. UpdateConsoleVerbs(spConsoleVerb, data);
  562. }
  563. else
  564. {
  565. return CBaseResultHandler::OnResultUpdateView(pComponent, pDataObject, data, hint);
  566. }
  567. Error:
  568. return hr;
  569. }
  570. /*!--------------------------------------------------------------------------
  571. CMTWinsHandler::OnResultContextHelp
  572. Implementation of ITFSResultHandler::OnResultContextHelp
  573. Author: v-shubk
  574. ---------------------------------------------------------------------------*/
  575. HRESULT
  576. CMTWinsHandler::OnResultContextHelp
  577. (
  578. ITFSComponent * pComponent,
  579. LPDATAOBJECT pDataObject,
  580. MMC_COOKIE cookie,
  581. LPARAM arg,
  582. LPARAM lParam
  583. )
  584. {
  585. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  586. HRESULT hr = hrOK;
  587. SPIDisplayHelp spDisplayHelp;
  588. SPIConsole spConsole;
  589. pComponent->GetConsole(&spConsole);
  590. hr = spConsole->QueryInterface (IID_IDisplayHelp, (LPVOID*) &spDisplayHelp);
  591. ASSERT (SUCCEEDED (hr));
  592. if ( SUCCEEDED (hr) )
  593. {
  594. LPCTSTR pszHelpFile = m_spTFSCompData->GetHTMLHelpFileName();
  595. if (pszHelpFile == NULL)
  596. goto Error;
  597. CString szHelpFilePath;
  598. UINT nLen = ::GetWindowsDirectory (szHelpFilePath.GetBufferSetLength(2 * MAX_PATH), 2 * MAX_PATH);
  599. if (nLen == 0)
  600. {
  601. hr = E_FAIL;
  602. goto Error;
  603. }
  604. szHelpFilePath.ReleaseBuffer();
  605. szHelpFilePath += g_szDefaultHelpTopic;
  606. hr = spDisplayHelp->ShowTopic (T2OLE ((LPTSTR)(LPCTSTR) szHelpFilePath));
  607. ASSERT (SUCCEEDED (hr));
  608. }
  609. Error:
  610. return hr;
  611. }
  612. /*!--------------------------------------------------------------------------
  613. CMTWinsHandler::SaveColumns
  614. -
  615. ---------------------------------------------------------------------------*/
  616. HRESULT
  617. CMTWinsHandler::SaveColumns
  618. (
  619. ITFSComponent * pComponent,
  620. MMC_COOKIE cookie,
  621. LPARAM arg,
  622. LPARAM lParam
  623. )
  624. {
  625. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  626. HRESULT hr = hrOK;
  627. LONG_PTR dwNodeType;
  628. int nCol = 0;
  629. int nColWidth;
  630. SPITFSNode spNode, spRootNode;
  631. SPIHeaderCtrl spHeaderCtrl;
  632. BOOL bDirty = FALSE;
  633. CORg (m_spNodeMgr->FindNode(cookie, &spNode));
  634. CORg (pComponent->GetHeaderCtrl(&spHeaderCtrl));
  635. dwNodeType = spNode->GetData(TFS_DATA_TYPE);
  636. while (aColumns[dwNodeType][nCol] != 0)
  637. {
  638. if (SUCCEEDED(spHeaderCtrl->GetColumnWidth(nCol, &nColWidth)) &&
  639. (aColumnWidths[dwNodeType][nCol] != nColWidth))
  640. {
  641. aColumnWidths[dwNodeType][nCol] = nColWidth;
  642. bDirty = TRUE;
  643. }
  644. nCol++;
  645. }
  646. if (bDirty)
  647. {
  648. CORg (m_spNodeMgr->GetRootNode(&spRootNode));
  649. spRootNode->SetData(TFS_DATA_DIRTY, TRUE);
  650. }
  651. Error:
  652. return hr;
  653. }
  654. /*---------------------------------------------------------------------------
  655. Class: CWinsHandler
  656. ---------------------------------------------------------------------------*/
  657. //
  658. // Called by the result handler when a command comes in that isn't handled
  659. // by the result handler. If appropriate it passes it to the scope pane hander.
  660. //
  661. HRESULT
  662. CWinsHandler::HandleScopeCommand
  663. (
  664. MMC_COOKIE cookie,
  665. int nCommandID,
  666. LPDATAOBJECT pDataObject
  667. )
  668. {
  669. HRESULT hr = hrOK;
  670. SPITFSNode spNode;
  671. DATA_OBJECT_TYPES dwType = CCT_RESULT;
  672. if (IS_SPECIAL_DATAOBJECT(pDataObject))
  673. {
  674. dwType = CCT_SCOPE;
  675. }
  676. else
  677. {
  678. if (pDataObject)
  679. {
  680. SPINTERNAL spInternal;
  681. spInternal = ::ExtractInternalFormat(pDataObject);
  682. if (spInternal)
  683. dwType = spInternal->m_type;
  684. }
  685. }
  686. if (dwType == CCT_SCOPE)
  687. {
  688. // call the handler to take care of this
  689. CORg (m_spNodeMgr->FindNode(cookie, &spNode));
  690. hr = OnCommand(spNode, nCommandID, dwType, pDataObject, (ULONG) spNode->GetData(TFS_DATA_TYPE));
  691. }
  692. Error:
  693. return hr;
  694. }
  695. //
  696. // Called by the result handler to add the scope pane menu items to the menu
  697. // where appropriate. Puts scope pane menu items in when action menu is clicked
  698. // and the message view has focus as well as when a right click happens in the white
  699. // space of the result pane.
  700. //
  701. HRESULT
  702. CWinsHandler::HandleScopeMenus
  703. (
  704. MMC_COOKIE cookie,
  705. LPDATAOBJECT pDataObject,
  706. LPCONTEXTMENUCALLBACK pContextMenuCallback,
  707. long * pInsertionAllowed
  708. )
  709. {
  710. HRESULT hr = hrOK;
  711. SPITFSNode spNode;
  712. DATA_OBJECT_TYPES dwType = CCT_RESULT;
  713. if (IS_SPECIAL_DATAOBJECT(pDataObject))
  714. {
  715. dwType = CCT_SCOPE;
  716. }
  717. else
  718. {
  719. if (pDataObject)
  720. {
  721. SPINTERNAL spInternal;
  722. spInternal = ::ExtractInternalFormat(pDataObject);
  723. if (spInternal)
  724. dwType = spInternal->m_type;
  725. }
  726. }
  727. if (dwType == CCT_SCOPE)
  728. {
  729. // call the normal handler to put up the menu items
  730. CORg (m_spNodeMgr->FindNode(cookie, &spNode));
  731. hr = OnAddMenuItems(spNode, pContextMenuCallback, pDataObject, CCT_SCOPE, (ULONG) spNode->GetData(TFS_DATA_TYPE), pInsertionAllowed);
  732. }
  733. Error:
  734. return hr;
  735. }
  736. /*---------------------------------------------------------------------------
  737. CWinsHandler::Command
  738. Description
  739. Author: EricDav
  740. ---------------------------------------------------------------------------*/
  741. STDMETHODIMP
  742. CWinsHandler::Command
  743. (
  744. ITFSComponent * pComponent,
  745. MMC_COOKIE cookie,
  746. int nCommandID,
  747. LPDATAOBJECT pDataObject
  748. )
  749. {
  750. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  751. HRESULT hr = S_OK;
  752. // this may have come from the scope pane handler, so pass it up
  753. hr = HandleScopeCommand(cookie, nCommandID, pDataObject);
  754. return hr;
  755. }
  756. /*!--------------------------------------------------------------------------
  757. CWinsHandler::AddMenuItems
  758. Over-ride this to add our view menu item
  759. Author: EricDav
  760. ---------------------------------------------------------------------------*/
  761. STDMETHODIMP
  762. CWinsHandler::AddMenuItems
  763. (
  764. ITFSComponent * pComponent,
  765. MMC_COOKIE cookie,
  766. LPDATAOBJECT pDataObject,
  767. LPCONTEXTMENUCALLBACK pContextMenuCallback,
  768. long * pInsertionAllowed
  769. )
  770. {
  771. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  772. HRESULT hr = S_OK;
  773. // figure out if we need to pass this to the scope pane menu handler
  774. hr = HandleScopeMenus(cookie, pDataObject, pContextMenuCallback, pInsertionAllowed);
  775. return hr;
  776. }
  777. /*---------------------------------------------------------------------------
  778. CWinsHandler::OnResultDelete
  779. Description
  780. Author: EricDav
  781. ---------------------------------------------------------------------------*/
  782. HRESULT
  783. CWinsHandler::OnResultDelete
  784. (
  785. ITFSComponent * pComponent,
  786. LPDATAOBJECT pDataObject,
  787. MMC_COOKIE cookie,
  788. LPARAM arg,
  789. LPARAM lParam
  790. )
  791. {
  792. HRESULT hr = hrOK;
  793. Trace0("CWinsHandler::OnResultDelete received\n");
  794. // translate this call to the parent and let it handle deletion
  795. // of result pane items
  796. SPITFSNode spNode, spParent;
  797. SPITFSResultHandler spParentRH;
  798. CORg (m_spNodeMgr->FindNode(cookie, &spNode));
  799. CORg (spNode->GetParent(&spParent));
  800. if (spParent == NULL)
  801. return hr;
  802. CORg (spParent->GetResultHandler(&spParentRH));
  803. CORg (spParentRH->Notify(pComponent, spParent->GetData(TFS_DATA_COOKIE), pDataObject, MMCN_DELETE, arg, lParam));
  804. Error:
  805. return hr;
  806. }
  807. /*!--------------------------------------------------------------------------
  808. CWinsHandler::UpdateConsoleVerbs
  809. Updates the standard verbs depending upon the state of the node
  810. Author: EricDav
  811. ---------------------------------------------------------------------------*/
  812. void
  813. CWinsHandler::UpdateConsoleVerbs
  814. (
  815. IConsoleVerb * pConsoleVerb,
  816. LONG_PTR dwNodeType,
  817. BOOL bMultiSelect
  818. )
  819. {
  820. BOOL bStates[ARRAYLEN(g_ConsoleVerbs)];
  821. MMC_BUTTON_STATE * ButtonState;
  822. int i;
  823. if (bMultiSelect)
  824. {
  825. ButtonState = g_ConsoleVerbStatesMultiSel[dwNodeType];
  826. for (i = 0; i < ARRAYLEN(g_ConsoleVerbs); bStates[i++] = TRUE);
  827. }
  828. else
  829. {
  830. /*
  831. ButtonState = g_ConsoleVerbStates[dwNodeType];
  832. for (i = 0; i < ARRAYLEN(g_ConsoleVerbs); bStates[i++] = TRUE);
  833. */
  834. ButtonState = g_ConsoleVerbStates[dwNodeType];
  835. for (i = 0; i < ARRAYLEN(g_ConsoleVerbs); bStates[i++] = TRUE);
  836. switch (m_nState)
  837. {
  838. case loaded:
  839. for (i = 0; i < ARRAYLEN(g_ConsoleVerbs); bStates[i++] = TRUE);
  840. break;
  841. case notLoaded:
  842. for (i = 0; i < ARRAYLEN(g_ConsoleVerbs); bStates[i++] = FALSE);
  843. bStates[MMC_VERB_REFRESH & 0x000F] = TRUE;
  844. bStates[MMC_VERB_DELETE & 0x000F] = TRUE;
  845. break;
  846. case loading:
  847. for (i = 0; i < ARRAYLEN(g_ConsoleVerbs); bStates[i++] = FALSE);
  848. break;
  849. case unableToLoad:
  850. for (i = 0; i < ARRAYLEN(g_ConsoleVerbs); bStates[i++] = FALSE);
  851. bStates[MMC_VERB_REFRESH & 0x000F] = TRUE;
  852. bStates[MMC_VERB_DELETE & 0x000F] = TRUE;
  853. break;
  854. }
  855. }
  856. EnableVerbs(pConsoleVerb, ButtonState, bStates);
  857. }
  858. /*!--------------------------------------------------------------------------
  859. CWinsHandler::EnableVerbs
  860. Enables the toolbar buttons
  861. Author: EricDav
  862. ---------------------------------------------------------------------------*/
  863. void
  864. CWinsHandler::EnableVerbs
  865. (
  866. IConsoleVerb * pConsoleVerb,
  867. MMC_BUTTON_STATE ButtonState[],
  868. BOOL bState[]
  869. )
  870. {
  871. if (pConsoleVerb == NULL)
  872. {
  873. Assert(FALSE);
  874. return;
  875. }
  876. for (int i=0; i < ARRAYLEN(g_ConsoleVerbs); ++i)
  877. {
  878. if (ButtonState[i] == ENABLED)
  879. {
  880. // unhide this button before enabling
  881. pConsoleVerb->SetVerbState(g_ConsoleVerbs[i],
  882. HIDDEN,
  883. FALSE);
  884. pConsoleVerb->SetVerbState(g_ConsoleVerbs[i],
  885. ButtonState[i],
  886. bState[i]);
  887. }
  888. else
  889. {
  890. // hide this button
  891. pConsoleVerb->SetVerbState(g_ConsoleVerbs[i],
  892. HIDDEN,
  893. TRUE);
  894. }
  895. }
  896. pConsoleVerb->SetDefaultVerb(m_verbDefault);
  897. }
  898. /*!--------------------------------------------------------------------------
  899. CWinsHandler::OnResultSelect
  900. Handles the MMCN_SELECT notifcation
  901. Author: EricDav
  902. ---------------------------------------------------------------------------*/
  903. HRESULT
  904. CWinsHandler::OnResultSelect
  905. (
  906. ITFSComponent * pComponent,
  907. LPDATAOBJECT pDataObject,
  908. MMC_COOKIE cookie,
  909. LPARAM arg,
  910. LPARAM lParam
  911. )
  912. {
  913. HRESULT hr = hrOK;
  914. SPIConsoleVerb spConsoleVerb;
  915. SPITFSNode spNode;
  916. SPINTERNAL spInternal;
  917. BOOL bMultiSelect;
  918. CORg (pComponent->GetConsoleVerb(&spConsoleVerb));
  919. spInternal = ::ExtractInternalFormat(pDataObject);
  920. if (spInternal &&
  921. spInternal->m_cookie == MMC_MULTI_SELECT_COOKIE)
  922. {
  923. CORg (pComponent->GetSelectedNode(&spNode));
  924. bMultiSelect = TRUE;
  925. }
  926. else
  927. {
  928. CORg (m_spNodeMgr->FindNode(cookie, &spNode));
  929. bMultiSelect = FALSE;
  930. }
  931. UpdateConsoleVerbs(spConsoleVerb, spNode->GetData(TFS_DATA_TYPE), bMultiSelect);
  932. Error:
  933. return hr;
  934. }
  935. /*!--------------------------------------------------------------------------
  936. CWinsHandler::OnCreateDataObject
  937. -
  938. Author: EricDav
  939. ---------------------------------------------------------------------------*/
  940. STDMETHODIMP
  941. CWinsHandler::OnCreateDataObject
  942. (
  943. ITFSComponent * pComponent,
  944. MMC_COOKIE cookie,
  945. DATA_OBJECT_TYPES type,
  946. IDataObject ** ppDataObject
  947. )
  948. {
  949. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  950. Assert(ppDataObject != NULL);
  951. CDataObject * pObject = NULL;
  952. SPIDataObject spDataObject;
  953. long lViewOptions;
  954. LPOLESTR pViewType;
  955. BOOL bVirtual;
  956. pObject = new CDataObject;
  957. spDataObject = pObject; // do this so that it gets released correctly
  958. Assert(pObject != NULL);
  959. if (cookie == MMC_MULTI_SELECT_COOKIE)
  960. {
  961. OnGetResultViewType(pComponent, cookie, &pViewType, &lViewOptions);
  962. bVirtual = (lViewOptions & MMC_VIEW_OPTIONS_OWNERDATALIST) ? TRUE : FALSE;
  963. CreateMultiSelectData(pComponent, pObject, bVirtual);
  964. }
  965. // Save cookie and type for delayed rendering
  966. pObject->SetType(type);
  967. pObject->SetCookie(cookie);
  968. // Store the coclass with the data object
  969. pObject->SetClsid(*(m_spTFSComponentData->GetCoClassID()));
  970. pObject->SetTFSComponentData(m_spTFSComponentData);
  971. return pObject->QueryInterface(IID_IDataObject,
  972. reinterpret_cast<void**>(ppDataObject));
  973. }
  974. /*!--------------------------------------------------------------------------
  975. CWinsHandler::CreateMultiSelectData
  976. -
  977. Author: EricDav
  978. ---------------------------------------------------------------------------*/
  979. HRESULT
  980. CWinsHandler::CreateMultiSelectData
  981. (
  982. ITFSComponent * pComponent,
  983. CDataObject * pObject,
  984. BOOL bVirtual
  985. )
  986. {
  987. HRESULT hr = hrOK;
  988. // build the list of selected nodes
  989. CTFSNodeList listSelectedNodes;
  990. CVirtualIndexArray arraySelectedIndicies;
  991. CGUIDArray rgGuids;
  992. UINT cb;
  993. GUID* pGuid;
  994. const GUID * pcGuid;
  995. int i;
  996. COM_PROTECT_TRY
  997. {
  998. if (bVirtual)
  999. {
  1000. // build a list of the selected indicies in the virtual listbox
  1001. CORg (BuildVirtualSelectedItemList(pComponent, &arraySelectedIndicies));
  1002. // now call and get the GUIDs for each one
  1003. for (i = 0; i < arraySelectedIndicies.GetSize(); i++)
  1004. {
  1005. pcGuid = GetVirtualGuid(arraySelectedIndicies[i]);
  1006. if (pcGuid)
  1007. rgGuids.AddUnique(*pcGuid);
  1008. }
  1009. }
  1010. else
  1011. {
  1012. CORg (BuildSelectedItemList(pComponent, &listSelectedNodes));
  1013. // collect all of the unique guids
  1014. while (listSelectedNodes.GetCount() > 0)
  1015. {
  1016. SPITFSNode spCurNode;
  1017. spCurNode = listSelectedNodes.RemoveHead();
  1018. pcGuid = spCurNode->GetNodeType();
  1019. rgGuids.AddUnique(*pcGuid);
  1020. }
  1021. }
  1022. // now put the information in the data object
  1023. cb = (UINT)(rgGuids.GetSize() * sizeof(GUID));
  1024. if (cb > 0)
  1025. {
  1026. pObject->SetMultiSelDobj();
  1027. pGuid = new GUID[(size_t)rgGuids.GetSize()];
  1028. CopyMemory(pGuid, rgGuids.GetData(), cb);
  1029. pObject->SetMultiSelData((BYTE*)pGuid, cb);
  1030. }
  1031. COM_PROTECT_ERROR_LABEL;
  1032. }
  1033. COM_PROTECT_CATCH
  1034. return hr;
  1035. }
  1036. /*!--------------------------------------------------------------------------
  1037. CWinsHandler::OnResultContextHelp
  1038. Implementation of ITFSResultHandler::OnResultContextHelp
  1039. Author: v-shubk
  1040. ---------------------------------------------------------------------------*/
  1041. HRESULT
  1042. CWinsHandler::OnResultContextHelp
  1043. (
  1044. ITFSComponent * pComponent,
  1045. LPDATAOBJECT pDataObject,
  1046. MMC_COOKIE cookie,
  1047. LPARAM arg,
  1048. LPARAM lParam
  1049. )
  1050. {
  1051. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1052. HRESULT hr = hrOK;
  1053. SPIDisplayHelp spDisplayHelp;
  1054. SPIConsole spConsole;
  1055. pComponent->GetConsole(&spConsole);
  1056. hr = spConsole->QueryInterface (IID_IDisplayHelp, (LPVOID*) &spDisplayHelp);
  1057. ASSERT (SUCCEEDED (hr));
  1058. if ( SUCCEEDED (hr) )
  1059. {
  1060. LPCTSTR pszHelpFile = m_spTFSCompData->GetHTMLHelpFileName();
  1061. if (pszHelpFile == NULL)
  1062. goto Error;
  1063. CString szHelpFilePath;
  1064. UINT nLen = ::GetWindowsDirectory (szHelpFilePath.GetBufferSetLength(2 * MAX_PATH), 2 * MAX_PATH);
  1065. if (nLen == 0)
  1066. {
  1067. hr = E_FAIL;
  1068. goto Error;
  1069. }
  1070. szHelpFilePath.ReleaseBuffer();
  1071. szHelpFilePath += g_szDefaultHelpTopic;
  1072. hr = spDisplayHelp->ShowTopic (T2OLE ((LPTSTR)(LPCTSTR) szHelpFilePath));
  1073. ASSERT (SUCCEEDED (hr));
  1074. }
  1075. Error:
  1076. return hr;
  1077. }
  1078. /*!--------------------------------------------------------------------------
  1079. CWinsHandler::SaveColumns
  1080. -
  1081. ---------------------------------------------------------------------------*/
  1082. HRESULT
  1083. CWinsHandler::SaveColumns
  1084. (
  1085. ITFSComponent * pComponent,
  1086. MMC_COOKIE cookie,
  1087. LPARAM arg,
  1088. LPARAM lParam
  1089. )
  1090. {
  1091. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1092. HRESULT hr = hrOK;
  1093. LONG_PTR dwNodeType;
  1094. int nCol = 0;
  1095. int nColWidth;
  1096. SPITFSNode spNode, spRootNode;
  1097. SPIHeaderCtrl spHeaderCtrl;
  1098. BOOL bDirty = FALSE;
  1099. CORg (m_spNodeMgr->FindNode(cookie, &spNode));
  1100. CORg (pComponent->GetHeaderCtrl(&spHeaderCtrl));
  1101. dwNodeType = spNode->GetData(TFS_DATA_TYPE);
  1102. while (aColumns[dwNodeType][nCol] != 0)
  1103. {
  1104. if (SUCCEEDED(spHeaderCtrl->GetColumnWidth(nCol, &nColWidth)) &&
  1105. (aColumnWidths[dwNodeType][nCol] != nColWidth))
  1106. {
  1107. aColumnWidths[dwNodeType][nCol] = nColWidth;
  1108. bDirty = TRUE;
  1109. }
  1110. nCol++;
  1111. }
  1112. if (bDirty)
  1113. {
  1114. CORg (m_spNodeMgr->GetRootNode(&spRootNode));
  1115. spRootNode->SetData(TFS_DATA_DIRTY, TRUE);
  1116. }
  1117. Error:
  1118. return hr;
  1119. }