[Win]NetworkAdapterInterface

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
HeX0R
Beiträge: 2959
Registriert: 10.09.2004 09:59
Computerausstattung: AMD Ryzen 7 5800X
96Gig Ram
NVIDIA GEFORCE RTX 3060TI/8Gig
Win10 64Bit
G19 Tastatur
2x 24" + 1x27" Monitore
Glorious O Wireless Maus
PB 3.x-PB 6.x
Oculus Quest 2
Kontaktdaten:

[Win]NetworkAdapterInterface

Beitrag von HeX0R »

Moin,

es gibt ein paar Ansätze in den Boards die WinAPI GetAdaptersInfo() zu benutzen, um erweiterte Infos der integrierten Netzwerkadapter zu bekommen.
Aber irgendwie waren die alle etwas unpraktisch und auch nicht immer fehlerfrei.
Also habe ich mich daran gesetzt und das ganze als Interface umgesetzt.
Man kann quasi alle Informationen der API benutzen ausser das WINS-Zeugs, weil ich dafür keine Verwendung habe.

Ausserdem gibt es zwei interessante Zusatzfunktionen, wegen den ich das ganze überhaupt erst begonnen habe.
AddIPAddress() und DeleteIPAddress().

Der (Un)Sinn hinter dem ganzen war folgendes Szenario:

Wir haben im Geschäft ein paar Monteure, die mit PCs... nun nicht wirklich aufgewachsen sind.
Mittlerweile müssen aber die meisten unserer Anlagen über Netzwerkkabel bedient werden.

Nachdem ich eine geschlagene halbe Stunde erklärt hatte, wie man die IP seiner Netzwerkkarte in den Subnetzbereich der
jeweiligen Anlage umbiegen kann, dachte ich, das muss doch einfacher gehn...
Also hab ich jetzt ein kleines Programm gebastelt, mit dem man auf Knopfdruck die IP (temporär) anpassen kann.

O.k., genug gelabert, hier der Code:

Code: Alles auswählen

;/--------------------------
;|
;| NetworkAdapterInterface_v02.pbi
;| V1.02 (22.10.2009)
;| ©HeX0R 2009
;|
;| for PB 4.x
;|
;| Add comments for yourself...
;/--------------------------

CompilerIf #PB_Compiler_Version < 600
	InitNetwork()
CompilerEndIf

Prototype __GetAdaptersAddresses(Family.l, Flags.l, Reserved.l, *AdapterAddresses, *SizePointer)

#MAX_ADAPTER_NAME_LENGTH        = 256
#MAX_ADAPTER_DESCRIPTION_LENGTH = 128
#MAX_ADAPTER_ADDRESS_LENGTH     = 8

#MIB_IF_TYPE_OTHER     =  1
#MIB_IF_TYPE_ETHERNET  =  6
#MIB_IF_TYPE_TOKENRING =  9
#MIB_IF_TYPE_FDDI      = 15
#MIB_IF_TYPE_PPP       = 23
#MIB_IF_TYPE_LOOPBACK  = 24
#MIB_IF_TYPE_SLIP      = 28
#IF_TYPE_ATM           = 37
#IF_TYPE_IEEE80211     = 71
#IF_TYPE_TUNNEL        = 131
#IF_TYPE_IEEE1394      = 144

Enumeration
	#MIB_IF_OPER_STATUS_NON_OPERATIONAL
	#MIB_IF_OPER_STATUS_UNREACHABLE
	#MIB_IF_OPER_STATUS_DISCONNECTED
	#MIB_IF_OPER_STATUS_CONNECTING
	#MIB_IF_OPER_STATUS_CONNECTED
	#MIB_IF_OPER_STATUS_OPERATIONAL
EndEnumeration

Enumeration
	#IpPrefixOriginOther
	#IpPrefixOriginManual
	#IpPrefixOriginWellKnown
	#IpPrefixOriginDhcp
	#IpPrefixOriginRouterAdvertisement
EndEnumeration
#IpPrefixOriginUnchanged = 16

#ScopeLevelInterface    = 1
#ScopeLevelLink         = 2
#ScopeLevelSubnet       = 3
#ScopeLevelAdmin        = 4
#ScopeLevelSite         = 5
#ScopeLevelOrganization = 8
#ScopeLevelGlobal       = 14

Enumeration
	#IpSuffixOriginOther
	#IpSuffixOriginManual
	#IpSuffixOriginWellKnown
	#IpSuffixOriginDhcp
	#IpSuffixOriginLinkLayerAddress
	#IpSuffixOriginRandom
EndEnumeration
#IpSuffixOriginUnchanged = 16

Enumeration
	#IpDadStateInvalid
	#IpDadStateTentative
	#IpDadStateDuplicate
	#IpDadStateDeprecated
	#IpDadStatePreferred
EndEnumeration

Enumeration
	#SELECT_UNICAST_ADDRESS
	#SELECT_ANYCAST_ADDRESS
	#SELECT_MULTICAST_ADDRESS
	#SELECT_DNS_ADDRESS
EndEnumeration

#MIB_IF_ADMIN_STATUS_UP      = 1
#MIB_IF_ADMIN_STATUS_DOWN    = 2
#MIB_IF_ADMIN_STATUS_TESTING = 3

#IP_ADAPTER_DDNS_ENABLED                  = $0001 ;Dynamic DNS is enabled on this adapter.
#IP_ADAPTER_REGISTER_ADAPTER_SUFFIX       = $0002 ;Register the DNS suffix For this adapter.
#IP_ADAPTER_DHCP_ENABLED                  = $0004 ;The Dynamic Host Configuration Protocol (DHCP) is enabled on this adapter.
#IP_ADAPTER_RECEIVE_ONLY                  = $0008 ;The adapter is a receive-only adapter.
#IP_ADAPTER_NO_MULTICAST                  = $0010 ;The adapter is not a multicast recipient.
#IP_ADAPTER_IPV6_OTHER_STATEFUL_CONFIG    = $0020 ;The adapter contains other IPv6-specific stateful configuration information.
#IP_ADAPTER_NETBIOS_OVER_TCPIP_ENABLED    = $0040 ;The adapter is enabled For NetBIOS over TCP/IP.
#IP_ADAPTER_IPV4_ENABLED                  = $0080 ;The adapter is enabled For IPv4.
#IP_ADAPTER_IPV6_ENABLED                  = $0100 ;The adapter is enabled For IPv6.
#Ipv6ManagedAddressConfigurationSupported = $0200

#NI_NUMERICHOST                  = 1
#GAA_FLAG_SKIP_UNICAST           = $0001
#GAA_FLAG_SKIP_ANYCAST           = $0002
#GAA_FLAG_SKIP_MULTICAST         = $0004
#GAA_FLAG_SKIP_DNS_SERVER        = $0008
#GAA_FLAG_INCLUDE_PREFIX         = $0010
#GAA_FLAG_SKIP_FRIENDLY_NAME     = $0020
#GAA_FLAG_INCLUDE_ALL_INTERFACES = $0100

CompilerIf Defined(IP_ADDR_STRING, #PB_Structure) = 0
	Structure IP_ADDR_STRING
		*pNext
		IpAddress.b[16]
		IpMask.b[16]
		Context.l
	EndStructure
CompilerEndIf

CompilerIf Defined(IP_ADAPTER_INFO, #PB_Structure) = 0
	Structure IP_ADAPTER_INFO
		*Next
		ComboIndex.l
		AdapterName.b[#MAX_ADAPTER_NAME_LENGTH + 4]
		Description.b[#MAX_ADAPTER_DESCRIPTION_LENGTH + 4]
		AddressLength.l
		Address.b[#MAX_ADAPTER_ADDRESS_LENGTH]
		Index.l
		Type.l
		DhcpEnabled.l
		*CurrentIpAddress.IP_ADDR_STRING
		IpAddressList.IP_ADDR_STRING
		GatewayList.IP_ADDR_STRING
		DhcpServer.IP_ADDR_STRING
		HaveWins.l
		PrimaryWinsServer.IP_ADDR_STRING
		SecondaryWinsServer.IP_ADDR_STRING
		LeaseObtained.l
		LeaseExpires.l
	EndStructure
CompilerEndIf

Structure SOCKET_ADDRESS
	*lpSockaddr
	iSockaddrLength.l
EndStructure

Structure sockaddr_in6
	sin6_family.w
	sin6_port.w
	sin6_flowinfo.l
	sin6_addr.b[16]
	sin6_scope_id.l
EndStructure

Structure MIB_IPADDRROW
	dwAddr.l
	dwIndex.l
	dwMask.l
	dwBCastAddr.l
	dwReasmSize.l
	unused1.w
	wType.w
EndStructure

Structure MIB_IPADDRTABLE
	dwNumEntries.l
	table.MIB_IPADDRROW[0]
EndStructure

Structure IP_ADAPTER_PREFIX
	Length.l
	Flags.l
	*Next
	Address.SOCKET_ADDRESS
	PrefixLength.l
EndStructure

Structure IP_ADAPTER_UNICAST_ADDRESS
	Length.l
	Flags.l
	*Next;
	Address.SOCKET_ADDRESS
	PrefixOrigin.l
	SuffixOrigin.l
	DadState.l
	ValidLifetime.l
	PreferredLifetime.l
	LeaseLifetime.l
	OnLinkPrefixLength.b ;<-uint8?
EndStructure

Structure IP_ADAPTER_DNS_SERVER_ADDRESS ;Same for anycast and multicast
	Length.l
	Reserved.l
	*Next
	Address.SOCKET_ADDRESS
EndStructure

Structure IP_ADAPTER_ADDRESSES
	Length.l
	IfIndex.l
	*Next
	*AdapterName                              ;
	*FirstUnicastAddress
	*FirstAnycastAddress
	*FirstMulticastAddress
	*FirstDnsServerAddress
	*DnsSuffix                             ;
	*Description                             ;
	*FriendlyName                             ;
	PhysicalAddress.b[#MAX_ADAPTER_ADDRESS_LENGTH]
	PhysicalAddressLength.l
	Flags.l
	Mtu.l
	IfType.l
	OperStatus.l ;?
	Ipv6IfIndex.l
	ZoneIndices.l[16]
	*FirstPrefix
	;   TransmitLinkSpeed.q
	;   ReceiveLinkSpeed.q
	;   *FirstWinsServerAddress;.IP_ADAPTER_WINS_SERVER_ADDRESS_LH
	;   *FirstGatewayAddress;.IP_ADAPTER_GATEWAY_ADDRESS_LH
	;   Ipv4Metric.l
	;   Ipv6Metric.l
	;   Luid.IF_LUID
	;   Dhcpv4Server.SOCKET_ADDRESS
	;   CompartmentId.NET_IF_COMPARTMENT_ID
	;   NetworkGuid.NET_IF_NETWORK_GUID
	;   ConnectionType.l
	;   TunnelType.l
	;   Dhcpv6Server.SOCKET_ADDRESS
	;   Dhcpv6ClientDuid.b[#MAX_DHCPV6_DUID_LENGTH]
	;   Dhcpv6ClientDuidLength.l
	;   Dhcpv6Iaid.l
	;   *FirstDnsSuffix;.IP_ADAPTER_DNS_SUFFIX
EndStructure

Structure _ST_IF_ADAPINFO_
	VTable.i
	*pAdapterInfo.IP_ADAPTER_INFO
	*pAdapterAddresses.IP_ADAPTER_ADDRESSES
	*IpAddrTable.MIB_IPADDRTABLE
	NumOfAdapters.l
	GetAdaptersAddresses.__GetAdaptersAddresses
	Lib.l
	IPOffset.l
	LastError.l
EndStructure

Interface _NETWORKADAPTERS_
	CountAdapters()
	CountIPAddresses(Num)
	SelectIP(IP)
	GetName.s(Num)
	GetDescription.s(Num)
	GetFriendlyName.s(Num)
	GetMACAddress.s(Num)
	GetIPAddress.s(Num, Index  = 0)
	GetSubnetMask.s(Num, Index = 0)
	GetGateway.s(Num, Index    = 0)
	GetDHCPServer.s(Num)
	GetType(Num)
	GetIndex(Num)
	UsesDHCP(Num)
	DHCPObtained(Num)
	DHCPExpires(Num)
	AddIPAddress(Num, Address, SubnetMask = $FFFFFF)
	DeleteIPAddress(Context)
	Refresh()
	Release()
EndInterface

Procedure IFNA_JumpToAdapter(*THIS._ST_IF_ADAPINFO_, Num)
	;Internal Procedure...
	Protected i, *Result, Offset

	*Result = *THIS\pAdapterInfo
	If Not *Result
		Offset  = OffsetOf(IP_ADAPTER_ADDRESSES\Next)
		*Result = *THIS\pAdapterAddresses
	EndIf

	If Num > 0
		For i = 1 To Num
			*Result = PeekI(*Result + Offset)
			If *Result = 0
				Break
			EndIf
		Next i
	EndIf

	ProcedureReturn *Result
EndProcedure

Procedure.s IFNA_CalcSubnet(*THIS._ST_IF_ADAPINFO_, Index)
	Protected Result.s
	
	For i = 0 To *THIS\IpAddrTable\dwNumEntries - 1
		If *THIS\IpAddrTable\table[i]\dwIndex = Index
			Result = IPString(*THIS\IpAddrTable\table[i]\dwMask)
			Break
		EndIf
	Next i
	
	ProcedureReturn Result
EndProcedure

Procedure IFNA_CountAdapters(*THIS._ST_IF_ADAPINFO_)
	;/-----------
	;| Returns how many Adapters this computer has
	;/-----------
	ProcedureReturn *THIS\NumOfAdapters
EndProcedure

Procedure IFNA_SelectIP(*THIS._ST_IF_ADAPINFO_, IP)
	Protected Result

	Result = *THIS\IPOffset
	Select IP
		Case #SELECT_ANYCAST_ADDRESS
			*THIS\IPOffset = OffsetOf(IP_ADAPTER_ADDRESSES\FirstAnycastAddress)
		Case #SELECT_MULTICAST_ADDRESS
			*THIS\IPOffset = OffsetOf(IP_ADAPTER_ADDRESSES\FirstMulticastAddress)
		Case #SELECT_DNS_ADDRESS
			*THIS\IPOffset = OffsetOf(IP_ADAPTER_ADDRESSES\FirstDnsServerAddress)
		Default
			*THIS\IPOffset = OffsetOf(IP_ADAPTER_ADDRESSES\FirstUnicastAddress)
	EndSelect

	ProcedureReturn Result
EndProcedure

Procedure.s IFNA_GetName(*THIS._ST_IF_ADAPINFO_, Num)
	;/------------
	;| Get Name of Adapter Num
	;| (This is mostly a GUID)
	;/------------
	Protected Result.s
	Protected *pAdapter.IP_ADAPTER_ADDRESSES

	If Num >= 0 And Num < *THIS\NumOfAdapters
		*pAdapter = IFNA_JumpToAdapter(*THIS, Num)
		If *pAdapter
			If *THIS\pAdapterInfo
				Result = PeekS(*pAdapter + OffsetOf(IP_ADAPTER_INFO\AdapterName), SizeOf(IP_ADAPTER_INFO\AdapterName), #PB_Ascii)
			Else
				Result = PeekS(*pAdapter\AdapterName, -1, #PB_Ascii)
			EndIf
		EndIf
	EndIf

	ProcedureReturn Result
EndProcedure

Procedure.s IFNA_GetDescription(*THIS._ST_IF_ADAPINFO_, Num)
	;/-----------
	;| Get Description of Adapter Num
	;| (Description is the readable name)
	;/-----------
	Protected Result.s
	Protected *pAdapter.IP_ADAPTER_ADDRESSES

	If Num >= 0 And Num < *THIS\NumOfAdapters
		*pAdapter = IFNA_JumpToAdapter(*THIS, Num)
		If *pAdapter
			If *THIS\pAdapterInfo
				Result = PeekS(*pAdapter + OffsetOf(IP_ADAPTER_INFO\Description), SizeOf(IP_ADAPTER_INFO\AdapterName), #PB_Ascii)
			Else
				Result = PeekS(*pAdapter\Description, -1, #PB_Unicode)
			EndIf
		EndIf
	EndIf

	ProcedureReturn Result
EndProcedure

Procedure.s IFNA_GetFriendlyName(*THIS._ST_IF_ADAPINFO_, Num)
	;/-----------
	;| Get FriendlyName of Adapter Num (only >= WinXP)
	;| (Description is the readable name)
	;/-----------
	Protected Result.s
	Protected *pAdapter.IP_ADAPTER_ADDRESSES

	If Num >= 0 And Num < *THIS\NumOfAdapters And *THIS\pAdapterAddresses
		*pAdapter = IFNA_JumpToAdapter(*THIS, Num)
		If *pAdapter
			Result = PeekS(*pAdapter\FriendlyName, -1, #PB_Unicode)
		EndIf
	EndIf

	ProcedureReturn Result
EndProcedure

Procedure.s IFNA_GetMACAddress(*THIS._ST_IF_ADAPINFO_, Num)
	;/----------
	;| Get MAC-Address of Adapter Num
	;/----------
	Protected Result.s, i, Offset, Length
	Protected *pAdapter

	If Num >= 0 And Num < *THIS\NumOfAdapters
		*pAdapter = IFNA_JumpToAdapter(*THIS, Num)
		If *pAdapter
			Result    = ""
			If *THIS\pAdapterInfo
				Offset = OffsetOf(IP_ADAPTER_INFO\Address)
				Length = PeekL(*pAdapter + OffsetOf(IP_ADAPTER_INFO\AddressLength))
			Else
				Offset = OffsetOf(IP_ADAPTER_ADDRESSES\PhysicalAddress)
				Length = PeekL(*pAdapter + OffsetOf(IP_ADAPTER_ADDRESSES\PhysicalAddressLength))
			EndIf
			For i = 0 To Length - 1
				Result + RSet(Hex(PeekB(*pAdapter + Offset + i) & $FF), 2, "0") + "-"
			Next i
			Result = Left(Result, Len(Result) - 1)
		EndIf
	EndIf

	ProcedureReturn Result
EndProcedure

Procedure IFNA_CountIPAddresses(*THIS._ST_IF_ADAPINFO_, Num)
	;/----------
	;| Count the IP Addresses of Adapter Num
	;/----------
	Protected Result, Offset
	Protected *pAdapter.IP_ADAPTER_INFO, *nextip

	If Num >= 0 And Num < *THIS\NumOfAdapters
		*pAdapter = IFNA_JumpToAdapter(*THIS, Num)
		If *pAdapter
			If *THIS\pAdapterInfo
				If *THIS\IPOffset = #SELECT_UNICAST_ADDRESS
					*nextip = *pAdapter\IpAddressList
					Offset  = OffsetOf(IP_ADDR_STRING\pNext)
				EndIf
			Else
				*nextip = PeekI(*pAdapter + *THIS\IPOffset)
				Offset  = OffsetOf(IP_ADAPTER_UNICAST_ADDRESS\Next)
			EndIf
			If *nextip
				Repeat
					Result + 1
					If PeekI(*nextip + Offset) = 0
						Break
					Else
						*nextip = PeekI(*nextip + Offset)
					EndIf
				ForEver
			EndIf
		EndIf
	EndIf

	ProcedureReturn Result
EndProcedure

Procedure IFNA_UsesDHCP(*THIS._ST_IF_ADAPINFO_, Num)
	;/---------
	;| Returns #True, when Adapter uses DHCP
	;/---------
	Protected Result
	Protected *pAdapter.IP_ADAPTER_INFO

	If Num >= 0 And Num < *THIS\NumOfAdapters
		If *THIS\pAdapterInfo
			*pAdapter = IFNA_JumpToAdapter(*THIS, Num)
			If *pAdapter
				Result = *pAdapter\DhcpEnabled
			EndIf
		EndIf
	EndIf

	ProcedureReturn Result
EndProcedure

Procedure IFNA_DHCPObtained(*THIS._ST_IF_ADAPINFO_, Num)
	;/---------
	;| Datestamp, when DHCP has been obtained
	;/---------
	Protected Result
	Protected *pAdapter.IP_ADAPTER_INFO

	If Num >= 0 And Num < *THIS\NumOfAdapters
		If *THIS\pAdapterInfo
			*pAdapter = IFNA_JumpToAdapter(*THIS, Num)
			If *pAdapter
				Result = *pAdapter\LeaseObtained
			EndIf
		EndIf
	EndIf

	ProcedureReturn Result
EndProcedure

Procedure IFNA_DHCPExpires(*THIS._ST_IF_ADAPINFO_, Num)
	;/---------
	;| Datestamp, when DHCP will expire
	;/---------
	Protected Result
	Protected *pAdapter.IP_ADAPTER_INFO

	If Num >= 0 And Num < *THIS\NumOfAdapters
		If *THIS\pAdapterInfo
			*pAdapter = IFNA_JumpToAdapter(*THIS, Num)
			If *pAdapter
				Result = *pAdapter\LeaseExpires
			EndIf
		EndIf
	EndIf

	ProcedureReturn Result
EndProcedure

Procedure.s IFNA_GetIPAddress(*THIS._ST_IF_ADAPINFO_, Num, Index = 0)
	;/----------
	;| Get IP Addresses of this Adapter.
	;| There can be more then one, thats why there is
	;| the parameter Index.
	;| You can check out how many IPs this Adapter has
	;| when calling CountIPAdresses()
	;/----------
	Protected Result.s, a$, i, j, k, Offset, L
	Protected *pAdapter.IP_ADAPTER_INFO, *nextip, *ipv4.SOCKADDR_IN, *ipv6.sockaddr_in6

	If Num >= 0 And Num < *THIS\NumOfAdapters
		*pAdapter = IFNA_JumpToAdapter(*THIS, Num)
		If *pAdapter
			If *THIS\pAdapterInfo
				*nextip = *pAdapter\IpAddressList
				Offset  = OffsetOf(IP_ADDR_STRING\pNext)
			Else
				*nextip = PeekI(*pAdapter + *THIS\IPOffset)
				Offset  = OffsetOf(IP_ADAPTER_DNS_SERVER_ADDRESS\Next)
			EndIf
			If *nextip
				For i = 1 To Index
					If PeekI(*nextip + Offset)
						*nextip = PeekI(*nextip + Offset)
					Else
						*nextip = 0
						Break
					EndIf
				Next i
				If *nextip
					If *THIS\pAdapterInfo
						Result = PeekS(*nextip + OffsetOf(IP_ADDR_STRING\IpAddress), SizeOf(IP_ADDR_STRING\IpAddress), #PB_Ascii)
					Else
						L = PeekL(*nextip + OffsetOf(IP_ADAPTER_DNS_SERVER_ADDRESS\Address) + OffsetOf(SOCKET_ADDRESS\iSockaddrLength))
						If L = SizeOf(SOCKADDR_IN)
							*ipv4  = PeekI(*nextip + OffsetOf(IP_ADAPTER_DNS_SERVER_ADDRESS\Address))
							Result = IPString(*ipv4\sin_addr)
						Else
							*ipv6  = PeekI(*nextip + OffsetOf(IP_ADAPTER_DNS_SERVER_ADDRESS\Address))
							For i = 0 To 15 Step 2
								k = *ipv6\sin6_addr[i] & $FF
								j = *ipv6\sin6_addr[i + 1] & $FF
								If k > 0
									Result + Hex(k)
								EndIf
								If j > 0
									Result + Hex(j)
								EndIf
								If Right(Result, 2) <> "::"
									Result + ":"
								EndIf
							Next i
							Result = Left(Result, Len(Result) - 1) + "%" + Str(*ipv6\sin6_scope_id)
						EndIf
					EndIf
				EndIf
			EndIf
		EndIf
	EndIf

	ProcedureReturn Result
EndProcedure

Procedure.s IFNA_GetSubnetMask(*THIS._ST_IF_ADAPINFO_, Num, Index = 0)
	;/----------
	;| Get SubnetMask for this Adapter-IP
	;| There can be more then one, thats why there is
	;| the parameter Index.
	;| You can check out how many IPs this Adapter has
	;| when calling CountIPAdresses()
	;/----------
	Protected Result.s, i
	Protected *pAdapter.IP_ADAPTER_INFO, *nextip.IP_ADDR_STRING, *pAdapter2.IP_ADAPTER_ADDRESSES

	If Num >= 0 And Num < *THIS\NumOfAdapters
		*pAdapter = IFNA_JumpToAdapter(*THIS, Num)
		If *pAdapter
			If *THIS\pAdapterInfo
				*nextip   = *pAdapter\IpAddressList
				For i = 1 To Index
					If *nextip\pNext
						*nextip = *nextip\pNext
					Else
						*nextip = 0
						Break
					EndIf
				Next i
				If *nextip
					Result = PeekS(*nextip + OffsetOf(IP_ADDR_STRING\IpMask), SizeOf(IP_ADDR_STRING\IpMask), #PB_Ascii)
				EndIf
			Else
				*pAdapter2 = *pAdapter
				Result = IFNA_CalcSubnet(*THIS, *pAdapter2\IfIndex)
			EndIf
		EndIf
	EndIf

	ProcedureReturn Result
EndProcedure

Procedure.s IFNA_GetGateway(*THIS._ST_IF_ADAPINFO_, Num, Index = 0)
	;/-----------
	;| Get Gateway IP for this Adapter (if any)
	;/-----------
	Protected Result.s, i
	Protected *pAdapter.IP_ADAPTER_INFO, *nextip.IP_ADDR_STRING

	If Num >= 0 And Num < *THIS\NumOfAdapters
		If *THIS\pAdapterInfo
			*pAdapter = IFNA_JumpToAdapter(*THIS, Num)
			If *pAdapter
				*nextip   = *pAdapter\GatewayList
				For i = 1 To Index
					If *nextip\pNext
						*nextip = *nextip\pNext
					Else
						*nextip = 0
						Break
					EndIf
				Next i
				If *nextip
					Result = PeekS(*nextip + OffsetOf(IP_ADDR_STRING\IpAddress), SizeOf(IP_ADDR_STRING\IpAddress), #PB_Ascii)
				EndIf
			EndIf
		EndIf
	EndIf

	ProcedureReturn Result
EndProcedure

Procedure.s IFNA_GetDHCPServer(*THIS._ST_IF_ADAPINFO_, Num)
	;/------------
	;| Get IP of DHCP-Server
	;| Value of "255.255.255.255" means there is
	;| still a connection attempt running, or it is unreachable
	;/------------
	Protected Result.s
	Protected *pAdapter.IP_ADAPTER_INFO, *nextip.IP_ADDR_STRING

	If Num >= 0 And Num < *THIS\NumOfAdapters
		If *THIS\pAdapterInfo
			*pAdapter = IFNA_JumpToAdapter(*THIS, Num)
			If *pAdapter
				*nextip   = *pAdapter\DhcpServer
				Result    = PeekS(*nextip + OffsetOf(IP_ADDR_STRING\IpAddress), SizeOf(IP_ADDR_STRING\IpAddress), #PB_Ascii)
			EndIf
		EndIf
	EndIf

	ProcedureReturn Result
EndProcedure

Procedure IFNA_GetType(*THIS._ST_IF_ADAPINFO_, Num)
	;/----------
	;| Returns Type of Adapter.
	;| Possible values are:
	;| #MIB_IF_TYPE_OTHER
	;| #MIB_IF_TYPE_ETHERNET
	;| #MIB_IF_TYPE_TOKENRING
	;| #MIB_IF_TYPE_FDDI
	;| #MIB_IF_TYPE_PPP
	;| #MIB_IF_TYPE_LOOPBACK
	;| #MIB_IF_TYPE_SLIP
	;/----------
	Protected Result, Offset = OffsetOf(IP_ADAPTER_ADDRESSES\IfType)
	Protected *pAdapter

	If Num >= 0 And Num < *THIS\NumOfAdapters
		If *THIS\pAdapterInfo
			Offset = OffsetOf(IP_ADAPTER_INFO\Type)
		EndIf
		*pAdapter = IFNA_JumpToAdapter(*THIS, Num)
		If *pAdapter
			Result = PeekL(*pAdapter + Offset)
		EndIf
	EndIf

	ProcedureReturn Result
EndProcedure


Procedure IFNA_GetIndex(*THIS._ST_IF_ADAPINFO_, Num)
	;/----------
	;| Internal Index of Adapters.
	;| Can change whenever Adapters are added or removed
	;/----------
	Protected Result
	Protected *pAdapter.IP_ADAPTER_INFO

	If Num >= 0 And Num < *THIS\NumOfAdapters
		*pAdapter = IFNA_JumpToAdapter(*THIS, Num)
		If *pAdapter
			If *THIS\pAdapterInfo
				Result = *pAdapter\Index
			Else
				Result = PeekL(*pAdapter + OffsetOf(IP_ADAPTER_ADDRESSES\IfIndex))
				If Result = 0
					Result = PeekL(*pAdapter + OffsetOf(IP_ADAPTER_ADDRESSES\Ipv6IfIndex))
				EndIf
			EndIf
		EndIf
	EndIf

	ProcedureReturn Result
EndProcedure

Procedure IFNA_AddIPAddress(*THIS._ST_IF_ADAPINFO_, Num, Address, SubnetMask = $FFFFFF)
	;/----------
	;| Will try to add another [temporary] IP to the Adapter Num.
	;| This only will succeed, when the cable is allready connected.
	;|
	;| The Result of this function has to be used as
	;| parameter for DeleteIPAddress
	;/----------
	Protected Context, Index, Instance

	If Num >= 0 And Num < *THIS\NumOfAdapters
		If *THIS\pAdapterInfo
			Index           = IFNA_GetIndex(*THIS, Num)
			*THIS\LastError = AddIPAddress_(Address, SubnetMask, Index, @Context, @Instance)
		EndIf
	EndIf

	ProcedureReturn Context
EndProcedure

Procedure IFNA_DeleteIPAddress(*THIS._ST_IF_ADAPINFO_, Context)
	;/----------
	;| Delete the above set IP Address
	;|
	;| Returns #NO_ERROR on success
	;/----------
	Protected Result

	*THIS\LastError = DeleteIPAddress_(Context)
	ProcedureReturn *THIS\LastError
EndProcedure

Procedure IFNA_Refresh(*THIS._ST_IF_ADAPINFO_)
	;/----------
	;| Refresh all Adapter-Data
	;/----------
	Protected ulOutBufLen, Result, i

	If *THIS\pAdapterInfo
		FreeMemory(*THIS\pAdapterInfo)
		*THIS\pAdapterInfo = #Null
	EndIf
	If *THIS\pAdapterAddresses
		FreeMemory(*THIS\pAdapterAddresses)
		*THIS\pAdapterAddresses = #Null
	EndIf
	If *THIS\IpAddrTable
		FreeMemory(*THIS\IpAddrTable)
		*THIS\IpAddrTable = #Null
	EndIf
	*THIS\NumOfAdapters = 0

	If OSVersion() >= #PB_OS_Windows_XP And *THIS\GetAdaptersAddresses
		*THIS\pAdapterAddresses        = AllocateMemory(SizeOf(IP_ADAPTER_ADDRESSES))
		*THIS\pAdapterAddresses\Length = SizeOf(IP_ADAPTER_ADDRESSES)
		ulOutBufLen                    = SizeOf(IP_ADAPTER_ADDRESSES)

		Result = *THIS\GetAdaptersAddresses(#AF_UNSPEC, #GAA_FLAG_INCLUDE_PREFIX | #GAA_FLAG_INCLUDE_ALL_INTERFACES, #Null, *THIS\pAdapterAddresses, @ulOutBufLen)
		If Result = #ERROR_BUFFER_OVERFLOW
			*THIS\pAdapterAddresses = ReAllocateMemory(*THIS\pAdapterAddresses, ulOutBufLen)
			Result                  = *THIS\GetAdaptersAddresses(#AF_UNSPEC, 0, #Null, *THIS\pAdapterAddresses, @ulOutBufLen)
		EndIf
		If Result = #NO_ERROR
			While IFNA_JumpToAdapter(*THIS, *THIS\NumOfAdapters)
				*THIS\NumOfAdapters + 1
			Wend
			*THIS\IpAddrTable = AllocateMemory(SizeOf(MIB_IPADDRTABLE))
			ulOutBufLen       = SizeOf(MIB_IPADDRTABLE)
			Result = GetIpAddrTable_(*THIS\IpAddrTable, @ulOutBufLen, #True)
			If Result = #ERROR_INSUFFICIENT_BUFFER
				*THIS\IpAddrTable = ReAllocateMemory(*THIS\IpAddrTable, ulOutBufLen)
				Result = GetIpAddrTable_(*THIS\IpAddrTable, @ulOutBufLen, #True)
			EndIf
		EndIf
	EndIf

	If *THIS\pAdapterAddresses = #Null
		*THIS\pAdapterInfo = AllocateMemory(SizeOf(IP_ADAPTER_INFO))
		ulOutBufLen        = SizeOf(IP_ADAPTER_INFO);

		Result = GetAdaptersInfo_(*THIS\pAdapterInfo, @ulOutBufLen)
		If Result = #ERROR_BUFFER_OVERFLOW
			*THIS\pAdapterInfo = ReAllocateMemory(*THIS\pAdapterInfo, ulOutBufLen)
			Result             = GetAdaptersInfo_(*THIS\pAdapterInfo, @ulOutBufLen)
		EndIf
		If Result = #NO_ERROR
			While IFNA_JumpToAdapter(*THIS, *THIS\NumOfAdapters)
				*THIS\NumOfAdapters + 1
			Wend
		EndIf
	EndIf

	ProcedureReturn Result
EndProcedure

Procedure IFNA_Release(*THIS._ST_IF_ADAPINFO_)
	;/----------
	;| Will release the Interface and all of its used Memory.
	;|
	;| !!ATTENTION!!
	;| Your Pointer to the Interface will be invalid after
	;| calling Release()!
	;| So it should only be used at end of program.
	;/----------
	If *THIS\pAdapterInfo
		FreeMemory(*THIS\pAdapterInfo)
	EndIf
	If *THIS\pAdapterAddresses
		FreeMemory(*THIS\pAdapterAddresses)
	EndIf
	If *THIS\IpAddrTable
		FreeMemory(*THIS\IpAddrTable)
	EndIf
	If *THIS\Lib
		CloseLibrary(*THIS\Lib)
	EndIf
	FreeMemory(*THIS)
EndProcedure

Procedure CreateNetworkAdapterInterface(ForceAdapterInfo = #False)
	;/----------
	;| The Interface creating procedure
	;/----------
	Protected *THIS._ST_IF_ADAPINFO_

	If OSVersion() < #PB_OS_Windows_2000
		ProcedureReturn #False
	EndIf

	*THIS         = AllocateMemory(SizeOf(_ST_IF_ADAPINFO_))
	*THIS\VTable  = ?_VT_IFNA_DATA_
	If *THIS = 0
		ProcedureReturn #False
	EndIf

	*THIS\GetAdaptersAddresses = #Null
	*THIS\Lib                  = #Null
	*THIS\IPOffset             = OffsetOf(IP_ADAPTER_ADDRESSES\FirstUnicastAddress)
	If ForceAdapterInfo = #False And OSVersion() >= #PB_OS_Windows_XP
		*THIS\Lib = OpenLibrary(#PB_Any, "Iphlpapi.dll")
		If *THIS\Lib
			*THIS\GetAdaptersAddresses = GetFunction(*THIS\Lib, "GetAdaptersAddresses")
			If *THIS\GetAdaptersAddresses = 0
				CloseLibrary(*THIS\Lib)
				*THIS\Lib = #Null
			EndIf
		EndIf
	EndIf

	If IFNA_Refresh(*THIS) <> #NO_ERROR
		If *THIS\pAdapterInfo
			FreeMemory(*THIS\pAdapterInfo)
		EndIf
		If *THIS\pAdapterAddresses
			FreeMemory(*THIS\pAdapterAddresses)
		EndIf
		If *THIS\IpAddrTable
			FreeMemory(*THIS\IpAddrTable)
		EndIf
		FreeMemory(*THIS)
		*THIS = 0
	EndIf

	ProcedureReturn *THIS
EndProcedure


DataSection
	_VT_IFNA_DATA_:
	Data.i @IFNA_CountAdapters()
	Data.i @IFNA_CountIPAddresses()
	Data.i @IFNA_SelectIP()
	Data.i @IFNA_GetName()
	Data.i @IFNA_GetDescription()
	Data.i @IFNA_GetFriendlyName()
	Data.i @IFNA_GetMACAddress()
	Data.i @IFNA_GetIPAddress()
	Data.i @IFNA_GetSubnetMask()
	Data.i @IFNA_GetGateway()
	Data.i @IFNA_GetDHCPServer()
	Data.i @IFNA_GetType()
	Data.i @IFNA_GetIndex()
	Data.i @IFNA_UsesDHCP()
	Data.i @IFNA_DHCPObtained()
	Data.i @IFNA_DHCPExpires()
	Data.i @IFNA_AddIPAddress()
	Data.i @IFNA_DeleteIPAddress()
	Data.i @IFNA_Refresh()
	Data.i @IFNA_Release()
EndDataSection
und ein Beispiel:

Code: Alles auswählen

XIncludeFile "NetworkAdapterInterface_V02.pbi"

Procedure.s TypeToString(Type)
	Protected Result.s

	Select Type
		Case #MIB_IF_TYPE_OTHER     : Result = "other type of network interface"
		Case #MIB_IF_TYPE_ETHERNET  : Result = "Ethernet network interface"
		Case #MIB_IF_TYPE_TOKENRING : Result = "token ring network interface"
		Case #MIB_IF_TYPE_FDDI      : Result = "FDDI"
		Case #MIB_IF_TYPE_PPP       : Result = "PPP network interface"
		Case #MIB_IF_TYPE_LOOPBACK  : Result = "software loopback network interface"
		Case #MIB_IF_TYPE_SLIP      : Result = "Slip"
		Case #IF_TYPE_ATM           : Result = "ATM network interface"
		Case #IF_TYPE_IEEE80211     : Result = "IEEE 802.11 wireless network interface"
		Case #IF_TYPE_TUNNEL        : Result = "tunnel type encapsulation network interface"
		Case #IF_TYPE_IEEE1394      : Result = "IEEE 1394 (Firewire) high performance serial bus network interface"
	EndSelect

	ProcedureReturn Result
EndProcedure

Procedure main()
	Protected i, j, k, l, a$
	Protected NetAd._NETWORKADAPTERS_
	
	Dim MyIPs.s(4)
	MyIPs(0) = "UNICAST IPs:"
	MyIPs(1) = "ANYCAST IPs:"
	MyIPs(2) = "MULTICAST IPs:"
	MyIPs(3) = "DNS IPs:"

	NetAd = CreateNetworkAdapterInterface()
	If NetAd = 0
		Debug "Error!"
		End
	EndIf

	For i = 0 To NetAd\CountAdapters() - 1
		Debug "Number " + Str(i + 1) + " (Index:" + Str(NetAd\GetIndex(i)) + ")"
		Debug "--------"
		Debug "Type: " + TypeToString(NetAd\GetType(i))
		Debug "Name: " + NetAd\GetName(i)
		Debug "FriendlyName: " + NetAd\GetFriendlyName(i)
		Debug "Desc: " + NetAd\GetDescription(i)
		Debug "MAC : " + NetAd\GetMACAddress(i)
		For l = 0 To 3
			NetAd\SelectIP(l)
			j = NetAd\CountIPAddresses(i)
			If j
				Debug MyIPs(l) + Str(j)
				For k = 0 To j - 1
					a$ = NetAd\GetIPAddress(i, k)
					Debug "IP#" + Str(k + 1) + ": " + a$
					If FindString(a$, ".", 1)
						Debug "Subnet#" + Str(k + 1) + ": " + NetAd\GetSubnetMask(i, k)
					EndIf
				Next k
			EndIf
		Next l
		Debug "Gateway: " + NetAd\GetGateway(i)
		If NetAd\UsesDHCP(i)
			Debug "uses DHCP!"
			Debug "DHCP Server: " + NetAd\GetDHCPServer(i)
			Debug "DHCP obtained: " + FormatDate("%dd.%mm.%yyyy %hh:%ii:%ss", NetAd\DHCPObtained(i))
			Debug "DHCP expires: "  + FormatDate("%dd.%mm.%yyyy %hh:%ii:%ss", NetAd\DHCPExpires(i))
		EndIf
		Debug ""
	Next i

	NetAd\Release()
EndProcedure

main()
1.10.22 => an PB6.0 angepasst
Zuletzt geändert von HeX0R am 01.10.2022 14:58, insgesamt 7-mal geändert.
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: [Win]NetworkAdapterInterface

Beitrag von ts-soft »

:allright:
HeX0R hat geschrieben: Eigentlich sollte die Struktur richtig sein, aber vielleicht kann das mal einer mit einem 64Bit OS testen.
Knackpunkte sind die uint Type, DhcpEnabled und AddressLength.

Ich hab die als Integer gesetzt, fände es aber ziemlich seltsam, wenn dafür 8 Bytes verplempert werden würden.
Egal ob DhcpEnabled oder AddressLength Integer oder Long, Ungültiger Speicherzugriff Zeile 28

Code: Alles auswählen

For i = 0 To NetAd\CountAdapters() - 1
Also nur im x64 Modus.

Gruß
Thomas
Benutzeravatar
Fluid Byte
Beiträge: 3110
Registriert: 27.09.2006 22:06
Wohnort: Berlin, Mitte

Re: [Win]NetworkAdapterInterface

Beitrag von Fluid Byte »

Das Feld "VTable" in "_ST_IF_ADAPINFO_" muss Integer sein. Allerdings gibt's danach einen IMA in Zeile 190.
Windows 10 Pro, 64-Bit / Outtakes | Derek
Benutzeravatar
HeX0R
Beiträge: 2959
Registriert: 10.09.2004 09:59
Computerausstattung: AMD Ryzen 7 5800X
96Gig Ram
NVIDIA GEFORCE RTX 3060TI/8Gig
Win10 64Bit
G19 Tastatur
2x 24" + 1x27" Monitore
Glorious O Wireless Maus
PB 3.x-PB 6.x
Oculus Quest 2
Kontaktdaten:

Re: [Win]NetworkAdapterInterface

Beitrag von HeX0R »

O.k., das Integer von VTable stimmt, das hab ich wohl vergeigt.
Ändert man das, sollte Thomas' Fehler schon mal weg sein.

Gibts den IMA auch, wenn du mit den uint - Werten spielst?
Das sieht nämlich durchaus so aus, dass die Länge da vor IpAddressList irgendwo nicht stimmt.

(Ich ändere das oben mal noch nicht, bis wir den IMA vielleicht auch entfernt haben)
Benutzeravatar
Fluid Byte
Beiträge: 3110
Registriert: 27.09.2006 22:06
Wohnort: Berlin, Mitte

Re: [Win]NetworkAdapterInterface

Beitrag von Fluid Byte »

HeX0R hat geschrieben:Ändert man das, sollte Thomas' Fehler schon mal weg sein.
Nicht sollte, er ist definitiv weg ;)
HeX0R hat geschrieben:Gibts den IMA auch, wenn du mit den uint - Werten spielst?
Ich bin mir ziemlich sicher das es an den API Strukturen liegt. Diese müssen wohl auf 64bit byte-alinged werden.
Keine Ahnung wie das geht. Frag' freak, der hat das auch für CHOOSECOLOR und andere gemacht.
Windows 10 Pro, 64-Bit / Outtakes | Derek
Benutzeravatar
HeX0R
Beiträge: 2959
Registriert: 10.09.2004 09:59
Computerausstattung: AMD Ryzen 7 5800X
96Gig Ram
NVIDIA GEFORCE RTX 3060TI/8Gig
Win10 64Bit
G19 Tastatur
2x 24" + 1x27" Monitore
Glorious O Wireless Maus
PB 3.x-PB 6.x
Oculus Quest 2
Kontaktdaten:

Re: [Win32]NetworkAdapterInterface

Beitrag von HeX0R »

Nun gut, bis das geklärt ist, hab ich mal den Titel angepasst und auch VTable verbessert.
Jetzt also erst mal nur für Win32.
Benutzeravatar
edel
Beiträge: 3667
Registriert: 28.07.2005 12:39
Computerausstattung: GameBoy
Kontaktdaten:

Re: [Win32]NetworkAdapterInterface

Beitrag von edel »

UINT ist auch unter 64bit nur 4 Byte gross. Also muss es heissen

Code: Alles auswählen

 AddressLength.l
usw...
Benutzeravatar
HeX0R
Beiträge: 2959
Registriert: 10.09.2004 09:59
Computerausstattung: AMD Ryzen 7 5800X
96Gig Ram
NVIDIA GEFORCE RTX 3060TI/8Gig
Win10 64Bit
G19 Tastatur
2x 24" + 1x27" Monitore
Glorious O Wireless Maus
PB 3.x-PB 6.x
Oculus Quest 2
Kontaktdaten:

Re: [Win]NetworkAdapterInterface

Beitrag von HeX0R »

Danke edel!

(Hätte aber eigentlich schon erwartet, dass das nochmal jemand ausprobiert, nachdem der offensichtliche Fehler mit VTable beseitigt war...)

Habs oben berichtigt.
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: [Win]NetworkAdapterInterface

Beitrag von ts-soft »

:allright:
funktioniert jetzt! (bin leider selber noch nicht dazu gekommen, den Fehler zu suchen)

Gruß
Thomas
Benutzeravatar
Fluid Byte
Beiträge: 3110
Registriert: 27.09.2006 22:06
Wohnort: Berlin, Mitte

Re: [Win]NetworkAdapterInterface

Beitrag von Fluid Byte »

Yes, it würgs nau!
Number 1
--------
Type: Ethernet
Name: {A6EF4651-FE22-49FE-AF4E-E7DFD2A9B2C3}
Desc: NVIDIA nForce 10/100/1000 Mbps Ethernet #3
MAC : 00-22-68-68-55-73
IPs : 1
IP#1:
Subnet#1:
Gateway:
uses DHCP!
DHCP Server:
DHCP obtained: 01.01.1970 00:00:00
DHCP expires: 01.01.1970 00:00:00

Number 2
--------
Type: Ethernet
Name: {76B275D1-9934-4CDE-B2D1-E0150028D98E}
Desc: VirtualBox Host-Only Ethernet Adapter
MAC : 08-00-27-00-E0-FC
IPs : 1
IP#1:
Subnet#1: 0
Gateway:
uses DHCP!
DHCP Server:
DHCP obtained: 01.01.1970 00:00:00
DHCP expires: 01.01.1970 00:00:00

Number 3
--------
Type:
Name: {530B0DBA-F116-43E9-96A7-616C195919A6}
Desc: 108Mbps Wireless Network USB Dongle
MAC : 00-14-6C-37-B4-09
IPs : 1
IP#1:
Subnet#1:
Gateway:
uses DHCP!
DHCP Server:
DHCP obtained: 01.01.1970 00:00:00
DHCP expires: 01.01.1970 00:00:00
Windows 10 Pro, 64-Bit / Outtakes | Derek
Antworten