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.

1332 lines
34 KiB

  1. /**********************************************************************/
  2. /** Microsoft Windows/NT **/
  3. /** Copyright(c) Microsoft Corporation, 1997 - 1999 **/
  4. /**********************************************************************/
  5. /*
  6. server.cpp
  7. IPSecMon machine node handler
  8. FILE HISTORY:
  9. */
  10. #include "stdafx.h"
  11. #include "server.h" // Server definition
  12. #include "spddb.h"
  13. #include "servpp.h"
  14. #include "modenode.h"
  15. #include "objplus.h"
  16. #include "ipaddres.h"
  17. CTimerMgr g_TimerMgr;
  18. CHashTable g_HashTable;
  19. extern ULONG RevertDwordBytes(DWORD dw);
  20. /////////////////////////////////////////////////////////////////////
  21. //
  22. // CTimerArray implementation
  23. //
  24. /////////////////////////////////////////////////////////////////////
  25. CTimerMgr::CTimerMgr()
  26. {
  27. }
  28. CTimerMgr::~CTimerMgr()
  29. {
  30. CTimerDesc * pTimerDesc;
  31. for (int i = (int)GetUpperBound(); i >= 0; --i)
  32. {
  33. pTimerDesc = GetAt(i);
  34. if (pTimerDesc->uTimer != 0)
  35. FreeTimer(i);
  36. delete pTimerDesc;
  37. }
  38. }
  39. int
  40. CTimerMgr::AllocateTimer
  41. (
  42. ITFSNode * pNode,
  43. CIpsmServer * pServer,
  44. UINT uTimerValue,
  45. TIMERPROC TimerProc
  46. )
  47. {
  48. CSingleLock slTimerMgr(&m_csTimerMgr);
  49. // get a lock on the timer mgr for the scope of this
  50. // function.
  51. slTimerMgr.Lock();
  52. CTimerDesc * pTimerDesc = NULL;
  53. // look for an empty slot
  54. for (int i = (int)GetUpperBound(); i >= 0; --i)
  55. {
  56. pTimerDesc = GetAt(i);
  57. if (pTimerDesc->uTimer == 0)
  58. break;
  59. }
  60. // did we find one? if not allocate one
  61. if (i < 0)
  62. {
  63. pTimerDesc = new CTimerDesc;
  64. Add(pTimerDesc);
  65. i = (int)GetUpperBound();
  66. }
  67. pTimerDesc->uTimer = SetTimer(NULL, (UINT) i, uTimerValue, TimerProc);
  68. if (pTimerDesc->uTimer == 0)
  69. return -1;
  70. pTimerDesc->spNode.Set(pNode);
  71. pTimerDesc->pServer = pServer;
  72. pTimerDesc->timerProc = TimerProc;
  73. return i;
  74. }
  75. void
  76. CTimerMgr::FreeTimer
  77. (
  78. UINT_PTR uEventId
  79. )
  80. {
  81. CSingleLock slTimerMgr(&m_csTimerMgr);
  82. // get a lock on the timer mgr for the scope of this
  83. // function.
  84. slTimerMgr.Lock();
  85. CTimerDesc * pTimerDesc;
  86. Assert(uEventId <= (UINT) GetUpperBound());
  87. if (uEventId > (UINT) GetUpperBound())
  88. return;
  89. pTimerDesc = GetAt((int) uEventId);
  90. ::KillTimer(NULL, pTimerDesc->uTimer);
  91. pTimerDesc->spNode.Release();
  92. pTimerDesc->pServer = NULL;
  93. pTimerDesc->uTimer = 0;
  94. }
  95. CTimerDesc *
  96. CTimerMgr::GetTimerDesc
  97. (
  98. UINT_PTR uEventId
  99. )
  100. {
  101. CSingleLock slTimerMgr(&m_csTimerMgr);
  102. // the caller of this function should lock the timer mgr
  103. // while accessing this pointer
  104. CTimerDesc * pTimerDesc;
  105. for (int i = (int)GetUpperBound(); i >= 0; --i)
  106. {
  107. pTimerDesc = GetAt(i);
  108. if (pTimerDesc->uTimer == (UINT) uEventId)
  109. return pTimerDesc;
  110. }
  111. return NULL;
  112. }
  113. void
  114. CTimerMgr::ChangeInterval
  115. (
  116. UINT_PTR uEventId,
  117. UINT uNewInterval
  118. )
  119. {
  120. CSingleLock slTimerMgr(&m_csTimerMgr);
  121. // get a lock on the timer mgr for the scope of this
  122. // function.
  123. slTimerMgr.Lock();
  124. Assert(uEventId <= (UINT) GetUpperBound());
  125. if (uEventId > (UINT) GetUpperBound())
  126. return;
  127. CTimerDesc tempTimerDesc;
  128. CTimerDesc * pTimerDesc;
  129. pTimerDesc = GetAt((int) uEventId);
  130. // kill the old timer
  131. ::KillTimer(NULL, pTimerDesc->uTimer);
  132. // set a new one with the new interval
  133. pTimerDesc->uTimer = ::SetTimer(NULL, (UINT) uEventId, uNewInterval, pTimerDesc->timerProc);
  134. }
  135. VOID CALLBACK
  136. StatisticsTimerProc
  137. (
  138. HWND hwnd,
  139. UINT uMsg,
  140. UINT_PTR idEvent,
  141. DWORD dwTime
  142. )
  143. {
  144. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  145. CSingleLock slTimerMgr(&g_TimerMgr.m_csTimerMgr);
  146. // get a lock on the timer mgr for the scope of this
  147. // function.
  148. slTimerMgr.Lock();
  149. // on the timer, get the timer descriptor for this event
  150. // Call into the appropriate handler to update the stats.
  151. CTimerDesc * pTimerDesc;
  152. pTimerDesc = g_TimerMgr.GetTimerDesc(idEvent);
  153. pTimerDesc->pServer->m_bStatsOnly = TRUE;
  154. pTimerDesc->pServer->OnRefreshStats(pTimerDesc->spNode,
  155. NULL,
  156. NULL,
  157. 0,
  158. 0);
  159. pTimerDesc->pServer->m_bStatsOnly = FALSE;
  160. }
  161. /*---------------------------------------------------------------------------
  162. Class CIpsmServer implementation
  163. ---------------------------------------------------------------------------*/
  164. /*--------------------------------------------------------------------------
  165. Constructor and destructor
  166. Description
  167. Author: NSun
  168. ---------------------------------------------------------------------------*/
  169. CIpsmServer::CIpsmServer
  170. (
  171. ITFSComponentData * pComponentData
  172. ) : CMTIpsmHandler(pComponentData),
  173. m_bStatsOnly(FALSE),
  174. m_StatsTimerId(-1),
  175. m_dwOptions(0)
  176. {
  177. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  178. }
  179. CIpsmServer::~CIpsmServer()
  180. {
  181. if (m_StatsDlg.GetSafeHwnd())
  182. {
  183. WaitForModelessDlgClose(&m_StatsDlg);
  184. }
  185. }
  186. /*!--------------------------------------------------------------------------
  187. CIpsmServer::InitializeNode
  188. Initializes node specific data
  189. Author: NSun
  190. ---------------------------------------------------------------------------*/
  191. HRESULT
  192. CIpsmServer::InitializeNode
  193. (
  194. ITFSNode * pNode
  195. )
  196. {
  197. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  198. HRESULT hr = hrOK;
  199. CString strTemp;
  200. COM_PROTECT_TRY
  201. {
  202. CORg (CreateSpdInfo(&m_spSpdInfo));
  203. m_spSpdInfo->SetComputerName((LPTSTR)(LPCTSTR)m_strServerAddress);
  204. BuildDisplayName(&strTemp);
  205. SetDisplayName(strTemp);
  206. // Make the node immediately visible
  207. pNode->SetVisibilityState(TFS_VIS_SHOW);
  208. pNode->SetData(TFS_DATA_COOKIE, (LPARAM) pNode);
  209. pNode->SetData(TFS_DATA_IMAGEINDEX, ICON_IDX_SERVER);
  210. pNode->SetData(TFS_DATA_OPENIMAGEINDEX, ICON_IDX_SERVER);
  211. pNode->SetData(TFS_DATA_USER, (LPARAM) this);
  212. pNode->SetData(TFS_DATA_TYPE, IPSMSNAP_SERVER);
  213. SetColumnStringIDs(&aColumns[IPSMSNAP_SERVER][0]);
  214. SetColumnWidths(&aColumnWidths[IPSMSNAP_SERVER][0]);
  215. m_StatsDlg.SetData(m_spSpdInfo);
  216. COM_PROTECT_ERROR_LABEL;
  217. }
  218. COM_PROTECT_CATCH
  219. return hr;
  220. }
  221. /*---------------------------------------------------------------------------
  222. CIpsmServer::GetImageIndex
  223. -
  224. Author: NSun
  225. ---------------------------------------------------------------------------*/
  226. int
  227. CIpsmServer::GetImageIndex(BOOL bOpenImage)
  228. {
  229. int nIndex = -1;
  230. switch (m_nState)
  231. {
  232. case notLoaded:
  233. nIndex = ICON_IDX_SERVER;
  234. break;
  235. case loading:
  236. nIndex = ICON_IDX_SERVER_BUSY;
  237. break;
  238. case loaded:
  239. nIndex = ICON_IDX_SERVER_CONNECTED;
  240. break;
  241. case unableToLoad:
  242. nIndex = ICON_IDX_SERVER_LOST_CONNECTION;
  243. break;
  244. default:
  245. ASSERT(FALSE);
  246. }
  247. return nIndex;
  248. }
  249. /*---------------------------------------------------------------------------
  250. CIpsmServer::OnHaveData
  251. When the background thread enumerates nodes to be added to the UI,
  252. we get called back here. We override this to force expansion of the
  253. node so that things show up correctly.
  254. Author: NSun
  255. ---------------------------------------------------------------------------*/
  256. void
  257. CIpsmServer::OnHaveData
  258. (
  259. ITFSNode * pParentNode,
  260. ITFSNode * pNewNode
  261. )
  262. {
  263. CMTIpsmHandler::OnHaveData(pParentNode, pNewNode);
  264. ExpandNode(pParentNode, TRUE);
  265. }
  266. /*---------------------------------------------------------------------------
  267. CIpsmServer::OnHaveData
  268. Description
  269. Author: NSun
  270. ---------------------------------------------------------------------------*/
  271. void
  272. CIpsmServer::OnHaveData
  273. (
  274. ITFSNode * pParentNode,
  275. LPARAM Data,
  276. LPARAM Type
  277. )
  278. {
  279. HRESULT hr = hrOK;
  280. HWND hStatsDlg = NULL;
  281. // This is how we get non-node data back from the background thread.
  282. switch (Type)
  283. {
  284. case IPSECMON_QDATA_REFRESH_STATS:
  285. {
  286. // tell all of the child nodes to clear their status caches
  287. // if any of the nodes is the selected node, then they should
  288. // repaint the window
  289. SPITFSNodeEnum spNodeEnum;
  290. SPITFSNode spCurrentNode;
  291. ULONG nNumReturned;
  292. CORg(pParentNode->GetEnum(&spNodeEnum));
  293. CORg(spNodeEnum->Next(1, &spCurrentNode, &nNumReturned));
  294. while (nNumReturned)
  295. {
  296. LONG_PTR dwDataType = spCurrentNode->GetData(TFS_DATA_TYPE);
  297. switch (dwDataType)
  298. {
  299. case IPSECMON_QUICK_MODE:
  300. {
  301. CQmNodeHandler * pQmHandler = GETHANDLER(CQmNodeHandler, spCurrentNode);
  302. pQmHandler->UpdateStatus(spCurrentNode);
  303. }
  304. break;
  305. case IPSECMON_MAIN_MODE:
  306. {
  307. CMmNodeHandler * pMmHandler = GETHANDLER(CMmNodeHandler, spCurrentNode);
  308. pMmHandler->UpdateStatus(spCurrentNode);
  309. }
  310. break;
  311. //Put it here if there is any other child node under machine node
  312. default:
  313. break;
  314. }
  315. spCurrentNode.Release();
  316. spNodeEnum->Next(1, &spCurrentNode, &nNumReturned);
  317. }
  318. //Tell the statistics window to update
  319. hStatsDlg = m_StatsDlg.GetSafeHwnd();
  320. if (hStatsDlg)
  321. {
  322. PostMessage(hStatsDlg, WM_UPDATE_STATS, 0, 0);
  323. }
  324. // reset the timer
  325. g_TimerMgr.ChangeInterval(m_StatsTimerId, m_dwRefreshInterval);
  326. }
  327. break;
  328. case IPSECMON_QDATA_FAILED:
  329. pParentNode->DeleteAllChildren(TRUE);
  330. // in OnChangeState, the sate will be changed to unableToLoad
  331. // and the error will be posted
  332. m_nState = loading;
  333. OnChangeState(pParentNode);
  334. //Also close the statistics window
  335. hStatsDlg = m_StatsDlg.GetSafeHwnd();
  336. if (hStatsDlg)
  337. {
  338. PostMessage(hStatsDlg, WM_CLOSE, 0, 0);
  339. }
  340. break;
  341. }
  342. COM_PROTECT_ERROR_LABEL;
  343. }
  344. /*---------------------------------------------------------------------------
  345. Overridden base handler functions
  346. ---------------------------------------------------------------------------*/
  347. /*---------------------------------------------------------------------------
  348. CIpsmServer::OnAddMenuItems
  349. Description
  350. Author: NSun
  351. ---------------------------------------------------------------------------*/
  352. STDMETHODIMP
  353. CIpsmServer::OnAddMenuItems
  354. (
  355. ITFSNode * pNode,
  356. LPCONTEXTMENUCALLBACK pContextMenuCallback,
  357. LPDATAOBJECT lpDataObject,
  358. DATA_OBJECT_TYPES type,
  359. DWORD dwType,
  360. long * pInsertionAllowed
  361. )
  362. {
  363. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  364. LONG fFlags = 0;
  365. HRESULT hr = S_OK;
  366. CString strMenuItem;
  367. //TODO handle menu items here
  368. if (m_nState != loaded)
  369. {
  370. fFlags |= MF_GRAYED;
  371. }
  372. if (type == CCT_SCOPE)
  373. {
  374. if (*pInsertionAllowed & CCM_INSERTIONALLOWED_TOP)
  375. {
  376. strMenuItem.LoadString(IDS_MENU_STATISTICS);
  377. hr = LoadAndAddMenuItem( pContextMenuCallback,
  378. strMenuItem,
  379. IDS_MENU_STATISTICS,
  380. CCM_INSERTIONPOINTID_PRIMARY_TOP,
  381. fFlags );
  382. strMenuItem.LoadString(IDS_MENU_RECONNECT);
  383. hr = LoadAndAddMenuItem( pContextMenuCallback,
  384. strMenuItem,
  385. IDS_MENU_RECONNECT,
  386. CCM_INSERTIONPOINTID_PRIMARY_TOP,
  387. 0
  388. );
  389. ASSERT( SUCCEEDED(hr) );
  390. }
  391. }
  392. return hr;
  393. }
  394. /*---------------------------------------------------------------------------
  395. CIpsmServer::OnCommand
  396. Description
  397. Author: NSun
  398. ---------------------------------------------------------------------------*/
  399. STDMETHODIMP
  400. CIpsmServer::OnCommand
  401. (
  402. ITFSNode * pNode,
  403. long nCommandId,
  404. DATA_OBJECT_TYPES type,
  405. LPDATAOBJECT pDataObject,
  406. DWORD dwType
  407. )
  408. {
  409. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  410. HRESULT hr = S_OK;
  411. switch (nCommandId)
  412. {
  413. case IDS_MENU_STATISTICS:
  414. CreateModelessDlg(&m_StatsDlg,
  415. FindMMCMainWindow(),
  416. IDD_IPSM_STATS);
  417. break;
  418. case IDS_MENU_RECONNECT:
  419. OnRefresh(pNode, pDataObject, 0, 0, 0);
  420. break;
  421. default:
  422. break;
  423. }
  424. return hr;
  425. }
  426. /*!--------------------------------------------------------------------------
  427. CIpsmServer::HasPropertyPages
  428. Implementation of ITFSNodeHandler::HasPropertyPages
  429. NOTE: the root node handler has to over-ride this function to
  430. handle the snapin manager property page (wizard) case!!!
  431. Author: KennT
  432. ---------------------------------------------------------------------------*/
  433. STDMETHODIMP
  434. CIpsmServer::HasPropertyPages
  435. (
  436. ITFSNode * pNode,
  437. LPDATAOBJECT pDataObject,
  438. DATA_OBJECT_TYPES type,
  439. DWORD dwType
  440. )
  441. {
  442. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  443. HRESULT hr = hrOK;
  444. if (dwType & TFS_COMPDATA_CREATE)
  445. {
  446. // This is the case where we are asked to bring up property
  447. // pages when the user is adding a new snapin. These calls
  448. // are forwarded to the root node to handle. Only for the root node
  449. hr = hrOK;
  450. Assert(FALSE); // should never get here
  451. }
  452. else
  453. {
  454. // we have property pages in the normal case, but don't put the
  455. // menu up if we are not loaded yet
  456. if ( (m_nState == loaded) ||
  457. (m_nState == unableToLoad) )
  458. {
  459. hr = hrOK;
  460. }
  461. else
  462. {
  463. hr = hrFalse;
  464. }
  465. }
  466. return hr;
  467. }
  468. /*---------------------------------------------------------------------------
  469. CIpsmServer::CreatePropertyPages
  470. Description
  471. Author: NSun
  472. ---------------------------------------------------------------------------*/
  473. STDMETHODIMP
  474. CIpsmServer::CreatePropertyPages
  475. (
  476. ITFSNode * pNode,
  477. LPPROPERTYSHEETCALLBACK lpProvider,
  478. LPDATAOBJECT pDataObject,
  479. LONG_PTR handle,
  480. DWORD dwType
  481. )
  482. {
  483. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  484. //
  485. // Create the property page
  486. //
  487. SPIComponentData spComponentData;
  488. m_spNodeMgr->GetComponentData(&spComponentData);
  489. CMachineProperties * pMachineProp = new CMachineProperties(
  490. pNode,
  491. spComponentData,
  492. m_spTFSCompData,
  493. m_spSpdInfo,
  494. NULL,
  495. loaded == m_nState
  496. );
  497. pMachineProp->m_strMachineName = m_strServerAddress;
  498. // fill in the auto refresh info
  499. pMachineProp->m_pageRefresh.m_dwRefreshInterval = GetAutoRefreshInterval();
  500. pMachineProp->m_pageRefresh.m_bAutoRefresh = GetOptions() & IPSMSNAP_OPTIONS_REFRESH ? TRUE : FALSE;
  501. pMachineProp->m_pageRefresh.m_bEnableDns = GetOptions() & IPSMSNAP_OPTIONS_DNS ? TRUE : FALSE;
  502. return pMachineProp->CreateModelessSheet(lpProvider, handle);
  503. }
  504. /*---------------------------------------------------------------------------
  505. CIpsmServer::OnPropertyChange
  506. Description
  507. Author: NSun
  508. ---------------------------------------------------------------------------*/
  509. HRESULT
  510. CIpsmServer::OnPropertyChange
  511. (
  512. ITFSNode * pNode,
  513. LPDATAOBJECT pDataobject,
  514. DWORD dwType,
  515. LPARAM arg,
  516. LPARAM lParam
  517. )
  518. {
  519. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  520. CMachineProperties * pMachineProp = reinterpret_cast<CMachineProperties *>(lParam);
  521. LONG_PTR changeMask = 0;
  522. // tell the property page to do whatever now that we are back on the
  523. // main thread
  524. pMachineProp->OnPropertyChange(TRUE, &changeMask);
  525. //Let the main thread know that we are done
  526. pMachineProp->AcknowledgeNotify();
  527. if (changeMask)
  528. pNode->ChangeNode(changeMask);
  529. return hrOK;
  530. }
  531. /*!--------------------------------------------------------------------------
  532. CIpsmServer::OnDelete
  533. The base handler calls this when MMC sends a MMCN_DELETE for a
  534. scope pane item. We just call our delete command handler.
  535. Author: NSun
  536. ---------------------------------------------------------------------------*/
  537. HRESULT
  538. CIpsmServer::OnDelete
  539. (
  540. ITFSNode * pNode,
  541. LPARAM arg,
  542. LPARAM lParam
  543. )
  544. {
  545. return OnDelete(pNode);
  546. }
  547. /*!--------------------------------------------------------------------------
  548. CIpsmServer::OnNotifyExiting
  549. We override this for the server node because we don't want the
  550. icon to change when the thread goes away. Normal behavior is that
  551. the node's icon changes to a wait cursor when the background thread
  552. is running. If we are only doing stats collection, then we
  553. don't want the icon to change.
  554. Author: NSun
  555. ---------------------------------------------------------------------------*/
  556. HRESULT
  557. CIpsmServer::OnNotifyExiting
  558. (
  559. LPARAM lParam
  560. )
  561. {
  562. CIpsmServerQueryObj * pQuery = (CIpsmServerQueryObj *) lParam;
  563. if (!pQuery->m_bStatsOnly)
  564. OnChangeState(m_spNode);
  565. ReleaseThreadHandler();
  566. Unlock();
  567. return hrOK;
  568. }
  569. /*---------------------------------------------------------------------------
  570. Command handlers
  571. ---------------------------------------------------------------------------*/
  572. /*!--------------------------------------------------------------------------
  573. CIpsmServer::OnRefresh
  574. Default implementation for the refresh functionality
  575. Author: NSun
  576. ---------------------------------------------------------------------------*/
  577. HRESULT
  578. CIpsmServer::OnRefresh
  579. (
  580. ITFSNode * pNode,
  581. LPDATAOBJECT pDataObject,
  582. DWORD dwType,
  583. LPARAM arg,
  584. LPARAM param
  585. )
  586. {
  587. HRESULT hr = S_OK;
  588. m_spSpdInfo->Destroy();
  589. hr = CMTHandler::OnRefresh(pNode, pDataObject, dwType, arg, param);
  590. HWND hStatsDlg = m_StatsDlg.GetSafeHwnd();
  591. if (hStatsDlg)
  592. {
  593. PostMessage(hStatsDlg, WM_UPDATE_STATS, 0, 0);
  594. }
  595. return hr;
  596. }
  597. /*!--------------------------------------------------------------------------
  598. CIpsmServer::OnRefreshStats
  599. Default implementation for the Stats refresh functionality
  600. Author: NSun
  601. ---------------------------------------------------------------------------*/
  602. HRESULT
  603. CIpsmServer::OnRefreshStats
  604. (
  605. ITFSNode * pNode,
  606. LPDATAOBJECT pDataObject,
  607. DWORD dwType,
  608. LPARAM arg,
  609. LPARAM param
  610. )
  611. {
  612. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  613. HRESULT hr = hrOK;
  614. SPITFSNode spNode;
  615. SPITFSNodeHandler spHandler;
  616. ITFSQueryObject * pQuery = NULL;
  617. if (m_bExpanded == FALSE)
  618. {
  619. // we cannot get statistics if the node hasn't been expanded yet
  620. return hr;
  621. }
  622. // only do stats refresh if the server was loaded correctly.
  623. if (m_nState != loaded)
  624. return hr;
  625. BOOL bLocked = IsLocked();
  626. if (bLocked)
  627. {
  628. // cannot refresh stats if this node is locked
  629. return hr;
  630. }
  631. Lock();
  632. //OnChangeState(pNode);
  633. pQuery = OnCreateQuery(pNode);
  634. Assert(pQuery);
  635. // notify the UI to change icon, if needed
  636. //Verify(SUCCEEDED(pComponentData->ChangeNode(this, SCOPE_PANE_CHANGE_ITEM_ICON)));
  637. Verify(StartBackgroundThread(pNode, m_spTFSCompData->GetHiddenWnd(), pQuery));
  638. pQuery->Release();
  639. return hrOK;
  640. }
  641. /*---------------------------------------------------------------------------
  642. CIpsmServer::OnDelete()
  643. Description
  644. Author: NSun
  645. ---------------------------------------------------------------------------*/
  646. HRESULT
  647. CIpsmServer::OnDelete(ITFSNode * pNode)
  648. {
  649. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  650. HRESULT hr = S_OK;
  651. CString strMessage;
  652. AfxFormatString1(strMessage, IDS_WARN_SERVER_DELETE, m_strServerAddress);
  653. if (AfxMessageBox(strMessage, MB_YESNO) == IDYES)
  654. {
  655. // remove this node from the list, there's nothing we need to tell
  656. // the server, it's just our local list of servers
  657. SPITFSNode spParent;
  658. pNode->GetParent(&spParent);
  659. spParent->RemoveChild(pNode);
  660. }
  661. return hr;
  662. }
  663. /*---------------------------------------------------------------------------
  664. Server manipulation functions
  665. ---------------------------------------------------------------------------*/
  666. /*---------------------------------------------------------------------------
  667. CIpsmServer::BuildDisplayName
  668. Builds the string that goes in the UI for this server
  669. Author: NSun
  670. ---------------------------------------------------------------------------*/
  671. HRESULT
  672. CIpsmServer::BuildDisplayName
  673. (
  674. CString * pstrDisplayName
  675. )
  676. {
  677. if (pstrDisplayName)
  678. {
  679. *pstrDisplayName = GetName();
  680. }
  681. return hrOK;
  682. }
  683. /*---------------------------------------------------------------------------
  684. CIpsmServer::SetAutoRefresh
  685. Description
  686. Author: NSun
  687. ---------------------------------------------------------------------------*/
  688. HRESULT
  689. CIpsmServer::SetAutoRefresh
  690. (
  691. ITFSNode * pNode,
  692. BOOL bOn,
  693. DWORD dwRefreshInterval
  694. )
  695. {
  696. BOOL bCurrentAutoRefresh = IsAutoRefreshEnabled();
  697. if (bCurrentAutoRefresh &&
  698. !bOn)
  699. {
  700. // turning off the timer
  701. g_TimerMgr.FreeTimer(m_StatsTimerId);
  702. }
  703. else
  704. if (!bCurrentAutoRefresh &&
  705. bOn)
  706. {
  707. // gotta turn on the timer
  708. m_StatsTimerId = g_TimerMgr.AllocateTimer(pNode, this, dwRefreshInterval, StatisticsTimerProc);
  709. }
  710. else
  711. if (bOn &&
  712. m_dwRefreshInterval != dwRefreshInterval)
  713. {
  714. // time to change the timer
  715. g_TimerMgr.ChangeInterval(m_StatsTimerId, dwRefreshInterval);
  716. }
  717. if (bOn)
  718. m_dwOptions |= IPSMSNAP_OPTIONS_REFRESH;
  719. else
  720. m_dwOptions &= ~IPSMSNAP_OPTIONS_REFRESH;
  721. m_dwRefreshInterval = dwRefreshInterval;
  722. return hrOK;
  723. }
  724. /*---------------------------------------------------------------------------
  725. CIpsmServer::SetDnsResolve
  726. Description
  727. Author: Briansw
  728. ---------------------------------------------------------------------------*/
  729. HRESULT
  730. CIpsmServer::SetDnsResolve
  731. (
  732. ITFSNode * pNode,
  733. BOOL bEnable
  734. )
  735. {
  736. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  737. if (bEnable)
  738. m_dwOptions |= IPSMSNAP_OPTIONS_DNS;
  739. else
  740. m_dwOptions &= ~IPSMSNAP_OPTIONS_DNS;
  741. g_HashTable.SetDnsResolve(bEnable);
  742. return hrOK;
  743. }
  744. /*---------------------------------------------------------------------------
  745. CIpsmServer::SetAutoRefresh
  746. Description
  747. Author: NSun
  748. ---------------------------------------------------------------------------*/
  749. void
  750. CIpsmServer::SetExtensionName()
  751. {
  752. CString strName;
  753. strName.LoadString(IDS_IPSECMON);
  754. SetDisplayName(strName);
  755. }
  756. /*!--------------------------------------------------------------------------
  757. CIpsmServer::UpdateStandardVerbs
  758. Updates the standard verbs depending upon the state of the node
  759. Author: NSun
  760. ---------------------------------------------------------------------------*/
  761. void
  762. CIpsmServer::UpdateConsoleVerbs
  763. (
  764. IConsoleVerb * pConsoleVerb,
  765. LONG_PTR dwNodeType,
  766. BOOL bMultiSelect
  767. )
  768. {
  769. BOOL bStates[ARRAYLEN(g_ConsoleVerbs)];
  770. MMC_BUTTON_STATE * ButtonState;
  771. int i;
  772. if (bMultiSelect)
  773. {
  774. ButtonState = g_ConsoleVerbStatesMultiSel[dwNodeType];
  775. for (i = 0; i < ARRAYLEN(g_ConsoleVerbs); bStates[i++] = TRUE);
  776. }
  777. else
  778. {
  779. ButtonState = g_ConsoleVerbStates[dwNodeType];
  780. switch (m_nState)
  781. {
  782. case loaded:
  783. for (i = 0; i < ARRAYLEN(g_ConsoleVerbs); bStates[i++] = TRUE);
  784. break;
  785. case notLoaded:
  786. case loading:
  787. for (i = 0; i < ARRAYLEN(g_ConsoleVerbs); bStates[i++] = FALSE);
  788. break;
  789. case unableToLoad:
  790. for (i = 0; i < ARRAYLEN(g_ConsoleVerbs); bStates[i++] = FALSE);
  791. bStates[MMC_VERB_REFRESH & 0x000F] = TRUE;
  792. bStates[MMC_VERB_DELETE & 0x000F] = TRUE;
  793. bStates[MMC_VERB_PROPERTIES & 0x000F] = TRUE;
  794. break;
  795. }
  796. }
  797. EnableVerbs(pConsoleVerb, ButtonState, bStates);
  798. }
  799. /*---------------------------------------------------------------------------
  800. Background thread functionality
  801. ---------------------------------------------------------------------------*/
  802. /*---------------------------------------------------------------------------
  803. CIpsmServer::OnCreateQuery
  804. Description
  805. Author: NSun
  806. ---------------------------------------------------------------------------*/
  807. ITFSQueryObject*
  808. CIpsmServer::OnCreateQuery(ITFSNode * pNode)
  809. {
  810. CIpsmServerQueryObj* pQuery =
  811. new CIpsmServerQueryObj(m_spTFSCompData, m_spNodeMgr);
  812. pQuery->m_strServer = GetName();
  813. pQuery->m_spSpdInfo.Set(m_spSpdInfo);
  814. pQuery->m_bStatsOnly = m_bStatsOnly;
  815. return pQuery;
  816. }
  817. /*---------------------------------------------------------------------------
  818. CIpsmServerQueryObj::Execute()
  819. Description
  820. Author: NSun
  821. ---------------------------------------------------------------------------*/
  822. STDMETHODIMP
  823. CIpsmServerQueryObj::Execute()
  824. {
  825. HRESULT hr = S_OK;
  826. DWORD dwActive=m_spSpdInfo->GetActiveInfo();
  827. DWORD dwInit=m_spSpdInfo->GetInitInfo();
  828. int i;
  829. //Query the data from SPD
  830. switch(dwActive) {
  831. case MON_MM_FILTER:
  832. case MON_MM_SP_FILTER:
  833. CORg(m_spSpdInfo->EnumMmFilters());
  834. CORg(m_spSpdInfo->EnumMmAuthMethods());
  835. break;
  836. case MON_MM_POLICY:
  837. CORg(m_spSpdInfo->EnumMmPolicies());
  838. break;
  839. case MON_MM_SA:
  840. CORg(m_spSpdInfo->EnumMmSAs());
  841. break;
  842. case MON_MM_AUTH:
  843. CORg(m_spSpdInfo->EnumMmAuthMethods());
  844. break;
  845. case MON_QM_FILTER:
  846. case MON_QM_SP_FILTER:
  847. CORg(m_spSpdInfo->EnumQmFilters());
  848. break;
  849. case MON_QM_POLICY:
  850. CORg(m_spSpdInfo->EnumQmPolicies());
  851. break;
  852. case MON_QM_SA:
  853. CORg(m_spSpdInfo->EnumQmSAs());
  854. break;
  855. case MON_STATS:
  856. CORg(m_spSpdInfo->LoadStatistics());
  857. break;
  858. default:
  859. // Initial load. Ping server to see if its up
  860. CORg(m_spSpdInfo->LoadStatistics());
  861. break;
  862. }
  863. if (m_bStatsOnly)
  864. {
  865. // we post this message esentially to get back on the main thread
  866. // so that we can update the UI
  867. AddToQueue(NULL, IPSECMON_QDATA_REFRESH_STATS);
  868. return hrFalse;
  869. }
  870. {
  871. SPITFSNode spMmNode;
  872. CMmNodeHandler * pMmNodeHandler = new CMmNodeHandler(m_spTFSCompData);
  873. CreateContainerTFSNode(&spMmNode,
  874. &GUID_MmNodeType,
  875. pMmNodeHandler,
  876. pMmNodeHandler,
  877. m_spNodeMgr);
  878. pMmNodeHandler->InitData(m_spSpdInfo);
  879. pMmNodeHandler->InitializeNode(spMmNode);
  880. AddToQueue(spMmNode);
  881. pMmNodeHandler->Release();
  882. }
  883. {
  884. SPITFSNode spQmNode;
  885. CQmNodeHandler * pQmNodeHandler = new CQmNodeHandler(m_spTFSCompData);
  886. CreateContainerTFSNode(&spQmNode,
  887. &GUID_QmNodeType,
  888. pQmNodeHandler,
  889. pQmNodeHandler,
  890. m_spNodeMgr);
  891. pQmNodeHandler->InitData(m_spSpdInfo);
  892. pQmNodeHandler->InitializeNode(spQmNode);
  893. AddToQueue(spQmNode);
  894. pQmNodeHandler->Release();
  895. }
  896. COM_PROTECT_ERROR_LABEL;
  897. if (FAILED(hr))
  898. {
  899. PostError(WIN32_FROM_HRESULT(hr));
  900. if (m_bStatsOnly)
  901. {
  902. //If we are doing auto-refresh, tell the main thread
  903. //that the query failed
  904. AddToQueue(NULL, IPSECMON_QDATA_FAILED);
  905. }
  906. }
  907. return hrFalse;
  908. }
  909. CHashTable::CHashTable()
  910. {
  911. DWORD i;
  912. m_bDnsResolveActive=FALSE;
  913. m_bThreadRunning=FALSE;
  914. for (i=0; i < TOTAL_TABLE_SIZE; i++) {
  915. InitializeListHead(&HashTable[i]);
  916. }
  917. }
  918. DWORD
  919. CHashTable::AddPendingObject(in_addr IpAddr)
  920. {
  921. HashEntry *newEntry=new HashEntry;
  922. CSingleLock slHashLock(&m_csHashLock);
  923. slHashLock.Lock();
  924. if (newEntry == NULL) {
  925. return ERROR_OUTOFMEMORY;
  926. }
  927. newEntry->IpAddr=IpAddr;
  928. InsertHeadList(&HashTable[PENDING_INDEX],&newEntry->Linkage);
  929. return ERROR_SUCCESS;
  930. }
  931. DWORD
  932. CHashTable::AddObject(HashEntry *pHE)
  933. {
  934. DWORD Key=HashData(pHE->IpAddr);
  935. CSingleLock slHashLock(&m_csHashLock);
  936. slHashLock.Lock();
  937. InsertHeadList(&HashTable[Key],&pHE->Linkage);
  938. return ERROR_SUCCESS;
  939. }
  940. DWORD
  941. CHashTable::GetObject(HashEntry **ppHashEntry,in_addr IpAddr)
  942. {
  943. DWORD Key=HashData(IpAddr);
  944. HashEntry *pHE;
  945. PLIST_ENTRY pEntry;
  946. DWORD dwErr;
  947. pHE=NULL;
  948. CSingleLock slHashLock(&m_csHashLock);
  949. slHashLock.Lock();
  950. if (!m_bDnsResolveActive) {
  951. return ERROR_NOT_READY;
  952. }
  953. // Start resolver thread
  954. if (!m_bThreadRunning) {
  955. AfxBeginThread((AFX_THREADPROC)HashResolverCallback,
  956. NULL);
  957. m_bThreadRunning=TRUE;
  958. }
  959. for ( pEntry = HashTable[Key].Flink;
  960. pEntry != &HashTable[Key];
  961. pEntry = pEntry->Flink) {
  962. pHE = CONTAINING_RECORD(pEntry,
  963. HashEntry,
  964. Linkage);
  965. if (memcmp(&pHE->IpAddr,&IpAddr,sizeof(in_addr)) == 0) {
  966. *ppHashEntry = pHE;
  967. return ERROR_SUCCESS;
  968. }
  969. }
  970. dwErr=AddPendingObject(IpAddr);
  971. return ERROR_INVALID_PARAMETER;
  972. }
  973. DWORD
  974. CHashTable::FlushTable()
  975. {
  976. DWORD i;
  977. PLIST_ENTRY pEntry,pNextEntry;
  978. HashEntry *pHE;
  979. CSingleLock slHashLock(&m_csHashLock);
  980. slHashLock.Lock();
  981. for (i=0; i < TOTAL_TABLE_SIZE; i++) {
  982. pEntry = HashTable[i].Flink;
  983. while ( pEntry != &HashTable[i]) {
  984. pHE = CONTAINING_RECORD(pEntry,
  985. HashEntry,
  986. Linkage);
  987. pNextEntry=pEntry->Flink;
  988. delete pHE;
  989. pEntry=pNextEntry;
  990. }
  991. InitializeListHead(&HashTable[i]);
  992. }
  993. return ERROR_SUCCESS;
  994. }
  995. CHashTable::~CHashTable()
  996. {
  997. DWORD i;
  998. PLIST_ENTRY pEntry,pNextEntry;
  999. HashEntry *pHE;
  1000. m_bDnsResolveActive=FALSE;
  1001. while(m_bThreadRunning) {
  1002. Sleep(10);
  1003. }
  1004. CSingleLock slHashLock(&m_csHashLock);
  1005. slHashLock.Lock();
  1006. for (i=0; i < TOTAL_TABLE_SIZE; i++) {
  1007. pEntry = HashTable[i].Flink;
  1008. while ( pEntry != &HashTable[i]) {
  1009. pHE = CONTAINING_RECORD(pEntry,
  1010. HashEntry,
  1011. Linkage);
  1012. pNextEntry=pEntry->Flink;
  1013. delete pHE;
  1014. pEntry=pNextEntry;
  1015. }
  1016. }
  1017. }
  1018. HRESULT
  1019. CHashTable::SetDnsResolve(BOOL bEnable)
  1020. {
  1021. CSingleLock slHashLock(&m_csHashLock);
  1022. slHashLock.Lock();
  1023. if (m_bDnsResolveActive != bEnable) {
  1024. m_bDnsResolveActive = bEnable;
  1025. FlushTable();
  1026. }
  1027. return hrOK;
  1028. }
  1029. DWORD
  1030. CHashTable::HashData(in_addr IpAddr)
  1031. {
  1032. int i;
  1033. int j=0;
  1034. for (i = 0; i < (sizeof(struct in_addr)); i++)
  1035. j ^= (unsigned char)(*((char *)&IpAddr + i));
  1036. return j % HASH_TABLE_SIZE;
  1037. }
  1038. DWORD
  1039. CHashTable::DnsResolve()
  1040. {
  1041. PLIST_ENTRY pEntry;
  1042. HashEntry *pHE;
  1043. HOSTENT *pHost;
  1044. BOOL bWorkAvail;
  1045. while(m_bDnsResolveActive) {
  1046. pHE=NULL;
  1047. bWorkAvail=FALSE;
  1048. CSingleLock slHashLock(&m_csHashLock);
  1049. slHashLock.Lock();
  1050. if (!IsListEmpty(&HashTable[PENDING_INDEX])) {
  1051. pEntry=RemoveHeadList(&HashTable[PENDING_INDEX]);
  1052. pHE = CONTAINING_RECORD(pEntry,
  1053. HashEntry,
  1054. Linkage);
  1055. bWorkAvail=TRUE;
  1056. }
  1057. slHashLock.Unlock();
  1058. // Make sure name resolution is outside of lock for perf
  1059. if (bWorkAvail) {
  1060. pHost=gethostbyaddr((char*)&pHE->IpAddr,sizeof(in_addr),AF_INET);
  1061. if (pHost) {
  1062. //Resolution succeeded
  1063. pHE->HostName = pHost->h_name;
  1064. g_HashTable.AddObject(pHE);
  1065. } else {
  1066. // Resolution attempted, failed, cache failure for perf
  1067. ULONG ul = RevertDwordBytes(*(DWORD*)&pHE->IpAddr);
  1068. CIpAddress TmpIpAddr = ul;
  1069. pHE->HostName = (CString)TmpIpAddr;
  1070. g_HashTable.AddObject(pHE);
  1071. }
  1072. } else {
  1073. Sleep(300);
  1074. }
  1075. }
  1076. m_bThreadRunning=FALSE;
  1077. return ERROR_SUCCESS;
  1078. }
  1079. UINT HashResolverCallback(LPVOID pParam)
  1080. {
  1081. g_HashTable.DnsResolve();
  1082. return ERROR_SUCCESS;
  1083. }