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.

1324 lines
35 KiB

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