Seite 1 von 2

[Win]NetworkAdapterInterface

Verfasst: 19.10.2009 21:31
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

Re: [Win]NetworkAdapterInterface

Verfasst: 19.10.2009 22:09
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

Re: [Win]NetworkAdapterInterface

Verfasst: 19.10.2009 22:41
von Fluid Byte
Das Feld "VTable" in "_ST_IF_ADAPINFO_" muss Integer sein. Allerdings gibt's danach einen IMA in Zeile 190.

Re: [Win]NetworkAdapterInterface

Verfasst: 19.10.2009 23:49
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)

Re: [Win]NetworkAdapterInterface

Verfasst: 19.10.2009 23:56
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.

Re: [Win32]NetworkAdapterInterface

Verfasst: 20.10.2009 00:03
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.

Re: [Win32]NetworkAdapterInterface

Verfasst: 20.10.2009 16:42
von edel
UINT ist auch unter 64bit nur 4 Byte gross. Also muss es heissen

Code: Alles auswählen

 AddressLength.l
usw...

Re: [Win]NetworkAdapterInterface

Verfasst: 20.10.2009 20:42
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.

Re: [Win]NetworkAdapterInterface

Verfasst: 20.10.2009 20:46
von ts-soft
:allright:
funktioniert jetzt! (bin leider selber noch nicht dazu gekommen, den Fehler zu suchen)

Gruß
Thomas

Re: [Win]NetworkAdapterInterface

Verfasst: 20.10.2009 21:07
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