📄 hxnetif.cpp
字号:
!_hxWSACleanup ||
!_raWSAIoctl)
#endif /* _WINCE */
{
rc = HXR_FAILED;
goto cleanup;
}
wVersionRequested = (1 << 8) + 1;
_hxWSAStartup(wVersionRequested, &wsaData);
#ifndef _WINCE
s = _hxsocket(AF_INET, SOCK_DGRAM, 0);
if (s == INVALID_SOCKET)
{
rc = HXR_FAILED;
goto cleanup;
}
pInfo = new INTERFACE_INFO[MAX_INTERFACES];
// get interfaces list
if (_raWSAIoctl(s, SIO_GET_INTERFACE_LIST, NULL, NULL, pInfo,
sizeof(INTERFACE_INFO)*MAX_INTERFACES, &ulBytes, NULL, NULL))
{
rc = HXR_FAILED;
goto cleanup;
}
// caculate # of interfaces we have
iStructures = ulBytes / sizeof(INTERFACE_INFO);
// iterate through the interface list
for (iPosition = 0; iPosition < iStructures; iPosition++)
{
lFlags = pInfo[iPosition].iiFlags;
if (lFlags & IFF_LOOPBACK)
{
continue;
}
else if ((lFlags & IFF_POINTTOPOINT) && (lFlags & IFF_UP))
{
type = POINTTOPOINT;
}
else if ((lFlags & IFF_BROADCAST) && (lFlags & IFF_UP))
{
type = BROADCAST;
}
else
{
continue;
}
ulNetAddress = ((sockaddr_in*)&(pInfo[iPosition].iiAddress))->sin_addr.s_addr;
ulNetMask = ((sockaddr_in*)&(pInfo[iPosition].iiNetmask))->sin_addr.s_addr;
// ignore the net interface with invalid IP/Mask
if (ulNetAddress == 0 || ulNetMask == 0)
{
continue;
}
pNIInfo = new NIInfo;
pNIInfo->bActive = TRUE;
pNIInfo->type = type;
pNIInfo->ulNetAddress = ulNetAddress;
pNIInfo->ulNetMask = ulNetMask;
if (!pNetInterfaceList)
{
pNetInterfaceList = new CHXSimpleList();
}
pNetInterfaceList->AddTail(pNIInfo);
}
cleanup:
if (_hxclosesocket)
{
_hxclosesocket(s);
}
if (_hxWSACleanup)
{
_hxWSACleanup();
}
HX_VECTOR_DELETE(pInfo);
#else
// WinCE does not support Winsock2, yet. Also, it has many variations for registry settings.
// Thus, it is better to use GetAdapterInfo defined in iphlpapi.h.
// Note: This call is supported only in WinCE 3.0 or later.
if (NULL == m_hIPLib)
m_hIPLib = LoadLibrary(OS_STRING("IPHLPAPI.DLL"));
if (m_hIPLib)
_pGetAdaptersInfo = (GETADAPTERSINFO) ::GetProcAddress(m_hIPLib, OS_STRING("GetAdaptersInfo"));
if (NULL == _pGetAdaptersInfo)
{
rc = HXR_FAILED;
goto cleanup;
}
// first make a call with ulSize = 0 to get the exact size needed
dwResult = _pGetAdaptersInfo(pAdapterInfo, &ulSize);
if (ERROR_BUFFER_OVERFLOW == dwResult)
{
// allocate right amount of space for adapter info
pAdapterInfo = (PIP_ADAPTER_INFO)(new char[ulSize]);
if (!pAdapterInfo)
{
rc = HXR_OUTOFMEMORY;
goto cleanup;
}
// fill up adapters info
dwResult= _pGetAdaptersInfo(pAdapterInfo, &ulSize);
if (ERROR_SUCCESS != dwResult)
{
rc = HXR_FAILED;
goto cleanup;
}
// step thru the adapters list that we received
while (pAdapterInfo != NULL)
{
if (MIB_IF_TYPE_PPP == pAdapterInfo->Type)
type = POINTTOPOINT;
else if (MIB_IF_TYPE_ETHERNET == pAdapterInfo->Type)
type = BROADCAST;
else
continue;
// step thru all IP addresses for each adapter
pAddrList = &(pAdapterInfo->IpAddressList);
do
{
ulNetAddress = _pInetAddr(pAddrList->IpAddress.String);
ulNetMask = _pInetAddr(pAddrList->IpMask.String);
// ignore the net interface with invalid IP/Mask
if (INADDR_NONE != ulNetAddress && 0 != ulNetAddress && INADDR_NONE != ulNetMask && 0 != ulNetMask)
{
pNIInfo = new NIInfo;
if (!pAdapterInfo)
{
rc = HXR_OUTOFMEMORY;
goto cleanup;
}
pNIInfo->bActive = TRUE;
pNIInfo->type = type;
pNIInfo->ulNetAddress = ulNetAddress;
pNIInfo->ulNetMask = ulNetMask;
if (!pNetInterfaceList)
{
pNetInterfaceList = new CHXSimpleList();
if (!pAdapterInfo)
{
rc = HXR_OUTOFMEMORY;
goto cleanup;
}
}
pNetInterfaceList->AddTail(pNIInfo);
pAddrList = pAddrList->Next;
}
}while (pAddrList != NULL);
pAdapterInfo = pAdapterInfo->Next;
}
}
else
{
rc = HXR_FAILED;
goto cleanup;
}
cleanup:
HX_VECTOR_DELETE(pAdapterInfo);
if (_hxWSACleanup)
{
_hxWSACleanup();
}
#endif /* _WINCE */
return rc;
}
void
HXNetInterface::CheckAddrChange(void)
{
DWORD dwResult = 0;
if (WAIT_OBJECT_0 == WaitForSingleObject(m_hAddrChangeEvent, 0))
{
Reset(m_pNetInterfaceList);
RetrieveNetInterface0(m_pNetInterfaceList);
if (m_pSinkList)
{
CHXSimpleList::Iterator ndx = m_pSinkList->Begin();
for (; ndx != m_pSinkList->End(); ++ndx)
{
IHXNetInterfacesAdviseSink* pSink = (IHXNetInterfacesAdviseSink*) (*ndx);
pSink->NetInterfacesUpdated();
}
}
#ifdef _WINCE
// Overlapped param is not supported in wince 3.0 in the second param to NotifyAddrChange
if(NO_ERROR == _pNotifyAddrChange(&m_hAddrChangeEvent, NULL))
#else
if (ERROR_IO_PENDING == _pNotifyAddrChange(&m_handle, &m_overLapped))
#endif /* _WINCE */
{
m_pAddrChangeCallback->m_bIsCallbackPending = TRUE;
m_pAddrChangeCallback->m_PendingHandle = m_pScheduler->RelativeEnter(m_pAddrChangeCallback, CHECK_ADDR_CHANGE_INTERVAL);
}
}
else
{
m_pAddrChangeCallback->m_bIsCallbackPending = TRUE;
m_pAddrChangeCallback->m_PendingHandle = m_pScheduler->RelativeEnter(m_pAddrChangeCallback, CHECK_ADDR_CHANGE_INTERVAL);
}
return;
}
BOOL
HXNetInterface::IsNetInterfaceChanged(void)
{
BOOL bResult = FALSE;
CHXSimpleList* pTempNetInterfaceList = NULL;
if (m_pAddrChangeCallback && m_pAddrChangeCallback->m_bIsCallbackPending)
{
if (WAIT_OBJECT_0 == WaitForSingleObject(m_hAddrChangeEvent, 0))
{
bResult = TRUE;
Reset(m_pNetInterfaceList);
RetrieveNetInterface0(m_pNetInterfaceList);
#ifdef _WINCE
// Overlapped param is not supported in wince 3.0 in the second param to NotifyAddrChange
if(NO_ERROR == _pNotifyAddrChange(&m_hAddrChangeEvent, NULL))
#else
if (ERROR_IO_PENDING == _pNotifyAddrChange(&m_handle, &m_overLapped))
#endif /* _WINCE */
{
m_pScheduler->Remove(m_pAddrChangeCallback->m_PendingHandle);
m_pAddrChangeCallback->m_PendingHandle = m_pScheduler->RelativeEnter(m_pAddrChangeCallback, CHECK_ADDR_CHANGE_INTERVAL);
}
}
goto cleanup;
}
else
{
pTempNetInterfaceList = new CHXSimpleList();
RetrieveNetInterface0(pTempNetInterfaceList);
if (!pTempNetInterfaceList || pTempNetInterfaceList->GetCount() == 0)
{
// try the generic method
RetrieveNetInterface1(pTempNetInterfaceList);
}
if (pTempNetInterfaceList && m_pNetInterfaceList)
{
if (pTempNetInterfaceList->GetCount() != m_pNetInterfaceList->GetCount())
{
bResult = TRUE;
}
else
{
CHXSimpleList::Iterator ndx0 = pTempNetInterfaceList->Begin();
CHXSimpleList::Iterator ndx1 = m_pNetInterfaceList->Begin();
for (; ndx0 != pTempNetInterfaceList->End() && ndx1 != m_pNetInterfaceList->End(); ++ndx0, ++ndx1)
{
NIInfo* pInfo0 = (NIInfo*)(*ndx0);
NIInfo* pInfo1 = (NIInfo*)(*ndx1);
if (pInfo0->ulNetAddress != pInfo1->ulNetAddress ||
pInfo0->ulNetMask != pInfo1->ulNetMask)
{
bResult = TRUE;
}
}
}
}
else if (pTempNetInterfaceList != m_pNetInterfaceList)
{
bResult = TRUE;
}
if (bResult)
{
Reset(m_pNetInterfaceList);
HX_DELETE(m_pNetInterfaceList);
m_pNetInterfaceList = pTempNetInterfaceList;
}
else
{
Reset(pTempNetInterfaceList);
HX_DELETE(pTempNetInterfaceList);
}
}
cleanup:
return bResult;
}
void
HXNetInterface::Reset(CHXSimpleList* pNetInterfaceList)
{
if (pNetInterfaceList)
{
while (pNetInterfaceList->GetCount())
{
NIInfo* pNIInfo = (NIInfo*)pNetInterfaceList->RemoveHead();
HX_DELETE(pNIInfo);
}
}
}
void
HXNetInterface::Close(void)
{
if (m_pAddrChangeCallback)
{
if (m_pAddrChangeCallback->m_bIsCallbackPending)
{
m_pAddrChangeCallback->m_bIsCallbackPending = FALSE;
m_pScheduler->Remove(m_pAddrChangeCallback->m_PendingHandle);
m_pAddrChangeCallback->m_PendingHandle = 0;
}
HX_RELEASE(m_pAddrChangeCallback);
}
if (m_hAddrChangeEvent)
{
CloseHandle(m_hAddrChangeEvent);
m_hAddrChangeEvent = NULL;
}
if (m_handle)
{
#ifndef _WINCE
CancelIo(m_handle);
#else
CloseHandle(m_handle);
#endif /* _WINCE */
// XXX HP
// Confirmed with MS TS that the caller doesn't need to
// call CloseHandle() on m_handle, it's taken care of by
// the FreeLibrary()
m_handle = NULL;
}
Reset(m_pNetInterfaceList);
HX_DELETE(m_pNetInterfaceList);
if (m_pSinkList)
{
HX_ASSERT(m_pSinkList->GetCount() == 0);
CHXSimpleList::Iterator ndx = m_pSinkList->Begin();
for (; ndx != m_pSinkList->End(); ++ndx)
{
IHXNetInterfacesAdviseSink* pSink = (IHXNetInterfacesAdviseSink*) (*ndx);
HX_RELEASE(pSink);
}
HX_DELETE(m_pSinkList);
}
if (m_hIPLib)
{
FreeLibrary(m_hIPLib);
m_hIPLib = NULL;
}
if (m_hWinSockLib)
{
FreeLibrary(m_hWinSockLib);
m_hWinSockLib = NULL;
}
HX_RELEASE(m_pScheduler);
HX_RELEASE(m_pContext);
}
AddrChangeCallback::AddrChangeCallback() :
m_lRefCount (0)
,m_pParent (0)
,m_PendingHandle (0)
,m_bIsCallbackPending (FALSE)
{
}
AddrChangeCallback::~AddrChangeCallback()
{
}
/*
* IUnknown methods
*/
/////////////////////////////////////////////////////////////////////////
// Method:
// IUnknown::QueryInterface
// Purpose:
// Implement this to export the interfaces supported by your
// object.
//
STDMETHODIMP AddrChangeCallback::QueryInterface(REFIID riid, void** ppvObj)
{
QInterfaceList qiList[] =
{
{ GET_IIDHANDLE(IID_IUnknown), this },
{ GET_IIDHANDLE(IID_IHXCallback), (IHXCallback*) this },
{ GET_IIDHANDLE(IID_IHXInterruptSafe), (IHXInterruptSafe*) this },
};
return QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
}
/////////////////////////////////////////////////////////////////////////
// Method:
// IUnknown::AddRef
// Purpose:
// Everyone usually implements this the same... feel free to use
// this implementation.
//
STDMETHODIMP_(ULONG32) AddrChangeCallback::AddRef()
{
return InterlockedIncrement(&m_lRefCount);
}
/////////////////////////////////////////////////////////////////////////
// Method:
// IUnknown::Release
// Purpose:
// Everyone usually implements this the same... feel free to use
// this implementation.
//
STDMETHODIMP_(ULONG32) AddrChangeCallback::Release()
{
if (InterlockedDecrement(&m_lRefCount) > 0)
{
return m_lRefCount;
}
delete this;
return 0;
}
STDMETHODIMP AddrChangeCallback::Func(void)
{
m_PendingHandle = 0;
m_bIsCallbackPending = FALSE;
if (m_pParent)
{
m_pParent->CheckAddrChange();
}
return HXR_OK;
}
STDMETHODIMP_(BOOL) AddrChangeCallback::IsInterruptSafe()
{
return FALSE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -