{"id":1812,"date":"2013-09-24T16:27:49","date_gmt":"2013-09-24T14:27:49","guid":{"rendered":"http:\/\/www.hjgode.de\/wp\/?p=1812"},"modified":"2013-09-24T16:53:21","modified_gmt":"2013-09-24T14:53:21","slug":"mobile-development-pockethosts-edit-windows-mobile-hosts-entries","status":"publish","type":"post","link":"https:\/\/www.hjgode.de\/wp\/2013\/09\/24\/mobile-development-pockethosts-edit-windows-mobile-hosts-entries\/","title":{"rendered":"Mobile development: pocketHosts-Edit Windows Mobile hosts entries"},"content":{"rendered":"<p>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.<\/p>\n<p><a href=\"http:\/\/www.hjgode.de\/wp\/wp-content\/uploads\/2013\/09\/Clipboard01.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-medium wp-image-1813\" alt=\"pocketHosts\" src=\"http:\/\/www.hjgode.de\/wp\/wp-content\/uploads\/2013\/09\/Clipboard01-225x300.jpg\" width=\"225\" height=\"300\" srcset=\"https:\/\/www.hjgode.de\/wp\/wp-content\/uploads\/2013\/09\/Clipboard01-225x300.jpg 225w, https:\/\/www.hjgode.de\/wp\/wp-content\/uploads\/2013\/09\/Clipboard01-112x150.jpg 112w, https:\/\/www.hjgode.de\/wp\/wp-content\/uploads\/2013\/09\/Clipboard01.jpg 240w\" sizes=\"(max-width: 225px) 100vw, 225px\" \/><\/a><\/p>\n<p>The platform builder help gives the details about how host entries are organized:<\/p>\n<h4>Host Name<\/h4>\n<p>The host name can be configured through the <b>HKEY_LOCAL_MACHINE\\Comm\\Tcpip\\Hosts<\/b> 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.<\/p>\n<p>The following table shows the values for the <b>HKEY_LOCAL_MACHINE\\Comm\\Tcpip\\Hosts\\<\/b>&lt;<i>Host Name<\/i>&gt; subkey.<\/p>\n<div>\n<table cellspacing=\"0\">\n<tbody>\n<tr valign=\"top\">\n<th width=\"34%\">Value : type<\/th>\n<th width=\"66%\">Description<\/th>\n<\/tr>\n<tr valign=\"top\">\n<td width=\"34%\"><b>Aliases<\/b> : REG_MULTI_SZ<\/td>\n<td width=\"66%\">This value stores the aliases by which this host is known.<\/td>\n<\/tr>\n<tr valign=\"top\">\n<td width=\"34%\"><b>ExpireTime<\/b> : REG_BINARY<\/td>\n<td width=\"66%\">If the current time, obtained by calling <b>GetCurrentFT<\/b>, exceeds the value in <b>ExpireTime<\/b>, the entire <i>Host Name<\/i> subkey is deleted the next time that <b>gethostbyname<\/b> is called. The length of this value is 8 bytes.<\/td>\n<\/tr>\n<tr valign=\"top\">\n<td width=\"34%\"><b>ipaddr<\/b> : REG_BINARY<\/td>\n<td width=\"66%\">This value stores the IPv4 addresses associated with this host name. The length of this value is 4 bytes per address.<\/td>\n<\/tr>\n<tr valign=\"top\">\n<td width=\"34%\"><b>ipaddr6<\/b> : REG_BINARY<\/td>\n<td width=\"66%\">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).<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>So, there is no simple hosts file.<\/p>\n<p><!--more--><\/p>\n<p>Before struggling all the time with these entries I decided to write a small app to manage these entries: pocketHosts.<\/p>\n<p>I created a class hostsentry to hold each hosts details and a class hostsentries to hold all host entries.<\/p>\n<pre>...\u00a0\u00a0\u00a0 \r\n    public class hostsentry\r\n\u00a0\u00a0\u00a0 {\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/##################################################################\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 public string sHost { get; set; }\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 public List&lt;System.Net.IPAddress&gt; ipAddress { get; set; }\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 public List&lt;System.Net.IPAddress&gt; ipAddress6 { get; set; }\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 public List&lt;string&gt; aliases { get; set; }\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 private ulong _expireTime = 0;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 public ulong expireTime { get { return (uint)_expireTime; } set { _expireTime = (ulong)value; } }\r\n...<\/pre>\n<p>The hostsentries class:<\/p>\n<pre>...\r\n\u00a0\u00a0\u00a0 public class hostsentries:IDisposable\r\n\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 const string regSubKey = @\"Comm\\Tcpip\\Hosts\";\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 RegistryKey rKeyTCPIP;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 public Dictionary&lt;string, hostsentry&gt; allHosts;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 public hostsentries()\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 allHosts = new Dictionary&lt;string, hostsentry&gt;();\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 init();\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n...<\/pre>\n<p>The registry can hold IP4 and IP6 addresses. pocketHosts shows them in one list:<\/p>\n<p><a href=\"http:\/\/www.hjgode.de\/wp\/wp-content\/uploads\/2013\/09\/pocketHostsIPentry.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-medium wp-image-1814\" alt=\"pocketHostsIPentry\" src=\"http:\/\/www.hjgode.de\/wp\/wp-content\/uploads\/2013\/09\/pocketHostsIPentry-225x300.jpg\" width=\"225\" height=\"300\" srcset=\"https:\/\/www.hjgode.de\/wp\/wp-content\/uploads\/2013\/09\/pocketHostsIPentry-225x300.jpg 225w, https:\/\/www.hjgode.de\/wp\/wp-content\/uploads\/2013\/09\/pocketHostsIPentry-112x150.jpg 112w, https:\/\/www.hjgode.de\/wp\/wp-content\/uploads\/2013\/09\/pocketHostsIPentry.jpg 240w\" sizes=\"(max-width: 225px) 100vw, 225px\" \/><\/a><\/p>\n<p>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:<\/p>\n<pre>...\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/convert 20010db8ac10fe010000000000000000\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/to 2001:0db8:ac10:fe01:0000:0000:0000:0000\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 private string getIP6StrfromByte(byte[] bIpAddress6)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (bIpAddress6.Length != 16)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return \"\";\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 string sIP6 = \"\";\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 for (int i = 0; i &lt; 16; i++)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 byte b = bIpAddress6[i];\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 sIP6 += b.ToString(\"x02\");\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (i &gt; 0 &amp;&amp; i % 2 != 0 &amp;&amp; i != 15)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 sIP6 += \":\";\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return sIP6;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 private System.Net.IPAddress getIP6fromByte(byte[] bIpAddress6)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 System.Net.IPAddress ip6 = new System.Net.IPAddress((long)0);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 string sIP = getIP6StrfromByte(bIpAddress6);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (sIP != \"\")\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 try{\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ip6 = System.Net.IPAddress.Parse(sIP);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 catch(Exception){}\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return ip6;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n...<\/pre>\n<p>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:<\/p>\n<pre>...\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 List&lt;byte&gt; b = new List&lt;byte&gt;();\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 foreach (System.Net.IPAddress ip in he.ipAddress)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 b.AddRange(ip.GetAddressBytes());\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 iRet++;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if(b.Count&gt;=4)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 regWork.SetValue(\"ipaddr\", b.ToArray(), RegistryValueKind.Binary);\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 b.Clear();\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 foreach (System.Net.IPAddress ip6 in he.ipAddress6)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <strong>b.AddRange(ip6.GetAddressBytes());<\/strong>\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 iRet++;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (b.Count &gt;= 4)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 regWork.SetValue(\"ipaddr6\", b.ToArray(), RegistryValueKind.Binary);\r\n...<\/pre>\n<p>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.<\/p>\n<p>The source code (VS2005, WM5 SDK, CF2) and a binary can be found at my <a title=\"pocketHosts source and bin\" href=\"http:\/\/code.google.com\/p\/win-mobile-code\/source\/browse\/#svn%2Ftrunk%2FpocketHosts\" target=\"_blank\">code.google.com<\/a> repository.<\/p>\n<p>There is one bug I could not fix: you cannot remove a hosts entry. The RegDelKey function always returns an error.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>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 [&hellip;]<\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[178,3,4,5],"tags":[539,169,392,15],"class_list":["post-1812","post","type-post","status-publish","format-standard","hentry","category-codeproject","category-programming","category-tools","category-utilities","tag-codeproject","tag-compact-framework","tag-hosts","tag-windows-mobile"],"_links":{"self":[{"href":"https:\/\/www.hjgode.de\/wp\/wp-json\/wp\/v2\/posts\/1812"}],"collection":[{"href":"https:\/\/www.hjgode.de\/wp\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.hjgode.de\/wp\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.hjgode.de\/wp\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/www.hjgode.de\/wp\/wp-json\/wp\/v2\/comments?post=1812"}],"version-history":[{"count":2,"href":"https:\/\/www.hjgode.de\/wp\/wp-json\/wp\/v2\/posts\/1812\/revisions"}],"predecessor-version":[{"id":1820,"href":"https:\/\/www.hjgode.de\/wp\/wp-json\/wp\/v2\/posts\/1812\/revisions\/1820"}],"wp:attachment":[{"href":"https:\/\/www.hjgode.de\/wp\/wp-json\/wp\/v2\/media?parent=1812"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.hjgode.de\/wp\/wp-json\/wp\/v2\/categories?post=1812"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.hjgode.de\/wp\/wp-json\/wp\/v2\/tags?post=1812"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}