windows-nt/Source/XPSP1/NT/net/mmc/wins/status.cpp
2020-09-26 16:20:57 +08:00

1772 lines
50 KiB
C++

/**********************************************************************/
/** Microsoft Windows/NT **/
/** Copyright(c) Microsoft Corporation, 1997 - 1999 **/
/**********************************************************************/
/*
status.cpp
wins status scope pane node handler.
FILE HISTORY:
*/
#include "stdafx.h"
#include "status.h"
#include "server.h"
#include "statnode.h"
#include "dhcp.h"
#include "statndpp.h"
#define WINS_MESSAGE_SIZE 576
#define ANSWER_TIMEOUT 20000
/*---------------------------------------------------------------------------
CWinsStatusHandler::CWinsStatusHandler
Description
---------------------------------------------------------------------------*/
CWinsStatusHandler::CWinsStatusHandler
(
ITFSComponentData * pCompData,
DWORD dwUpdateInterval
) : CMTWinsHandler(pCompData),
m_hListenThread(NULL),
m_hMainMonThread(NULL),
m_hPauseListening(NULL),
m_nServersUpdated(0)
{
m_bExpanded = FALSE;
m_nState = loaded;
m_dwUpdateInterval = dwUpdateInterval;
// from class ThreadHandler
m_uMsgBase = 0;
}
/*---------------------------------------------------------------------------
CWinsStatusHandler::CWinsStatusHandler
Destructor
---------------------------------------------------------------------------*/
CWinsStatusHandler::~CWinsStatusHandler()
{
m_listServers.RemoveAll();
if (m_uMsgBase)
{
::SendMessage(m_hwndHidden, WM_HIDDENWND_REGISTER, FALSE, m_uMsgBase);
m_uMsgBase = 0;
}
CloseSockets();
}
/*---------------------------------------------------------------------------
CWinsStatusHandler::DestroyHandler
Release and pointers we have here
Author: EricDav
----------------------------------------------------------------------------*/
HRESULT
CWinsStatusHandler::DestroyHandler
(
ITFSNode * pNode
)
{
m_spNode.Set(NULL);
return hrOK;
}
/*---------------------------------------------------------------------------
CWinsStatusHandler::OnCreateNodeId2
Returns a unique string for this node
Author: EricDav
---------------------------------------------------------------------------*/
HRESULT CWinsStatusHandler::OnCreateNodeId2(ITFSNode * pNode, CString & strId, DWORD * dwFlags)
{
const GUID * pGuid = pNode->GetNodeType();
CString strGuid;
StringFromGUID2(*pGuid, strGuid.GetBuffer(256), 256);
strGuid.ReleaseBuffer();
strId = strGuid;
return hrOK;
}
/*---------------------------------------------------------------------------
CWinsStatusHandler::InitializeNode
Initializes node specific data
----------------------------------------------------------------------------*/
HRESULT
CWinsStatusHandler::InitializeNode
(
ITFSNode * pNode
)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
HRESULT hr = hrOK;
SPITFSNode spParent;
CString strTemp;
strTemp.LoadString(IDS_SERVER_STATUS_FOLDER);
SetDisplayName(strTemp);
// Make the node immediately visible
pNode->SetData(TFS_DATA_COOKIE, (LPARAM) pNode);
pNode->SetData(TFS_DATA_IMAGEINDEX, ICON_IDX_SERVER);
pNode->SetData(TFS_DATA_OPENIMAGEINDEX, ICON_IDX_SERVER);
pNode->SetData(TFS_DATA_USER, (LPARAM) this);
pNode->SetData(TFS_DATA_TYPE, WINSSNAP_SERVER_STATUS);
pNode->SetData(TFS_DATA_RELATIVE_FLAGS, SDI_FIRST);
pNode->SetData(TFS_DATA_SCOPE_LEAF_NODE, TRUE);
SetColumnStringIDs(&aColumns[WINSSNAP_SERVER_STATUS][0]);
SetColumnWidths(&aColumnWidths[WINSSNAP_SERVER_STATUS][0]);
// the event to signal the Listen thread to abort
m_hAbortListen = ::CreateEvent(NULL, FALSE, FALSE, NULL);
if (m_hAbortListen == NULL)
{
Trace1("WinsStatusHandler::InitializeNode - CreateEvent Failed m_hAbortListen %d\n", ::GetLastError());
return HRESULT_FROM_WIN32(::GetLastError());
}
// the event to signal the main thread to abort
m_hAbortMain = ::CreateEvent(NULL, FALSE, FALSE, NULL);
if (m_hAbortListen == NULL)
{
Trace1("WinsStatusHandler::InitializeNode - CreateEvent Failed m_hAbortMain %d\n", ::GetLastError());
return HRESULT_FROM_WIN32(::GetLastError());
}
// the event to signal the threads to wakeup
m_hWaitIntervalListen = ::CreateEvent(NULL, FALSE, FALSE, NULL);
if (m_hWaitIntervalListen == NULL)
{
Trace1("WinsStatusHandler::InitializeNode - CreateEvent Failed m_hWaitIntervalListen %d\n", ::GetLastError());
return HRESULT_FROM_WIN32(::GetLastError());
}
m_hWaitIntervalMain = ::CreateEvent(NULL, FALSE, FALSE, NULL);
if (m_hWaitIntervalMain == NULL)
{
Trace1("WinsStatusHandler::InitializeNode - CreateEvent Failed m_hWaitIntervalMain %d\n", ::GetLastError());
return HRESULT_FROM_WIN32(::GetLastError());
}
// when sending a probe, the thread waits for this
m_hAnswer = ::CreateEvent(NULL, FALSE, FALSE, NULL);
if (m_hAnswer == NULL)
{
Trace1("WinsStatusHandler::InitializeNode - CreateEvent Failed m_hAnswer %d\n", ::GetLastError());
return HRESULT_FROM_WIN32(::GetLastError());
}
return hr;
}
/*---------------------------------------------------------------------------
Overridden base handler functions
---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------
CWinsStatusHandler::GetString
Implementation of ITFSNodeHandler::GetString
Author: KennT
---------------------------------------------------------------------------*/
STDMETHODIMP_(LPCTSTR)
CWinsStatusHandler::GetString
(
ITFSNode * pNode,
int nCol
)
{
if (nCol == 0 || nCol == -1)
return GetDisplayName();
else
return NULL;
}
/*---------------------------------------------------------------------------
CWinsStatusHandler::OnAddMenuItems
Description
---------------------------------------------------------------------------*/
STDMETHODIMP
CWinsStatusHandler::OnAddMenuItems
(
ITFSNode * pNode,
LPCONTEXTMENUCALLBACK pContextMenuCallback,
LPDATAOBJECT lpDataObject,
DATA_OBJECT_TYPES type,
DWORD dwType,
long * pInsertionAllowed
)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
HRESULT hr = S_OK;
return hr;
}
/*!--------------------------------------------------------------------------
CWinsStatusHandler::HasPropertyPages
Implementation of ITFSNodeHandler::HasPropertyPages
NOTE: the root node handler has to over-ride this function to
handle the snapin manager property page (wizard) case!!!
Author: KennT
---------------------------------------------------------------------------*/
STDMETHODIMP
CWinsStatusHandler::HasPropertyPages
(
ITFSNode * pNode,
LPDATAOBJECT pDataObject,
DATA_OBJECT_TYPES type,
DWORD dwType
)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
HRESULT hr = hrOK;
if (dwType & TFS_COMPDATA_CREATE)
{
// This is the case where we are asked to bring up property
// pages when the user is adding a new snapin. These calls
// are forwarded to the root node to handle.
hr = hrOK;
}
else
{
// we have property pages in the normal case
hr = hrOK;
}
return hr;
}
/*---------------------------------------------------------------------------
CWinsStatusHandler::CreatePropertyPages
Description
---------------------------------------------------------------------------*/
STDMETHODIMP
CWinsStatusHandler::CreatePropertyPages
(
ITFSNode * pNode,
LPPROPERTYSHEETCALLBACK lpProvider,
LPDATAOBJECT pDataObject,
LONG_PTR handle,
DWORD dwType
)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
HRESULT hr = hrOK;
Assert(pNode->GetData(TFS_DATA_COOKIE) != 0);
// Object gets deleted when the page is destroyed
SPIComponentData spComponentData;
m_spNodeMgr->GetComponentData(&spComponentData);
CStatusNodeProperties * pStatProp =
new CStatusNodeProperties(pNode,
spComponentData,
m_spTFSCompData,
NULL);
Assert(lpProvider != NULL);
return pStatProp->CreateModelessSheet(lpProvider, handle);
}
/*---------------------------------------------------------------------------
CWinsStatusHandler::OnPropertyChange
Description
---------------------------------------------------------------------------*/
HRESULT
CWinsStatusHandler::OnPropertyChange
(
ITFSNode * pNode,
LPDATAOBJECT pDataobject,
DWORD dwType,
LPARAM arg,
LPARAM lParam
)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
LONG_PTR changeMask = 0;
CStatusNodeProperties * pProp
= reinterpret_cast<CStatusNodeProperties *>(lParam);
// tell the property page to do whatever now that we are back on the
// main thread
pProp->OnPropertyChange(TRUE, &changeMask);
pProp->AcknowledgeNotify();
if (changeMask)
pNode->ChangeNode(changeMask);
return hrOK;
}
HRESULT
CWinsStatusHandler::OnExpand
(
ITFSNode * pNode,
LPDATAOBJECT pDataObject,
DWORD dwType,
LPARAM arg,
LPARAM param
)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
HRESULT hr = hrOK;
if (m_bExpanded)
return hr;
m_spNode.Set(pNode);
// build the list to hold the list of the servers
BuildServerList(pNode);
// Create the result pane data here
CreateNodes(pNode);
// start monitoring
StartMonitoring(pNode);
m_bExpanded = TRUE;
return hr;
}
/*!--------------------------------------------------------------------------
CWinsStatusHandler::OnNotifyHaveData
-
Author: EricDav
---------------------------------------------------------------------------*/
HRESULT
CWinsStatusHandler::OnNotifyHaveData
(
LPARAM lParam
)
{
// The background wins monitoring stuff sends us a message to update the
// status column information
UpdateStatusColumn(m_spNode);
return hrOK;
}
/*---------------------------------------------------------------------------
CWinsStatusHandler::OnResultRefresh
Base handler override
Author: v-shubk
---------------------------------------------------------------------------*/
HRESULT
CWinsStatusHandler::OnResultRefresh
(
ITFSComponent * pComponent,
LPDATAOBJECT pDataObject,
MMC_COOKIE cookie,
LPARAM arg,
LPARAM lParam
)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
// wait up the monitoring thread
SetEvent(m_hWaitIntervalMain);
return hrOK;
}
/*---------------------------------------------------------------------------
CWinsStatusHandler::CompareItems
Description
Author: EricDav
---------------------------------------------------------------------------*/
STDMETHODIMP_(int)
CWinsStatusHandler::CompareItems
(
ITFSComponent * pComponent,
MMC_COOKIE cookieA,
MMC_COOKIE cookieB,
int nCol
)
{
SPITFSNode spNode1, spNode2;
m_spNodeMgr->FindNode(cookieA, &spNode1);
m_spNodeMgr->FindNode(cookieB, &spNode2);
int nCompare = 0;
CServerStatus * pWins1 = GETHANDLER(CServerStatus, spNode1);
CServerStatus * pWins2 = GETHANDLER(CServerStatus, spNode2);
switch (nCol)
{
// name
case 0:
{
nCompare = lstrcmp(pWins1->GetServerName(), pWins2->GetServerName());
}
break;
// status
case 1:
{
CString str1;
str1 = pWins1->GetStatus();
nCompare = str1.CompareNoCase(pWins2->GetStatus());
}
break;
}
return nCompare;
}
/*---------------------------------------------------------------------------
CWinsStatusHandler::BuildServerList
Description
Author: v-shubk
---------------------------------------------------------------------------*/
void
CWinsStatusHandler::BuildServerList(ITFSNode *pNode)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
// get the root node
SPITFSNode spRootNode;
m_spNodeMgr->GetRootNode(&spRootNode);
// enumerate thro' all the nodes
HRESULT hr = hrOK;
SPITFSNodeEnum spNodeEnum;
SPITFSNode spCurrentNode;
ULONG nNumReturned = 0;
BOOL bFound = FALSE;
// get the enumerator for this node
spRootNode->GetEnum(&spNodeEnum);
spNodeEnum->Next(1, &spCurrentNode, &nNumReturned);
while (nNumReturned)
{
// iterate to teh next node, if the status handler node is seen
const GUID* pGuid;
pGuid = spCurrentNode->GetNodeType();
if (*pGuid != GUID_WinsServerStatusNodeType)
{
// add to the list
CServerStatus* pServ = NULL;
char szBuffer[MAX_PATH];
CWinsServerHandler * pServer
= GETHANDLER(CWinsServerHandler, spCurrentNode);
CString strTemp = pServer->GetServerAddress();
// this should be ACP
WideToMBCS(strTemp, szBuffer);
pServ = new CServerStatus(m_spTFSCompData);
strcpy(pServ->szServerName, szBuffer);
pServ->dwIPAddress = pServer->GetServerIP();
pServ->dwMsgCount = 0;
strcpy(pServ->szIPAddress, "");
m_listServers.Add(pServ);
}
// get the next Server in the list
spCurrentNode.Release();
spNodeEnum->Next(1, &spCurrentNode, &nNumReturned);
}
}
/*---------------------------------------------------------------------------
CWinsStatusHandler::CreateListeningSockets( )
Abstract:
This function initializes Winsock and opens a socket that listens
to bcasts the DHCP srv sends to UDP port 68.
Arguments:
pListenSockCl - reference to the socket we're going to open
(argument passed by reference - clean but hidden)
this socket will listen on the DHCP client port
so that it can pick up bcasts on the local segmnt
pListenSockSrv - reference to the socket we're going to open
(argument passed by reference - clean but hidden)
this socket will listen on the DHCP server port
so that it can pick up unicasts to the "relay"
listenNameSvcSock - reference to the socket we're going to open
(argument passed by reference - clean but hidden)
this socket will listen on the NBT name svc port
so that it can pick up answers from the WINS srv
We have to do this on the socket layer because on
the NetBIOS layer we wouldn't notice that a name
query has been resolved by bcasting.
Return value:
none
--------------------------------------------------------------------------*/
HRESULT
CWinsStatusHandler::CreateListeningSockets( )
{
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
int nResult = 0; // status info returned from function calls
WSADATA wsaData; // WinSock startup details buffer
DWORD optionValue; // helper var for setsockopt()
SOCKADDR_IN sockAddr; // struct holding source socket info
// the event to signal listening thread to pause
m_hPauseListening = ::CreateEvent(NULL, FALSE, FALSE, NULL);
if (m_hPauseListening == NULL)
{
Trace1("WinsStatusHandler::CreateListeningSockets - CreateEvent Failed m_hPauseListening %d\n", ::GetLastError());
return HRESULT_FROM_WIN32(::GetLastError());
}
// create socket to listen to the WINS servers on the client port (same subnet)
listenSockCl = socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP );
if ( listenSockCl == INVALID_SOCKET )
{
Trace1("\nError %d creating socket to listen to WINS traffic.\n",
WSAGetLastError() );
return HRESULT_FROM_WIN32(WSAGetLastError());
}
optionValue = TRUE;
if ( setsockopt(listenSockCl, SOL_SOCKET, SO_REUSEADDR, (const char *)&optionValue, sizeof(optionValue)) )
{
Trace1("\nError %d setting SO_REUSEADDR option.\n",
WSAGetLastError() );
return HRESULT_FROM_WIN32(WSAGetLastError());
}
optionValue = TRUE;
if ( setsockopt(listenSockCl, SOL_SOCKET, SO_BROADCAST, (const char *)&optionValue, sizeof(optionValue)) )
{
Trace1("\nError %d setting SO_REUSEADDR option.\n",
WSAGetLastError() );
return HRESULT_FROM_WIN32(WSAGetLastError());
}
sockAddr.sin_family = PF_INET;
sockAddr.sin_addr.s_addr = 0; // use any local address
sockAddr.sin_port = htons( DHCP_CLIENT_PORT );
RtlZeroMemory( sockAddr.sin_zero, 8 );
if ( bind(listenSockCl, (LPSOCKADDR )&sockAddr, sizeof(sockAddr)) == SOCKET_ERROR )
{
Trace1("\nError %d binding the listening socket.\n",
WSAGetLastError() );
return HRESULT_FROM_WIN32(WSAGetLastError());
}
// create socket to listen to the WINS servers on the server port (remote subnet, fake relay)
listenSockSrv = socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP );
if ( listenSockSrv == INVALID_SOCKET )
{
Trace1("\nError %d creating socket to listen to DHCP traffic.\n",
WSAGetLastError() );
return HRESULT_FROM_WIN32(WSAGetLastError());
}
optionValue = TRUE;
if ( setsockopt(listenSockSrv, SOL_SOCKET, SO_REUSEADDR, (const char *)&optionValue, sizeof(optionValue)) )
{
Trace1("\nError %d setting SO_REUSEADDR option.\n",
WSAGetLastError() );
return HRESULT_FROM_WIN32(WSAGetLastError());
}
optionValue = TRUE;
if ( setsockopt(listenSockSrv, SOL_SOCKET, SO_BROADCAST, (const char *)&optionValue, sizeof(optionValue)) )
{
Trace1("\nError %d setting SO_REUSEADDR option.\n",
WSAGetLastError() );
return HRESULT_FROM_WIN32(WSAGetLastError());
}
sockAddr.sin_family = PF_INET;
sockAddr.sin_addr.s_addr = 0; // use any local address
sockAddr.sin_port = htons( DHCP_SERVR_PORT );
RtlZeroMemory( sockAddr.sin_zero, 8 );
if ( bind(listenSockSrv, (LPSOCKADDR )&sockAddr, sizeof(sockAddr)) == SOCKET_ERROR )
{
Trace1("\nError %d binding the listening socket.\n",
WSAGetLastError() );
return HRESULT_FROM_WIN32(WSAGetLastError());
}
// create socket to listen to name svc responses from the WINS server
listenNameSvcSock = socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP );
if ( listenNameSvcSock == INVALID_SOCKET )
{
Trace1("\nError %d creating socket to listen to WINS traffic.\n", WSAGetLastError() );
return HRESULT_FROM_WIN32(WSAGetLastError());
}
optionValue = TRUE;
if ( setsockopt(listenNameSvcSock, SOL_SOCKET, SO_REUSEADDR, (const char *)&optionValue, sizeof(optionValue)) )
{
Trace1("\nError %d setting SO_REUSEADDR option.\n",
WSAGetLastError() );
return HRESULT_FROM_WIN32(WSAGetLastError());
}
optionValue = FALSE;
if ( setsockopt(listenNameSvcSock, SOL_SOCKET, SO_BROADCAST, (const char *)&optionValue, sizeof(optionValue)) )
{
Trace1("\nError %d setting SO_REUSEADDR option.\n",
WSAGetLastError() );
return HRESULT_FROM_WIN32(WSAGetLastError());
}
sockAddr.sin_family = PF_INET;
sockAddr.sin_addr.s_addr = INADDR_ANY;
sockAddr.sin_port = 0;
RtlZeroMemory( sockAddr.sin_zero, 8 );
if ( bind(listenNameSvcSock, (LPSOCKADDR )&sockAddr, sizeof(sockAddr)) == SOCKET_ERROR )
{
Trace1("\nError %d binding the listening socket.\n",
WSAGetLastError() );
return HRESULT_FROM_WIN32(WSAGetLastError());
}
return hrOK;
}
/*---------------------------------------------------------------------------
CWinsStatusHandler::ListeningThreadFunc( )
Abstract:
A blocking recvfrom() is sitting in an infinite loop. Whenever we
receive anything on our listening socket we do a quick sanity chk
on the packet and then increment a counter.
The processing is kept minimal to spare the CPU cycles.
Arguments:
pListenSock - pointer to the socket set we've opened to listen for
xmits from the server
Return value:
none
---------------------------------------------------------------------------*/
DWORD WINAPI
CWinsStatusHandler::ListeningThreadFunc( )
{
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
SOCKADDR_IN senderSockAddr;
int nSockAddrSize = sizeof( senderSockAddr );
int nBytesRcvd = 0;
int nSocksReady;
char MsgBuf[WINS_MESSAGE_SIZE];
int nSockNdx;
LPBYTE MagicCookie;
SOCKET listenSock;
fd_set localSockSet; // to take care of reinit for select()
char szOutput[MAX_PATH];
while ( TRUE )
{
// check if the thread needs to be aborted
if (WaitForSingleObject(m_hPauseListening, 0) == WAIT_OBJECT_0)
{
Trace0("CWinsStatusHandler::ListenThreadFun - going to sleep\n");
// wait until we are woken up or the next time interval expires
WaitForSingleObject(m_hWaitIntervalListen, INFINITE);
Trace0("CWinsStatusHandler::ListenThreadFun - waking up\n");
}
if (WaitForSingleObject(m_hAbortListen, 0) == WAIT_OBJECT_0)
{
// we are going away.. break out man
Trace0("CWinsStatusHandler::ListenThreadFun - abort detected, bye bye\n");
break;
}
// reinit the select set in every loop
localSockSet = m_listenSockSet;
timeval tm;
tm.tv_sec = 5;
// number of sockets ready
nSocksReady = select( 0, &localSockSet, NULL, NULL, &tm );
if ( nSocksReady == SOCKET_ERROR )
{
Trace1("select() failed with error %d.\n", WSAGetLastError() );
}
for ( nSockNdx = 0; nSockNdx < nSocksReady; nSockNdx++ )
{
listenSock = localSockSet.fd_array[nSockNdx];
nBytesRcvd = recvfrom( listenSock, MsgBuf, sizeof(MsgBuf), 0, (LPSOCKADDR )&senderSockAddr, &nSockAddrSize );
if ( nBytesRcvd == SOCKET_ERROR )
{
Trace1( "recvfrom() failed with error %d.\n", WSAGetLastError() );
}
strcpy(szOutput, (LPSTR)inet_ntoa(senderSockAddr.sin_addr));
CString strOutput(szOutput);
Trace2("ListeningThreadFunc(): processing frame from %s port %d \n", strOutput, ntohs(senderSockAddr.sin_port));
// process incoming WINS
if ( (listenSock == listenNameSvcSock) &&
(senderSockAddr.sin_port == NBT_NAME_SERVICE_PORT)
)
{
strcpy(szOutput, (LPSTR)inet_ntoa(senderSockAddr.sin_addr));
CString str(szOutput);
Trace1("ListeningThreadFunc(): processing WINS frame from %s \n", str);
int nCount = GetListSize();
for ( int i=0; i < nCount ; i++)
{
CServerStatus *pWinsSrvEntry = GetServer(i);
// check if the server has been deleted in the scope pane
if (IsServerDeleted(pWinsSrvEntry))
continue;
// get the iP address for the server
DWORD dwIPAdd = pWinsSrvEntry->dwIPAddress;
CString strIP;
::MakeIPAddress(dwIPAdd, strIP);
char szBuffer[MAX_PATH] = {0};
// convert to mbcs
// NOTE: this should be ACP because its being handed to a winsock call
WideToMBCS(strIP, szBuffer);
// check if the server has been deleted in the scope pane
if (IsServerDeleted(pWinsSrvEntry))
continue;
if (dwIPAdd == 0)
strcpy(szBuffer, pWinsSrvEntry->szIPAddress);
DWORD dwSrvIPAdd = inet_addr( szBuffer );
if ( senderSockAddr.sin_addr.s_addr == dwSrvIPAdd )
{
// check if the server has been deleted in the scope pane
if (IsServerDeleted(pWinsSrvEntry))
continue;
pWinsSrvEntry->dwMsgCount++;
struct in_addr addrStruct;
addrStruct.s_addr = dwSrvIPAdd;
strcpy(szOutput, inet_ntoa(addrStruct));
CString str(szOutput);
Trace1("ListeningThreadFunc(): WINS msg received from %s \n", str );
// notify the thread we got something
SetEvent(m_hAnswer);
}
}
}
} /* END OF for() processing indicated sockets from select() */
} /* END OF while( TRUE ) */
return TRUE;
}
/*---------------------------------------------------------------------------
int CWinsHandler::Probe()
Assembles and sends a name query to the WINS server.
Arguments:
none
Return value:
TRUE if a response has been received from the server
FALSE otherwise
Author: v-shubk
---------------------------------------------------------------------------*/
int
CWinsStatusHandler::Probe(
CServerStatus *pServer,
SOCKET listenNameSvcSock
)
{
NM_FRAME_HDR *pNbtHeader = (NM_FRAME_HDR *)pServer->nbtFrameBuf;
NM_QUESTION_SECT *pNbtQuestion = (NM_QUESTION_SECT *)( pServer->nbtFrameBuf + sizeof(NM_FRAME_HDR) );
char *pDest, *pName;
struct sockaddr_in destSockAddr; // struct holding dest socket info
int nBytesSent = 0;
// char m_szNameToQry[MAX_PATH] = "Rhino1";
/* RFC 1002 section 4.2.12
1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| NAME_TRN_ID |0| 0x0 |0|0|1|0|0 0|B| 0x0 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x0001 | 0x0000 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x0000 | 0x0000 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
/ QUESTION_NAME /
/ /
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| NB (0x0020) | IN (0x0001) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
pNbtHeader->xid = NM_QRY_XID;
pNbtHeader->flags = NBT_NM_OPC_QUERY |
NBT_NM_OPC_REQUEST |
NBT_NM_FLG_RECURS_DESRD;
pNbtHeader->question_cnt = 0x0100;
pNbtHeader->answer_cnt = 0;
pNbtHeader->name_serv_cnt = 0;
pNbtHeader->additional_cnt = 0;
// pDest is filling nbtQuestion->q_name
pNbtQuestion->q_type = NBT_NM_QTYP_NB;
pNbtQuestion->q_class = NBT_NM_QCLASS_IN;
//
// translate the name
//
pDest = (char *)&(pNbtQuestion->q_name);
pName = pServer->szServerName;
// the first byte of the name is the length field = 2*16
*pDest++ = NBT_NAME_SIZE;
// step through name converting ascii to half ascii, for 32 times
for ( int i = 0; i < (NBT_NAME_SIZE / 2) ; i++ ) {
*pDest++ = (*pName >> 4) + 'A';
*pDest++ = (*pName++ & 0x0F) + 'A';
}
*pDest++ = '\0';
*pDest = '\0';
// check if the server has been deleted in the scope pane
if (IsServerDeleted(pServer))
return FALSE;
CString strIP;
DWORD dwIPAdd = pServer->dwIPAddress;
// even then 0 means, invalid server
if (dwIPAdd == 0 && strcmp(pServer->szIPAddress, "") == 0)
return FALSE;
::MakeIPAddress(dwIPAdd, strIP);
char szBuffer[MAX_PATH] = {0};
// convert to mbcs
// NOTE: this should be ACP because it is being used in a winsock call
WideToMBCS(strIP, szBuffer);
// if the name is not yet resolved
if (dwIPAdd == 0)
{
strcpy(szBuffer, pServer->szIPAddress);
}
DWORD dwSrvIPAdd = inet_addr( szBuffer );
//
// send the name query frame
//
destSockAddr.sin_family = PF_INET;
destSockAddr.sin_port = NBT_NAME_SERVICE_PORT;
destSockAddr.sin_addr.s_addr = dwSrvIPAdd;
for (int k = 0; k < 8 ; k++ ) { destSockAddr.sin_zero[k] = 0; }
struct in_addr addrStruct;
addrStruct.s_addr = dwSrvIPAdd;
Trace1( "CWinsSrv::Probe(): sending probe Name Query to %s \n", strIP);
nBytesSent = sendto( listenNameSvcSock,
(PCHAR )pServer->nbtFrameBuf,
sizeof(NM_FRAME_HDR) + sizeof(NM_QUESTION_SECT),
0,
(struct sockaddr *)&destSockAddr,
sizeof( struct sockaddr )
);
if ( nBytesSent == SOCKET_ERROR )
{
Trace1("CWinsSrv::Probe(): Error %d in sendto().\n", WSAGetLastError() );
}
//
// the other thread should see the incoming frame and increment dwMsgCount
//
WaitForSingleObject(m_hAnswer, ANSWER_TIMEOUT);
if ( pServer->dwMsgCount == 0 )
return FALSE;
return TRUE;
} /* END OF Probe() */
/*---------------------------------------------------------------------------
CWinsStatusHandler::ExecuteMonitoring()
Starts monitoring thread for the servers
Author: v-shubk
----------------------------------------------------------------------------*/
DWORD WINAPI
CWinsStatusHandler::ExecuteMonitoring()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
HANDLE hListeningThread;
CServerStatus *pWinsSrvEntry = NULL;
// create listening thread
FD_ZERO( &m_listenSockSet );
FD_SET( listenSockCl, &m_listenSockSet );
FD_SET( listenSockSrv, &m_listenSockSet );
FD_SET( listenNameSvcSock, &m_listenSockSet );
m_hListenThread = CreateThread( NULL, // handle can't be inherited
0, // default stack size
MonThreadProc, // thread function
this, // argument to the thread function
0, // start thread immediately
NULL
);
if (m_hListenThread == NULL )
{
Trace0("CWinsStatusHandler::ExecuteMonitoring() - Listening thread failed to start\n");
return hrOK;
}
// main checking loop
while ( TRUE )
{
// scanning the list of WINS servers
POSITION pos;
int nCount = GetListSize();
m_nServersUpdated = 0;
for (int i = 0; i < nCount; i++)
{
pWinsSrvEntry = GetServer(i);
if (IsServerDeleted(pWinsSrvEntry))
continue;
UpdateStatus(i, IDS_ROOTNODE_STATUS_WORKING, ICON_IDX_SERVER_BUSY);
NotifyMainThread();
DWORD dwIPAdd = pWinsSrvEntry->dwIPAddress;
// if the server is not connected, try to get the host IP address
if (dwIPAdd == 0)
{
// get the server name and convert to MBCS. Get the IP for this server and try
// to check the status
char* dest_ip=NULL;
char hostname[MAX_PATH] ;
struct sockaddr_in dest;
unsigned addr =0;
if (IsServerDeleted(pWinsSrvEntry))
continue;
strcpy(hostname,pWinsSrvEntry->szServerName);
HOSTENT *hp = gethostbyname(hostname);
if ((!hp) && (addr == INADDR_NONE) )
{
CString str(hostname);
Trace1("Unable to resolve %s \n",str);
SetIPAddress(i, NULL);
}
else if (!hp)
{
addr = inet_addr(hostname);
SetIPAddress(i, hostname);
}
else
{
if (hp != NULL)
memcpy(&(dest.sin_addr),hp->h_addr, hp->h_length);
else
dest.sin_addr.s_addr = addr;
if (hp)
dest.sin_family = hp->h_addrtype;
else
dest.sin_family = AF_INET;
dest_ip = inet_ntoa(dest.sin_addr);
SetIPAddress(i, dest_ip);
}
}
CString strIP;
if (IsServerDeleted(pWinsSrvEntry))
continue;
::MakeIPAddress(pWinsSrvEntry->dwIPAddress, strIP);
// TRY to probe max 3 times
if (pWinsSrvEntry->dwMsgCount == 0)
{
UINT uStatus = 0;
UINT uImage;
if (IsServerDeleted(pWinsSrvEntry))
continue;
BOOL fResponding = FALSE;
if (pWinsSrvEntry->dwIPAddress != 0)
{
for (int j = 0; j < 3; j++)
{
fResponding = Probe(pWinsSrvEntry, listenNameSvcSock);
if (fResponding)
break;
if (FCheckForAbort())
{
// we are going away.. break out man
Trace0("CWinsStatusHandler::ExecuteMonitoring() - abort detected, bye bye \n");
break;
}
}
}
// check to see if we need to clear out
if (FCheckForAbort())
{
// we are going away.. break out man
Trace0("CWinsStatusHandler::ExecuteMonitoring() - abort detected, bye bye \n");
break;
}
if (!fResponding)
{
Trace1("Status is DOWN for the server %s \n", strIP);
uStatus = IDS_ROOTNODE_STATUS_DOWN;
uImage = ICON_IDX_SERVER_LOST_CONNECTION;
}
else
{
Trace1("Status is UP for the server %s \n", strIP);
uStatus = IDS_ROOTNODE_STATUS_UP;
uImage = ICON_IDX_SERVER_CONNECTED;
}
if (IsServerDeleted(pWinsSrvEntry))
continue;
UpdateStatus(i, uStatus, uImage);
m_nServersUpdated++;
// update the last checked time
pWinsSrvEntry->m_timeLast = CTime::GetCurrentTime();
NotifyMainThread();
}
else
{
Trace2( "%d WINS msg from server %s - zeroing counter\n",
pWinsSrvEntry->dwMsgCount, strIP);
if (IsServerDeleted(pWinsSrvEntry))
continue;
pWinsSrvEntry->dwMsgCount = 0;
}
pWinsSrvEntry->dwMsgCount = 0;
}
// tell the listening thread to go to sleep
SetEvent(m_hPauseListening);
m_nServersUpdated = 0;
// wait for the next interval or if we are triggered
Trace1("CWinsStatusHandler::ExecuteMonitoring() - going to sleep for %d \n", m_dwUpdateInterval);
WaitForSingleObject(m_hWaitIntervalMain, m_dwUpdateInterval);
Trace0("CWinsStatusHandler::ExecuteMonitoring() - waking up\n");
// wake up the listening thread
SetEvent(m_hWaitIntervalListen);
if (FCheckForAbort())
{
// we are going away.. break out man
Trace0("CWinsStatusHandler::ExecuteMonitoring() - abort detected, bye bye \n");
break;
}
}
return TRUE;
}
/*---------------------------------------------------------------------------
CWinsStatusHandler::CloseSockets
Closes all the socket connections that were opened
Author: v-shubk
---------------------------------------------------------------------------*/
BOOL
CWinsStatusHandler::FCheckForAbort()
{
BOOL fAbort = FALSE;
if (WaitForSingleObject(m_hAbortMain, 0) == WAIT_OBJECT_0)
{
// we are going away.. break out man
fAbort = TRUE;
}
return fAbort;
}
/*---------------------------------------------------------------------------
CWinsStatusHandler::CloseSockets
Closes all the socket connections that were opened
Author: v-shubk
---------------------------------------------------------------------------*/
void
CWinsStatusHandler::CloseSockets()
{
// final clean up
if (closesocket(listenSockCl) == SOCKET_ERROR)
{
Trace1("closesocket(listenSockCl) failed with error %d.\n", WSAGetLastError());
}
if (closesocket(listenSockSrv) == SOCKET_ERROR)
{
Trace1("closesocket(listenSockSrv) failed with error %d.\n", WSAGetLastError());
}
if (closesocket(listenNameSvcSock) == SOCKET_ERROR)
{
Trace1("closesocket(listenNameSvcSock) failed with error %d \n", WSAGetLastError());
}
// we're going away...
Trace0("CWinsStatusHandler::CloseSockets() - Setting abort event.\n");
SetEvent(m_hAbortListen);
SetEvent(m_hAbortMain);
// wake everybody up
Trace0("CWinsStatusHandler::CloseSockets() - waking up threads.\n");
SetEvent(m_hWaitIntervalListen);
SetEvent(m_hWaitIntervalMain);
SetEvent(m_hAnswer);
// terminate the threads
if (m_hListenThread)
{
if (WaitForSingleObject(m_hListenThread, 5000) != WAIT_OBJECT_0)
{
Trace0("CWinsStatusHandler::CloseSockets() - ListenThread failed to cleanup!\n");
}
::CloseHandle(m_hListenThread);
m_hListenThread = NULL;
}
if (m_hMainMonThread)
{
if (WaitForSingleObject(m_hMainMonThread, 5000) != WAIT_OBJECT_0)
{
Trace0("CWinsStatusHandler::CloseSockets() - MainMonThread failed to cleanup!\n");
}
::CloseHandle(m_hMainMonThread);
m_hMainMonThread = NULL;
}
// clean up our events
if (m_hPauseListening)
{
::CloseHandle(m_hPauseListening);
m_hPauseListening = NULL;
}
if (m_hAbortListen)
{
::CloseHandle(m_hAbortListen);
m_hAbortListen = NULL;
}
if (m_hAbortMain)
{
::CloseHandle(m_hAbortMain);
m_hAbortMain = NULL;
}
if (m_hWaitIntervalListen)
{
::CloseHandle(m_hWaitIntervalListen);
m_hWaitIntervalListen = NULL;
}
if (m_hWaitIntervalMain)
{
::CloseHandle(m_hWaitIntervalMain);
m_hWaitIntervalMain = NULL;
}
if (m_hAnswer)
{
::CloseHandle(m_hAnswer);
m_hAnswer = NULL;
}
}
/*---------------------------------------------------------------------------
CWinsStatusHandler::CreateNodes(ITFSNode *pNode)
Displays the result pane nodes for the servers
Author: v-shubk
---------------------------------------------------------------------------*/
HRESULT
CWinsStatusHandler::CreateNodes(ITFSNode *pNode)
{
HRESULT hr = hrOK;
POSITION pos = NULL;
int nCount = (int)m_listServers.GetSize();
for(int i = 0; i < nCount; i++)
{
SPITFSNode spStatLeaf;
CServerStatus *pWinsSrvEntry = m_listServers.GetAt(i);
CreateLeafTFSNode(&spStatLeaf,
&GUID_WinsServerStatusLeafNodeType,
pWinsSrvEntry,
pWinsSrvEntry,
m_spNodeMgr);
// Tell the handler to initialize any specific data
pWinsSrvEntry->InitializeNode((ITFSNode *) spStatLeaf);
// Add the node as a child to the Active Leases container
pNode->AddChild(spStatLeaf);
pWinsSrvEntry->Release();
}
return hr;
}
/*---------------------------------------------------------------------------
CWinsStatusHandler::UpdateStatusColumn(ITFSNode *pNode)
Updates the status column of the servers in the result pane
Author: v-shubk
---------------------------------------------------------------------------*/
void
CWinsStatusHandler::UpdateStatusColumn(ITFSNode *pNode)
{
HRESULT hr = hrOK;
// enumerate thro' all the nodes
SPITFSNodeEnum spNodeEnum;
SPITFSNode spCurrentNode;
ULONG nNumReturned = 0;
BOOL bFound = FALSE;
// get the enumerator for this node
pNode->GetEnum(&spNodeEnum);
spNodeEnum->Next(1, &spCurrentNode, &nNumReturned);
while (nNumReturned)
{
CServerStatus * pStat = GETHANDLER(CServerStatus, spCurrentNode);
spCurrentNode->SetData(TFS_DATA_IMAGEINDEX, pStat->m_uImage);
spCurrentNode->SetData(TFS_DATA_OPENIMAGEINDEX, pStat->m_uImage);
// fillup the status column
spCurrentNode->ChangeNode(RESULT_PANE_CHANGE_ITEM);
// get the next Server in the list
spCurrentNode.Release();
spNodeEnum->Next(1, &spCurrentNode, &nNumReturned);
}
}
/*---------------------------------------------------------------------------
CWinsStatusHandler::AddNode(ITFSNode *pNode, CWinsServerHandler *pServer)
Adds a node to the result pane, used when a new server is added to
tree that has to be reflected for the status node
Author: v-shubk
---------------------------------------------------------------------------*/
HRESULT
CWinsStatusHandler::AddNode(ITFSNode *pNode, CWinsServerHandler *pServer)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
HRESULT hr = hrOK;
CServerStatus* pServ = NULL;
char szBuffer[MAX_PATH] = {0};
SPITFSNode spStatLeaf;
// if we haven't been expanded, don't add now. Will get done
// when we are expanded.
if (!m_bExpanded)
return hr;
// add to the list
// NOTE: this should be ACP because it's being used through winsock
CString strTemp = pServer->GetServerAddress();
WideToMBCS(strTemp, szBuffer);
// check if the server already exists, if so, just change the
// state stored to SERVER_ADDED and change the variables
// appropriately
if ((pServ = GetExistingServer(szBuffer)) == NULL)
{
pServ = new CServerStatus(m_spTFSCompData);
strcpy(pServ->szServerName, szBuffer);
AddServer(pServ);
}
else
{
// just add the related data to the CServerStatus and add the node
// to the UI
strcpy(pServ->szServerName, szBuffer);
// set the flag to SERVER_ADDED
MarkAsDeleted(szBuffer, FALSE);
}
pServ->dwIPAddress = pServer->GetServerIP();
pServ->dwMsgCount = 0;
strcpy(pServ->szIPAddress, "");
// create the new node here
CreateLeafTFSNode(&spStatLeaf,
&GUID_WinsServerStatusLeafNodeType,
pServ,
pServ,
m_spNodeMgr);
// Tell the handler to initialize any specific data
pServ->InitializeNode((ITFSNode *) spStatLeaf);
// Add the node as a child to the Active Leases container
pNode->AddChild(spStatLeaf);
pServ->Release();
spStatLeaf->ChangeNode(RESULT_PANE_CHANGE_ITEM_DATA);
pNode->ChangeNode(SCOPE_PANE_CHANGE_ITEM);
return hr;
}
/*---------------------------------------------------------------------------
CWinsStatusHandler::DeleteNode(ITFSNode *pNode,
CWinsServerHandler *pServer)
Removes the particular server from tehresult pane
Author: v-shubk
---------------------------------------------------------------------------*/
HRESULT
CWinsStatusHandler::DeleteNode(ITFSNode *pNode, CWinsServerHandler *pServer)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
HRESULT hr = hrOK;
CServerStatus* pServ = NULL;
char szBuffer[MAX_PATH];
SPITFSNode spStatLeaf;
// loop thro' the status nodes and set the flag to deleted so that this
// server is not seen in the result pane
SPITFSNodeEnum spNodeEnum;
SPITFSNode spCurrentNode;
ULONG nNumReturned = 0;
// get the enumerator
pNode->GetEnum(&spNodeEnum);
spNodeEnum->Next(1, &spCurrentNode, &nNumReturned);
while (nNumReturned)
{
char szBuffer[MAX_PATH];
// iterate thro' all the nodes and get the one that matches the
// current server
CServerStatus * pStat = GETHANDLER(CServerStatus, spCurrentNode);
// convert to ANSI
CString strTemp = pServer->GetServerAddress();
WideToMBCS(strTemp, szBuffer);
// if found
if (_stricmp(szBuffer, pStat->szServerName) == 0)
{
// mark as deleted and break
MarkAsDeleted(szBuffer, TRUE);
// remove this node
spCurrentNode->SetVisibilityState(TFS_VIS_HIDE);
spCurrentNode->ChangeNode(RESULT_PANE_DELETE_ITEM);
// do the cleanup and break
//spCurrentNode.Release();
//break;
}
// get the next server in the list
spCurrentNode.Release();
spNodeEnum->Next(1, &spCurrentNode, &nNumReturned);
}
return hr;
}
/*---------------------------------------------------------------------------
CWinsStatusHandler::StartMonitoring
Spawns off the monitoring thread
Author: v-shubk
---------------------------------------------------------------------------*/
void
CWinsStatusHandler::StartMonitoring(ITFSNode *pNode)
{
HRESULT hr = hrOK;
// create the sockets, they need to be closed at the end
hr = CreateListeningSockets();
if (hr != hrOK)
{
Trace0("CWinsStatusHandler::StartMonitoring, Initializing the sockets failed\n");
// no point continuing
return;
}
m_hMainMonThread = CreateThread(NULL,
0,
MainMonThread,
this,
0,
NULL
);
if (m_hMainMonThread == NULL)
{
Trace0("CWinsStatusHandler:: Main Monitoring thread failed to start\n");
return;
}
}
/*---------------------------------------------------------------------------
CWinsStatusHandler::GetServer(int i)
Returns the Server given the index
Author: v-shubk
---------------------------------------------------------------------------*/
CServerStatus*
CWinsStatusHandler::GetServer(int i)
{
CSingleLock sl(&m_cs);
sl.Lock();
return m_listServers.GetAt(i);
}
/*---------------------------------------------------------------------------
CWinsStatusHandler::AddServer(CServerStatus* pServer)
Adds a server to the array maintained
Author: v-shubk
---------------------------------------------------------------------------*/
void
CWinsStatusHandler::AddServer(CServerStatus* pServer)
{
CSingleLock sl(&m_cs);
sl.Lock();
m_listServers.Add(pServer);
}
/*---------------------------------------------------------------------------
CWinsStatusHandler::RemoveServer(int i)
Removes a server from the array
Author: v-shubk
---------------------------------------------------------------------------*/
void
CWinsStatusHandler::RemoveServer(int i)
{
CSingleLock sl(&m_cs);
sl.Lock();
m_listServers.RemoveAt(i);
}
/*---------------------------------------------------------------------------
CWinsStatusHandler::UpdateStatus(UINT nID, int i)
Upadtes the status string for the server
Author: v-shubk
---------------------------------------------------------------------------*/
void
CWinsStatusHandler::UpdateStatus(int nIndex, UINT uStatusId, UINT uImage)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
CSingleLock sl(&m_cs);
sl.Lock();
CServerStatus *pStat = m_listServers.GetAt(nIndex);
pStat->m_strStatus.LoadString(uStatusId);
pStat->m_uImage = uImage;
}
/*---------------------------------------------------------------------------
CWinsStatusHandler::GetListSize()
Retruns the number of elements in the array
Author: v-shubk
---------------------------------------------------------------------------*/
int
CWinsStatusHandler::GetListSize()
{
CSingleLock sl(&m_cs);
sl.Lock();
return (int)m_listServers.GetSize();
}
/*---------------------------------------------------------------------------
CWinsStatusHandler::SetIPAddress(int i, LPSTR szIP)
Sets the iP Address of the server, this is the case when the server
is added with Do not connect option, but we still need to update the
status
Author: v-shubk
---------------------------------------------------------------------------*/
void
CWinsStatusHandler::SetIPAddress(int i, LPSTR szIP)
{
CSingleLock sl(&m_cs);
sl.Lock();
CServerStatus *pStat = m_listServers.GetAt(i);
strcpy(pStat->szIPAddress, szIP);
}
/*---------------------------------------------------------------------------
CWinsStatusHandler::MarkAsDeleted(LPSTR szBuffer, BOOL bDelete)
Marks the flag to DELETED if bDelete is TRUE, else to ADDED
All the servers with the flag DELETED set are not processed
and are not shown in the UI.
Author: v-shubk
---------------------------------------------------------------------------*/
void
CWinsStatusHandler::MarkAsDeleted(LPSTR szBuffer, BOOL bDelete)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
CSingleLock sl(&m_cs);
sl.Lock();
int nCount = 0;
CServerStatus *pStat = NULL;
// get the list of the servers maintained
nCount = (int)m_listServers.GetSize();
for(int i = 0; i < nCount; i++)
{
pStat = m_listServers.GetAt(i);
if (_stricmp(szBuffer, pStat->szServerName) == 0)
{
// set the deleted flag
if (bDelete)
pStat->dwState = SERVER_DELETED;
else
pStat->dwState = SERVER_ADDED;
break;
}
}
return;
}
/*---------------------------------------------------------------------------
CWinsStatusHandler::GetExistingServer(LPSTR szBuffer)
Gets the pointer to the existing server in the array
This function is useful when the server is deletd and again added back
to the scope tree.
Author: v-shubk
----------------------------------------------------------------------------*/
CServerStatus *
CWinsStatusHandler::GetExistingServer(LPSTR szBuffer)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
CSingleLock sl(&m_cs);
sl.Lock();
int nCount = 0;
CServerStatus *pStat = NULL;
for(int i = 0; i < nCount; i++)
{
pStat = m_listServers.GetAt(i);
if (_strcmpi(pStat->szServerName, szBuffer) == 0)
return pStat;
}
return NULL;
}
/*---------------------------------------------------------------------------
CWinsStatusHandler::IsServerDeleted(CServerStatus *pStat)
Checks if a server has been deleted, such servers
sre not considered for monitoring
Author: v-shubk
---------------------------------------------------------------------------*/
BOOL
CWinsStatusHandler::IsServerDeleted(CServerStatus *pStat)
{
return (pStat->dwState == SERVER_DELETED) ? TRUE : FALSE;
}
/*---------------------------------------------------------------------------
CWinsStatusHandler::NotifyMainThread()
Description
Author: EricDav
---------------------------------------------------------------------------*/
void
CWinsStatusHandler::NotifyMainThread()
{
if (!m_uMsgBase)
{
m_uMsgBase = (INT) ::SendMessage(m_spTFSCompData->GetHiddenWnd(), WM_HIDDENWND_REGISTER, TRUE, 0);
}
::PostMessage(m_spTFSCompData->GetHiddenWnd(),
m_uMsgBase + WM_HIDDENWND_INDEX_HAVEDATA,
(WPARAM)(ITFSThreadHandler *)this,
NULL);
}
// listening thread for the main monitoring thread
DWORD WINAPI
MonThreadProc(LPVOID pParam)
{
DWORD dwReturn;
HRESULT hr = hrOK;
COM_PROTECT_TRY
{
CWinsStatusHandler * pWinsStatus = (CWinsStatusHandler *) pParam;
Trace0("MonThreadProc - Thread started.\n");
dwReturn = pWinsStatus->ListeningThreadFunc();
Trace0("MonThreadProc - Thread ending.\n");
}
COM_PROTECT_CATCH
return dwReturn;
}
// main monitoring thread
DWORD WINAPI MainMonThread(LPVOID pParam)
{
DWORD dwReturn;
HRESULT hr = hrOK;
COM_PROTECT_TRY
{
CWinsStatusHandler * pWinsStatus = (CWinsStatusHandler *) pParam;
Trace0("MainMonThread - Thread started.\n");
dwReturn = pWinsStatus->ExecuteMonitoring();
Trace0("MainMonThread - Thread ending.\n");
}
COM_PROTECT_CATCH
return dwReturn;
}