From a7c4a365e864256728b49bd1cddda154ef00f9ef Mon Sep 17 00:00:00 2001 From: rinrab Date: Sat, 20 Jan 2024 18:49:57 +0100 Subject: [PATCH] Create `RasApi.DisconnectAll()` function. --- AOVpnManager.Tests/RasApiTests.cs | 25 +++++++++++ AOVpnManager/RasApi.cs | 74 +++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 AOVpnManager.Tests/RasApiTests.cs create mode 100644 AOVpnManager/RasApi.cs diff --git a/AOVpnManager.Tests/RasApiTests.cs b/AOVpnManager.Tests/RasApiTests.cs new file mode 100644 index 0000000..fdb81bc --- /dev/null +++ b/AOVpnManager.Tests/RasApiTests.cs @@ -0,0 +1,25 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Diagnostics; + +namespace AOVpnManager.Tests +{ + [TestClass] + public class RasApiTests + { + [TestMethod] + public void HangupAllTest() + { + if (!Debugger.IsAttached) + { + return; + } + + RasApi.DisconnectAll((x) => + { + Console.WriteLine(x); + return true; + }); + } + } +} diff --git a/AOVpnManager/RasApi.cs b/AOVpnManager/RasApi.cs new file mode 100644 index 0000000..50ffdee --- /dev/null +++ b/AOVpnManager/RasApi.cs @@ -0,0 +1,74 @@ +using System; +using System.ComponentModel; +using System.Runtime.InteropServices; + +namespace AOVpnManager +{ + public static class RasApi + { + public static void DisconnectAll(Predicate filter) + { + uint dwSize = (uint)Marshal.SizeOf(typeof(RASCONN)); + uint count = 1; + RASCONN[] connections; + while (true) + { + uint cb = dwSize * count; + connections = new RASCONN[count]; + connections[0].dwSize = dwSize; + + int err = RasEnumConnections(connections, ref cb, ref count); + + if (err == 0) + { + break; + } + else if (err != ERROR_BUFFER_TOO_SMALL) + { + throw new Win32Exception(err); + } + + count = (cb + dwSize - 1) / dwSize; + } + + for (int i = 0; i < count; i++) + { + if (filter(connections[i].szEntryName)) + { + RasHangUp(connections[i].hrasconn); + } + } + } + + const int RAS_MaxEntryName = 256; + const int RAS_MaxDeviceType = 16; + const int RAS_MaxDeviceName = 128; + + const int ERROR_BUFFER_TOO_SMALL = 603; + + [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Auto)] + private struct RASCONN + { + public uint dwSize; + + public IntPtr hrasconn; + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = RAS_MaxEntryName + 1)] + public string szEntryName; + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = RAS_MaxDeviceType + 1)] + public string szDeviceType; + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = RAS_MaxDeviceName + 1)] + public string szDeviceName; + + // We don't care about other feilds. + } + + [DllImport("Rasapi32.dll", ExactSpelling = false, CharSet = CharSet.Auto, SetLastError = false)] + private static extern int RasEnumConnections([In, Out] RASCONN[] connections, ref uint cb, ref uint count); + + [DllImport("Rasapi32.dll", ExactSpelling = false, CharSet = CharSet.Auto, SetLastError = false)] + private static extern int RasHangUp(IntPtr rasconn); + } +}