Using the IP Helper API from Delphi
May 20, 2001
Borland Delphi 5Windows 2000
If you are building advanced Internet applications, you will often have the need to get information about the network configuration of the system on which your application is running. For example, you might need to retrieve the MAC address (sometimes called the physical address) of the network adapter or the IP address of the default DNS server. The IP Helper API allows you to retrieve such information on Windows 2000.
The IP Helper API <http://msdn.microsoft.com/library/default.asp?URL=/library/psdk/rras/iphpport_7vz9.htm> (or IPHLPAPI or Internet Protocol Helper) is new to Windows 2000, and thus it is not directly usable from Delphi 5. Delphi 6 might contain the necessary header translations, but since Delphi 6 is not yet shipping (it has been announced <http://www.borland.com/about/press/2001/del6released.html> , though), it is impossible to confirm.
The sample application demonstrates using two IP Helper API functions, GetNetworkParams and GetAdaptersInfo. They are declared like this (translated from IPHLPAPI.H):
Function GetNetworkParams(FI : PFixedInfo; Var BufLen : Integer) : Integer;
StdCall; External 'iphlpapi.dll' Name 'GetNetworkParams';
Function GetAdaptersInfo(AI : PIPAdapterInfo; Var BufLen : Integer) : Integer;
StdCall; External 'iphlpapi.dll' Name 'GetAdaptersInfo';
As you can see, both of these functions are implemented in IPHLPAPI.DLL. The first function can be used to return overall information about the IP configuration of the system. The sample application uses the following procedure to demonstrate the usage of the function:
procedure TIPMainForm.GetNetworkParameters;
Var
FI : PFixedInfo;
Size : Integer;
Res : Integer;
I : Integer;
DNS : PIPAddrString;
begin
Size := 1024;
GetMem(FI,Size);
Res := GetNetworkParams(FI,Size);
If (Res <> ERROR_SUCCESS) Then Begin
SetLastError(Res);
RaiseLastWin32Error;
End;
With Info,Lines do Begin
Clear;
Add('Host name: '+FI^.HostName);
Add('Domain name: '+FI^.DomainName);
If (FI^.CurrentDNSServer <> nil) Then
Add('Current DNS Server: '+FI^.CurrentDNSServer^.IPAddress)
Else Add('Current DNS Server: (none)');
I := 1;
DNS := @FI^.DNSServerList;
Repeat
Add('DNS '+IntToStr(I)+': '+DNS^.IPAddress);
Inc(I);
DNS := DNS^.Next;
Until (DNS = nil);
Add('Scope ID: '+FI^.ScopeId);
Add('Routing: '+IntToStr(FI^.EnableRouting));
Add('Proxy: '+IntToStr(FI^.EnableProxy));
Add('DNS: '+IntToStr(FI^.EnableDNS));
End;
FreeMem(FI);
end;
Similarly, the GetAdaptersInfo function can be used like this:
procedure TIPMainForm.GetAdapterInformation;
Var
AI,Work : PIPAdapterInfo;
Size : Integer;
Res : Integer;
I : Integer;
begin
Size := 5120;
GetMem(AI,Size);
Res := GetAdaptersInfo(AI,Size);
If (Res <> ERROR_SUCCESS) Then Begin
SetLastError(Res);
RaiseLastWin32Error;
End;
With Info,Lines do Begin
Work := AI;
I := 1;
Repeat
Add('');
Add('Adapter '+IntToStr(I));
Add(' ComboIndex: '+IntToStr(Work^.ComboIndex));
Add(' Adapter name: '+Work^.AdapterName);
Add(' Description: '+Work^.Description);
Add(' Adapter address: '+MACToStr(@Work^.Address,Work^.AddressLength));
Add(' Index: '+IntToStr(Work^.Index));
Add(' Type: '+IntToStr(Work^._Type));
Add(' DHCP: '+IntToStr(Work^.DHCPEnabled));
Add(' Current IP: '+GetAddrString(Work^.CurrentIPAddress));
Add(' IP addresses: '+GetAddrString(@Work^.IPAddressList));
Add(' Gateways: '+GetAddrString(@Work^.GatewayList));
Add(' DHCP servers: '+GetAddrString(@Work^.DHCPServer));
Add(' Has WINS: '+IntToStr(Integer(Work^.HaveWINS)));
Add(' Primary WINS: '+GetAddrString(@Work^.PrimaryWINSServer));
Add(' Secondary WINS: '+GetAddrString(@Work^.SecondaryWINSServer));
Add(' Lease obtained: '+TimeTToDateTimeStr(Work^.LeaseObtained));
Add(' Lease expires: '+TimeTToDateTimeStr(Work^.LeaseExpires));
Inc(I);
Work := Work^.Next;
Until (Work = nil);
End;
FreeMem(AI);
end;
Since GetAdaptersInfo is able to return complex information about the network adapters installed to the system, you need to be extra-careful when converting the information to the display. The sample application uses the following three helper functions:
Function MACToStr(ByteArr : PByte; Len : Integer) : String;
Begin
Result := '';
While (Len > 0) do Begin
Result := Result+IntToHex(ByteArr^,2)+'-';
ByteArr := Pointer(Integer(ByteArr)+SizeOf(Byte));
Dec(Len);
End;
SetLength(Result,Length(Result)-1); { remove last dash }
End;
Function GetAddrString(Addr : PIPAddrString) : String;
Begin
Result := '';
While (Addr <> nil) do Begin
Result := Result+'A: '+Addr^.IPAddress+' M: '+Addr^.IPMask+#13;
Addr := Addr^.Next;
End;
End;
Function TimeTToDateTimeStr(TimeT : Integer) : String;
Const UnixDateDelta = 25569; { days between 12/31/1899 and 1/1/1970 }
Var
DT : TDateTime;
TZ : TTimeZoneInformation;
Res : DWord;
Begin
If (TimeT = 0) Then Result := ''
Else Begin
{ Unix TIME_T is secs since 1/1/1970 }
DT := UnixDateDelta+(TimeT / (24*60*60)); { in UTC }
{ calculate bias }
Res := GetTimeZoneInformation(TZ);
If (Res = TIME_ZONE_ID_INVALID) Then RaiseLastWin32Error;
If (Res = TIME_ZONE_ID_STANDARD) Then Begin
DT := DT-((TZ.Bias+TZ.StandardBias) / (24*60));
Result := DateTimeToStr(DT)+' '+WideCharToString(TZ.StandardName);
End
Else Begin { daylight saving time }
DT := DT-((TZ.Bias+TZ.DaylightBias) / (24*60));
Result := DateTimeToStr(DT)+' '+WideCharToString(TZ.DaylightName);
End;
End;
End;
The last function, TimeTToDateTimeStr, is particularly interesting because it is able to convert a Unix Time_T type to a TDateTime, and also take into account local time zone and daylight savings time (DST).
Testing the sample application
Once you have downloaded the sample application (see below), and compiled it, you are ready to run the application. The main user interface is really quite trivial, but nonetheless the following information is displayed on screen:
Host name: emerald
Domain name: pp.htv.fi
Current DNS Server: (none)
DNS 1: 212.93.64.18
DNS 2: 212.93.64.16
Scope ID:
Routing: 0
Proxy: 0
DNS: 0
Adapter 1
ComboIndex: 0
Adapter name: {F2B85B21-4E6F-4EDB-AE3E-87BB6B5CAD73}
Description: 3Com 3C90x Ethernet Adapter
Adapter address: 00-60-08-10-28-79
Index: 0
Type: 6
DHCP: 1
Current IP:
IP addresses: A: 212.93.92.191 M: 255.255.255.0
Gateways: A: 212.93.92.1 M: 0.0.0.0
DHCP servers: A: 212.93.64.98 M:
Has WINS: 0
Primary WINS: A: 0.0.0.0 M: 0.0.0.0
Secondary WINS: A: 0.0.0.0 M: 0.0.0.0
Lease obtained: 20.5.2001 14:31:49 FLE Daylight Time
Lease expires: 20.5.2001 19:31:49 FLE Daylight Time
In case you are interested, the main screen looks like this:
Certainly, the information will be quite different on your computer, but you get the idea. For more details about the IP Helper API library, see the Platform SDK documentation, available from http://msdn.microsoft.com .
Download the example code
Download usingtheiphelperapi.zip <http://www.whirlwater.com/downloads/2001/usingtheiphelperapi.zip> (167 kB) which contains the sample application IP Helper Demo that uses the IP Helper API available in Windows 2000. Please note that the sample application requires Delphi 5 or later and Windows 2000 or later.