hxnetif.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:23k
源码类别:

Symbian

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Source last modified: $Id: hxnetif.cpp,v 1.6.8.1 2004/07/09 02:06:49 hubbe Exp $
  3.  * 
  4.  * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
  5.  * 
  6.  * The contents of this file, and the files included with this file,
  7.  * are subject to the current version of the RealNetworks Public
  8.  * Source License (the "RPSL") available at
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed
  10.  * the file under the current version of the RealNetworks Community
  11.  * Source License (the "RCSL") available at
  12.  * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
  13.  * will apply. You may also obtain the license terms directly from
  14.  * RealNetworks.  You may not use this file except in compliance with
  15.  * the RPSL or, if you have a valid RCSL with RealNetworks applicable
  16.  * to this file, the RCSL.  Please see the applicable RPSL or RCSL for
  17.  * the rights, obligations and limitations governing use of the
  18.  * contents of the file.
  19.  * 
  20.  * Alternatively, the contents of this file may be used under the
  21.  * terms of the GNU General Public License Version 2 or later (the
  22.  * "GPL") in which case the provisions of the GPL are applicable
  23.  * instead of those above. If you wish to allow use of your version of
  24.  * this file only under the terms of the GPL, and not to allow others
  25.  * to use your version of this file under the terms of either the RPSL
  26.  * or RCSL, indicate your decision by deleting the provisions above
  27.  * and replace them with the notice and other provisions required by
  28.  * the GPL. If you do not delete the provisions above, a recipient may
  29.  * use your version of this file under the terms of any one of the
  30.  * RPSL, the RCSL or the GPL.
  31.  * 
  32.  * This file is part of the Helix DNA Technology. RealNetworks is the
  33.  * developer of the Original Code and owns the copyrights in the
  34.  * portions it created.
  35.  * 
  36.  * This file, and the files included with this file, is distributed
  37.  * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
  38.  * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
  39.  * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
  40.  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
  41.  * ENJOYMENT OR NON-INFRINGEMENT.
  42.  * 
  43.  * Technology Compatibility Kit Test Suite(s) Location:
  44.  *    http://www.helixcommunity.org/content/tck
  45.  * 
  46.  * Contributor(s):
  47.  * 
  48.  * ***** END LICENSE BLOCK ***** */
  49. #include "hxcom.h"
  50. #include <string.h>
  51. #include <stdio.h>
  52. #ifndef _WINCE
  53. #include <sys/types.h>
  54. #include <sys/stat.h>
  55. #include <time.h>
  56. #include <winsock2.h>
  57. #include <ws2tcpip.h>
  58. #endif /* _WINCE */
  59. #include <windows.h>
  60. #include "hlxclib/sys/socket.h"
  61. #include "hlxosstr.h"
  62. #include "hxresult.h"
  63. #include "hxslist.h"
  64. #include "netbyte.h"
  65. #include "hxengin.h"
  66. #include "hxnetif.h"
  67. #define CHECK_ADDR_CHANGE_INTERVAL  60000
  68. HXNetInterface::HXNetInterface(IUnknown* pContext)
  69. : m_lRefCount(0)
  70. , m_bInitialized(FALSE)
  71. , m_hIPLib(NULL)
  72. , m_hWinSockLib(NULL)
  73. , m_hAddrChangeEvent(NULL)
  74. , m_pScheduler(NULL)
  75. , m_pAddrChangeCallback(NULL)
  76. , m_pNetInterfaceList(NULL)
  77. , m_pSinkList(NULL)
  78. , _pGetIfTable(NULL)
  79. , _pGetIpAddrTable(NULL)
  80. , _pNotifyAddrChange(NULL)
  81. , _hxWSAStartup(NULL)
  82. , _hxWSACleanup(NULL)
  83. #ifdef _WINCE
  84. , _pInetAddr(NULL)
  85. ,_pGetAdaptersInfo(NULL)
  86. #else
  87. , _hxsocket(NULL)
  88. , _hxclosesocket(NULL)
  89. , _raWSAIoctl(NULL)
  90. #endif /* _WINCE */
  91. , m_handle(NULL)
  92. {
  93.     m_pContext = pContext;
  94.     HX_ADDREF(m_pContext);
  95. }
  96. HXNetInterface::~HXNetInterface()
  97. {
  98.     Close();
  99. }
  100. STDMETHODIMP
  101. HXNetInterface::QueryInterface(REFIID riid, void**ppvObj)
  102. {
  103.     if (IsEqualIID(riid, IID_IUnknown))
  104.     {
  105. AddRef();
  106. *ppvObj = this;
  107. return HXR_OK;
  108.     }
  109.     else if (IsEqualIID(riid, IID_IHXNetInterfaces))
  110.     {
  111. AddRef();
  112. *ppvObj = (IHXNetInterfaces*)this;
  113. return HXR_OK;
  114.     }
  115.     *ppvObj = NULL;
  116.     return HXR_NOINTERFACE;
  117. }
  118. /////////////////////////////////////////////////////////////////////////
  119. //  Method:
  120. // IUnknown::AddRef
  121. //  Purpose:
  122. // Everyone usually implements this the same... feel free to use
  123. // this implementation.
  124. //
  125. STDMETHODIMP_(ULONG32) 
  126. HXNetInterface::AddRef()
  127. {
  128.     return InterlockedIncrement(&m_lRefCount);
  129. }
  130. /////////////////////////////////////////////////////////////////////////
  131. //  Method:
  132. // IUnknown::Release
  133. //  Purpose:
  134. // Everyone usually implements this the same... feel free to use
  135. // this implementation.
  136. //
  137. STDMETHODIMP_(ULONG32) 
  138. HXNetInterface::Release()
  139. {
  140.     if (InterlockedDecrement(&m_lRefCount) > 0)
  141.     {
  142.         return m_lRefCount;
  143.     }
  144.     delete this;
  145.     return 0;
  146. }
  147. STDMETHODIMP
  148. HXNetInterface::UpdateNetInterfaces(void)
  149. {
  150.     HX_RESULT     rc = HXR_OK;    
  151.     if (!m_bInitialized)
  152.     {
  153. m_bInitialized = TRUE;
  154. rc = RetrieveNetInterface0(m_pNetInterfaceList);
  155. if (!m_pNetInterfaceList || m_pNetInterfaceList->GetCount() == 0)
  156. {
  157.     // try the generic method
  158.     RetrieveNetInterface1(m_pNetInterfaceList);
  159. }
  160. if (_pNotifyAddrChange)
  161. {
  162.     m_hAddrChangeEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  163. #ifndef _WINCE
  164.     m_overLapped.Internal = NULL;
  165.     m_overLapped.InternalHigh = NULL;
  166.     m_overLapped.Offset = 0;
  167.     m_overLapped.OffsetHigh = 0;
  168.     m_overLapped.hEvent = m_hAddrChangeEvent;
  169.     if (ERROR_IO_PENDING == _pNotifyAddrChange(&m_handle, &m_overLapped))
  170. #else
  171. // Overlapped param is not supported in wince 3.0 in the second param to NotifyAddrChange
  172. if(NO_ERROR == _pNotifyAddrChange(&m_hAddrChangeEvent, NULL))
  173. #endif /* _WINCE */
  174.     {
  175. if (!m_pScheduler)
  176. {
  177.     m_pContext->QueryInterface(IID_IHXScheduler, (void**)&m_pScheduler);
  178. }
  179. if (m_pScheduler)
  180. {
  181.     m_pAddrChangeCallback = new AddrChangeCallback;
  182.     m_pAddrChangeCallback->m_pParent = this;
  183.     m_pAddrChangeCallback->AddRef();
  184.     m_pAddrChangeCallback->m_bIsCallbackPending = TRUE;
  185.     m_pAddrChangeCallback->m_PendingHandle = m_pScheduler->RelativeEnter(m_pAddrChangeCallback, CHECK_ADDR_CHANGE_INTERVAL);
  186. }
  187.     }
  188. }
  189.     }
  190.     else if (IsNetInterfaceChanged())
  191.     {
  192. if (m_pSinkList)
  193. {
  194.     CHXSimpleList::Iterator ndx = m_pSinkList->Begin();
  195.     for (; ndx != m_pSinkList->End(); ++ndx)
  196.     {
  197. IHXNetInterfacesAdviseSink* pSink = (IHXNetInterfacesAdviseSink*) (*ndx);
  198. pSink->NetInterfacesUpdated();
  199.     }
  200. }
  201.     }
  202.     return rc;
  203. }
  204. STDMETHODIMP_(UINT32)
  205. HXNetInterface::GetNumOfNetInterfaces()
  206. {
  207.     if (!m_bInitialized)
  208.     {
  209. UpdateNetInterfaces();
  210.     }
  211.     return m_pNetInterfaceList ? m_pNetInterfaceList->GetCount() : 0;
  212. }
  213. STDMETHODIMP
  214. HXNetInterface::GetNetInterfaces(UINT16 lIndex,
  215.   REF(NIInfo*) pNIInfo)
  216. {
  217.     HX_RESULT rc = HXR_OK;
  218.     int i = 0;
  219.     CHXSimpleList::Iterator iter;
  220.     pNIInfo = NULL;
  221.     if (!m_bInitialized)
  222.     {
  223. UpdateNetInterfaces();
  224.     }
  225.     if (m_pNetInterfaceList)
  226.     {
  227. iter = m_pNetInterfaceList->Begin();
  228. for (; iter != m_pNetInterfaceList->End(); ++iter, ++i)
  229. {
  230.     NIInfo* pInfo = (NIInfo*)(*iter);
  231.     if (i == lIndex)
  232.     {
  233. pNIInfo = pInfo;
  234. break;
  235.     }
  236. }
  237.     }
  238.     if (!pNIInfo)
  239.     {
  240. rc = HXR_FAILED;
  241.     }
  242.     return rc;
  243. }
  244. STDMETHODIMP
  245. HXNetInterface::AddAdviseSink(IHXNetInterfacesAdviseSink* pSink)
  246. {
  247.     HX_RESULT rc = HXR_OK;
  248.     if (!m_pSinkList)
  249.     {
  250. m_pSinkList = new CHXSimpleList();
  251.     }
  252.     pSink->AddRef();
  253.     m_pSinkList->AddTail(pSink);
  254.     return rc;
  255. }
  256. STDMETHODIMP
  257. HXNetInterface::RemoveAdviseSink(IHXNetInterfacesAdviseSink* pSink)
  258. {
  259.     HX_RESULT rc = HXR_OK;
  260.     LISTPOSITION lPosition = m_pSinkList->Find(pSink);
  261.     if (!lPosition)
  262.     {
  263. rc = HXR_UNEXPECTED;
  264. goto cleanup;
  265.     }
  266.     m_pSinkList->RemoveAt(lPosition);
  267.     pSink->Release();
  268. cleanup:
  269.     return rc;
  270. }
  271. HX_RESULT
  272. HXNetInterface::RetrieveNetInterface0(CHXSimpleList*& pNetInterfaceList)
  273. {
  274.     HX_RESULT rc = HXR_OK;
  275.     char temp;
  276.     DWORD dwFlags = 0;
  277.     UINT32 ulSize = 1;
  278.     UINT32 ulNetAddress = 0;
  279.     UINT32 ulNetMask = 0;
  280.     DWORD i = 0;
  281.     DWORD j = 0;
  282.     PMIB_IFTABLE ifTable = NULL;
  283.     PMIB_IPADDRTABLE ipAddrTable = NULL;
  284.     NIType type = UNKNOWN;
  285.     NIInfo* pNIInfo = NULL;
  286.     if (!m_hIPLib)
  287.     {
  288. m_hIPLib = LoadLibrary(OS_STRING("IPHLPAPI.DLL"));
  289. if (m_hIPLib)
  290. {
  291.     _pGetIfTable = (GETIFTABLE)GetProcAddress(m_hIPLib, OS_STRING("GetIfTable"));
  292.     _pGetIpAddrTable = (GETIPADDRTABLE)GetProcAddress(m_hIPLib, OS_STRING("GetIpAddrTable"));
  293.     _pNotifyAddrChange = (NOTIFYADDRCHANGE)GetProcAddress(m_hIPLib, OS_STRING("NotifyAddrChange"));
  294. }
  295.     }
  296.     if (!_pGetIfTable     ||
  297. !_pGetIpAddrTable   ||
  298. !_pNotifyAddrChange)
  299.     {
  300. rc = HXR_FAILED;
  301. goto cleanup;
  302.     }
  303.     
  304.     // get interface table
  305.     rc = _pGetIfTable(PMIB_IFTABLE(&temp),&ulSize,TRUE);
  306.     if(HXR_OK == rc)
  307.     {
  308. rc = HXR_FAILED;
  309. goto cleanup;
  310.     }
  311.     ifTable = (PMIB_IFTABLE) new char[ulSize];
  312.     rc = _pGetIfTable(ifTable, &ulSize, TRUE);
  313.     if (HXR_OK != rc)
  314.     {
  315. rc = HXR_FAILED;
  316. goto cleanup;
  317.     }
  318.     // get ip addresses table
  319.     ulSize = 1;
  320.   
  321.     rc = _pGetIpAddrTable(PMIB_IPADDRTABLE(&temp), &ulSize, TRUE);
  322.     if (HXR_OK == rc)
  323.     {
  324. rc = HXR_FAILED;
  325. goto cleanup;
  326.     }
  327.     ipAddrTable = (PMIB_IPADDRTABLE) new char[ulSize];
  328.     rc = _pGetIpAddrTable(ipAddrTable, &ulSize, TRUE);
  329.     if (HXR_OK != rc)
  330.     {
  331. rc = HXR_FAILED;
  332. goto cleanup;
  333.     }
  334.     // check if interface exists
  335.     if (0 == ifTable->dwNumEntries)
  336.     {
  337. rc = HXR_FAILED;
  338. goto cleanup;
  339.     }
  340.     // enumerate all interfaces
  341.     for (i = 0; i < ifTable->dwNumEntries; i++) 
  342.     {
  343. // ignore the LOOPBACK
  344. if (ifTable->table[i].dwType == MIB_IF_TYPE_LOOPBACK)
  345. {
  346.     continue;;
  347. }
  348. else if (ifTable->table[i].dwType == MIB_IF_TYPE_PPP &&
  349.  ifTable->table[i].dwOperStatus)
  350. {
  351.     type = POINTTOPOINT;
  352. }
  353. else if (ifTable->table[i].dwOperStatus)
  354. {
  355.     type = BROADCAST;
  356. }
  357. else
  358. {
  359.     continue;
  360. }
  361. // get corresponding IP
  362. for(j=0; j < ipAddrTable->dwNumEntries; j++) 
  363. {
  364.     if(ipAddrTable->table[j].dwIndex == ifTable->table[i].dwIndex) 
  365.     {
  366. ulNetAddress = ipAddrTable->table[j].dwAddr;
  367. ulNetMask = ipAddrTable->table[j].dwMask;
  368. break;
  369.     }
  370. }
  371. // ignore net interface with invalid IP/Mask
  372. if (ulNetAddress == 0 || ulNetMask == 0)
  373. {
  374.     continue;
  375. }
  376. pNIInfo = new NIInfo;
  377. pNIInfo->bActive = TRUE;
  378. pNIInfo->type = type;
  379. pNIInfo->ulNetAddress = ulNetAddress; 
  380. pNIInfo->ulNetMask = ulNetMask;
  381. if (!pNetInterfaceList)
  382. {
  383.     pNetInterfaceList = new CHXSimpleList();
  384. }
  385. pNetInterfaceList->AddTail(pNIInfo);
  386.     }
  387.     
  388. cleanup:
  389.     
  390.     if (ifTable)
  391.     {
  392. delete[] ((char*)ifTable);
  393.     }
  394.     if (ipAddrTable)
  395.     {
  396. delete[] ((char*)ipAddrTable);
  397.     }
  398.     return rc;
  399. }
  400. HX_RESULT
  401. HXNetInterface::RetrieveNetInterface1(CHXSimpleList*& pNetInterfaceList)
  402. {
  403.     HX_RESULT     rc = HXR_OK;
  404.     int     iStructures = 0;
  405.     int     iPosition = 0;
  406.     long     lFlags = 0;
  407.     UINT32     ulBytes = 0; 
  408.     UINT32     ulNetAddress = 0;
  409.     UINT32     ulNetMask = 0;
  410.     SOCKET     s = 0;
  411.     WORD     wVersionRequested = 0;
  412.     NIType     type = UNKNOWN;
  413.     NIInfo*     pNIInfo = NULL;
  414.     WSADATA     wsaData;
  415. #ifdef _WINCE
  416. PIP_ADAPTER_INFO pAdapterInfo = NULL;
  417. PIP_ADDR_STRING pAddrList = NULL;
  418. ULONG ulSize = 0;
  419. DWORD dwResult = ERROR_NOT_SUPPORTED;
  420. #else
  421. INTERFACE_INFO* pInfo = NULL;
  422. #endif
  423.     if (!m_hWinSockLib)
  424.     {
  425. #ifdef _WINCE
  426. m_hWinSockLib = LoadLibrary(OS_STRING("winsock.dll"));
  427. #else
  428. m_hWinSockLib = LoadLibrary(OS_STRING("ws2_32.dll"));
  429. #endif /* _WINCE */
  430. if (m_hWinSockLib)
  431. {
  432. _hxWSAStartup = (WSASTARTUP)GetProcAddress(m_hWinSockLib, OS_STRING("WSAStartup"));
  433. _hxWSACleanup = (WSACLEANUP)GetProcAddress(m_hWinSockLib, OS_STRING("WSACleanup"));
  434. #ifdef _WINCE
  435. _pInetAddr = (INET_ADDR) ::GetProcAddress(m_hWinSockLib, OS_STRING("inet_addr"));
  436. #else
  437. _hxsocket = (HXSOCKET)GetProcAddress(m_hWinSockLib, OS_STRING("socket"));
  438. _hxclosesocket = (CLOSESOCKET)GetProcAddress(m_hWinSockLib, OS_STRING("closesocket"));
  439. _raWSAIoctl = (WSAIOCTL)GetProcAddress(m_hWinSockLib, OS_STRING("WSAIoctl"));
  440. #endif /* _WINCE */
  441. }
  442.     }
  443. #ifdef _WINCE
  444. if (!_hxWSAStartup ||
  445. !_hxWSACleanup ||
  446. !_pInetAddr)
  447. #else
  448.     if (!_hxsocket ||
  449. !_hxclosesocket ||
  450. !_hxWSAStartup  ||
  451. !_hxWSACleanup  ||
  452. !_raWSAIoctl)
  453. #endif /* _WINCE */
  454.     {
  455. rc = HXR_FAILED;
  456. goto cleanup;
  457.     }
  458.     wVersionRequested = (1 << 8) + 1;
  459.     _hxWSAStartup(wVersionRequested, &wsaData);
  460. #ifndef _WINCE
  461.     s = _hxsocket(AF_INET, SOCK_DGRAM, 0);
  462.     
  463.     if (s == INVALID_SOCKET)
  464.     {
  465. rc = HXR_FAILED;
  466. goto cleanup;
  467.     }
  468.     pInfo = new INTERFACE_INFO[MAX_INTERFACES];
  469.     // get interfaces list
  470.     if (_raWSAIoctl(s, SIO_GET_INTERFACE_LIST, NULL, NULL, pInfo,
  471.     sizeof(INTERFACE_INFO)*MAX_INTERFACES, &ulBytes, NULL, NULL))
  472.     {
  473. rc = HXR_FAILED;
  474. goto cleanup;
  475.     }
  476.     // caculate # of interfaces we have
  477.     iStructures = ulBytes / sizeof(INTERFACE_INFO);
  478.     // iterate through the interface list
  479.     for (iPosition = 0; iPosition < iStructures; iPosition++)
  480.     {
  481. lFlags = pInfo[iPosition].iiFlags;
  482. if (lFlags & IFF_LOOPBACK)
  483. {
  484.     continue;
  485. }
  486. else if ((lFlags & IFF_POINTTOPOINT) && (lFlags & IFF_UP))
  487. {
  488.     type = POINTTOPOINT;
  489. }
  490. else if ((lFlags & IFF_BROADCAST) && (lFlags & IFF_UP))
  491. {
  492.     type = BROADCAST;
  493. }
  494. else
  495. {
  496.     continue;
  497. }
  498. ulNetAddress = ((sockaddr_in*)&(pInfo[iPosition].iiAddress))->sin_addr.s_addr;
  499. ulNetMask = ((sockaddr_in*)&(pInfo[iPosition].iiNetmask))->sin_addr.s_addr;
  500. // ignore the net interface with invalid IP/Mask
  501. if (ulNetAddress == 0 || ulNetMask == 0)
  502. {
  503.     continue;
  504. }
  505. pNIInfo = new NIInfo;
  506. pNIInfo->bActive = TRUE;
  507. pNIInfo->type = type;
  508. pNIInfo->ulNetAddress = ulNetAddress; 
  509. pNIInfo->ulNetMask = ulNetMask;
  510. if (!pNetInterfaceList)
  511. {
  512.     pNetInterfaceList = new CHXSimpleList();
  513. }
  514. pNetInterfaceList->AddTail(pNIInfo);
  515.     }
  516. cleanup:
  517.     if (_hxclosesocket)
  518.     {
  519. _hxclosesocket(s);
  520.     }
  521.     if (_hxWSACleanup)
  522.     {
  523. _hxWSACleanup();
  524.     }
  525.     HX_VECTOR_DELETE(pInfo);
  526. #else
  527. // WinCE does not support Winsock2, yet. Also, it has many variations for registry settings.
  528. // Thus, it is better to use GetAdapterInfo defined in iphlpapi.h.
  529. // Note: This call is supported only in WinCE 3.0 or later.
  530. if (NULL == m_hIPLib)
  531. m_hIPLib = LoadLibrary(OS_STRING("IPHLPAPI.DLL"));
  532. if (m_hIPLib)
  533. _pGetAdaptersInfo = (GETADAPTERSINFO) ::GetProcAddress(m_hIPLib, OS_STRING("GetAdaptersInfo"));
  534. if (NULL == _pGetAdaptersInfo)
  535.     {
  536. rc = HXR_FAILED;
  537. goto cleanup;
  538.     }
  539. // first make a call with ulSize = 0 to get the exact size needed
  540. dwResult = _pGetAdaptersInfo(pAdapterInfo, &ulSize);
  541. if (ERROR_BUFFER_OVERFLOW == dwResult)
  542. {
  543. // allocate right amount of space for adapter info
  544. pAdapterInfo = (PIP_ADAPTER_INFO)(new char[ulSize]);
  545. if (!pAdapterInfo)
  546. {
  547. rc = HXR_OUTOFMEMORY;
  548. goto cleanup;
  549. }
  550. // fill up adapters info
  551. dwResult= _pGetAdaptersInfo(pAdapterInfo, &ulSize);
  552. if (ERROR_SUCCESS != dwResult)
  553. {
  554. rc = HXR_FAILED;
  555. goto cleanup;
  556. }
  557. // step thru the adapters list that we received
  558. while (pAdapterInfo != NULL)
  559. {
  560. if (MIB_IF_TYPE_PPP == pAdapterInfo->Type)
  561. type = POINTTOPOINT;
  562. else if (MIB_IF_TYPE_ETHERNET == pAdapterInfo->Type)
  563. type = BROADCAST;
  564. else
  565. continue;
  566. // step thru all IP addresses for each adapter
  567. pAddrList = &(pAdapterInfo->IpAddressList);
  568. do
  569. {
  570. ulNetAddress = _pInetAddr(pAddrList->IpAddress.String);
  571. ulNetMask = _pInetAddr(pAddrList->IpMask.String);
  572. // ignore the net interface with invalid IP/Mask
  573. if (INADDR_NONE != ulNetAddress && 0 != ulNetAddress && INADDR_NONE != ulNetMask && 0 != ulNetMask)
  574. {
  575. pNIInfo = new NIInfo;
  576. if (!pAdapterInfo)
  577. {
  578. rc = HXR_OUTOFMEMORY;
  579. goto cleanup;
  580. }
  581. pNIInfo->bActive = TRUE;
  582. pNIInfo->type = type;
  583. pNIInfo->ulNetAddress = ulNetAddress; 
  584. pNIInfo->ulNetMask = ulNetMask;
  585. if (!pNetInterfaceList)
  586. {
  587. pNetInterfaceList = new CHXSimpleList();
  588. if (!pAdapterInfo)
  589. {
  590. rc = HXR_OUTOFMEMORY;
  591. goto cleanup;
  592. }
  593. }
  594. pNetInterfaceList->AddTail(pNIInfo);
  595. pAddrList = pAddrList->Next;
  596. }
  597. }while (pAddrList != NULL);
  598. pAdapterInfo = pAdapterInfo->Next;
  599. }
  600. }
  601. else
  602. {
  603. rc = HXR_FAILED;
  604. goto cleanup;
  605. }
  606. cleanup:
  607.     HX_VECTOR_DELETE(pAdapterInfo);
  608.     if (_hxWSACleanup)
  609.     {
  610. _hxWSACleanup();
  611.     }
  612. #endif /* _WINCE */
  613.     return rc;
  614. }
  615. void
  616. HXNetInterface::CheckAddrChange(void)
  617. {
  618.     DWORD dwResult = 0;
  619.     if (WAIT_OBJECT_0 == WaitForSingleObject(m_hAddrChangeEvent, 0))
  620.     {
  621. Reset(m_pNetInterfaceList);
  622. RetrieveNetInterface0(m_pNetInterfaceList);
  623. if (m_pSinkList)
  624. {
  625.     CHXSimpleList::Iterator ndx = m_pSinkList->Begin();
  626.     for (; ndx != m_pSinkList->End(); ++ndx)
  627.     {
  628. IHXNetInterfacesAdviseSink* pSink = (IHXNetInterfacesAdviseSink*) (*ndx);
  629. pSink->NetInterfacesUpdated();
  630.     }
  631. }
  632. #ifdef _WINCE
  633. // Overlapped param is not supported in wince 3.0 in the second param to NotifyAddrChange
  634. if(NO_ERROR == _pNotifyAddrChange(&m_hAddrChangeEvent, NULL))
  635. #else
  636. if (ERROR_IO_PENDING == _pNotifyAddrChange(&m_handle, &m_overLapped))
  637. #endif /* _WINCE */
  638. {
  639.     m_pAddrChangeCallback->m_bIsCallbackPending = TRUE;
  640.     m_pAddrChangeCallback->m_PendingHandle = m_pScheduler->RelativeEnter(m_pAddrChangeCallback, CHECK_ADDR_CHANGE_INTERVAL);
  641. }
  642.     }
  643.     else
  644.     {
  645. m_pAddrChangeCallback->m_bIsCallbackPending = TRUE;
  646. m_pAddrChangeCallback->m_PendingHandle = m_pScheduler->RelativeEnter(m_pAddrChangeCallback, CHECK_ADDR_CHANGE_INTERVAL);
  647.     }
  648.     return;
  649. }
  650. BOOL
  651. HXNetInterface::IsNetInterfaceChanged(void)
  652. {
  653.     BOOL     bResult = FALSE;
  654.     CHXSimpleList*  pTempNetInterfaceList = NULL;
  655.     if (m_pAddrChangeCallback && m_pAddrChangeCallback->m_bIsCallbackPending)
  656.     {
  657. if (WAIT_OBJECT_0 == WaitForSingleObject(m_hAddrChangeEvent, 0))
  658. {
  659.     bResult = TRUE;
  660.     Reset(m_pNetInterfaceList);
  661.     RetrieveNetInterface0(m_pNetInterfaceList);
  662. #ifdef _WINCE
  663. // Overlapped param is not supported in wince 3.0 in the second param to NotifyAddrChange
  664. if(NO_ERROR == _pNotifyAddrChange(&m_hAddrChangeEvent, NULL))
  665. #else
  666.     if (ERROR_IO_PENDING == _pNotifyAddrChange(&m_handle, &m_overLapped))
  667. #endif /* _WINCE */
  668.     {
  669. m_pScheduler->Remove(m_pAddrChangeCallback->m_PendingHandle);
  670. m_pAddrChangeCallback->m_PendingHandle = m_pScheduler->RelativeEnter(m_pAddrChangeCallback, CHECK_ADDR_CHANGE_INTERVAL);
  671.     }
  672. }
  673. goto cleanup;
  674.     }
  675.     else
  676.     {
  677. pTempNetInterfaceList = new CHXSimpleList();
  678. RetrieveNetInterface0(pTempNetInterfaceList);
  679. if (!pTempNetInterfaceList || pTempNetInterfaceList->GetCount() == 0)
  680. {
  681.     // try the generic method
  682.     RetrieveNetInterface1(pTempNetInterfaceList);
  683. }
  684. if (pTempNetInterfaceList && m_pNetInterfaceList)
  685. {
  686.     if (pTempNetInterfaceList->GetCount() != m_pNetInterfaceList->GetCount())
  687.     {
  688. bResult = TRUE;
  689.     }
  690.     else
  691.     {
  692. CHXSimpleList::Iterator ndx0 = pTempNetInterfaceList->Begin();
  693. CHXSimpleList::Iterator ndx1 = m_pNetInterfaceList->Begin();
  694. for (; ndx0 != pTempNetInterfaceList->End() && ndx1 != m_pNetInterfaceList->End(); ++ndx0, ++ndx1)
  695. {
  696.     NIInfo* pInfo0 = (NIInfo*)(*ndx0);
  697.     NIInfo* pInfo1 = (NIInfo*)(*ndx1);
  698.     if (pInfo0->ulNetAddress != pInfo1->ulNetAddress ||
  699. pInfo0->ulNetMask != pInfo1->ulNetMask)
  700.     {
  701. bResult = TRUE;
  702.     }
  703. }
  704.     }
  705. }
  706. else if (pTempNetInterfaceList != m_pNetInterfaceList)
  707. {
  708.     bResult = TRUE;
  709. }
  710. if (bResult)
  711. {
  712.     Reset(m_pNetInterfaceList);
  713.     HX_DELETE(m_pNetInterfaceList);
  714.     m_pNetInterfaceList = pTempNetInterfaceList;
  715. }
  716. else
  717. {
  718.     Reset(pTempNetInterfaceList);
  719.     HX_DELETE(pTempNetInterfaceList);
  720. }
  721.     }
  722. cleanup:
  723.     return bResult;
  724. }
  725. void
  726. HXNetInterface::Reset(CHXSimpleList* pNetInterfaceList)
  727. {
  728.     if (pNetInterfaceList)
  729.     {
  730. while (pNetInterfaceList->GetCount())
  731. {
  732.     NIInfo* pNIInfo = (NIInfo*)pNetInterfaceList->RemoveHead();
  733.     HX_DELETE(pNIInfo);
  734. }
  735.     }
  736. }
  737. void
  738. HXNetInterface::Close(void)
  739. {
  740.     if (m_pAddrChangeCallback)
  741.     {
  742. if (m_pAddrChangeCallback->m_bIsCallbackPending)
  743. {
  744.     m_pAddrChangeCallback->m_bIsCallbackPending = FALSE;
  745.     m_pScheduler->Remove(m_pAddrChangeCallback->m_PendingHandle);
  746.     m_pAddrChangeCallback->m_PendingHandle = 0;
  747. }
  748. HX_RELEASE(m_pAddrChangeCallback);
  749.     }
  750.     if (m_hAddrChangeEvent)
  751.     {
  752. CloseHandle(m_hAddrChangeEvent);
  753. m_hAddrChangeEvent = NULL;
  754.     }
  755.     if (m_handle)
  756.     {
  757. #ifndef _WINCE
  758. CancelIo(m_handle);
  759. #else
  760. CloseHandle(m_handle);
  761. #endif /* _WINCE */
  762. // XXX HP
  763. // Confirmed with MS TS that the caller doesn't need to
  764. // call CloseHandle() on m_handle, it's taken care of by
  765. // the FreeLibrary()
  766. m_handle = NULL;
  767.     }
  768.     Reset(m_pNetInterfaceList);
  769.     HX_DELETE(m_pNetInterfaceList);
  770.     if (m_pSinkList)
  771.     {
  772. HX_ASSERT(m_pSinkList->GetCount() == 0);
  773. CHXSimpleList::Iterator ndx = m_pSinkList->Begin();
  774. for (; ndx != m_pSinkList->End(); ++ndx)
  775. {
  776.     IHXNetInterfacesAdviseSink* pSink = (IHXNetInterfacesAdviseSink*) (*ndx);
  777.     HX_RELEASE(pSink);
  778. }
  779. HX_DELETE(m_pSinkList);
  780.     }
  781.     if (m_hIPLib)
  782.     {
  783. FreeLibrary(m_hIPLib);
  784. m_hIPLib = NULL;
  785.     }
  786.     if (m_hWinSockLib)
  787.     {
  788. FreeLibrary(m_hWinSockLib);
  789. m_hWinSockLib = NULL;
  790.     }
  791.     HX_RELEASE(m_pScheduler);
  792.     HX_RELEASE(m_pContext);
  793. }
  794. AddrChangeCallback::AddrChangeCallback() :
  795.      m_lRefCount (0)
  796.     ,m_pParent (0)
  797.     ,m_PendingHandle (0)
  798.     ,m_bIsCallbackPending (FALSE)
  799. {
  800. }
  801. AddrChangeCallback::~AddrChangeCallback()
  802. {
  803. }
  804. /*
  805.  * IUnknown methods
  806.  */
  807. /////////////////////////////////////////////////////////////////////////
  808. //      Method:
  809. //              IUnknown::QueryInterface
  810. //      Purpose:
  811. //              Implement this to export the interfaces supported by your
  812. //              object.
  813. //
  814. STDMETHODIMP AddrChangeCallback::QueryInterface(REFIID riid, void** ppvObj)
  815. {
  816. QInterfaceList qiList[] =
  817. {
  818. { GET_IIDHANDLE(IID_IUnknown), this },
  819. { GET_IIDHANDLE(IID_IHXCallback), (IHXCallback*) this },
  820. { GET_IIDHANDLE(IID_IHXInterruptSafe), (IHXInterruptSafe*) this },
  821. };
  822.     return QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
  823. }
  824. /////////////////////////////////////////////////////////////////////////
  825. //      Method:
  826. //              IUnknown::AddRef
  827. //      Purpose:
  828. //              Everyone usually implements this the same... feel free to use
  829. //              this implementation.
  830. //
  831. STDMETHODIMP_(ULONG32) AddrChangeCallback::AddRef()
  832. {
  833.     return InterlockedIncrement(&m_lRefCount);
  834. }
  835. /////////////////////////////////////////////////////////////////////////
  836. //      Method:
  837. //              IUnknown::Release
  838. //      Purpose:
  839. //              Everyone usually implements this the same... feel free to use
  840. //              this implementation.
  841. //
  842. STDMETHODIMP_(ULONG32) AddrChangeCallback::Release()
  843. {
  844.     if (InterlockedDecrement(&m_lRefCount) > 0)
  845.     {
  846. return m_lRefCount;
  847.     }
  848.     delete this;
  849.     return 0;
  850. }
  851. STDMETHODIMP AddrChangeCallback::Func(void)
  852. {
  853.     m_PendingHandle         = 0;
  854.     m_bIsCallbackPending    = FALSE;
  855.     if (m_pParent)
  856.     {
  857. m_pParent->CheckAddrChange();
  858.     }
  859.     return HXR_OK;
  860. }
  861. STDMETHODIMP_(BOOL) AddrChangeCallback::IsInterruptSafe()
  862. {
  863.     return FALSE;
  864. }