Network DNS menu made configurable by user

This commit is contained in:
Shreyas Zare
2019-02-16 18:30:37 +05:30
parent 8149c4659a
commit 87bf6074ac
7 changed files with 1110 additions and 181 deletions

View File

@@ -0,0 +1,135 @@
/*
Technitium DNS Server
Copyright (C) 2019 Shreyas Zare (shreyas@technitium.com)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Sockets;
using TechnitiumLibrary.IO;
using TechnitiumLibrary.Net;
namespace DnsServerSystemTrayApp
{
public class DnsProvider : IComparable<DnsProvider>
{
#region variables
public string Name;
public ICollection<IPAddress> Addresses;
#endregion
#region constructor
public DnsProvider(string name, ICollection<IPAddress> addresses)
{
this.Name = name;
this.Addresses = addresses;
}
public DnsProvider(BinaryReader bR)
{
this.Name = bR.ReadShortString();
this.Addresses = new List<IPAddress>();
int count = bR.ReadInt32();
for (int i = 0; i < count; i++)
this.Addresses.Add(IPAddressExtension.Parse(bR));
}
#endregion
#region static
public static DnsProvider[] GetDefaultProviders()
{
return new DnsProvider[] {
new DnsProvider("Technitium", new IPAddress[] { IPAddress.Loopback, IPAddress.IPv6Loopback }),
new DnsProvider("Cloudflare", new IPAddress[] { IPAddress.Parse("1.1.1.1"), IPAddress.Parse("1.0.0.1"), IPAddress.Parse("[2606:4700:4700::1111]"), IPAddress.Parse("[2606:4700:4700::1001]") }),
new DnsProvider("Google", new IPAddress[] { IPAddress.Parse("8.8.8.8"), IPAddress.Parse("8.8.4.4"), IPAddress.Parse("[2001:4860:4860::8888]"), IPAddress.Parse("[2001:4860:4860::8844]") }),
new DnsProvider("Quad9", new IPAddress[] { IPAddress.Parse("9.9.9.9"), IPAddress.Parse("[2620:fe::fe]") }),
new DnsProvider("OpenDNS", new IPAddress[] { IPAddress.Parse("208.67.222.222"), IPAddress.Parse("208.67.220.220"), IPAddress.Parse("[2620:0:ccc::2]"), IPAddress.Parse("[2620:0:ccd::2]") })
};
}
#endregion
#region public
public string GetIpv4Addresses()
{
string ipv4Addresses = null;
foreach (IPAddress address in Addresses)
{
if (address.AddressFamily == AddressFamily.InterNetwork)
{
if (ipv4Addresses == null)
ipv4Addresses = address.ToString();
else
ipv4Addresses += ", " + address.ToString();
}
}
return ipv4Addresses;
}
public string GetIpv6Addresses()
{
string ipv6Addresses = null;
foreach (IPAddress address in Addresses)
{
if (address.AddressFamily == AddressFamily.InterNetworkV6)
{
if (ipv6Addresses == null)
ipv6Addresses = address.ToString();
else
ipv6Addresses += ", " + address.ToString();
}
}
return ipv6Addresses;
}
public override string ToString()
{
return Name;
}
public int CompareTo(DnsProvider other)
{
return this.Name.CompareTo(other.Name);
}
public void WriteTo(BinaryWriter bW)
{
bW.WriteShortString(Name);
bW.Write(Addresses.Count);
foreach (IPAddress address in Addresses)
address.WriteTo(bW);
}
#endregion
}
}

View File

@@ -38,28 +38,43 @@
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.Management" />
<Reference Include="System.ServiceProcess" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
<Reference Include="TechnitiumLibrary.IO, Version=2.5.4.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\TechnitiumLibrary\bin\TechnitiumLibrary.IO.dll</HintPath>
</Reference>
<Reference Include="TechnitiumLibrary.Net">
<HintPath>..\..\TechnitiumLibrary\bin\TechnitiumLibrary.Net.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="AboutForm.cs">
<Compile Include="DnsProvider.cs" />
<Compile Include="frmAbout.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="AboutForm.Designer.cs">
<DependentUpon>AboutForm.cs</DependentUpon>
<Compile Include="frmAbout.Designer.cs">
<DependentUpon>frmAbout.cs</DependentUpon>
</Compile>
<Compile Include="frmManageDnsProviders.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="frmManageDnsProviders.Designer.cs">
<DependentUpon>frmManageDnsProviders.cs</DependentUpon>
</Compile>
<Compile Include="NotifyIconExtension.cs" />
<Compile Include="MainApplicationContext.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<EmbeddedResource Include="AboutForm.resx">
<DependentUpon>AboutForm.cs</DependentUpon>
<EmbeddedResource Include="frmAbout.resx">
<DependentUpon>frmAbout.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="frmManageDnsProviders.resx">
<DependentUpon>frmManageDnsProviders.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>

View File

@@ -20,6 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
using DnsServerSystemTrayApp.Properties;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
@@ -43,19 +44,15 @@ namespace DnsServerSystemTrayApp
const int SERVICE_WAIT_TIMEOUT_SECONDS = 30;
private readonly ServiceController _service = new ServiceController("DnsService");
readonly IPAddress[] _cloudflareDns = new IPAddress[] { IPAddress.Parse("1.1.1.1"), IPAddress.Parse("1.0.0.1") };
readonly IPAddress[] _googleDns = new IPAddress[] { IPAddress.Parse("8.8.8.8"), IPAddress.Parse("8.8.4.4") };
readonly IPAddress[] _quad9Dns = new IPAddress[] { IPAddress.Parse("9.9.9.9") };
readonly string _configFile;
readonly List<DnsProvider> _dnsProviders = new List<DnsProvider>();
private NotifyIcon TrayIcon;
private ContextMenuStrip TrayIconContextMenu;
private ToolStripMenuItem DashboardMenuItem;
private ToolStripMenuItem NetworkDnsMenuItem;
private ToolStripMenuItem DefaultNetworkDnsMenuItem;
private ToolStripMenuItem TechnitiumNetworkDnsMenuItem;
private ToolStripMenuItem CloudflareNetworkDnsMenuItem;
private ToolStripMenuItem GoogleNetworkDnsMenuItem;
private ToolStripMenuItem Quad9NetworkDnsMenuItem;
private ToolStripMenuItem ManageNetworkDnsMenuItem;
private ToolStripMenuItem ServiceMenuItem;
private ToolStripMenuItem StartServiceMenuItem;
private ToolStripMenuItem RestartServiceMenuItem;
@@ -68,8 +65,11 @@ namespace DnsServerSystemTrayApp
#region constructor
public MainApplicationContext()
public MainApplicationContext(string configFile)
{
_configFile = configFile;
LoadConfig();
InitializeComponent();
}
@@ -102,7 +102,7 @@ namespace DnsServerSystemTrayApp
//
// TrayIcon
//
var resources = new ComponentResourceManager(typeof(AboutForm));
var resources = new ComponentResourceManager(typeof(frmAbout));
TrayIcon = new NotifyIcon();
TrayIcon.Icon = (Icon)resources.GetObject("$this.Icon");
TrayIcon.Visible = true;
@@ -129,27 +129,8 @@ namespace DnsServerSystemTrayApp
DefaultNetworkDnsMenuItem = new ToolStripMenuItem("Default");
DefaultNetworkDnsMenuItem.Click += DefaultNetworkDnsMenuItem_Click;
TechnitiumNetworkDnsMenuItem = new ToolStripMenuItem("Technitium");
TechnitiumNetworkDnsMenuItem.Click += TechnitiumNetworkDnsMenuItem_Click;
CloudflareNetworkDnsMenuItem = new ToolStripMenuItem("Cloudflare");
CloudflareNetworkDnsMenuItem.Click += CloudflareNetworkDnsMenuItem_Click;
GoogleNetworkDnsMenuItem = new ToolStripMenuItem("Google");
GoogleNetworkDnsMenuItem.Click += GoogleNetworkDnsMenuItem_Click;
Quad9NetworkDnsMenuItem = new ToolStripMenuItem("IBM Quad9");
Quad9NetworkDnsMenuItem.Click += Quad9NetworkDnsMenuItem_Click;
NetworkDnsMenuItem.DropDownItems.AddRange(new ToolStripItem[]
{
DefaultNetworkDnsMenuItem,
new ToolStripSeparator(),
TechnitiumNetworkDnsMenuItem,
CloudflareNetworkDnsMenuItem,
GoogleNetworkDnsMenuItem,
Quad9NetworkDnsMenuItem
});
ManageNetworkDnsMenuItem = new ToolStripMenuItem("Manage");
ManageNetworkDnsMenuItem.Click += ManageNetworkDnsMenuItem_Click;
//
// ServiceMenuItem
@@ -213,7 +194,76 @@ namespace DnsServerSystemTrayApp
TrayIconContextMenu.ResumeLayout(false);
}
private static void SetNameServerIPv4(NetworkInterface nic, IPAddress[] dnsAddresses)
private void LoadConfig()
{
try
{
using (FileStream fS = new FileStream(_configFile, FileMode.Open, FileAccess.Read))
{
BinaryReader bR = new BinaryReader(fS);
if (Encoding.ASCII.GetString(bR.ReadBytes(2)) != "DT")
throw new InvalidDataException("Invalid DNS Server System Tray App config file format.");
switch (bR.ReadByte())
{
case 1:
int count = bR.ReadInt32();
_dnsProviders.Clear();
for (int i = 0; i < count; i++)
_dnsProviders.Add(new DnsProvider(bR));
_dnsProviders.Sort();
break;
default:
throw new NotSupportedException("DNS Server System Tray App config file format is not supported.");
}
}
}
catch (FileNotFoundException)
{
_dnsProviders.Clear();
_dnsProviders.AddRange(DnsProvider.GetDefaultProviders());
SaveConfig();
}
catch (Exception ex)
{
MessageBox.Show("Error occured while loading config file. " + ex.Message, "Error - " + Resources.ServiceName, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void SaveConfig()
{
try
{
using (FileStream fS = new FileStream(_configFile, FileMode.Create, FileAccess.Write))
{
BinaryWriter bW = new BinaryWriter(fS);
bW.Write(Encoding.ASCII.GetBytes("DT"));
bW.Write((byte)1);
bW.Write(_dnsProviders.Count);
foreach (DnsProvider dnsProvider in _dnsProviders)
dnsProvider.WriteTo(bW);
}
}
catch (Exception ex)
{
MessageBox.Show("Error occured while saving config file. " + ex.Message, "Error - " + Resources.ServiceName, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private static void SetNameServer(NetworkInterface nic, ICollection<IPAddress> dnsAddresses)
{
SetNameServerIPv4(nic, dnsAddresses);
SetNameServerIPv6(nic, dnsAddresses);
}
private static void SetNameServerIPv4(NetworkInterface nic, ICollection<IPAddress> dnsAddresses)
{
ManagementClass networkAdapterConfig = new ManagementClass("Win32_NetworkAdapterConfiguration");
ManagementObjectCollection instances = networkAdapterConfig.GetInstances();
@@ -222,17 +272,18 @@ namespace DnsServerSystemTrayApp
{
if ((bool)obj["IPEnabled"] && obj["SettingID"].Equals(nic.Id))
{
string[] dnsServers = new string[dnsAddresses.Length];
List<string> dnsServers = new List<string>();
for (int i = 0; i < dnsServers.Length; i++)
foreach (IPAddress dnsAddress in dnsAddresses)
{
if (dnsAddresses[i].AddressFamily != AddressFamily.InterNetwork)
throw new ArgumentException();
if (dnsAddress.AddressFamily != AddressFamily.InterNetwork)
continue;
dnsServers[i] = dnsAddresses[i].ToString();
dnsServers.Add(dnsAddress.ToString());
}
ManagementBaseObject objParameter = obj.GetMethodParameters("SetDNSServerSearchOrder");
objParameter["DNSServerSearchOrder"] = dnsServers;
objParameter["DNSServerSearchOrder"] = dnsServers.ToArray();
ManagementBaseObject response = obj.InvokeMethod("SetDNSServerSearchOrder", objParameter, null);
uint returnValue = (uint)response.GetPropertyValue("ReturnValue");
@@ -267,7 +318,7 @@ namespace DnsServerSystemTrayApp
}
}
private static void SetNameServerIPv6(NetworkInterface nic, IPAddress[] dnsAddresses)
private static void SetNameServerIPv6(NetworkInterface nic, ICollection<IPAddress> dnsAddresses)
{
//HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip6\Parameters\Interfaces\{}
@@ -276,7 +327,7 @@ namespace DnsServerSystemTrayApp
foreach (IPAddress dnsAddress in dnsAddresses)
{
if (dnsAddress.AddressFamily != AddressFamily.InterNetworkV6)
throw new ArgumentException();
continue;
if (nameServer == null)
nameServer = dnsAddress.ToString();
@@ -294,13 +345,16 @@ namespace DnsServerSystemTrayApp
}
}
private static bool AddressExists(IPAddress checkAddress, IPAddress[] addresses)
private static bool AddressExists(ICollection<IPAddress> checkAddresses, ICollection<IPAddress> addresses)
{
foreach (IPAddress checkAddress in checkAddresses)
{
foreach (IPAddress address in addresses)
{
if (checkAddress.Equals(address))
return true;
}
}
return false;
}
@@ -311,11 +365,7 @@ namespace DnsServerSystemTrayApp
{
#region Network DNS
bool isDefaultDns = false;
bool isTechnitiumDns = false;
bool isCloudflareDns = false;
bool isGoogleDns = false;
bool isQuad9Dns = false;
List<IPAddress> networkDnsAddresses = new List<IPAddress>();
try
{
@@ -324,42 +374,51 @@ namespace DnsServerSystemTrayApp
if (nic.OperationalStatus != OperationalStatus.Up)
continue;
foreach (IPAddress dnsAddress in nic.GetIPProperties().DnsAddresses)
{
if (IPAddress.IsLoopback(dnsAddress))
{
isTechnitiumDns = true;
}
else if (AddressExists(dnsAddress, _cloudflareDns))
{
isCloudflareDns = true;
}
else if (AddressExists(dnsAddress, _googleDns))
{
isGoogleDns = true;
}
else if (AddressExists(dnsAddress, _quad9Dns))
{
isQuad9Dns = true;
}
else if (!dnsAddress.IsIPv6SiteLocal)
{
isDefaultDns = true;
}
if (isDefaultDns && isTechnitiumDns && isCloudflareDns && isGoogleDns && isQuad9Dns)
break;
}
networkDnsAddresses.AddRange(nic.GetIPProperties().DnsAddresses);
}
}
catch
{ }
DefaultNetworkDnsMenuItem.Checked = isDefaultDns;
TechnitiumNetworkDnsMenuItem.Checked = isTechnitiumDns;
CloudflareNetworkDnsMenuItem.Checked = isCloudflareDns;
GoogleNetworkDnsMenuItem.Checked = isGoogleDns;
Quad9NetworkDnsMenuItem.Checked = isQuad9Dns;
NetworkDnsMenuItem.DropDownItems.Clear();
NetworkDnsMenuItem.DropDownItems.Add(DefaultNetworkDnsMenuItem);
NetworkDnsMenuItem.DropDownItems.Add(new ToolStripSeparator());
bool noItemChecked = true;
DefaultNetworkDnsMenuItem.Checked = false;
foreach (DnsProvider dnsProvider in _dnsProviders)
{
ToolStripMenuItem item = new ToolStripMenuItem(dnsProvider.Name);
item.Tag = dnsProvider;
item.Click += NetworkDnsMenuSubItem_Click;
if (AddressExists(networkDnsAddresses, dnsProvider.Addresses))
{
item.Checked = true;
noItemChecked = false;
}
NetworkDnsMenuItem.DropDownItems.Add(item);
}
if (noItemChecked)
{
foreach (IPAddress dnsAddress in networkDnsAddresses)
{
if (!dnsAddress.IsIPv6SiteLocal)
{
DefaultNetworkDnsMenuItem.Checked = true;
break;
}
}
}
if (_dnsProviders.Count > 0)
NetworkDnsMenuItem.DropDownItems.Add(new ToolStripSeparator());
NetworkDnsMenuItem.DropDownItems.Add(ManageNetworkDnsMenuItem);
#endregion
@@ -370,7 +429,6 @@ namespace DnsServerSystemTrayApp
switch (_service.Status)
{
case ServiceControllerStatus.Stopped:
TechnitiumNetworkDnsMenuItem.Enabled = false;
DashboardMenuItem.Enabled = false;
StartServiceMenuItem.Enabled = true;
RestartServiceMenuItem.Enabled = false;
@@ -378,7 +436,6 @@ namespace DnsServerSystemTrayApp
break;
case ServiceControllerStatus.Running:
TechnitiumNetworkDnsMenuItem.Enabled = true;
DashboardMenuItem.Enabled = true;
StartServiceMenuItem.Enabled = false;
RestartServiceMenuItem.Enabled = true;
@@ -386,7 +443,6 @@ namespace DnsServerSystemTrayApp
break;
default:
TechnitiumNetworkDnsMenuItem.Enabled = false;
DashboardMenuItem.Enabled = false;
StartServiceMenuItem.Enabled = false;
RestartServiceMenuItem.Enabled = false;
@@ -398,7 +454,6 @@ namespace DnsServerSystemTrayApp
}
catch
{
TechnitiumNetworkDnsMenuItem.Enabled = false;
DashboardMenuItem.Enabled = false;
ServiceMenuItem.Enabled = false;
}
@@ -471,6 +526,8 @@ namespace DnsServerSystemTrayApp
SetNameServerIPv6(nic, new IPAddress[] { });
try
{
IPInterfaceProperties properties = nic.GetIPProperties();
if (properties.GetIPv4Properties().IsDhcpEnabled)
@@ -486,6 +543,9 @@ namespace DnsServerSystemTrayApp
SetNameServerIPv4(nic, new IPAddress[] { });
}
}
catch (NetworkInformationException)
{ }
}
MessageBox.Show("The network DNS servers were set to default successfully.", "Default DNS Set - " + Resources.ServiceName, MessageBoxButtons.OK, MessageBoxIcon.Information);
}
@@ -495,8 +555,26 @@ namespace DnsServerSystemTrayApp
}
}
private void TechnitiumNetworkDnsMenuItem_Click(object sender, EventArgs e)
private void ManageNetworkDnsMenuItem_Click(object sender, EventArgs e)
{
using (frmManageDnsProviders frm = new frmManageDnsProviders(_dnsProviders))
{
if (frm.ShowDialog() == DialogResult.OK)
{
_dnsProviders.Clear();
_dnsProviders.AddRange(frm.DnsProviders);
_dnsProviders.Sort();
SaveConfig();
}
}
}
private void NetworkDnsMenuSubItem_Click(object sender, EventArgs e)
{
ToolStripMenuItem item = sender as ToolStripMenuItem;
DnsProvider dnsProvider = item.Tag as DnsProvider;
try
{
foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces())
@@ -507,95 +585,14 @@ namespace DnsServerSystemTrayApp
IPInterfaceProperties properties = nic.GetIPProperties();
if ((properties.DnsAddresses.Count > 0) && !properties.DnsAddresses[0].IsIPv6SiteLocal)
{
SetNameServerIPv6(nic, new IPAddress[] { IPAddress.IPv6Loopback });
SetNameServerIPv4(nic, new IPAddress[] { IPAddress.Loopback });
}
SetNameServer(nic, dnsProvider.Addresses);
}
MessageBox.Show("The network DNS servers were set to Technitium DNS successfully.", "Technitium DNS Set - " + Resources.ServiceName, MessageBoxButtons.OK, MessageBoxIcon.Information);
MessageBox.Show("The network DNS servers were set to " + dnsProvider.Name + " successfully.", dnsProvider.Name + " Configured - " + Resources.ServiceName, MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception ex)
{
MessageBox.Show("Error occured while setting Technitium as network DNS server. " + ex.Message, "Error - " + Resources.ServiceName, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void CloudflareNetworkDnsMenuItem_Click(object sender, EventArgs e)
{
try
{
foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces())
{
if (nic.OperationalStatus != OperationalStatus.Up)
continue;
IPInterfaceProperties properties = nic.GetIPProperties();
if ((properties.DnsAddresses.Count > 0) && !properties.DnsAddresses[0].IsIPv6SiteLocal)
{
SetNameServerIPv6(nic, new IPAddress[] { });
SetNameServerIPv4(nic, _cloudflareDns);
}
}
MessageBox.Show("The network DNS servers were set to Cloudflare DNS successfully.", "Cloudflare DNS Set - " + Resources.ServiceName, MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception ex)
{
MessageBox.Show("Error occured while setting Cloudflare as network DNS server. " + ex.Message, "Error - " + Resources.ServiceName, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void GoogleNetworkDnsMenuItem_Click(object sender, EventArgs e)
{
try
{
foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces())
{
if (nic.OperationalStatus != OperationalStatus.Up)
continue;
IPInterfaceProperties properties = nic.GetIPProperties();
if ((properties.DnsAddresses.Count > 0) && !properties.DnsAddresses[0].IsIPv6SiteLocal)
{
SetNameServerIPv6(nic, new IPAddress[] { });
SetNameServerIPv4(nic, _googleDns);
}
}
MessageBox.Show("The network DNS servers were set to Google DNS successfully.", "Google DNS Set - " + Resources.ServiceName, MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception ex)
{
MessageBox.Show("Error occured while setting Google as network DNS server. " + ex.Message, "Error - " + Resources.ServiceName, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void Quad9NetworkDnsMenuItem_Click(object sender, EventArgs e)
{
try
{
foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces())
{
if (nic.OperationalStatus != OperationalStatus.Up)
continue;
IPInterfaceProperties properties = nic.GetIPProperties();
if ((properties.DnsAddresses.Count > 0) && !properties.DnsAddresses[0].IsIPv6SiteLocal)
{
SetNameServerIPv6(nic, new IPAddress[] { });
SetNameServerIPv4(nic, _quad9Dns);
}
}
MessageBox.Show("The network DNS servers were set to IBM Quad9 DNS successfully.", "IBM Quad9 DNS Set - " + Resources.ServiceName, MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception ex)
{
MessageBox.Show("Error occured while setting IBM Quad9 as network DNS server. " + ex.Message, "Error - " + Resources.ServiceName, MessageBoxButtons.OK, MessageBoxIcon.Error);
MessageBox.Show("Error occured while setting " + dnsProvider.Name + " as network DNS server. " + ex.Message, "Error - " + Resources.ServiceName, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
@@ -660,9 +657,9 @@ namespace DnsServerSystemTrayApp
private void AboutMenuItem_Click(object sender, EventArgs e)
{
using (AboutForm aboutForm = new AboutForm())
using (frmAbout frm = new frmAbout())
{
aboutForm.ShowDialog();
frm.ShowDialog();
}
}

View File

@@ -20,6 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Security.Principal;
using System.Threading;
@@ -45,12 +46,13 @@ namespace DnsServerSystemTrayApp
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
string appPath = Assembly.GetEntryAssembly().Location;
#region admin elevation
bool isAdmin = (new WindowsPrincipal(WindowsIdentity.GetCurrent())).IsInRole(WindowsBuiltInRole.Administrator);
if (!isAdmin)
{
string appPath = Assembly.GetEntryAssembly().Location;
ProcessStartInfo processInfo = new ProcessStartInfo(appPath, string.Join(" ", args));
processInfo.UseShellExecute = true;
@@ -86,7 +88,9 @@ namespace DnsServerSystemTrayApp
#endregion
Application.Run(new MainApplicationContext());
string configFile = Path.Combine(Path.GetDirectoryName(appPath), "SystemTrayApp.config");
Application.Run(new MainApplicationContext(configFile));
}
#endregion

View File

@@ -0,0 +1,270 @@
namespace DnsServerSystemTrayApp
{
partial class frmManageDnsProviders
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(frmManageDnsProviders));
this.listView1 = new System.Windows.Forms.ListView();
this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.columnHeader3 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.btnDelete = new System.Windows.Forms.Button();
this.btnClear = new System.Windows.Forms.Button();
this.btnAddUpdate = new System.Windows.Forms.Button();
this.txtIpv6Addresses = new System.Windows.Forms.TextBox();
this.label3 = new System.Windows.Forms.Label();
this.txtIpv4Addresses = new System.Windows.Forms.TextBox();
this.label2 = new System.Windows.Forms.Label();
this.txtDnsProviderName = new System.Windows.Forms.TextBox();
this.label1 = new System.Windows.Forms.Label();
this.btnOK = new System.Windows.Forms.Button();
this.btnCancel = new System.Windows.Forms.Button();
this.btnRestoreDefaults = new System.Windows.Forms.Button();
this.groupBox1.SuspendLayout();
this.SuspendLayout();
//
// listView1
//
this.listView1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.listView1.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.columnHeader1,
this.columnHeader2,
this.columnHeader3});
this.listView1.FullRowSelect = true;
this.listView1.HideSelection = false;
this.listView1.Location = new System.Drawing.Point(12, 12);
this.listView1.MultiSelect = false;
this.listView1.Name = "listView1";
this.listView1.Size = new System.Drawing.Size(660, 200);
this.listView1.Sorting = System.Windows.Forms.SortOrder.Ascending;
this.listView1.TabIndex = 0;
this.listView1.UseCompatibleStateImageBehavior = false;
this.listView1.View = System.Windows.Forms.View.Details;
this.listView1.SelectedIndexChanged += new System.EventHandler(this.listView1_SelectedIndexChanged);
//
// columnHeader1
//
this.columnHeader1.Text = "DNS Provider";
this.columnHeader1.Width = 150;
//
// columnHeader2
//
this.columnHeader2.Text = "IPv4 Addresses";
this.columnHeader2.Width = 240;
//
// columnHeader3
//
this.columnHeader3.Text = "IPv6 Addresses";
this.columnHeader3.Width = 240;
//
// groupBox1
//
this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.groupBox1.Controls.Add(this.btnDelete);
this.groupBox1.Controls.Add(this.btnClear);
this.groupBox1.Controls.Add(this.btnAddUpdate);
this.groupBox1.Controls.Add(this.txtIpv6Addresses);
this.groupBox1.Controls.Add(this.label3);
this.groupBox1.Controls.Add(this.txtIpv4Addresses);
this.groupBox1.Controls.Add(this.label2);
this.groupBox1.Controls.Add(this.txtDnsProviderName);
this.groupBox1.Controls.Add(this.label1);
this.groupBox1.Location = new System.Drawing.Point(12, 216);
this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new System.Drawing.Size(661, 130);
this.groupBox1.TabIndex = 9;
this.groupBox1.TabStop = false;
//
// btnDelete
//
this.btnDelete.Enabled = false;
this.btnDelete.Location = new System.Drawing.Point(179, 97);
this.btnDelete.Name = "btnDelete";
this.btnDelete.Size = new System.Drawing.Size(75, 23);
this.btnDelete.TabIndex = 16;
this.btnDelete.Text = "&Delete";
this.btnDelete.UseVisualStyleBackColor = true;
this.btnDelete.Click += new System.EventHandler(this.btnDelete_Click);
//
// btnClear
//
this.btnClear.Location = new System.Drawing.Point(260, 97);
this.btnClear.Name = "btnClear";
this.btnClear.Size = new System.Drawing.Size(75, 23);
this.btnClear.TabIndex = 17;
this.btnClear.Text = "&Clear";
this.btnClear.UseVisualStyleBackColor = true;
this.btnClear.Click += new System.EventHandler(this.btnClear_Click);
//
// btnAddUpdate
//
this.btnAddUpdate.Location = new System.Drawing.Point(98, 97);
this.btnAddUpdate.Name = "btnAddUpdate";
this.btnAddUpdate.Size = new System.Drawing.Size(75, 23);
this.btnAddUpdate.TabIndex = 15;
this.btnAddUpdate.Text = "&Add";
this.btnAddUpdate.UseVisualStyleBackColor = true;
this.btnAddUpdate.Click += new System.EventHandler(this.btnAddUpdate_Click);
//
// txtIpv6Addresses
//
this.txtIpv6Addresses.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.txtIpv6Addresses.Location = new System.Drawing.Point(98, 71);
this.txtIpv6Addresses.MaxLength = 255;
this.txtIpv6Addresses.Name = "txtIpv6Addresses";
this.txtIpv6Addresses.Size = new System.Drawing.Size(552, 20);
this.txtIpv6Addresses.TabIndex = 14;
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(11, 74);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(81, 13);
this.label3.TabIndex = 13;
this.label3.Text = "IPv6 Addresses";
//
// txtIpv4Addresses
//
this.txtIpv4Addresses.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.txtIpv4Addresses.Location = new System.Drawing.Point(98, 45);
this.txtIpv4Addresses.MaxLength = 255;
this.txtIpv4Addresses.Name = "txtIpv4Addresses";
this.txtIpv4Addresses.Size = new System.Drawing.Size(552, 20);
this.txtIpv4Addresses.TabIndex = 12;
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(11, 48);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(81, 13);
this.label2.TabIndex = 11;
this.label2.Text = "IPv4 Addresses";
//
// txtDnsProviderName
//
this.txtDnsProviderName.Location = new System.Drawing.Point(98, 19);
this.txtDnsProviderName.MaxLength = 255;
this.txtDnsProviderName.Name = "txtDnsProviderName";
this.txtDnsProviderName.Size = new System.Drawing.Size(200, 20);
this.txtDnsProviderName.TabIndex = 10;
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(20, 22);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(72, 13);
this.label1.TabIndex = 9;
this.label1.Text = "DNS Provider";
//
// btnOK
//
this.btnOK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.btnOK.DialogResult = System.Windows.Forms.DialogResult.OK;
this.btnOK.Location = new System.Drawing.Point(517, 356);
this.btnOK.Name = "btnOK";
this.btnOK.Size = new System.Drawing.Size(75, 23);
this.btnOK.TabIndex = 10;
this.btnOK.Text = "OK";
this.btnOK.UseVisualStyleBackColor = true;
//
// btnCancel
//
this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.btnCancel.Location = new System.Drawing.Point(598, 356);
this.btnCancel.Name = "btnCancel";
this.btnCancel.Size = new System.Drawing.Size(75, 23);
this.btnCancel.TabIndex = 11;
this.btnCancel.Text = "Cancel";
this.btnCancel.UseVisualStyleBackColor = true;
//
// btnRestoreDefaults
//
this.btnRestoreDefaults.Location = new System.Drawing.Point(12, 356);
this.btnRestoreDefaults.Name = "btnRestoreDefaults";
this.btnRestoreDefaults.Size = new System.Drawing.Size(100, 23);
this.btnRestoreDefaults.TabIndex = 12;
this.btnRestoreDefaults.Text = "Restore &Defaults";
this.btnRestoreDefaults.UseVisualStyleBackColor = true;
this.btnRestoreDefaults.Click += new System.EventHandler(this.btnRestoreDefaults_Click);
//
// frmManageDnsProviders
//
this.AcceptButton = this.btnOK;
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.CancelButton = this.btnCancel;
this.ClientSize = new System.Drawing.Size(684, 386);
this.Controls.Add(this.btnRestoreDefaults);
this.Controls.Add(this.btnCancel);
this.Controls.Add(this.btnOK);
this.Controls.Add(this.groupBox1);
this.Controls.Add(this.listView1);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "frmManageDnsProviders";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "Manage Network DNS Providers - Technitium DNS Server";
this.Load += new System.EventHandler(this.frmManageDnsProviders_Load);
this.groupBox1.ResumeLayout(false);
this.groupBox1.PerformLayout();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.ListView listView1;
private System.Windows.Forms.ColumnHeader columnHeader1;
private System.Windows.Forms.ColumnHeader columnHeader2;
private System.Windows.Forms.ColumnHeader columnHeader3;
private System.Windows.Forms.GroupBox groupBox1;
private System.Windows.Forms.Button btnClear;
private System.Windows.Forms.Button btnAddUpdate;
private System.Windows.Forms.TextBox txtIpv6Addresses;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.TextBox txtIpv4Addresses;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.TextBox txtDnsProviderName;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Button btnOK;
private System.Windows.Forms.Button btnCancel;
private System.Windows.Forms.Button btnRestoreDefaults;
private System.Windows.Forms.Button btnDelete;
}
}

View File

@@ -0,0 +1,196 @@
/*
Technitium DNS Server
Copyright (C) 2019 Shreyas Zare (shreyas@technitium.com)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Windows.Forms;
namespace DnsServerSystemTrayApp
{
public partial class frmManageDnsProviders : Form
{
#region variables
readonly List<DnsProvider> _dnsProviders = new List<DnsProvider>();
#endregion
#region constructor
public frmManageDnsProviders(ICollection<DnsProvider> dnsProviders)
{
InitializeComponent();
_dnsProviders.AddRange(dnsProviders);
}
#endregion
#region private
private void RefreshDnsProvidersList()
{
listView1.SuspendLayout();
listView1.Items.Clear();
foreach (DnsProvider dnsProvider in _dnsProviders)
{
ListViewItem item = listView1.Items.Add(dnsProvider.Name);
item.SubItems.Add(dnsProvider.GetIpv4Addresses());
item.SubItems.Add(dnsProvider.GetIpv6Addresses());
item.Tag = dnsProvider;
}
listView1.ResumeLayout();
}
private void ClearForm()
{
txtDnsProviderName.Text = "";
txtIpv4Addresses.Text = "";
txtIpv6Addresses.Text = "";
btnAddUpdate.Text = "Add";
btnDelete.Enabled = false;
}
private void frmManageDnsProviders_Load(object sender, EventArgs e)
{
RefreshDnsProvidersList();
}
private void listView1_SelectedIndexChanged(object sender, EventArgs e)
{
if (listView1.SelectedItems.Count > 0)
{
ListViewItem selectedItem = listView1.SelectedItems[0];
txtDnsProviderName.Text = selectedItem.Text;
txtIpv4Addresses.Text = selectedItem.SubItems[1].Text;
txtIpv6Addresses.Text = selectedItem.SubItems[2].Text;
btnAddUpdate.Text = "&Update";
btnDelete.Enabled = true;
}
else
{
ClearForm();
}
}
private void btnAddUpdate_Click(object sender, EventArgs e)
{
if (string.IsNullOrWhiteSpace(txtDnsProviderName.Text))
{
MessageBox.Show("Please enter a valid DNS Provider name.", "Missing DNS Provider!", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
return;
}
List<IPAddress> addresses = new List<IPAddress>();
foreach (string item in txtIpv4Addresses.Text.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
{
if (IPAddress.TryParse(item.Trim(), out IPAddress address) && (address.AddressFamily == AddressFamily.InterNetwork))
{
addresses.Add(address);
}
else
{
MessageBox.Show("Please enter a valid IPv4 address.", "Invalid IPv4 Address!", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
return;
}
}
foreach (string item in txtIpv6Addresses.Text.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
{
if (IPAddress.TryParse(item.Trim(), out IPAddress address) && (address.AddressFamily == AddressFamily.InterNetworkV6))
{
addresses.Add(address);
}
else
{
MessageBox.Show("Please enter a valid IPv6 address.", "Invalid IPv6 Address!", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
return;
}
}
if (addresses.Count == 0)
{
MessageBox.Show("Please enter at least one valid DNS provider IP address.", "Missing DNS Provider IP Address!", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
return;
}
if ((btnAddUpdate.Text != "Add") && (listView1.SelectedItems.Count > 0))
{
ListViewItem selectedItem = listView1.SelectedItems[0];
DnsProvider dnsProvider = selectedItem.Tag as DnsProvider;
dnsProvider.Name = txtDnsProviderName.Text.Trim();
dnsProvider.Addresses = addresses;
}
else
{
_dnsProviders.Add(new DnsProvider(txtDnsProviderName.Text.Trim(), addresses));
}
RefreshDnsProvidersList();
ClearForm();
}
private void btnDelete_Click(object sender, EventArgs e)
{
if (listView1.SelectedItems.Count > 0)
{
ListViewItem selectedItem = listView1.SelectedItems[0];
DnsProvider dnsProvider = selectedItem.Tag as DnsProvider;
_dnsProviders.Remove(dnsProvider);
listView1.Items.Remove(selectedItem);
}
RefreshDnsProvidersList();
ClearForm();
}
private void btnClear_Click(object sender, EventArgs e)
{
ClearForm();
}
private void btnRestoreDefaults_Click(object sender, EventArgs e)
{
_dnsProviders.Clear();
_dnsProviders.AddRange(DnsProvider.GetDefaultProviders());
RefreshDnsProvidersList();
ClearForm();
}
#endregion
#region properties
public List<DnsProvider> DnsProviders
{ get { return _dnsProviders; } }
#endregion
}
}

View File

@@ -0,0 +1,312 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="listView1.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="groupBox1.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="btnDelete.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="btnClear.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="btnAddUpdate.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="txtIpv6Addresses.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="label3.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="txtIpv4Addresses.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="label2.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="txtDnsProviderName.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="label1.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="btnOK.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="btnCancel.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="btnRestoreDefaults.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="$this.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
AAABAAUAICAQAAAAAADoAgAAVgAAACAgAAAAAAAAqAgAAD4DAAAwMAAAAAAAAKgOAADmCwAAEBAQAAAA
AAAoAQAAjhoAABAQAAAAAAAAaAUAALYbAAAoAAAAIAAAAEAAAAABAAQAAAAAAIACAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAgAAAgAAAAICAAIAAAACAAIAAgIAAAMDAwACAgIAAAAD/AAD/AAAA//8A/wAAAP8A
/wD//wAA////AMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzP//zP//////////////zMz/
/8z//////////////8zM///M///////////////MzP//zP//////////////zMz//8zMzMzMzMz//8zM
zMzM///MzMzMzMzM///MzMzMzP//////////zP//zP//zMz//////////8z//8z//8zM///////////M
///M///MzP//////////zP//zP//zMz//8zMzMzMzMz//8z//8zM///MzMzMzMzM///M///MzP//zP//
zMzMzP//zP//zMz//8z//8zMzMz//8z//8zM///M///MzMzM///M///MzP//zP//zMzMzP//zP//zMz/
/8z//8zMzMzMzMz//8zM///M///MzMzMzMzM///MzP//zP//zP//////////zMz//8z//8z/////////
/8zM///M///M///////////MzP//zP//zP//////////zMzMzMz//8zMzMzMzMz//8zMzMzM///MzMzM
zMzM///MzP//////////////zP//zMz//////////////8z//8zM///////////////M///MzP//////
////////zP//zMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAIAAAAEAA
AAABAAgAAAAAAIAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAgAAAAICAAIAAAACAAIAAgIAAAMDA
wADA3MAA8MqmAAQEBAAICAgADAwMABEREQAWFhYAHBwcACIiIgApKSkAVVVVAE1NTQBCQkIAOTk5AIB8
/wBQUP8AkwDWAP/szADG1u8A1ufnAJCprQAAADMAAABmAAAAmQAAAMwAADMAAAAzMwAAM2YAADOZAAAz
zAAAM/8AAGYAAABmMwAAZmYAAGaZAABmzAAAZv8AAJkAAACZMwAAmWYAAJmZAACZzAAAmf8AAMwAAADM
MwAAzGYAAMyZAADMzAAAzP8AAP9mAAD/mQAA/8wAMwAAADMAMwAzAGYAMwCZADMAzAAzAP8AMzMAADMz
MwAzM2YAMzOZADMzzAAzM/8AM2YAADNmMwAzZmYAM2aZADNmzAAzZv8AM5kAADOZMwAzmWYAM5mZADOZ
zAAzmf8AM8wAADPMMwAzzGYAM8yZADPMzAAzzP8AM/8zADP/ZgAz/5kAM//MADP//wBmAAAAZgAzAGYA
ZgBmAJkAZgDMAGYA/wBmMwAAZjMzAGYzZgBmM5kAZjPMAGYz/wBmZgAAZmYzAGZmZgBmZpkAZmbMAGaZ
AABmmTMAZplmAGaZmQBmmcwAZpn/AGbMAABmzDMAZsyZAGbMzABmzP8AZv8AAGb/MwBm/5kAZv/MAMwA
/wD/AMwAmZkAAJkzmQCZAJkAmQDMAJkAAACZMzMAmQBmAJkzzACZAP8AmWYAAJlmMwCZM2YAmWaZAJlm
zACZM/8AmZkzAJmZZgCZmZkAmZnMAJmZ/wCZzAAAmcwzAGbMZgCZzJkAmczMAJnM/wCZ/wAAmf8zAJnM
ZgCZ/5kAmf/MAJn//wDMAAAAmQAzAMwAZgDMAJkAzADMAJkzAADMMzMAzDNmAMwzmQDMM8wAzDP/AMxm
AADMZjMAmWZmAMxmmQDMZswAmWb/AMyZAADMmTMAzJlmAMyZmQDMmcwAzJn/AMzMAADMzDMAzMxmAMzM
mQDMzMwAzMz/AMz/AADM/zMAmf9mAMz/mQDM/8wAzP//AMwAMwD/AGYA/wCZAMwzAAD/MzMA/zNmAP8z
mQD/M8wA/zP/AP9mAAD/ZjMAzGZmAP9mmQD/ZswAzGb/AP+ZAAD/mTMA/5lmAP+ZmQD/mcwA/5n/AP/M
AAD/zDMA/8xmAP/MmQD/zMwA/8z/AP//MwDM/2YA//+ZAP//zABmZv8AZv9mAGb//wD/ZmYA/2b/AP//
ZgAhAKUAX19fAHd3dwCGhoYAlpaWAMvLywCysrIA19fXAN3d3QDj4+MA6urqAPHx8QD4+PgA8Pv/AKSg
oACAgIAAAAD/AAD/AAAA//8A/wAAAP8A/wD//wAA////ANXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV
1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1f/////V1f//////////////////
///////////V1dXV/////9XV/////////////////////////////9XV1dX/////1dX/////////////
////////////////1dXV1f/////V1f/////////////////////////////V1dXV/////9XV1dXV1dXV
1dXV1dXV/////9XV1dXV1dXV1dX/////1dXV1dXV1dXV1dXV1dX/////1dXV1dXV1dXV1f//////////
///////////V1f/////V1f/////V1dXV/////////////////////9XV/////9XV/////9XV1dX/////
////////////////1dX/////1dX/////1dXV1f/////////////////////V1f/////V1f/////V1dXV
/////9XV1dXV1dXV1dXV1dXV/////9XV/////9XV1dX/////1dXV1dXV1dXV1dXV1dX/////1dX/////
1dXV1f/////V1f/////V1dXV1dXV1f/////V1f/////V1dXV/////9XV/////9XV1dXV1dXV/////9XV
/////9XV1dX/////1dX/////1dXV1dXV1dX/////1dX/////1dXV1f/////V1f/////V1dXV1dXV1f//
///V1f/////V1dXV/////9XV/////9XV1dXV1dXV1dXV1dXV/////9XV1dX/////1dX/////1dXV1dXV
1dXV1dXV1dX/////1dXV1f/////V1f/////V1f/////////////////////V1dXV/////9XV/////9XV
/////////////////////9XV1dX/////1dX/////1dX/////////////////////1dXV1f/////V1f//
///V1f/////////////////////V1dXV1dXV1dXV/////9XV1dXV1dXV1dXV1dXV/////9XV1dXV1dXV
1dX/////1dXV1dXV1dXV1dXV1dX/////1dXV1f/////////////////////////////V1f/////V1dXV
/////////////////////////////9XV/////9XV1dX/////////////////////////////1dX/////
1dXV1f/////////////////////////////V1f/////V1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV
1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dUAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAwAAAAYAAAAAEA
CAAAAAAAgAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAACAAAAAgIAAgAAAAIAAgACAgAAAwMDAAMDc
wADwyqYABAQEAAgICAAMDAwAERERABYWFgAcHBwAIiIiACkpKQBVVVUATU1NAEJCQgA5OTkAgHz/AFBQ
/wCTANYA/+zMAMbW7wDW5+cAkKmtAAAAMwAAAGYAAACZAAAAzAAAMwAAADMzAAAzZgAAM5kAADPMAAAz
/wAAZgAAAGYzAABmZgAAZpkAAGbMAABm/wAAmQAAAJkzAACZZgAAmZkAAJnMAACZ/wAAzAAAAMwzAADM
ZgAAzJkAAMzMAADM/wAA/2YAAP+ZAAD/zAAzAAAAMwAzADMAZgAzAJkAMwDMADMA/wAzMwAAMzMzADMz
ZgAzM5kAMzPMADMz/wAzZgAAM2YzADNmZgAzZpkAM2bMADNm/wAzmQAAM5kzADOZZgAzmZkAM5nMADOZ
/wAzzAAAM8wzADPMZgAzzJkAM8zMADPM/wAz/zMAM/9mADP/mQAz/8wAM///AGYAAABmADMAZgBmAGYA
mQBmAMwAZgD/AGYzAABmMzMAZjNmAGYzmQBmM8wAZjP/AGZmAABmZjMAZmZmAGZmmQBmZswAZpkAAGaZ
MwBmmWYAZpmZAGaZzABmmf8AZswAAGbMMwBmzJkAZszMAGbM/wBm/wAAZv8zAGb/mQBm/8wAzAD/AP8A
zACZmQAAmTOZAJkAmQCZAMwAmQAAAJkzMwCZAGYAmTPMAJkA/wCZZgAAmWYzAJkzZgCZZpkAmWbMAJkz
/wCZmTMAmZlmAJmZmQCZmcwAmZn/AJnMAACZzDMAZsxmAJnMmQCZzMwAmcz/AJn/AACZ/zMAmcxmAJn/
mQCZ/8wAmf//AMwAAACZADMAzABmAMwAmQDMAMwAmTMAAMwzMwDMM2YAzDOZAMwzzADMM/8AzGYAAMxm
MwCZZmYAzGaZAMxmzACZZv8AzJkAAMyZMwDMmWYAzJmZAMyZzADMmf8AzMwAAMzMMwDMzGYAzMyZAMzM
zADMzP8AzP8AAMz/MwCZ/2YAzP+ZAMz/zADM//8AzAAzAP8AZgD/AJkAzDMAAP8zMwD/M2YA/zOZAP8z
zAD/M/8A/2YAAP9mMwDMZmYA/2aZAP9mzADMZv8A/5kAAP+ZMwD/mWYA/5mZAP+ZzAD/mf8A/8wAAP/M
MwD/zGYA/8yZAP/MzAD/zP8A//8zAMz/ZgD//5kA///MAGZm/wBm/2YAZv//AP9mZgD/Zv8A//9mACEA
pQBfX18Ad3d3AIaGhgCWlpYAy8vLALKysgDX19cA3d3dAOPj4wDq6uoA8fHxAPj4+ADw+/8ApKCgAICA
gAAAAP8AAP8AAAD//wD/AAAA/wD/AP//AAD///8A1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV
1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV
1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV////
////1dXV////////////////////////////////////////////1dXV1dXV////////1dXV////////
////////////////////////////////////1dXV1dXV////////1dXV////////////////////////
////////////////////1dXV1dXV////////1dXV////////////////////////////////////////
////1dXV1dXV////////1dXV////////////////////////////////////////////1dXV1dXV////
////1dXV////////////////////////////////////////////1dXV1dXV////////1dXV1dXV1dXV
1dXV1dXV1dXV1dXV////////1dXV1dXV1dXV1dXV1dXV////////1dXV1dXV1dXV1dXV1dXV1dXV1dXV
////////1dXV1dXV1dXV1dXV1dXV////////1dXV1dXV1dXV1dXV1dXV1dXV1dXV////////1dXV1dXV
1dXV1dXV1dXV////////////////////////////////1dXV////////1dXV////////1dXV1dXV////
////////////////////////////1dXV////////1dXV////////1dXV1dXV////////////////////
////////////1dXV////////1dXV////////1dXV1dXV////////////////////////////////1dXV
////////1dXV////////1dXV1dXV////////////////////////////////1dXV////////1dXV////
////1dXV1dXV////////////////////////////////1dXV////////1dXV////////1dXV1dXV////
////1dXV1dXV1dXV1dXV1dXV1dXV1dXV////////1dXV////////1dXV1dXV////////1dXV1dXV1dXV
1dXV1dXV1dXV1dXV////////1dXV////////1dXV1dXV////////1dXV1dXV1dXV1dXV1dXV1dXV1dXV
////////1dXV////////1dXV1dXV////////1dXV////////1dXV1dXV1dXV1dXV////////1dXV////
////1dXV1dXV////////1dXV////////1dXV1dXV1dXV1dXV////////1dXV////////1dXV1dXV////
////1dXV////////1dXV1dXV1dXV1dXV////////1dXV////////1dXV1dXV////////1dXV////////
1dXV1dXV1dXV1dXV////////1dXV////////1dXV1dXV////////1dXV////////1dXV1dXV1dXV1dXV
////////1dXV////////1dXV1dXV////////1dXV////////1dXV1dXV1dXV1dXV////////1dXV////
////1dXV1dXV////////1dXV////////1dXV1dXV1dXV1dXV1dXV1dXV1dXV////////1dXV1dXV////
////1dXV////////1dXV1dXV1dXV1dXV1dXV1dXV1dXV////////1dXV1dXV////////1dXV////////
1dXV1dXV1dXV1dXV1dXV1dXV1dXV////////1dXV1dXV////////1dXV////////1dXV////////////
////////////////////1dXV1dXV////////1dXV////////1dXV////////////////////////////
////1dXV1dXV////////1dXV////////1dXV////////////////////////////////1dXV1dXV////
////1dXV////////1dXV////////////////////////////////1dXV1dXV////////1dXV////////
1dXV////////////////////////////////1dXV1dXV////////1dXV////////1dXV////////////
////////////////////1dXV1dXV1dXV1dXV1dXV////////1dXV1dXV1dXV1dXV1dXV1dXV1dXV////
////1dXV1dXV1dXV1dXV1dXV////////1dXV1dXV1dXV1dXV1dXV1dXV1dXV////////1dXV1dXV1dXV
1dXV1dXV////////1dXV1dXV1dXV1dXV1dXV1dXV1dXV////////1dXV1dXV////////////////////
////////////////////////1dXV////////1dXV1dXV////////////////////////////////////
////////1dXV////////1dXV1dXV////////////////////////////////////////////1dXV////
////1dXV1dXV////////////////////////////////////////////1dXV////////1dXV1dXV////
////////////////////////////////////////1dXV////////1dXV1dXV////////////////////
////////////////////////1dXV////////1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV
1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV
1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXVAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAKAAAABAAAAAgAAAAAQAEAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAIAAAIAAAACAgACAAAAAgACAAICAAADAwMAAgICAAAAA/wAA/wAAAP//AP8AAAD/AP8A//8AAP//
/wDMzMzMzMzMzM/8///////8z/z///////zP/MzMzP/MzM/////8/8/8z/////z/z/zP/MzMzP/P/M/8
/8zM/8/8z/z/zMz/z/zP/P/MzMzP/M/8/8/////8z/z/z/////zMzP/MzMzP/M///////8/8z///////
z/zMzMzMzMzMzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAoAAAAEAAAACAAAAABAAgAAAAAAEABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
gAAAgAAAAICAAIAAAACAAIAAgIAAAMDAwADA3MAA8MqmAAQEBAAICAgADAwMABEREQAWFhYAHBwcACIi
IgApKSkAVVVVAE1NTQBCQkIAOTk5AIB8/wBQUP8AkwDWAP/szADG1u8A1ufnAJCprQAAADMAAABmAAAA
mQAAAMwAADMAAAAzMwAAM2YAADOZAAAzzAAAM/8AAGYAAABmMwAAZmYAAGaZAABmzAAAZv8AAJkAAACZ
MwAAmWYAAJmZAACZzAAAmf8AAMwAAADMMwAAzGYAAMyZAADMzAAAzP8AAP9mAAD/mQAA/8wAMwAAADMA
MwAzAGYAMwCZADMAzAAzAP8AMzMAADMzMwAzM2YAMzOZADMzzAAzM/8AM2YAADNmMwAzZmYAM2aZADNm
zAAzZv8AM5kAADOZMwAzmWYAM5mZADOZzAAzmf8AM8wAADPMMwAzzGYAM8yZADPMzAAzzP8AM/8zADP/
ZgAz/5kAM//MADP//wBmAAAAZgAzAGYAZgBmAJkAZgDMAGYA/wBmMwAAZjMzAGYzZgBmM5kAZjPMAGYz
/wBmZgAAZmYzAGZmZgBmZpkAZmbMAGaZAABmmTMAZplmAGaZmQBmmcwAZpn/AGbMAABmzDMAZsyZAGbM
zABmzP8AZv8AAGb/MwBm/5kAZv/MAMwA/wD/AMwAmZkAAJkzmQCZAJkAmQDMAJkAAACZMzMAmQBmAJkz
zACZAP8AmWYAAJlmMwCZM2YAmWaZAJlmzACZM/8AmZkzAJmZZgCZmZkAmZnMAJmZ/wCZzAAAmcwzAGbM
ZgCZzJkAmczMAJnM/wCZ/wAAmf8zAJnMZgCZ/5kAmf/MAJn//wDMAAAAmQAzAMwAZgDMAJkAzADMAJkz
AADMMzMAzDNmAMwzmQDMM8wAzDP/AMxmAADMZjMAmWZmAMxmmQDMZswAmWb/AMyZAADMmTMAzJlmAMyZ
mQDMmcwAzJn/AMzMAADMzDMAzMxmAMzMmQDMzMwAzMz/AMz/AADM/zMAmf9mAMz/mQDM/8wAzP//AMwA
MwD/AGYA/wCZAMwzAAD/MzMA/zNmAP8zmQD/M8wA/zP/AP9mAAD/ZjMAzGZmAP9mmQD/ZswAzGb/AP+Z
AAD/mTMA/5lmAP+ZmQD/mcwA/5n/AP/MAAD/zDMA/8xmAP/MmQD/zMwA/8z/AP//MwDM/2YA//+ZAP//
zABmZv8AZv9mAGb//wD/ZmYA/2b/AP//ZgAhAKUAX19fAHd3dwCGhoYAlpaWAMvLywCysrIA19fXAN3d
3QDj4+MA6urqAPHx8QD4+PgA8Pv/AKSgoACAgIAAAAD/AAD/AAAA//8A/wAAAP8A/wD//wAA////ANXV
1dXV1dXV1dXV1dXV1dXV///V///////////////V1f//1f//////////////1dX//9XV1dXV1dX//9XV
1dXV///////////V///V///V1f//////////1f//1f//1dX//9XV1dXV1dX//9X//9XV///V///V1dXV
///V///V1f//1f//1dXV1f//1f//1dX//9X//9XV1dXV1dX//9XV///V///V///////////V1f//1f//
1f//////////1dXV1dX//9XV1dXV1dX//9XV///////////////V///V1f//////////////1f//1dXV
1dXV1dXV1dXV1dXV1dUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAA
</value>
</data>
</root>