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.

1316 lines
36 KiB

  1. /**********************************************************************/
  2. /** Microsoft Windows/NT **/
  3. /** Copyright(c) Microsoft Corporation, 1997 - 1999 **/
  4. /**********************************************************************/
  5. /*
  6. summary.cpp
  7. IPX summary node implementation.
  8. FILE HISTORY:
  9. */
  10. #include "stdafx.h"
  11. #include "util.h"
  12. #include "nbview.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 "column.h" // ComponentConfigStream
  22. #include "rtrui.h"
  23. #include "nbprop.h" // NetBIOS broadcast property pages
  24. #include "ipxutil.h" // IPX formatting helper functions
  25. #include "routprot.h"
  26. #include "ipxrtdef.h"
  27. /*---------------------------------------------------------------------------
  28. Keep this in sync with the column ids in nbview.h
  29. ---------------------------------------------------------------------------*/
  30. extern const ContainerColumnInfo s_rgNBViewColumnInfo[];
  31. const ContainerColumnInfo s_rgNBViewColumnInfo[] =
  32. {
  33. { IDS_IPX_NB_COL_NAME, CON_SORT_BY_STRING, TRUE, COL_IF_NAME },
  34. { IDS_IPX_NB_COL_TYPE, CON_SORT_BY_STRING, TRUE, COL_IF_DEVICE },
  35. { IDS_IPX_NB_COL_ACCEPTED, CON_SORT_BY_STRING, TRUE, COL_STRING },
  36. { IDS_IPX_NB_COL_DELIVERED, CON_SORT_BY_STRING, TRUE, COL_STRING },
  37. { IDS_IPX_NB_COL_SENT, CON_SORT_BY_DWORD, TRUE, COL_LARGE_NUM },
  38. { IDS_IPX_NB_COL_RECEIVED, CON_SORT_BY_DWORD, TRUE, COL_LARGE_NUM },
  39. };
  40. /*---------------------------------------------------------------------------
  41. IpxNBHandler implementation
  42. ---------------------------------------------------------------------------*/
  43. IpxNBHandler::IpxNBHandler(ITFSComponentData *pCompData)
  44. : BaseContainerHandler(pCompData, COLUMNS_NBBROADCASTS,
  45. s_rgNBViewColumnInfo),
  46. m_ulConnId(0),
  47. m_ulRefreshConnId(0)
  48. {
  49. // Setup the verb states
  50. m_rgButtonState[MMC_VERB_REFRESH_INDEX] = ENABLED;
  51. m_bState[MMC_VERB_REFRESH_INDEX] = TRUE;
  52. }
  53. STDMETHODIMP IpxNBHandler::QueryInterface(REFIID riid, LPVOID *ppv)
  54. {
  55. // Is the pointer bad?
  56. if (ppv == NULL)
  57. return E_INVALIDARG;
  58. // Place NULL in *ppv in case of failure
  59. *ppv = NULL;
  60. // This is the non-delegating IUnknown implementation
  61. if (riid == IID_IUnknown)
  62. *ppv = (LPVOID) this;
  63. else if (riid == IID_IRtrAdviseSink)
  64. *ppv = &m_IRtrAdviseSink;
  65. else
  66. return BaseContainerHandler::QueryInterface(riid, ppv);
  67. // If we're going to return an interface, AddRef it first
  68. if (*ppv)
  69. {
  70. ((LPUNKNOWN) *ppv)->AddRef();
  71. return hrOK;
  72. }
  73. else
  74. return E_NOINTERFACE;
  75. }
  76. /*!--------------------------------------------------------------------------
  77. IpxNBHandler::DestroyHandler
  78. Implementation of ITFSNodeHandler::DestroyHandler
  79. Author: KennT
  80. ---------------------------------------------------------------------------*/
  81. STDMETHODIMP IpxNBHandler::DestroyHandler(ITFSNode *pNode)
  82. {
  83. IPXConnection * pIpxConn;
  84. pIpxConn = GET_IPXNB_NODEDATA(pNode);
  85. pIpxConn->Release();
  86. if (m_ulRefreshConnId)
  87. {
  88. SPIRouterRefresh spRefresh;
  89. if (m_spRouterInfo)
  90. m_spRouterInfo->GetRefreshObject(&spRefresh);
  91. if (spRefresh)
  92. spRefresh->UnadviseRefresh(m_ulRefreshConnId);
  93. }
  94. m_ulRefreshConnId = 0;
  95. // if (m_ulStatsConnId)
  96. // {
  97. // SPIRouterRefresh spRefresh;
  98. // if (m_spRouterInfo)
  99. // m_spRouterInfo->GetRefreshObject(&spRefresh);
  100. // if (spRefresh)
  101. // spRefresh->UnadviseRefresh(m_ulStatsConnId);
  102. // }
  103. // m_ulStatsConnId = 0;
  104. if (m_ulConnId)
  105. m_spRtrMgrInfo->RtrUnadvise(m_ulConnId);
  106. m_ulConnId = 0;
  107. m_spRtrMgrInfo.Release();
  108. // WaitForStatisticsWindow(&m_IpxStats);
  109. m_spRouterInfo.Release();
  110. return hrOK;
  111. }
  112. /*!--------------------------------------------------------------------------
  113. IpxNBHandler::HasPropertyPages
  114. Implementation of ITFSNodeHandler::HasPropertyPages
  115. NOTE: the root node handler has to over-ride this function to
  116. handle the snapin manager property page (wizard) case!!!
  117. Author: KennT
  118. ---------------------------------------------------------------------------*/
  119. STDMETHODIMP
  120. IpxNBHandler::HasPropertyPages
  121. (
  122. ITFSNode * pNode,
  123. LPDATAOBJECT pDataObject,
  124. DATA_OBJECT_TYPES type,
  125. DWORD dwType
  126. )
  127. {
  128. return hrFalse;
  129. }
  130. /*!--------------------------------------------------------------------------
  131. IpxNBHandler::OnAddMenuItems
  132. Implementation of ITFSNodeHandler::OnAddMenuItems
  133. Author: KennT
  134. ---------------------------------------------------------------------------*/
  135. STDMETHODIMP IpxNBHandler::OnAddMenuItems(
  136. ITFSNode *pNode,
  137. LPCONTEXTMENUCALLBACK pContextMenuCallback,
  138. LPDATAOBJECT lpDataObject,
  139. DATA_OBJECT_TYPES type,
  140. DWORD dwType,
  141. long *pInsertionAllowed)
  142. {
  143. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  144. HRESULT hr = S_OK;
  145. COM_PROTECT_TRY
  146. {
  147. }
  148. COM_PROTECT_CATCH;
  149. return hr;
  150. }
  151. STDMETHODIMP IpxNBHandler::OnCommand(ITFSNode *pNode, long nCommandId,
  152. DATA_OBJECT_TYPES type,
  153. LPDATAOBJECT pDataObject,
  154. DWORD dwType)
  155. {
  156. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  157. HRESULT hr = S_OK;
  158. SPITFSNode spParent;
  159. SPITFSNodeHandler spHandler;
  160. COM_PROTECT_TRY
  161. {
  162. switch (nCommandId)
  163. {
  164. case IDS_MENU_SYNC:
  165. SynchronizeNodeData(pNode);
  166. break;
  167. }
  168. }
  169. COM_PROTECT_CATCH;
  170. return hr;
  171. }
  172. /*!--------------------------------------------------------------------------
  173. IpxNBHandler::OnExpand
  174. -
  175. Author: KennT
  176. ---------------------------------------------------------------------------*/
  177. HRESULT IpxNBHandler::OnExpand(ITFSNode *pNode,
  178. LPDATAOBJECT pDataObject,
  179. DWORD dwType,
  180. LPARAM arg,
  181. LPARAM lParam)
  182. {
  183. HRESULT hr = hrOK;
  184. SPIEnumInterfaceInfo spEnumIf;
  185. SPIInterfaceInfo spIf;
  186. SPIRtrMgrInterfaceInfo spRmIf;
  187. // Windows NT Bug: 288427
  188. // This flag may also get set inside of the OnChange() call.
  189. // The OnChange() will enumerate and all interfaces.
  190. // They may have been added as the result of an OnChange()
  191. // because they were added before the OnExpand() was called.
  192. //
  193. // WARNING! Be careful about adding anything to this function,
  194. // since the m_bExpanded can be set in another function.
  195. // ----------------------------------------------------------------
  196. if (m_bExpanded)
  197. return hrOK;
  198. COM_PROTECT_TRY
  199. {
  200. CORg( m_spRouterInfo->EnumInterface(&spEnumIf) );
  201. while (spEnumIf->Next(1, &spIf, NULL) == hrOK)
  202. {
  203. if (spIf->FindRtrMgrInterface(PID_IPX, &spRmIf) == hrOK)
  204. {
  205. // Now we create an interface node for this interface
  206. AddInterfaceNode(pNode, spIf, FALSE);
  207. }
  208. spRmIf.Release();
  209. spIf.Release();
  210. }
  211. //$CLIENT: Add the client interface (setup default data)
  212. // the only thing that we can do in synchronize is to
  213. // get the Administrative status
  214. AddInterfaceNode(pNode, NULL, TRUE);
  215. m_bExpanded = TRUE;
  216. // Now that we have all of the nodes, update the data for
  217. // all of the nodes
  218. SynchronizeNodeData(pNode);
  219. COM_PROTECT_ERROR_LABEL;
  220. }
  221. COM_PROTECT_CATCH;
  222. m_bExpanded = TRUE;
  223. return hr;
  224. }
  225. /*!--------------------------------------------------------------------------
  226. IpxNBHandler::GetString
  227. Implementation of ITFSNodeHandler::GetString
  228. We don't need to do anything, since our root node is an extension
  229. only and thus can't do anything to the node text.
  230. Author: KennT
  231. ---------------------------------------------------------------------------*/
  232. STDMETHODIMP_(LPCTSTR) IpxNBHandler::GetString(ITFSNode *pNode, int nCol)
  233. {
  234. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  235. HRESULT hr = hrOK;
  236. COM_PROTECT_TRY
  237. {
  238. if (m_stTitle.IsEmpty())
  239. m_stTitle.LoadString(IDS_IPXNB_TITLE);
  240. }
  241. COM_PROTECT_CATCH;
  242. return m_stTitle;
  243. }
  244. /*!--------------------------------------------------------------------------
  245. IpxNBHandler::OnCreateDataObject
  246. -
  247. Author: KennT
  248. ---------------------------------------------------------------------------*/
  249. STDMETHODIMP IpxNBHandler::OnCreateDataObject(MMC_COOKIE cookie, DATA_OBJECT_TYPES type, IDataObject **ppDataObject)
  250. {
  251. HRESULT hr = hrOK;
  252. COM_PROTECT_TRY
  253. {
  254. Assert(m_spRtrMgrInfo);
  255. CORg( CreateDataObjectFromRtrMgrInfo(m_spRtrMgrInfo,
  256. type, cookie, m_spTFSCompData,
  257. ppDataObject) );
  258. COM_PROTECT_ERROR_LABEL;
  259. }
  260. COM_PROTECT_CATCH;
  261. return hr;
  262. }
  263. /*!--------------------------------------------------------------------------
  264. IpxNBHandler::Init
  265. -
  266. Author: KennT
  267. ---------------------------------------------------------------------------*/
  268. HRESULT IpxNBHandler::Init(IRtrMgrInfo *pRmInfo, IPXAdminConfigStream *pConfigStream)
  269. {
  270. m_spRtrMgrInfo.Set(pRmInfo);
  271. if (pRmInfo)
  272. pRmInfo->GetParentRouterInfo(&m_spRouterInfo);
  273. m_pConfigStream = pConfigStream;
  274. // Also need to register for change notifications
  275. Assert(m_ulConnId == 0);
  276. m_spRtrMgrInfo->RtrAdvise(&m_IRtrAdviseSink, &m_ulConnId, 0);
  277. // m_IpxStats.SetConfigInfo(pConfigStream, IPXSTRM_STATS_IPX);
  278. return hrOK;
  279. }
  280. HRESULT IpxNBHandler::OnResultRefresh(ITFSComponent * pComponent, LPDATAOBJECT pDataObject, MMC_COOKIE cookie, LPARAM arg, LPARAM lParam)
  281. {
  282. HRESULT hr = hrOK;
  283. SPITFSNode spNode, spParent;
  284. SPITFSResultHandler spParentRH;
  285. m_spNodeMgr->FindNode(cookie, &spNode);
  286. // forward this command to the parent to handle
  287. CORg (spNode->GetParent(&spParent));
  288. CORg (spParent->GetResultHandler(&spParentRH));
  289. CORg (spParentRH->Notify(pComponent, spParent->GetData(TFS_DATA_COOKIE), pDataObject, MMCN_REFRESH, arg, lParam));
  290. Error:
  291. return hrOK;
  292. }
  293. /*!--------------------------------------------------------------------------
  294. IpxNBHandler::ConstructNode
  295. Initializes the root node (sets it up).
  296. Author: KennT
  297. ---------------------------------------------------------------------------*/
  298. HRESULT IpxNBHandler::ConstructNode(ITFSNode *pNode, LPCTSTR pszName,
  299. IPXConnection *pIpxConn)
  300. {
  301. Assert(pIpxConn);
  302. HRESULT hr = hrOK;
  303. if (pNode == NULL)
  304. return hrOK;
  305. COM_PROTECT_TRY
  306. {
  307. // Need to initialize the data for the root node
  308. pNode->SetData(TFS_DATA_IMAGEINDEX, IMAGE_IDX_IPX_NODE_GENERAL);
  309. pNode->SetData(TFS_DATA_OPENIMAGEINDEX, IMAGE_IDX_IPX_NODE_GENERAL);
  310. pNode->SetData(TFS_DATA_SCOPEID, 0);
  311. // This is a leaf node in the scope pane
  312. pNode->SetData(TFS_DATA_SCOPE_LEAF_NODE, TRUE);
  313. m_cookie = reinterpret_cast<DWORD_PTR>(pNode);
  314. pNode->SetData(TFS_DATA_COOKIE, m_cookie);
  315. pNode->SetNodeType(&GUID_IPXNetBIOSBroadcastsNodeType);
  316. // Setup the node data
  317. pIpxConn->AddRef();
  318. SET_IPXNB_NODEDATA(pNode, pIpxConn);
  319. // m_IpxStats.SetConnectionData(pIpxConn);
  320. }
  321. COM_PROTECT_CATCH;
  322. if (!FHrSucceeded(hr))
  323. {
  324. SET_IPXNB_NODEDATA(pNode, NULL);
  325. }
  326. return hr;
  327. }
  328. /*!--------------------------------------------------------------------------
  329. IpxNBHandler::AddInterfaceNode
  330. -
  331. Author: KennT
  332. ---------------------------------------------------------------------------*/
  333. HRESULT IpxNBHandler::AddInterfaceNode(ITFSNode *pParent, IInterfaceInfo *pIf, BOOL fClient)
  334. {
  335. IpxNBInterfaceHandler * pHandler;
  336. SPITFSResultHandler spHandler;
  337. SPITFSNode spNode;
  338. HRESULT hr = hrOK;
  339. IPXConnection * pIPXConn;
  340. BaseIPXResultNodeData * pResultData = NULL;
  341. int cBlocks = 0;
  342. SPIInfoBase spInfoBase;
  343. SPIRtrMgrInterfaceInfo spRmIf;
  344. // Create the handler for this node
  345. pHandler = new IpxNBInterfaceHandler(m_spTFSCompData);
  346. spHandler = pHandler;
  347. CORg( pHandler->Init(m_spRtrMgrInfo, pIf, pParent) );
  348. pIPXConn = GET_IPXNB_NODEDATA(pParent);
  349. // Create a result item node (or a leaf node)
  350. CORg( CreateLeafTFSNode(&spNode,
  351. NULL,
  352. static_cast<ITFSNodeHandler *>(pHandler),
  353. static_cast<ITFSResultHandler *>(pHandler),
  354. m_spNodeMgr) );
  355. CORg( pHandler->ConstructNode(spNode, pIf, pIPXConn) );
  356. pResultData = GET_BASEIPXRESULT_NODEDATA(spNode);
  357. Assert(pResultData);
  358. ASSERT_BASEIPXRESULT_NODEDATA(pResultData);
  359. pResultData->m_fClient = fClient;
  360. // Make the node immediately visible
  361. CORg( spNode->SetVisibilityState(TFS_VIS_SHOW) );
  362. CORg( spNode->Show() );
  363. CORg( pParent->AddChild(spNode) );
  364. Error:
  365. return hr;
  366. }
  367. /*!--------------------------------------------------------------------------
  368. IpxNBHandler::SynchronizeNodeData
  369. -
  370. Author: KennT
  371. ---------------------------------------------------------------------------*/
  372. HRESULT IpxNBHandler::SynchronizeNodeData(ITFSNode *pThisNode)
  373. {
  374. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  375. SPITFSNode spNode;
  376. SPITFSNodeEnum spEnumNode;
  377. SPIInterfaceInfo spIf;
  378. IpxNBArray ipxNBArray;
  379. IpxNBArrayEntry ipxNBEntry;
  380. IpxNBArrayEntry * pEntry;
  381. HRESULT hr = hrOK;
  382. int cEntries;
  383. BaseIPXResultNodeData * pData;
  384. int cArray, iArray;
  385. // Get a list of interface ids
  386. CORg( pThisNode->GetEnum(&spEnumNode) );
  387. cEntries = 0;
  388. for (; spEnumNode->Next(1, &spNode, NULL) == hrOK; spNode.Release())
  389. {
  390. pData = GET_BASEIPXRESULT_NODEDATA(spNode);
  391. Assert(pData);
  392. ASSERT_BASEIPXRESULT_NODEDATA(pData);
  393. // Fill in the strings with a set of default values
  394. if (pData->m_fClient)
  395. {
  396. pData->m_rgData[IPXNB_SI_NAME].m_stData.LoadString(IDS_IPX_DIAL_IN_CLIENTS);
  397. pData->m_rgData[IPXNB_SI_TYPE].m_stData =
  398. IpxTypeToCString(ROUTER_IF_TYPE_CLIENT);
  399. }
  400. else
  401. {
  402. pData->m_rgData[IPXNB_SI_NAME].m_stData =
  403. pData->m_spIf->GetTitle();
  404. pData->m_rgData[IPXNB_SI_TYPE].m_dwData =
  405. pData->m_spIf->GetInterfaceType();
  406. pData->m_rgData[IPXNB_SI_TYPE].m_stData =
  407. InterfaceTypeToCString(pData->m_spIf->GetInterfaceType());
  408. }
  409. // Setup some defaults
  410. ::ZeroMemory(&ipxNBEntry, sizeof(ipxNBEntry));
  411. ipxNBEntry.m_dwAccept = 0xFFFFFFFF;
  412. ipxNBEntry.m_dwDeliver = 0xFFFFFFFF;
  413. ipxNBEntry.m_cSent = 0xFFFFFFFF;
  414. ipxNBEntry.m_cReceived = 0xFFFFFFFF;
  415. ipxNBEntry.m_fClient = pData->m_fClient;
  416. // If this is not a client, then we should have an m_spIf
  417. if (!pData->m_fClient)
  418. StrnCpyTFromOle(ipxNBEntry.m_szId, pData->m_spIf->GetId(),
  419. DimensionOf(ipxNBEntry.m_szId));
  420. ipxNBArray.SetAtGrow(cEntries, ipxNBEntry);
  421. cEntries++;
  422. }
  423. // Gather the data for this set of interface ids, this part
  424. // could go on a background thread (so that we don't block the
  425. // main thread).
  426. CORg( GetIpxNBData(pThisNode, &ipxNBArray) );
  427. // Write the data back out to the nodes ( and also fill in
  428. // some data).
  429. spEnumNode->Reset();
  430. for (; spEnumNode->Next(1, &spNode, NULL) == hrOK; spNode.Release())
  431. {
  432. pData = GET_BASEIPXRESULT_NODEDATA(spNode);
  433. Assert(pData);
  434. ASSERT_BASEIPXRESULT_NODEDATA(pData);
  435. cArray = (int) ipxNBArray.GetSize();
  436. for (iArray = 0; iArray < cArray; iArray++)
  437. {
  438. pEntry = &ipxNBArray[iArray];
  439. if ((pData->m_fClient && pEntry->m_fClient) ||
  440. (pData->m_spIf &&
  441. (StriCmp(pEntry->m_szId, pData->m_spIf->GetId()) == 0)))
  442. {
  443. pData->m_rgData[IPXNB_SI_ACCEPTED].m_stData =
  444. IpxAcceptBroadcastsToCString(pEntry->m_dwAccept);
  445. pData->m_rgData[IPXNB_SI_DELIVERED].m_stData =
  446. IpxDeliveredBroadcastsToCString(pEntry->m_dwDeliver);
  447. if (pEntry->m_cSent == 0xFFFFFFFF)
  448. pData->m_rgData[IPXNB_SI_SENT].m_stData.LoadString(IDS_STATS_NA);
  449. else
  450. FillInNumberData(pData, IPXNB_SI_SENT,
  451. pEntry->m_cSent);
  452. if (pEntry->m_cReceived == 0xFFFFFFFF)
  453. pData->m_rgData[IPXNB_SI_RECEIVED].m_stData.LoadString(IDS_STATS_NA);
  454. else
  455. FillInNumberData(pData, IPXNB_SI_RECEIVED,
  456. pEntry->m_cReceived);
  457. break;
  458. }
  459. }
  460. // Force MMC to redraw the nodes
  461. spNode->ChangeNode(RESULT_PANE_CHANGE_ITEM_DATA);
  462. }
  463. Error:
  464. return hr;
  465. }
  466. /*!--------------------------------------------------------------------------
  467. IpxNBHandler::GetClientInterfaceData
  468. -
  469. Author: KennT
  470. ---------------------------------------------------------------------------*/
  471. HRESULT IpxNBHandler::GetClientInterfaceData(IpxNBArrayEntry *pClient,
  472. IRtrMgrInfo *pRm)
  473. {
  474. SPIInfoBase spInfoBase;
  475. InfoBlock * pIpxBlock;
  476. InfoBlock * pWanBlock;
  477. HRESULT hr = hrOK;
  478. BOOL fSave = FALSE;
  479. IPX_IF_INFO *pIpxInfo;
  480. pRm->GetInfoBase(NULL, NULL, NULL, &spInfoBase);
  481. if (spInfoBase == NULL)
  482. {
  483. CORg( CreateInfoBase(&spInfoBase) );
  484. }
  485. if (spInfoBase->GetBlock(IPX_INTERFACE_INFO_TYPE, &pIpxBlock, 0) != hrOK)
  486. {
  487. // We couldn't find the block, add it in
  488. IPX_IF_INFO ipx;
  489. ipx.AdminState = ADMIN_STATE_ENABLED;
  490. ipx.NetbiosAccept = ADMIN_STATE_DISABLED;
  491. ipx.NetbiosDeliver = ADMIN_STATE_DISABLED;
  492. CORg( spInfoBase->AddBlock(IPX_INTERFACE_INFO_TYPE,
  493. sizeof(ipx),
  494. (PBYTE) &ipx,
  495. 1,
  496. 0) );
  497. CORg( spInfoBase->GetBlock(IPX_INTERFACE_INFO_TYPE, &pIpxBlock, 0) );
  498. fSave = TRUE;
  499. }
  500. pIpxInfo = (PIPX_IF_INFO) pIpxBlock->pData;
  501. pClient->m_dwAccept = pIpxInfo->NetbiosAccept;
  502. pClient->m_dwDeliver = pIpxInfo->NetbiosDeliver;
  503. if (spInfoBase->GetBlock(IPXWAN_INTERFACE_INFO_TYPE, &pWanBlock, 0) != hrOK)
  504. {
  505. // We couldn't find the block, add it in
  506. IPXWAN_IF_INFO wan;
  507. wan.AdminState = ADMIN_STATE_ENABLED;
  508. CORg( spInfoBase->AddBlock(IPXWAN_INTERFACE_INFO_TYPE,
  509. sizeof(wan),
  510. (PBYTE) &wan,
  511. 1,
  512. 0) );
  513. CORg( spInfoBase->GetBlock(IPXWAN_INTERFACE_INFO_TYPE,
  514. &pWanBlock, 0) );
  515. fSave = TRUE;
  516. }
  517. if (fSave)
  518. {
  519. pRm->Save(NULL, // pszMachine
  520. NULL, // hMachine
  521. NULL, // hTransport
  522. NULL, // pGlobalInfo
  523. spInfoBase, // pClientInfo
  524. 0); // dwDeleteProtocolId
  525. }
  526. Error:
  527. return hr;
  528. }
  529. /*!--------------------------------------------------------------------------
  530. IpxNBHandler::GetIpxNBData
  531. -
  532. Author: KennT
  533. ---------------------------------------------------------------------------*/
  534. HRESULT IpxNBHandler::GetIpxNBData(ITFSNode *pThisNode,
  535. IpxNBArray *pIpxNBArray)
  536. {
  537. HRESULT hr = hrOK;
  538. IPXConnection * pIPXConn;
  539. IPX_MIB_GET_INPUT_DATA MibGetInputData;
  540. PIPX_INTERFACE pIpxIf = NULL;
  541. DWORD cbIpxIf;
  542. SPMprMibBuffer spMib;
  543. IpxNBArrayEntry * pEntry = NULL;
  544. DWORD dwErr;
  545. int iArray, cArray;
  546. SPIRtrMgrInterfaceInfo spRmIf;
  547. SPIInfoBase spInfoBase;
  548. PIPX_IF_INFO pIfInfo;
  549. SPITFSNodeEnum spEnumNode;
  550. SPITFSNode spNode;
  551. BaseIPXResultNodeData * pData;
  552. USES_CONVERSION;
  553. pIPXConn = GET_IPXNB_NODEDATA(pThisNode);
  554. // Go through the array, filling in all of the interface indices
  555. MibGetInputData.TableId = IPX_INTERFACE_TABLE;
  556. dwErr = ::MprAdminMIBEntryGetFirst(pIPXConn->GetMibHandle(),
  557. PID_IPX,
  558. IPX_PROTOCOL_BASE,
  559. &MibGetInputData,
  560. sizeof(MibGetInputData),
  561. (LPVOID *) &pIpxIf,
  562. &cbIpxIf);
  563. hr = HRESULT_FROM_WIN32(dwErr);
  564. spMib = (PBYTE) pIpxIf;
  565. while (FHrSucceeded(hr))
  566. {
  567. // Now match this up to a name in the array
  568. cArray = (int) pIpxNBArray->GetSize();
  569. for (iArray = 0; iArray<cArray; iArray++)
  570. {
  571. pEntry = &((*pIpxNBArray)[iArray]);
  572. if (StriCmp(pEntry->m_szId, A2CT((LPCSTR) pIpxIf->InterfaceName)) == 0)
  573. {
  574. // Ok, we found a match
  575. pEntry->m_cSent = pIpxIf->IfStats.NetbiosSent;
  576. pEntry->m_cReceived = pIpxIf->IfStats.NetbiosReceived;
  577. break;
  578. }
  579. }
  580. MibGetInputData.MibIndex.InterfaceTableIndex.InterfaceIndex =
  581. pIpxIf->InterfaceIndex;
  582. // Get the next name
  583. spMib.Free();
  584. pIpxIf = NULL;
  585. dwErr = ::MprAdminMIBEntryGetNext(pIPXConn->GetMibHandle(),
  586. PID_IPX,
  587. IPX_PROTOCOL_BASE,
  588. &MibGetInputData,
  589. sizeof(MibGetInputData),
  590. (LPVOID *) &pIpxIf,
  591. &cbIpxIf);
  592. hr = HRESULT_FROM_WIN32(dwErr);
  593. spMib = (PBYTE) pIpxIf;
  594. }
  595. spMib.Free();
  596. // Now we need to grab the data from the infobase (these access
  597. // could lead to a MIB access and thus a RPC). This is why we do
  598. // it here also.
  599. // Instead of iterating through the MIBs, iterate through the
  600. // interfaces that appear in the node.
  601. pThisNode->GetEnum(&spEnumNode);
  602. for (; spEnumNode->Next(1, &spNode, NULL) == hrOK; spNode.Release())
  603. {
  604. pData = GET_BASEIPXRESULT_NODEDATA(spNode);
  605. Assert(pData);
  606. ASSERT_BASEIPXRESULT_NODEDATA(pData);
  607. // Now look for a match in the nodes
  608. cArray = (int) pIpxNBArray->GetSize();
  609. for (iArray=0; iArray < cArray; iArray++)
  610. {
  611. pEntry = &((*pIpxNBArray)[iArray]);
  612. if (pEntry->m_fClient && pData->m_fClient)
  613. {
  614. GetClientInterfaceData(pEntry, m_spRtrMgrInfo);
  615. break;
  616. }
  617. else if (pData->m_fClient)
  618. break;
  619. // No match, continue on
  620. if (StriCmp(pEntry->m_szId, pData->m_spIf->GetId()))
  621. continue;
  622. // Get the data for this node and set it.
  623. spRmIf.Release();
  624. hr = pData->m_spIf->FindRtrMgrInterface(PID_IPX, &spRmIf);
  625. if (hr != hrOK)
  626. break;
  627. spInfoBase.Release();
  628. hr = spRmIf->GetInfoBase(NULL, NULL, NULL, &spInfoBase);
  629. if (hr != hrOK)
  630. break;
  631. spInfoBase->GetData(IPX_INTERFACE_INFO_TYPE, 0, (LPBYTE *) &pIfInfo);
  632. if (pIfInfo)
  633. {
  634. pEntry->m_dwAccept = pIfInfo->NetbiosAccept;
  635. pEntry->m_dwDeliver = pIfInfo->NetbiosDeliver;
  636. }
  637. break;
  638. }
  639. }
  640. //Error:
  641. if (hr == HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS))
  642. hr = hrOK;
  643. return hr;
  644. }
  645. /*!--------------------------------------------------------------------------
  646. IpxNBHandler::AddMenuItems
  647. Implementation of ITFSResultHandler::AddMenuItems
  648. Use this to add commands to the context menu of the blank areas
  649. of the result pane.
  650. Author: KennT
  651. ---------------------------------------------------------------------------*/
  652. STDMETHODIMP IpxNBHandler::AddMenuItems(ITFSComponent *pComponent,
  653. MMC_COOKIE cookie,
  654. LPDATAOBJECT pDataObject,
  655. LPCONTEXTMENUCALLBACK pCallback,
  656. long *pInsertionAllowed)
  657. {
  658. return hrOK;
  659. }
  660. /*!--------------------------------------------------------------------------
  661. IpxNBHandler::Command
  662. -
  663. Author: KennT
  664. ---------------------------------------------------------------------------*/
  665. STDMETHODIMP IpxNBHandler::Command(ITFSComponent *pComponent,
  666. MMC_COOKIE cookie,
  667. int nCommandID,
  668. LPDATAOBJECT pDataObject)
  669. {
  670. return hrOK;
  671. }
  672. ImplementEmbeddedUnknown(IpxNBHandler, IRtrAdviseSink)
  673. STDMETHODIMP IpxNBHandler::EIRtrAdviseSink::OnChange(LONG_PTR ulConn,
  674. DWORD dwChangeType, DWORD dwObjectType, LPARAM lUserParam, LPARAM lParam)
  675. {
  676. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  677. InitPThis(IpxNBHandler, IRtrAdviseSink);
  678. SPITFSNode spThisNode;
  679. SPITFSNode spNode;
  680. SPITFSNodeEnum spEnumNode;
  681. SPIEnumInterfaceInfo spEnumIf;
  682. SPIInterfaceInfo spIf;
  683. BOOL fFound;
  684. BOOL fPleaseAdd;
  685. BaseIPXResultNodeData * pData;
  686. HRESULT hr = hrOK;
  687. pThis->m_spNodeMgr->FindNode(pThis->m_cookie, &spThisNode);
  688. if (dwObjectType == ROUTER_OBJ_RmIf)
  689. {
  690. if (dwChangeType == ROUTER_CHILD_ADD)
  691. {
  692. // Enumerate through the list of interfaces looking for
  693. // the interfaces that have this protocol. If we find
  694. // one, look for this interface in our list of nodes.
  695. spThisNode->GetEnum(&spEnumNode);
  696. CORg( pThis->m_spRouterInfo->EnumInterface(&spEnumIf) );
  697. spEnumIf->Reset();
  698. fPleaseAdd = FALSE;
  699. for (; spEnumIf->Next(1, &spIf, NULL) == hrOK; spIf.Release())
  700. {
  701. // Look for this interface in our list of nodes
  702. // If it's there than continue on
  703. fFound = FALSE;
  704. spEnumNode->Reset();
  705. spNode.Release();
  706. for (; spEnumNode->Next(1, &spNode, NULL) == hrOK; spNode.Release())
  707. {
  708. pData = GET_BASEIPXRESULT_NODEDATA(spNode);
  709. Assert(pData);
  710. ASSERT_BASEIPXRESULT_NODEDATA(pData);
  711. if (!pData->m_fClient && StriCmpW(pData->m_spIf->GetId(), spIf->GetId()) == 0)
  712. {
  713. fFound = TRUE;
  714. break;
  715. }
  716. }
  717. // If the interface was not found in the list of nodes,
  718. // then it is a candidate. Now we have to see if the
  719. // interface supports this transport.
  720. if (!fFound && (spIf->FindRtrMgrInterface(pThis->m_spRtrMgrInfo->GetTransportId(), NULL) == hrOK))
  721. {
  722. // If this interface has this transport, and is NOT in
  723. // the current list of nodes then add this interface
  724. // to the UI
  725. pThis->AddInterfaceNode(spThisNode, spIf, FALSE);
  726. fPleaseAdd = TRUE;
  727. }
  728. }
  729. // If it's not expanded, then we haven't added
  730. // the dial-in clients node.
  731. if (!pThis->m_bExpanded)
  732. {
  733. //$CLIENT: Add the client interface (setup default data)
  734. // the only thing that we can do in synchronize is to
  735. // get the Administrative status
  736. pThis->AddInterfaceNode(spThisNode, NULL, TRUE);
  737. fPleaseAdd = TRUE;
  738. }
  739. // Now that we have all of the nodes, update the data for
  740. // all of the nodes
  741. if (fPleaseAdd)
  742. pThis->SynchronizeNodeData(spThisNode);
  743. // Windows NT Bug : 288247
  744. // Set this here, so that we can avoid the nodes being
  745. // added in the OnExpand().
  746. pThis->m_bExpanded = TRUE;
  747. }
  748. else if (dwChangeType == ROUTER_CHILD_DELETE)
  749. {
  750. // Go through the list of nodes, if we cannot find the
  751. // node in the list of interfaces, delete the node
  752. spThisNode->GetEnum(&spEnumNode);
  753. spEnumNode->Reset();
  754. while (spEnumNode->Next(1, &spNode, NULL) == hrOK)
  755. {
  756. // Get the node data, look for the interface
  757. pData = GET_BASEIPXRESULT_NODEDATA(spNode);
  758. ASSERT_BASEIPXRESULT_NODEDATA(pData);
  759. //$CLIENT: if this is a client interface, we can't
  760. // delete the node
  761. if (!pData->m_fClient &&
  762. (LookupRtrMgrInterface(pThis->m_spRouterInfo,
  763. pData->m_spIf->GetId(),
  764. pThis->m_spRtrMgrInfo->GetTransportId(),
  765. NULL) != hrOK))
  766. {
  767. // cannot find the interface, release this node!
  768. spThisNode->RemoveChild(spNode);
  769. spNode->Destroy();
  770. }
  771. spNode.Release();
  772. spIf.Release();
  773. }
  774. }
  775. }
  776. else if (dwChangeType == ROUTER_REFRESH)
  777. {
  778. pThis->SynchronizeNodeData(spThisNode);
  779. }
  780. Error:
  781. return hrOK;
  782. }
  783. /*!--------------------------------------------------------------------------
  784. IpxNBHandler::OnResultShow
  785. -
  786. Author: KennT
  787. ---------------------------------------------------------------------------*/
  788. HRESULT IpxNBHandler::OnResultShow(ITFSComponent *pTFSComponent, MMC_COOKIE cookie, LPARAM arg, LPARAM lParam)
  789. {
  790. BOOL bSelect = (BOOL) arg;
  791. HRESULT hr = hrOK;
  792. SPIRouterRefresh spRefresh;
  793. SPITFSNode spNode;
  794. BaseContainerHandler::OnResultShow(pTFSComponent, cookie, arg, lParam);
  795. if (bSelect)
  796. {
  797. // Call synchronize on this node
  798. m_spNodeMgr->FindNode(cookie, &spNode);
  799. if (spNode)
  800. SynchronizeNodeData(spNode);
  801. }
  802. // Un/Register for refresh advises
  803. if (m_spRouterInfo)
  804. m_spRouterInfo->GetRefreshObject(&spRefresh);
  805. if (spRefresh)
  806. {
  807. if (bSelect)
  808. {
  809. if (m_ulRefreshConnId == 0)
  810. spRefresh->AdviseRefresh(&m_IRtrAdviseSink, &m_ulRefreshConnId, 0);
  811. // if (m_ulStatsConnId == 0)
  812. // spRefresh->AdviseRefresh(&m_IRtrAdviseSink, &m_ulStatsConnId, 0);
  813. }
  814. else
  815. {
  816. if (m_ulRefreshConnId)
  817. spRefresh->UnadviseRefresh(m_ulRefreshConnId);
  818. m_ulRefreshConnId = 0;
  819. // We do not clean up the stats refresh on not show, since the
  820. // dialogs may still be up.
  821. }
  822. }
  823. return hr;
  824. }
  825. /*!--------------------------------------------------------------------------
  826. IpxNBHandler::CompareItems
  827. -
  828. Author: KennT
  829. ---------------------------------------------------------------------------*/
  830. STDMETHODIMP_(int) IpxNBHandler::CompareItems(
  831. ITFSComponent * pComponent,
  832. MMC_COOKIE cookieA,
  833. MMC_COOKIE cookieB,
  834. int nCol)
  835. {
  836. // Get the strings from the nodes and use that as a basis for
  837. // comparison.
  838. SPITFSNode spNode;
  839. SPITFSResultHandler spResult;
  840. m_spNodeMgr->FindNode(cookieA, &spNode);
  841. spNode->GetResultHandler(&spResult);
  842. return spResult->CompareItems(pComponent, cookieA, cookieB, nCol);
  843. }
  844. /*---------------------------------------------------------------------------
  845. Class: IpxNBInterfaceHandler
  846. ---------------------------------------------------------------------------*/
  847. IpxNBInterfaceHandler::IpxNBInterfaceHandler(ITFSComponentData *pCompData)
  848. : BaseIPXResultHandler(pCompData, COLUMNS_NBBROADCASTS),
  849. m_ulConnId(0)
  850. {
  851. m_rgButtonState[MMC_VERB_PROPERTIES_INDEX] = ENABLED;
  852. m_bState[MMC_VERB_PROPERTIES_INDEX] = TRUE;
  853. m_rgButtonState[MMC_VERB_REFRESH_INDEX] = ENABLED;
  854. m_bState[MMC_VERB_REFRESH_INDEX] = TRUE;
  855. m_verbDefault = MMC_VERB_PROPERTIES;
  856. }
  857. static const DWORD s_rgInterfaceImageMap[] =
  858. {
  859. ROUTER_IF_TYPE_HOME_ROUTER, IMAGE_IDX_WAN_CARD,
  860. ROUTER_IF_TYPE_FULL_ROUTER, IMAGE_IDX_WAN_CARD,
  861. ROUTER_IF_TYPE_CLIENT, IMAGE_IDX_WAN_CARD,
  862. ROUTER_IF_TYPE_DEDICATED, IMAGE_IDX_LAN_CARD,
  863. ROUTER_IF_TYPE_INTERNAL, IMAGE_IDX_LAN_CARD,
  864. ROUTER_IF_TYPE_LOOPBACK, IMAGE_IDX_LAN_CARD,
  865. -1, IMAGE_IDX_WAN_CARD, // sentinel value
  866. };
  867. /*!--------------------------------------------------------------------------
  868. IpxNBInterfaceHandler::ConstructNode
  869. Initializes the Domain node (sets it up).
  870. Author: KennT
  871. ---------------------------------------------------------------------------*/
  872. HRESULT IpxNBInterfaceHandler::ConstructNode(ITFSNode *pNode, IInterfaceInfo *pIfInfo, IPXConnection *pIPXConn)
  873. {
  874. HRESULT hr = hrOK;
  875. int i;
  876. if (pNode == NULL)
  877. return hrOK;
  878. COM_PROTECT_TRY
  879. {
  880. // Find the right image index for this type of node
  881. if (pIfInfo)
  882. {
  883. for (i=0; i<DimensionOf(s_rgInterfaceImageMap); i+=2)
  884. {
  885. if ((pIfInfo->GetInterfaceType() == s_rgInterfaceImageMap[i]) ||
  886. (-1 == s_rgInterfaceImageMap[i]))
  887. break;
  888. }
  889. }
  890. else
  891. {
  892. i = 2; // if no interface, assume this is a client interface
  893. }
  894. pNode->SetData(TFS_DATA_IMAGEINDEX, s_rgInterfaceImageMap[i+1]);
  895. pNode->SetData(TFS_DATA_OPENIMAGEINDEX, s_rgInterfaceImageMap[i+1]);
  896. pNode->SetData(TFS_DATA_SCOPEID, 0);
  897. pNode->SetData(TFS_DATA_COOKIE, reinterpret_cast<DWORD_PTR>(pNode));
  898. //$ Review: kennt, what are the different type of interfaces
  899. // do we distinguish based on the same list as above? (i.e. the
  900. // one for image indexes).
  901. pNode->SetNodeType(&GUID_IPXNetBIOSBroadcastsInterfaceNodeType);
  902. BaseIPXResultNodeData::Init(pNode, pIfInfo, pIPXConn);
  903. }
  904. COM_PROTECT_CATCH
  905. return hr;
  906. }
  907. /*!--------------------------------------------------------------------------
  908. IpxNBInterfaceHandler::OnCreateDataObject
  909. -
  910. Author: KennT
  911. ---------------------------------------------------------------------------*/
  912. STDMETHODIMP IpxNBInterfaceHandler::OnCreateDataObject(MMC_COOKIE cookie, DATA_OBJECT_TYPES type, IDataObject **ppDataObject)
  913. {
  914. HRESULT hr = hrOK;
  915. COM_PROTECT_TRY
  916. {
  917. CORg( CreateDataObjectFromInterfaceInfo(m_spInterfaceInfo,
  918. type, cookie, m_spTFSCompData,
  919. ppDataObject) );
  920. COM_PROTECT_ERROR_LABEL;
  921. }
  922. COM_PROTECT_CATCH;
  923. return hr;
  924. }
  925. /*!--------------------------------------------------------------------------
  926. IpxNBInterfaceHandler::OnCreateDataObject
  927. Implementation of ITFSResultHandler::OnCreateDataObject
  928. Author: KennT
  929. ---------------------------------------------------------------------------*/
  930. STDMETHODIMP IpxNBInterfaceHandler::OnCreateDataObject(ITFSComponent *pComp, MMC_COOKIE cookie, DATA_OBJECT_TYPES type, IDataObject **ppDataObject)
  931. {
  932. HRESULT hr = hrOK;
  933. COM_PROTECT_TRY
  934. {
  935. CORg( CreateDataObjectFromInterfaceInfo(m_spInterfaceInfo,
  936. type, cookie, m_spTFSCompData,
  937. ppDataObject) );
  938. COM_PROTECT_ERROR_LABEL;
  939. }
  940. COM_PROTECT_CATCH;
  941. return hr;
  942. }
  943. /*!--------------------------------------------------------------------------
  944. IpxNBInterfaceHandler::RefreshInterface
  945. -
  946. Author: KennT
  947. ---------------------------------------------------------------------------*/
  948. void IpxNBInterfaceHandler::RefreshInterface(MMC_COOKIE cookie)
  949. {
  950. SPITFSNode spNode;
  951. m_spNodeMgr->FindNode(cookie, &spNode);
  952. ForwardCommandToParent(spNode, IDS_MENU_SYNC,
  953. CCT_RESULT, NULL, 0);
  954. }
  955. /*!--------------------------------------------------------------------------
  956. IpxNBInterfaceHandler::Init
  957. -
  958. Author: KennT
  959. ---------------------------------------------------------------------------*/
  960. HRESULT IpxNBInterfaceHandler::Init(IRtrMgrInfo *pRm, IInterfaceInfo *pIfInfo, ITFSNode *pParent)
  961. {
  962. m_spRm.Set(pRm);
  963. if (pRm)
  964. pRm->GetParentRouterInfo(&m_spRouterInfo);
  965. m_spInterfaceInfo.Set(pIfInfo);
  966. BaseIPXResultHandler::Init(pIfInfo, pParent);
  967. return hrOK;
  968. }
  969. /*!--------------------------------------------------------------------------
  970. IpxNBInterfaceHandler::DestroyResultHandler
  971. -
  972. Author: KennT
  973. ---------------------------------------------------------------------------*/
  974. STDMETHODIMP IpxNBInterfaceHandler::DestroyResultHandler(MMC_COOKIE cookie)
  975. {
  976. m_spInterfaceInfo.Release();
  977. BaseIPXResultHandler::DestroyResultHandler(cookie);
  978. return hrOK;
  979. }
  980. /*---------------------------------------------------------------------------
  981. This is the list of commands that will show up for the result pane
  982. nodes.
  983. ---------------------------------------------------------------------------*/
  984. struct SIPXInterfaceNodeMenu
  985. {
  986. ULONG m_sidMenu; // string/command id for this menu item
  987. ULONG (IpxNBInterfaceHandler:: *m_pfnGetMenuFlags)(IpxNBInterfaceHandler::SMenuData *);
  988. ULONG m_ulPosition;
  989. };
  990. /*!--------------------------------------------------------------------------
  991. IpxNBInterfaceHandler::AddMenuItems
  992. Implementation of ITFSResultHandler::AddMenuItems
  993. Author: KennT
  994. ---------------------------------------------------------------------------*/
  995. STDMETHODIMP IpxNBInterfaceHandler::AddMenuItems(
  996. ITFSComponent *pComponent,
  997. MMC_COOKIE cookie,
  998. LPDATAOBJECT lpDataObject,
  999. LPCONTEXTMENUCALLBACK pContextMenuCallback,
  1000. long *pInsertionAllowed)
  1001. {
  1002. return hrOK;
  1003. }
  1004. /*!--------------------------------------------------------------------------
  1005. IpxNBInterfaceHandler::Command
  1006. -
  1007. Author: KennT
  1008. ---------------------------------------------------------------------------*/
  1009. STDMETHODIMP IpxNBInterfaceHandler::Command(ITFSComponent *pComponent,
  1010. MMC_COOKIE cookie,
  1011. int nCommandID,
  1012. LPDATAOBJECT pDataObject)
  1013. {
  1014. return hrOK;
  1015. }
  1016. /*!--------------------------------------------------------------------------
  1017. IpxNBInterfaceHandler::HasPropertyPages
  1018. -
  1019. Author: KennT
  1020. ---------------------------------------------------------------------------*/
  1021. STDMETHODIMP IpxNBInterfaceHandler::HasPropertyPages
  1022. (
  1023. ITFSNode * pNode,
  1024. LPDATAOBJECT pDataObject,
  1025. DATA_OBJECT_TYPES type,
  1026. DWORD dwType
  1027. )
  1028. {
  1029. return hrTrue;
  1030. }
  1031. /*!--------------------------------------------------------------------------
  1032. IpxNBInterfaceHandler::CreatePropertyPages
  1033. -
  1034. Author: KennT
  1035. ---------------------------------------------------------------------------*/
  1036. STDMETHODIMP IpxNBInterfaceHandler::CreatePropertyPages
  1037. (
  1038. ITFSNode * pNode,
  1039. LPPROPERTYSHEETCALLBACK lpProvider,
  1040. LPDATAOBJECT pDataObject,
  1041. LONG_PTR handle,
  1042. DWORD dwType
  1043. )
  1044. {
  1045. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1046. HRESULT hr = hrOK;
  1047. IpxNBInterfaceProperties * pProperties = NULL;
  1048. SPIComponentData spComponentData;
  1049. CString stTitle;
  1050. CORg( m_spNodeMgr->GetComponentData(&spComponentData) );
  1051. if (m_spInterfaceInfo)
  1052. stTitle.Format(IDS_IPXNB_IF_PAGE_TITLE,
  1053. m_spInterfaceInfo->GetTitle());
  1054. else
  1055. stTitle.LoadString(IDS_IPXNB_CLIENT_IF_PAGE_TITLE);
  1056. pProperties = new IpxNBInterfaceProperties(pNode, spComponentData,
  1057. m_spTFSCompData, stTitle);
  1058. CORg( pProperties->Init(m_spRm, m_spInterfaceInfo) );
  1059. if (lpProvider)
  1060. hr = pProperties->CreateModelessSheet(lpProvider, handle);
  1061. else
  1062. hr = pProperties->DoModelessSheet();
  1063. Error:
  1064. return hr;
  1065. }
  1066. /*!--------------------------------------------------------------------------
  1067. IpxNBInterfaceHandler::CreatePropertyPages
  1068. Implementation of ResultHandler::CreatePropertyPages
  1069. Author: KennT
  1070. ---------------------------------------------------------------------------*/
  1071. STDMETHODIMP IpxNBInterfaceHandler::CreatePropertyPages
  1072. (
  1073. ITFSComponent * pComponent,
  1074. MMC_COOKIE cookie,
  1075. LPPROPERTYSHEETCALLBACK lpProvider,
  1076. LPDATAOBJECT pDataObject,
  1077. LONG_PTR handle
  1078. )
  1079. {
  1080. // Forward this call onto the NodeHandler::CreatePropertyPages
  1081. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1082. HRESULT hr = hrOK;
  1083. SPITFSNode spNode;
  1084. Assert( m_spNodeMgr );
  1085. CORg( m_spNodeMgr->FindNode(cookie, &spNode) );
  1086. // Call the ITFSNodeHandler::CreatePropertyPages
  1087. hr = CreatePropertyPages(spNode, lpProvider, pDataObject, handle, 0);
  1088. Error:
  1089. return hr;
  1090. }