golang.zx2c4.com/wireguard/windows@v0.5.4-0.20230123132234-dcc0eb72a04b/embeddable-dll-service/csharp/TunnelDll/Service.cs (about) 1 /* SPDX-License-Identifier: MIT 2 * 3 * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved. 4 */ 5 6 using System; 7 using System.IO; 8 using System.IO.Pipes; 9 using System.Runtime.InteropServices; 10 using System.ComponentModel; 11 using System.Diagnostics; 12 using System.Threading; 13 14 namespace Tunnel 15 { 16 public class Service 17 { 18 private const string LongName = "WireGuard Demo Box"; 19 private const string Description = "Demonstration tunnel for testing WireGuard"; 20 21 [DllImport("tunnel.dll", EntryPoint = "WireGuardTunnelService", CallingConvention = CallingConvention.Cdecl)] 22 public static extern bool Run([MarshalAs(UnmanagedType.LPWStr)] string configFile); 23 24 public static Driver.Adapter GetAdapter(string configFile) 25 { 26 return new Driver.Adapter(Path.GetFileNameWithoutExtension(configFile)); 27 } 28 29 public static void Add(string configFile, bool ephemeral) 30 { 31 var tunnelName = Path.GetFileNameWithoutExtension(configFile); 32 var shortName = String.Format("WireGuardTunnel${0}", tunnelName); 33 var longName = String.Format("{0}: {1}", LongName, tunnelName); 34 var exeName = Process.GetCurrentProcess().MainModule.FileName; 35 var pathAndArgs = String.Format("\"{0}\" /service \"{1}\" {2}", exeName, configFile, Process.GetCurrentProcess().Id); //TODO: This is not the proper way to escape file args. 36 37 var scm = Win32.OpenSCManager(null, null, Win32.ScmAccessRights.AllAccess); 38 if (scm == IntPtr.Zero) 39 throw new Win32Exception(Marshal.GetLastWin32Error()); 40 try 41 { 42 var service = Win32.OpenService(scm, shortName, Win32.ServiceAccessRights.AllAccess); 43 if (service != IntPtr.Zero) 44 { 45 Win32.CloseServiceHandle(service); 46 Remove(configFile, true); 47 } 48 service = Win32.CreateService(scm, shortName, longName, Win32.ServiceAccessRights.AllAccess, Win32.ServiceType.Win32OwnProcess, Win32.ServiceStartType.Demand, Win32.ServiceError.Normal, pathAndArgs, null, IntPtr.Zero, "Nsi\0TcpIp\0", null, null); 49 if (service == IntPtr.Zero) 50 throw new Win32Exception(Marshal.GetLastWin32Error()); 51 try 52 { 53 var sidType = Win32.ServiceSidType.Unrestricted; 54 if (!Win32.ChangeServiceConfig2(service, Win32.ServiceConfigType.SidInfo, ref sidType)) 55 throw new Win32Exception(Marshal.GetLastWin32Error()); 56 57 var description = new Win32.ServiceDescription { lpDescription = Description }; 58 if (!Win32.ChangeServiceConfig2(service, Win32.ServiceConfigType.Description, ref description)) 59 throw new Win32Exception(Marshal.GetLastWin32Error()); 60 61 if (!Win32.StartService(service, 0, null)) 62 throw new Win32Exception(Marshal.GetLastWin32Error()); 63 64 if (ephemeral && !Win32.DeleteService(service)) 65 throw new Win32Exception(Marshal.GetLastWin32Error()); 66 } 67 finally 68 { 69 Win32.CloseServiceHandle(service); 70 } 71 } 72 finally 73 { 74 Win32.CloseServiceHandle(scm); 75 } 76 } 77 78 public static void Remove(string configFile, bool waitForStop) 79 { 80 var tunnelName = Path.GetFileNameWithoutExtension(configFile); 81 var shortName = String.Format("WireGuardTunnel${0}", tunnelName); 82 83 var scm = Win32.OpenSCManager(null, null, Win32.ScmAccessRights.AllAccess); 84 if (scm == IntPtr.Zero) 85 throw new Win32Exception(Marshal.GetLastWin32Error()); 86 try 87 { 88 var service = Win32.OpenService(scm, shortName, Win32.ServiceAccessRights.AllAccess); 89 if (service == IntPtr.Zero) 90 return; 91 try 92 { 93 var serviceStatus = new Win32.ServiceStatus(); 94 Win32.ControlService(service, Win32.ServiceControl.Stop, serviceStatus); 95 96 for (int i = 0; waitForStop && i < 180 && Win32.QueryServiceStatus(service, serviceStatus) && serviceStatus.dwCurrentState != Win32.ServiceState.Stopped; ++i) 97 Thread.Sleep(1000); 98 99 if (!Win32.DeleteService(service) && Marshal.GetLastWin32Error() != 0x00000430) 100 throw new Win32Exception(Marshal.GetLastWin32Error()); 101 } 102 finally 103 { 104 Win32.CloseServiceHandle(service); 105 } 106 } 107 finally 108 { 109 Win32.CloseServiceHandle(scm); 110 } 111 } 112 } 113 }