aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/embeddable-dll-service/csharp/TunnelDll/Service.cs
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 /embeddable-dll-service/csharp/TunnelDll/Service.cs
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 'embeddable-dll-service/csharp/TunnelDll/Service.cs')
-rw-r--r--embeddable-dll-service/csharp/TunnelDll/Service.cs117
1 files changed, 117 insertions, 0 deletions
diff --git a/embeddable-dll-service/csharp/TunnelDll/Service.cs b/embeddable-dll-service/csharp/TunnelDll/Service.cs
new file mode 100644
index 00000000..7f2c622e
--- /dev/null
+++ b/embeddable-dll-service/csharp/TunnelDll/Service.cs
@@ -0,0 +1,117 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ */
+
+using System;
+using System.IO;
+using System.IO.Pipes;
+using System.Runtime.InteropServices;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Threading;
+
+namespace Tunnel
+{
+ public class Service
+ {
+ 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);
+
+ public static NamedPipeClientStream GetPipe(string configFile)
+ {
+ var pipepath = "ProtectedPrefix\\Administrators\\WireGuard\\" + Path.GetFileNameWithoutExtension(configFile);
+ return new NamedPipeClientStream(pipepath);
+ }
+
+ 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}\" {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)
+ throw new Win32Exception(Marshal.GetLastWin32Error());
+ try
+ {
+ var service = Win32.OpenService(scm, shortName, Win32.ServiceAccessRights.AllAccess);
+ if (service != IntPtr.Zero)
+ {
+ Win32.CloseServiceHandle(service);
+ 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)
+ throw new Win32Exception(Marshal.GetLastWin32Error());
+ try
+ {
+ var sidType = Win32.ServiceSidType.Unrestricted;
+ if (!Win32.ChangeServiceConfig2(service, Win32.ServiceConfigType.SidInfo, ref sidType))
+ throw new Win32Exception(Marshal.GetLastWin32Error());
+
+ var description = new Win32.ServiceDescription { lpDescription = Description };
+ if (!Win32.ChangeServiceConfig2(service, Win32.ServiceConfigType.Description, ref description))
+ throw new Win32Exception(Marshal.GetLastWin32Error());
+
+ if (!Win32.StartService(service, 0, null))
+ throw new Win32Exception(Marshal.GetLastWin32Error());
+
+ if (ephemeral && !Win32.DeleteService(service))
+ throw new Win32Exception(Marshal.GetLastWin32Error());
+ }
+ finally
+ {
+ Win32.CloseServiceHandle(service);
+ }
+ }
+ finally
+ {
+ Win32.CloseServiceHandle(scm);
+ }
+ }
+
+ public static void Remove(string configFile, bool waitForStop)
+ {
+ var tunnelName = Path.GetFileNameWithoutExtension(configFile);
+ var shortName = String.Format("WireGuardTunnel${0}", tunnelName);
+
+ var scm = Win32.OpenSCManager(null, null, Win32.ScmAccessRights.AllAccess);
+ if (scm == IntPtr.Zero)
+ throw new Win32Exception(Marshal.GetLastWin32Error());
+ try
+ {
+ var service = Win32.OpenService(scm, shortName, Win32.ServiceAccessRights.AllAccess);
+ if (service == IntPtr.Zero)
+ {
+ Win32.CloseServiceHandle(service);
+ return;
+ }
+ try
+ {
+ var serviceStatus = new Win32.ServiceStatus();
+ Win32.ControlService(service, Win32.ServiceControl.Stop, serviceStatus);
+
+ for (int i = 0; waitForStop && i < 180 && Win32.QueryServiceStatus(service, serviceStatus) && serviceStatus.dwCurrentState != Win32.ServiceState.Stopped; ++i)
+ Thread.Sleep(1000);
+
+ if (!Win32.DeleteService(service) && Marshal.GetLastWin32Error() != 0x00000430)
+ throw new Win32Exception(Marshal.GetLastWin32Error());
+ }
+ finally
+ {
+ Win32.CloseServiceHandle(service);
+ }
+ }
+ finally
+ {
+ Win32.CloseServiceHandle(scm);
+ }
+ }
+ }
+}