/*++ Copyright (c) 1999 Microsoft Corporation Module Name: info.c Abstract: exports GetNetworkInformation routine --*/ #include // // 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= InterfaceGUID=\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; }