1 // OneNetAdapterInfo.cpp: implementation of the COneNetAdapterInfo class.
3 //////////////////////////////////////////////////////////////////////
6 #include "SpeedPostEmail.h"
7 #include "NetAdapterInfo.h"
13 static char THIS_FILE
[]=__FILE__
;
17 #define MALLOC( bytes ) ::HeapAlloc( ::GetProcessHeap(), HEAP_ZERO_MEMORY, (bytes) )
18 #define FREE( ptr ) if( ptr ) ::HeapFree( ::GetProcessHeap(), 0, ptr )
19 #define REMALLOC( ptr, bytes ) ::HeapReAlloc( ::GetProcessHeap(), HEAP_ZERO_MEMORY, ptr, bytes )
21 #pragma comment ( lib, "iphlpapi.lib" )
23 //////////////////////////////////////////////////////////////////////
24 // Construction/Destruction
25 //////////////////////////////////////////////////////////////////////
26 COneNetAdapterInfo::COneNetAdapterInfo ( IP_ADAPTER_INFO
*pAdptInfo
)
29 memset ( &m_PhysicalAddress
, 0, sizeof(m_PhysicalAddress
) );
30 m_nPhysicalAddressLength
= 0;
32 memcpy ( &m_AdptInfo
, pAdptInfo
, sizeof(IP_ADAPTER_INFO
) );
35 TRACE ( _T("[%s - %s] initialize failed."), Get_Name(), Get_Desc() );
39 COneNetAdapterInfo::~COneNetAdapterInfo()
45 // ¸ù¾Ý´«ÈëµÄ pAdptInfo ÐÅÏ¢À´»ñÈ¡Ö¸¶¨Íø¿¨µÄ»ù±¾ÐÅÏ¢
47 BOOL
COneNetAdapterInfo::Init ()
49 IP_ADDR_STRING
* pNext
= NULL
;
50 IP_PER_ADAPTER_INFO
* pPerAdapt
= NULL
;
52 DWORD dwErr
= ERROR_SUCCESS
;
53 ASSERT ( m_AdptInfo
.AddressLength
> 0 );
60 m_CurIPInfo
.csIP
.Empty ();
61 m_CurIPInfo
.csSubnet
.Empty ();
62 m_Ary_IP
.RemoveAll ();
63 m_Ary_DNS
.RemoveAll ();
64 m_Ary_Gateway
.RemoveAll ();
67 m_csName
= m_AdptInfo
.AdapterName
;
68 m_csDesc
= m_AdptInfo
.Description
;
71 m_csName
= A2W ( m_AdptInfo
.AdapterName
);
72 m_csDesc
= A2W ( m_AdptInfo
.Description
);
75 // »ñÈ¡µ±Ç°ÕýÔÚʹÓõÄIPµØÖ·
76 if ( m_AdptInfo
.CurrentIpAddress
)
78 m_CurIPInfo
.csIP
= m_AdptInfo
.CurrentIpAddress
->IpAddress
.String
;
79 m_CurIPInfo
.csSubnet
= m_AdptInfo
.CurrentIpAddress
->IpMask
.String
;
83 m_CurIPInfo
.csIP
= _T("0.0.0.0");
84 m_CurIPInfo
.csSubnet
= _T("0.0.0.0");
87 // »ñÈ¡±¾Íø¿¨ÖÐËùÓеÄIPµØÖ·
88 pNext
= &( m_AdptInfo
.IpAddressList
);
91 iphold
.csIP
= pNext
->IpAddress
.String
;
92 iphold
.csSubnet
= pNext
->IpMask
.String
;
93 m_Ary_IP
.Add ( iphold
);
97 // »ñÈ¡±¾Íø¿¨ÖÐËùÓеÄÍø¹ØÐÅÏ¢
98 pNext
= &( m_AdptInfo
.GatewayList
);
101 m_Ary_Gateway
.Add ( A2W( pNext
->IpAddress
.String
));
105 // »ñÈ¡±¾Íø¿¨ÖÐËùÓÐµÄ DNS
106 dwErr
= ::GetPerAdapterInfo ( m_AdptInfo
.Index
, pPerAdapt
, &ulLen
);
107 if( dwErr
== ERROR_BUFFER_OVERFLOW
)
109 pPerAdapt
= ( IP_PER_ADAPTER_INFO
* ) MALLOC( ulLen
);
110 dwErr
= ::GetPerAdapterInfo( m_AdptInfo
.Index
, pPerAdapt
, &ulLen
);
112 // if we succeed than we need to drop into our loop
113 // and fill the dns array will all available IP
115 if( dwErr
== ERROR_SUCCESS
)
117 pNext
= &( pPerAdapt
->DnsServerList
);
120 m_Ary_DNS
.Add( A2W( pNext
->IpAddress
.String
) );
126 // this is done outside the dwErr == ERROR_SUCCES just in case. the macro
127 // uses NULL pointer checking so it is ok if pPerAdapt was never allocated.
135 // ÊÍ·Å»òˢб¾Íø¿¨µÄIPµØÖ·
137 BOOL
COneNetAdapterInfo::RenewReleaseIP( Func_OperateIP func
)
139 IP_INTERFACE_INFO
* pInfo
= NULL
;
142 int nNumInterfaces
= 0;
144 DWORD dwErr
= ERROR_SUCCESS
;
146 dwErr
= ::GetInterfaceInfo ( pInfo
, &ulLen
);
147 if( dwErr
== ERROR_INSUFFICIENT_BUFFER
)
149 pInfo
= ( IP_INTERFACE_INFO
* ) MALLOC( ulLen
);
150 dwErr
= ::GetInterfaceInfo ( pInfo
, &ulLen
);
152 if( dwErr
!= ERROR_SUCCESS
)
158 // we can assume from here out that we have a valid array
159 // of IP_INTERFACE_INFO structures due to the error
160 // checking one above.
161 nNumInterfaces
= ulLen
/ sizeof( IP_INTERFACE_INFO
);
162 for( nCnt
= 0; nCnt
< nNumInterfaces
; nCnt
++ )
164 if( pInfo
[ nCnt
].Adapter
[ 0 ].Index
== m_AdptInfo
.Index
)
166 dwErr
= func( &pInfo
[ nCnt
].Adapter
[ 0 ] );
168 // free all used memory since we don't need it any more.
171 bDidIt
= ( dwErr
== NO_ERROR
);
183 ////////////////////////////////////////////////////////////
185 // Releases the addresses held by this adapter.
186 ////////////////////////////////////////////////////////////
187 BOOL
COneNetAdapterInfo::ReleaseIP()
189 return RenewReleaseIP ( ::IpReleaseAddress
);
192 ////////////////////////////////////////////////////////////
194 // Renews the address being held by this adapter.
195 ////////////////////////////////////////////////////////////
196 BOOL
COneNetAdapterInfo::RenewIP()
198 return RenewReleaseIP ( ::IpRenewAddress
);
201 CString
COneNetAdapterInfo::GetAdapterTypeString ()
203 UINT nType
= m_AdptInfo
.Type
;
204 CString csType
= _T("");
207 case MIB_IF_TYPE_OTHER
: csType
= _T("Other"); break;
208 case MIB_IF_TYPE_ETHERNET
: csType
= _T("Ethernet"); break;
209 case MIB_IF_TYPE_TOKENRING
: csType
= _T("Token Ring"); break;
210 case MIB_IF_TYPE_FDDI
: csType
= _T("FDDI"); break;
211 case MIB_IF_TYPE_PPP
: csType
= _T("PPP"); break;
212 case MIB_IF_TYPE_LOOPBACK
: csType
= _T("Loopback"); break;
213 case MIB_IF_TYPE_SLIP
: csType
= _T("SLIP"); break;
214 default: csType
= _T("Invalid Adapter Type"); break;
220 time_t COneNetAdapterInfo::Get_LeaseObtained() const { return m_AdptInfo
.LeaseObtained
; }
221 time_t COneNetAdapterInfo::Get_LeaseExpired() const { return m_AdptInfo
.LeaseExpires
; }
222 int COneNetAdapterInfo::Get_IPCount() const { return (int)m_Ary_IP
.GetSize(); }
223 int COneNetAdapterInfo::Get_DNSCount() const { return (int)m_Ary_DNS
.GetSize(); }
224 CString
COneNetAdapterInfo::Get_CurrentIP() const { return m_CurIPInfo
.csIP
; }
225 BOOL
COneNetAdapterInfo::Is_DHCP_Used() const { return m_AdptInfo
.DhcpEnabled
; }
226 CString
COneNetAdapterInfo::Get_DHCPAddr() const { return m_AdptInfo
.DhcpServer
.IpAddress
.String
; }
227 BOOL
COneNetAdapterInfo::Is_Wins_Used() const { return m_AdptInfo
.HaveWins
; }
228 CString
COneNetAdapterInfo::Get_PrimaryWinsServer() const { return m_AdptInfo
.PrimaryWinsServer
.IpAddress
.String
; }
229 CString
COneNetAdapterInfo::Get_SecondaryWinsServer() const { return m_AdptInfo
.SecondaryWinsServer
.IpAddress
.String
; }
230 int COneNetAdapterInfo::Get_GatewayCount() const { return m_Ary_Gateway
.GetSize(); }
231 DWORD
COneNetAdapterInfo::Get_AdapterIndex() const { return m_AdptInfo
.Index
; }
232 UINT
COneNetAdapterInfo::Get_AdapterType() const { return m_AdptInfo
.Type
; }
234 CString
COneNetAdapterInfo::Get_IPAddr ( int nIndex
) const
236 CString csAddr
= _T("");
237 if ( nIndex
>= 0 && nIndex
< m_Ary_IP
.GetSize() )
239 csAddr
= m_Ary_IP
.GetAt(nIndex
).csIP
;
245 CString
COneNetAdapterInfo::Get_Subnet ( int nIndex
) const
247 CString csAddr
= _T("");
248 if ( nIndex
>= 0 && nIndex
< m_Ary_IP
.GetSize() )
250 csAddr
= m_Ary_IP
.GetAt(nIndex
).csSubnet
;
256 CString
COneNetAdapterInfo::Get_DNSAddr ( int nIndex
) const
258 CString csAddr
= _T("");
259 if ( nIndex
>= 0 && nIndex
< m_Ary_DNS
.GetSize() )
261 csAddr
= m_Ary_DNS
.GetAt(nIndex
);
267 CString
COneNetAdapterInfo::Get_GatewayAddr ( int nIndex
) const
269 CString csAddr
= _T("");
270 if ( nIndex
>= 0 && nIndex
< m_Ary_Gateway
.GetSize() )
272 csAddr
= m_Ary_Gateway
.GetAt(nIndex
);
278 void COneNetAdapterInfo::Set_PhysicalAddress ( int nPhysicalAddressLength
, BYTE
*pPhysicalAddress
)
280 if ( !pPhysicalAddress
) return;
281 m_nPhysicalAddressLength
= __min(nPhysicalAddressLength
,sizeof(m_PhysicalAddress
));
282 memcpy ( m_PhysicalAddress
, pPhysicalAddress
, m_nPhysicalAddressLength
);
285 //////////////////////////////////////////////////////////////////////
286 // Construction/Destruction
287 //////////////////////////////////////////////////////////////////////
289 CNetAdapterInfo::CNetAdapterInfo ()
293 CNetAdapterInfo::~CNetAdapterInfo()
295 DeleteAllNetAdapterInfo ();
298 void CNetAdapterInfo::DeleteAllNetAdapterInfo()
300 for ( int i
=0; i
<m_Ary_NetAdapterInfo
.GetSize(); i
++ )
302 COneNetAdapterInfo
*pOneNetAdapterInfo
= (COneNetAdapterInfo
*)m_Ary_NetAdapterInfo
.GetAt(i
);
303 if ( pOneNetAdapterInfo
) delete pOneNetAdapterInfo
;
305 m_Ary_NetAdapterInfo
.RemoveAll ();
310 // return : ------------------------------------------------------------
312 // >=0 - ÍøÂçÊÊÅäÆ÷ÊýÁ¿
314 int CNetAdapterInfo::EnumNetworkAdapters ()
316 DeleteAllNetAdapterInfo ();
318 IP_ADAPTER_INFO
* pAdptInfo
= NULL
;
319 IP_ADAPTER_INFO
* pNextAd
= NULL
;
323 DWORD dwError
= ::GetAdaptersInfo ( pAdptInfo
, &ulLen
);
324 if( dwError
!= ERROR_BUFFER_OVERFLOW
) return -1;
325 pAdptInfo
= ( IP_ADAPTER_INFO
* )MALLOC ( ulLen
);
326 dwError
= ::GetAdaptersInfo( pAdptInfo
, &ulLen
);
327 if ( dwError
!= ERROR_SUCCESS
) return -1;
332 COneNetAdapterInfo
*pOneNetAdapterInfo
= new COneNetAdapterInfo ( pNextAd
);
333 if ( pOneNetAdapterInfo
)
335 m_Ary_NetAdapterInfo
.Add ( pOneNetAdapterInfo
);
338 pNextAd
= pNextAd
->Next
;
341 // free any memory we allocated from the heap before
342 // exit. we wouldn't wanna leave memory leaks now would we? ;p
348 COneNetAdapterInfo
* CNetAdapterInfo::Get_OneNetAdapterInfo ( int nIndex
)
350 if ( nIndex
< 0 || nIndex
>= m_Ary_NetAdapterInfo
.GetSize() )
356 return (COneNetAdapterInfo
*)m_Ary_NetAdapterInfo
.GetAt(nIndex
);
359 COneNetAdapterInfo
* CNetAdapterInfo::Get_OneNetAdapterInfo ( DWORD dwIndex
)
361 for ( int i
=0; i
<m_Ary_NetAdapterInfo
.GetSize(); i
++ )
363 COneNetAdapterInfo
*pOneNetAdapterInfo
= (COneNetAdapterInfo
*)m_Ary_NetAdapterInfo
.GetAt(i
);
364 if ( pOneNetAdapterInfo
&& pOneNetAdapterInfo
->Get_AdapterIndex() == dwIndex
)
365 return pOneNetAdapterInfo
;
371 void CNetAdapterInfo::Refresh ()
373 DeleteAllNetAdapterInfo ();
374 EnumNetworkAdapters ();
375 GetAdapterAddress ();
379 // »ñÈ¡Íø¿¨µÄµØÖ·ÐÅÏ¢£¬Ö÷ÒªÊÇMACµØÖ·
381 BOOL
CNetAdapterInfo::GetAdapterAddress ()
389 // Set the flags to pass to GetAdaptersAddresses
390 ULONG flags
= GAA_FLAG_INCLUDE_PREFIX
;
392 // default to unspecified address family (both)
393 // AF_INET for IPv4, AF_INET6 for IPv6
394 ULONG family
= AF_UNSPEC
;
396 LPVOID lpMsgBuf
= NULL
;
398 PIP_ADAPTER_ADDRESSES pAddresses
= NULL
;
401 PIP_ADAPTER_ADDRESSES pCurrAddresses
= NULL
;
402 PIP_ADAPTER_UNICAST_ADDRESS pUnicast
= NULL
;
403 PIP_ADAPTER_ANYCAST_ADDRESS pAnycast
= NULL
;
404 PIP_ADAPTER_MULTICAST_ADDRESS pMulticast
= NULL
;
405 IP_ADAPTER_DNS_SERVER_ADDRESS
*pDnServer
= NULL
;
406 IP_ADAPTER_PREFIX
*pPrefix
= NULL
;
408 outBufLen
= sizeof (IP_ADAPTER_ADDRESSES
);
409 pAddresses
= (IP_ADAPTER_ADDRESSES
*) MALLOC(outBufLen
);
410 if (pAddresses
== NULL
) return FALSE
;
412 // Make an initial call to GetAdaptersAddresses to get the
413 // size needed into the outBufLen variable
414 if ( ::GetAdaptersAddresses ( family
, flags
, NULL
, pAddresses
, &outBufLen
) == ERROR_BUFFER_OVERFLOW
)
417 pAddresses
= (IP_ADAPTER_ADDRESSES
*) MALLOC(outBufLen
);
419 if (pAddresses
== NULL
) return FALSE
;
421 // Make a second call to GetAdapters Addresses to get the
422 // actual data we want
424 TRACE ( _T("Memory allocated for GetAdapterAddresses = %d bytes\n"), outBufLen
);
425 TRACE ( _T("Calling GetAdaptersAddresses function with family = " ) );
426 if (family
== AF_INET
)
427 TRACE(_T("AF_INET\n"));
428 if (family
== AF_INET6
)
429 TRACE(_T("AF_INET6\n"));
430 if (family
== AF_UNSPEC
)
431 TRACE(_T("AF_UNSPEC\n\n"));
433 dwRetVal
= GetAdaptersAddresses ( family
, flags
, NULL
, pAddresses
, &outBufLen
);
435 if ( dwRetVal
== NO_ERROR
)
437 // If successful, output some information from the data we received
438 pCurrAddresses
= pAddresses
;
439 while (pCurrAddresses
)
441 TRACE(_T("\tLength of the IP_ADAPTER_ADDRESS struct: %ld\n"),
442 pCurrAddresses
->Length
);
443 TRACE(_T("\tIfIndex (IPv4 interface): %u\n"), pCurrAddresses
->IfIndex
);
444 TRACE(_T("\tAdapter name: %s\n"), pCurrAddresses
->AdapterName
);
446 pUnicast
= pCurrAddresses
->FirstUnicastAddress
;
447 if (pUnicast
!= NULL
)
449 for (i
= 0; pUnicast
!= NULL
; i
++)
450 pUnicast
= pUnicast
->Next
;
451 TRACE(_T("\tNumber of Unicast Addresses: %d\n"), i
);
455 TRACE(_T("\tNo Unicast Addresses\n"));
458 pAnycast
= pCurrAddresses
->FirstAnycastAddress
;
461 for (i
= 0; pAnycast
!= NULL
; i
++)
462 pAnycast
= pAnycast
->Next
;
463 TRACE(_T("\tNumber of Anycast Addresses: %d\n"), i
);
467 TRACE(_T("\tNo Anycast Addresses\n"));
470 pMulticast
= pCurrAddresses
->FirstMulticastAddress
;
473 for (i
= 0; pMulticast
!= NULL
; i
++)
474 pMulticast
= pMulticast
->Next
;
475 TRACE(_T("\tNumber of Multicast Addresses: %d\n"), i
);
479 TRACE(_T("\tNo Multicast Addresses\n"));
482 pDnServer
= pCurrAddresses
->FirstDnsServerAddress
;
485 for (i
= 0; pDnServer
!= NULL
; i
++)
486 pDnServer
= pDnServer
->Next
;
487 TRACE(_T("\tNumber of DNS Server Addresses: %d\n"), i
);
491 TRACE(_T("\tNo DNS Server Addresses\n"));
494 TRACE(_T("\tDNS Suffix: %wS\n"), pCurrAddresses
->DnsSuffix
);
495 TRACE(_T("\tDescription: %wS\n"), pCurrAddresses
->Description
);
496 TRACE(_T("\tFriendly name: %wS\n"), pCurrAddresses
->FriendlyName
);
498 if (pCurrAddresses
->PhysicalAddressLength
!= 0)
500 TRACE(_T("\tPhysical address: "));
501 for (i
= 0; i
< (int) pCurrAddresses
->PhysicalAddressLength
; i
++)
503 if ( i
== (int)(pCurrAddresses
->PhysicalAddressLength
- 1))
504 TRACE(_T("%.2X\n"), (int) pCurrAddresses
->PhysicalAddress
[i
]);
506 TRACE(_T("%.2X-"), (int) pCurrAddresses
->PhysicalAddress
[i
]);
509 COneNetAdapterInfo
* pNetAdapterInfo
= Get_OneNetAdapterInfo ( pCurrAddresses
->IfIndex
);
510 if ( pNetAdapterInfo
)
512 pNetAdapterInfo
->Set_PhysicalAddress ( pCurrAddresses
->PhysicalAddressLength
, pCurrAddresses
->PhysicalAddress
);
515 TRACE(_T("\tFlags: %ld\n"), pCurrAddresses
->Flags
);
516 TRACE(_T("\tMtu: %lu\n"), pCurrAddresses
->Mtu
);
517 TRACE(_T("\tIfType: %ld\n"), pCurrAddresses
->IfType
);
518 TRACE(_T("\tOperStatus: %ld\n"), pCurrAddresses
->OperStatus
);
519 TRACE(_T("\tIpv6IfIndex (IPv6 interface): %u\n"),
520 pCurrAddresses
->Ipv6IfIndex
);
521 TRACE(_T("\tZoneIndices (hex): "));
522 for (i
= 0; i
< 16; i
++)
523 TRACE(_T("%lx "), pCurrAddresses
->ZoneIndices
[i
]);
526 pPrefix
= pCurrAddresses
->FirstPrefix
;
529 for (i
= 0; pPrefix
!= NULL
; i
++)
530 pPrefix
= pPrefix
->Next
;
531 TRACE(_T("\tNumber of IP Adapter Prefix entries: %d\n"), i
);
535 TRACE(_T("\tNumber of IP Adapter Prefix entries: 0\n"));
540 pCurrAddresses
= pCurrAddresses
->Next
;
546 TRACE(_T("Call to GetAdaptersAddresses failed with error: %d\n"), dwRetVal
);
547 if (dwRetVal
== ERROR_NO_DATA
)
549 TRACE(_T("\tNo addresses were found for the requested parameters\n"));
553 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
| FORMAT_MESSAGE_IGNORE_INSERTS
, NULL
, dwRetVal
, MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
), // Default language
554 (LPTSTR
) & lpMsgBuf
, 0, NULL
))
556 TRACE(_T("\tError: %s"), lpMsgBuf
);
568 CString
MacAddress2String ( int nPhysicalAddressLength
, BYTE
*pPhysicalAddress
)
570 ASSERT ( nPhysicalAddressLength
>= 6 );
571 AfxIsValidAddress(pPhysicalAddress
,nPhysicalAddressLength
,TRUE
);
572 CString csMacAddress
, csOneCell
;
573 for ( int i
=0; i
<nPhysicalAddressLength
; i
++ )
575 csOneCell
.Format ( _T("%.2X"), (int)pPhysicalAddress
[i
] );
576 if ( !csMacAddress
.IsEmpty() ) csMacAddress
+= _T("-");
577 csMacAddress
+= csOneCell
;