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.

1771 lines
50 KiB

  1. /**********************************************************************/
  2. /** Microsoft Windows/NT **/
  3. /** Copyright(c) Microsoft Corporation, 1997 - 1999 **/
  4. /**********************************************************************/
  5. /*
  6. status.cpp
  7. wins status scope pane node handler.
  8. FILE HISTORY:
  9. */
  10. #include "stdafx.h"
  11. #include "status.h"
  12. #include "server.h"
  13. #include "statnode.h"
  14. #include "dhcp.h"
  15. #include "statndpp.h"
  16. #define WINS_MESSAGE_SIZE 576
  17. #define ANSWER_TIMEOUT 20000
  18. /*---------------------------------------------------------------------------
  19. CWinsStatusHandler::CWinsStatusHandler
  20. Description
  21. ---------------------------------------------------------------------------*/
  22. CWinsStatusHandler::CWinsStatusHandler
  23. (
  24. ITFSComponentData * pCompData,
  25. DWORD dwUpdateInterval
  26. ) : CMTWinsHandler(pCompData),
  27. m_hListenThread(NULL),
  28. m_hMainMonThread(NULL),
  29. m_hPauseListening(NULL),
  30. m_nServersUpdated(0)
  31. {
  32. m_bExpanded = FALSE;
  33. m_nState = loaded;
  34. m_dwUpdateInterval = dwUpdateInterval;
  35. // from class ThreadHandler
  36. m_uMsgBase = 0;
  37. }
  38. /*---------------------------------------------------------------------------
  39. CWinsStatusHandler::CWinsStatusHandler
  40. Destructor
  41. ---------------------------------------------------------------------------*/
  42. CWinsStatusHandler::~CWinsStatusHandler()
  43. {
  44. m_listServers.RemoveAll();
  45. if (m_uMsgBase)
  46. {
  47. ::SendMessage(m_hwndHidden, WM_HIDDENWND_REGISTER, FALSE, m_uMsgBase);
  48. m_uMsgBase = 0;
  49. }
  50. CloseSockets();
  51. }
  52. /*---------------------------------------------------------------------------
  53. CWinsStatusHandler::DestroyHandler
  54. Release and pointers we have here
  55. Author: EricDav
  56. ----------------------------------------------------------------------------*/
  57. HRESULT
  58. CWinsStatusHandler::DestroyHandler
  59. (
  60. ITFSNode * pNode
  61. )
  62. {
  63. m_spNode.Set(NULL);
  64. return hrOK;
  65. }
  66. /*---------------------------------------------------------------------------
  67. CWinsStatusHandler::OnCreateNodeId2
  68. Returns a unique string for this node
  69. Author: EricDav
  70. ---------------------------------------------------------------------------*/
  71. HRESULT CWinsStatusHandler::OnCreateNodeId2(ITFSNode * pNode, CString & strId, DWORD * dwFlags)
  72. {
  73. const GUID * pGuid = pNode->GetNodeType();
  74. CString strGuid;
  75. StringFromGUID2(*pGuid, strGuid.GetBuffer(256), 256);
  76. strGuid.ReleaseBuffer();
  77. strId = strGuid;
  78. return hrOK;
  79. }
  80. /*---------------------------------------------------------------------------
  81. CWinsStatusHandler::InitializeNode
  82. Initializes node specific data
  83. ----------------------------------------------------------------------------*/
  84. HRESULT
  85. CWinsStatusHandler::InitializeNode
  86. (
  87. ITFSNode * pNode
  88. )
  89. {
  90. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  91. HRESULT hr = hrOK;
  92. SPITFSNode spParent;
  93. CString strTemp;
  94. strTemp.LoadString(IDS_SERVER_STATUS_FOLDER);
  95. SetDisplayName(strTemp);
  96. // Make the node immediately visible
  97. pNode->SetData(TFS_DATA_COOKIE, (LPARAM) pNode);
  98. pNode->SetData(TFS_DATA_IMAGEINDEX, ICON_IDX_SERVER);
  99. pNode->SetData(TFS_DATA_OPENIMAGEINDEX, ICON_IDX_SERVER);
  100. pNode->SetData(TFS_DATA_USER, (LPARAM) this);
  101. pNode->SetData(TFS_DATA_TYPE, WINSSNAP_SERVER_STATUS);
  102. pNode->SetData(TFS_DATA_RELATIVE_FLAGS, SDI_FIRST);
  103. pNode->SetData(TFS_DATA_SCOPE_LEAF_NODE, TRUE);
  104. SetColumnStringIDs(&aColumns[WINSSNAP_SERVER_STATUS][0]);
  105. SetColumnWidths(&aColumnWidths[WINSSNAP_SERVER_STATUS][0]);
  106. // the event to signal the Listen thread to abort
  107. m_hAbortListen = ::CreateEvent(NULL, FALSE, FALSE, NULL);
  108. if (m_hAbortListen == NULL)
  109. {
  110. Trace1("WinsStatusHandler::InitializeNode - CreateEvent Failed m_hAbortListen %d\n", ::GetLastError());
  111. return HRESULT_FROM_WIN32(::GetLastError());
  112. }
  113. // the event to signal the main thread to abort
  114. m_hAbortMain = ::CreateEvent(NULL, FALSE, FALSE, NULL);
  115. if (m_hAbortListen == NULL)
  116. {
  117. Trace1("WinsStatusHandler::InitializeNode - CreateEvent Failed m_hAbortMain %d\n", ::GetLastError());
  118. return HRESULT_FROM_WIN32(::GetLastError());
  119. }
  120. // the event to signal the threads to wakeup
  121. m_hWaitIntervalListen = ::CreateEvent(NULL, FALSE, FALSE, NULL);
  122. if (m_hWaitIntervalListen == NULL)
  123. {
  124. Trace1("WinsStatusHandler::InitializeNode - CreateEvent Failed m_hWaitIntervalListen %d\n", ::GetLastError());
  125. return HRESULT_FROM_WIN32(::GetLastError());
  126. }
  127. m_hWaitIntervalMain = ::CreateEvent(NULL, FALSE, FALSE, NULL);
  128. if (m_hWaitIntervalMain == NULL)
  129. {
  130. Trace1("WinsStatusHandler::InitializeNode - CreateEvent Failed m_hWaitIntervalMain %d\n", ::GetLastError());
  131. return HRESULT_FROM_WIN32(::GetLastError());
  132. }
  133. // when sending a probe, the thread waits for this
  134. m_hAnswer = ::CreateEvent(NULL, FALSE, FALSE, NULL);
  135. if (m_hAnswer == NULL)
  136. {
  137. Trace1("WinsStatusHandler::InitializeNode - CreateEvent Failed m_hAnswer %d\n", ::GetLastError());
  138. return HRESULT_FROM_WIN32(::GetLastError());
  139. }
  140. return hr;
  141. }
  142. /*---------------------------------------------------------------------------
  143. Overridden base handler functions
  144. ---------------------------------------------------------------------------*/
  145. /*---------------------------------------------------------------------------
  146. CWinsStatusHandler::GetString
  147. Implementation of ITFSNodeHandler::GetString
  148. Author: KennT
  149. ---------------------------------------------------------------------------*/
  150. STDMETHODIMP_(LPCTSTR)
  151. CWinsStatusHandler::GetString
  152. (
  153. ITFSNode * pNode,
  154. int nCol
  155. )
  156. {
  157. if (nCol == 0 || nCol == -1)
  158. return GetDisplayName();
  159. else
  160. return NULL;
  161. }
  162. /*---------------------------------------------------------------------------
  163. CWinsStatusHandler::OnAddMenuItems
  164. Description
  165. ---------------------------------------------------------------------------*/
  166. STDMETHODIMP
  167. CWinsStatusHandler::OnAddMenuItems
  168. (
  169. ITFSNode * pNode,
  170. LPCONTEXTMENUCALLBACK pContextMenuCallback,
  171. LPDATAOBJECT lpDataObject,
  172. DATA_OBJECT_TYPES type,
  173. DWORD dwType,
  174. long * pInsertionAllowed
  175. )
  176. {
  177. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  178. HRESULT hr = S_OK;
  179. return hr;
  180. }
  181. /*!--------------------------------------------------------------------------
  182. CWinsStatusHandler::HasPropertyPages
  183. Implementation of ITFSNodeHandler::HasPropertyPages
  184. NOTE: the root node handler has to over-ride this function to
  185. handle the snapin manager property page (wizard) case!!!
  186. Author: KennT
  187. ---------------------------------------------------------------------------*/
  188. STDMETHODIMP
  189. CWinsStatusHandler::HasPropertyPages
  190. (
  191. ITFSNode * pNode,
  192. LPDATAOBJECT pDataObject,
  193. DATA_OBJECT_TYPES type,
  194. DWORD dwType
  195. )
  196. {
  197. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  198. HRESULT hr = hrOK;
  199. if (dwType & TFS_COMPDATA_CREATE)
  200. {
  201. // This is the case where we are asked to bring up property
  202. // pages when the user is adding a new snapin. These calls
  203. // are forwarded to the root node to handle.
  204. hr = hrOK;
  205. }
  206. else
  207. {
  208. // we have property pages in the normal case
  209. hr = hrOK;
  210. }
  211. return hr;
  212. }
  213. /*---------------------------------------------------------------------------
  214. CWinsStatusHandler::CreatePropertyPages
  215. Description
  216. ---------------------------------------------------------------------------*/
  217. STDMETHODIMP
  218. CWinsStatusHandler::CreatePropertyPages
  219. (
  220. ITFSNode * pNode,
  221. LPPROPERTYSHEETCALLBACK lpProvider,
  222. LPDATAOBJECT pDataObject,
  223. LONG_PTR handle,
  224. DWORD dwType
  225. )
  226. {
  227. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  228. HRESULT hr = hrOK;
  229. Assert(pNode->GetData(TFS_DATA_COOKIE) != 0);
  230. // Object gets deleted when the page is destroyed
  231. SPIComponentData spComponentData;
  232. m_spNodeMgr->GetComponentData(&spComponentData);
  233. CStatusNodeProperties * pStatProp =
  234. new CStatusNodeProperties(pNode,
  235. spComponentData,
  236. m_spTFSCompData,
  237. NULL);
  238. Assert(lpProvider != NULL);
  239. return pStatProp->CreateModelessSheet(lpProvider, handle);
  240. }
  241. /*---------------------------------------------------------------------------
  242. CWinsStatusHandler::OnPropertyChange
  243. Description
  244. ---------------------------------------------------------------------------*/
  245. HRESULT
  246. CWinsStatusHandler::OnPropertyChange
  247. (
  248. ITFSNode * pNode,
  249. LPDATAOBJECT pDataobject,
  250. DWORD dwType,
  251. LPARAM arg,
  252. LPARAM lParam
  253. )
  254. {
  255. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  256. LONG_PTR changeMask = 0;
  257. CStatusNodeProperties * pProp
  258. = reinterpret_cast<CStatusNodeProperties *>(lParam);
  259. // tell the property page to do whatever now that we are back on the
  260. // main thread
  261. pProp->OnPropertyChange(TRUE, &changeMask);
  262. pProp->AcknowledgeNotify();
  263. if (changeMask)
  264. pNode->ChangeNode(changeMask);
  265. return hrOK;
  266. }
  267. HRESULT
  268. CWinsStatusHandler::OnExpand
  269. (
  270. ITFSNode * pNode,
  271. LPDATAOBJECT pDataObject,
  272. DWORD dwType,
  273. LPARAM arg,
  274. LPARAM param
  275. )
  276. {
  277. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  278. HRESULT hr = hrOK;
  279. if (m_bExpanded)
  280. return hr;
  281. m_spNode.Set(pNode);
  282. // build the list to hold the list of the servers
  283. BuildServerList(pNode);
  284. // Create the result pane data here
  285. CreateNodes(pNode);
  286. // start monitoring
  287. StartMonitoring(pNode);
  288. m_bExpanded = TRUE;
  289. return hr;
  290. }
  291. /*!--------------------------------------------------------------------------
  292. CWinsStatusHandler::OnNotifyHaveData
  293. -
  294. Author: EricDav
  295. ---------------------------------------------------------------------------*/
  296. HRESULT
  297. CWinsStatusHandler::OnNotifyHaveData
  298. (
  299. LPARAM lParam
  300. )
  301. {
  302. // The background wins monitoring stuff sends us a message to update the
  303. // status column information
  304. UpdateStatusColumn(m_spNode);
  305. return hrOK;
  306. }
  307. /*---------------------------------------------------------------------------
  308. CWinsStatusHandler::OnResultRefresh
  309. Base handler override
  310. Author: v-shubk
  311. ---------------------------------------------------------------------------*/
  312. HRESULT
  313. CWinsStatusHandler::OnResultRefresh
  314. (
  315. ITFSComponent * pComponent,
  316. LPDATAOBJECT pDataObject,
  317. MMC_COOKIE cookie,
  318. LPARAM arg,
  319. LPARAM lParam
  320. )
  321. {
  322. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  323. // wait up the monitoring thread
  324. SetEvent(m_hWaitIntervalMain);
  325. return hrOK;
  326. }
  327. /*---------------------------------------------------------------------------
  328. CWinsStatusHandler::CompareItems
  329. Description
  330. Author: EricDav
  331. ---------------------------------------------------------------------------*/
  332. STDMETHODIMP_(int)
  333. CWinsStatusHandler::CompareItems
  334. (
  335. ITFSComponent * pComponent,
  336. MMC_COOKIE cookieA,
  337. MMC_COOKIE cookieB,
  338. int nCol
  339. )
  340. {
  341. SPITFSNode spNode1, spNode2;
  342. m_spNodeMgr->FindNode(cookieA, &spNode1);
  343. m_spNodeMgr->FindNode(cookieB, &spNode2);
  344. int nCompare = 0;
  345. CServerStatus * pWins1 = GETHANDLER(CServerStatus, spNode1);
  346. CServerStatus * pWins2 = GETHANDLER(CServerStatus, spNode2);
  347. switch (nCol)
  348. {
  349. // name
  350. case 0:
  351. {
  352. nCompare = lstrcmp(pWins1->GetServerName(), pWins2->GetServerName());
  353. }
  354. break;
  355. // status
  356. case 1:
  357. {
  358. CString str1;
  359. str1 = pWins1->GetStatus();
  360. nCompare = str1.CompareNoCase(pWins2->GetStatus());
  361. }
  362. break;
  363. }
  364. return nCompare;
  365. }
  366. /*---------------------------------------------------------------------------
  367. CWinsStatusHandler::BuildServerList
  368. Description
  369. Author: v-shubk
  370. ---------------------------------------------------------------------------*/
  371. void
  372. CWinsStatusHandler::BuildServerList(ITFSNode *pNode)
  373. {
  374. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  375. // get the root node
  376. SPITFSNode spRootNode;
  377. m_spNodeMgr->GetRootNode(&spRootNode);
  378. // enumerate thro' all the nodes
  379. HRESULT hr = hrOK;
  380. SPITFSNodeEnum spNodeEnum;
  381. SPITFSNode spCurrentNode;
  382. ULONG nNumReturned = 0;
  383. BOOL bFound = FALSE;
  384. // get the enumerator for this node
  385. spRootNode->GetEnum(&spNodeEnum);
  386. spNodeEnum->Next(1, &spCurrentNode, &nNumReturned);
  387. while (nNumReturned)
  388. {
  389. // iterate to teh next node, if the status handler node is seen
  390. const GUID* pGuid;
  391. pGuid = spCurrentNode->GetNodeType();
  392. if (*pGuid != GUID_WinsServerStatusNodeType)
  393. {
  394. // add to the list
  395. CServerStatus* pServ = NULL;
  396. char szBuffer[MAX_PATH];
  397. CWinsServerHandler * pServer
  398. = GETHANDLER(CWinsServerHandler, spCurrentNode);
  399. CString strTemp = pServer->GetServerAddress();
  400. // this should be ACP
  401. WideToMBCS(strTemp, szBuffer);
  402. pServ = new CServerStatus(m_spTFSCompData);
  403. strcpy(pServ->szServerName, szBuffer);
  404. pServ->dwIPAddress = pServer->GetServerIP();
  405. pServ->dwMsgCount = 0;
  406. strcpy(pServ->szIPAddress, "");
  407. m_listServers.Add(pServ);
  408. }
  409. // get the next Server in the list
  410. spCurrentNode.Release();
  411. spNodeEnum->Next(1, &spCurrentNode, &nNumReturned);
  412. }
  413. }
  414. /*---------------------------------------------------------------------------
  415. CWinsStatusHandler::CreateListeningSockets( )
  416. Abstract:
  417. This function initializes Winsock and opens a socket that listens
  418. to bcasts the DHCP srv sends to UDP port 68.
  419. Arguments:
  420. pListenSockCl - reference to the socket we're going to open
  421. (argument passed by reference - clean but hidden)
  422. this socket will listen on the DHCP client port
  423. so that it can pick up bcasts on the local segmnt
  424. pListenSockSrv - reference to the socket we're going to open
  425. (argument passed by reference - clean but hidden)
  426. this socket will listen on the DHCP server port
  427. so that it can pick up unicasts to the "relay"
  428. listenNameSvcSock - reference to the socket we're going to open
  429. (argument passed by reference - clean but hidden)
  430. this socket will listen on the NBT name svc port
  431. so that it can pick up answers from the WINS srv
  432. We have to do this on the socket layer because on
  433. the NetBIOS layer we wouldn't notice that a name
  434. query has been resolved by bcasting.
  435. Return value:
  436. none
  437. --------------------------------------------------------------------------*/
  438. HRESULT
  439. CWinsStatusHandler::CreateListeningSockets( )
  440. {
  441. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  442. int nResult = 0; // status info returned from function calls
  443. WSADATA wsaData; // WinSock startup details buffer
  444. DWORD optionValue; // helper var for setsockopt()
  445. SOCKADDR_IN sockAddr; // struct holding source socket info
  446. // the event to signal listening thread to pause
  447. m_hPauseListening = ::CreateEvent(NULL, FALSE, FALSE, NULL);
  448. if (m_hPauseListening == NULL)
  449. {
  450. Trace1("WinsStatusHandler::CreateListeningSockets - CreateEvent Failed m_hPauseListening %d\n", ::GetLastError());
  451. return HRESULT_FROM_WIN32(::GetLastError());
  452. }
  453. // create socket to listen to the WINS servers on the client port (same subnet)
  454. listenSockCl = socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP );
  455. if ( listenSockCl == INVALID_SOCKET )
  456. {
  457. Trace1("\nError %d creating socket to listen to WINS traffic.\n",
  458. WSAGetLastError() );
  459. return HRESULT_FROM_WIN32(WSAGetLastError());
  460. }
  461. optionValue = TRUE;
  462. if ( setsockopt(listenSockCl, SOL_SOCKET, SO_REUSEADDR, (const char *)&optionValue, sizeof(optionValue)) )
  463. {
  464. Trace1("\nError %d setting SO_REUSEADDR option.\n",
  465. WSAGetLastError() );
  466. return HRESULT_FROM_WIN32(WSAGetLastError());
  467. }
  468. optionValue = TRUE;
  469. if ( setsockopt(listenSockCl, SOL_SOCKET, SO_BROADCAST, (const char *)&optionValue, sizeof(optionValue)) )
  470. {
  471. Trace1("\nError %d setting SO_REUSEADDR option.\n",
  472. WSAGetLastError() );
  473. return HRESULT_FROM_WIN32(WSAGetLastError());
  474. }
  475. sockAddr.sin_family = PF_INET;
  476. sockAddr.sin_addr.s_addr = 0; // use any local address
  477. sockAddr.sin_port = htons( DHCP_CLIENT_PORT );
  478. RtlZeroMemory( sockAddr.sin_zero, 8 );
  479. if ( bind(listenSockCl, (LPSOCKADDR )&sockAddr, sizeof(sockAddr)) == SOCKET_ERROR )
  480. {
  481. Trace1("\nError %d binding the listening socket.\n",
  482. WSAGetLastError() );
  483. return HRESULT_FROM_WIN32(WSAGetLastError());
  484. }
  485. // create socket to listen to the WINS servers on the server port (remote subnet, fake relay)
  486. listenSockSrv = socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP );
  487. if ( listenSockSrv == INVALID_SOCKET )
  488. {
  489. Trace1("\nError %d creating socket to listen to DHCP traffic.\n",
  490. WSAGetLastError() );
  491. return HRESULT_FROM_WIN32(WSAGetLastError());
  492. }
  493. optionValue = TRUE;
  494. if ( setsockopt(listenSockSrv, SOL_SOCKET, SO_REUSEADDR, (const char *)&optionValue, sizeof(optionValue)) )
  495. {
  496. Trace1("\nError %d setting SO_REUSEADDR option.\n",
  497. WSAGetLastError() );
  498. return HRESULT_FROM_WIN32(WSAGetLastError());
  499. }
  500. optionValue = TRUE;
  501. if ( setsockopt(listenSockSrv, SOL_SOCKET, SO_BROADCAST, (const char *)&optionValue, sizeof(optionValue)) )
  502. {
  503. Trace1("\nError %d setting SO_REUSEADDR option.\n",
  504. WSAGetLastError() );
  505. return HRESULT_FROM_WIN32(WSAGetLastError());
  506. }
  507. sockAddr.sin_family = PF_INET;
  508. sockAddr.sin_addr.s_addr = 0; // use any local address
  509. sockAddr.sin_port = htons( DHCP_SERVR_PORT );
  510. RtlZeroMemory( sockAddr.sin_zero, 8 );
  511. if ( bind(listenSockSrv, (LPSOCKADDR )&sockAddr, sizeof(sockAddr)) == SOCKET_ERROR )
  512. {
  513. Trace1("\nError %d binding the listening socket.\n",
  514. WSAGetLastError() );
  515. return HRESULT_FROM_WIN32(WSAGetLastError());
  516. }
  517. // create socket to listen to name svc responses from the WINS server
  518. listenNameSvcSock = socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP );
  519. if ( listenNameSvcSock == INVALID_SOCKET )
  520. {
  521. Trace1("\nError %d creating socket to listen to WINS traffic.\n", WSAGetLastError() );
  522. return HRESULT_FROM_WIN32(WSAGetLastError());
  523. }
  524. optionValue = TRUE;
  525. if ( setsockopt(listenNameSvcSock, SOL_SOCKET, SO_REUSEADDR, (const char *)&optionValue, sizeof(optionValue)) )
  526. {
  527. Trace1("\nError %d setting SO_REUSEADDR option.\n",
  528. WSAGetLastError() );
  529. return HRESULT_FROM_WIN32(WSAGetLastError());
  530. }
  531. optionValue = FALSE;
  532. if ( setsockopt(listenNameSvcSock, SOL_SOCKET, SO_BROADCAST, (const char *)&optionValue, sizeof(optionValue)) )
  533. {
  534. Trace1("\nError %d setting SO_REUSEADDR option.\n",
  535. WSAGetLastError() );
  536. return HRESULT_FROM_WIN32(WSAGetLastError());
  537. }
  538. sockAddr.sin_family = PF_INET;
  539. sockAddr.sin_addr.s_addr = INADDR_ANY;
  540. sockAddr.sin_port = 0;
  541. RtlZeroMemory( sockAddr.sin_zero, 8 );
  542. if ( bind(listenNameSvcSock, (LPSOCKADDR )&sockAddr, sizeof(sockAddr)) == SOCKET_ERROR )
  543. {
  544. Trace1("\nError %d binding the listening socket.\n",
  545. WSAGetLastError() );
  546. return HRESULT_FROM_WIN32(WSAGetLastError());
  547. }
  548. return hrOK;
  549. }
  550. /*---------------------------------------------------------------------------
  551. CWinsStatusHandler::ListeningThreadFunc( )
  552. Abstract:
  553. A blocking recvfrom() is sitting in an infinite loop. Whenever we
  554. receive anything on our listening socket we do a quick sanity chk
  555. on the packet and then increment a counter.
  556. The processing is kept minimal to spare the CPU cycles.
  557. Arguments:
  558. pListenSock - pointer to the socket set we've opened to listen for
  559. xmits from the server
  560. Return value:
  561. none
  562. ---------------------------------------------------------------------------*/
  563. DWORD WINAPI
  564. CWinsStatusHandler::ListeningThreadFunc( )
  565. {
  566. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  567. SOCKADDR_IN senderSockAddr;
  568. int nSockAddrSize = sizeof( senderSockAddr );
  569. int nBytesRcvd = 0;
  570. int nSocksReady;
  571. char MsgBuf[WINS_MESSAGE_SIZE];
  572. int nSockNdx;
  573. LPBYTE MagicCookie;
  574. SOCKET listenSock;
  575. fd_set localSockSet; // to take care of reinit for select()
  576. char szOutput[MAX_PATH];
  577. while ( TRUE )
  578. {
  579. // check if the thread needs to be aborted
  580. if (WaitForSingleObject(m_hPauseListening, 0) == WAIT_OBJECT_0)
  581. {
  582. Trace0("CWinsStatusHandler::ListenThreadFun - going to sleep\n");
  583. // wait until we are woken up or the next time interval expires
  584. WaitForSingleObject(m_hWaitIntervalListen, INFINITE);
  585. Trace0("CWinsStatusHandler::ListenThreadFun - waking up\n");
  586. }
  587. if (WaitForSingleObject(m_hAbortListen, 0) == WAIT_OBJECT_0)
  588. {
  589. // we are going away.. break out man
  590. Trace0("CWinsStatusHandler::ListenThreadFun - abort detected, bye bye\n");
  591. break;
  592. }
  593. // reinit the select set in every loop
  594. localSockSet = m_listenSockSet;
  595. timeval tm;
  596. tm.tv_sec = 5;
  597. // number of sockets ready
  598. nSocksReady = select( 0, &localSockSet, NULL, NULL, &tm );
  599. if ( nSocksReady == SOCKET_ERROR )
  600. {
  601. Trace1("select() failed with error %d.\n", WSAGetLastError() );
  602. }
  603. for ( nSockNdx = 0; nSockNdx < nSocksReady; nSockNdx++ )
  604. {
  605. listenSock = localSockSet.fd_array[nSockNdx];
  606. nBytesRcvd = recvfrom( listenSock, MsgBuf, sizeof(MsgBuf), 0, (LPSOCKADDR )&senderSockAddr, &nSockAddrSize );
  607. if ( nBytesRcvd == SOCKET_ERROR )
  608. {
  609. Trace1( "recvfrom() failed with error %d.\n", WSAGetLastError() );
  610. }
  611. strcpy(szOutput, (LPSTR)inet_ntoa(senderSockAddr.sin_addr));
  612. CString strOutput(szOutput);
  613. Trace2("ListeningThreadFunc(): processing frame from %s port %d \n", strOutput, ntohs(senderSockAddr.sin_port));
  614. // process incoming WINS
  615. if ( (listenSock == listenNameSvcSock) &&
  616. (senderSockAddr.sin_port == NBT_NAME_SERVICE_PORT)
  617. )
  618. {
  619. strcpy(szOutput, (LPSTR)inet_ntoa(senderSockAddr.sin_addr));
  620. CString str(szOutput);
  621. Trace1("ListeningThreadFunc(): processing WINS frame from %s \n", str);
  622. int nCount = GetListSize();
  623. for ( int i=0; i < nCount ; i++)
  624. {
  625. CServerStatus *pWinsSrvEntry = GetServer(i);
  626. // check if the server has been deleted in the scope pane
  627. if (IsServerDeleted(pWinsSrvEntry))
  628. continue;
  629. // get the iP address for the server
  630. DWORD dwIPAdd = pWinsSrvEntry->dwIPAddress;
  631. CString strIP;
  632. ::MakeIPAddress(dwIPAdd, strIP);
  633. char szBuffer[MAX_PATH] = {0};
  634. // convert to mbcs
  635. // NOTE: this should be ACP because its being handed to a winsock call
  636. WideToMBCS(strIP, szBuffer);
  637. // check if the server has been deleted in the scope pane
  638. if (IsServerDeleted(pWinsSrvEntry))
  639. continue;
  640. if (dwIPAdd == 0)
  641. strcpy(szBuffer, pWinsSrvEntry->szIPAddress);
  642. DWORD dwSrvIPAdd = inet_addr( szBuffer );
  643. if ( senderSockAddr.sin_addr.s_addr == dwSrvIPAdd )
  644. {
  645. // check if the server has been deleted in the scope pane
  646. if (IsServerDeleted(pWinsSrvEntry))
  647. continue;
  648. pWinsSrvEntry->dwMsgCount++;
  649. struct in_addr addrStruct;
  650. addrStruct.s_addr = dwSrvIPAdd;
  651. strcpy(szOutput, inet_ntoa(addrStruct));
  652. CString str(szOutput);
  653. Trace1("ListeningThreadFunc(): WINS msg received from %s \n", str );
  654. // notify the thread we got something
  655. SetEvent(m_hAnswer);
  656. }
  657. }
  658. }
  659. } /* END OF for() processing indicated sockets from select() */
  660. } /* END OF while( TRUE ) */
  661. return TRUE;
  662. }
  663. /*---------------------------------------------------------------------------
  664. int CWinsHandler::Probe()
  665. Assembles and sends a name query to the WINS server.
  666. Arguments:
  667. none
  668. Return value:
  669. TRUE if a response has been received from the server
  670. FALSE otherwise
  671. Author: v-shubk
  672. ---------------------------------------------------------------------------*/
  673. int
  674. CWinsStatusHandler::Probe(
  675. CServerStatus *pServer,
  676. SOCKET listenNameSvcSock
  677. )
  678. {
  679. NM_FRAME_HDR *pNbtHeader = (NM_FRAME_HDR *)pServer->nbtFrameBuf;
  680. NM_QUESTION_SECT *pNbtQuestion = (NM_QUESTION_SECT *)( pServer->nbtFrameBuf + sizeof(NM_FRAME_HDR) );
  681. char *pDest, *pName;
  682. struct sockaddr_in destSockAddr; // struct holding dest socket info
  683. int nBytesSent = 0;
  684. // char m_szNameToQry[MAX_PATH] = "Rhino1";
  685. /* RFC 1002 section 4.2.12
  686. 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
  687. 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  688. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  689. | NAME_TRN_ID |0| 0x0 |0|0|1|0|0 0|B| 0x0 |
  690. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  691. | 0x0001 | 0x0000 |
  692. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  693. | 0x0000 | 0x0000 |
  694. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  695. | |
  696. / QUESTION_NAME /
  697. / /
  698. | |
  699. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  700. | NB (0x0020) | IN (0x0001) |
  701. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  702. */
  703. pNbtHeader->xid = NM_QRY_XID;
  704. pNbtHeader->flags = NBT_NM_OPC_QUERY |
  705. NBT_NM_OPC_REQUEST |
  706. NBT_NM_FLG_RECURS_DESRD;
  707. pNbtHeader->question_cnt = 0x0100;
  708. pNbtHeader->answer_cnt = 0;
  709. pNbtHeader->name_serv_cnt = 0;
  710. pNbtHeader->additional_cnt = 0;
  711. // pDest is filling nbtQuestion->q_name
  712. pNbtQuestion->q_type = NBT_NM_QTYP_NB;
  713. pNbtQuestion->q_class = NBT_NM_QCLASS_IN;
  714. //
  715. // translate the name
  716. //
  717. pDest = (char *)&(pNbtQuestion->q_name);
  718. pName = pServer->szServerName;
  719. // the first byte of the name is the length field = 2*16
  720. *pDest++ = NBT_NAME_SIZE;
  721. // step through name converting ascii to half ascii, for 32 times
  722. for ( int i = 0; i < (NBT_NAME_SIZE / 2) ; i++ ) {
  723. *pDest++ = (*pName >> 4) + 'A';
  724. *pDest++ = (*pName++ & 0x0F) + 'A';
  725. }
  726. *pDest++ = '\0';
  727. *pDest = '\0';
  728. // check if the server has been deleted in the scope pane
  729. if (IsServerDeleted(pServer))
  730. return FALSE;
  731. CString strIP;
  732. DWORD dwIPAdd = pServer->dwIPAddress;
  733. // even then 0 means, invalid server
  734. if (dwIPAdd == 0 && strcmp(pServer->szIPAddress, "") == 0)
  735. return FALSE;
  736. ::MakeIPAddress(dwIPAdd, strIP);
  737. char szBuffer[MAX_PATH] = {0};
  738. // convert to mbcs
  739. // NOTE: this should be ACP because it is being used in a winsock call
  740. WideToMBCS(strIP, szBuffer);
  741. // if the name is not yet resolved
  742. if (dwIPAdd == 0)
  743. {
  744. strcpy(szBuffer, pServer->szIPAddress);
  745. }
  746. DWORD dwSrvIPAdd = inet_addr( szBuffer );
  747. //
  748. // send the name query frame
  749. //
  750. destSockAddr.sin_family = PF_INET;
  751. destSockAddr.sin_port = NBT_NAME_SERVICE_PORT;
  752. destSockAddr.sin_addr.s_addr = dwSrvIPAdd;
  753. for (int k = 0; k < 8 ; k++ ) { destSockAddr.sin_zero[k] = 0; }
  754. struct in_addr addrStruct;
  755. addrStruct.s_addr = dwSrvIPAdd;
  756. Trace1( "CWinsSrv::Probe(): sending probe Name Query to %s \n", strIP);
  757. nBytesSent = sendto( listenNameSvcSock,
  758. (PCHAR )pServer->nbtFrameBuf,
  759. sizeof(NM_FRAME_HDR) + sizeof(NM_QUESTION_SECT),
  760. 0,
  761. (struct sockaddr *)&destSockAddr,
  762. sizeof( struct sockaddr )
  763. );
  764. if ( nBytesSent == SOCKET_ERROR )
  765. {
  766. Trace1("CWinsSrv::Probe(): Error %d in sendto().\n", WSAGetLastError() );
  767. }
  768. //
  769. // the other thread should see the incoming frame and increment dwMsgCount
  770. //
  771. WaitForSingleObject(m_hAnswer, ANSWER_TIMEOUT);
  772. if ( pServer->dwMsgCount == 0 )
  773. return FALSE;
  774. return TRUE;
  775. } /* END OF Probe() */
  776. /*---------------------------------------------------------------------------
  777. CWinsStatusHandler::ExecuteMonitoring()
  778. Starts monitoring thread for the servers
  779. Author: v-shubk
  780. ----------------------------------------------------------------------------*/
  781. DWORD WINAPI
  782. CWinsStatusHandler::ExecuteMonitoring()
  783. {
  784. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  785. HANDLE hListeningThread;
  786. CServerStatus *pWinsSrvEntry = NULL;
  787. // create listening thread
  788. FD_ZERO( &m_listenSockSet );
  789. FD_SET( listenSockCl, &m_listenSockSet );
  790. FD_SET( listenSockSrv, &m_listenSockSet );
  791. FD_SET( listenNameSvcSock, &m_listenSockSet );
  792. m_hListenThread = CreateThread( NULL, // handle can't be inherited
  793. 0, // default stack size
  794. MonThreadProc, // thread function
  795. this, // argument to the thread function
  796. 0, // start thread immediately
  797. NULL
  798. );
  799. if (m_hListenThread == NULL )
  800. {
  801. Trace0("CWinsStatusHandler::ExecuteMonitoring() - Listening thread failed to start\n");
  802. return hrOK;
  803. }
  804. // main checking loop
  805. while ( TRUE )
  806. {
  807. // scanning the list of WINS servers
  808. POSITION pos;
  809. int nCount = GetListSize();
  810. m_nServersUpdated = 0;
  811. for (int i = 0; i < nCount; i++)
  812. {
  813. pWinsSrvEntry = GetServer(i);
  814. if (IsServerDeleted(pWinsSrvEntry))
  815. continue;
  816. UpdateStatus(i, IDS_ROOTNODE_STATUS_WORKING, ICON_IDX_SERVER_BUSY);
  817. NotifyMainThread();
  818. DWORD dwIPAdd = pWinsSrvEntry->dwIPAddress;
  819. // if the server is not connected, try to get the host IP address
  820. if (dwIPAdd == 0)
  821. {
  822. // get the server name and convert to MBCS. Get the IP for this server and try
  823. // to check the status
  824. char* dest_ip=NULL;
  825. char hostname[MAX_PATH] ;
  826. struct sockaddr_in dest;
  827. unsigned addr =0;
  828. if (IsServerDeleted(pWinsSrvEntry))
  829. continue;
  830. strcpy(hostname,pWinsSrvEntry->szServerName);
  831. HOSTENT *hp = gethostbyname(hostname);
  832. if ((!hp) && (addr == INADDR_NONE) )
  833. {
  834. CString str(hostname);
  835. Trace1("Unable to resolve %s \n",str);
  836. SetIPAddress(i, NULL);
  837. }
  838. else if (!hp)
  839. {
  840. addr = inet_addr(hostname);
  841. SetIPAddress(i, hostname);
  842. }
  843. else
  844. {
  845. if (hp != NULL)
  846. memcpy(&(dest.sin_addr),hp->h_addr, hp->h_length);
  847. else
  848. dest.sin_addr.s_addr = addr;
  849. if (hp)
  850. dest.sin_family = hp->h_addrtype;
  851. else
  852. dest.sin_family = AF_INET;
  853. dest_ip = inet_ntoa(dest.sin_addr);
  854. SetIPAddress(i, dest_ip);
  855. }
  856. }
  857. CString strIP;
  858. if (IsServerDeleted(pWinsSrvEntry))
  859. continue;
  860. ::MakeIPAddress(pWinsSrvEntry->dwIPAddress, strIP);
  861. // TRY to probe max 3 times
  862. if (pWinsSrvEntry->dwMsgCount == 0)
  863. {
  864. UINT uStatus = 0;
  865. UINT uImage;
  866. if (IsServerDeleted(pWinsSrvEntry))
  867. continue;
  868. BOOL fResponding = FALSE;
  869. if (pWinsSrvEntry->dwIPAddress != 0)
  870. {
  871. for (int j = 0; j < 3; j++)
  872. {
  873. fResponding = Probe(pWinsSrvEntry, listenNameSvcSock);
  874. if (fResponding)
  875. break;
  876. if (FCheckForAbort())
  877. {
  878. // we are going away.. break out man
  879. Trace0("CWinsStatusHandler::ExecuteMonitoring() - abort detected, bye bye \n");
  880. break;
  881. }
  882. }
  883. }
  884. // check to see if we need to clear out
  885. if (FCheckForAbort())
  886. {
  887. // we are going away.. break out man
  888. Trace0("CWinsStatusHandler::ExecuteMonitoring() - abort detected, bye bye \n");
  889. break;
  890. }
  891. if (!fResponding)
  892. {
  893. Trace1("Status is DOWN for the server %s \n", strIP);
  894. uStatus = IDS_ROOTNODE_STATUS_DOWN;
  895. uImage = ICON_IDX_SERVER_LOST_CONNECTION;
  896. }
  897. else
  898. {
  899. Trace1("Status is UP for the server %s \n", strIP);
  900. uStatus = IDS_ROOTNODE_STATUS_UP;
  901. uImage = ICON_IDX_SERVER_CONNECTED;
  902. }
  903. if (IsServerDeleted(pWinsSrvEntry))
  904. continue;
  905. UpdateStatus(i, uStatus, uImage);
  906. m_nServersUpdated++;
  907. // update the last checked time
  908. pWinsSrvEntry->m_timeLast = CTime::GetCurrentTime();
  909. NotifyMainThread();
  910. }
  911. else
  912. {
  913. Trace2( "%d WINS msg from server %s - zeroing counter\n",
  914. pWinsSrvEntry->dwMsgCount, strIP);
  915. if (IsServerDeleted(pWinsSrvEntry))
  916. continue;
  917. pWinsSrvEntry->dwMsgCount = 0;
  918. }
  919. pWinsSrvEntry->dwMsgCount = 0;
  920. }
  921. // tell the listening thread to go to sleep
  922. SetEvent(m_hPauseListening);
  923. m_nServersUpdated = 0;
  924. // wait for the next interval or if we are triggered
  925. Trace1("CWinsStatusHandler::ExecuteMonitoring() - going to sleep for %d \n", m_dwUpdateInterval);
  926. WaitForSingleObject(m_hWaitIntervalMain, m_dwUpdateInterval);
  927. Trace0("CWinsStatusHandler::ExecuteMonitoring() - waking up\n");
  928. // wake up the listening thread
  929. SetEvent(m_hWaitIntervalListen);
  930. if (FCheckForAbort())
  931. {
  932. // we are going away.. break out man
  933. Trace0("CWinsStatusHandler::ExecuteMonitoring() - abort detected, bye bye \n");
  934. break;
  935. }
  936. }
  937. return TRUE;
  938. }
  939. /*---------------------------------------------------------------------------
  940. CWinsStatusHandler::CloseSockets
  941. Closes all the socket connections that were opened
  942. Author: v-shubk
  943. ---------------------------------------------------------------------------*/
  944. BOOL
  945. CWinsStatusHandler::FCheckForAbort()
  946. {
  947. BOOL fAbort = FALSE;
  948. if (WaitForSingleObject(m_hAbortMain, 0) == WAIT_OBJECT_0)
  949. {
  950. // we are going away.. break out man
  951. fAbort = TRUE;
  952. }
  953. return fAbort;
  954. }
  955. /*---------------------------------------------------------------------------
  956. CWinsStatusHandler::CloseSockets
  957. Closes all the socket connections that were opened
  958. Author: v-shubk
  959. ---------------------------------------------------------------------------*/
  960. void
  961. CWinsStatusHandler::CloseSockets()
  962. {
  963. // final clean up
  964. if (closesocket(listenSockCl) == SOCKET_ERROR)
  965. {
  966. Trace1("closesocket(listenSockCl) failed with error %d.\n", WSAGetLastError());
  967. }
  968. if (closesocket(listenSockSrv) == SOCKET_ERROR)
  969. {
  970. Trace1("closesocket(listenSockSrv) failed with error %d.\n", WSAGetLastError());
  971. }
  972. if (closesocket(listenNameSvcSock) == SOCKET_ERROR)
  973. {
  974. Trace1("closesocket(listenNameSvcSock) failed with error %d \n", WSAGetLastError());
  975. }
  976. // we're going away...
  977. Trace0("CWinsStatusHandler::CloseSockets() - Setting abort event.\n");
  978. SetEvent(m_hAbortListen);
  979. SetEvent(m_hAbortMain);
  980. // wake everybody up
  981. Trace0("CWinsStatusHandler::CloseSockets() - waking up threads.\n");
  982. SetEvent(m_hWaitIntervalListen);
  983. SetEvent(m_hWaitIntervalMain);
  984. SetEvent(m_hAnswer);
  985. // terminate the threads
  986. if (m_hListenThread)
  987. {
  988. if (WaitForSingleObject(m_hListenThread, 5000) != WAIT_OBJECT_0)
  989. {
  990. Trace0("CWinsStatusHandler::CloseSockets() - ListenThread failed to cleanup!\n");
  991. }
  992. ::CloseHandle(m_hListenThread);
  993. m_hListenThread = NULL;
  994. }
  995. if (m_hMainMonThread)
  996. {
  997. if (WaitForSingleObject(m_hMainMonThread, 5000) != WAIT_OBJECT_0)
  998. {
  999. Trace0("CWinsStatusHandler::CloseSockets() - MainMonThread failed to cleanup!\n");
  1000. }
  1001. ::CloseHandle(m_hMainMonThread);
  1002. m_hMainMonThread = NULL;
  1003. }
  1004. // clean up our events
  1005. if (m_hPauseListening)
  1006. {
  1007. ::CloseHandle(m_hPauseListening);
  1008. m_hPauseListening = NULL;
  1009. }
  1010. if (m_hAbortListen)
  1011. {
  1012. ::CloseHandle(m_hAbortListen);
  1013. m_hAbortListen = NULL;
  1014. }
  1015. if (m_hAbortMain)
  1016. {
  1017. ::CloseHandle(m_hAbortMain);
  1018. m_hAbortMain = NULL;
  1019. }
  1020. if (m_hWaitIntervalListen)
  1021. {
  1022. ::CloseHandle(m_hWaitIntervalListen);
  1023. m_hWaitIntervalListen = NULL;
  1024. }
  1025. if (m_hWaitIntervalMain)
  1026. {
  1027. ::CloseHandle(m_hWaitIntervalMain);
  1028. m_hWaitIntervalMain = NULL;
  1029. }
  1030. if (m_hAnswer)
  1031. {
  1032. ::CloseHandle(m_hAnswer);
  1033. m_hAnswer = NULL;
  1034. }
  1035. }
  1036. /*---------------------------------------------------------------------------
  1037. CWinsStatusHandler::CreateNodes(ITFSNode *pNode)
  1038. Displays the result pane nodes for the servers
  1039. Author: v-shubk
  1040. ---------------------------------------------------------------------------*/
  1041. HRESULT
  1042. CWinsStatusHandler::CreateNodes(ITFSNode *pNode)
  1043. {
  1044. HRESULT hr = hrOK;
  1045. POSITION pos = NULL;
  1046. int nCount = (int)m_listServers.GetSize();
  1047. for(int i = 0; i < nCount; i++)
  1048. {
  1049. SPITFSNode spStatLeaf;
  1050. CServerStatus *pWinsSrvEntry = m_listServers.GetAt(i);
  1051. CreateLeafTFSNode(&spStatLeaf,
  1052. &GUID_WinsServerStatusLeafNodeType,
  1053. pWinsSrvEntry,
  1054. pWinsSrvEntry,
  1055. m_spNodeMgr);
  1056. // Tell the handler to initialize any specific data
  1057. pWinsSrvEntry->InitializeNode((ITFSNode *) spStatLeaf);
  1058. // Add the node as a child to the Active Leases container
  1059. pNode->AddChild(spStatLeaf);
  1060. pWinsSrvEntry->Release();
  1061. }
  1062. return hr;
  1063. }
  1064. /*---------------------------------------------------------------------------
  1065. CWinsStatusHandler::UpdateStatusColumn(ITFSNode *pNode)
  1066. Updates the status column of the servers in the result pane
  1067. Author: v-shubk
  1068. ---------------------------------------------------------------------------*/
  1069. void
  1070. CWinsStatusHandler::UpdateStatusColumn(ITFSNode *pNode)
  1071. {
  1072. HRESULT hr = hrOK;
  1073. // enumerate thro' all the nodes
  1074. SPITFSNodeEnum spNodeEnum;
  1075. SPITFSNode spCurrentNode;
  1076. ULONG nNumReturned = 0;
  1077. BOOL bFound = FALSE;
  1078. // get the enumerator for this node
  1079. pNode->GetEnum(&spNodeEnum);
  1080. spNodeEnum->Next(1, &spCurrentNode, &nNumReturned);
  1081. while (nNumReturned)
  1082. {
  1083. CServerStatus * pStat = GETHANDLER(CServerStatus, spCurrentNode);
  1084. spCurrentNode->SetData(TFS_DATA_IMAGEINDEX, pStat->m_uImage);
  1085. spCurrentNode->SetData(TFS_DATA_OPENIMAGEINDEX, pStat->m_uImage);
  1086. // fillup the status column
  1087. spCurrentNode->ChangeNode(RESULT_PANE_CHANGE_ITEM);
  1088. // get the next Server in the list
  1089. spCurrentNode.Release();
  1090. spNodeEnum->Next(1, &spCurrentNode, &nNumReturned);
  1091. }
  1092. }
  1093. /*---------------------------------------------------------------------------
  1094. CWinsStatusHandler::AddNode(ITFSNode *pNode, CWinsServerHandler *pServer)
  1095. Adds a node to the result pane, used when a new server is added to
  1096. tree that has to be reflected for the status node
  1097. Author: v-shubk
  1098. ---------------------------------------------------------------------------*/
  1099. HRESULT
  1100. CWinsStatusHandler::AddNode(ITFSNode *pNode, CWinsServerHandler *pServer)
  1101. {
  1102. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  1103. HRESULT hr = hrOK;
  1104. CServerStatus* pServ = NULL;
  1105. char szBuffer[MAX_PATH] = {0};
  1106. SPITFSNode spStatLeaf;
  1107. // if we haven't been expanded, don't add now. Will get done
  1108. // when we are expanded.
  1109. if (!m_bExpanded)
  1110. return hr;
  1111. // add to the list
  1112. // NOTE: this should be ACP because it's being used through winsock
  1113. CString strTemp = pServer->GetServerAddress();
  1114. WideToMBCS(strTemp, szBuffer);
  1115. // check if the server already exists, if so, just change the
  1116. // state stored to SERVER_ADDED and change the variables
  1117. // appropriately
  1118. if ((pServ = GetExistingServer(szBuffer)) == NULL)
  1119. {
  1120. pServ = new CServerStatus(m_spTFSCompData);
  1121. strcpy(pServ->szServerName, szBuffer);
  1122. AddServer(pServ);
  1123. }
  1124. else
  1125. {
  1126. // just add the related data to the CServerStatus and add the node
  1127. // to the UI
  1128. strcpy(pServ->szServerName, szBuffer);
  1129. // set the flag to SERVER_ADDED
  1130. MarkAsDeleted(szBuffer, FALSE);
  1131. }
  1132. pServ->dwIPAddress = pServer->GetServerIP();
  1133. pServ->dwMsgCount = 0;
  1134. strcpy(pServ->szIPAddress, "");
  1135. // create the new node here
  1136. CreateLeafTFSNode(&spStatLeaf,
  1137. &GUID_WinsServerStatusLeafNodeType,
  1138. pServ,
  1139. pServ,
  1140. m_spNodeMgr);
  1141. // Tell the handler to initialize any specific data
  1142. pServ->InitializeNode((ITFSNode *) spStatLeaf);
  1143. // Add the node as a child to the Active Leases container
  1144. pNode->AddChild(spStatLeaf);
  1145. pServ->Release();
  1146. spStatLeaf->ChangeNode(RESULT_PANE_CHANGE_ITEM_DATA);
  1147. pNode->ChangeNode(SCOPE_PANE_CHANGE_ITEM);
  1148. return hr;
  1149. }
  1150. /*---------------------------------------------------------------------------
  1151. CWinsStatusHandler::DeleteNode(ITFSNode *pNode,
  1152. CWinsServerHandler *pServer)
  1153. Removes the particular server from tehresult pane
  1154. Author: v-shubk
  1155. ---------------------------------------------------------------------------*/
  1156. HRESULT
  1157. CWinsStatusHandler::DeleteNode(ITFSNode *pNode, CWinsServerHandler *pServer)
  1158. {
  1159. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  1160. HRESULT hr = hrOK;
  1161. CServerStatus* pServ = NULL;
  1162. char szBuffer[MAX_PATH];
  1163. SPITFSNode spStatLeaf;
  1164. // loop thro' the status nodes and set the flag to deleted so that this
  1165. // server is not seen in the result pane
  1166. SPITFSNodeEnum spNodeEnum;
  1167. SPITFSNode spCurrentNode;
  1168. ULONG nNumReturned = 0;
  1169. // get the enumerator
  1170. pNode->GetEnum(&spNodeEnum);
  1171. spNodeEnum->Next(1, &spCurrentNode, &nNumReturned);
  1172. while (nNumReturned)
  1173. {
  1174. char szBuffer[MAX_PATH];
  1175. // iterate thro' all the nodes and get the one that matches the
  1176. // current server
  1177. CServerStatus * pStat = GETHANDLER(CServerStatus, spCurrentNode);
  1178. // convert to ANSI
  1179. CString strTemp = pServer->GetServerAddress();
  1180. WideToMBCS(strTemp, szBuffer);
  1181. // if found
  1182. if (_stricmp(szBuffer, pStat->szServerName) == 0)
  1183. {
  1184. // mark as deleted and break
  1185. MarkAsDeleted(szBuffer, TRUE);
  1186. // remove this node
  1187. spCurrentNode->SetVisibilityState(TFS_VIS_HIDE);
  1188. spCurrentNode->ChangeNode(RESULT_PANE_DELETE_ITEM);
  1189. // do the cleanup and break
  1190. //spCurrentNode.Release();
  1191. //break;
  1192. }
  1193. // get the next server in the list
  1194. spCurrentNode.Release();
  1195. spNodeEnum->Next(1, &spCurrentNode, &nNumReturned);
  1196. }
  1197. return hr;
  1198. }
  1199. /*---------------------------------------------------------------------------
  1200. CWinsStatusHandler::StartMonitoring
  1201. Spawns off the monitoring thread
  1202. Author: v-shubk
  1203. ---------------------------------------------------------------------------*/
  1204. void
  1205. CWinsStatusHandler::StartMonitoring(ITFSNode *pNode)
  1206. {
  1207. HRESULT hr = hrOK;
  1208. // create the sockets, they need to be closed at the end
  1209. hr = CreateListeningSockets();
  1210. if (hr != hrOK)
  1211. {
  1212. Trace0("CWinsStatusHandler::StartMonitoring, Initializing the sockets failed\n");
  1213. // no point continuing
  1214. return;
  1215. }
  1216. m_hMainMonThread = CreateThread(NULL,
  1217. 0,
  1218. MainMonThread,
  1219. this,
  1220. 0,
  1221. NULL
  1222. );
  1223. if (m_hMainMonThread == NULL)
  1224. {
  1225. Trace0("CWinsStatusHandler:: Main Monitoring thread failed to start\n");
  1226. return;
  1227. }
  1228. }
  1229. /*---------------------------------------------------------------------------
  1230. CWinsStatusHandler::GetServer(int i)
  1231. Returns the Server given the index
  1232. Author: v-shubk
  1233. ---------------------------------------------------------------------------*/
  1234. CServerStatus*
  1235. CWinsStatusHandler::GetServer(int i)
  1236. {
  1237. CSingleLock sl(&m_cs);
  1238. sl.Lock();
  1239. return m_listServers.GetAt(i);
  1240. }
  1241. /*---------------------------------------------------------------------------
  1242. CWinsStatusHandler::AddServer(CServerStatus* pServer)
  1243. Adds a server to the array maintained
  1244. Author: v-shubk
  1245. ---------------------------------------------------------------------------*/
  1246. void
  1247. CWinsStatusHandler::AddServer(CServerStatus* pServer)
  1248. {
  1249. CSingleLock sl(&m_cs);
  1250. sl.Lock();
  1251. m_listServers.Add(pServer);
  1252. }
  1253. /*---------------------------------------------------------------------------
  1254. CWinsStatusHandler::RemoveServer(int i)
  1255. Removes a server from the array
  1256. Author: v-shubk
  1257. ---------------------------------------------------------------------------*/
  1258. void
  1259. CWinsStatusHandler::RemoveServer(int i)
  1260. {
  1261. CSingleLock sl(&m_cs);
  1262. sl.Lock();
  1263. m_listServers.RemoveAt(i);
  1264. }
  1265. /*---------------------------------------------------------------------------
  1266. CWinsStatusHandler::UpdateStatus(UINT nID, int i)
  1267. Upadtes the status string for the server
  1268. Author: v-shubk
  1269. ---------------------------------------------------------------------------*/
  1270. void
  1271. CWinsStatusHandler::UpdateStatus(int nIndex, UINT uStatusId, UINT uImage)
  1272. {
  1273. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  1274. CSingleLock sl(&m_cs);
  1275. sl.Lock();
  1276. CServerStatus *pStat = m_listServers.GetAt(nIndex);
  1277. pStat->m_strStatus.LoadString(uStatusId);
  1278. pStat->m_uImage = uImage;
  1279. }
  1280. /*---------------------------------------------------------------------------
  1281. CWinsStatusHandler::GetListSize()
  1282. Retruns the number of elements in the array
  1283. Author: v-shubk
  1284. ---------------------------------------------------------------------------*/
  1285. int
  1286. CWinsStatusHandler::GetListSize()
  1287. {
  1288. CSingleLock sl(&m_cs);
  1289. sl.Lock();
  1290. return (int)m_listServers.GetSize();
  1291. }
  1292. /*---------------------------------------------------------------------------
  1293. CWinsStatusHandler::SetIPAddress(int i, LPSTR szIP)
  1294. Sets the iP Address of the server, this is the case when the server
  1295. is added with Do not connect option, but we still need to update the
  1296. status
  1297. Author: v-shubk
  1298. ---------------------------------------------------------------------------*/
  1299. void
  1300. CWinsStatusHandler::SetIPAddress(int i, LPSTR szIP)
  1301. {
  1302. CSingleLock sl(&m_cs);
  1303. sl.Lock();
  1304. CServerStatus *pStat = m_listServers.GetAt(i);
  1305. strcpy(pStat->szIPAddress, szIP);
  1306. }
  1307. /*---------------------------------------------------------------------------
  1308. CWinsStatusHandler::MarkAsDeleted(LPSTR szBuffer, BOOL bDelete)
  1309. Marks the flag to DELETED if bDelete is TRUE, else to ADDED
  1310. All the servers with the flag DELETED set are not processed
  1311. and are not shown in the UI.
  1312. Author: v-shubk
  1313. ---------------------------------------------------------------------------*/
  1314. void
  1315. CWinsStatusHandler::MarkAsDeleted(LPSTR szBuffer, BOOL bDelete)
  1316. {
  1317. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  1318. CSingleLock sl(&m_cs);
  1319. sl.Lock();
  1320. int nCount = 0;
  1321. CServerStatus *pStat = NULL;
  1322. // get the list of the servers maintained
  1323. nCount = (int)m_listServers.GetSize();
  1324. for(int i = 0; i < nCount; i++)
  1325. {
  1326. pStat = m_listServers.GetAt(i);
  1327. if (_stricmp(szBuffer, pStat->szServerName) == 0)
  1328. {
  1329. // set the deleted flag
  1330. if (bDelete)
  1331. pStat->dwState = SERVER_DELETED;
  1332. else
  1333. pStat->dwState = SERVER_ADDED;
  1334. break;
  1335. }
  1336. }
  1337. return;
  1338. }
  1339. /*---------------------------------------------------------------------------
  1340. CWinsStatusHandler::GetExistingServer(LPSTR szBuffer)
  1341. Gets the pointer to the existing server in the array
  1342. This function is useful when the server is deletd and again added back
  1343. to the scope tree.
  1344. Author: v-shubk
  1345. ----------------------------------------------------------------------------*/
  1346. CServerStatus *
  1347. CWinsStatusHandler::GetExistingServer(LPSTR szBuffer)
  1348. {
  1349. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  1350. CSingleLock sl(&m_cs);
  1351. sl.Lock();
  1352. int nCount = 0;
  1353. CServerStatus *pStat = NULL;
  1354. for(int i = 0; i < nCount; i++)
  1355. {
  1356. pStat = m_listServers.GetAt(i);
  1357. if (_strcmpi(pStat->szServerName, szBuffer) == 0)
  1358. return pStat;
  1359. }
  1360. return NULL;
  1361. }
  1362. /*---------------------------------------------------------------------------
  1363. CWinsStatusHandler::IsServerDeleted(CServerStatus *pStat)
  1364. Checks if a server has been deleted, such servers
  1365. sre not considered for monitoring
  1366. Author: v-shubk
  1367. ---------------------------------------------------------------------------*/
  1368. BOOL
  1369. CWinsStatusHandler::IsServerDeleted(CServerStatus *pStat)
  1370. {
  1371. return (pStat->dwState == SERVER_DELETED) ? TRUE : FALSE;
  1372. }
  1373. /*---------------------------------------------------------------------------
  1374. CWinsStatusHandler::NotifyMainThread()
  1375. Description
  1376. Author: EricDav
  1377. ---------------------------------------------------------------------------*/
  1378. void
  1379. CWinsStatusHandler::NotifyMainThread()
  1380. {
  1381. if (!m_uMsgBase)
  1382. {
  1383. m_uMsgBase = (INT) ::SendMessage(m_spTFSCompData->GetHiddenWnd(), WM_HIDDENWND_REGISTER, TRUE, 0);
  1384. }
  1385. ::PostMessage(m_spTFSCompData->GetHiddenWnd(),
  1386. m_uMsgBase + WM_HIDDENWND_INDEX_HAVEDATA,
  1387. (WPARAM)(ITFSThreadHandler *)this,
  1388. NULL);
  1389. }
  1390. // listening thread for the main monitoring thread
  1391. DWORD WINAPI
  1392. MonThreadProc(LPVOID pParam)
  1393. {
  1394. DWORD dwReturn;
  1395. HRESULT hr = hrOK;
  1396. COM_PROTECT_TRY
  1397. {
  1398. CWinsStatusHandler * pWinsStatus = (CWinsStatusHandler *) pParam;
  1399. Trace0("MonThreadProc - Thread started.\n");
  1400. dwReturn = pWinsStatus->ListeningThreadFunc();
  1401. Trace0("MonThreadProc - Thread ending.\n");
  1402. }
  1403. COM_PROTECT_CATCH
  1404. return dwReturn;
  1405. }
  1406. // main monitoring thread
  1407. DWORD WINAPI MainMonThread(LPVOID pParam)
  1408. {
  1409. DWORD dwReturn;
  1410. HRESULT hr = hrOK;
  1411. COM_PROTECT_TRY
  1412. {
  1413. CWinsStatusHandler * pWinsStatus = (CWinsStatusHandler *) pParam;
  1414. Trace0("MainMonThread - Thread started.\n");
  1415. dwReturn = pWinsStatus->ExecuteMonitoring();
  1416. Trace0("MainMonThread - Thread ending.\n");
  1417. }
  1418. COM_PROTECT_CATCH
  1419. return dwReturn;
  1420. }