unit uWinGetAdaptersAddresses;
interface
uses Windows, SysUtils;
const
MAX_ADAPTER_ADDRESS_LENGTH = 8;
MAX_DHCPV6_DUID_LENGTH = 130;
{ Which values?
//Family
AF_INET = ;
AF_INET6 = ;
AF_UNSPEC = ;
}
//ifType Const
IF_TYPE_OTHER = 1;
IF_TYPE_ETHERNET_CSMACD = 6;
IF_TYPE_ISO88025_TOKENRING = 9;
IF_TYPE_PPP = 23;
IF_TYPE_SOFTWARE_LOOPBACK = 24;
IF_TYPE_ATM = 37;
IF_TYPE_IEEE80211 = 71;
IF_TYPE_TUNNEL = 131;
IF_TYPE_IEEE1394 = 144;
//OperStatus Const
IfOperStatusUp = 1;
IfOperStatusDown = 2;
IfOperStatusTesting = 3;
IfOperStatusUnknown = 4;
IfOperStatusDormant = 5;
IfOperStatusNotPresent = 6;
IfOperStatusLowerLayerDown = 7;
type
PhysAddrArray =
array[0..MAX_ADAPTER_ADDRESS_LENGTH - 1]
of BYTE;
//http://msdn.microsoft.com/en-us/library/ms740496(VS.85).aspx
PSOCKADDR = ^SOCKADDR;
SOCKADDR =
record
sa_family : ShortInt;
sa_data :
array[0..13]
of Char;
end;
//http://msdn.microsoft.com/en-us/library/ms740507(VS.85).aspx
PSOCKET_ADDRESS = ^SOCKET_ADDRESS;
SOCKET_ADDRESS =
record
lpSocketaddr : PSOCKADDR;
iSockaddrLength : Integer;
end;
//NET_IF_CONNECTION_TYPE Const
NET_IF_CONNECTION_TYPE = (
NET_IF_CONNECTION_DEDICATED = 1,
NET_IF_CONNECTION_PASSIVE = 2,
NET_IF_CONNECTION_DEMAND = 3,
NET_IF_CONNECTION_MAXIMUM = 4
);
//http://msdn.microsoft.com/en-us/library/aa366281(VS.85).aspx
IP_PREFIX_ORIGIN = (
IpPrefixOriginOther = 0,
IpPrefixOriginManual,
IpPrefixOriginWellKnown,
IpPrefixOriginDhcp,
IpPrefixOriginRouterAdvertisement,
IpPrefixOriginUnchanged = 16
);
//http://msdn.microsoft.com/en-us/library/aa366283(VS.85).aspx
IP_SUFFIX_ORIGIN = (
IpSuffixOriginOther = 0,
IpSuffixOriginManual,
IpSuffixOriginWellKnown,
IpSuffixOriginDhcp,
IpSuffixOriginLinkLayerAddress,
IpSuffixOriginRandom,
IpSuffixOriginUnchanged = 16
);
//http://msdn.microsoft.com/en-us/library/aa366069(VS.85).aspx
IP_DAD_STATE = (
IpDadStateInvalid = 0,
IpDadStateTentative,
IpDadStateDuplicate,
IpDadStateDeprecated,
IpDadStatePreferred
);
//http://msdn.microsoft.com/en-us/library/aa366066(VS.85).aspx
PIP_ADAPTER_UNICAST_ADDRESS = ^IP_ADAPTER_UNICAST_ADDRESS;
IP_ADAPTER_UNICAST_ADDRESS =
record
union:
record
case Integer
of
0: (Length: LongInt; Flags: DWORD);
end;
Next : PIP_ADAPTER_UNICAST_ADDRESS;
Address : SOCKET_ADDRESS;
PrefixOrigin : IP_PREFIX_ORIGIN;
SuffixOrigin : IP_SUFFIX_ORIGIN;
DadState : IP_DAD_STATE;
ValidLifeTime : LongInt;
PreferredLifeTime : LongInt;
LeaseLifeTime : LongInt;
OnLinkPrefixLength :
array[0..7]
of Integer;
end;
//http://msdn.microsoft.com/en-us/library/aa366059(VS.85).aspx
PIP_ADAPTER_ANYCAST_ADDRESS = ^IP_ADAPTER_ANYCAST_ADDRESS;
IP_ADAPTER_ANYCAST_ADDRESS =
record
union:
record
case Integer
of
0: (Alignment: LongInt);
1: (Length: LongInt; Flags: DWORD);
end;
Next : PIP_ADAPTER_ANYCAST_ADDRESS;
Address : SOCKET_ADDRESS;
end;
//http://msdn.microsoft.com/en-us/library/aa366063(VS.85).aspx
PIP_ADAPTER_MULTICAST_ADDRESS = ^IP_ADAPTER_MULTICAST_ADDRESS;
IP_ADAPTER_MULTICAST_ADDRESS =
record
union:
record
case Integer
of
0: (Alignment: LongInt);
1: (Length: LongInt; Flags: DWORD);
end;
Next : PIP_ADAPTER_MULTICAST_ADDRESS;
Address : SOCKET_ADDRESS;
end;
//http://msdn.microsoft.com/en-us/library/aa366060(VS.85).aspx
PIP_ADAPTER_DNS_SERVER_ADDRESS = ^IP_ADAPTER_DNS_SERVER_ADDRESS;
IP_ADAPTER_DNS_SERVER_ADDRESS =
record
union:
record
case Integer
of
0: (Alignment: LongInt);
1: (Length: LongInt; Reserved: DWORD);
end;
Next : PIP_ADAPTER_DNS_SERVER_ADDRESS;
Address : SOCKET_ADDRESS;
end;
//http://msdn.microsoft.com/en-us/library/aa366065(VS.85).aspx
PIP_ADAPTER_PREFIX = ^IP_ADAPTER_PREFIX;
IP_ADAPTER_PREFIX =
record
union:
record
case Integer
of
0: (Alignment: LongInt);
1: (Length: LongInt; Flags: DWORD);
end;
Next : PIP_ADAPTER_PREFIX;
Address : SOCKET_ADDRESS;
PrefixLength : LongInt;
end;
//http://msdn.microsoft.com/en-us/library/aa366058(VS.85).aspx
PIP_ADAPTER_ADDRESSES = ^IP_ADAPTER_ADDRESSES;
IP_ADAPTER_ADDRESSES =
record
union:
record
case Integer
of
0: (Alignment: LongInt);
1: (Length: LongInt; IfIndex: DWORD);
end;
Next : PIP_ADAPTER_ADDRESSES;
AdapterName : PCHAR;
FirstUnicastAddress : PIP_ADAPTER_UNICAST_ADDRESS;
FirstAnycastAddress : PIP_ADAPTER_ANYCAST_ADDRESS;
FirstMulticastAddress : PIP_ADAPTER_MULTICAST_ADDRESS;
FirstDnsServerAddress : PIP_ADAPTER_DNS_SERVER_ADDRESS;
DnsSuffix : PWCHAR;
Description : PWCHAR;
FriendlyName : PWCHAR;
PhysicalAdress : PhysAddrArray;
PhysicalAdressLength : DWORD;
Flags : DWORD;
Mtu : DWORD;
IfType : DWORD;
// OperStatus : IF_OPER_STATUS;
Ipv6IfIndex : DWORD;
ZoneIndices :
array[0..15]
of DWORD;
FirstPrefix : PIP_ADAPTER_PREFIX;
TransmitLinkSpeed : Int64;
ReceiveLinkSpeed : Int64;
// FirstWinsServerAddress: PIP_ADAPTER_WINS_SERVER_ADDRESS_LH;
// FirstGatewayAddress : PIP_ADAPTER_GATEWAY_ADDRESS_LH;
Ipv4Metric : LongInt;
Ipv6Metric : LongInt;
// Luid : IF_LUID;
Dhcpv4Server : SOCKET_ADDRESS;
// CompartmentId : NET_IF_COMPARTMENT_ID; [This member is not currently supported and is reserved for future use]
// NetworkGuid : NET_IF_NETWORK_GUID;
ConnectionType : NET_IF_CONNECTION_TYPE;
// TunnelType : TUNNEL_TYPE;
Dhcpv6Server : SOCKET_ADDRESS;
Dhcpv6ClientDuid :
array[0..MAX_DHCPV6_DUID_LENGTH - 1]
of BYTE;
Dhcpv6ClientDuidLength: LongInt;
Dhcpv6Iaid : LongInt;
// FirstDnsSuffix : PIP_ADAPTER_DNS_SUFFIX;
end;
TAdapter =
Class(TObject)
private
FAdapterName : PChar;
FFriendlyName : PWChar;
FDnsSuffix : PWChar;
FSockAddr : PChar;
FIpv4Metric : LongInt;
FTransmitLinkspeed : Extended;
FReceiveLinkSpeed : Extended;
FIfType : DWORD;
FPhysicalAddress :
String;
function GetIfType :
string;
function GetPhysicalAddress :
string;
procedure SetPhysicalAddress(
const aPhysAddr : PhysAddrArray;
const Len : DWORD);
public
constructor Create(aAdapter : IP_ADAPTER_ADDRESSES);
destructor Destroy;
override;
property FriendlyName : PWChar
read FFriendlyName;
property AdapterName : PChar
read FAdapterName;
property DnsSuffix : PWChar
read FDnsSuffix;
property SockAddr : PChar
read FSockAddr;
property Ipv4Metric : LongInt
read FIpv4Metric;
property TransmitLinkspeed : Extended
read FTransmitLinkspeed;
property ReceiveLinkSpeed : Extended
read FReceiveLinkSpeed;
property IfType :
String read GetIfType;
property PhysicalAddress :
String read GetPhysicalAddress;
end;
PVOID = Pointer;
//http://msdn.microsoft.com/en-us/library/aa365915(VS.85).aspx
function GetAdaptersAddresses(Family: ULONG; Flags: DWORD; Reserved: PVOID;
pAdapterAddresses: PIP_ADAPTER_ADDRESSES;
pOutBufLen: PULONG): DWORD;
stdcall;
external '
IPHLPAPI.DLL'
name '
GetAdaptersAddresses';
function DecToHex(
dec : integer) :
String;
implementation
{ TAdaper }
constructor TAdapter.Create(aAdapter: IP_ADAPTER_ADDRESSES);
begin
inherited Create;
FAdapterName := aAdapter.AdapterName;
FFriendlyName := aAdapter.FriendlyName;
FDnsSuffix := aAdapter.DnsSuffix;
FSockAddr := aAdapter.Dhcpv4Server.lpSocketaddr^.sa_data;
FIpv4Metric := aAdapter.Ipv4Metric;
FTransmitLinkspeed := aAdapter.TransmitLinkspeed / 8589934592;
// MByte/s
FReceiveLinkspeed := aAdapter.ReceiveLinkSpeed / 8589934592;
FIfType := aAdapter.IfType;
SetPhysicalAddress(aAdapter.PhysicalAdress, aAdapter.PhysicalAdressLength);
end;
destructor TAdapter.Destroy;
begin
//
inherited;
end;
function TAdapter.GetIfType:
string;
begin
case FIfType
of
1: result := '
IF_TYPE_OTHER';
6: result := '
IF_TYPE_ETHERNET_CSMACD';
9: result := '
IF_TYPE_ISO88025_TOKENRING';
23: result := '
IF_TYPE_PPP';
24: result := '
IF_TYPE_SOFTWARE_LOOPBACK';
37: result := '
IF_TYPE_ATM';
71: result := '
IF_TYPE_IEEE80211';
131: result := '
IF_TYPE_TUNNEL';
144: result := '
IF_TYPE_IEEE1394';
else result := '
Not set yet';
end;
end;
function TAdapter.GetPhysicalAddress:
string;
begin
result := FPhysicalAddress;
end;
procedure TAdapter.SetPhysicalAddress(
const aPhysAddr: PhysAddrArray;
const Len: DWORD);
var
i : integer;
begin
FPhysicalAddress := DecToHex(aPhysAddr[0]);
if len = 0
then exit;
for i := 1
to len-1
do begin
FPhysicalAddress := FPhysicalAddress + '
-' + DecToHex(aPhysAddr[i]);
end;
end;
function DecToHex(
dec : Integer) :
String;
const
HexArr :
array[0..15]
of Char = ('
0', '
1', '
2', '
3', '
4', '
5', '
6', '
7', '
8', '
9', '
A', '
B', '
C', '
D', '
E', '
F');
var
tmp : Integer;
begin
result := '
';
tmp := 0;
{
HEX |0|1|2|3|4|5|6|7|8|9|A |B |C |D |E |F represent Array[tmp]
------------------------------------------
DEC |0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15 represent tmp
}
repeat
tmp :=
dec mod 16;
dec :=
dec div 16;
result := HexArr[tmp] + result;
until (tmp = 0)
or (length(result) = 2);
if result = '
0'
then result := '
00';
end;
end.