hxnetif.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:23k
源码类别:

Symbian

开发平台:

C/C++

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