50 lines
3.1 KiB
C#
50 lines
3.1 KiB
C#
using System.IO;
|
|
using System.Net.NetworkInformation;
|
|
using System.Net.Sockets;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
using QSafe.Core;
|
|
|
|
namespace QSafe.Desktop;
|
|
|
|
/// <summary>Reads the actual WLAN association; adapter/profile names and VPN adapters are not SSIDs.</summary>
|
|
public sealed class HomeWifiNetwork : ILanNetwork
|
|
{
|
|
public static readonly HomeWifiNetwork Instance = new();
|
|
[DllImport("wlanapi.dll")] private static extern uint WlanOpenHandle(uint version, IntPtr reserved, out uint negotiated, out IntPtr handle);
|
|
[DllImport("wlanapi.dll")] private static extern uint WlanCloseHandle(IntPtr handle, IntPtr reserved);
|
|
[DllImport("wlanapi.dll")] private static extern uint WlanQueryInterface(IntPtr handle, ref Guid guid, uint opcode, IntPtr reserved, out uint size, out IntPtr data, out uint valueType);
|
|
[DllImport("wlanapi.dll")] private static extern void WlanFreeMemory(IntPtr data);
|
|
public LanBinding Current(Connection connection)
|
|
{
|
|
if (WlanOpenHandle(2, IntPtr.Zero, out _, out var handle) != 0) throw Offline();
|
|
try
|
|
{
|
|
foreach (var adapter in NetworkInterface.GetAllNetworkInterfaces().Where(a => a.NetworkInterfaceType == NetworkInterfaceType.Wireless80211 && a.OperationalStatus == OperationalStatus.Up))
|
|
{
|
|
if (!Guid.TryParse(adapter.Id, out var guid)) continue;
|
|
IntPtr raw = IntPtr.Zero;
|
|
try
|
|
{
|
|
// WLAN_CONNECTION_ATTRIBUTES: state, mode, WCHAR profile[256], DOT11_SSID.
|
|
if (WlanQueryInterface(handle, ref guid, 7, IntPtr.Zero, out var size, out raw, out _) != 0 || size < 556 || Marshal.ReadInt32(raw) != 1) continue;
|
|
int length = Marshal.ReadInt32(raw, 520); if (length is < 1 or > 32) continue;
|
|
var ssidBytes = new byte[length]; Marshal.Copy(IntPtr.Add(raw, 524), ssidBytes, 0, length);
|
|
string ssid = new UTF8Encoding(false, true).GetString(ssidBytes);
|
|
if (ssid != connection.HomeWifiSsid) continue;
|
|
var properties = adapter.GetIPProperties(); int index = properties.GetIPv4Properties().Index;
|
|
foreach (var address in properties.UnicastAddresses.Where(a => a.Address.AddressFamily == AddressFamily.InterNetwork))
|
|
{
|
|
var binding = new LanBinding(ssid, true, address.Address, address.PrefixLength, index);
|
|
try { LanPolicy.Check(connection, binding); return binding; } catch (IOException) { }
|
|
}
|
|
}
|
|
finally { if (raw != IntPtr.Zero) WlanFreeMemory(raw); }
|
|
}
|
|
}
|
|
finally { WlanCloseHandle(handle, IntPtr.Zero); }
|
|
throw Offline();
|
|
}
|
|
private static IOException Offline() => new("Автономный режим: домашний Wi-Fi не подтверждён. Синхронизация не выполняется. Если Windows скрывает SSID, проверьте разрешение доступа к имени Wi-Fi.");
|
|
}
|