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.

2124 lines
57 KiB

  1. /**********************************************************************/
  2. /** Microsoft Windows/NT **/
  3. /** Copyright(c) Microsoft Corporation, 1997 - 1999 **/
  4. /**********************************************************************/
  5. /*
  6. dhcphand.cpp
  7. DHCP specifc handler base classes
  8. FILE HISTORY:
  9. */
  10. #include "stdafx.h"
  11. #include "dhcphand.h"
  12. #include "snaputil.h" // For CGUIDArray
  13. #include "extract.h" // For ExtractInternalFormat
  14. #include "nodes.h"
  15. #include "classmod.h"
  16. //
  17. // Called by the result handler when a command comes in that isn't handled
  18. // by the result handler. If appropriate it passes it to the scope pane hander.
  19. //
  20. HRESULT
  21. CMTDhcpHandler::HandleScopeCommand
  22. (
  23. MMC_COOKIE cookie,
  24. int nCommandID,
  25. LPDATAOBJECT pDataObject
  26. )
  27. {
  28. HRESULT hr = hrOK;
  29. SPITFSNode spNode;
  30. DATA_OBJECT_TYPES dwType = CCT_RESULT;
  31. if (IS_SPECIAL_DATAOBJECT(pDataObject))
  32. {
  33. dwType = CCT_SCOPE;
  34. }
  35. else
  36. {
  37. if (pDataObject)
  38. {
  39. SPINTERNAL spInternal;
  40. spInternal = ::ExtractInternalFormat(pDataObject);
  41. if (spInternal)
  42. dwType = spInternal->m_type;
  43. }
  44. }
  45. if (dwType == CCT_SCOPE)
  46. {
  47. // call the handler to take care of this
  48. CORg (m_spNodeMgr->FindNode(cookie, &spNode));
  49. hr = OnCommand(spNode, nCommandID, dwType, pDataObject, (ULONG) spNode->GetData(TFS_DATA_TYPE));
  50. }
  51. Error:
  52. return hr;
  53. }
  54. //
  55. // Called by the result handler to add the scope pane menu items to the menu
  56. // where appropriate. Puts scope pane menu items in when action menu is clicked
  57. // and the message view has focus as well as when a right click happens in the white
  58. // space of the result pane.
  59. //
  60. HRESULT
  61. CMTDhcpHandler::HandleScopeMenus
  62. (
  63. MMC_COOKIE cookie,
  64. LPDATAOBJECT pDataObject,
  65. LPCONTEXTMENUCALLBACK pContextMenuCallback,
  66. long * pInsertionAllowed
  67. )
  68. {
  69. HRESULT hr = hrOK;
  70. SPITFSNode spNode;
  71. DATA_OBJECT_TYPES dwType = CCT_RESULT;
  72. if (IS_SPECIAL_DATAOBJECT(pDataObject))
  73. {
  74. dwType = CCT_SCOPE;
  75. }
  76. else
  77. {
  78. if (pDataObject)
  79. {
  80. SPINTERNAL spInternal;
  81. spInternal = ::ExtractInternalFormat(pDataObject);
  82. if (spInternal)
  83. dwType = spInternal->m_type;
  84. }
  85. }
  86. if (dwType == CCT_SCOPE)
  87. {
  88. // call the normal handler to put up the menu items
  89. CORg (m_spNodeMgr->FindNode(cookie, &spNode));
  90. hr = OnAddMenuItems(spNode, pContextMenuCallback, pDataObject, CCT_SCOPE, (ULONG) spNode->GetData(TFS_DATA_TYPE), pInsertionAllowed);
  91. }
  92. Error:
  93. return hr;
  94. }
  95. /*---------------------------------------------------------------------------
  96. CMTDhcpHandler::Command
  97. Description
  98. Author: EricDav
  99. ---------------------------------------------------------------------------*/
  100. STDMETHODIMP
  101. CMTDhcpHandler::Command
  102. (
  103. ITFSComponent * pComponent,
  104. MMC_COOKIE cookie,
  105. int nCommandID,
  106. LPDATAOBJECT pDataObject
  107. )
  108. {
  109. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  110. HRESULT hr = S_OK;
  111. // this may have come from the scope pane handler, so pass it up
  112. hr = HandleScopeCommand(cookie, nCommandID, pDataObject);
  113. return hr;
  114. }
  115. /*!--------------------------------------------------------------------------
  116. CMTDhcpHandler::AddMenuItems
  117. Over-ride this to add our view menu item
  118. Author: EricDav
  119. ---------------------------------------------------------------------------*/
  120. STDMETHODIMP
  121. CMTDhcpHandler::AddMenuItems
  122. (
  123. ITFSComponent * pComponent,
  124. MMC_COOKIE cookie,
  125. LPDATAOBJECT pDataObject,
  126. LPCONTEXTMENUCALLBACK pContextMenuCallback,
  127. long * pInsertionAllowed
  128. )
  129. {
  130. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  131. HRESULT hr = S_OK;
  132. // figure out if we need to pass this to the scope pane menu handler
  133. hr = HandleScopeMenus(cookie, pDataObject, pContextMenuCallback, pInsertionAllowed);
  134. return hr;
  135. }
  136. /*---------------------------------------------------------------------------
  137. CMTDhcpHandler::OnChangeState
  138. Description
  139. Author: EricDav
  140. ---------------------------------------------------------------------------*/
  141. void CMTDhcpHandler::OnChangeState
  142. (
  143. ITFSNode * pNode
  144. )
  145. {
  146. // Increment the state to the next position
  147. switch (m_nState)
  148. {
  149. case notLoaded:
  150. case loaded:
  151. case unableToLoad:
  152. {
  153. m_nState = loading;
  154. m_dwErr = 0;
  155. }
  156. break;
  157. case loading:
  158. {
  159. m_nState = (m_dwErr != 0) ? unableToLoad : loaded;
  160. if (m_dwErr)
  161. {
  162. CString strTitle, strBody;
  163. IconIdentifier icon;
  164. GetErrorMessages(strTitle, strBody, &icon);
  165. if (!strBody.IsEmpty())
  166. ShowMessage(pNode, strTitle, strBody, icon);
  167. else
  168. ClearMessage(pNode);
  169. }
  170. else
  171. {
  172. ClearMessage(pNode);
  173. }
  174. m_fSilent = FALSE;
  175. }
  176. break;
  177. default:
  178. ASSERT(FALSE);
  179. }
  180. // check to make sure we are still the visible node in the UI
  181. if (m_bSelected)
  182. {
  183. UpdateStandardVerbs(pNode, pNode->GetData(TFS_DATA_TYPE));
  184. SendUpdateToolbar(pNode, m_bSelected);
  185. }
  186. // Now check and see if there is a new image for this state for this handler
  187. int nImage, nOpenImage;
  188. nImage = GetImageIndex(FALSE);
  189. nOpenImage = GetImageIndex(TRUE);
  190. if (nImage >= 0)
  191. pNode->SetData(TFS_DATA_IMAGEINDEX, nImage);
  192. if (nOpenImage >= 0)
  193. pNode->SetData(TFS_DATA_OPENIMAGEINDEX, nOpenImage);
  194. VERIFY(SUCCEEDED(pNode->ChangeNode(SCOPE_PANE_CHANGE_ITEM)));
  195. }
  196. /*!--------------------------------------------------------------------------
  197. CMTDhcpHandler::GetErrorMessages
  198. Default message view text for errors
  199. Author: EricDav
  200. ---------------------------------------------------------------------------*/
  201. void CMTDhcpHandler::GetErrorMessages
  202. (
  203. CString & strTitle,
  204. CString & strBody,
  205. IconIdentifier * icon
  206. )
  207. {
  208. TCHAR chMesg [4000] = {0};
  209. BOOL bOk ;
  210. UINT nIdPrompt = (UINT) m_dwErr;
  211. CString strTemp;
  212. strTitle.LoadString(IDS_SERVER_MESSAGE_CONNECT_FAILED_TITLE);
  213. bOk = LoadMessage(nIdPrompt, chMesg, sizeof(chMesg)/sizeof(chMesg[0]));
  214. AfxFormatString1(strBody, IDS_SERVER_MESSAGE_CONNECT_FAILED_BODY, chMesg);
  215. strTemp.LoadString(IDS_SERVER_MESSAGE_CONNECT_FAILED_REFRESH);
  216. strBody += strTemp;
  217. if (icon)
  218. *icon = Icon_Error;
  219. }
  220. /*!--------------------------------------------------------------------------
  221. CMTDhcpHandler::UpdateStandardVerbs
  222. Tells the IComponent to update the verbs for this node
  223. Author: EricDav
  224. ---------------------------------------------------------------------------*/
  225. void
  226. CMTDhcpHandler::UpdateStandardVerbs
  227. (
  228. ITFSNode * pNode,
  229. LONG_PTR dwNodeType
  230. )
  231. {
  232. HRESULT hr = hrOK;
  233. SPIComponentData spCompData;
  234. SPIConsole spConsole;
  235. IDataObject* pDataObject;
  236. m_spNodeMgr->GetComponentData(&spCompData);
  237. CORg ( spCompData->QueryDataObject(NULL, CCT_RESULT, &pDataObject) );
  238. CORg ( m_spNodeMgr->GetConsole(&spConsole) );
  239. CORg ( spConsole->UpdateAllViews(pDataObject,
  240. reinterpret_cast<LONG_PTR>(pNode),
  241. RESULT_PANE_UPDATE_VERBS) );
  242. pDataObject->Release();
  243. Error:
  244. return;
  245. }
  246. /*!--------------------------------------------------------------------------
  247. CMTDhcpHandler::SendUpdateToolbar
  248. Tells the IComponent to update the verbs for this node
  249. Author: EricDav
  250. ---------------------------------------------------------------------------*/
  251. void
  252. CMTDhcpHandler::SendUpdateToolbar
  253. (
  254. ITFSNode * pNode,
  255. BOOL fSelected
  256. )
  257. {
  258. HRESULT hr = hrOK;
  259. SPIComponentData spCompData;
  260. SPIConsole spConsole;
  261. IDataObject* pDataObject = NULL;
  262. CToolbarInfo * pToolbarInfo = NULL;
  263. COM_PROTECT_TRY
  264. {
  265. m_spNodeMgr->GetComponentData(&spCompData);
  266. CORg ( spCompData->QueryDataObject(NULL, CCT_RESULT, &pDataObject) );
  267. CORg ( m_spNodeMgr->GetConsole(&spConsole) );
  268. pToolbarInfo = new CToolbarInfo;
  269. pToolbarInfo->spNode.Set(pNode);
  270. pToolbarInfo->fSelected = fSelected;
  271. CORg ( spConsole->UpdateAllViews(pDataObject,
  272. reinterpret_cast<LONG_PTR>(pToolbarInfo),
  273. DHCPSNAP_UPDATE_TOOLBAR) );
  274. }
  275. COM_PROTECT_CATCH
  276. COM_PROTECT_ERROR_LABEL;
  277. if (pDataObject)
  278. pDataObject->Release();
  279. if (pToolbarInfo)
  280. delete pToolbarInfo;
  281. return;
  282. }
  283. /*!--------------------------------------------------------------------------
  284. CMTDhcpHandler::ExpandNode
  285. Expands/compresses this node
  286. Author: EricDav
  287. ---------------------------------------------------------------------------*/
  288. void
  289. CMTDhcpHandler::ExpandNode
  290. (
  291. ITFSNode * pNode,
  292. BOOL fExpand
  293. )
  294. {
  295. SPIComponentData spCompData;
  296. SPIDataObject spDataObject;
  297. LPDATAOBJECT pDataObject;
  298. SPIConsole spConsole;
  299. HRESULT hr = hrOK;
  300. // don't expand the node if we are handling the EXPAND_SYNC message,
  301. // this screws up the insertion of item, getting duplicates.
  302. if (!m_fExpandSync)
  303. {
  304. m_spNodeMgr->GetComponentData(&spCompData);
  305. CORg ( spCompData->QueryDataObject((MMC_COOKIE) pNode, CCT_SCOPE, &pDataObject) );
  306. spDataObject = pDataObject;
  307. CORg ( m_spNodeMgr->GetConsole(&spConsole) );
  308. CORg ( spConsole->UpdateAllViews(pDataObject, TRUE, RESULT_PANE_EXPAND) );
  309. }
  310. Error:
  311. return;
  312. }
  313. /*!--------------------------------------------------------------------------
  314. CMTDhcpHandler::OnCreateDataObject
  315. -
  316. Author: EricDav
  317. ---------------------------------------------------------------------------*/
  318. STDMETHODIMP
  319. CMTDhcpHandler::OnCreateDataObject
  320. (
  321. ITFSComponent * pComponent,
  322. MMC_COOKIE cookie,
  323. DATA_OBJECT_TYPES type,
  324. IDataObject ** ppDataObject
  325. )
  326. {
  327. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  328. Assert(ppDataObject != NULL);
  329. CDataObject * pObject = NULL;
  330. SPIDataObject spDataObject;
  331. pObject = new CDataObject;
  332. spDataObject = pObject; // do this so that it gets released correctly
  333. Assert(pObject != NULL);
  334. if (cookie == MMC_MULTI_SELECT_COOKIE)
  335. {
  336. CreateMultiSelectData(pComponent, pObject);
  337. }
  338. // Save cookie and type for delayed rendering
  339. pObject->SetType(type);
  340. pObject->SetCookie(cookie);
  341. // Store the coclass with the data object
  342. pObject->SetClsid(*(m_spTFSComponentData->GetCoClassID()));
  343. pObject->SetTFSComponentData(m_spTFSComponentData);
  344. return pObject->QueryInterface(IID_IDataObject,
  345. reinterpret_cast<void**>(ppDataObject));
  346. }
  347. HRESULT
  348. CMTDhcpHandler::CreateMultiSelectData(ITFSComponent * pComponent, CDataObject * pObject)
  349. {
  350. HRESULT hr = hrOK;
  351. // build the list of selected nodes
  352. CTFSNodeList listSelectedNodes;
  353. CGUIDArray rgGuids;
  354. UINT cb;
  355. GUID* pGuid;
  356. COM_PROTECT_TRY
  357. {
  358. CORg (BuildSelectedItemList(pComponent, &listSelectedNodes));
  359. // collect all of the unique guids
  360. while (listSelectedNodes.GetCount() > 0)
  361. {
  362. SPITFSNode spCurNode;
  363. const GUID * pGuid1;
  364. spCurNode = listSelectedNodes.RemoveHead();
  365. pGuid1 = spCurNode->GetNodeType();
  366. rgGuids.AddUnique(*pGuid1);
  367. }
  368. // now put the information in the data object
  369. pObject->SetMultiSelDobj();
  370. cb = (UINT)(rgGuids.GetSize() * sizeof(GUID));
  371. pGuid = new GUID[UINT(rgGuids.GetSize())];
  372. CopyMemory(pGuid, rgGuids.GetData(), cb);
  373. pObject->SetMultiSelData((BYTE*)pGuid, cb);
  374. COM_PROTECT_ERROR_LABEL;
  375. }
  376. COM_PROTECT_CATCH
  377. return hr;
  378. }
  379. /*!--------------------------------------------------------------------------
  380. CMTDhcpHandler::SaveColumns
  381. -
  382. Author: EricDav
  383. ---------------------------------------------------------------------------*/
  384. HRESULT
  385. CMTDhcpHandler::SaveColumns
  386. (
  387. ITFSComponent * pComponent,
  388. MMC_COOKIE cookie,
  389. LPARAM arg,
  390. LPARAM lParam
  391. )
  392. {
  393. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  394. HRESULT hr = hrOK;
  395. LONG_PTR dwNodeType;
  396. int nCol = 0;
  397. int nColWidth;
  398. SPITFSNode spNode, spRootNode;
  399. SPIHeaderCtrl spHeaderCtrl;
  400. BOOL bDirty = FALSE;
  401. if (m_spTFSCompData->GetTaskpadState(GetTaskpadIndex()))
  402. return hr;
  403. if (IsMessageView())
  404. return hr;
  405. CORg (m_spNodeMgr->FindNode(cookie, &spNode));
  406. CORg (pComponent->GetHeaderCtrl(&spHeaderCtrl));
  407. dwNodeType = spNode->GetData(TFS_DATA_TYPE);
  408. while (aColumns[dwNodeType][nCol] != 0)
  409. {
  410. hr = spHeaderCtrl->GetColumnWidth(nCol, &nColWidth);
  411. if (SUCCEEDED(hr) &&
  412. (nColWidth != 0) &&
  413. aColumnWidths[dwNodeType][nCol] != nColWidth)
  414. {
  415. aColumnWidths[dwNodeType][nCol] = nColWidth;
  416. bDirty = TRUE;
  417. }
  418. nCol++;
  419. }
  420. if (bDirty)
  421. {
  422. CORg (m_spNodeMgr->GetRootNode(&spRootNode));
  423. spRootNode->SetData(TFS_DATA_DIRTY, TRUE);
  424. }
  425. Error:
  426. return hr;
  427. }
  428. /*!--------------------------------------------------------------------------
  429. CMTDhcpHandler::OnExpandSync
  430. Handles the MMCN_EXPANDSYNC notifcation
  431. We need to do syncronous enumeration. We'll fire off the background
  432. thread like before, but we'll wait for it to exit before we return.
  433. Author: EricDav
  434. ---------------------------------------------------------------------------*/
  435. HRESULT
  436. CMTDhcpHandler::OnExpandSync
  437. (
  438. ITFSNode * pNode,
  439. LPDATAOBJECT pDataObject,
  440. LPARAM arg,
  441. LPARAM lParam
  442. )
  443. {
  444. HRESULT hr = hrOK;
  445. MSG msg;
  446. m_fExpandSync = TRUE;
  447. hr = OnExpand(pNode, pDataObject, CCT_SCOPE, arg, lParam);
  448. // wait for the background thread to exit
  449. WaitForSingleObject(m_hThread, INFINITE);
  450. // The background thread posts messages to a hidden window to
  451. // pass data back to the main thread. The messages won't go through since we are
  452. // blocking the main thread. The data goes on a queue in the query object
  453. // which the handler has a pointer to so we can just fake the notification.
  454. if (m_spQuery.p)
  455. OnNotifyHaveData((LPARAM) m_spQuery.p);
  456. // Tell MMC we handled this message
  457. MMC_EXPANDSYNC_STRUCT * pES = reinterpret_cast<MMC_EXPANDSYNC_STRUCT *>(lParam);
  458. if (pES)
  459. pES->bHandled = TRUE;
  460. m_fExpandSync = FALSE;
  461. return hr;
  462. }
  463. /*!--------------------------------------------------------------------------
  464. CMTDhcpHandler::OnResultSelect
  465. Handles the MMCN_SELECT notifcation
  466. Author: EricDav
  467. ---------------------------------------------------------------------------*/
  468. HRESULT
  469. CMTDhcpHandler::OnResultSelect
  470. (
  471. ITFSComponent * pComponent,
  472. LPDATAOBJECT pDataObject,
  473. MMC_COOKIE cookie,
  474. LPARAM arg,
  475. LPARAM lParam
  476. )
  477. {
  478. SPIConsoleVerb spConsoleVerb;
  479. SPITFSNode spNode;
  480. HRESULT hr = hrOK;
  481. SPINTERNAL spInternal;
  482. BOOL bMultiSelect = FALSE;
  483. CORg (pComponent->GetConsoleVerb(&spConsoleVerb));
  484. spInternal = ::ExtractInternalFormat(pDataObject);
  485. if (spInternal &&
  486. spInternal->m_cookie == MMC_MULTI_SELECT_COOKIE)
  487. {
  488. CORg (pComponent->GetSelectedNode(&spNode));
  489. bMultiSelect = TRUE;
  490. }
  491. else
  492. {
  493. CORg (m_spNodeMgr->FindNode(cookie, &spNode));
  494. }
  495. UpdateConsoleVerbs(spConsoleVerb, spNode->GetData(TFS_DATA_TYPE), bMultiSelect);
  496. Error:
  497. return hr;
  498. }
  499. /*!--------------------------------------------------------------------------
  500. CMTDhcpHandler::OnRefresh
  501. Default implementation for the refresh functionality
  502. Author: EricDav
  503. ---------------------------------------------------------------------------*/
  504. HRESULT
  505. CMTDhcpHandler::OnRefresh
  506. (
  507. ITFSNode * pNode,
  508. LPDATAOBJECT pDataObject,
  509. DWORD dwType,
  510. LPARAM arg,
  511. LPARAM param
  512. )
  513. {
  514. HRESULT hr = hrOK;
  515. if (m_bExpanded == FALSE)
  516. {
  517. // we cannot refresh/add items to a node that hasn't been expanded yet.
  518. return hr;
  519. }
  520. BOOL bLocked = IsLocked();
  521. if (bLocked)
  522. {
  523. // cannot do refresh on locked node, the UI should prevent this
  524. return hr;
  525. }
  526. pNode->DeleteAllChildren(TRUE);
  527. int nVisible, nTotal;
  528. pNode->GetChildCount(&nVisible, &nTotal);
  529. Assert(nVisible == 0);
  530. Assert(nTotal == 0);
  531. m_bExpanded = FALSE;
  532. OnExpand(pNode, pDataObject, dwType, arg, param); // will spawn a thread to do enumeration
  533. if (m_spTFSCompData->GetTaskpadState(GetTaskpadIndex()) && m_bSelected)
  534. {
  535. // tell the taskpad to update
  536. SPIConsole spConsole;
  537. m_spTFSCompData->GetConsole(&spConsole);
  538. spConsole->SelectScopeItem(m_spNode->GetData(TFS_DATA_SCOPEID));
  539. }
  540. return hr;
  541. }
  542. /*!--------------------------------------------------------------------------
  543. CMTDhcpHandler::OnResultUpdateView
  544. Implementation of ITFSResultHandler::OnResultUpdateView
  545. Author: EricDav
  546. ---------------------------------------------------------------------------*/
  547. HRESULT CMTDhcpHandler::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. spNode.Set(reinterpret_cast<ITFSNode *>(data));
  562. UpdateConsoleVerbs(spConsoleVerb, spNode->GetData(TFS_DATA_TYPE));
  563. }
  564. else
  565. if (hint == DHCPSNAP_UPDATE_TOOLBAR)
  566. {
  567. SPIToolbar spToolbar;
  568. CToolbarInfo * pToolbarInfo;
  569. CORg (pComponent->GetToolbar(&spToolbar));
  570. pToolbarInfo = reinterpret_cast<CToolbarInfo *>(data);
  571. if (pToolbarInfo && spToolbar)
  572. {
  573. UpdateToolbar(spToolbar, pToolbarInfo->spNode->GetData(TFS_DATA_TYPE), pToolbarInfo->fSelected);
  574. }
  575. }
  576. else
  577. {
  578. return CBaseResultHandler::OnResultUpdateView(pComponent, pDataObject, data, hint);
  579. }
  580. Error:
  581. return hr;
  582. }
  583. /*!--------------------------------------------------------------------------
  584. CMTDhcpHandler::OnResultContextHelp
  585. Implementation of ITFSResultHandler::OnResultContextHelp
  586. Author: EricDav
  587. ---------------------------------------------------------------------------*/
  588. HRESULT
  589. CMTDhcpHandler::OnResultContextHelp
  590. (
  591. ITFSComponent * pComponent,
  592. LPDATAOBJECT pDataObject,
  593. MMC_COOKIE cookie,
  594. LPARAM arg,
  595. LPARAM lParam
  596. )
  597. {
  598. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  599. HRESULT hr = hrOK;
  600. SPIDisplayHelp spDisplayHelp;
  601. SPIConsole spConsole;
  602. pComponent->GetConsole(&spConsole);
  603. hr = spConsole->QueryInterface (IID_IDisplayHelp, (LPVOID*) &spDisplayHelp);
  604. ASSERT (SUCCEEDED (hr));
  605. if ( SUCCEEDED (hr) )
  606. {
  607. LPCTSTR pszHelpFile = m_spTFSCompData->GetHTMLHelpFileName();
  608. if (pszHelpFile == NULL)
  609. goto Error;
  610. CString szHelpFilePath;
  611. UINT nLen = ::GetWindowsDirectory (szHelpFilePath.GetBufferSetLength(2 * MAX_PATH), 2 * MAX_PATH);
  612. if (nLen == 0)
  613. {
  614. hr = E_FAIL;
  615. goto Error;
  616. }
  617. szHelpFilePath.ReleaseBuffer();
  618. szHelpFilePath += g_szDefaultHelpTopic;
  619. hr = spDisplayHelp->ShowTopic (T2OLE ((LPTSTR)(LPCTSTR) szHelpFilePath));
  620. ASSERT (SUCCEEDED (hr));
  621. }
  622. Error:
  623. return hr;
  624. }
  625. /*!--------------------------------------------------------------------------
  626. CMTDhcpHandler::UpdateStandardVerbs
  627. Updates the standard verbs depending upon the state of the node
  628. Author: EricDav
  629. ---------------------------------------------------------------------------*/
  630. void
  631. CMTDhcpHandler::UpdateConsoleVerbs
  632. (
  633. IConsoleVerb * pConsoleVerb,
  634. LONG_PTR dwNodeType,
  635. BOOL bMultiSelect
  636. )
  637. {
  638. BOOL bStates[ARRAYLEN(g_ConsoleVerbs)];
  639. MMC_BUTTON_STATE * ButtonState;
  640. int i;
  641. if (bMultiSelect)
  642. {
  643. ButtonState = g_ConsoleVerbStatesMultiSel[dwNodeType];
  644. for (i = 0; i < ARRAYLEN(g_ConsoleVerbs); bStates[i++] = TRUE);
  645. }
  646. else
  647. {
  648. ButtonState = g_ConsoleVerbStates[dwNodeType];
  649. switch (m_nState)
  650. {
  651. case loaded:
  652. for (i = 0; i < ARRAYLEN(g_ConsoleVerbs); bStates[i++] = TRUE);
  653. break;
  654. case notLoaded:
  655. case loading:
  656. for (i = 0; i < ARRAYLEN(g_ConsoleVerbs); bStates[i++] = FALSE);
  657. bStates[MMC_VERB_DELETE & 0x000F] = TRUE;
  658. break;
  659. case unableToLoad:
  660. for (i = 0; i < ARRAYLEN(g_ConsoleVerbs); bStates[i++] = FALSE);
  661. bStates[MMC_VERB_REFRESH & 0x000F] = TRUE;
  662. bStates[MMC_VERB_DELETE & 0x000F] = TRUE;
  663. break;
  664. }
  665. }
  666. EnableVerbs(pConsoleVerb, ButtonState, bStates);
  667. }
  668. /*!--------------------------------------------------------------------------
  669. CMTDhcpHandler::EnableVerbs
  670. Enables the toolbar buttons
  671. Author: EricDav
  672. ---------------------------------------------------------------------------*/
  673. void
  674. CMTDhcpHandler::EnableVerbs
  675. (
  676. IConsoleVerb * pConsoleVerb,
  677. MMC_BUTTON_STATE ButtonState[],
  678. BOOL bState[]
  679. )
  680. {
  681. if (pConsoleVerb == NULL)
  682. {
  683. Assert(FALSE);
  684. return;
  685. }
  686. for (int i=0; i < ARRAYLEN(g_ConsoleVerbs); ++i)
  687. {
  688. if (ButtonState[i] == ENABLED)
  689. {
  690. // unhide this button before enabling
  691. pConsoleVerb->SetVerbState(g_ConsoleVerbs[i],
  692. HIDDEN,
  693. FALSE);
  694. pConsoleVerb->SetVerbState(g_ConsoleVerbs[i],
  695. ButtonState[i],
  696. bState[i]);
  697. }
  698. else
  699. {
  700. // hide this button
  701. pConsoleVerb->SetVerbState(g_ConsoleVerbs[i],
  702. HIDDEN,
  703. TRUE);
  704. }
  705. }
  706. pConsoleVerb->SetDefaultVerb(m_verbDefault);
  707. }
  708. /*!--------------------------------------------------------------------------
  709. CMTDhcpHandler::UpdateToolbar
  710. Updates the toolbar depending upon the state of the node
  711. Author: EricDav
  712. ---------------------------------------------------------------------------*/
  713. void
  714. CMTDhcpHandler::UpdateToolbar
  715. (
  716. IToolbar * pToolbar,
  717. LONG_PTR dwNodeType,
  718. BOOL bSelect
  719. )
  720. {
  721. // Enable/disable toolbar buttons
  722. int i;
  723. BOOL aEnable[TOOLBAR_IDX_MAX];
  724. switch (m_nState)
  725. {
  726. case loaded:
  727. for (i = 0; i < TOOLBAR_IDX_MAX; aEnable[i++] = TRUE);
  728. break;
  729. case notLoaded:
  730. case loading:
  731. for (i = 0; i < TOOLBAR_IDX_MAX; aEnable[i++] = FALSE);
  732. break;
  733. case unableToLoad:
  734. for (i = 0; i < TOOLBAR_IDX_MAX; aEnable[i++] = FALSE);
  735. aEnable[TOOLBAR_IDX_REFRESH] = TRUE;
  736. break;
  737. }
  738. // if we are deselecting, then disable all
  739. if (!bSelect)
  740. for (i = 0; i < TOOLBAR_IDX_MAX; aEnable[i++] = FALSE);
  741. EnableToolbar(pToolbar,
  742. g_SnapinButtons,
  743. ARRAYLEN(g_SnapinButtons),
  744. g_SnapinButtonStates[dwNodeType],
  745. aEnable);
  746. }
  747. /*!--------------------------------------------------------------------------
  748. CMTDhcpHandler::UserResultNotify
  749. We override this to handle toolbar notification
  750. Author: EricDav
  751. ---------------------------------------------------------------------------*/
  752. STDMETHODIMP
  753. CMTDhcpHandler::UserResultNotify
  754. (
  755. ITFSNode * pNode,
  756. LPARAM dwParam1,
  757. LPARAM dwParam2
  758. )
  759. {
  760. HRESULT hr = hrOK;
  761. switch (dwParam1)
  762. {
  763. case DHCP_MSG_CONTROLBAR_NOTIFY:
  764. hr = OnResultControlbarNotify(pNode, reinterpret_cast<LPDHCPTOOLBARNOTIFY>(dwParam2));
  765. break;
  766. default:
  767. // we don't handle this message. Forward it down the line...
  768. hr = CHandler::UserResultNotify(pNode, dwParam1, dwParam2);
  769. break;
  770. }
  771. return hr;
  772. }
  773. /*!--------------------------------------------------------------------------
  774. CMTDhcpHandler::UserNotify
  775. We override this to handle toolbar notification
  776. Author: EricDav
  777. ---------------------------------------------------------------------------*/
  778. STDMETHODIMP
  779. CMTDhcpHandler::UserNotify
  780. (
  781. ITFSNode * pNode,
  782. LPARAM dwParam1,
  783. LPARAM dwParam2
  784. )
  785. {
  786. HRESULT hr = hrOK;
  787. switch (dwParam1)
  788. {
  789. case DHCP_MSG_CONTROLBAR_NOTIFY:
  790. hr = OnControlbarNotify(pNode, reinterpret_cast<LPDHCPTOOLBARNOTIFY>(dwParam2));
  791. break;
  792. default:
  793. // we don't handle this message. Forward it down the line...
  794. hr = CHandler::UserNotify(pNode, dwParam1, dwParam2);
  795. break;
  796. }
  797. return hr;
  798. }
  799. /*!--------------------------------------------------------------------------
  800. CMTDhcpHandler::OnResultRefresh
  801. Call into the MTHandler to do a refresh
  802. Author: EricDav
  803. ---------------------------------------------------------------------------*/
  804. HRESULT
  805. CMTDhcpHandler::OnResultRefresh
  806. (
  807. ITFSComponent * pComponent,
  808. LPDATAOBJECT pDataObject,
  809. MMC_COOKIE cookie,
  810. LPARAM arg,
  811. LPARAM lParam
  812. )
  813. {
  814. HRESULT hr = hrOK;
  815. SPITFSNode spNode;
  816. CORg (m_spNodeMgr->FindNode(cookie, &spNode));
  817. OnRefresh(spNode, pDataObject, 0, arg, lParam);
  818. Error:
  819. return hr;
  820. }
  821. /*!--------------------------------------------------------------------------
  822. CMTDhcpHandler::OnResultControlbarNotify
  823. Our implementation of the toobar handlers
  824. Author: EricDav
  825. ---------------------------------------------------------------------------*/
  826. HRESULT
  827. CMTDhcpHandler::OnResultControlbarNotify
  828. (
  829. ITFSNode * pNode,
  830. LPDHCPTOOLBARNOTIFY pToolbarNotify
  831. )
  832. {
  833. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  834. HRESULT hr = hrOK;
  835. // mark this node as selected
  836. m_bSelected = pToolbarNotify->bSelect;
  837. SPITFSNode spParent;
  838. SPITFSNodeHandler spNodeHandler;
  839. switch (pToolbarNotify->event)
  840. {
  841. case MMCN_BTN_CLICK:
  842. // forward the button click to the parent because our result pane
  843. // items don't have any functions for the toolbar
  844. // our result pane items only use the standard verbs
  845. CORg(pNode->GetParent(&spParent));
  846. CORg(spParent->GetHandler(&spNodeHandler));
  847. if (spNodeHandler)
  848. CORg( spNodeHandler->UserNotify(spParent,
  849. (LPARAM) DHCP_MSG_CONTROLBAR_NOTIFY,
  850. (LPARAM) pToolbarNotify) );
  851. break;
  852. case MMCN_SELECT:
  853. if (pNode->IsContainer())
  854. {
  855. hr = OnUpdateToolbarButtons(pNode,
  856. pToolbarNotify);
  857. }
  858. break;
  859. default:
  860. Assert(FALSE);
  861. break;
  862. }
  863. Error:
  864. return hr;
  865. }
  866. /*!--------------------------------------------------------------------------
  867. CMTDhcpHandler::OnControlbarNotify
  868. Our implementation of the toobar handlers
  869. Author: EricDav
  870. ---------------------------------------------------------------------------*/
  871. HRESULT
  872. CMTDhcpHandler::OnControlbarNotify
  873. (
  874. ITFSNode * pNode,
  875. LPDHCPTOOLBARNOTIFY pToolbarNotify
  876. )
  877. {
  878. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  879. HRESULT hr = hrOK;
  880. // mark this node as selected
  881. m_bSelected = pToolbarNotify->bSelect;
  882. switch (pToolbarNotify->event)
  883. {
  884. case MMCN_BTN_CLICK:
  885. hr = OnToolbarButtonClick(pNode,
  886. pToolbarNotify);
  887. break;
  888. case MMCN_SELECT:
  889. hr = OnUpdateToolbarButtons(pNode,
  890. pToolbarNotify);
  891. break;
  892. default:
  893. Assert(FALSE);
  894. }
  895. return hr;
  896. }
  897. /*!--------------------------------------------------------------------------
  898. CMTDhcpHandler::OnToolbarButtonClick
  899. Default implementation of OnToolbarButtonClick
  900. Author: EricDav
  901. ---------------------------------------------------------------------------*/
  902. HRESULT
  903. CMTDhcpHandler::OnToolbarButtonClick
  904. (
  905. ITFSNode * pNode,
  906. LPDHCPTOOLBARNOTIFY pToolbarNotify
  907. )
  908. {
  909. // forward this command to the normal command handler
  910. return OnCommand(pNode, (long) pToolbarNotify->id, (DATA_OBJECT_TYPES) 0, NULL, 0);
  911. }
  912. /*!--------------------------------------------------------------------------
  913. CMTDhcpHandler::OnUpdateToolbarButtons
  914. Default implementation of OnUpdateToolbarButtons
  915. Author: EricDav
  916. ---------------------------------------------------------------------------*/
  917. HRESULT
  918. CMTDhcpHandler::OnUpdateToolbarButtons
  919. (
  920. ITFSNode * pNode,
  921. LPDHCPTOOLBARNOTIFY pToolbarNotify
  922. )
  923. {
  924. HRESULT hr = hrOK;
  925. if (pToolbarNotify->bSelect)
  926. {
  927. BOOL bAttach = FALSE;
  928. // check to see if we should attach this toolbar
  929. for (int i = 0; i < TOOLBAR_IDX_MAX; i++)
  930. {
  931. if (g_SnapinButtonStates[pNode->GetData(TFS_DATA_TYPE)][i] == ENABLED)
  932. {
  933. bAttach = TRUE;
  934. break;
  935. }
  936. }
  937. // attach the toolbar and enable the appropriate buttons
  938. if (pToolbarNotify->pControlbar)
  939. {
  940. if (bAttach)
  941. {
  942. pToolbarNotify->pControlbar->Attach(TOOLBAR, pToolbarNotify->pToolbar);
  943. UpdateToolbar(pToolbarNotify->pToolbar, pNode->GetData(TFS_DATA_TYPE), pToolbarNotify->bSelect);
  944. }
  945. else
  946. {
  947. pToolbarNotify->pControlbar->Detach(pToolbarNotify->pToolbar);
  948. }
  949. }
  950. }
  951. return hr;
  952. }
  953. /*!--------------------------------------------------------------------------
  954. CMTDhcpHandler::EnableToolbar
  955. Enables the toolbar buttons
  956. Author: EricDav
  957. ---------------------------------------------------------------------------*/
  958. void
  959. CMTDhcpHandler::EnableToolbar
  960. (
  961. LPTOOLBAR pToolbar,
  962. MMCBUTTON rgSnapinButtons[],
  963. int nRgSize,
  964. MMC_BUTTON_STATE ButtonState[],
  965. BOOL bState[]
  966. )
  967. {
  968. if (pToolbar == NULL)
  969. {
  970. Assert(FALSE);
  971. return;
  972. }
  973. #ifdef DBG
  974. CString strDbg;
  975. strDbg.Format(_T("CMTDhcpHandler::EnableToolbar - Calling on thread %lx\n"), GetCurrentThreadId());
  976. OutputDebugString(strDbg);
  977. #endif
  978. for (int i=0; i < nRgSize; ++i)
  979. {
  980. if (rgSnapinButtons[i].idCommand != 0)
  981. {
  982. if (ButtonState[i] == ENABLED)
  983. {
  984. // unhide this button before enabling
  985. pToolbar->SetButtonState(rgSnapinButtons[i].idCommand,
  986. HIDDEN,
  987. FALSE);
  988. pToolbar->SetButtonState(rgSnapinButtons[i].idCommand,
  989. ButtonState[i],
  990. bState[i]);
  991. }
  992. else
  993. {
  994. // hide this button
  995. pToolbar->SetButtonState(rgSnapinButtons[i].idCommand,
  996. HIDDEN,
  997. TRUE);
  998. }
  999. }
  1000. }
  1001. }
  1002. /*!--------------------------------------------------------------------------
  1003. CMTDhcpHandler::OnRefreshStats
  1004. Default implementation for the Stats refresh functionality
  1005. Author: EricDav
  1006. ---------------------------------------------------------------------------*/
  1007. HRESULT
  1008. CMTDhcpHandler::OnRefreshStats
  1009. (
  1010. ITFSNode * pNode,
  1011. LPDATAOBJECT pDataObject,
  1012. DWORD dwType,
  1013. LPARAM arg,
  1014. LPARAM param
  1015. )
  1016. {
  1017. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1018. HRESULT hr = hrOK;
  1019. SPITFSNode spNode;
  1020. SPITFSNodeHandler spHandler;
  1021. ITFSQueryObject * pQuery = NULL;
  1022. // if (m_bExpanded == FALSE)
  1023. // {
  1024. // we cannot get statistics if the node hasn't been expanded yet
  1025. // return hr;
  1026. // }
  1027. // only do stats refresh if the server was loaded correctly.
  1028. if (m_nState == unableToLoad)
  1029. return hr;
  1030. BOOL bLocked = IsLocked();
  1031. if (bLocked)
  1032. {
  1033. // cannot refresh stats if this node is locked
  1034. return hr;
  1035. }
  1036. Lock();
  1037. //OnChangeState(pNode);
  1038. pQuery = OnCreateQuery(pNode);
  1039. Assert(pQuery);
  1040. // notify the UI to change icon, if needed
  1041. //Verify(SUCCEEDED(pComponentData->ChangeNode(this, SCOPE_PANE_CHANGE_ITEM_ICON)));
  1042. Verify(StartBackgroundThread(pNode, m_spTFSCompData->GetHiddenWnd(), pQuery));
  1043. pQuery->Release();
  1044. return hrOK;
  1045. }
  1046. /*!--------------------------------------------------------------------------
  1047. CMTDhcpHandler::OnResultUpdateOptions
  1048. Updates the result pane of any of the option nodes
  1049. Author: EricDav
  1050. ---------------------------------------------------------------------------*/
  1051. HRESULT
  1052. CMTDhcpHandler::OnResultUpdateOptions
  1053. (
  1054. ITFSComponent * pComponent,
  1055. ITFSNode * pNode,
  1056. CClassInfoArray * pClassInfoArray,
  1057. COptionValueEnum * aEnum[],
  1058. int aImages[],
  1059. int nCount
  1060. )
  1061. {
  1062. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1063. HRESULT hr = hrOK;
  1064. CDhcpOption * pOption;
  1065. //
  1066. // Walk the list of children to see if there's anything
  1067. // to put in the result pane
  1068. //
  1069. SPITFSNodeEnum spNodeEnum;
  1070. ITFSNode * pCurrentNode;
  1071. ULONG nNumReturned = 0;
  1072. SPIResultData spResultData;
  1073. int i;
  1074. if (IsMessageView())
  1075. return hr;
  1076. CORg ( pComponent->GetResultData(&spResultData) );
  1077. spResultData->DeleteAllRsltItems();
  1078. pNode->DeleteAllChildren(FALSE);
  1079. for (i = 0; i < nCount; i++)
  1080. {
  1081. while (pOption = aEnum[i]->Next())
  1082. {
  1083. BOOL bValid = TRUE;
  1084. BOOL bAdded = FALSE;
  1085. pNode->GetEnum(&spNodeEnum);
  1086. spNodeEnum->Next(1, &pCurrentNode, &nNumReturned);
  1087. while (nNumReturned)
  1088. {
  1089. // so the node gets release correctly
  1090. SPITFSNode spCurNode;
  1091. spCurNode = pCurrentNode;
  1092. //
  1093. // All containers go into the scope pane and automatically get
  1094. // put into the result pane for us by the MMC
  1095. //
  1096. CDhcpOptionItem * pCurOption = GETHANDLER(CDhcpOptionItem, pCurrentNode);
  1097. if (!pCurrentNode->IsContainer())
  1098. {
  1099. if ( lstrlen(pCurOption->GetClassName()) > 0 &&
  1100. !pClassInfoArray->IsValidClass(pCurOption->GetClassName()) )
  1101. {
  1102. // user class is no longer valid
  1103. bValid = FALSE;
  1104. Trace2("CMTDhcpHandler::OnResultUpdateOptions - Filtering option %d, user class %s\n", pCurOption->GetOptionId(), pOption->GetClassName());
  1105. break;
  1106. }
  1107. else
  1108. if ( pOption->IsVendor() &&
  1109. !pClassInfoArray->IsValidClass(pOption->GetVendor()) )
  1110. {
  1111. // the vendor class for this option has gone away
  1112. bValid = FALSE;
  1113. Trace2("CMTDhcpHandler::OnResultUpdateOptions - Filtering option %d, vendor class %s\n", pCurOption->GetOptionId(), pOption->GetVendor());
  1114. break;
  1115. }
  1116. else
  1117. if ( pCurOption->GetOptionId() == pOption->QueryId() &&
  1118. (lstrcmp(pCurOption->GetVendor(), pOption->GetVendor()) == 0) &&
  1119. (lstrcmp(pCurOption->GetClassName(), pOption->GetClassName()) == 0) )
  1120. {
  1121. // option has already been created, just need to re-add to the result pane
  1122. // update the value in case it has changed
  1123. bAdded = TRUE;
  1124. break;
  1125. }
  1126. }
  1127. spNodeEnum->Next(1, &pCurrentNode, &nNumReturned);
  1128. }
  1129. if (!bAdded && bValid)
  1130. {
  1131. CDhcpOptionItem * pOptionItem;
  1132. SPITFSNode spNode;
  1133. if ( lstrlen(pOption->GetClassName()) > 0 &&
  1134. !pClassInfoArray->IsValidClass(pOption->GetClassName()) )
  1135. {
  1136. // the user class for this option has gone away
  1137. }
  1138. else
  1139. if ( pOption->IsVendor() &&
  1140. !pClassInfoArray->IsValidClass(pOption->GetVendor()) )
  1141. {
  1142. // the vendor class for this option has gone away
  1143. }
  1144. else
  1145. {
  1146. // option hasn't been added to the UI yet. Make it so.
  1147. pOptionItem = new CDhcpOptionItem(m_spTFSCompData, pOption, aImages[i]);
  1148. CORg (CreateLeafTFSNode(&spNode,
  1149. &GUID_DhcpOptionNodeType,
  1150. pOptionItem,
  1151. pOptionItem,
  1152. m_spNodeMgr));
  1153. // Tell the handler to initialize any specific data
  1154. pOptionItem->InitializeNode(spNode);
  1155. // extra addref to keep the node alive while it is on the list
  1156. spNode->SetVisibilityState(TFS_VIS_HIDE);
  1157. pNode->AddChild(spNode);
  1158. pOptionItem->Release();
  1159. AddResultPaneItem(pComponent, spNode);
  1160. }
  1161. }
  1162. spNodeEnum.Set(NULL);
  1163. }
  1164. }
  1165. Error:
  1166. return hr;
  1167. }
  1168. /*---------------------------------------------------------------------------
  1169. Class: CDhcpHandler
  1170. ---------------------------------------------------------------------------*/
  1171. //
  1172. // Called by the result handler when a command comes in that isn't handled
  1173. // by the result handler. If appropriate it passes it to the scope pane hander.
  1174. //
  1175. HRESULT
  1176. CDhcpHandler::HandleScopeCommand
  1177. (
  1178. MMC_COOKIE cookie,
  1179. int nCommandID,
  1180. LPDATAOBJECT pDataObject
  1181. )
  1182. {
  1183. HRESULT hr = hrOK;
  1184. SPITFSNode spNode;
  1185. DATA_OBJECT_TYPES dwType = CCT_RESULT;
  1186. if (IS_SPECIAL_DATAOBJECT(pDataObject))
  1187. {
  1188. dwType = CCT_SCOPE;
  1189. }
  1190. else
  1191. {
  1192. if (pDataObject)
  1193. {
  1194. SPINTERNAL spInternal;
  1195. spInternal = ::ExtractInternalFormat(pDataObject);
  1196. if (spInternal)
  1197. dwType = spInternal->m_type;
  1198. }
  1199. }
  1200. if (dwType == CCT_SCOPE)
  1201. {
  1202. // call the handler to take care of this
  1203. CORg (m_spNodeMgr->FindNode(cookie, &spNode));
  1204. hr = OnCommand(spNode, nCommandID, dwType, pDataObject, (ULONG) spNode->GetData(TFS_DATA_TYPE));
  1205. }
  1206. Error:
  1207. return hr;
  1208. }
  1209. //
  1210. // Called by the result handler to add the scope pane menu items to the menu
  1211. // where appropriate. Puts scope pane menu items in when action menu is clicked
  1212. // and the message view has focus as well as when a right click happens in the white
  1213. // space of the result pane.
  1214. //
  1215. HRESULT
  1216. CDhcpHandler::HandleScopeMenus
  1217. (
  1218. MMC_COOKIE cookie,
  1219. LPDATAOBJECT pDataObject,
  1220. LPCONTEXTMENUCALLBACK pContextMenuCallback,
  1221. long * pInsertionAllowed
  1222. )
  1223. {
  1224. HRESULT hr = hrOK;
  1225. SPITFSNode spNode;
  1226. DATA_OBJECT_TYPES dwType = CCT_RESULT;
  1227. if (IS_SPECIAL_DATAOBJECT(pDataObject))
  1228. {
  1229. dwType = CCT_SCOPE;
  1230. }
  1231. else
  1232. {
  1233. if (pDataObject)
  1234. {
  1235. SPINTERNAL spInternal;
  1236. spInternal = ::ExtractInternalFormat(pDataObject);
  1237. if (spInternal)
  1238. dwType = spInternal->m_type;
  1239. }
  1240. }
  1241. if (dwType == CCT_SCOPE)
  1242. {
  1243. // call the normal handler to put up the menu items
  1244. CORg (m_spNodeMgr->FindNode(cookie, &spNode));
  1245. hr = OnAddMenuItems(spNode, pContextMenuCallback, pDataObject, CCT_SCOPE, (ULONG) spNode->GetData(TFS_DATA_TYPE), pInsertionAllowed);
  1246. }
  1247. Error:
  1248. return hr;
  1249. }
  1250. /*---------------------------------------------------------------------------
  1251. CDhcpHandler::Command
  1252. Description
  1253. Author: EricDav
  1254. ---------------------------------------------------------------------------*/
  1255. STDMETHODIMP
  1256. CDhcpHandler::Command
  1257. (
  1258. ITFSComponent * pComponent,
  1259. MMC_COOKIE cookie,
  1260. int nCommandID,
  1261. LPDATAOBJECT pDataObject
  1262. )
  1263. {
  1264. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1265. HRESULT hr = S_OK;
  1266. // this may have come from the scope pane handler, so pass it up
  1267. hr = HandleScopeCommand(cookie, nCommandID, pDataObject);
  1268. return hr;
  1269. }
  1270. /*!--------------------------------------------------------------------------
  1271. CDhcpHandler::AddMenuItems
  1272. Over-ride this to add our view menu item
  1273. Author: EricDav
  1274. ---------------------------------------------------------------------------*/
  1275. STDMETHODIMP
  1276. CDhcpHandler::AddMenuItems
  1277. (
  1278. ITFSComponent * pComponent,
  1279. MMC_COOKIE cookie,
  1280. LPDATAOBJECT pDataObject,
  1281. LPCONTEXTMENUCALLBACK pContextMenuCallback,
  1282. long * pInsertionAllowed
  1283. )
  1284. {
  1285. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  1286. HRESULT hr = S_OK;
  1287. // figure out if we need to pass this to the scope pane menu handler
  1288. hr = HandleScopeMenus(cookie, pDataObject, pContextMenuCallback, pInsertionAllowed);
  1289. return hr;
  1290. }
  1291. /*!--------------------------------------------------------------------------
  1292. CDhcpHandler::SaveColumns
  1293. -
  1294. Author: EricDav
  1295. ---------------------------------------------------------------------------*/
  1296. HRESULT
  1297. CDhcpHandler::SaveColumns
  1298. (
  1299. ITFSComponent * pComponent,
  1300. MMC_COOKIE cookie,
  1301. LPARAM arg,
  1302. LPARAM lParam
  1303. )
  1304. {
  1305. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1306. HRESULT hr = hrOK;
  1307. LONG_PTR dwNodeType;
  1308. int nCol = 0;
  1309. int nColWidth;
  1310. SPITFSNode spNode, spRootNode;
  1311. SPIHeaderCtrl spHeaderCtrl;
  1312. BOOL bDirty = FALSE;
  1313. if (m_spTFSCompData->GetTaskpadState(GetTaskpadIndex()))
  1314. return hr;
  1315. CORg (m_spNodeMgr->FindNode(cookie, &spNode));
  1316. CORg (pComponent->GetHeaderCtrl(&spHeaderCtrl));
  1317. dwNodeType = spNode->GetData(TFS_DATA_TYPE);
  1318. while (aColumns[dwNodeType][nCol] != 0)
  1319. {
  1320. hr = spHeaderCtrl->GetColumnWidth(nCol, &nColWidth);
  1321. if (SUCCEEDED(hr) &&
  1322. (nColWidth != 0) &&
  1323. aColumnWidths[dwNodeType][nCol] != nColWidth)
  1324. {
  1325. aColumnWidths[dwNodeType][nCol] = nColWidth;
  1326. bDirty = TRUE;
  1327. }
  1328. nCol++;
  1329. }
  1330. if (bDirty)
  1331. {
  1332. CORg (m_spNodeMgr->GetRootNode(&spRootNode));
  1333. spRootNode->SetData(TFS_DATA_DIRTY, TRUE);
  1334. }
  1335. Error:
  1336. return hr;
  1337. }
  1338. /*!--------------------------------------------------------------------------
  1339. CMTDhcpHandler::OnCreateDataObject
  1340. -
  1341. Author: EricDav
  1342. ---------------------------------------------------------------------------*/
  1343. STDMETHODIMP
  1344. CDhcpHandler::OnCreateDataObject
  1345. (
  1346. ITFSComponent * pComponent,
  1347. MMC_COOKIE cookie,
  1348. DATA_OBJECT_TYPES type,
  1349. IDataObject ** ppDataObject
  1350. )
  1351. {
  1352. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1353. Assert(ppDataObject != NULL);
  1354. CDataObject * pObject = NULL;
  1355. SPIDataObject spDataObject;
  1356. pObject = new CDataObject;
  1357. spDataObject = pObject; // do this so that it gets released correctly
  1358. Assert(pObject != NULL);
  1359. if (cookie == MMC_MULTI_SELECT_COOKIE)
  1360. {
  1361. CreateMultiSelectData(pComponent, pObject);
  1362. }
  1363. // Save cookie and type for delayed rendering
  1364. pObject->SetType(type);
  1365. pObject->SetCookie(cookie);
  1366. // Store the coclass with the data object
  1367. pObject->SetClsid(*(m_spTFSComponentData->GetCoClassID()));
  1368. pObject->SetTFSComponentData(m_spTFSComponentData);
  1369. return pObject->QueryInterface(IID_IDataObject,
  1370. reinterpret_cast<void**>(ppDataObject));
  1371. }
  1372. HRESULT
  1373. CDhcpHandler::CreateMultiSelectData(ITFSComponent * pComponent, CDataObject * pObject)
  1374. {
  1375. HRESULT hr = hrOK;
  1376. // build the list of selected nodes
  1377. CTFSNodeList listSelectedNodes;
  1378. CGUIDArray rgGuids;
  1379. UINT cb;
  1380. GUID* pGuid;
  1381. COM_PROTECT_TRY
  1382. {
  1383. CORg (BuildSelectedItemList(pComponent, &listSelectedNodes));
  1384. // collect all of the unique guids
  1385. while (listSelectedNodes.GetCount() > 0)
  1386. {
  1387. SPITFSNode spCurNode;
  1388. const GUID * pGuid;
  1389. spCurNode = listSelectedNodes.RemoveHead();
  1390. pGuid = spCurNode->GetNodeType();
  1391. rgGuids.AddUnique(*pGuid);
  1392. }
  1393. // now put the information in the data object
  1394. pObject->SetMultiSelDobj();
  1395. cb = (UINT) (rgGuids.GetSize() * sizeof(GUID));
  1396. pGuid = new GUID[(UINT)rgGuids.GetSize()];
  1397. CopyMemory(pGuid, rgGuids.GetData(), cb);
  1398. pObject->SetMultiSelData((BYTE*)pGuid, cb);
  1399. COM_PROTECT_ERROR_LABEL;
  1400. }
  1401. COM_PROTECT_CATCH
  1402. return hr;
  1403. }
  1404. /*---------------------------------------------------------------------------
  1405. CDhcpHandler::OnResultDelete
  1406. Description
  1407. Author: EricDav
  1408. ---------------------------------------------------------------------------*/
  1409. HRESULT
  1410. CDhcpHandler::OnResultDelete
  1411. (
  1412. ITFSComponent * pComponent,
  1413. LPDATAOBJECT pDataObject,
  1414. MMC_COOKIE cookie,
  1415. LPARAM arg,
  1416. LPARAM lParam
  1417. )
  1418. {
  1419. HRESULT hr = hrOK;
  1420. Trace0("CDhcpHandler::OnResultDelete received\n");
  1421. // translate this call to the parent and let it handle deletion
  1422. // of result pane items
  1423. SPITFSNode spNode, spParent;
  1424. SPITFSResultHandler spParentRH;
  1425. CORg (m_spNodeMgr->FindNode(cookie, &spNode));
  1426. CORg (spNode->GetParent(&spParent));
  1427. if (spParent == NULL)
  1428. return hr;
  1429. CORg (spParent->GetResultHandler(&spParentRH));
  1430. CORg (spParentRH->Notify(pComponent, spParent->GetData(TFS_DATA_COOKIE), pDataObject, MMCN_DELETE, arg, lParam));
  1431. Error:
  1432. return hr;
  1433. }
  1434. /*!--------------------------------------------------------------------------
  1435. CDhcpHandler::OnResultContextHelp
  1436. Implementation of ITFSResultHandler::OnResultContextHelp
  1437. Author: EricDav
  1438. ---------------------------------------------------------------------------*/
  1439. HRESULT
  1440. CDhcpHandler::OnResultContextHelp
  1441. (
  1442. ITFSComponent * pComponent,
  1443. LPDATAOBJECT pDataObject,
  1444. MMC_COOKIE cookie,
  1445. LPARAM arg,
  1446. LPARAM lParam
  1447. )
  1448. {
  1449. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1450. HRESULT hr = hrOK;
  1451. SPIDisplayHelp spDisplayHelp;
  1452. SPIConsole spConsole;
  1453. pComponent->GetConsole(&spConsole);
  1454. hr = spConsole->QueryInterface (IID_IDisplayHelp, (LPVOID*) &spDisplayHelp);
  1455. ASSERT (SUCCEEDED (hr));
  1456. if ( SUCCEEDED (hr) )
  1457. {
  1458. LPCTSTR pszHelpFile = m_spTFSCompData->GetHTMLHelpFileName();
  1459. if (pszHelpFile == NULL)
  1460. goto Error;
  1461. CString szHelpFilePath;
  1462. UINT nLen = ::GetWindowsDirectory (szHelpFilePath.GetBufferSetLength(2 * MAX_PATH), 2 * MAX_PATH);
  1463. if (nLen == 0)
  1464. {
  1465. hr = E_FAIL;
  1466. goto Error;
  1467. }
  1468. szHelpFilePath.ReleaseBuffer();
  1469. szHelpFilePath += g_szDefaultHelpTopic;
  1470. hr = spDisplayHelp->ShowTopic (T2OLE ((LPTSTR)(LPCTSTR) szHelpFilePath));
  1471. ASSERT (SUCCEEDED (hr));
  1472. }
  1473. Error:
  1474. return hr;
  1475. }
  1476. /*!--------------------------------------------------------------------------
  1477. CDhcpHandler::UserResultNotify
  1478. We override this to handle toolbar notification
  1479. Author: EricDav
  1480. ---------------------------------------------------------------------------*/
  1481. STDMETHODIMP
  1482. CDhcpHandler::UserResultNotify
  1483. (
  1484. ITFSNode * pNode,
  1485. LPARAM dwParam1,
  1486. LPARAM dwParam2
  1487. )
  1488. {
  1489. HRESULT hr = hrOK;
  1490. switch (dwParam1)
  1491. {
  1492. case DHCP_MSG_CONTROLBAR_NOTIFY:
  1493. hr = OnResultControlbarNotify(pNode, reinterpret_cast<LPDHCPTOOLBARNOTIFY>(dwParam2));
  1494. break;
  1495. default:
  1496. // we don't handle this message. Forward it down the line...
  1497. hr = CHandler::UserResultNotify(pNode, dwParam1, dwParam2);
  1498. break;
  1499. }
  1500. return hr;
  1501. }
  1502. /*!--------------------------------------------------------------------------
  1503. CDhcpHandler::UserNotify
  1504. We override this to handle toolbar notification
  1505. Author: EricDav
  1506. ---------------------------------------------------------------------------*/
  1507. STDMETHODIMP
  1508. CDhcpHandler::UserNotify
  1509. (
  1510. ITFSNode * pNode,
  1511. LPARAM dwParam1,
  1512. LPARAM dwParam2
  1513. )
  1514. {
  1515. HRESULT hr = hrOK;
  1516. switch (dwParam1)
  1517. {
  1518. case DHCP_MSG_CONTROLBAR_NOTIFY:
  1519. hr = OnControlbarNotify(pNode, reinterpret_cast<LPDHCPTOOLBARNOTIFY>(dwParam2));
  1520. break;
  1521. default:
  1522. // we don't handle this message. Forward it down the line...
  1523. hr = CHandler::UserNotify(pNode, dwParam1, dwParam2);
  1524. break;
  1525. }
  1526. return hr;
  1527. }
  1528. /*!--------------------------------------------------------------------------
  1529. CDhcpHandler::OnResultControlbarNotify
  1530. On a result pane notification all we can do is enable/hide buttons.
  1531. We cannot attach/detach toolbars.
  1532. Author: EricDav
  1533. ---------------------------------------------------------------------------*/
  1534. HRESULT
  1535. CDhcpHandler::OnResultControlbarNotify
  1536. (
  1537. ITFSNode * pNode,
  1538. LPDHCPTOOLBARNOTIFY pToolbarNotify
  1539. )
  1540. {
  1541. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1542. HRESULT hr = hrOK;
  1543. SPITFSNode spParent;
  1544. SPITFSNodeHandler spNodeHandler;
  1545. switch (pToolbarNotify->event)
  1546. {
  1547. case MMCN_BTN_CLICK:
  1548. // forward the button click to the parent because our result pane
  1549. // items don't have any functions for the toolbar
  1550. // our result pane items only use the standard verbs
  1551. CORg(pNode->GetParent(&spParent));
  1552. CORg(spParent->GetHandler(&spNodeHandler));
  1553. if (spNodeHandler)
  1554. CORg( spNodeHandler->UserNotify(spParent,
  1555. DHCP_MSG_CONTROLBAR_NOTIFY,
  1556. (LPARAM) pToolbarNotify) );
  1557. break;
  1558. case MMCN_SELECT:
  1559. if (!pNode->IsContainer())
  1560. {
  1561. // use the parent's toolbar info
  1562. SPITFSNode spParentNode;
  1563. pNode->GetParent(&spParentNode);
  1564. hr = OnUpdateToolbarButtons(spParentNode,
  1565. pToolbarNotify);
  1566. }
  1567. else
  1568. {
  1569. hr = OnUpdateToolbarButtons(pNode,
  1570. pToolbarNotify);
  1571. }
  1572. break;
  1573. default:
  1574. Assert(FALSE);
  1575. break;
  1576. }
  1577. Error:
  1578. return hr;
  1579. }
  1580. /*!--------------------------------------------------------------------------
  1581. CDhcpHandler::OnControlbarNotify
  1582. Our implementation of the toobar handlers
  1583. Author: EricDav
  1584. ---------------------------------------------------------------------------*/
  1585. HRESULT
  1586. CDhcpHandler::OnControlbarNotify
  1587. (
  1588. ITFSNode * pNode,
  1589. LPDHCPTOOLBARNOTIFY pToolbarNotify
  1590. )
  1591. {
  1592. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1593. HRESULT hr = hrOK;
  1594. switch (pToolbarNotify->event)
  1595. {
  1596. case MMCN_BTN_CLICK:
  1597. hr = OnToolbarButtonClick(pNode,
  1598. pToolbarNotify);
  1599. break;
  1600. case MMCN_SELECT:
  1601. hr = OnUpdateToolbarButtons(pNode,
  1602. pToolbarNotify);
  1603. break;
  1604. default:
  1605. Assert(FALSE);
  1606. }
  1607. return hr;
  1608. }
  1609. /*!--------------------------------------------------------------------------
  1610. CDhcpHandler::OnToolbarButtonClick
  1611. Default implementation of OnToolbarButtonClick
  1612. Author: EricDav
  1613. ---------------------------------------------------------------------------*/
  1614. HRESULT
  1615. CDhcpHandler::OnToolbarButtonClick
  1616. (
  1617. ITFSNode * pNode,
  1618. LPDHCPTOOLBARNOTIFY pToolbarNotify
  1619. )
  1620. {
  1621. // forward this command to the normal command handler
  1622. return OnCommand(pNode, (long) pToolbarNotify->id, (DATA_OBJECT_TYPES) 0, NULL, 0);
  1623. }
  1624. /*!--------------------------------------------------------------------------
  1625. CDhcpHandler::OnUpdateToolbarButtons
  1626. Default implementation of OnUpdateToolbarButtons
  1627. Author: EricDav
  1628. ---------------------------------------------------------------------------*/
  1629. HRESULT
  1630. CDhcpHandler::OnUpdateToolbarButtons
  1631. (
  1632. ITFSNode * pNode,
  1633. LPDHCPTOOLBARNOTIFY pToolbarNotify
  1634. )
  1635. {
  1636. HRESULT hr = hrOK;
  1637. LONG_PTR dwNodeType = pNode->GetData(TFS_DATA_TYPE);
  1638. if (pToolbarNotify->bSelect)
  1639. {
  1640. BOOL bAttach = FALSE;
  1641. // check to see if we should attach this toolbar
  1642. for (int i = 0; i < TOOLBAR_IDX_MAX; i++)
  1643. {
  1644. if (g_SnapinButtonStates[pNode->GetData(TFS_DATA_TYPE)][i] == ENABLED)
  1645. {
  1646. bAttach = TRUE;
  1647. break;
  1648. }
  1649. }
  1650. // attach the toolbar and enable the appropriate buttons
  1651. if (pToolbarNotify->pControlbar)
  1652. {
  1653. if (bAttach)
  1654. {
  1655. // attach the toolbar and enable the appropriate buttons
  1656. pToolbarNotify->pControlbar->Attach(TOOLBAR, pToolbarNotify->pToolbar);
  1657. EnableToolbar(pToolbarNotify->pToolbar,
  1658. g_SnapinButtons,
  1659. ARRAYLEN(g_SnapinButtons),
  1660. g_SnapinButtonStates[dwNodeType]);
  1661. }
  1662. else
  1663. {
  1664. pToolbarNotify->pControlbar->Detach(pToolbarNotify->pToolbar);
  1665. }
  1666. }
  1667. }
  1668. else
  1669. {
  1670. // disable the buttons
  1671. EnableToolbar(pToolbarNotify->pToolbar,
  1672. g_SnapinButtons,
  1673. ARRAYLEN(g_SnapinButtons),
  1674. g_SnapinButtonStates[dwNodeType],
  1675. FALSE);
  1676. }
  1677. return hr;
  1678. }
  1679. /*!--------------------------------------------------------------------------
  1680. CDhcpHandler::EnableToolbar
  1681. Enables the toolbar buttons
  1682. Author: EricDav
  1683. ---------------------------------------------------------------------------*/
  1684. void
  1685. CDhcpHandler::EnableToolbar
  1686. (
  1687. LPTOOLBAR pToolbar,
  1688. MMCBUTTON rgSnapinButtons[],
  1689. int nRgSize,
  1690. MMC_BUTTON_STATE ButtonState[],
  1691. BOOL bState
  1692. )
  1693. {
  1694. for (int i=0; i < nRgSize; ++i)
  1695. {
  1696. if (rgSnapinButtons[i].idCommand != 0)
  1697. {
  1698. if (ButtonState[i] == ENABLED)
  1699. {
  1700. // unhide this button before enabling
  1701. pToolbar->SetButtonState(rgSnapinButtons[i].idCommand,
  1702. HIDDEN,
  1703. FALSE);
  1704. pToolbar->SetButtonState(rgSnapinButtons[i].idCommand,
  1705. ButtonState[i],
  1706. bState);
  1707. }
  1708. else
  1709. {
  1710. // hide this button
  1711. pToolbar->SetButtonState(rgSnapinButtons[i].idCommand,
  1712. HIDDEN,
  1713. TRUE);
  1714. }
  1715. }
  1716. }
  1717. }
  1718. /*!--------------------------------------------------------------------------
  1719. CDhcpHandler::OnResultSelect
  1720. Handles the MMCN_SELECT notifcation
  1721. Author: EricDav
  1722. ---------------------------------------------------------------------------*/
  1723. HRESULT
  1724. CDhcpHandler::OnResultSelect
  1725. (
  1726. ITFSComponent * pComponent,
  1727. LPDATAOBJECT pDataObject,
  1728. MMC_COOKIE cookie,
  1729. LPARAM arg,
  1730. LPARAM lParam
  1731. )
  1732. {
  1733. SPIConsoleVerb spConsoleVerb;
  1734. SPITFSNode spNode;
  1735. HRESULT hr = hrOK;
  1736. BOOL bStates[ARRAYLEN(g_ConsoleVerbs)];
  1737. int i;
  1738. CORg (pComponent->GetConsoleVerb(&spConsoleVerb));
  1739. CORg (m_spNodeMgr->FindNode(cookie, &spNode));
  1740. for (i = 0; i < ARRAYLEN(g_ConsoleVerbs); bStates[i++] = TRUE);
  1741. EnableVerbs(spConsoleVerb, g_ConsoleVerbStates[spNode->GetData(TFS_DATA_TYPE)], bStates);
  1742. Error:
  1743. return hr;
  1744. }
  1745. /*!--------------------------------------------------------------------------
  1746. CMTDhcpHandler::EnableVerbs
  1747. Enables the toolbar buttons
  1748. Author: EricDav
  1749. ---------------------------------------------------------------------------*/
  1750. void
  1751. CDhcpHandler::EnableVerbs
  1752. (
  1753. IConsoleVerb * pConsoleVerb,
  1754. MMC_BUTTON_STATE ButtonState[],
  1755. BOOL bState[]
  1756. )
  1757. {
  1758. if (pConsoleVerb == NULL)
  1759. {
  1760. Assert(FALSE);
  1761. return;
  1762. }
  1763. for (int i=0; i < ARRAYLEN(g_ConsoleVerbs); ++i)
  1764. {
  1765. if (ButtonState[i] == ENABLED)
  1766. {
  1767. // unhide this button before enabling
  1768. pConsoleVerb->SetVerbState(g_ConsoleVerbs[i],
  1769. HIDDEN,
  1770. FALSE);
  1771. pConsoleVerb->SetVerbState(g_ConsoleVerbs[i],
  1772. ButtonState[i],
  1773. bState[i]);
  1774. }
  1775. else
  1776. {
  1777. // hide this button
  1778. pConsoleVerb->SetVerbState(g_ConsoleVerbs[i],
  1779. HIDDEN,
  1780. TRUE);
  1781. }
  1782. }
  1783. pConsoleVerb->SetDefaultVerb(m_verbDefault);
  1784. }