aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2021-01-04 16:26:47 +0100
committerJason A. Donenfeld <Jason@zx2c4.com>2021-01-21 15:26:07 +0100
commite9ed04e8ba4f3bee171938a435d70b2f2302f6a8 (patch)
tree6d169de5dd2a34041e40836040e8e1d994500a14
parentlocales: sync with crowdin (diff)
downloadwireguard-windows-e9ed04e8ba4f3bee171938a435d70b2f2302f6a8.tar.xz
wireguard-windows-e9ed04e8ba4f3bee171938a435d70b2f2302f6a8.zip
embeddable-dll-service: add more robust example for .NET 5
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Diffstat (limited to '')
-rw-r--r--embeddable-dll-service/csharp/DemoUI/MainWindow.Designer.cs87
-rw-r--r--embeddable-dll-service/csharp/DemoUI/MainWindow.cs213
-rw-r--r--embeddable-dll-service/csharp/DemoUI/MainWindow.resx60
-rw-r--r--embeddable-dll-service/csharp/DemoUI/Program.cs44
-rw-r--r--embeddable-dll-service/csharp/DemoUI/app.manifest48
-rw-r--r--embeddable-dll-service/csharp/Program.cs92
-rw-r--r--embeddable-dll-service/csharp/README.md15
-rw-r--r--embeddable-dll-service/csharp/TunnelDll/Keypair.cs (renamed from embeddable-dll-service/csharp/Keypair.cs)4
-rw-r--r--embeddable-dll-service/csharp/TunnelDll/Ringlogger.cs (renamed from embeddable-dll-service/csharp/Ringlogger.cs)2
-rw-r--r--embeddable-dll-service/csharp/TunnelDll/Service.cs (renamed from embeddable-dll-service/csharp/Service.cs)26
-rw-r--r--embeddable-dll-service/csharp/TunnelDll/Win32.cs (renamed from embeddable-dll-service/csharp/Win32.cs)2
-rw-r--r--embeddable-dll-service/csharp/demo-client.csproj14
-rw-r--r--embeddable-dll-service/csharp/demo-client.csproj.user8
-rw-r--r--embeddable-dll-service/csharp/demo-client.sln25
14 files changed, 530 insertions, 110 deletions
diff --git a/embeddable-dll-service/csharp/DemoUI/MainWindow.Designer.cs b/embeddable-dll-service/csharp/DemoUI/MainWindow.Designer.cs
new file mode 100644
index 00000000..5fae35d3
--- /dev/null
+++ b/embeddable-dll-service/csharp/DemoUI/MainWindow.Designer.cs
@@ -0,0 +1,87 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ */
+
+namespace DemoUI
+{
+ partial class MainWindow
+ {
+ /// <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()
+ {
+ this.connectButton = new System.Windows.Forms.Button();
+ this.logBox = new System.Windows.Forms.TextBox();
+ this.SuspendLayout();
+ //
+ // connectButton
+ //
+ this.connectButton.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.connectButton.Location = new System.Drawing.Point(12, 12);
+ this.connectButton.Name = "connectButton";
+ this.connectButton.Size = new System.Drawing.Size(1137, 46);
+ this.connectButton.TabIndex = 5;
+ this.connectButton.Text = "&Connect";
+ this.connectButton.UseVisualStyleBackColor = true;
+ this.connectButton.Click += new System.EventHandler(this.connectButton_Click);
+ //
+ // logBox
+ //
+ this.logBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.logBox.Location = new System.Drawing.Point(12, 64);
+ this.logBox.Multiline = true;
+ this.logBox.Name = "logBox";
+ this.logBox.ReadOnly = true;
+ this.logBox.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
+ this.logBox.Size = new System.Drawing.Size(1137, 561);
+ this.logBox.TabIndex = 4;
+ this.logBox.TabStop = false;
+ //
+ // MainWindow
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(13F, 32F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(1161, 637);
+ this.Controls.Add(this.logBox);
+ this.Controls.Add(this.connectButton);
+ this.Name = "MainWindow";
+ this.Text = "WireGuard Demo Client";
+ this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainWindow_FormClosing);
+ this.Load += new System.EventHandler(this.MainWindow_Load);
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+ private System.Windows.Forms.Button connectButton;
+ private System.Windows.Forms.TextBox logBox;
+ }
+}
+
diff --git a/embeddable-dll-service/csharp/DemoUI/MainWindow.cs b/embeddable-dll-service/csharp/DemoUI/MainWindow.cs
new file mode 100644
index 00000000..13499fcb
--- /dev/null
+++ b/embeddable-dll-service/csharp/DemoUI/MainWindow.cs
@@ -0,0 +1,213 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ */
+
+using System;
+using System.Text;
+using System.Threading.Tasks;
+using System.IO;
+using System.Windows.Forms;
+using System.Threading;
+using System.IO.Pipes;
+using System.Diagnostics;
+using System.Net.Sockets;
+
+namespace DemoUI
+{
+ public partial class MainWindow : Form
+ {
+ private static readonly string userDirectory = Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName);
+ private static readonly string configFile = Path.Combine(userDirectory, "demobox.conf");
+ private static readonly string logFile = Path.Combine(userDirectory, "log.bin");
+
+ private Tunnel.Ringlogger log;
+ private Thread logPrintingThread, transferUpdateThread;
+ private volatile bool threadsRunning;
+ private bool connected;
+
+ public MainWindow()
+ {
+ InitializeComponent();
+ Application.ApplicationExit += Application_ApplicationExit;
+
+ try { File.Delete(logFile); } catch { }
+ log = new Tunnel.Ringlogger(logFile, "GUI");
+ logPrintingThread = new Thread(new ThreadStart(tailLog));
+ transferUpdateThread = new Thread(new ThreadStart(tailTransfer));
+ }
+
+ private void tailLog()
+ {
+ var cursor = Tunnel.Ringlogger.CursorAll;
+ while (threadsRunning)
+ {
+ var lines = log.FollowFromCursor(ref cursor);
+ foreach (var line in lines)
+ logBox.Invoke(new Action<string>(logBox.AppendText), new object[] { line + "\r\n" });
+ try
+ {
+ Thread.Sleep(300);
+ }
+ catch
+ {
+ break;
+ }
+ }
+ }
+
+ private void tailTransfer()
+ {
+ NamedPipeClientStream stream = null;
+ try
+ {
+ while (threadsRunning)
+ {
+ while (threadsRunning)
+ {
+ try
+ {
+ stream = Tunnel.Service.GetPipe(configFile);
+ stream.Connect();
+ break;
+ }
+ catch { }
+ Thread.Sleep(1000);
+ }
+
+ var reader = new StreamReader(stream);
+ stream.Write(Encoding.UTF8.GetBytes("get=1\n\n"));
+ ulong rx = 0, tx = 0;
+ while (threadsRunning)
+ {
+ var line = reader.ReadLine();
+ if (line == null)
+ break;
+ line = line.Trim();
+ if (line.Length == 0)
+ break;
+ if (line.StartsWith("rx_bytes="))
+ rx += ulong.Parse(line.Substring(9));
+ else if (line.StartsWith("tx_bytes="))
+ tx += ulong.Parse(line.Substring(9));
+ }
+ Invoke(new Action<ulong, ulong>(updateTransferTitle), new object[] { rx, tx });
+ stream.Close();
+ Thread.Sleep(1000);
+ }
+ }
+ catch { }
+ finally
+ {
+ if (stream != null && stream.IsConnected)
+ stream.Close();
+ }
+ }
+
+ private void Application_ApplicationExit(object sender, EventArgs e)
+ {
+ Tunnel.Service.Remove(configFile, true);
+ try { File.Delete(logFile); } catch { }
+ try { File.Delete(configFile); } catch { }
+ }
+
+ private void MainWindow_Load(object sender, EventArgs e)
+ {
+ threadsRunning = true;
+ logPrintingThread.Start();
+ transferUpdateThread.Start();
+ }
+
+ private void MainWindow_FormClosing(object sender, FormClosingEventArgs e)
+ {
+ threadsRunning = false;
+ logPrintingThread.Interrupt();
+ transferUpdateThread.Interrupt();
+ try { logPrintingThread.Join(); } catch { }
+ try { transferUpdateThread.Join(); } catch { }
+ }
+
+ private static string formatBytes(ulong bytes)
+ {
+ decimal d = bytes;
+ string selectedUnit = null;
+ foreach (string unit in new string[] { "B", "KiB", "MiB", "GiB", "TiB" })
+ {
+ selectedUnit = unit;
+ if (d < 1024)
+ break;
+ d /= 1024;
+ }
+ return string.Format("{0:0.##} {1}", d, selectedUnit);
+ }
+
+ private void updateTransferTitle(ulong rx, ulong tx)
+ {
+ var titleBase = Text;
+ var idx = titleBase.IndexOf(" - ");
+ if (idx != -1)
+ titleBase = titleBase.Substring(0, idx);
+ if (rx == 0 && tx == 0)
+ Text = titleBase;
+ else
+ Text = string.Format("{0} - rx: {1}, tx: {2}", titleBase, formatBytes(rx), formatBytes(tx));
+ }
+
+ private async Task<string> generateNewConfig()
+ {
+ log.Write("Generating keys");
+ var keys = Tunnel.Keypair.Generate();
+ log.Write("Exchanging keys with demo server");
+ var client = new TcpClient();
+ await client.ConnectAsync("demo.wireguard.com", 42912);
+ var stream = client.GetStream();
+ var reader = new StreamReader(stream, Encoding.UTF8);
+ var pubKeyBytes = Encoding.UTF8.GetBytes(keys.Public + "\n");
+ await stream.WriteAsync(pubKeyBytes, 0, pubKeyBytes.Length);
+ await stream.FlushAsync();
+ var ret = (await reader.ReadLineAsync()).Split(':');
+ client.Close();
+ var status = ret.Length >= 1 ? ret[0] : "";
+ var serverPubkey = ret.Length >= 2 ? ret[1] : "";
+ var serverPort = ret.Length >= 3 ? ret[2] : "";
+ var internalIP = ret.Length >= 4 ? ret[3] : "";
+ if (status != "OK")
+ throw new InvalidOperationException(string.Format("Server status is {0}", status));
+ return string.Format("[Interface]\nPrivateKey = {0}\nAddress = {1}/24\nDNS = 8.8.8.8, 8.8.4.4\n\n[Peer]\nPublicKey = {2}\nEndpoint = demo.wireguard.com:{3}\nAllowedIPs = 0.0.0.0/0\n", keys.Private, internalIP, serverPubkey, serverPort);
+ }
+
+ private async void connectButton_Click(object sender, EventArgs e)
+ {
+ if (connected)
+ {
+ connectButton.Enabled = false;
+ await Task.Run(() =>
+ {
+ Tunnel.Service.Remove(configFile, true);
+ try { File.Delete(configFile); } catch { }
+ });
+ updateTransferTitle(0, 0);
+ connectButton.Text = "&Connect";
+ connectButton.Enabled = true;
+ connected = false;
+ return;
+ }
+
+ connectButton.Enabled = false;
+ try
+ {
+ var config = await generateNewConfig();
+ await File.WriteAllBytesAsync(configFile, Encoding.UTF8.GetBytes(config));
+ await Task.Run(() => Tunnel.Service.Add(configFile, true));
+ connected = true;
+ connectButton.Text = "&Disconnect";
+ }
+ catch (Exception ex)
+ {
+ log.Write(ex.Message);
+ try { File.Delete(configFile); } catch { }
+ }
+ connectButton.Enabled = true;
+ }
+ }
+}
diff --git a/embeddable-dll-service/csharp/DemoUI/MainWindow.resx b/embeddable-dll-service/csharp/DemoUI/MainWindow.resx
new file mode 100644
index 00000000..f298a7be
--- /dev/null
+++ b/embeddable-dll-service/csharp/DemoUI/MainWindow.resx
@@ -0,0 +1,60 @@
+<root>
+ <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>
+</root> \ No newline at end of file
diff --git a/embeddable-dll-service/csharp/DemoUI/Program.cs b/embeddable-dll-service/csharp/DemoUI/Program.cs
new file mode 100644
index 00000000..8c420973
--- /dev/null
+++ b/embeddable-dll-service/csharp/DemoUI/Program.cs
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ */
+
+using System;
+using System.Threading;
+using System.Diagnostics;
+using System.Windows.Forms;
+
+namespace DemoUI
+{
+ static class Program
+ {
+ [STAThread]
+ static void Main(string[] args)
+ {
+ if (args.Length == 3 && args[0] == "/service")
+ {
+ var t = new Thread(() =>
+ {
+ try
+ {
+ var currentProcess = Process.GetCurrentProcess();
+ var uiProcess = Process.GetProcessById(int.Parse(args[2]));
+ if (uiProcess.MainModule.FileName != currentProcess.MainModule.FileName)
+ return;
+ uiProcess.WaitForExit();
+ Tunnel.Service.Remove(args[1], false);
+ }
+ catch { }
+ });
+ t.Start();
+ Tunnel.Service.Run(args[1]);
+ t.Interrupt();
+ return;
+ }
+ Application.SetHighDpiMode(HighDpiMode.SystemAware);
+ Application.EnableVisualStyles();
+ Application.SetCompatibleTextRenderingDefault(false);
+ Application.Run(new MainWindow());
+ }
+ }
+}
diff --git a/embeddable-dll-service/csharp/DemoUI/app.manifest b/embeddable-dll-service/csharp/DemoUI/app.manifest
new file mode 100644
index 00000000..616ab5b9
--- /dev/null
+++ b/embeddable-dll-service/csharp/DemoUI/app.manifest
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
+ <assemblyIdentity version="1.0.0.0" name="demo-client"/>
+ <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
+ <security>
+ <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
+ <requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
+ </requestedPrivileges>
+ </security>
+ </trustInfo>
+
+ <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
+ <application>
+ <!-- Windows 7 -->
+ <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />
+
+ <!-- Windows 8 -->
+ <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />
+
+ <!-- Windows 8.1 -->
+ <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />
+
+ <!-- Windows 10 -->
+ <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
+
+ </application>
+ </compatibility>
+
+ <application xmlns="urn:schemas-microsoft-com:asm.v3">
+ <windowsSettings>
+ <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
+ </windowsSettings>
+ </application>
+
+ <dependency>
+ <dependentAssembly>
+ <assemblyIdentity
+ type="win32"
+ name="Microsoft.Windows.Common-Controls"
+ version="6.0.0.0"
+ processorArchitecture="*"
+ publicKeyToken="6595b64144ccf1df"
+ language="*"
+ />
+ </dependentAssembly>
+ </dependency>
+
+</assembly>
diff --git a/embeddable-dll-service/csharp/Program.cs b/embeddable-dll-service/csharp/Program.cs
deleted file mode 100644
index dfefc3ec..00000000
--- a/embeddable-dll-service/csharp/Program.cs
+++ /dev/null
@@ -1,92 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2019-2020 WireGuard LLC. All Rights Reserved.
- */
-
-using System;
-using System.Net.Sockets;
-using System.IO;
-using System.Text;
-using System.Diagnostics;
-using System.Threading;
-using System.Runtime.InteropServices;
-
-namespace Tunnel
-{
- class Program
- {
-
- [DllImport("kernel32.dll")]
- private static extern bool SetConsoleCtrlHandler(SetConsoleCtrlEventHandler handler, bool add);
- private delegate bool SetConsoleCtrlEventHandler(UInt32 signal);
-
- public static void Main(string[] args)
- {
- if (args.Length == 2 && args[0] == "/service")
- {
- Service.Run(args[1]);
- return;
- }
-
- var baseDirectory = Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName);
- var configFile = Path.Combine(baseDirectory, "demobox.conf");
- var logFile = Path.Combine(baseDirectory, "log.bin");
-
- try { File.Delete(logFile); } catch { }
- Ringlogger log = new Ringlogger(logFile, "GUI");
-
- var logPrintingThread = new Thread(() =>
- {
- var cursor = Ringlogger.CursorAll;
- while (Thread.CurrentThread.IsAlive)
- {
- var lines = log.FollowFromCursor(ref cursor);
- foreach (var line in lines)
- Console.WriteLine(line);
- Thread.Sleep(300);
- }
- });
- logPrintingThread.Start();
-
- log.Write("Generating keys");
- var keys = Keypair.Generate();
- log.Write("Exchanging keys with demo server");
- var client = new TcpClient("demo.wireguard.com", 42912);
- var stream = client.GetStream();
- var reader = new StreamReader(stream, Encoding.UTF8);
- var pubKeyBytes = Encoding.UTF8.GetBytes(keys.Public + "\n");
- stream.Write(pubKeyBytes, 0, pubKeyBytes.Length);
- stream.Flush();
- var ret = reader.ReadLine().Split(':');
- client.Close();
- var status = ret.Length >= 1 ? ret[0] : "";
- var serverPubkey = ret.Length >= 2 ? ret[1] : "";
- var serverPort = ret.Length >= 3 ? ret[2] : "";
- var internalIP = ret.Length >= 4 ? ret[3] : "";
-
- if (status != "OK")
- throw new InvalidOperationException(String.Format("Server status is {0}", status));
-
- SetConsoleCtrlHandler(delegate
- {
- Service.Remove(configFile);
- Environment.Exit(0);
- return true;
- }, true);
-
- log.Write("Writing config file to disk");
- var configFileContents = String.Format("[Interface]\nPrivateKey = {0}\nAddress = {1}/24\nDNS = 8.8.8.8, 8.8.4.4\n\n[Peer]\nPublicKey = {2}\nEndpoint = demo.wireguard.com:{3}\nAllowedIPs = 0.0.0.0/0\n", keys.Private, internalIP, serverPubkey, serverPort);
- File.WriteAllText(configFile, configFileContents);
-
- try
- {
- Service.Add(configFile);
- logPrintingThread.Join();
- }
- finally
- {
- Service.Remove(configFile);
- }
- }
- }
-}
diff --git a/embeddable-dll-service/csharp/README.md b/embeddable-dll-service/csharp/README.md
new file mode 100644
index 00000000..071d15f6
--- /dev/null
+++ b/embeddable-dll-service/csharp/README.md
@@ -0,0 +1,15 @@
+# Example WireGuard Demo Client for Windows
+
+This is a simple client for demo.wireguard.com, which brings up WireGuard tunnels using the [embeddable-dll-service](https://git.zx2c4.com/wireguard-windows/about/embeddable-dll-service/README.md).
+
+## Building
+
+The code in this repository can be built in Visual Studio 2019 by opening the .sln and pressing build. However, it requires `tunnel.dll` to be present in the run directory. That can be built by:
+
+```batch
+> git clone https://git.zx2c4.com/wireguard-windows
+> cd wireguard-windows\embeddable-dll-service
+> .\build.bat
+```
+
+In addition, `tunnel.dll` requires `wintun.dll`, which can be downloaded from [wintun.net](https://www.wintun.net).
diff --git a/embeddable-dll-service/csharp/Keypair.cs b/embeddable-dll-service/csharp/TunnelDll/Keypair.cs
index 17a0a876..146d56e0 100644
--- a/embeddable-dll-service/csharp/Keypair.cs
+++ b/embeddable-dll-service/csharp/TunnelDll/Keypair.cs
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2020 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
*/
using System;
@@ -13,7 +13,7 @@ namespace Tunnel
public readonly string Public;
public readonly string Private;
- private Keypair(string pub, string priv)
+ public Keypair(string pub, string priv)
{
Public = pub;
Private = priv;
diff --git a/embeddable-dll-service/csharp/Ringlogger.cs b/embeddable-dll-service/csharp/TunnelDll/Ringlogger.cs
index 801eaa59..469927c1 100644
--- a/embeddable-dll-service/csharp/Ringlogger.cs
+++ b/embeddable-dll-service/csharp/TunnelDll/Ringlogger.cs
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2020 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
*/
using System;
diff --git a/embeddable-dll-service/csharp/Service.cs b/embeddable-dll-service/csharp/TunnelDll/Service.cs
index 0310d693..7f2c622e 100644
--- a/embeddable-dll-service/csharp/Service.cs
+++ b/embeddable-dll-service/csharp/TunnelDll/Service.cs
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2020 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
*/
using System;
@@ -9,15 +9,14 @@ using System.IO.Pipes;
using System.Runtime.InteropServices;
using System.ComponentModel;
using System.Diagnostics;
-using System.Security.Principal;
using System.Threading;
namespace Tunnel
{
public class Service
{
- private const string LongName = "Example WireGuard Tunnel Client";
- private const string Description = "A WireGuard tunnel created by example code.";
+ private const string LongName = "WireGuard Demo Box";
+ private const string Description = "Demonstration tunnel for testing WireGuard";
[DllImport("tunnel.dll", EntryPoint = "WireGuardTunnelService", CallingConvention = CallingConvention.Cdecl)]
public static extern bool Run([MarshalAs(UnmanagedType.LPWStr)] string configFile);
@@ -28,17 +27,13 @@ namespace Tunnel
return new NamedPipeClientStream(pipepath);
}
- public static void Add(string configFile)
+ public static void Add(string configFile, bool ephemeral)
{
var tunnelName = Path.GetFileNameWithoutExtension(configFile);
var shortName = String.Format("WireGuardTunnel${0}", tunnelName);
var longName = String.Format("{0}: {1}", LongName, tunnelName);
var exeName = Process.GetCurrentProcess().MainModule.FileName;
- var pathAndArgs = String.Format("\"{0}\" /service \"{1}\"", exeName, configFile); //TODO: This is not the proper way to escape file args.
-
- var accessControl = File.GetAccessControl(configFile); //TODO: TOCTOU!
- accessControl.SetOwner(new NTAccount(Environment.UserDomainName, Environment.UserName));
- File.SetAccessControl(configFile, accessControl);
+ var pathAndArgs = String.Format("\"{0}\" /service \"{1}\" {2}", exeName, configFile, Process.GetCurrentProcess().Id); //TODO: This is not the proper way to escape file args.
var scm = Win32.OpenSCManager(null, null, Win32.ScmAccessRights.AllAccess);
if (scm == IntPtr.Zero)
@@ -49,7 +44,7 @@ namespace Tunnel
if (service != IntPtr.Zero)
{
Win32.CloseServiceHandle(service);
- Remove(configFile);
+ Remove(configFile, true);
}
service = Win32.CreateService(scm, shortName, longName, Win32.ServiceAccessRights.AllAccess, Win32.ServiceType.Win32OwnProcess, Win32.ServiceStartType.Demand, Win32.ServiceError.Normal, pathAndArgs, null, IntPtr.Zero, "Nsi\0TcpIp", null, null);
if (service == IntPtr.Zero)
@@ -66,6 +61,9 @@ namespace Tunnel
if (!Win32.StartService(service, 0, null))
throw new Win32Exception(Marshal.GetLastWin32Error());
+
+ if (ephemeral && !Win32.DeleteService(service))
+ throw new Win32Exception(Marshal.GetLastWin32Error());
}
finally
{
@@ -78,7 +76,7 @@ namespace Tunnel
}
}
- public static void Remove(string configFile)
+ public static void Remove(string configFile, bool waitForStop)
{
var tunnelName = Path.GetFileNameWithoutExtension(configFile);
var shortName = String.Format("WireGuardTunnel${0}", tunnelName);
@@ -99,10 +97,10 @@ namespace Tunnel
var serviceStatus = new Win32.ServiceStatus();
Win32.ControlService(service, Win32.ServiceControl.Stop, serviceStatus);
- for (int i = 0; i < 180 && Win32.QueryServiceStatus(service, serviceStatus) && serviceStatus.dwCurrentState != Win32.ServiceState.Stopped; ++i)
+ for (int i = 0; waitForStop && i < 180 && Win32.QueryServiceStatus(service, serviceStatus) && serviceStatus.dwCurrentState != Win32.ServiceState.Stopped; ++i)
Thread.Sleep(1000);
- if (!Win32.DeleteService(service))
+ if (!Win32.DeleteService(service) && Marshal.GetLastWin32Error() != 0x00000430)
throw new Win32Exception(Marshal.GetLastWin32Error());
}
finally
diff --git a/embeddable-dll-service/csharp/Win32.cs b/embeddable-dll-service/csharp/TunnelDll/Win32.cs
index 9d6808f3..d8447f7f 100644
--- a/embeddable-dll-service/csharp/Win32.cs
+++ b/embeddable-dll-service/csharp/TunnelDll/Win32.cs
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2020 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
*/
using System;
diff --git a/embeddable-dll-service/csharp/demo-client.csproj b/embeddable-dll-service/csharp/demo-client.csproj
new file mode 100644
index 00000000..00339ee2
--- /dev/null
+++ b/embeddable-dll-service/csharp/demo-client.csproj
@@ -0,0 +1,14 @@
+<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
+
+ <PropertyGroup>
+ <OutputType>WinExe</OutputType>
+ <TargetFramework>net5.0-windows</TargetFramework>
+ <RootNamespace>DemoUI</RootNamespace>
+ <UseWindowsForms>true</UseWindowsForms>
+ <AssemblyName>demo-client</AssemblyName>
+ <Platforms>x64</Platforms>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <ApplicationManifest>DemoUI\app.manifest</ApplicationManifest>
+ </PropertyGroup>
+
+</Project>
diff --git a/embeddable-dll-service/csharp/demo-client.csproj.user b/embeddable-dll-service/csharp/demo-client.csproj.user
new file mode 100644
index 00000000..27d1a581
--- /dev/null
+++ b/embeddable-dll-service/csharp/demo-client.csproj.user
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Compile Update="DemoUI\MainWindow.cs">
+ <SubType>Form</SubType>
+ </Compile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/embeddable-dll-service/csharp/demo-client.sln b/embeddable-dll-service/csharp/demo-client.sln
new file mode 100644
index 00000000..a7d8b0ee
--- /dev/null
+++ b/embeddable-dll-service/csharp/demo-client.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30804.86
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "demo-client", "demo-client.csproj", "{AADC81E1-0294-483B-ABAE-63DBE82436E9}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x64 = Debug|x64
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {AADC81E1-0294-483B-ABAE-63DBE82436E9}.Debug|x64.ActiveCfg = Debug|x64
+ {AADC81E1-0294-483B-ABAE-63DBE82436E9}.Debug|x64.Build.0 = Debug|x64
+ {AADC81E1-0294-483B-ABAE-63DBE82436E9}.Release|x64.ActiveCfg = Release|x64
+ {AADC81E1-0294-483B-ABAE-63DBE82436E9}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {E410FD53-4E4A-4299-B6BD-CE91685DF7BE}
+ EndGlobalSection
+EndGlobal