From be89293fc286b9edcd812223dd1c89cf156ae9e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20CHAVE?= Date: Thu, 8 Oct 2026 15:56:42 +0200 Subject: [PATCH] fix(connect): pass WLAN interface GUIDs by reference for ARM64 WlanGetAvailableNetworkList, WlanScan and WlanQueryInterface take the interface identifier as const GUID*, but the imports declared it as a by-value Guid. That only works on x64, where 16-byte structures are passed by reference. ARM64 passes them in two registers, which shifts every following argument, so network discovery and connection state queries always failed and Foundry Connect showed no Wi-Fi networks. Refs #424 Co-Authored-By: Claude Opus 5.5 --- .../NativeWifiApiTests.cs | 27 +++++++++++++++++++ .../Services/Network/NativeWifiApi.cs | 11 +++++--- 2 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 src/Foundry.Connect.Tests/NativeWifiApiTests.cs diff --git a/src/Foundry.Connect.Tests/NativeWifiApiTests.cs b/src/Foundry.Connect.Tests/NativeWifiApiTests.cs new file mode 100644 index 000000000..8e3ce4e9e --- /dev/null +++ b/src/Foundry.Connect.Tests/NativeWifiApiTests.cs @@ -0,0 +1,27 @@ +// Copyright (c) Foundry Project contributors. +// Licensed under the MIT License. +// See the LICENSE file in the project root for more information. + +using System.Reflection; +using Foundry.Connect.Services.Network; + +namespace Foundry.Connect.Tests; + +public sealed class NativeWifiApiTests +{ + // wlanapi takes interface identifiers as const GUID*. A by-value Guid only reaches the callee as a + // pointer under the x64 calling convention; ARM64 passes it in two registers and every call fails. + [Fact] + public void WlanImports_PassInterfaceGuidsByReference() + { + MethodInfo[] imports = typeof(NativeWifiApi) + .GetMethods(BindingFlags.Static | BindingFlags.NonPublic) + .Where(static method => method.Attributes.HasFlag(MethodAttributes.PinvokeImpl)) + .ToArray(); + + Assert.NotEmpty(imports); + Assert.DoesNotContain( + imports.SelectMany(static method => method.GetParameters()), + static parameter => parameter.ParameterType == typeof(Guid)); + } +} diff --git a/src/Foundry.Connect/Services/Network/NativeWifiApi.cs b/src/Foundry.Connect/Services/Network/NativeWifiApi.cs index 68bfa692c..09382d78f 100644 --- a/src/Foundry.Connect/Services/Network/NativeWifiApi.cs +++ b/src/Foundry.Connect/Services/Network/NativeWifiApi.cs @@ -12,6 +12,11 @@ namespace Foundry.Connect.Services.Network; /// /// Provides the native WLAN API calls used by Foundry.Connect to discover and inspect Wi-Fi state. /// +/// +/// Interface identifiers must be declared as because wlanapi expects +/// const GUID*. A by-value only works on x64, where the calling convention happens to +/// pass 16-byte structures by reference; ARM64 passes them in registers and the calls fail. +/// internal static class NativeWifiApi { private const uint ClientVersion = 2; @@ -404,7 +409,7 @@ private static extern uint WlanEnumInterfaces( [DllImport("wlanapi.dll")] private static extern uint WlanGetAvailableNetworkList( IntPtr clientHandle, - Guid interfaceGuid, + in Guid interfaceGuid, uint flags, IntPtr reserved, out IntPtr availableNetworkList); @@ -412,7 +417,7 @@ private static extern uint WlanGetAvailableNetworkList( [DllImport("wlanapi.dll")] private static extern uint WlanScan( IntPtr clientHandle, - Guid interfaceGuid, + in Guid interfaceGuid, IntPtr dot11Ssid, IntPtr ieData, IntPtr reserved); @@ -420,7 +425,7 @@ private static extern uint WlanScan( [DllImport("wlanapi.dll")] private static extern uint WlanQueryInterface( IntPtr clientHandle, - Guid interfaceGuid, + in Guid interfaceGuid, WlanIntfOpcode opCode, IntPtr reserved, out uint dataSize,