diff --git a/Demo.WindowsForms/Source/Program.cs b/Demo.WindowsForms/Source/Program.cs
new file mode 100644
--- /dev/null
+++ b/Demo.WindowsForms/Source/Program.cs
@@ -0,0 +1,428 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Net;
+using System.Net.NetworkInformation;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Windows.Forms;
+using System.IO;
+using System.IO.Ports;
+using System.Threading;
+
+namespace Demo.WindowsForms
+{
+ class Program
+ {
+ ///
+ /// The main entry point for the application.
+ ///
+ ///
+ // Instantiate the communications port
+ private SerialPort port = new SerialPort("COM1", 9600, Parity.None, 8, StopBits.One);
+ static MainForm windowGUI;
+
+ [STAThread]
+ static void Main()
+ {
+ Application.SetCompatibleTextRenderingDefault(false);
+ var program = new Program();
+ windowGUI = new MainForm();
+ program.SerialInitialize();
+ Application.EnableVisualStyles();
+
+ Application.Run(new MainForm());
+ }
+
+ //inits the serial port and event handler
+ private void SerialInitialize()
+ {
+ // http://msmvps.com/blogs/coad/archive/2005/03/23/SerialPort-_2800_RS_2D00_232-Serial-COM-Port_2900_-in-C_2300_-.NET.aspx
+ // Attach a method to be called when there is data waiting in the port's buffer
+ port.DataReceived += new SerialDataReceivedEventHandler(ReceiveData);
+
+ // Open the port for communications
+ port.Open();
+
+ }
+
+ //process received data
+ private void ReceiveData(object sender, SerialDataReceivedEventArgs e)
+ {
+ // Show all the incoming data in the port's buffer
+ string testChk = port.ReadLine();
+ windowGUI.ParseIncomingData(testChk);
+ }
+ }
+
+ public class Dummy
+ {
+
+ }
+
+ class IpInfo
+ {
+ public string Ip;
+ //public int Port;
+ //public TcpState State;
+ //public string ProcessName;
+
+ public string CountryName;
+ public string RegionName;
+ public string City;
+ public double Latitude;
+ public double Longitude;
+ public DateTime CacheTime;
+
+ //public DateTime StatusTime;
+ //public bool TracePoint;
+ }
+
+ struct IpStatus
+ {
+ private string countryName;
+ public string CountryName
+ {
+ get
+ {
+ return countryName;
+ }
+ set
+ {
+ countryName = value;
+ }
+ }
+
+ private int connectionsCount;
+ public int ConnectionsCount
+ {
+ get
+ {
+ return connectionsCount;
+ }
+ set
+ {
+ connectionsCount = value;
+ }
+ }
+ }
+
+ class DescendingComparer : IComparer
+ {
+ public bool SortOnlyCountryName = false;
+
+ public int Compare(IpStatus x, IpStatus y)
+ {
+ int r = 0;
+
+ if(!SortOnlyCountryName)
+ {
+ r = y.ConnectionsCount.CompareTo(x.ConnectionsCount);
+ }
+
+ if(r == 0)
+ {
+ return x.CountryName.CompareTo(y.CountryName);
+ }
+ return r;
+ }
+ }
+
+ class TraceRoute
+ {
+ readonly static string Data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
+ readonly static byte[] DataBuffer;
+ readonly static int timeout = 8888;
+
+ static TraceRoute()
+ {
+ DataBuffer = Encoding.ASCII.GetBytes(Data);
+ }
+
+ public static List GetTraceRoute(string hostNameOrAddress)
+ {
+ var ret = GetTraceRoute(hostNameOrAddress, 1);
+
+ return ret;
+ }
+
+ private static List GetTraceRoute(string hostNameOrAddress, int ttl)
+ {
+ List result = new List();
+
+ using(Ping pinger = new Ping())
+ {
+ PingOptions pingerOptions = new PingOptions(ttl, true);
+
+ PingReply reply = pinger.Send(hostNameOrAddress, timeout, DataBuffer, pingerOptions);
+
+ //Debug.WriteLine("GetTraceRoute[" + hostNameOrAddress + "]: " + reply.RoundtripTime + "ms " + reply.Address + " -> " + reply.Status);
+
+ if(reply.Status == IPStatus.Success)
+ {
+ result.Add(reply);
+ }
+ else if(reply.Status == IPStatus.TtlExpired)
+ {
+ // add the currently returned address
+ result.Add(reply);
+
+ // recurse to get the next address...
+ result.AddRange(GetTraceRoute(hostNameOrAddress, ttl + 1));
+ }
+ else
+ {
+ Debug.WriteLine("GetTraceRoute: " + hostNameOrAddress + " - " + reply.Status);
+ }
+ }
+
+ return result;
+ }
+ }
+
+
+#if !MONO
+ #region Managed IP Helper API
+
+ public struct TcpTable : IEnumerable
+ {
+ #region Private Fields
+
+ private IEnumerable tcpRows;
+
+ #endregion
+
+ #region Constructors
+
+ public TcpTable(IEnumerable tcpRows)
+ {
+ this.tcpRows = tcpRows;
+ }
+
+ #endregion
+
+ #region Public Properties
+
+ public IEnumerable Rows
+ {
+ get
+ {
+ return this.tcpRows;
+ }
+ }
+
+ #endregion
+
+ #region IEnumerable Members
+
+ public IEnumerator GetEnumerator()
+ {
+ return this.tcpRows.GetEnumerator();
+ }
+
+ #endregion
+
+ #region IEnumerable Members
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return this.tcpRows.GetEnumerator();
+ }
+
+ #endregion
+ }
+
+ public struct TcpRow
+ {
+ #region Private Fields
+
+ private IPEndPoint localEndPoint;
+ private IPEndPoint remoteEndPoint;
+ private TcpState state;
+ private int processId;
+
+ #endregion
+
+ #region Constructors
+
+ public TcpRow(IpHelper.TcpRow tcpRow)
+ {
+ this.state = tcpRow.state;
+ this.processId = tcpRow.owningPid;
+
+ int localPort = (tcpRow.localPort1 << 8) + (tcpRow.localPort2) + (tcpRow.localPort3 << 24) + (tcpRow.localPort4 << 16);
+ long localAddress = tcpRow.localAddr;
+ this.localEndPoint = new IPEndPoint(localAddress, localPort);
+
+ int remotePort = (tcpRow.remotePort1 << 8) + (tcpRow.remotePort2) + (tcpRow.remotePort3 << 24) + (tcpRow.remotePort4 << 16);
+ long remoteAddress = tcpRow.remoteAddr;
+ this.remoteEndPoint = new IPEndPoint(remoteAddress, remotePort);
+ }
+
+ #endregion
+
+ #region Public Properties
+
+ public IPEndPoint LocalEndPoint
+ {
+ get
+ {
+ return this.localEndPoint;
+ }
+ }
+
+ public IPEndPoint RemoteEndPoint
+ {
+ get
+ {
+ return this.remoteEndPoint;
+ }
+ }
+
+ public TcpState State
+ {
+ get
+ {
+ return this.state;
+ }
+ }
+
+ public int ProcessId
+ {
+ get
+ {
+ return this.processId;
+ }
+ }
+
+ #endregion
+ }
+
+ public static class ManagedIpHelper
+ {
+ public static readonly List TcpRows = new List();
+
+ #region Public Methods
+
+ public static void UpdateExtendedTcpTable(bool sorted)
+ {
+ TcpRows.Clear();
+
+ IntPtr tcpTable = IntPtr.Zero;
+ int tcpTableLength = 0;
+
+ if(IpHelper.GetExtendedTcpTable(tcpTable, ref tcpTableLength, sorted, IpHelper.AfInet, IpHelper.TcpTableType.OwnerPidConnections, 0) != 0)
+ {
+ try
+ {
+ tcpTable = Marshal.AllocHGlobal(tcpTableLength);
+ if(IpHelper.GetExtendedTcpTable(tcpTable, ref tcpTableLength, true, IpHelper.AfInet, IpHelper.TcpTableType.OwnerPidConnections, 0) == 0)
+ {
+ IpHelper.TcpTable table = (IpHelper.TcpTable)Marshal.PtrToStructure(tcpTable, typeof(IpHelper.TcpTable));
+
+ IntPtr rowPtr = (IntPtr)((long)tcpTable + Marshal.SizeOf(table.Length));
+ for(int i = 0; i < table.Length; ++i)
+ {
+ TcpRows.Add(new TcpRow((IpHelper.TcpRow)Marshal.PtrToStructure(rowPtr, typeof(IpHelper.TcpRow))));
+ rowPtr = (IntPtr)((long)rowPtr + Marshal.SizeOf(typeof(IpHelper.TcpRow)));
+ }
+ }
+ }
+ finally
+ {
+ if(tcpTable != IntPtr.Zero)
+ {
+ Marshal.FreeHGlobal(tcpTable);
+ }
+ }
+ }
+ }
+
+ #endregion
+ }
+
+ #endregion
+
+ #region P/Invoke IP Helper API
+
+ ///
+ ///
+ ///
+ public static class IpHelper
+ {
+ #region Public Fields
+
+ public const string DllName = "iphlpapi.dll";
+ public const int AfInet = 2;
+
+ #endregion
+
+ #region Public Methods
+
+ ///
+ ///
+ ///
+ [DllImport(IpHelper.DllName, SetLastError = true)]
+ public static extern uint GetExtendedTcpTable(IntPtr tcpTable, ref int tcpTableLength, bool sort, int ipVersion, TcpTableType tcpTableType, int reserved);
+
+ #endregion
+
+ #region Public Enums
+
+ ///
+ ///
+ ///
+ public enum TcpTableType
+ {
+ BasicListener,
+ BasicConnections,
+ BasicAll,
+ OwnerPidListener,
+ OwnerPidConnections,
+ OwnerPidAll,
+ OwnerModuleListener,
+ OwnerModuleConnections,
+ OwnerModuleAll,
+ }
+
+ #endregion
+
+ #region Public Structs
+
+ ///
+ ///
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ public struct TcpTable
+ {
+ public uint Length;
+ public TcpRow row;
+ }
+
+ ///
+ ///
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ public struct TcpRow
+ {
+ public TcpState state;
+ public uint localAddr;
+ public byte localPort1;
+ public byte localPort2;
+ public byte localPort3;
+ public byte localPort4;
+ public uint remoteAddr;
+ public byte remotePort1;
+ public byte remotePort2;
+ public byte remotePort3;
+ public byte remotePort4;
+ public int owningPid;
+ }
+
+ #endregion
+ }
+
+ #endregion
+#endif
+}