|
|
/*++
Copyright (c) 1999 Microsoft Corporation
Module Name:
info.c
Abstract:
exports GetNetworkInformation routine
--*/
#include <precomp.h>
//
// seems that if WINS addresses not specified, NetBT reports 127.0.0.0 so if
// this value is returned, we won't display them
//
#define LOCAL_WINS_ADDRESS 0x0000007f // 127.0.0.0
#define New(Size) LocalAlloc( LPTR, Size)
#define Delete(Ptr) if( NULL != Ptr ) LocalFree( Ptr )
#define CheckBoolError(Internal) if( FALSE == fSuccess ) {\
(*InternalError) = Internal; Error = GetLastError(); break; }
#define CheckError(Internal) if( NO_ERROR != Error ) {\
(*InternalError) = Internal; break; }
VOID FreeIfInfo( IN OUT PINTERFACE_NETWORK_INFO IfInfo ) { if( NULL == IfInfo ) return; Delete( IfInfo->FriendlyName ); Delete( IfInfo->ConnectionName ); Delete( IfInfo->DhcpClassId ); Delete( IfInfo->IpAddress ); Delete( IfInfo->Ipv6Address ); Delete( IfInfo->IpMask ); Delete( IfInfo->Router ); Delete( IfInfo->WinsServer ); Delete( IfInfo->DnsServer ); Delete( IfInfo->Ipv6DnsServer ); Delete( IfInfo ); }
VOID FreeNetworkInfo( IN OUT PNETWORK_INFO NetInfo ) { DWORD i;
if( NULL == NetInfo ) return; for( i = 0; i < NetInfo->nInterfaces ; i ++ ) { FreeIfInfo( NetInfo->IfInfo[i] ); }
Delete( NetInfo->SuffixSearchList ); Delete( NetInfo ); }
DWORD MapIfType( IN OUT PINTERFACE_NETWORK_INFO IfInfo, IN ULONG IfType ) { DWORD i; DWORD Map[][2] = { IF_TYPE_OTHER, IfTypeOther, IF_TYPE_ETHERNET_CSMACD, IfTypeEthernet, IF_TYPE_ISO88025_TOKENRING, IfTypeTokenring, IF_TYPE_FDDI, IfTypeFddi, IF_TYPE_PPP, IfTypePPP, IF_TYPE_SOFTWARE_LOOPBACK, IfTypeLoopback, IF_TYPE_SLIP, IfTypeSlip, IF_TYPE_TUNNEL, IfTypeTunnel, IF_TYPE_IEEE1394, IfType1394 };
for( i = 0; i < sizeof(Map)/sizeof(Map[0]); i ++ ) { if( Map[i][0] == IfType ) { IfInfo->IfType = Map[i][1]; return NO_ERROR; } }
return ERROR_NOT_FOUND; }
LPWSTR GetProperty( IN HDEVINFO hdi, IN SP_DEVINFO_DATA *deid, IN ULONG Property ) { BOOL fSuccess; ULONG Error, cbSize; LPWSTR RetVal;
cbSize = 0; fSuccess = SetupDiGetDeviceRegistryPropertyW( hdi, deid, Property, NULL, NULL, 0, &cbSize ); if( fSuccess ) { RetVal = LocalAlloc(LPTR, sizeof(WCHAR)); if( NULL == RetVal ) return NULL; (*RetVal) = L'\0'; return RetVal; }
Error = GetLastError(); if( ERROR_INSUFFICIENT_BUFFER != Error ) return NULL;
RetVal = New( cbSize * sizeof(WCHAR) ); if( NULL == RetVal ) return NULL ;
fSuccess = SetupDiGetDeviceRegistryPropertyW( hdi, deid, Property, NULL, (PVOID)RetVal, cbSize, NULL ); if( FALSE == fSuccess ) { Error = GetLastError(); Delete( RetVal ); SetLastError(Error); return NULL; }
return RetVal; }
LPWSTR GetDescriptionFromGuid( IN GUID *Guid ) { WCHAR InstanceIdBuf[1000]; ULONG BufSizeInWChars = sizeof(InstanceIdBuf)/sizeof(WCHAR); HRESULT hr; HDEVINFO hdi; SP_DEVINFO_DATA deid; BOOL fSuccess; ULONG Error; LPWSTR DescrName = NULL;
deid.cbSize = sizeof(SP_DEVINFO_DATA); hr = HrPnpInstanceIdFromGuid(Guid, InstanceIdBuf, BufSizeInWChars); if( !SUCCEEDED(hr) ) { SetLastError( HRESULT_CODE(hr) ); IPCFG_TRACE(IPCFG_TRACE_TCPIP, ("HrPnpInstanceIdFromGuid returns 0x%lx (%d)\n", hr, hr)); return NULL; }
hdi = SetupDiCreateDeviceInfoList(&GUID_DEVCLASS_NET, NULL); if( INVALID_HANDLE_VALUE != hdi ) { fSuccess = SetupDiOpenDeviceInfoW(hdi, InstanceIdBuf, NULL, 0, &deid); if( fSuccess ) { DescrName = GetProperty(hdi, &deid, SPDRP_FRIENDLYNAME); if( NULL == DescrName ) { Error = GetLastError(); if( ERROR_SUCCESS != Error ) { DescrName = GetProperty( hdi, &deid, SPDRP_DEVICEDESC ); if( NULL == DescrName ) { Error = GetLastError(); } else { Error = ERROR_SUCCESS; } } else { //
// Error already set.
//
} } else { //
// We succeeded..
//
Error = ERROR_SUCCESS; } } else { Error = GetLastError(); } SetupDiDestroyDeviceInfoList(hdi); } else { Error = GetLastError(); }
SetLastError(Error); return (ERROR_SUCCESS == Error)?DescrName:NULL; }
LPWSTR GetDescription( IN GUID *Guid, IN LPWSTR GuidString ) { LPWSTR RetVal = GetDescriptionFromGuid(Guid); WCHAR GuidStringBuf[500]; GUID GuidStruct; ULONG Status;
if( NULL != RetVal ) return RetVal;
SetLastError( ERROR_CAN_NOT_COMPLETE ); if( NULL == GuidString ) return NULL; if( wcslen(GuidString)*sizeof(WCHAR) >= sizeof(GuidStringBuf)) { return NULL; } if( GuidString[0] != L'{' ) return NULL;
wcscpy(GuidStringBuf, &GuidString[1]); if( L'}' != GuidStringBuf[wcslen(GuidStringBuf)-1] ) { return NULL; }
GuidStringBuf[wcslen(GuidStringBuf)-1] = L'\0';
Status = UuidFromStringW(GuidStringBuf, &GuidStruct); if( RPC_S_OK != Status ) { SetLastError( Status ); return NULL; }
return GetDescriptionFromGuid(&GuidStruct); }
VOID GetInterfaceGuidAndDeviceName( IN PMIB_IFROW IfRow, IN PIP_INTERFACE_INFO InterfaceInfo, IN PIP_INTERFACE_NAME_INFO IfNameInfo, IN ULONG IfNameCount, OUT GUID *IfGuid, OUT LPWSTR *IfDeviceName ) { DWORD i;
//
// Search interface name info to get the interface guid for
// this interface. Also, search the InterfaceInfo to get the
// devicename for this interface.
//
ZeroMemory( IfGuid, sizeof(*IfGuid) ); for( i = 0; i < IfNameCount ; i ++ ) { if( IfRow->dwIndex != IfNameInfo[i].Index ) continue; (*IfGuid) = IfNameInfo[i].InterfaceGuid; break; }
(*IfDeviceName) = NULL; for( i = 0; i < (DWORD)InterfaceInfo->NumAdapters; i ++ ) { if( InterfaceInfo->Adapter[i].Index != IfRow->dwIndex ) continue; (*IfDeviceName) = InterfaceInfo->Adapter[i].Name + strlen( "\\Device\\Tcpip_" ); break; } }
DWORD MapFriendlyAndConnectionNames( IN OUT PINTERFACE_NETWORK_INFO IfInfo, IN PMIB_IFROW IfRow, IN GUID IfGuid, IN LPWSTR IfDeviceName ) { DWORD Size, Error; WCHAR ConnName[500];
//
// Try to get friendly device name from IfGuid or DeviceName
// or failing both just use the description provided by tcpip
//
IfInfo->FriendlyName = GetDescription( &IfGuid, IfDeviceName ); IPCFG_TRACE(IPCFG_TRACE_TCPIP, ("GetDescription returns %p for %ws\n", IfInfo->FriendlyName, IfDeviceName)); if( NULL == IfInfo->FriendlyName ) {
Size = MultiByteToWideChar( CP_ACP, 0, (LPSTR)IfRow->bDescr, IfRow->dwDescrLen, NULL, 0 ); if( Size == 0 ) return GetLastError();
Size ++; IfInfo->FriendlyName = New( Size * sizeof(WCHAR) ); if (IfInfo->FriendlyName == NULL) return GetLastError();
Size = MultiByteToWideChar( CP_ACP, 0, (LPSTR)IfRow->bDescr, IfRow->dwDescrLen, IfInfo->FriendlyName, Size ); if( 0 == Size ) return GetLastError(); }
IPCFG_TRACE(IPCFG_TRACE_TCPIP, ("\tFriendly Name: %ws\n", IfInfo->FriendlyName));
//
// Now get the connection name. First try with LAN, then RAS
//
Size = sizeof(ConnName)/sizeof(WCHAR); Error = HrLanConnectionNameFromGuidOrPath( NULL, IfDeviceName, ConnName, &Size );
if( NO_ERROR != Error ) { Size = sizeof(ConnName)/sizeof(WCHAR);
IPCFG_TRACE(IPCFG_TRACE_TCPIP, ("HrLanConnectionNameFromGuidOrPath fails 0x%lx(%d)", Error, Error));
Error = NhGetInterfaceNameFromGuid( &IfGuid, ConnName, &Size, FALSE, FALSE ); if( NO_ERROR != Error ) { ConnName[0] = L'\0'; IPCFG_TRACE(IPCFG_TRACE_TCPIP, (" NhGetInterfaceNameFromGuid fails 0x%lx(%d)", Error, Error)); //return Error;
} }
IPCFG_TRACE(IPCFG_TRACE_TCPIP, ("\tConnection Name: %ws\n", ConnName));
IfInfo->ConnectionName = New( sizeof(WCHAR)*(1+wcslen(ConnName))); if( NULL == IfInfo->ConnectionName ) return GetLastError();
wcscpy(IfInfo->ConnectionName, ConnName );
return NO_ERROR; }
DWORD GetMediaStatus( IN LPWSTR IfDeviceName, OUT BOOL *fDisconnected ) { WCHAR NdisDeviceString[512]; UNICODE_STRING NdisDevice; NIC_STATISTICS NdisStats;
wcscpy((LPWSTR)NdisDeviceString, (LPWSTR)L"\\Device\\" ); wcscat((LPWSTR)NdisDeviceString, IfDeviceName );
ZeroMemory(&NdisStats, sizeof(NdisStats)); NdisStats.Size = sizeof(NdisStats);
RtlInitUnicodeString(&NdisDevice, (LPWSTR)NdisDeviceString);
if( FALSE == NdisQueryStatistics(&NdisDevice, &NdisStats) ) { ULONG Error;
//
// Could not get statistics.. use default answer.
//
Error = GetLastError(); if( ERROR_NOT_READY == Error ) { *fDisconnected = TRUE; return NO_ERROR; }
return Error; }
if( NdisStats.MediaState == MEDIA_STATE_DISCONNECTED ) { *fDisconnected = TRUE; } else { *fDisconnected = FALSE; }
return NO_ERROR; }
BOOL IsMediaSenseDisabled( HKEY RegKey ) { LPTSTR regValueName = (LPTSTR)(TEXT ("DisableDHCPMediaSense") ); DWORD regValueData; DWORD regValueDataType; DWORD regValueDataLen = sizeof(DWORD); DWORD Error;
Error = RegQueryValueEx( RegKey, regValueName, NULL, ®ValueDataType, (LPBYTE)®ValueData, ®ValueDataLen);
return (Error == NO_ERROR) && (regValueDataType == REG_DWORD) && (regValueData != 0); }
DWORD OpenRegKey( IN LPCWSTR Device, IN DWORD KeyType, IN DWORD AccessType, OUT HKEY *phKey ) { DWORD Access; WCHAR KeyLoc[256]; LPTSTR TcpipParmLoc = (LPTSTR)(TEXT( "SYSTEM\\CurrentControlSet\\Services" ) TEXT( "\\Tcpip\\Parameters" ) ); LPTSTR TcpipLoc = (LPTSTR)(TEXT( "SYSTEM\\CurrentControlSet\\Services" ) TEXT( "\\Tcpip\\Parameters\\Interfaces\\") ); LPTSTR NbtLoc = (LPTSTR)(TEXT("SYSTEM\\CurrentControlSet\\Services") TEXT("\\Netbt\\Parameters\\Interfaces\\Tcpip_"));
switch (KeyType) { case OpenTcpipParmKey: wcscpy(KeyLoc, TcpipParmLoc); break; case OpenTcpipKey: wcscpy(KeyLoc, TcpipLoc); wcscat(KeyLoc, Device); break; case OpenNbtKey: wcscpy(KeyLoc, NbtLoc); wcscat(KeyLoc, Device); break; }
Access = KEY_READ; if( AccessType & OpenKeyForWrite ) Access |= KEY_WRITE;
return RegOpenKeyEx( HKEY_LOCAL_MACHINE, KeyLoc, 0, Access, phKey ); }
VOID SecondsToAbsolute( OUT FILETIME *SysTime, IN LONGLONG SecondsDifference ) { LONGLONG Diff = SecondsDifference; Diff *= 10000; Diff *= 1000; GetSystemTimeAsFileTime( SysTime ); (*((LONGLONG UNALIGNED64 *)SysTime)) -= Diff; }
DWORD GetDhcpValues( IN PNETWORK_INFO NetInfo, IN OUT PINTERFACE_NETWORK_INFO IfInfo, IN HKEY hKey ) { WCHAR ClassId[200]; LPSTR DhcpServer; DWORD Error, Value, Size, Type; time_t CurrentTime, Obtained, Expires;
//
// First check if dhcp is enabled
//
do { Size = sizeof(Value); Error = RegQueryValueEx( hKey, (LPTSTR)TEXT("EnableDHCP"), NULL, &Type, (LPBYTE)&Value, &Size );
if( NO_ERROR != Error ) return Error; if( Type != REG_DWORD ) return ERROR_INVALID_DATA; IfInfo->EnableDhcp = (Value != 0 );
} while ( 0 );
//
// Now check for class id
//
do { Size = sizeof(ClassId); Error = RegQueryValueExW( hKey, (LPWSTR)L"DhcpClassId", NULL, &Type, (LPBYTE)ClassId, &Size );
if( ERROR_FILE_NOT_FOUND == Error ) { Error = NO_ERROR; Size = 0; } if( NO_ERROR != Error ) return Error;
if( Size == 0 ) break; if( Type != REG_SZ ) return ERROR_INVALID_DATA;
Size = sizeof(WCHAR)*(1+wcslen(ClassId)); IfInfo->DhcpClassId = New( Size ); if( NULL == IfInfo->DhcpClassId ) return GetLastError();
wcscpy(IfInfo->DhcpClassId, ClassId ); } while( 0 );
//
// Now check if autoconfiguration is enabled
//
if( IfInfo->EnableDhcp ) do { Size = sizeof(Value); Error = RegQueryValueEx( hKey, (LPTSTR)TEXT("IPAutoconfigurationEnabled"), NULL, &Type, (LPBYTE)&Value, &Size );
if( ERROR_FILE_NOT_FOUND == Error ) { IfInfo->EnableAutoconfig = NetInfo->GlobalEnableAutoconfig; } else if( NO_ERROR != Error ) return Error; else if( REG_DWORD != Type ) return ERROR_INVALID_DATA; else IfInfo->EnableAutoconfig = (Value != 0 ); } while ( 0 );
//
// Get Dhcp server value
//
if( IfInfo->EnableDhcp ) do { Size = sizeof(ClassId); DhcpServer = (LPSTR)ClassId;
Error = RegQueryValueExA( hKey, "DhcpServer", NULL, &Type, (LPBYTE)DhcpServer, &Size ); if( ERROR_FILE_NOT_FOUND == Error ) break; if( NO_ERROR != Error ) return Error; if( REG_SZ != Type ) return ERROR_INVALID_DATA;
IfInfo->DhcpServer = inet_addr(DhcpServer); } while( 0 );
//
// Now get lease expired and obtained times
//
CurrentTime = time(NULL);
if( IfInfo->EnableDhcp ) do { Size = sizeof(Value); Error = RegQueryValueEx( hKey, (LPTSTR)TEXT("LeaseObtainedTime"), NULL, &Type, (LPBYTE)&Value, &Size );
if( ERROR_FILE_NOT_FOUND == Error ) break; if( NO_ERROR != Error ) return Error; if( REG_DWORD != Type ) return ERROR_INVALID_DATA;
Obtained = (time_t)Value;
SecondsToAbsolute( (FILETIME *)(&IfInfo->LeaseObtainedTime), ((LONGLONG)CurrentTime) - ((LONGLONG)Obtained) );
} while ( 0 );
if( IfInfo->EnableDhcp ) do { Size = sizeof(Value); Error = RegQueryValueEx( hKey, (LPTSTR)TEXT("LeaseTerminatesTime"), NULL, &Type, (LPBYTE)&Value, &Size );
if( ERROR_FILE_NOT_FOUND == Error ) break; if( NO_ERROR != Error ) return Error; if( REG_DWORD != Type ) return ERROR_INVALID_DATA;
Expires = (time_t)Value;
SecondsToAbsolute( (FILETIME *)(&IfInfo->LeaseExpiresTime), ((LONGLONG)CurrentTime) - ((LONGLONG)Expires) ); } while ( 0 );
return NO_ERROR; }
DWORD GetDnsValues( IN OUT PINTERFACE_NETWORK_INFO IfInfo, IN HKEY hKey ) { CHAR *Servers = NULL, *Str; DWORD Error, BufferSize, Size, Type, i, Count, *ThisAddr;
//
// First get DnsSuffix for the interface
//
Size = sizeof(IfInfo->DnsSuffix)/sizeof(WCHAR); Error = RegQueryValueExW( hKey, (LPWSTR)L"Domain", NULL, &Type, (LPBYTE)IfInfo->DnsSuffix, &Size ); if( NO_ERROR != Error ) { if( ERROR_FILE_NOT_FOUND != Error ) return Error;
Size = 0; Type = REG_SZ; }
if( REG_SZ != Type ) return ERROR_INVALID_DATA; if( 0 == Size || 0 == wcslen(IfInfo->DnsSuffix) ) {
Size = sizeof(IfInfo->DnsSuffix)/sizeof(WCHAR); Error = RegQueryValueExW( hKey, (LPWSTR)L"DhcpDomain", NULL, &Type, (LPBYTE)IfInfo->DnsSuffix, &Size ); if( NO_ERROR != Error ) { if( ERROR_FILE_NOT_FOUND != Error ) return Error;
Size = 0; IfInfo->DnsSuffix[0] = L'\0'; } }
//
// Now attempt to read the DnsServers list
//
BufferSize = 800; do { Servers = New( BufferSize ); if( NULL == Servers) return GetLastError();
ZeroMemory(Servers, BufferSize);
Size = BufferSize; Error = RegQueryValueExA( hKey, (LPSTR)"NameServer", NULL, &Type, (LPBYTE)Servers, &Size );
if( NO_ERROR == Error ) { break; }
Delete(Servers); Servers = NULL; if( ERROR_FILE_NOT_FOUND == Error ) { Size = 0; Type = REG_SZ; break; }
if (Error != ERROR_MORE_DATA) { return Error; } BufferSize *= 2; } while(1);
if( REG_SZ != Type ) return ERROR_INVALID_DATA; if( 0 == Size || NULL == Servers || 0 == strlen(Servers) ) { if (Servers) Delete(Servers);
BufferSize = 800; do { Servers = New( BufferSize ); if( NULL == Servers) return GetLastError();
ZeroMemory(Servers, BufferSize);
Size = BufferSize; Error = RegQueryValueExA( hKey, (LPSTR)"DhcpNameServer", NULL, &Type, (LPBYTE)Servers, &Size );
if( NO_ERROR == Error ) { break; }
Delete(Servers); Servers = NULL; if( ERROR_FILE_NOT_FOUND == Error ) { Size = 0; Type = REG_SZ; break; }
if (Error != ERROR_MORE_DATA) { return Error; } BufferSize *= 2; } while(1); }
//
// If there are any DNS Servers, convert them to IPaddr
//
if( 0 != Size && NULL != Servers && strlen(Servers) ) { for( i = 0; i < Size; i ++ ) { if( Servers[i] == ' ' || Servers[i] == ',' || Servers[i] == ';' ) { Servers[i] = '\0'; } } Servers[Size] = '\0';
Count = 0; Str = (LPSTR)Servers; while( strlen(Str) ) { Count ++; Str += strlen(Str); Str ++; }
ThisAddr = New( sizeof(IPV4_ADDRESS) * Count ); if( NULL == ThisAddr ) return GetLastError(); IfInfo->DnsServer = ThisAddr;
for (i = 0, Str = (LPSTR)Servers; *Str != '\0'; Str += strlen(Str) + 1) { IfInfo->DnsServer[i] = inet_addr( Str ); if (IfInfo->DnsServer[i] != 0) i++; } IfInfo->nDnsServers = i; }
if (Servers) { Delete (Servers); }
return NO_ERROR; }
DWORD GetWinsValues( IN OUT PINTERFACE_NETWORK_INFO IfInfo, IN LPCWSTR DeviceName, IN OUT ULONG *NodeType ) { WCHAR NbtDevice[MAX_PATH]; UNICODE_STRING NbtDeviceString; HANDLE h; OBJECT_ATTRIBUTES objAttr; IO_STATUS_BLOCK iosb; NTSTATUS status; tWINS_NODE_INFO NodeInfo; DWORD Count; INT i;
wcscpy(NbtDevice, (LPWSTR)L"\\Device\\NetBT_Tcpip_"); wcscat(NbtDevice, DeviceName);
RtlInitUnicodeString( &NbtDeviceString, (LPWSTR)NbtDevice );
InitializeObjectAttributes( &objAttr, &NbtDeviceString, OBJ_CASE_INSENSITIVE, (HANDLE)NULL, (PSECURITY_DESCRIPTOR)NULL );
status = NtCreateFile( &h, SYNCHRONIZE | GENERIC_EXECUTE, &objAttr, &iosb, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN_IF, 0, NULL, 0 );
if (!NT_SUCCESS(status)) { DWORD w32error = RtlNtStatusToDosError( status );
IfInfo->EnableNbtOverTcpip = FALSE; (*NodeType) = NodeTypeUnknown; return w32error == ERROR_FILE_NOT_FOUND ? NO_ERROR : w32error; }
status = NtDeviceIoControlFile( h, NULL, NULL, NULL, &iosb, IOCTL_NETBT_GET_WINS_ADDR, NULL, 0, (PVOID)&NodeInfo, sizeof(NodeInfo) );
if (status == STATUS_PENDING) { status = NtWaitForSingleObject(h, TRUE, NULL); if (NT_SUCCESS(status)) { status = iosb.Status; } }
NtClose(h);
if (!NT_SUCCESS(status)) { return RtlNtStatusToDosError( status ); }
//
// for some reason, NetBT returns the addresses in low-byte order. We have
// to swap them
//
Count = 0; for( i = 0; i < 2+MAX_NUM_OTHER_NAME_SERVERS; i ++ ) { NodeInfo.AllNameServers[i] = htonl(NodeInfo.AllNameServers[i]); if( LOCAL_WINS_ADDRESS == NodeInfo.AllNameServers[i] || INADDR_ANY == NodeInfo.AllNameServers[i] || INADDR_BROADCAST == NodeInfo.AllNameServers[i] ) { break; }
Count ++; }
for ( i = IfInfo->nIpAddresses-1; i >= 0; i--) if (IfInfo->IpAddress[i] != 0) break;
if (Count > (DWORD)(NodeInfo.NumOtherServers + 2)) { Count = (DWORD)(NodeInfo.NumOtherServers + 2); } if( i != -1 && Count != 0 ) { IfInfo->WinsServer = New( sizeof(IPV4_ADDRESS)*Count ); if( NULL == IfInfo->WinsServer ) return GetLastError();
IfInfo->nWinsServers = Count; for( i = 0; (DWORD)i < Count; i ++ ) { IfInfo->WinsServer[i] = NodeInfo.AllNameServers[i]; } }
IfInfo->EnableNbtOverTcpip = NodeInfo.NetbiosEnabled;
#define NODE_TYPE_BROADCAST 1
#define NODE_TYPE_PEER_PEER 2
#define NODE_TYPE_MIXED 4
#define NODE_TYPE_HYBRID 8
switch( NodeInfo.NodeType ) { case NODE_TYPE_BROADCAST : (*NodeType) = NodeTypeBroadcast; break; case NODE_TYPE_PEER_PEER : (*NodeType) = NodeTypePeerPeer; break; case NODE_TYPE_MIXED : (*NodeType) = NodeTypeMixed; break; case NODE_TYPE_HYBRID : (*NodeType) = NodeTypeHybrid ; break; default: (*NodeType) = NodeTypeUnknown; break; }
return NO_ERROR; }
DWORD GetAddressValues( IN OUT PINTERFACE_NETWORK_INFO IfInfo, IN PMIB_IPADDRTABLE AddrTable, IN ULONG IfIndex ) { DWORD i, Count;
if( NULL == AddrTable ) return ERROR_NOT_FOUND;
Count = 0; for( i = 0; i < AddrTable->dwNumEntries ; i ++ ) { if( AddrTable->table[i].dwIndex == IfIndex ) { Count ++; } }
if( 0 == Count ) return NO_ERROR;
//
// Allocate space for this
//
IfInfo->IpAddress = New( sizeof(IPV4_ADDRESS)*Count ); if( NULL == IfInfo->IpAddress ) return GetLastError();
IfInfo->IpMask = New( sizeof(IPV4_ADDRESS)*Count ); if( NULL == IfInfo->IpMask ) return GetLastError();
IfInfo->nIpAddresses = IfInfo->nIpMasks = Count;
//
// First add the primary addresses
//
Count = 0; for( i = 0; i < AddrTable->dwNumEntries; i ++ ) { if( AddrTable->table[i].dwIndex != IfIndex ) continue; if( !(AddrTable->table[i].wType & MIB_IPADDR_PRIMARY)) continue;
IfInfo->IpAddress[Count] = AddrTable->table[i].dwAddr; IfInfo->IpMask[Count] = AddrTable->table[i].dwMask; Count ++; }
//
// Now add just the non-primary addresses
//
for( i = 0; i < AddrTable->dwNumEntries; i ++ ) { if( AddrTable->table[i].dwIndex != IfIndex ) continue; if(AddrTable->table[i].wType & MIB_IPADDR_PRIMARY) continue;
IfInfo->IpAddress[Count] = AddrTable->table[i].dwAddr; IfInfo->IpMask[Count] = AddrTable->table[i].dwMask; Count ++; }
return NO_ERROR; }
DWORD GetRouteValues( IN OUT PINTERFACE_NETWORK_INFO IfInfo, IN PMIB_IPFORWARDTABLE RouteTable, IN ULONG IfIndex ) { DWORD i, Count;
if( NULL == RouteTable ) return ERROR_NOT_FOUND;
Count = 0; for( i = 0; i < RouteTable->dwNumEntries; i ++ ) { if( RouteTable->table[i].dwForwardIfIndex == IfIndex && INADDR_ANY == RouteTable->table[i].dwForwardDest && MIB_IPROUTE_TYPE_INVALID != RouteTable->table[i].dwForwardType ) { Count ++; } }
if( 0 == Count ) return NO_ERROR;
IfInfo->Router = New( sizeof(IPV4_ADDRESS)*Count); if( NULL == IfInfo->Router ) return GetLastError(); IfInfo->nRouters = Count;
Count = 0; for( i = 0; i < RouteTable->dwNumEntries; i ++ ) { if( RouteTable->table[i].dwForwardIfIndex == IfIndex && INADDR_ANY == RouteTable->table[i].dwForwardDest && MIB_IPROUTE_TYPE_INVALID != RouteTable->table[i].dwForwardType ) {
IfInfo->Router[Count] = RouteTable->table[i].dwForwardNextHop; Count ++; } }
return NO_ERROR; }
VOID IncrementCount( IN IPV6_INFO_ROUTE_TABLE *RTE, IN PVOID Arg1, IN OUT PVOID Count ) { PIP_ADAPTER_ADDRESSES If = (PIP_ADAPTER_ADDRESSES)Arg1;
if ((RTE->This.PrefixLength == 0) && (RTE->This.Neighbor.IF.Index == If->Ipv6IfIndex)) {
(*(ULONG *)Count)++; } }
VOID AddRouter( IN IPV6_INFO_ROUTE_TABLE *RTE, IN PVOID Arg1, IN OUT PVOID Arg2 ) { PIP_ADAPTER_ADDRESSES If = (PIP_ADAPTER_ADDRESSES)Arg1; PINTERFACE_NETWORK_INFO pIfInfo = (PINTERFACE_NETWORK_INFO)Arg2; ULONG Index; LPSOCKADDR_IN6 Addr;
if (RTE->This.PrefixLength != 0) { return; } if (RTE->This.Neighbor.IF.Index != If->Ipv6IfIndex) { return; }
//
// We now have a default router to add to the list.
//
Index = pIfInfo->nIpv6Routers++; Addr = &pIfInfo->Ipv6Router[Index]; Addr->sin6_family = AF_INET6; Addr->sin6_addr = RTE->This.Neighbor.Address; Addr->sin6_port = 0; if (IN6_IS_ADDR_LINKLOCAL(&Addr->sin6_addr)) { Addr->sin6_scope_id = If->ZoneIndices[ScopeLevelLink]; } else if (IN6_IS_ADDR_SITELOCAL(&Addr->sin6_addr)) { Addr->sin6_scope_id = If->ZoneIndices[ScopeLevelSite]; } else { Addr->sin6_scope_id = 0; } }
ULONG ForEachRoute( IN VOID (*Func)(IPV6_INFO_ROUTE_TABLE *, PVOID, PVOID), IN PVOID Arg1, IN OUT PVOID Arg2 ) { IPV6_QUERY_ROUTE_TABLE Query, NextQuery; IPV6_INFO_ROUTE_TABLE RTE; ULONG BytesReturned; static HANDLE Ipv6Handle = INVALID_HANDLE_VALUE;
if (Ipv6Handle == INVALID_HANDLE_VALUE) { //
// Open a handle to the IPv6 device on our first invocation.
// Keep it open until the process terminates, since we'll
// terminate once we've generated the output.
//
Ipv6Handle = CreateFileW(WIN_IPV6_DEVICE_NAME, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, // security attributes
OPEN_EXISTING, 0, // flags & attributes
NULL); // template file
}
NextQuery.Neighbor.IF.Index = 0;
for (;;) { Query = NextQuery;
if (!DeviceIoControl(Ipv6Handle, IOCTL_IPV6_QUERY_ROUTE_TABLE, &Query, sizeof Query, &RTE, sizeof RTE, &BytesReturned, NULL)) { return GetLastError(); }
NextQuery = RTE.Next;
if (Query.Neighbor.IF.Index != 0) {
RTE.This = Query; (*Func)(&RTE, Arg1, Arg2); }
if (NextQuery.Neighbor.IF.Index == 0) break; }
return NO_ERROR; }
VOID AddIpv6PerInterfaceInfo( IN DWORD IfIndex, IN PINTERFACE_NETWORK_INFO pIfInfo, IN PIP_ADAPTER_ADDRESSES IfList ) { PIP_ADAPTER_ADDRESSES If; PIP_ADAPTER_UNICAST_ADDRESS Addr; PIP_ADAPTER_DNS_SERVER_ADDRESS Dns; ULONG Count, BytesReturned; LPSOCKADDR_IN6 SockAddr; IPV6_QUERY_ROUTE_TABLE Query, NextQuery; IPV6_INFO_ROUTE_TABLE RTE;
//
// Find matching entry in the IPv6 interface list.
//
for (If = IfList; If; If = If->Next) { if (IfIndex == If->IfIndex) { break; } }
if ((If == NULL) || (If->Ipv6IfIndex == 0)) { return; }
//
// Append IPv6 unicast addresses.
//
Count = 0; for (Addr = If->FirstUnicastAddress; Addr; Addr = Addr->Next) { if ((Addr->Address.lpSockaddr->sa_family == AF_INET6) && (Addr->DadState >= IpDadStateDeprecated)) { Count++; } } pIfInfo->Ipv6Address = New(Count * sizeof(SOCKADDR_IN6)); if (pIfInfo->Ipv6Address != NULL) { Count = 0; for (Addr = If->FirstUnicastAddress; Addr; Addr = Addr->Next) { if ((Addr->Address.lpSockaddr->sa_family == AF_INET6) && (Addr->DadState >= IpDadStateDeprecated)) { CopyMemory(&pIfInfo->Ipv6Address[Count++], Addr->Address.lpSockaddr, sizeof(SOCKADDR_IN6)); } } pIfInfo->nIpv6Addresses = Count; } else { pIfInfo->nIpv6Addresses = 0; }
//
// Append IPv6 DNS server addresses.
//
Count = 0; for (Dns = If->FirstDnsServerAddress; Dns; Dns = Dns->Next) { if (Dns->Address.lpSockaddr->sa_family == AF_INET6) { Count++; } } pIfInfo->Ipv6DnsServer = New(Count * sizeof(SOCKADDR_IN6)); if (pIfInfo->Ipv6DnsServer != NULL) { Count = 0; for (Dns = If->FirstDnsServerAddress; Dns; Dns = Dns->Next) { if (Dns->Address.lpSockaddr->sa_family == AF_INET6) { CopyMemory(&pIfInfo->Ipv6DnsServer[Count++], Dns->Address.lpSockaddr, sizeof(SOCKADDR_IN6)); } } pIfInfo->nIpv6DnsServers = Count; } else { pIfInfo->nIpv6DnsServers = 0; }
//
// Append IPv6 default router addresses.
//
Count = 0; ForEachRoute(IncrementCount, If, &Count);
pIfInfo->nIpv6Routers = 0; pIfInfo->Ipv6Router = New(Count * sizeof(SOCKADDR_IN6));
if (pIfInfo->Ipv6Router != NULL) { ForEachRoute(AddRouter, If, pIfInfo); } }
DWORD GetPerInterfaceInfo( IN OUT PNETWORK_INFO NetInfo, OUT PINTERFACE_NETWORK_INFO *pIfInfo, IN PMIB_IFROW IfRow, IN PIP_INTERFACE_INFO InterfaceInfo, IN PIP_INTERFACE_NAME_INFO IfNameInfo, IN ULONG IfNameCount, IN PMIB_IPADDRTABLE AddrTable, IN PMIB_IPFORWARDTABLE RouteTable, IN PIP_ADAPTER_ADDRESSES IfList, IN OUT DWORD *InternalError ) { DWORD Error, NodeType; PINTERFACE_NETWORK_INFO IfInfo = New( sizeof(*IfInfo) ); GUID IfGuid; LPWSTR IfDeviceName; HKEY TcpipKey = NULL; HKEY TcpipParmKey = NULL;
if( NULL == IfInfo ) return GetLastError(); (*pIfInfo) = IfInfo; ZeroMemory( &IfGuid, sizeof(IfGuid) ); IfDeviceName = NULL;
GetInterfaceGuidAndDeviceName( IfRow, InterfaceInfo, IfNameInfo, IfNameCount, &IfGuid, &IfDeviceName );
if( NULL == IfDeviceName ) { (*InternalError) = InterfaceUnknownTcpipDevice; return ERROR_NOT_FOUND; } IPCFG_TRACE(IPCFG_TRACE_TCPIP, ("\tDeviceName: %ws\n", IfDeviceName));
wcscpy(IfInfo->DeviceGuidName, IfDeviceName );
Error = OpenRegKey( IfDeviceName, OpenTcpipKey, OpenKeyForRead, &TcpipKey );
if (Error == NO_ERROR) Error = OpenRegKey( IfDeviceName, OpenTcpipParmKey, OpenKeyForRead, &TcpipParmKey );
if( NO_ERROR != Error ) { (*InternalError) = InterfaceOpenTcpipKeyReadFailure; }
while (Error == NO_ERROR) { Error = MapIfType( IfInfo, IfRow->dwType); CheckError( InterfaceUnknownType );
IfInfo->PhysicalNameLength = IfRow->dwPhysAddrLen; CopyMemory( IfInfo->PhysicalName,IfRow->bPhysAddr, IfRow->dwPhysAddrLen );
Error = MapFriendlyAndConnectionNames( IfInfo, IfRow, IfGuid, IfDeviceName ); CheckError( InterfaceUnknownFriendlyName );
if( IfRow->dwType == IF_TYPE_PPP || IfRow->dwType == IF_TYPE_TUNNEL || IsMediaSenseDisabled(TcpipParmKey)) { IfInfo->MediaDisconnected = FALSE; } else { Error = GetMediaStatus( IfDeviceName, &IfInfo->MediaDisconnected ); CheckError( InterfaceUnknownMediaStatus ); }
Error = GetDhcpValues( NetInfo, IfInfo, TcpipKey ); CheckError( InterfaceDhcpValuesFailure );
Error = GetDnsValues( IfInfo, TcpipKey ); CheckError( InterfaceDnsValuesFailure );
Error = GetAddressValues( IfInfo, AddrTable, IfRow->dwIndex );
CheckError( InterfaceAddressValuesFailure );
Error = GetRouteValues( IfInfo, RouteTable, IfRow->dwIndex );
CheckError( InterfaceRouteValuesFailure );
Error = GetWinsValues( IfInfo, IfDeviceName, &NodeType ); CheckError( InterfaceWinsValuesFailure );
//
// Now set the node type as well
//
NetInfo->NodeType = NodeType;
//
// Now write out if autoconfig is active. The way this
// works is to check if dhcp is enabled and dhcpserver
// address is zero or all ones
//
if( IfInfo->EnableDhcp && IfInfo->EnableAutoconfig && IfInfo->nIpAddresses && IfInfo->IpAddress[0] != INADDR_ANY && ( IfInfo->DhcpServer == INADDR_BROADCAST || IfInfo->DhcpServer == INADDR_ANY ) ) { IfInfo->AutoconfigActive = TRUE; }
break; }
if (TcpipKey != NULL) RegCloseKey( TcpipKey );
if (TcpipParmKey != NULL) RegCloseKey( TcpipParmKey );
AddIpv6PerInterfaceInfo( IfRow->dwIndex, IfInfo, IfList );
return Error; }
DWORD GetIpv6OnlyPerInterfaceInfo( OUT PINTERFACE_NETWORK_INFO *pIfInfo, IN PIP_ADAPTER_ADDRESSES If ) { DWORD Error = NO_ERROR; PINTERFACE_NETWORK_INFO IfInfo;
IfInfo = New( sizeof(*IfInfo) ); if( NULL == IfInfo ) return GetLastError(); (*pIfInfo) = IfInfo;
ZeroMemory(IfInfo, sizeof(*IfInfo)); MapIfType(IfInfo, If->IfType);
IfInfo->PhysicalNameLength = If->PhysicalAddressLength; CopyMemory(IfInfo->PhysicalName, If->PhysicalAddress, If->PhysicalAddressLength);
//
// INTERFACE_NETWORK_INFO has weird field names compared to
// IP_ADAPTER_ADDRESSES. The former puts the description in its
// "friendly name" field.
//
IfInfo->FriendlyName = New((wcslen(If->Description) + 1) * sizeof(WCHAR)); if( NULL != IfInfo->FriendlyName ) { wcscpy(IfInfo->FriendlyName, If->Description); } IfInfo->ConnectionName = New((wcslen(If->FriendlyName) + 1) * sizeof(WCHAR)); if( NULL != IfInfo->ConnectionName ) { wcscpy(IfInfo->ConnectionName, If->FriendlyName); }
IfInfo->MediaDisconnected = (If->OperStatus == IfOperStatusLowerLayerDown); IfInfo->EnableAutoconfig = TRUE; wcscpy(IfInfo->DnsSuffix, If->DnsSuffix);
AddIpv6PerInterfaceInfo(0, IfInfo, If);
return Error; }
BOOL GetGlobalTcpipAutoconfigFlag() { HKEY hKey; BOOL rtn; DWORD Error; DWORD Type, Value, Size;
rtn = TRUE;
Error = OpenRegKey( NULL, OpenTcpipParmKey, OpenKeyForRead, &hKey );
if (Error != NO_ERROR) { return TRUE; } Error = RegQueryValueEx( hKey, (LPTSTR)TEXT("IPAutoconfigurationEnabled"), NULL, &Type, (LPBYTE)&Value, &Size );
if (Error == NO_ERROR && Type == REG_DWORD) { rtn = (Value)? TRUE: FALSE; }
RegCloseKey( hKey ); return rtn; }
ULONG CountIpv6OnlyInterfaces( IN PIP_ADAPTER_ADDRESSES IfList ) { PIP_ADAPTER_ADDRESSES If; ULONG Count = 0; for (If = IfList; If; If = If->Next) { if ((If->IfIndex == 0) && (If->Ipv6IfIndex != 0) && (If->IfType != IF_TYPE_SOFTWARE_LOOPBACK) && ((If->IfType != IF_TYPE_TUNNEL) || (If->FirstUnicastAddress != NULL))) { Count++; } }
return Count; }
DWORD GetNetworkInformation( OUT PNETWORK_INFO *pNetInfo, IN OUT DWORD *InternalError ) { DWORD Size, Length, Error, i, j, k, IfNameCount, IfCount; BOOL fSuccess; PNETWORK_INFO NetInfo; MIB_IPSTATS IpStats; FIXED_INFO *FixedInfo; PDNS_SEARCH_INFORMATION SearchInfo; PMIB_IFTABLE pIfTable; PIP_INTERFACE_INFO InterfaceInfo; PIP_INTERFACE_NAME_INFO IfNameInfo; PMIB_IPADDRTABLE AddrTable; PMIB_IPFORWARDTABLE RouteTable; PIP_ADAPTER_ADDRESSES IfList, If; ULONG BufferLength, Flags;
//
// Allocate main structure
//
(*InternalError) = NO_ERROR; (*pNetInfo) = NetInfo = New( sizeof(NETWORK_INFO ) );
if( NULL == NetInfo ) return GetLastError();
Flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST; GetAdaptersAddresses(AF_UNSPEC, Flags, NULL, NULL, &BufferLength);
IfList = (PIP_ADAPTER_ADDRESSES)New(BufferLength); if( NULL == IfList ) return GetLastError();
Error = GetAdaptersAddresses(AF_UNSPEC, Flags, NULL, IfList, &BufferLength); if( Error != NO_ERROR ) { Delete(IfList); return Error; }
SearchInfo = NULL; pIfTable = NULL; InterfaceInfo = NULL; IfNameInfo = NULL; AddrTable = NULL; RouteTable = NULL;
do {
//
// Fill important fields of the main structure
//
Length = MaxHostNameSize; fSuccess = GetComputerNameExW( ComputerNameDnsHostname, NetInfo->HostName, &Length ); CheckBoolError( GlobalHostNameFailure );
Length = MaxDomainNameSize; fSuccess = GetComputerNameExW( ComputerNameDnsDomain, NetInfo->DomainName, &Length ); if( FALSE == fSuccess ) NetInfo->DomainName[0] = L'\0';
Error = GetIpStatistics( &IpStats ); CheckError( GlobalEnableRouterFailure ); NetInfo->EnableRouting = ( IpStats.dwForwarding == MIB_IP_FORWARDING );
//
// EnableProxy and EnableDnsForNetbios both come from the
// registry directly? We will use the GetNetworkParams
// API for this instead.
//
Size = 1000; FixedInfo = NULL; do { Delete(FixedInfo); FixedInfo = (PFIXED_INFO)New(Size); if (NULL == FixedInfo) { Error = ERROR_NOT_ENOUGH_MEMORY; break; }
Length = Size; Error = GetNetworkParams( FixedInfo, &Length ); Size = Length; } while (Error == ERROR_BUFFER_OVERFLOW); CheckError( GlobalEnableDnsFailure );
NetInfo->EnableProxy = FixedInfo->EnableProxy; NetInfo->EnableDnsForNetbios = FixedInfo->EnableDns; Delete(FixedInfo); FixedInfo = NULL;
//
// Now get the suffix search list from Dns
//
SearchInfo = DnsQueryConfigAlloc( DnsConfigSearchInformation, NULL );
if( NULL != SearchInfo ) { Length = 0;
for( i = 0; i < SearchInfo->cNameCount ; i ++ ) { Length += MultiByteToWideChar( CP_UTF8, 0, SearchInfo->aSearchListNames[i], -1, NULL, 0 ); }
if( Length != 0 ) { Length ++; NetInfo->SuffixSearchList = New( sizeof(WCHAR)*Length); if( NULL == NetInfo->SuffixSearchList ) { Error = GetLastError(); break; }
Size = Length; Length = 0; for( i = 0; i < SearchInfo->cNameCount ; i ++ ) { Length += MultiByteToWideChar( CP_UTF8, 0, SearchInfo->aSearchListNames[i], -1, &NetInfo->SuffixSearchList[Length], Size - Length ); } } }
//
// Now go for the interface specific stuff.
//
Error = NhpAllocateAndGetInterfaceInfoFromStack( &IfNameInfo, &IfNameCount, TRUE, GetProcessHeap(), HEAP_NO_SERIALIZE ); CheckError( GlobalIfNameInfoFailure );
#ifdef __IPCFG_ENABLE_LOG__
IPCFG_TRACE(IPCFG_TRACE_TCPIP, ("NhpAllocateAndGetInterfaceInfoFromStack returns 0x%lx (%d) %d Interfaces\n", Error, Error, IfNameCount)); for (i = 0; i < IfNameCount; i++) { LPWSTR DeviceGuid, InterfaceGuid;
DeviceGuid = InterfaceGuid = NULL; UuidToStringW(&IfNameInfo[i].DeviceGuid, &DeviceGuid); UuidToStringW(&IfNameInfo[i].InterfaceGuid, &InterfaceGuid); if (DeviceGuid == NULL || InterfaceGuid == NULL) { if (DeviceGuid) RpcStringFree(&DeviceGuid); if (InterfaceGuid) RpcStringFree(&InterfaceGuid); IPCFG_TRACE(IPCFG_TRACE_TCPIP, ("\t%2d. Index=0x%x DeviceGUID=<fail> InterfaceGUID=<fail>\n", i + 1, IfNameInfo[i].Index)); } else { IPCFG_TRACE(IPCFG_TRACE_TCPIP, ("\t%2d. Index=0x%x\n\t DeviceGUID=%ws\n\t InterfaceGUID=%ws\n", i + 1, IfNameInfo[i].Index, DeviceGuid, InterfaceGuid)); RpcStringFree(&DeviceGuid); RpcStringFree(&InterfaceGuid); } } #endif
Size = 1000; do { Delete( RouteTable ); RouteTable = New( Size );
if( NULL == RouteTable ) { Error = GetLastError(); } else { Error = GetIpForwardTable( RouteTable, &Size, FALSE ); } } while( ERROR_INSUFFICIENT_BUFFER == Error ); #ifdef __IPCFG_ENABLE_LOG__
if (RouteTable) { IPCFG_TRACE(IPCFG_TRACE_TCPIP, ("GetIpForwardTable returns 0x%lx (%d) %d routing entries\n", Error, Error, RouteTable->dwNumEntries)); for (i = 0; i < RouteTable->dwNumEntries; i++) { IPCFG_TRACE(IPCFG_TRACE_TCPIP, ("\t%2d. Index=0x%x Next Hop=%s ", i + 1, RouteTable->table[i].dwForwardIfIndex, inet_ntoa(*(struct in_addr*)&RouteTable->table[i].dwForwardNextHop)));
IPCFG_TRACE(IPCFG_TRACE_TCPIP, ("Mask=%s Type=0x%x\n", inet_ntoa(*(struct in_addr*)&RouteTable->table[i].dwForwardMask), RouteTable->table[i].dwForwardType)); } } #endif
Size = 1000; do { Delete( AddrTable ); AddrTable = New( Size );
if( NULL == AddrTable ) { Error = GetLastError(); } else { Error = GetIpAddrTable( AddrTable, &Size, TRUE ); } } while( ERROR_INSUFFICIENT_BUFFER == Error );
CheckError( GlobalAddrTableFailure ); #ifdef __IPCFG_ENABLE_LOG__
IPCFG_TRACE(IPCFG_TRACE_TCPIP, ("GetIpAddrTable returns 0x%lx (%d) %d IP entries\n", Error, Error, AddrTable->dwNumEntries)); for (i = 0; i < AddrTable->dwNumEntries; i++) { IPCFG_TRACE(IPCFG_TRACE_TCPIP, ("\t%2d. Index=0x%x IP=%s", i + 1, AddrTable->table[i].dwIndex, inet_ntoa(*(struct in_addr*)&AddrTable->table[i].dwAddr))); IPCFG_TRACE(IPCFG_TRACE_TCPIP, (" mask=%s Type=0x%x\n", inet_ntoa(*(struct in_addr*)&AddrTable->table[i].dwMask), AddrTable->table[i].wType)); } #endif
Size = 1000; do { Delete( pIfTable ); pIfTable = New( Size );
if( NULL == pIfTable ) { Error = GetLastError(); } else { Error = GetIfTable( pIfTable, &Size, TRUE ); }
} while( ERROR_INSUFFICIENT_BUFFER == Error );
CheckError( GlobalIfTableFailure ); #ifdef __IPCFG_ENABLE_LOG__
IPCFG_TRACE(IPCFG_TRACE_TCPIP, ("GetIfTable returns 0x%lx (%d) %d Interfaces\n", Error, Error, pIfTable->dwNumEntries)); for( i = 0; i < pIfTable->dwNumEntries; i ++ ) { IPCFG_TRACE(IPCFG_TRACE_TCPIP, ("\t%2d. IfIndex=0x%x Name=%ws IfType=0x%x\n", i + 1, pIfTable->table[i].dwIndex, pIfTable->table[i].wszName, pIfTable->table[i].dwType)); } #endif
Size = 1000; do { Delete( InterfaceInfo ); InterfaceInfo = New( Size );
if( NULL == InterfaceInfo ) { Error = GetLastError(); } else { Error = GetInterfaceInfo( InterfaceInfo, &Size ); } } while( ERROR_INSUFFICIENT_BUFFER == Error );
CheckError( GlobalIfInfoFailure ); #ifdef __IPCFG_ENABLE_LOG__
IPCFG_TRACE(IPCFG_TRACE_TCPIP, ("GetInterfaceInfo returns 0x%lx (%d) %d Interfaces\n", Error, Error, InterfaceInfo->NumAdapters)); for( i = 0; i < (DWORD)InterfaceInfo->NumAdapters; i ++ ) { IPCFG_TRACE(IPCFG_TRACE_TCPIP, ("\t%2d. Index=0x%x\n\t Name=%ws\n", i + 1, InterfaceInfo->Adapter[i].Index, InterfaceInfo->Adapter[i].Name)); } #endif
//
// Get global AutoConfig settings
//
NetInfo->GlobalEnableAutoconfig = GetGlobalTcpipAutoconfigFlag(); IPCFG_TRACE(IPCFG_TRACE_TCPIP, ("GlobalAutoConfigFlag: %d\n", NetInfo->GlobalEnableAutoconfig));
//
// Check for number of interfaces and allocate required
// space in the IfInfo field
//
IfCount = pIfTable->dwNumEntries; IfCount += CountIpv6OnlyInterfaces(IfList); if( IfCount > 1 ) { NetInfo->nInterfaces = IfCount-1; NetInfo->IfInfo = New( NetInfo->nInterfaces * sizeof(PVOID) ); if( NULL == NetInfo->IfInfo ) { Error = GetLastError(); break; }
//
// First add interfaces running IPv4.
//
j = 0; for( i = 0; i < pIfTable->dwNumEntries ; i ++ ) { BOOL fFound = FALSE;
for( k = 0; k < (DWORD)InterfaceInfo->NumAdapters; k ++ ) {
if( pIfTable->table[i].dwIndex == InterfaceInfo->Adapter[k].Index ) { fFound = TRUE; break; }
}
if( fFound && pIfTable->table[i].dwType != IF_TYPE_SOFTWARE_LOOPBACK ) {
IPCFG_TRACE(IPCFG_TRACE_TCPIP, ("\n\n************ GetPerInterfaceInfo for " "IfIndex=0x%x Name=%ws IfType=0x%x\n", pIfTable->table[i].dwIndex, pIfTable->table[i].wszName, pIfTable->table[i].dwType));
Error = GetPerInterfaceInfo( NetInfo, &NetInfo->IfInfo[j], &pIfTable->table[i], InterfaceInfo, IfNameInfo, IfNameCount, AddrTable, RouteTable, IfList, InternalError );
if( NO_ERROR != Error ) break; j ++; } }
//
// Now add any IPv6-only interfaces.
//
for (If = IfList; If; If = If->Next) { if ((If->IfIndex == 0) && (If->Ipv6IfIndex != 0) && (If->IfType != IF_TYPE_SOFTWARE_LOOPBACK) && ((If->IfType != IF_TYPE_TUNNEL) || (If->FirstUnicastAddress != NULL))) { Error = GetIpv6OnlyPerInterfaceInfo(&NetInfo->IfInfo[j], If); if( NO_ERROR != Error ) break; j ++; } }
NetInfo->nInterfaces = j;
if( NO_ERROR != Error ) break; }
} while ( 0 );
Delete( pIfTable ); Delete( InterfaceInfo ); Delete( IfNameInfo ); Delete( AddrTable ); Delete( RouteTable ); Delete( FixedInfo ); Delete( IfList );
if ( SearchInfo ) { DnsFreeConfigStructure( SearchInfo, DnsConfigSearchInformation ); }
return Error; }
|