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

1910 lines
52 KiB

  1. /**********************************************************************/
  2. /** Microsoft Windows/NT **/
  3. /** Copyright(c) Microsoft Corporation, 1997 - 1999 **/
  4. /**********************************************************************/
  5. /*
  6. ssview.cpp
  7. IPX Static Services node implementation.
  8. FILE HISTORY:
  9. */
  10. #include "stdafx.h"
  11. #include "util.h"
  12. #include "ssview.h"
  13. #include "reg.h"
  14. #include "ipxadmin.h"
  15. #include "rtrutil.h" // smart MPR handle pointers
  16. #include "ipxstrm.h" // IPXAdminConfigStream
  17. #include "strmap.h" // XXXtoCString functions
  18. #include "service.h" // TFS service APIs
  19. #include "format.h" // FormatNumber function
  20. #include "coldlg.h" // columndlg
  21. #include "ipxutil.h"
  22. #include "column.h" // ComponentConfigStream
  23. #include "rtrui.h"
  24. #include "routprot.h" // IP_LOCAL
  25. #include "rtrres.h"
  26. #include "dumbprop.h"
  27. #include "ipxstaticsvc.h"
  28. /*---------------------------------------------------------------------------
  29. Keep this in sync with the column ids in ssview.h
  30. ---------------------------------------------------------------------------*/
  31. extern const ContainerColumnInfo s_rgSSViewColumnInfo[];
  32. const ContainerColumnInfo s_rgSSViewColumnInfo[] =
  33. {
  34. { IDS_IPX_SS_COL_NAME, CON_SORT_BY_STRING, TRUE, COL_IF_NAME },
  35. { IDS_IPX_SS_COL_SERVICE_TYPE, CON_SORT_BY_STRING, TRUE, COL_STRING },
  36. { IDS_IPX_SS_COL_SERVICE_NAME, CON_SORT_BY_STRING, TRUE, COL_STRING },
  37. { IDS_IPX_SS_COL_SERVICE_ADDRESS,CON_SORT_BY_STRING, TRUE, COL_STRING },
  38. { IDS_IPX_SS_COL_HOP_COUNT, CON_SORT_BY_DWORD, TRUE, COL_SMALL_NUM},
  39. };
  40. /*---------------------------------------------------------------------------
  41. IpxSSHandler implementation
  42. ---------------------------------------------------------------------------*/
  43. DEBUG_DECLARE_INSTANCE_COUNTER(IpxSSHandler)
  44. IpxSSHandler::IpxSSHandler(ITFSComponentData *pCompData)
  45. : BaseContainerHandler(pCompData, COLUMNS_STATICSERVICES,
  46. s_rgSSViewColumnInfo),
  47. m_ulConnId(0),
  48. m_ulRefreshConnId(0)
  49. {
  50. // Setup the verb states
  51. m_rgButtonState[MMC_VERB_REFRESH_INDEX] = ENABLED;
  52. m_bState[MMC_VERB_REFRESH_INDEX] = TRUE;
  53. DEBUG_INCREMENT_INSTANCE_COUNTER(IpxSSHandler)
  54. }
  55. IpxSSHandler::~IpxSSHandler()
  56. {
  57. DEBUG_DECREMENT_INSTANCE_COUNTER(IpxSSHandler)
  58. }
  59. STDMETHODIMP IpxSSHandler::QueryInterface(REFIID riid, LPVOID *ppv)
  60. {
  61. // Is the pointer bad?
  62. if (ppv == NULL)
  63. return E_INVALIDARG;
  64. // Place NULL in *ppv in case of failure
  65. *ppv = NULL;
  66. // This is the non-delegating IUnknown implementation
  67. if (riid == IID_IUnknown)
  68. *ppv = (LPVOID) this;
  69. else if (riid == IID_IRtrAdviseSink)
  70. *ppv = &m_IRtrAdviseSink;
  71. else
  72. return BaseContainerHandler::QueryInterface(riid, ppv);
  73. // If we're going to return an interface, AddRef it first
  74. if (*ppv)
  75. {
  76. ((LPUNKNOWN) *ppv)->AddRef();
  77. return hrOK;
  78. }
  79. else
  80. return E_NOINTERFACE;
  81. }
  82. /*!--------------------------------------------------------------------------
  83. IpxSSHandler::DestroyHandler
  84. Implementation of ITFSNodeHandler::DestroyHandler
  85. Author: KennT
  86. ---------------------------------------------------------------------------*/
  87. STDMETHODIMP IpxSSHandler::DestroyHandler(ITFSNode *pNode)
  88. {
  89. IPXConnection * pIPXConn;
  90. pIPXConn = GET_IPX_SS_NODEDATA(pNode);
  91. pIPXConn->Release();
  92. if (m_ulRefreshConnId)
  93. {
  94. SPIRouterRefresh spRefresh;
  95. if (m_spRouterInfo)
  96. m_spRouterInfo->GetRefreshObject(&spRefresh);
  97. if (spRefresh)
  98. spRefresh->UnadviseRefresh(m_ulRefreshConnId);
  99. }
  100. m_ulRefreshConnId = 0;
  101. if (m_ulConnId)
  102. m_spRtrMgrInfo->RtrUnadvise(m_ulConnId);
  103. m_ulConnId = 0;
  104. m_spRtrMgrInfo.Release();
  105. m_spRouterInfo.Release();
  106. return hrOK;
  107. }
  108. /*!--------------------------------------------------------------------------
  109. IpxSSHandler::HasPropertyPages
  110. Implementation of ITFSNodeHandler::HasPropertyPages
  111. NOTE: the root node handler has to over-ride this function to
  112. handle the snapin manager property page (wizard) case!!!
  113. Author: KennT
  114. ---------------------------------------------------------------------------*/
  115. STDMETHODIMP
  116. IpxSSHandler::HasPropertyPages
  117. (
  118. ITFSNode * pNode,
  119. LPDATAOBJECT pDataObject,
  120. DATA_OBJECT_TYPES type,
  121. DWORD dwType
  122. )
  123. {
  124. return hrFalse;
  125. }
  126. /*---------------------------------------------------------------------------
  127. Menu data structure for our menus
  128. ---------------------------------------------------------------------------*/
  129. static const SRouterNodeMenu s_rgIfNodeMenu[] =
  130. {
  131. { IDS_MENU_IPX_SS_NEW_SERVICE, 0,
  132. CCM_INSERTIONPOINTID_PRIMARY_TOP },
  133. { IDS_MENU_SEPARATOR, 0,
  134. CCM_INSERTIONPOINTID_PRIMARY_TOP },
  135. { IDS_MENU_IPX_SS_TASK_SERVICE, 0,
  136. CCM_INSERTIONPOINTID_PRIMARY_TOP },
  137. };
  138. /*!--------------------------------------------------------------------------
  139. IpxSSHandler::OnAddMenuItems
  140. Implementation of ITFSNodeHandler::OnAddMenuItems
  141. Author: KennT
  142. ---------------------------------------------------------------------------*/
  143. STDMETHODIMP IpxSSHandler::OnAddMenuItems(
  144. ITFSNode *pNode,
  145. LPCONTEXTMENUCALLBACK pContextMenuCallback,
  146. LPDATAOBJECT lpDataObject,
  147. DATA_OBJECT_TYPES type,
  148. DWORD dwType,
  149. long *pInsertionAllowed)
  150. {
  151. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  152. HRESULT hr = S_OK;
  153. IpxSSHandler::SMenuData menuData;
  154. COM_PROTECT_TRY
  155. {
  156. menuData.m_spNode.Set(pNode);
  157. hr = AddArrayOfMenuItems(pNode, s_rgIfNodeMenu,
  158. DimensionOf(s_rgIfNodeMenu),
  159. pContextMenuCallback,
  160. *pInsertionAllowed,
  161. reinterpret_cast<INT_PTR>(&menuData));
  162. }
  163. COM_PROTECT_CATCH;
  164. return hr;
  165. }
  166. HRESULT IpxSSHandler::OnResultRefresh(ITFSComponent * pComponent, LPDATAOBJECT pDataObject, MMC_COOKIE cookie, LPARAM arg, LPARAM lParam)
  167. {
  168. HRESULT hr = hrOK;
  169. SPITFSNode spNode, spParent;
  170. SPITFSResultHandler spParentRH;
  171. m_spNodeMgr->FindNode(cookie, &spNode);
  172. // forward this command to the parent to handle
  173. CORg (spNode->GetParent(&spParent));
  174. CORg (spParent->GetResultHandler(&spParentRH));
  175. CORg (spParentRH->Notify(pComponent, spParent->GetData(TFS_DATA_COOKIE), pDataObject, MMCN_REFRESH, arg, lParam));
  176. Error:
  177. return hrOK;
  178. }
  179. /*!--------------------------------------------------------------------------
  180. IpxSSHandler::OnCommand
  181. Implementation of ITFSNodeHandler::OnCommand
  182. Author: KennT
  183. ---------------------------------------------------------------------------*/
  184. STDMETHODIMP IpxSSHandler::OnCommand(ITFSNode *pNode, long nCommandId,
  185. DATA_OBJECT_TYPES type,
  186. LPDATAOBJECT pDataObject,
  187. DWORD dwType)
  188. {
  189. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  190. HRESULT hr = S_OK;
  191. COM_PROTECT_TRY
  192. {
  193. switch (nCommandId)
  194. {
  195. case IDS_MENU_IPX_SS_NEW_SERVICE:
  196. hr = OnNewService(pNode);
  197. if (!FHrSucceeded(hr))
  198. DisplayErrorMessage(NULL, hr);
  199. break;
  200. case IDS_MENU_IPX_SS_TASK_SERVICE:
  201. hr = ForwardCommandToParent(pNode,
  202. IDS_MENU_IPXSUM_TASK_SERVICE_TABLE,
  203. type, pDataObject, dwType);
  204. break;
  205. case IDS_MENU_SYNC:
  206. SynchronizeNodeData(pNode);
  207. break;
  208. }
  209. }
  210. COM_PROTECT_CATCH;
  211. return hr;
  212. }
  213. /*!--------------------------------------------------------------------------
  214. IpxSSHandler::GenerateListOfServices
  215. -
  216. Author: KennT
  217. ---------------------------------------------------------------------------*/
  218. HRESULT IpxSSHandler::GenerateListOfServices(ITFSNode *pNode, IpxSSList *pSSList)
  219. {
  220. Assert(pSSList);
  221. HRESULT hr = hrOK;
  222. SPIEnumInterfaceInfo spEnumIf;
  223. SPIInterfaceInfo spIf;
  224. SPIRtrMgrInterfaceInfo spRmIf;
  225. SPIInfoBase spInfoBase;
  226. PIPX_STATIC_SERVICE_INFO pService;
  227. InfoBlock * pBlock;
  228. int i;
  229. IpxSSListEntry * pSSEntry;
  230. COM_PROTECT_TRY
  231. {
  232. // Ok go through and find all of the static Services
  233. CORg( m_spRouterInfo->EnumInterface(&spEnumIf) );
  234. for (; spEnumIf->Next(1, &spIf, NULL) == hrOK; spIf.Release())
  235. {
  236. // Get the next interface
  237. spRmIf.Release();
  238. if (spIf->FindRtrMgrInterface(PID_IPX, &spRmIf) != hrOK)
  239. continue;
  240. // Load IP information for this interface
  241. spInfoBase.Release();
  242. if (spRmIf->GetInfoBase(NULL, NULL, NULL, &spInfoBase) != hrOK)
  243. continue;
  244. // Retrieve the data for the IPX_STATIC_SERVICE_INFO block
  245. if (spInfoBase->GetBlock(IPX_STATIC_SERVICE_INFO_TYPE, &pBlock, 0) != hrOK)
  246. continue;
  247. pService = (PIPX_STATIC_SERVICE_INFO) pBlock->pData;
  248. // Update our list of Services with the Services read from this
  249. // interface
  250. for (i=0; i<(int) pBlock->dwCount; i++, pService++)
  251. {
  252. pSSEntry = new IpxSSListEntry;
  253. pSSEntry->m_spIf.Set(spIf);
  254. pSSEntry->m_service = *pService;
  255. pSSList->AddTail(pSSEntry);
  256. }
  257. }
  258. }
  259. COM_PROTECT_CATCH;
  260. if (!FHrSucceeded(hr))
  261. {
  262. // Should make sure that we get the SSList cleaned up
  263. while (!pSSList->IsEmpty())
  264. delete pSSList->RemoveHead();
  265. }
  266. Error:
  267. return hr;
  268. }
  269. /*!--------------------------------------------------------------------------
  270. IpxSSHandler::OnExpand
  271. -
  272. Author: KennT
  273. ---------------------------------------------------------------------------*/
  274. HRESULT IpxSSHandler::OnExpand(ITFSNode *pNode,
  275. LPDATAOBJECT pDataObject,
  276. DWORD dwType,
  277. LPARAM arg,
  278. LPARAM lParam)
  279. {
  280. HRESULT hr = hrOK;
  281. IpxSSList SSList;
  282. IpxSSListEntry * pSSEntry;
  283. if (m_bExpanded)
  284. return hrOK;
  285. COM_PROTECT_TRY
  286. {
  287. // Ok go through and find all of the static Services
  288. CORg( GenerateListOfServices(pNode, &SSList) );
  289. // Now iterate through the list of static Services adding them
  290. // all in. Ideally we could merge this into the Refresh code,
  291. // but the refresh code can't assume a blank slate.
  292. while (!SSList.IsEmpty())
  293. {
  294. pSSEntry = SSList.RemoveHead();
  295. AddStaticServiceNode(pNode, pSSEntry);
  296. delete pSSEntry;
  297. }
  298. COM_PROTECT_ERROR_LABEL;
  299. }
  300. COM_PROTECT_CATCH;
  301. // Should make sure that we get the SSList cleaned up
  302. while (!SSList.IsEmpty())
  303. delete SSList.RemoveHead();
  304. m_bExpanded = TRUE;
  305. return hr;
  306. }
  307. /*!--------------------------------------------------------------------------
  308. IpxSSHandler::GetString
  309. Implementation of ITFSNodeHandler::GetString
  310. We don't need to do anything, since our root node is an extension
  311. only and thus can't do anything to the node text.
  312. Author: KennT
  313. ---------------------------------------------------------------------------*/
  314. STDMETHODIMP_(LPCTSTR) IpxSSHandler::GetString(ITFSNode *pNode, int nCol)
  315. {
  316. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  317. HRESULT hr = hrOK;
  318. COM_PROTECT_TRY
  319. {
  320. if (m_stTitle.IsEmpty())
  321. m_stTitle.LoadString(IDS_IPX_SS_TITLE);
  322. }
  323. COM_PROTECT_CATCH;
  324. return m_stTitle;
  325. }
  326. /*!--------------------------------------------------------------------------
  327. IpxSSHandler::OnCreateDataObject
  328. -
  329. Author: KennT
  330. ---------------------------------------------------------------------------*/
  331. STDMETHODIMP IpxSSHandler::OnCreateDataObject(MMC_COOKIE cookie, DATA_OBJECT_TYPES type, IDataObject **ppDataObject)
  332. {
  333. HRESULT hr = hrOK;
  334. COM_PROTECT_TRY
  335. {
  336. Assert(m_spRtrMgrInfo);
  337. CORg( CreateDataObjectFromRtrMgrInfo(m_spRtrMgrInfo,
  338. type, cookie, m_spTFSCompData,
  339. ppDataObject) );
  340. COM_PROTECT_ERROR_LABEL;
  341. }
  342. COM_PROTECT_CATCH;
  343. return hr;
  344. }
  345. /*!--------------------------------------------------------------------------
  346. IpxSSHandler::Init
  347. -
  348. Author: KennT
  349. ---------------------------------------------------------------------------*/
  350. HRESULT IpxSSHandler::Init(IRtrMgrInfo *pRmInfo, IPXAdminConfigStream *pConfigStream)
  351. {
  352. m_spRtrMgrInfo.Set(pRmInfo);
  353. if (pRmInfo)
  354. pRmInfo->GetParentRouterInfo(&m_spRouterInfo);
  355. m_pConfigStream = pConfigStream;
  356. // Also need to register for change notifications
  357. Assert(m_ulConnId == 0);
  358. m_spRtrMgrInfo->RtrAdvise(&m_IRtrAdviseSink, &m_ulConnId, 0);
  359. return hrOK;
  360. }
  361. /*!--------------------------------------------------------------------------
  362. IpxSSHandler::ConstructNode
  363. Initializes the root node (sets it up).
  364. Author: KennT
  365. ---------------------------------------------------------------------------*/
  366. HRESULT IpxSSHandler::ConstructNode(ITFSNode *pNode, LPCTSTR pszName,
  367. IPXConnection *pIPXConn)
  368. {
  369. Assert(pIPXConn);
  370. HRESULT hr = hrOK;
  371. if (pNode == NULL)
  372. return hrOK;
  373. COM_PROTECT_TRY
  374. {
  375. // Need to initialize the data for the root node
  376. pNode->SetData(TFS_DATA_IMAGEINDEX, IMAGE_IDX_IPX_NODE_GENERAL);
  377. pNode->SetData(TFS_DATA_OPENIMAGEINDEX, IMAGE_IDX_IPX_NODE_GENERAL);
  378. pNode->SetData(TFS_DATA_SCOPEID, 0);
  379. // This is a leaf node in the scope pane
  380. pNode->SetData(TFS_DATA_SCOPE_LEAF_NODE, TRUE);
  381. m_cookie = reinterpret_cast<DWORD_PTR>(pNode);
  382. pNode->SetData(TFS_DATA_COOKIE, m_cookie);
  383. pNode->SetNodeType(&GUID_IPXStaticServicesNodeType);
  384. // Setup the node data
  385. pIPXConn->AddRef();
  386. SET_IPX_SS_NODEDATA(pNode, pIPXConn);
  387. }
  388. COM_PROTECT_CATCH;
  389. if (!FHrSucceeded(hr))
  390. {
  391. SET_IPX_SS_NODEDATA(pNode, NULL);
  392. }
  393. return hr;
  394. }
  395. /*!--------------------------------------------------------------------------
  396. IpxSSHandler::AddStaticServiceNode
  397. -
  398. Author: KennT
  399. ---------------------------------------------------------------------------*/
  400. HRESULT IpxSSHandler::AddStaticServiceNode(ITFSNode *pParent, IpxSSListEntry *pService)
  401. {
  402. IpxServiceHandler * pHandler;
  403. SPITFSResultHandler spHandler;
  404. SPITFSNode spNode;
  405. HRESULT hr = hrOK;
  406. BaseIPXResultNodeData * pData;
  407. IPXConnection * pIPXConn;
  408. // Create the handler for this node
  409. pHandler = new IpxServiceHandler(m_spTFSCompData);
  410. spHandler = pHandler;
  411. CORg( pHandler->Init(pService->m_spIf, pParent) );
  412. pIPXConn = GET_IPX_SS_NODEDATA(pParent);
  413. // Create a result item node (or a leaf node)
  414. CORg( CreateLeafTFSNode(&spNode,
  415. NULL,
  416. static_cast<ITFSNodeHandler *>(pHandler),
  417. static_cast<ITFSResultHandler *>(pHandler),
  418. m_spNodeMgr) );
  419. CORg( pHandler->ConstructNode(spNode, pService->m_spIf, pIPXConn) );
  420. pData = GET_BASEIPXRESULT_NODEDATA(spNode);
  421. Assert(pData);
  422. ASSERT_BASEIPXRESULT_NODEDATA(pData);
  423. // Set the data for this node
  424. SetServiceData(pData, pService);
  425. // Make the node immediately visible
  426. CORg( spNode->SetVisibilityState(TFS_VIS_SHOW) );
  427. CORg( pParent->AddChild(spNode) );
  428. Error:
  429. return hr;
  430. }
  431. /*!--------------------------------------------------------------------------
  432. IpxSSHandler::SynchronizeNodeData
  433. -
  434. Author: KennT
  435. ---------------------------------------------------------------------------*/
  436. HRESULT IpxSSHandler::SynchronizeNodeData(ITFSNode *pNode)
  437. {
  438. HRESULT hr = hrOK;
  439. BaseIPXResultNodeData * pNodeData;
  440. SPITFSNodeEnum spNodeEnum;
  441. SPITFSNode spChildNode;
  442. BOOL fFound;
  443. IpxSSList SSList;
  444. IpxSSList newSSList;
  445. IpxSSListEntry * pSSEntry;
  446. USES_CONVERSION;
  447. COM_PROTECT_TRY
  448. {
  449. // Mark all of the nodes
  450. CORg( pNode->GetEnum(&spNodeEnum) );
  451. MarkAllNodes(pNode, spNodeEnum);
  452. // Go out and grab the data, merge the new data in with the old data
  453. // This is the data-gathering code and this is what should go
  454. // on the background thread for the refresh code.
  455. CORg( GenerateListOfServices(pNode, &SSList) );
  456. while (!SSList.IsEmpty())
  457. {
  458. pSSEntry = SSList.RemoveHead();
  459. // Look for this entry in our current list of nodes
  460. spNodeEnum->Reset();
  461. spChildNode.Release();
  462. fFound = FALSE;
  463. for (;spNodeEnum->Next(1, &spChildNode, NULL) == hrOK; spChildNode.Release())
  464. {
  465. TCHAR szNumber[32];
  466. pNodeData = GET_BASEIPXRESULT_NODEDATA(spChildNode);
  467. Assert(pNodeData);
  468. ASSERT_BASEIPXRESULT_NODEDATA(pNodeData);
  469. if ((pNodeData->m_rgData[IPX_SS_SI_SERVICE_TYPE].m_dwData ==
  470. pSSEntry->m_service.Type) &&
  471. (StriCmp(pNodeData->m_rgData[IPX_SS_SI_SERVICE_NAME].m_stData,
  472. A2CT((LPSTR) pSSEntry->m_service.Name)) == 0) &&
  473. (StriCmp(pNodeData->m_spIf->GetId(), pSSEntry->m_spIf->GetId()) == 0))
  474. {
  475. // Ok, this route already exists, update the metric
  476. // and mark it
  477. Assert(pNodeData->m_dwMark == FALSE);
  478. pNodeData->m_dwMark = TRUE;
  479. fFound = TRUE;
  480. SetServiceData(pNodeData, pSSEntry);
  481. // Force MMC to redraw the node
  482. spChildNode->ChangeNode(RESULT_PANE_CHANGE_ITEM_DATA);
  483. break;
  484. }
  485. }
  486. if (fFound)
  487. delete pSSEntry;
  488. else
  489. newSSList.AddTail(pSSEntry);
  490. }
  491. // Now remove all nodes that were not marked
  492. RemoveAllUnmarkedNodes(pNode, spNodeEnum);
  493. // Now iterate through the list of static Services adding them
  494. // all in. Ideally we could merge this into the Refresh code,
  495. // but the refresh code can't assume a blank slate.
  496. POSITION pos;
  497. while (!newSSList.IsEmpty())
  498. {
  499. pSSEntry = newSSList.RemoveHead();
  500. AddStaticServiceNode(pNode, pSSEntry);
  501. delete pSSEntry;
  502. }
  503. COM_PROTECT_ERROR_LABEL;
  504. }
  505. COM_PROTECT_CATCH;
  506. while (!SSList.IsEmpty())
  507. delete SSList.RemoveHead();
  508. while (!newSSList.IsEmpty())
  509. delete newSSList.RemoveHead();
  510. return hr;
  511. }
  512. /*!--------------------------------------------------------------------------
  513. IpxSSHandler::MarkAllNodes
  514. -
  515. Author: KennT
  516. ---------------------------------------------------------------------------*/
  517. HRESULT IpxSSHandler::MarkAllNodes(ITFSNode *pNode, ITFSNodeEnum *pEnum)
  518. {
  519. SPITFSNode spChildNode;
  520. BaseIPXResultNodeData * pNodeData;
  521. pEnum->Reset();
  522. for ( ;pEnum->Next(1, &spChildNode, NULL) == hrOK; spChildNode.Release())
  523. {
  524. pNodeData = GET_BASEIPXRESULT_NODEDATA(spChildNode);
  525. Assert(pNodeData);
  526. ASSERT_BASEIPXRESULT_NODEDATA(pNodeData);
  527. pNodeData->m_dwMark = FALSE;
  528. }
  529. return hrOK;
  530. }
  531. /*!--------------------------------------------------------------------------
  532. IpxSSHandler::RemoveAllUnmarkedNodes
  533. -
  534. Author: KennT
  535. ---------------------------------------------------------------------------*/
  536. HRESULT IpxSSHandler::RemoveAllUnmarkedNodes(ITFSNode *pNode, ITFSNodeEnum *pEnum)
  537. {
  538. HRESULT hr = hrOK;
  539. SPITFSNode spChildNode;
  540. BaseIPXResultNodeData * pNodeData;
  541. pEnum->Reset();
  542. for ( ;pEnum->Next(1, &spChildNode, NULL) == hrOK; spChildNode.Release())
  543. {
  544. pNodeData = GET_BASEIPXRESULT_NODEDATA(spChildNode);
  545. Assert(pNodeData);
  546. ASSERT_BASEIPXRESULT_NODEDATA(pNodeData);
  547. if (pNodeData->m_dwMark == FALSE)
  548. {
  549. pNode->RemoveChild(spChildNode);
  550. spChildNode->Destroy();
  551. }
  552. }
  553. return hr;
  554. }
  555. /*---------------------------------------------------------------------------
  556. This is the set of menus that will appear when a right-click is
  557. done on the blank area of the result pane.
  558. ---------------------------------------------------------------------------*/
  559. static const SRouterNodeMenu s_rgIfResultNodeMenu[] =
  560. {
  561. { IDS_MENU_IPX_SS_NEW_SERVICE, 0,
  562. CCM_INSERTIONPOINTID_PRIMARY_TOP },
  563. { IDS_MENU_SEPARATOR, 0,
  564. CCM_INSERTIONPOINTID_PRIMARY_TOP },
  565. { IDS_MENU_IPX_SS_TASK_SERVICE, 0,
  566. CCM_INSERTIONPOINTID_PRIMARY_TOP },
  567. };
  568. /*!--------------------------------------------------------------------------
  569. IpxSSHandler::AddMenuItems
  570. Implementation of ITFSResultHandler::AddMenuItems
  571. Use this to add commands to the context menu of the blank areas
  572. of the result pane.
  573. Author: KennT
  574. ---------------------------------------------------------------------------*/
  575. STDMETHODIMP IpxSSHandler::AddMenuItems(ITFSComponent *pComponent,
  576. MMC_COOKIE cookie,
  577. LPDATAOBJECT pDataObject,
  578. LPCONTEXTMENUCALLBACK pCallback,
  579. long *pInsertionAllowed)
  580. {
  581. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  582. HRESULT hr = hrOK;
  583. SPITFSNode spNode;
  584. IpxSSHandler::SMenuData menuData;
  585. COM_PROTECT_TRY
  586. {
  587. m_spNodeMgr->FindNode(cookie, &spNode);
  588. menuData.m_spNode.Set(spNode);
  589. hr = AddArrayOfMenuItems(spNode,
  590. s_rgIfResultNodeMenu,
  591. DimensionOf(s_rgIfResultNodeMenu),
  592. pCallback,
  593. *pInsertionAllowed,
  594. reinterpret_cast<INT_PTR>(&menuData));
  595. }
  596. COM_PROTECT_CATCH;
  597. return hr;
  598. }
  599. /*!--------------------------------------------------------------------------
  600. IpxSSHandler::Command
  601. -
  602. Author: KennT
  603. ---------------------------------------------------------------------------*/
  604. STDMETHODIMP IpxSSHandler::Command(ITFSComponent *pComponent,
  605. MMC_COOKIE cookie,
  606. int nCommandID,
  607. LPDATAOBJECT pDataObject)
  608. {
  609. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  610. SPITFSNode spNode;
  611. HRESULT hr = hrOK;
  612. switch (nCommandID)
  613. {
  614. case IDS_MENU_IPX_SS_NEW_SERVICE:
  615. {
  616. m_spNodeMgr->FindNode(cookie, &spNode);
  617. hr = OnNewService(spNode);
  618. if (!FHrSucceeded(hr))
  619. DisplayErrorMessage(NULL, hr);
  620. }
  621. break;
  622. case IDS_MENU_IPX_SS_TASK_SERVICE:
  623. {
  624. m_spNodeMgr->FindNode(cookie, &spNode);
  625. hr = ForwardCommandToParent(spNode,
  626. IDS_MENU_IPXSUM_TASK_SERVICE_TABLE,
  627. CCT_RESULT, NULL, 0
  628. );
  629. }
  630. break;
  631. }
  632. return hr;
  633. }
  634. /*!--------------------------------------------------------------------------
  635. IpxSSHandler::CompareItems
  636. -
  637. Author: KennT
  638. ---------------------------------------------------------------------------*/
  639. STDMETHODIMP_(int) IpxSSHandler::CompareItems(
  640. ITFSComponent * pComponent,
  641. MMC_COOKIE cookieA,
  642. MMC_COOKIE cookieB,
  643. int nCol)
  644. {
  645. // Get the strings from the nodes and use that as a basis for
  646. // comparison.
  647. SPITFSNode spNode;
  648. SPITFSResultHandler spResult;
  649. m_spNodeMgr->FindNode(cookieA, &spNode);
  650. spNode->GetResultHandler(&spResult);
  651. return spResult->CompareItems(pComponent, cookieA, cookieB, nCol);
  652. }
  653. /*!--------------------------------------------------------------------------
  654. IpxSSHandler::OnNewService
  655. -
  656. Author: KennT
  657. ---------------------------------------------------------------------------*/
  658. HRESULT IpxSSHandler::OnNewService(ITFSNode *pNode)
  659. {
  660. HRESULT hr = hrOK;
  661. IpxSSListEntry SREntry;
  662. CStaticServiceDlg srdlg(&SREntry, 0, m_spRouterInfo);
  663. SPIInfoBase spInfoBase;
  664. SPIRtrMgrInterfaceInfo spRmIf;
  665. IPXConnection * pIPXConn;
  666. InfoBlock * pBlock;
  667. pIPXConn = GET_IPX_SS_NODEDATA(pNode);
  668. Assert(pIPXConn);
  669. ::ZeroMemory(&(SREntry.m_service), sizeof(SREntry.m_service));
  670. if (srdlg.DoModal() == IDOK)
  671. {
  672. CORg( SREntry.m_spIf->FindRtrMgrInterface(PID_IPX, &spRmIf) );
  673. CORg( spRmIf->GetInfoBase(pIPXConn->GetConfigHandle(),
  674. NULL,
  675. NULL,
  676. &spInfoBase));
  677. // Ok, go ahead and add the route
  678. // Get the IPX_STATIC_SERVICE_INFO block from the interface
  679. spInfoBase->GetBlock(IPX_STATIC_SERVICE_INFO_TYPE, &pBlock, 0);
  680. CORg( AddStaticService(&SREntry, spInfoBase, pBlock) );
  681. // Update the interface information
  682. CORg( spRmIf->Save(SREntry.m_spIf->GetMachineName(),
  683. pIPXConn->GetConfigHandle(),
  684. NULL,
  685. NULL,
  686. spInfoBase,
  687. 0));
  688. // Refresh the node
  689. SynchronizeNodeData(pNode);
  690. }
  691. Error:
  692. return hr;
  693. }
  694. ImplementEmbeddedUnknown(IpxSSHandler, IRtrAdviseSink)
  695. STDMETHODIMP IpxSSHandler::EIRtrAdviseSink::OnChange(LONG_PTR ulConn,
  696. DWORD dwChangeType, DWORD dwObjectType, LPARAM lUserParam, LPARAM lParam)
  697. {
  698. InitPThis(IpxSSHandler, IRtrAdviseSink);
  699. HRESULT hr = hrOK;
  700. COM_PROTECT_TRY
  701. {
  702. if (dwChangeType == ROUTER_REFRESH)
  703. {
  704. SPITFSNode spNode;
  705. Assert(ulConn == pThis->m_ulRefreshConnId);
  706. pThis->m_spNodeMgr->FindNode(pThis->m_cookie, &spNode);
  707. pThis->SynchronizeNodeData(spNode);
  708. }
  709. }
  710. COM_PROTECT_CATCH;
  711. return hr;
  712. }
  713. /*!--------------------------------------------------------------------------
  714. IpxSSHandler::OnResultShow
  715. -
  716. Author: KennT
  717. ---------------------------------------------------------------------------*/
  718. HRESULT IpxSSHandler::OnResultShow(ITFSComponent *pTFSComponent, MMC_COOKIE cookie, LPARAM arg, LPARAM lParam)
  719. {
  720. BOOL bSelect = (BOOL) arg;
  721. HRESULT hr = hrOK;
  722. SPIRouterRefresh spRefresh;
  723. SPITFSNode spNode;
  724. BaseContainerHandler::OnResultShow(pTFSComponent, cookie, arg, lParam);
  725. if (bSelect)
  726. {
  727. // Call synchronize on this node
  728. m_spNodeMgr->FindNode(cookie, &spNode);
  729. if (spNode)
  730. SynchronizeNodeData(spNode);
  731. }
  732. // Un/Register for refresh advises
  733. if (m_spRouterInfo)
  734. m_spRouterInfo->GetRefreshObject(&spRefresh);
  735. if (spRefresh)
  736. {
  737. if (bSelect)
  738. {
  739. if (m_ulRefreshConnId == 0)
  740. spRefresh->AdviseRefresh(&m_IRtrAdviseSink, &m_ulRefreshConnId, 0);
  741. }
  742. else
  743. {
  744. if (m_ulRefreshConnId)
  745. spRefresh->UnadviseRefresh(m_ulRefreshConnId);
  746. m_ulRefreshConnId = 0;
  747. }
  748. }
  749. return hr;
  750. }
  751. /*---------------------------------------------------------------------------
  752. Class: IpxServiceHandler
  753. ---------------------------------------------------------------------------*/
  754. IpxServiceHandler::IpxServiceHandler(ITFSComponentData *pCompData)
  755. : BaseIPXResultHandler(pCompData, COLUMNS_STATICSERVICES),
  756. m_ulConnId(0)
  757. {
  758. m_rgButtonState[MMC_VERB_PROPERTIES_INDEX] = ENABLED;
  759. m_bState[MMC_VERB_PROPERTIES_INDEX] = TRUE;
  760. m_rgButtonState[MMC_VERB_DELETE_INDEX] = ENABLED;
  761. m_bState[MMC_VERB_DELETE_INDEX] = TRUE;
  762. m_rgButtonState[MMC_VERB_REFRESH_INDEX] = ENABLED;
  763. m_bState[MMC_VERB_REFRESH_INDEX] = TRUE;
  764. m_verbDefault = MMC_VERB_PROPERTIES;
  765. }
  766. /*!--------------------------------------------------------------------------
  767. IpxServiceHandler::ConstructNode
  768. Initializes the Domain node (sets it up).
  769. Author: KennT
  770. ---------------------------------------------------------------------------*/
  771. HRESULT IpxServiceHandler::ConstructNode(ITFSNode *pNode, IInterfaceInfo *pIfInfo, IPXConnection *pIPXConn)
  772. {
  773. HRESULT hr = hrOK;
  774. int i;
  775. if (pNode == NULL)
  776. return hrOK;
  777. COM_PROTECT_TRY
  778. {
  779. // Need to initialize the data for the Domain node
  780. pNode->SetData(TFS_DATA_SCOPEID, 0);
  781. // We don't want icons for these nodes.
  782. pNode->SetData(TFS_DATA_IMAGEINDEX, IMAGE_IDX_IPX_NODE_GENERAL);
  783. pNode->SetData(TFS_DATA_OPENIMAGEINDEX, IMAGE_IDX_IPX_NODE_GENERAL);
  784. pNode->SetData(TFS_DATA_COOKIE, reinterpret_cast<DWORD_PTR>(pNode));
  785. //$ Review: kennt, what are the different type of interfaces
  786. // do we distinguish based on the same list as above? (i.e. the
  787. // one for image indexes).
  788. pNode->SetNodeType(&GUID_IPXStaticServicesResultNodeType);
  789. BaseIPXResultNodeData::Init(pNode, pIfInfo, pIPXConn);
  790. }
  791. COM_PROTECT_CATCH
  792. return hr;
  793. }
  794. /*!--------------------------------------------------------------------------
  795. IpxServiceHandler::OnCreateDataObject
  796. -
  797. Author: KennT
  798. ---------------------------------------------------------------------------*/
  799. STDMETHODIMP IpxServiceHandler::OnCreateDataObject(MMC_COOKIE cookie, DATA_OBJECT_TYPES type, IDataObject **ppDataObject)
  800. {
  801. HRESULT hr = hrOK;
  802. COM_PROTECT_TRY
  803. {
  804. CORg( CreateDataObjectFromInterfaceInfo(m_spInterfaceInfo,
  805. type, cookie, m_spTFSCompData,
  806. ppDataObject) );
  807. COM_PROTECT_ERROR_LABEL;
  808. }
  809. COM_PROTECT_CATCH;
  810. return hr;
  811. }
  812. /*!--------------------------------------------------------------------------
  813. IpxServiceHandler::OnCreateDataObject
  814. Implementation of ITFSResultHandler::OnCreateDataObject
  815. Author: KennT
  816. ---------------------------------------------------------------------------*/
  817. STDMETHODIMP IpxServiceHandler::OnCreateDataObject(ITFSComponent *pComp, MMC_COOKIE cookie, DATA_OBJECT_TYPES type, IDataObject **ppDataObject)
  818. {
  819. HRESULT hr = hrOK;
  820. COM_PROTECT_TRY
  821. {
  822. CORg( CreateDataObjectFromInterfaceInfo(m_spInterfaceInfo,
  823. type, cookie, m_spTFSCompData,
  824. ppDataObject) );
  825. COM_PROTECT_ERROR_LABEL;
  826. }
  827. COM_PROTECT_CATCH;
  828. return hr;
  829. }
  830. /*!--------------------------------------------------------------------------
  831. IpxServiceHandler::Init
  832. -
  833. Author: KennT
  834. ---------------------------------------------------------------------------*/
  835. HRESULT IpxServiceHandler::Init(IInterfaceInfo *pIfInfo, ITFSNode *pParent)
  836. {
  837. Assert(pIfInfo);
  838. m_spInterfaceInfo.Set(pIfInfo);
  839. pIfInfo->GetParentRouterInfo(&m_spRouterInfo);
  840. BaseIPXResultHandler::Init(pIfInfo, pParent);
  841. return hrOK;
  842. }
  843. /*!--------------------------------------------------------------------------
  844. IpxServiceHandler::DestroyResultHandler
  845. -
  846. Author: KennT
  847. ---------------------------------------------------------------------------*/
  848. STDMETHODIMP IpxServiceHandler::DestroyResultHandler(MMC_COOKIE cookie)
  849. {
  850. m_spInterfaceInfo.Release();
  851. BaseIPXResultHandler::DestroyResultHandler(cookie);
  852. return hrOK;
  853. }
  854. /*!--------------------------------------------------------------------------
  855. IpxServiceHandler::AddMenuItems
  856. Implementation of ITFSResultHandler::AddMenuItems
  857. Author: KennT
  858. ---------------------------------------------------------------------------*/
  859. STDMETHODIMP IpxServiceHandler::AddMenuItems(
  860. ITFSComponent *pComponent,
  861. MMC_COOKIE cookie,
  862. LPDATAOBJECT lpDataObject,
  863. LPCONTEXTMENUCALLBACK pContextMenuCallback,
  864. long *pInsertionAllowed)
  865. {
  866. return hrOK;
  867. }
  868. /*!--------------------------------------------------------------------------
  869. IpxServiceHandler::Command
  870. -
  871. Author: KennT
  872. ---------------------------------------------------------------------------*/
  873. STDMETHODIMP IpxServiceHandler::Command(ITFSComponent *pComponent,
  874. MMC_COOKIE cookie,
  875. int nCommandID,
  876. LPDATAOBJECT pDataObject)
  877. {
  878. return hrOK;
  879. }
  880. /*!--------------------------------------------------------------------------
  881. IpxServiceHandler::HasPropertyPages
  882. -
  883. Author: KennT
  884. ---------------------------------------------------------------------------*/
  885. STDMETHODIMP IpxServiceHandler::HasPropertyPages
  886. (
  887. ITFSNode * pNode,
  888. LPDATAOBJECT pDataObject,
  889. DATA_OBJECT_TYPES type,
  890. DWORD dwType
  891. )
  892. {
  893. return S_OK;
  894. /* AFX_MANAGE_STATE(AfxGetStaticModuleState());
  895. // Need to fill in a IpxSSListEntry
  896. IpxSSListEntry SREntry;
  897. IpxSSListEntry SREntryOld;
  898. SPIRouterInfo spRouterInfo;
  899. HRESULT hr = hrOK;
  900. CORg( m_spInterfaceInfo->GetParentRouterInfo(&spRouterInfo) );
  901. BaseIPXResultNodeData * pNodeData;
  902. pNodeData = GET_BASEIPXRESULT_NODEDATA(pNode);
  903. Assert(pNodeData);
  904. ASSERT_BASEIPXRESULT_NODEDATA(pNodeData);
  905. // Fill in our SREntry
  906. SREntry.LoadFrom(pNodeData);
  907. SREntryOld.LoadFrom(pNodeData);
  908. {
  909. CStaticServiceDlg srdlg(&SREntry, SR_DLG_MODIFY, spRouterInfo);
  910. if (srdlg.DoModal() == IDOK)
  911. {
  912. // Updates the route info for this route
  913. ModifyRouteInfo(pNode, &SREntry, &SREntryOld);
  914. // Update the data in the UI
  915. SetServiceData(pNodeData, &SREntry);
  916. m_spInterfaceInfo.Set(SREntry.m_spIf);
  917. // Force a refresh
  918. pNode->ChangeNode(RESULT_PANE_CHANGE_ITEM_DATA);
  919. }
  920. }
  921. Error:
  922. return hrOK;*/
  923. }
  924. STDMETHODIMP IpxServiceHandler::HasPropertyPages(ITFSComponent *pComponent,
  925. MMC_COOKIE cookie,
  926. LPDATAOBJECT pDataObject)
  927. {
  928. SPITFSNode spNode;
  929. m_spNodeMgr->FindNode(cookie, &spNode);
  930. return HasPropertyPages(spNode, pDataObject, CCT_RESULT, 0);
  931. }
  932. /*!--------------------------------------------------------------------------
  933. IpxServiceHandler::CreatePropertyPages
  934. Implementation of ResultHandler::CreatePropertyPages
  935. Author: KennT
  936. ---------------------------------------------------------------------------*/
  937. STDMETHODIMP IpxServiceHandler::CreatePropertyPages
  938. (
  939. ITFSComponent * pComponent,
  940. MMC_COOKIE cookie,
  941. LPPROPERTYSHEETCALLBACK lpProvider,
  942. LPDATAOBJECT pDataObject,
  943. LONG_PTR handle
  944. )
  945. {
  946. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  947. HRESULT hr = hrOK;
  948. SPITFSNode spNode;
  949. Assert( m_spNodeMgr );
  950. CORg( m_spNodeMgr->FindNode(cookie, &spNode) );
  951. // Call the ITFSNodeHandler::CreatePropertyPages
  952. hr = CreatePropertyPages(spNode, lpProvider, pDataObject, handle, 0);
  953. Error:
  954. return hr;
  955. }
  956. /*!--------------------------------------------------------------------------
  957. IpxServiceHandler::CreatePropertyPages
  958. Implementation of NodeHandler::CreatePropertyPages
  959. Author: Deonb
  960. ---------------------------------------------------------------------------*/
  961. STDMETHODIMP IpxServiceHandler::CreatePropertyPages
  962. (
  963. ITFSNode * pNode,
  964. LPPROPERTYSHEETCALLBACK lpProvider,
  965. LPDATAOBJECT pDataObject,
  966. LONG_PTR handle,
  967. DWORD dwType
  968. )
  969. {
  970. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  971. HRESULT hr = hrOK;
  972. IpxStaticServicePropertySheet *pProperties = NULL;
  973. SPIComponentData spComponentData;
  974. CString stTitle;
  975. CComPtr<IInterfaceInfo> spInterfaceInfo;
  976. BaseIPXResultNodeData * pNodeData;
  977. CORg( m_spNodeMgr->GetComponentData(&spComponentData) );
  978. if (m_spInterfaceInfo)
  979. stTitle.Format(IDS_IPXSUMMARY_IF_PAGE_TITLE, m_spInterfaceInfo->GetTitle());
  980. else
  981. stTitle.LoadString(IDS_IPXSUMMARY_CLIENT_IF_PAGE_TITLE);
  982. pProperties = new IpxStaticServicePropertySheet(pNode, spComponentData, m_spTFSCompData, stTitle);
  983. pNodeData = GET_BASEIPXRESULT_NODEDATA(pNode);
  984. Assert(pNodeData);
  985. ASSERT_BASEIPXRESULT_NODEDATA(pNodeData);
  986. CORg( m_spNodeMgr->GetComponentData(&spComponentData) );
  987. spInterfaceInfo = m_spInterfaceInfo;
  988. CORg( pProperties->Init(pNodeData, spInterfaceInfo) );
  989. if (lpProvider)
  990. hr = pProperties->CreateModelessSheet(lpProvider, handle);
  991. else
  992. hr = pProperties->DoModelessSheet();
  993. Error:
  994. return hr;
  995. }
  996. /*!--------------------------------------------------------------------------
  997. IpxServiceHandler::OnResultDelete
  998. -
  999. Author: KennT
  1000. ---------------------------------------------------------------------------*/
  1001. HRESULT IpxServiceHandler::OnResultDelete(ITFSComponent *pComponent,
  1002. LPDATAOBJECT pDataObject,
  1003. MMC_COOKIE cookie,
  1004. LPARAM arg,
  1005. LPARAM param)
  1006. {
  1007. SPITFSNode spNode;
  1008. m_spNodeMgr->FindNode(cookie, &spNode);
  1009. return OnRemoveStaticService(spNode);
  1010. }
  1011. /*!--------------------------------------------------------------------------
  1012. IpxServiceHandler::OnRemoveStaticService
  1013. -
  1014. Author: KennT
  1015. ---------------------------------------------------------------------------*/
  1016. HRESULT IpxServiceHandler::OnRemoveStaticService(ITFSNode *pNode)
  1017. {
  1018. HRESULT hr = hrOK;
  1019. SPIInfoBase spInfoBase;
  1020. SPIRtrMgrInterfaceInfo spRmIf;
  1021. IPXConnection *pIPXConn;
  1022. SPITFSNode spNodeParent;
  1023. BaseIPXResultNodeData * pData;
  1024. IpxSSListEntry SREntry;
  1025. CWaitCursor wait;
  1026. pNode->GetParent(&spNodeParent);
  1027. pIPXConn = GET_IPX_SS_NODEDATA(spNodeParent);
  1028. Assert(pIPXConn);
  1029. pData = GET_BASEIPXRESULT_NODEDATA(pNode);
  1030. Assert(pData);
  1031. ASSERT_BASEIPXRESULT_NODEDATA(pData);
  1032. //
  1033. // Load the old interface's information
  1034. //
  1035. Assert(lstrcmpi(m_spInterfaceInfo->GetId(), pData->m_spIf->GetId()) == 0);
  1036. CORg( m_spInterfaceInfo->FindRtrMgrInterface(PID_IPX, &spRmIf) );
  1037. CORg( spRmIf->GetInfoBase(pIPXConn->GetConfigHandle(),
  1038. NULL,
  1039. NULL,
  1040. &spInfoBase));
  1041. SREntry.LoadFrom(pData);
  1042. CORg( RemoveStaticService(&SREntry, spInfoBase) );
  1043. // Update the interface information
  1044. CORg( spRmIf->Save(m_spInterfaceInfo->GetMachineName(),
  1045. pIPXConn->GetConfigHandle(),
  1046. NULL,
  1047. NULL,
  1048. spInfoBase,
  1049. 0));
  1050. // Refresh the node
  1051. ParentRefresh(pNode);
  1052. Error:
  1053. return hr;
  1054. }
  1055. /*!--------------------------------------------------------------------------
  1056. IpxServiceHandler::RemoveStaticService
  1057. -
  1058. Author: KennT
  1059. ---------------------------------------------------------------------------*/
  1060. HRESULT IpxServiceHandler::RemoveStaticService(IpxSSListEntry *pSSEntry,
  1061. IInfoBase *pInfoBase)
  1062. {
  1063. HRESULT hr = hrOK;
  1064. InfoBlock * pBlock;
  1065. PIPX_STATIC_SERVICE_INFO pRow;
  1066. INT i;
  1067. // Get the IPX_STATIC_SERVICE_INFO block from the interface
  1068. CORg( pInfoBase->GetBlock(IPX_STATIC_SERVICE_INFO_TYPE, &pBlock, 0) );
  1069. // Look for the removed route in the IPX_STATIC_SERVICE_INFO
  1070. pRow = (IPX_STATIC_SERVICE_INFO*) pBlock->pData;
  1071. for (i = 0; i < (INT)pBlock->dwCount; i++, pRow++)
  1072. {
  1073. // Compare this route to the removed one
  1074. if (FAreTwoServicesEqual(pRow, &(pSSEntry->m_service)))
  1075. {
  1076. // This is the removed route, so modify this block
  1077. // to exclude the route:
  1078. // Decrement the number of Services
  1079. --pBlock->dwCount;
  1080. if (pBlock->dwCount && (i < (INT)pBlock->dwCount))
  1081. {
  1082. // Overwrite this route with the ones which follow it
  1083. ::memmove(pRow,
  1084. pRow + 1,
  1085. (pBlock->dwCount - i) * sizeof(*pRow));
  1086. }
  1087. break;
  1088. }
  1089. }
  1090. Error:
  1091. return hr;
  1092. }
  1093. /*!--------------------------------------------------------------------------
  1094. IpxServiceHandler::ModifyRouteInfo
  1095. -
  1096. Author: KennT
  1097. ---------------------------------------------------------------------------*/
  1098. HRESULT IpxServiceHandler::ModifyRouteInfo(ITFSNode *pNode,
  1099. IpxSSListEntry *pSSEntryNew,
  1100. IpxSSListEntry *pSSEntryOld)
  1101. {
  1102. Assert(pSSEntryNew);
  1103. Assert(pSSEntryOld);
  1104. INT i;
  1105. HRESULT hr = hrOK;
  1106. InfoBlock* pBlock;
  1107. SPIInfoBase spInfoBase;
  1108. SPIRtrMgrInterfaceInfo spRmIf;
  1109. SPITFSNode spNodeParent;
  1110. IPXConnection * pIPXConn;
  1111. IPX_STATIC_SERVICE_INFO *psr, *psrOld;
  1112. IPX_STATIC_SERVICE_INFO IpxRow;
  1113. CWaitCursor wait;
  1114. pNode->GetParent(&spNodeParent);
  1115. pIPXConn = GET_IPX_SS_NODEDATA(spNodeParent);
  1116. Assert(pIPXConn);
  1117. // Remove the old route if it is on another interface
  1118. if (lstrcmpi(pSSEntryOld->m_spIf->GetId(), pSSEntryNew->m_spIf->GetId()) != 0)
  1119. {
  1120. // the outgoing interface for a route is to be changed.
  1121. CORg( pSSEntryOld->m_spIf->FindRtrMgrInterface(PID_IPX, &spRmIf) );
  1122. CORg( spRmIf->GetInfoBase(pIPXConn->GetConfigHandle(),
  1123. NULL,
  1124. NULL,
  1125. &spInfoBase));
  1126. // Remove the old interface
  1127. CORg( RemoveStaticService(pSSEntryOld, spInfoBase) );
  1128. // Update the interface information
  1129. CORg( spRmIf->Save(pSSEntryOld->m_spIf->GetMachineName(),
  1130. pIPXConn->GetConfigHandle(),
  1131. NULL,
  1132. NULL,
  1133. spInfoBase,
  1134. 0));
  1135. }
  1136. spRmIf.Release();
  1137. spInfoBase.Release();
  1138. // Either
  1139. // (a) a route is being modified (on the same interface)
  1140. // (b) a route is being moved from one interface to another.
  1141. // Retrieve the configuration for the interface to which the route
  1142. // is now attached;
  1143. CORg( pSSEntryNew->m_spIf->FindRtrMgrInterface(PID_IPX, &spRmIf) );
  1144. CORg( spRmIf->GetInfoBase(pIPXConn->GetConfigHandle(),
  1145. NULL,
  1146. NULL,
  1147. &spInfoBase));
  1148. // Get the IPX_STATIC_SERVICE_INFO block from the interface
  1149. hr = spInfoBase->GetBlock(IPX_STATIC_SERVICE_INFO_TYPE, &pBlock, 0);
  1150. if (!FHrOK(hr))
  1151. {
  1152. //
  1153. // No IPX_STATIC_SERVICE_INFO block was found; we create a new block
  1154. // with the new route, and add that block to the interface-info
  1155. //
  1156. CORg( AddStaticService(pSSEntryNew, spInfoBase, NULL) );
  1157. }
  1158. else
  1159. {
  1160. //
  1161. // An IPX_STATIC_SERVICE_INFO block was found.
  1162. //
  1163. // We are modifying an existing route.
  1164. // If the route's interface was not changed when it was modified,
  1165. // look for the existing route in the IPX_STATIC_SERVICE_INFO, and then
  1166. // update its parameters.
  1167. // Otherwise, write a completely new route in the IPX_STATIC_SERVICE_INFO;
  1168. //
  1169. if (lstrcmpi(pSSEntryOld->m_spIf->GetId(), pSSEntryNew->m_spIf->GetId()) == 0)
  1170. {
  1171. //
  1172. // The route's interface was not changed when it was modified;
  1173. // We now look for it amongst the existing Services
  1174. // for this interface.
  1175. // The route's original parameters are in 'preOld',
  1176. // so those are the parameters with which we search
  1177. // for a route to modify
  1178. //
  1179. psr = (IPX_STATIC_SERVICE_INFO*)pBlock->pData;
  1180. for (i = 0; i < (INT)pBlock->dwCount; i++, psr++)
  1181. {
  1182. // Compare this route to the re-configured one
  1183. if (!FAreTwoServicesEqual(&(pSSEntryOld->m_service), psr))
  1184. continue;
  1185. // This is the route which was modified;
  1186. // We can now modify the parameters for the route in-place.
  1187. *psr = pSSEntryNew->m_service;
  1188. break;
  1189. }
  1190. }
  1191. else
  1192. {
  1193. CORg( AddStaticService(pSSEntryNew, spInfoBase, pBlock) );
  1194. }
  1195. // Save the updated information
  1196. CORg( spRmIf->Save(pSSEntryNew->m_spIf->GetMachineName(),
  1197. pIPXConn->GetConfigHandle(),
  1198. NULL,
  1199. NULL,
  1200. spInfoBase,
  1201. 0));
  1202. }
  1203. Error:
  1204. return hr;
  1205. }
  1206. /*!--------------------------------------------------------------------------
  1207. IpxServiceHandler::ParentRefresh
  1208. -
  1209. Author: KennT
  1210. ---------------------------------------------------------------------------*/
  1211. HRESULT IpxServiceHandler::ParentRefresh(ITFSNode *pNode)
  1212. {
  1213. return ForwardCommandToParent(pNode, IDS_MENU_SYNC,
  1214. CCT_RESULT, NULL, 0);
  1215. }
  1216. //----------------------------------------------------------------------------
  1217. // Class: CStaticServiceDlg
  1218. //
  1219. //----------------------------------------------------------------------------
  1220. //----------------------------------------------------------------------------
  1221. // Function: CStaticServiceDlg::CStaticServiceDlg
  1222. //
  1223. // Constructor: initialize the base-class and the dialog's data.
  1224. //----------------------------------------------------------------------------
  1225. CStaticServiceDlg::CStaticServiceDlg(IpxSSListEntry * pSSEntry,
  1226. DWORD dwFlags,
  1227. IRouterInfo *pRouter,
  1228. CWnd *pParent)
  1229. : CBaseDialog(IDD_STATIC_SERVICE, pParent),
  1230. m_pSSEntry(pSSEntry),
  1231. m_dwFlags(dwFlags)
  1232. {
  1233. //{{AFX_DATA_INIT(CStaticServiceDlg)
  1234. //}}AFX_DATA_INIT
  1235. m_spRouterInfo.Set(pRouter);
  1236. // SetHelpMap(m_dwHelpMap);
  1237. }
  1238. //----------------------------------------------------------------------------
  1239. // Function: CStaticServiceDlg::DoDataExchange
  1240. //----------------------------------------------------------------------------
  1241. VOID
  1242. CStaticServiceDlg::DoDataExchange(
  1243. CDataExchange* pDX
  1244. ) {
  1245. CBaseDialog::DoDataExchange(pDX);
  1246. //{{AFX_DATA_MAP(CStaticServiceDlg)
  1247. DDX_Control(pDX, IDC_SSD_COMBO_INTERFACE, m_cbInterfaces);
  1248. DDX_Control(pDX, IDC_SSD_SPIN_HOP_COUNT, m_spinHopCount);
  1249. //}}AFX_DATA_MAP
  1250. }
  1251. BEGIN_MESSAGE_MAP(CStaticServiceDlg, CBaseDialog)
  1252. //{{AFX_MSG_MAP(CStaticServiceDlg)
  1253. //}}AFX_MSG_MAP
  1254. END_MESSAGE_MAP()
  1255. DWORD CStaticServiceDlg::m_dwHelpMap[] =
  1256. {
  1257. // IDC_SRD_DESTINATION, HIDC_SRD_DESTINATION,
  1258. // IDC_SRD_NETMASK, HIDC_SRD_NETMASK,
  1259. // IDC_SRD_GATEWAY, HIDC_SRD_GATEWAY,
  1260. // IDC_SRD_METRIC, HIDC_SRD_METRIC,
  1261. // IDC_SRD_SPINMETRIC, HIDC_SRD_SPINMETRIC,
  1262. // IDC_SRD_INTERFACES, HIDC_SRD_INTERFACES,
  1263. 0,0
  1264. };
  1265. //----------------------------------------------------------------------------
  1266. // Function: CStaticServiceDlg::OnInitDialog
  1267. //
  1268. // Handles the 'WM_INITDIALOG' message for the dialog.
  1269. //----------------------------------------------------------------------------
  1270. BOOL
  1271. CStaticServiceDlg::OnInitDialog(
  1272. )
  1273. {
  1274. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1275. SPIEnumInterfaceInfo spEnumIf;
  1276. SPIInterfaceInfo spIf;
  1277. SPIRtrMgrInterfaceInfo spRmIf;
  1278. TCHAR szNumber[32];
  1279. USES_CONVERSION;
  1280. CBaseDialog::OnInitDialog();
  1281. // initialize the controls
  1282. m_spinHopCount.SetRange(0, 15);
  1283. m_spinHopCount.SetBuddy(GetDlgItem(IDC_SSD_EDIT_HOP_COUNT));
  1284. ((CEdit *) GetDlgItem(IDC_SSD_EDIT_SERVICE_TYPE))->LimitText(4);
  1285. ((CEdit *) GetDlgItem(IDC_SSD_EDIT_SERVICE_NAME))->LimitText(48);
  1286. ((CEdit *) GetDlgItem(IDC_SSD_EDIT_NETWORK_ADDRESS))->LimitText(8);
  1287. ((CEdit *) GetDlgItem(IDC_SSD_EDIT_NODE_ADDRESS))->LimitText(12);
  1288. ((CEdit *) GetDlgItem(IDC_SSD_EDIT_SOCKET_ADDRESS))->LimitText(4);
  1289. // Get a list of the interfaces enabled for IPX routing.
  1290. m_spRouterInfo->EnumInterface(&spEnumIf);
  1291. for( ; spEnumIf->Next(1, &spIf, NULL) == hrOK; spIf.Release())
  1292. {
  1293. spRmIf.Release();
  1294. if (spIf->FindRtrMgrInterface(PID_IPX, &spRmIf) != hrOK)
  1295. continue;
  1296. // Add the interface to the combobox
  1297. INT i = m_cbInterfaces.AddString(spIf->GetTitle());
  1298. m_cbInterfaces.SetItemData(i, (DWORD_PTR)m_ifidList.AddTail(spIf->GetId()));
  1299. }
  1300. if (!m_cbInterfaces.GetCount())
  1301. {
  1302. AfxMessageBox(IDS_ERR_NO_IPX_INTERFACES);
  1303. EndDialog(IDCANCEL);
  1304. return FALSE;
  1305. }
  1306. m_cbInterfaces.SetCurSel(0);
  1307. //
  1308. // If we were given a route to modify, set the dialog up
  1309. // with the parameters in the route
  1310. //
  1311. if ((m_dwFlags & SR_DLG_MODIFY) == 0)
  1312. {
  1313. // No route was given, so leave the controls blank
  1314. }
  1315. else
  1316. {
  1317. // A route to be edited was given, so initialize the controls
  1318. wsprintf(szNumber, _T("%.4x"), m_pSSEntry->m_service.Type);
  1319. SetDlgItemText(IDC_SSD_EDIT_SERVICE_TYPE, szNumber);
  1320. SetDlgItemText(IDC_SSD_EDIT_SERVICE_NAME, A2CT((LPSTR) m_pSSEntry->m_service.Name));
  1321. FormatIpxNetworkNumber(szNumber,
  1322. DimensionOf(szNumber),
  1323. m_pSSEntry->m_service.Network,
  1324. sizeof(m_pSSEntry->m_service.Network));
  1325. SetDlgItemText(IDC_SSD_EDIT_NETWORK_ADDRESS, szNumber);
  1326. // Zero out the address beforehand
  1327. FormatBytes(szNumber, DimensionOf(szNumber),
  1328. (BYTE *) m_pSSEntry->m_service.Node,
  1329. sizeof(m_pSSEntry->m_service.Node));
  1330. SetDlgItemText(IDC_SSD_EDIT_NODE_ADDRESS, szNumber);
  1331. FormatBytes(szNumber, DimensionOf(szNumber),
  1332. (BYTE *) m_pSSEntry->m_service.Socket,
  1333. sizeof(m_pSSEntry->m_service.Socket));
  1334. SetDlgItemText(IDC_SSD_EDIT_SOCKET_ADDRESS, szNumber);
  1335. m_cbInterfaces.SelectString(-1, m_pSSEntry->m_spIf->GetTitle());
  1336. m_spinHopCount.SetPos(m_pSSEntry->m_service.HopCount);
  1337. // Disable the network number, next hop, and interface
  1338. GetDlgItem(IDC_SSD_EDIT_SERVICE_TYPE)->EnableWindow(FALSE);
  1339. GetDlgItem(IDC_SSD_EDIT_SERVICE_NAME)->EnableWindow(FALSE);
  1340. GetDlgItem(IDC_SSD_COMBO_INTERFACE)->EnableWindow(FALSE);
  1341. }
  1342. return TRUE;
  1343. }
  1344. //----------------------------------------------------------------------------
  1345. // Function: CStaticServiceDlg::OnOK
  1346. //
  1347. // Handles 'BN_CLICKED' notification from the 'OK' button.
  1348. //----------------------------------------------------------------------------
  1349. VOID
  1350. CStaticServiceDlg::OnOK(
  1351. ) {
  1352. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1353. CString st;
  1354. SPIInterfaceInfo spIf;
  1355. CString stIf;
  1356. POSITION pos;
  1357. do
  1358. {
  1359. // Get the route's outgoing interface
  1360. INT item = m_cbInterfaces.GetCurSel();
  1361. if (item == CB_ERR)
  1362. break;
  1363. pos = (POSITION)m_cbInterfaces.GetItemData(item);
  1364. stIf = (LPCTSTR)m_ifidList.GetAt(pos);
  1365. m_spRouterInfo->FindInterface(stIf, &spIf);
  1366. m_pSSEntry->m_spIf.Set(spIf);
  1367. // Get the rest of the data
  1368. GetDlgItemText(IDC_SSD_EDIT_SERVICE_TYPE, st);
  1369. m_pSSEntry->m_service.Type = (USHORT) _tcstoul(st, NULL, 16);
  1370. GetDlgItemText(IDC_SSD_EDIT_SERVICE_NAME, st);
  1371. st.TrimLeft();
  1372. st.TrimRight();
  1373. if (st.IsEmpty())
  1374. {
  1375. GetDlgItem(IDC_SSD_EDIT_SERVICE_NAME)->SetFocus();
  1376. AfxMessageBox(IDS_ERR_INVALID_SERVICE_NAME);
  1377. break;
  1378. }
  1379. StrnCpyAFromW((LPSTR) m_pSSEntry->m_service.Name,
  1380. st,
  1381. sizeof(m_pSSEntry->m_service.Name));
  1382. GetDlgItemText(IDC_SSD_EDIT_NETWORK_ADDRESS, st);
  1383. ConvertToBytes(st,
  1384. m_pSSEntry->m_service.Network,
  1385. DimensionOf(m_pSSEntry->m_service.Network));
  1386. GetDlgItemText(IDC_SSD_EDIT_NODE_ADDRESS, st);
  1387. ConvertToBytes(st,
  1388. m_pSSEntry->m_service.Node,
  1389. DimensionOf(m_pSSEntry->m_service.Node));
  1390. GetDlgItemText(IDC_SSD_EDIT_SOCKET_ADDRESS, st);
  1391. ConvertToBytes(st,
  1392. m_pSSEntry->m_service.Socket,
  1393. DimensionOf(m_pSSEntry->m_service.Socket));
  1394. m_pSSEntry->m_service.HopCount = (USHORT) m_spinHopCount.GetPos();
  1395. CBaseDialog::OnOK();
  1396. } while(FALSE);
  1397. }
  1398. /*!--------------------------------------------------------------------------
  1399. IpxSSListEntry::LoadFrom
  1400. -
  1401. Author: KennT
  1402. ---------------------------------------------------------------------------*/
  1403. void IpxSSListEntry::LoadFrom(BaseIPXResultNodeData *pNodeData)
  1404. {
  1405. CString stFullAddress;
  1406. CString stNumber;
  1407. m_spIf.Set(pNodeData->m_spIf);
  1408. m_service.Type = (USHORT) _tcstoul(
  1409. pNodeData->m_rgData[IPX_SS_SI_SERVICE_TYPE].m_stData,
  1410. NULL, 16);
  1411. StrnCpyAFromW((LPSTR) m_service.Name,
  1412. pNodeData->m_rgData[IPX_SS_SI_SERVICE_NAME].m_stData,
  1413. DimensionOf(m_service.Name));
  1414. // Need to break the address up into Network.Node.Socket
  1415. stFullAddress = pNodeData->m_rgData[IPX_SS_SI_SERVICE_ADDRESS].m_stData;
  1416. Assert(StrLen(stFullAddress) == (8 + 1 + 12 + 1 + 4));
  1417. stNumber = stFullAddress.Left(8);
  1418. ConvertToBytes(stNumber,
  1419. m_service.Network, sizeof(m_service.Network));
  1420. stNumber = stFullAddress.Mid(9, 12);
  1421. ConvertToBytes(stNumber,
  1422. m_service.Node, sizeof(m_service.Node));
  1423. stNumber = stFullAddress.Mid(22, 4);
  1424. ConvertToBytes(stNumber,
  1425. m_service.Socket, sizeof(m_service.Socket));
  1426. m_service.HopCount = (USHORT) pNodeData->m_rgData[IPX_SS_SI_HOP_COUNT].m_dwData;
  1427. }
  1428. /*!--------------------------------------------------------------------------
  1429. IpxSSListEntry::SaveTo
  1430. -
  1431. Author: KennT
  1432. ---------------------------------------------------------------------------*/
  1433. void IpxSSListEntry::SaveTo(BaseIPXResultNodeData *pNodeData)
  1434. {
  1435. TCHAR szNumber[32];
  1436. CString st;
  1437. USES_CONVERSION;
  1438. pNodeData->m_spIf.Set(m_spIf);
  1439. pNodeData->m_rgData[IPX_SS_SI_NAME].m_stData = m_spIf->GetTitle();
  1440. wsprintf(szNumber, _T("%.4x"), m_service.Type);
  1441. pNodeData->m_rgData[IPX_SS_SI_SERVICE_TYPE].m_stData = szNumber;
  1442. pNodeData->m_rgData[IPX_SS_SI_SERVICE_TYPE].m_dwData = (DWORD) m_service.Type;
  1443. pNodeData->m_rgData[IPX_SS_SI_SERVICE_NAME].m_stData =
  1444. A2CT((LPSTR) m_service.Name);
  1445. FormatBytes(szNumber, DimensionOf(szNumber),
  1446. m_service.Network, sizeof(m_service.Network));
  1447. st = szNumber;
  1448. st += _T(".");
  1449. FormatBytes(szNumber, DimensionOf(szNumber),
  1450. m_service.Node, sizeof(m_service.Node));
  1451. st += szNumber;
  1452. st += _T(".");
  1453. FormatBytes(szNumber, DimensionOf(szNumber),
  1454. m_service.Socket, sizeof(m_service.Socket));
  1455. st += szNumber;
  1456. Assert(st.GetLength() == (8+1+12+1+4));
  1457. pNodeData->m_rgData[IPX_SS_SI_SERVICE_ADDRESS].m_stData = st;
  1458. FormatNumber(m_service.HopCount,
  1459. szNumber,
  1460. DimensionOf(szNumber),
  1461. FALSE);
  1462. pNodeData->m_rgData[IPX_SS_SI_HOP_COUNT].m_stData = szNumber;
  1463. pNodeData->m_rgData[IPX_SS_SI_HOP_COUNT].m_dwData = m_service.HopCount;
  1464. }
  1465. /*!--------------------------------------------------------------------------
  1466. SetServiceData
  1467. -
  1468. Author: KennT
  1469. ---------------------------------------------------------------------------*/
  1470. HRESULT SetServiceData(BaseIPXResultNodeData *pData,
  1471. IpxSSListEntry *pService)
  1472. {
  1473. pService->SaveTo(pData);
  1474. return hrOK;
  1475. }
  1476. /*!--------------------------------------------------------------------------
  1477. AddStaticService
  1478. This function ASSUMES that the route is NOT in the block.
  1479. Author: KennT
  1480. ---------------------------------------------------------------------------*/
  1481. HRESULT AddStaticService(IpxSSListEntry *pSSEntryNew,
  1482. IInfoBase *pInfoBase,
  1483. InfoBlock *pBlock)
  1484. {
  1485. IPX_STATIC_SERVICE_INFO srRow;
  1486. HRESULT hr = hrOK;
  1487. if (pBlock == NULL)
  1488. {
  1489. //
  1490. // No IPX_STATIC_SERVICE_INFO block was found; we create a new block
  1491. // with the new route, and add that block to the interface-info
  1492. //
  1493. CORg( pInfoBase->AddBlock(IPX_STATIC_SERVICE_INFO_TYPE,
  1494. sizeof(IPX_STATIC_SERVICE_INFO),
  1495. (LPBYTE) &(pSSEntryNew->m_service), 1, 0) );
  1496. }
  1497. else
  1498. {
  1499. // Either the route is completely new, or it is a route
  1500. // which was moved from one interface to another.
  1501. // Set a new block as the IPX_STATIC_SERVICE_INFO,
  1502. // and include the re-configured route in the new block.
  1503. PIPX_STATIC_SERVICE_INFO psrTable;
  1504. psrTable = new IPX_STATIC_SERVICE_INFO[pBlock->dwCount + 1];
  1505. Assert(psrTable);
  1506. // Copy the original table of Services
  1507. ::memcpy(psrTable, pBlock->pData,
  1508. pBlock->dwCount * sizeof(IPX_STATIC_SERVICE_INFO));
  1509. // Append the new route
  1510. psrTable[pBlock->dwCount] = pSSEntryNew->m_service;
  1511. // Replace the old route-table with the new one
  1512. CORg( pInfoBase->SetData(IPX_STATIC_SERVICE_INFO_TYPE,
  1513. sizeof(IPX_STATIC_SERVICE_INFO),
  1514. (LPBYTE) psrTable, pBlock->dwCount + 1, 0) );
  1515. }
  1516. Error:
  1517. return hr;
  1518. }
  1519. BOOL FAreTwoServicesEqual(IPX_STATIC_SERVICE_INFO *pService1,
  1520. IPX_STATIC_SERVICE_INFO *pService2)
  1521. {
  1522. return (pService1->Type == pService2->Type) &&
  1523. (StrnCmpA((LPCSTR) pService1->Name, (LPCSTR) pService2->Name, DimensionOf(pService1->Name)) == 0);
  1524. }