Page 1 of 1

[WinAPI] IP Helper functions

Posted: 15 Jan 2020, 03:10
by jNizM
IP Helper (WinAPI)
Internet Protocol Helper (IP Helper) assists network administration of the local computer by enabling applications to retrieve information about the network configuration of the local computer, and to modify that configuration.

Functions:
> GetAdaptersInfo
> GetNetworkParams

more functions coming soon

Re: [WinAPI] IP Helper functions

Posted: 15 Jan 2020, 03:11
by jNizM
GetAdaptersInfo function (msdn)

Code: Select all

; ===============================================================================================================================
; The GetAdaptersInfo function retrieves adapter information for the local computer.
; https://docs.microsoft.com/en-us/windows/win32/api/iphlpapi/nf-iphlpapi-getadaptersinfo
; ===============================================================================================================================

GetAdaptersInfo()
{
	static ERROR_SUCCESS                  := 0
	static ERROR_BUFFER_OVERFLOW          := 111
	static MAX_ADAPTER_NAME_LENGTH        := 256
	static MAX_ADAPTER_DESCRIPTION_LENGTH := 128
	static MAX_ADAPTER_ADDRESS_LENGTH     := 8
	static MIB_IF_TYPE := { 1: "OTHER", 6: "ETHERNET", 9: "ISO88025_TOKENRING", 23: "PPP", 24: "LOOPBACK", 28: "SLIP", 71: "IEEE80211" }

	if (DllCall("iphlpapi\GetAdaptersInfo", "ptr", 0, "uint*", size) = ERROR_BUFFER_OVERFLOW)
	{
		VarSetCapacity(buf, size, 0)
		if (DllCall("iphlpapi\GetAdaptersInfo", "ptr", &buf, "uint*", size) = ERROR_SUCCESS)
		{
			addr := &buf, IP_ADAPTER_INFO := []
			while (addr)
			{
				offset := A_PtrSize

				IP_ADAPTER_INFO[A_Index, "ComboIndex"]          := NumGet(addr + offset, "uint")                                   , offset += 4
				IP_ADAPTER_INFO[A_Index, "AdapterName"]         := StrGet(addr + offset, MAX_ADAPTER_NAME_LENGTH + 4, "cp0")       , offset += MAX_ADAPTER_NAME_LENGTH + 4
				IP_ADAPTER_INFO[A_Index, "Description"]         := StrGet(addr + offset, MAX_ADAPTER_DESCRIPTION_LENGTH + 4, "cp0"), offset += MAX_ADAPTER_DESCRIPTION_LENGTH + 4
				ADAPTER_ADDRESS_LENGTH                          := NumGet(addr + offset, "uint")                                   , offset += 4
				loop % ADAPTER_ADDRESS_LENGTH
					ADAPTER_ADDRESS .= Format("{:02X}",            NumGet(addr + offset, A_Index - 1, "uchar")) "-"
				IP_ADAPTER_INFO[A_Index, "Address"]             := SubStr(ADAPTER_ADDRESS, 1, -1), ADAPTER_ADDRESS := ""           , offset += MAX_ADAPTER_ADDRESS_LENGTH
				IP_ADAPTER_INFO[A_Index, "Index"]               := NumGet(addr + offset, "uint")                                   , offset += 4
				IP_ADAPTER_INFO[A_Index, "Type"]                := MIB_IF_TYPE[NumGet(addr + offset, "uint")]                      , offset += 4
				IP_ADAPTER_INFO[A_Index, "DhcpEnabled"]         := NumGet(addr + offset, "uint")                                   , offset += A_PtrSize
				PIP_ADDR_STRING                                 := NumGet(addr + offset, A_PtrSize, "uptr")                        , offset += A_PtrSize
				IP_ADAPTER_INFO[A_Index, "IpAddressList"]       := StrGet(addr + offset + A_PtrSize, "cp0")
				IP_ADAPTER_INFO[A_Index, "IpMaskList"]          := StrGet(addr + offset + A_PtrSize + 16, "cp0")                   , offset += A_PtrSize + 32 + A_PtrSize
				IP_ADAPTER_INFO[A_Index, "GatewayList"]         := StrGet(addr + offset + A_PtrSize, "cp0")                        , offset += A_PtrSize + 32 + A_PtrSize
				IP_ADAPTER_INFO[A_Index, "DhcpServer"]          := StrGet(addr + offset + A_PtrSize, "cp0")                        , offset += A_PtrSize + 32 + A_PtrSize
				IP_ADAPTER_INFO[A_Index, "HaveWins"]            := NumGet(addr + offset, "int")                                    , offset += A_PtrSize
				IP_ADAPTER_INFO[A_Index, "PrimaryWinsServer"]   := StrGet(addr + offset + A_PtrSize, "cp0")                        , offset += A_PtrSize + 32 + A_PtrSize
				IP_ADAPTER_INFO[A_Index, "SecondaryWinsServer"] := StrGet(addr + offset + A_PtrSize, "cp0")                        , offset += A_PtrSize + 32 + A_PtrSize
				IP_ADAPTER_INFO[A_Index, "LeaseObtained"]       := ConvertUnixTime(NumGet(addr + offset, "int"))                   , offset += A_PtrSize
				IP_ADAPTER_INFO[A_Index, "LeaseExpires"]        := ConvertUnixTime(NumGet(addr + offset, "int"))

				addr := NumGet(addr + 0, "uptr")
			}
			return IP_ADAPTER_INFO
		}
	}
	return ""
}

ConvertUnixTime(value)
{
	unix := 1970
	unix += value, s
	FormatTime, unix, % unix, yyyy-MM-dd HH:mm:ss
	return unix
}
Example

Code: Select all

GetAdaptersInfo := GetAdaptersInfo()
for i, v in GetAdaptersInfo {
	for k, v in GetAdaptersInfo[i]
		output .= k ": " v "`n"
	MsgBox % output
	output := ""
}

Re: [WinAPI] IP Helper functions

Posted: 15 Jan 2020, 03:15
by jNizM
GetNetworkParams function (msdn)

Code: Select all

; ===============================================================================================================================
; The GetNetworkParams function retrieves network parameters for the local computer.
; https://docs.microsoft.com/en-us/windows/win32/api/iphlpapi/nf-iphlpapi-getnetworkparams
; ===============================================================================================================================

GetNetworkParams()
{
	static ERROR_SUCCESS         := 0
	static ERROR_BUFFER_OVERFLOW := 111
	static MAX_HOSTNAME_LEN      := 128
	static MAX_DOMAIN_NAME_LEN   := 128
	static MAX_SCOPE_ID_LEN      := 256
	static NODETYPE              := { 1: "BROADCAST", 2: "PEER_TO_PEER", 4: "MIXED", 8: "HYBRID" }

	if (DllCall("iphlpapi\GetNetworkParams", "ptr", 0, "uint*", size) = ERROR_BUFFER_OVERFLOW)
	{
		VarSetCapacity(buf, size, 0)
		if (DllCall("iphlpapi\GetNetworkParams", "ptr", &buf, "uint*", size) = ERROR_SUCCESS)
		{
			addr := &buf, offset := 0, FIXED_INFO := []

			FIXED_INFO["HostName"]         := StrGet(addr + offset, MAX_HOSTNAME_LEN + 4, "cp0")   , offset += MAX_HOSTNAME_LEN + 4
			FIXED_INFO["DomainName"]       := StrGet(addr + offset, MAX_DOMAIN_NAME_LEN + 4, "cp0"), offset += MAX_DOMAIN_NAME_LEN + 4
			PIP_ADDR_STRING                := NumGet(addr + offset, A_PtrSize, "uptr")             , offset += A_PtrSize
			IP_ADDR_STRING                 := NumGet(addr + offset, "uptr")
			while (IP_ADDR_STRING)
			{
				FIXED_INFO["DnsServerList", "IpAddress", A_Index + 1] := StrGet(IP_ADDR_STRING + A_PtrSize,     "cp0")
				FIXED_INFO["DnsServerList", "IpMask",    A_Index + 1] := StrGet(IP_ADDR_STRING + A_PtrSize * 3, "cp0")
				IP_ADDR_STRING                                        := NumGet(IP_ADDR_STRING + 0, "uptr")
			}
			FIXED_INFO["DnsServerList", "IpAddress", 1] := StrGet(addr + offset + A_PtrSize, "cp0"), offset += A_PtrSize * 2
			FIXED_INFO["DnsServerList", "IpMask", 1]    := StrGet(addr + offset + A_PtrSize, "cp0"), offset += A_PtrSize * 4
			
			FIXED_INFO["NodeType"]         := NODETYPE[NumGet(addr + offset, "uint")]              , offset += 4
			FIXED_INFO["ScopeId"]          := StrGet(addr + offset, MAX_SCOPE_ID_LEN + 4, "cp0")   , offset += MAX_SCOPE_ID_LEN + 4
			FIXED_INFO["EnableRouting"]    := NumGet(addr + offset, "uint")                        , offset += 4
			FIXED_INFO["EnableProxy"]      := NumGet(addr + offset, "uint")                        , offset += 4
			FIXED_INFO["EnableDns"]        := NumGet(addr + offset, "uint")

			return FIXED_INFO
		}
	}
	return ""
}
Example

Code: Select all

GetNetworkParams := GetNetworkParams()

ShowNetworkParams := "HostName:`t`t`t" GetNetworkParams.HostName
ShowNetworkParams .= "`nDomainName:`t`t`t" GetNetworkParams.DomainName
loop % GetNetworkParams.DnsServerList.Count()
{
	ShowNetworkParams .= "`nDnsServerList.IpAddress[" A_Index "]:`t`t" GetNetworkParams.DnsServerList.IpAddress[A_Index]
	ShowNetworkParams .= "`nDnsServerList.IpMask[" A_Index "]:`t`t" GetNetworkParams.DnsServerList.IpMask[A_Index]
}
ShowNetworkParams .= "`nNodeType:`t`t`t" GetNetworkParams.NodeType
ShowNetworkParams .= "`nScopeId:`t`t`t" GetNetworkParams.ScopeId
ShowNetworkParams .= "`nEnableRouting:`t`t`t" GetNetworkParams.EnableRouting
ShowNetworkParams .= "`nEnableProxy:`t`t`t" GetNetworkParams.EnableProxy
ShowNetworkParams .= "`nEnableDns:`t`t`t" GetNetworkParams.EnableDns

MsgBox % ShowNetworkParams

Re: [WinAPI] IP Helper functions

Posted: 15 Jan 2020, 03:17
by jNizM
*reserved

Re: [WinAPI] IP Helper functions

Posted: 15 Jan 2020, 03:17
by jNizM
*reserved

Re: [WinAPI] IP Helper functions

Posted: 18 Jan 2020, 12:08
by BGM
I want to find the information about the network adapter that is in use. I found that if I just used this:

Code: Select all

adaptersinfo := GetAdaptersInfo()
msgbox % adaptersinfo[1].ipaddresslist
that it would try and get the ipaddress of the first adapter even if it was bluetooth.

So I wrote this wrapper which will find the first network adapter with an actual ipaddress.

My problem is that if the computer has two active adapters (one on the LAN and one for a VPN, for example) that there is no way to tell them apart. If the vpn adapter is first in order then that is what gets returned, rather than the LAN's ipaddress.

Is there a way to discern which is the computer's "primary" adapter? I can't see any way to tell this.

Code: Select all

;make sure the connection is an ethernet connection, and the ipaddress is actual
;whichadapter = a number indicating the adapter order;  leave it blank to pull the active adapter (or rather, the first valid ipaddress)
GetActiveAdapterInfo(whichadapter=""){
	adaptersinfo := GetAdaptersInfo()
	if(whichadapter){
		return adaptersinfo[whichadapter]
	}else{
		for key, thisadapter in adaptersinfo
		{
			if( adaptersinfo[key].ipaddresslist != "0.0.0.0"){
				return adaptersinfo[key]
			}
		}
	}
}

Re: [WinAPI] IP Helper functions

Posted: 20 Jan 2020, 03:34
by jNizM
You can check the "Best Interface" before

Code: Select all

MsgBox % GetBestInterface()

GetBestInterface()
{
	static NO_ERROR := 0

	if (DllCall("iphlpapi\GetBestInterface", "ptr", 0, "uint*", BestIfIndex) = NO_ERROR)
		return BestIfIndex
	return false
}
BestIfIndex (GetBestInterface) -> Index (GetAdaptersInfo)

Re: [WinAPI] IP Helper functions

Posted: 20 Jan 2020, 20:01
by BGM
Thanks again, jNizM - that's awesome. The docs say that it finds the best route to the interface for ipv4. I didn't even know this existed.