[WinAPI] IP Helper functions

Post your working scripts, libraries and tools for AHK v1.1 and older
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

[WinAPI] IP Helper functions

15 Jan 2020, 03:10

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
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: [WinAPI] IP Helper functions

15 Jan 2020, 03:11

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 := ""
}
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: [WinAPI] IP Helper functions

15 Jan 2020, 03:15

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
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: [WinAPI] IP Helper functions

15 Jan 2020, 03:17

*reserved
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: [WinAPI] IP Helper functions

15 Jan 2020, 03:17

*reserved
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
User avatar
BGM
Posts: 507
Joined: 20 Nov 2013, 20:56
Contact:

Re: [WinAPI] IP Helper functions

18 Jan 2020, 12:08

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]
			}
		}
	}
}
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: [WinAPI] IP Helper functions

20 Jan 2020, 03:34

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)
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
User avatar
BGM
Posts: 507
Joined: 20 Nov 2013, 20:56
Contact:

Re: [WinAPI] IP Helper functions

20 Jan 2020, 20:01

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.

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: KnIfER and 92 guests