Mobile development: pocketHosts-Edit Windows Mobile hosts entries
PocketPC and Windows Mobile does not support a hosts file as desktop windows. As I recently had to add an entry for a virtual machine running Mini SAP (Netweaver 7.01 Trial) I stumbled about how to add a host entry to a windows mobile device.
The platform builder help gives the details about how host entries are organized:
Host Name
The host name can be configured through the HKEY_LOCAL_MACHINE\Comm\Tcpip\Hosts subkey. When an application calls gethostbyname or getaddrinfo, the registry is queried first, before a DNS or WINS request is sent. If the host name is found in the registry, the registry values are returned.
The following table shows the values for the HKEY_LOCAL_MACHINE\Comm\Tcpip\Hosts\<Host Name> subkey.
Value : type | Description |
---|---|
Aliases : REG_MULTI_SZ | This value stores the aliases by which this host is known. |
ExpireTime : REG_BINARY | If the current time, obtained by calling GetCurrentFT, exceeds the value in ExpireTime, the entire Host Name subkey is deleted the next time that gethostbyname is called. The length of this value is 8 bytes. |
ipaddr : REG_BINARY | This value stores the IPv4 addresses associated with this host name. The length of this value is 4 bytes per address. |
ipaddr6 : REG_BINARY | This value stores the IPv6 addresses associated with this host name. The length of this value is 20 bytes per address (16 bytes for address and 4 bytes for Scope ID). |
So, there is no simple hosts file.
Before struggling all the time with these entries I decided to write a small app to manage these entries: pocketHosts.
I created a class hostsentry to hold each hosts details and a class hostsentries to hold all host entries.
... public class hostsentry { //################################################################## public string sHost { get; set; } public List<System.Net.IPAddress> ipAddress { get; set; } public List<System.Net.IPAddress> ipAddress6 { get; set; } public List<string> aliases { get; set; } private ulong _expireTime = 0; public ulong expireTime { get { return (uint)_expireTime; } set { _expireTime = (ulong)value; } } ...
The hostsentries class:
... public class hostsentries:IDisposable { const string regSubKey = @"Comm\Tcpip\Hosts"; RegistryKey rKeyTCPIP; public Dictionary<string, hostsentry> allHosts; public hostsentries() { allHosts = new Dictionary<string, hostsentry>(); init(); } ...
The registry can hold IP4 and IP6 addresses. pocketHosts shows them in one list:
Then there are some helper functions to convert byte arrays of ipaddr and ipaddr6 to single ipAddresses. All ipAddresses are saved to the registry as binary:
... //convert 20010db8ac10fe010000000000000000 //to 2001:0db8:ac10:fe01:0000:0000:0000:0000 private string getIP6StrfromByte(byte[] bIpAddress6) { if (bIpAddress6.Length != 16) return ""; string sIP6 = ""; for (int i = 0; i < 16; i++) { byte b = bIpAddress6[i]; sIP6 += b.ToString("x02"); if (i > 0 && i % 2 != 0 && i != 15) sIP6 += ":"; } return sIP6; } private System.Net.IPAddress getIP6fromByte(byte[] bIpAddress6) { System.Net.IPAddress ip6 = new System.Net.IPAddress((long)0); string sIP = getIP6StrfromByte(bIpAddress6); if (sIP != "") { try{ ip6 = System.Net.IPAddress.Parse(sIP); } catch(Exception){} } return ip6; } ...
These function are called to convert the byte arrays back to IP addresses. The functions to convert the IP addresses back to bytes are much easier:
... List<byte> b = new List<byte>(); foreach (System.Net.IPAddress ip in he.ipAddress) { b.AddRange(ip.GetAddressBytes()); iRet++; } if(b.Count>=4) regWork.SetValue("ipaddr", b.ToArray(), RegistryValueKind.Binary); b.Clear(); foreach (System.Net.IPAddress ip6 in he.ipAddress6) { b.AddRange(ip6.GetAddressBytes()); iRet++; } if (b.Count >= 4) regWork.SetValue("ipaddr6", b.ToArray(), RegistryValueKind.Binary); ...
Although the registry holds the IP addresses in ipaddr and ipaddr6 entries. The application can treat both IP address types the same. Only when saving, the list has to be diverted into IP4 and IP6 addresses.
The source code (VS2005, WM5 SDK, CF2) and a binary can be found at my code.google.com repository.
There is one bug I could not fix: you cannot remove a hosts entry. The RegDelKey function always returns an error.