diff --git a/src/Tizen.Network.WiFi/Tizen.Network.WiFi/WiFiManagerImpl.cs b/src/Tizen.Network.WiFi/Tizen.Network.WiFi/WiFiManagerImpl.cs index 21762e8f180..8b9712627b5 100644 --- a/src/Tizen.Network.WiFi/Tizen.Network.WiFi/WiFiManagerImpl.cs +++ b/src/Tizen.Network.WiFi/Tizen.Network.WiFi/WiFiManagerImpl.cs @@ -181,97 +181,99 @@ internal SafeWiFiManagerHandle GetSafeHandle() } - internal IEnumerable GetFoundAPs() + // Shared "native foreach -> List" collector for the GetFound*/ + // GetWiFiConfigurations methods. Each call site supplies only what + // differs: the operation name and privilege (for CheckReturnValue), + // the native foreach function, and how to wrap a native item handle + // into its managed type. + private List EnumerateForeach(string opName, string privilege, + Func nativeForeach, + Func wrap) { - Log.Info(Globals.LogTag, "GetFoundAPs"); - List apList = new List(); - Interop.WiFi.HandleCallback callback = (IntPtr apHandle, IntPtr userData) => + Log.Info(Globals.LogTag, opName); + List list = new List(); + Exception capturedException = null; + Interop.WiFi.HandleCallback callback = (IntPtr handle, IntPtr userData) => { - if (apHandle != IntPtr.Zero) + if (handle != IntPtr.Zero) { - IntPtr clonedHandle; - Interop.WiFi.AP.Clone(out clonedHandle, apHandle); - WiFiAP apItem = new WiFiAP(clonedHandle); - apList.Add(apItem); + try + { + list.Add(wrap(handle)); + } + catch (Exception ex) + { + // Never let a managed exception unwind through the native + // P/Invoke boundary. Capture it, stop the iteration, and + // rethrow once the native foreach has returned. + capturedException = ex; + return false; + } return true; } return false; }; - int ret = Interop.WiFi.GetForeachFoundAPs(GetSafeHandle(), callback, IntPtr.Zero); - CheckReturnValue(ret, "GetForeachFoundAPs", PrivilegeNetworkGet); - - return apList; - } - - internal IEnumerable GetFoundSpecificAPs() - { - Log.Info(Globals.LogTag, "GetFoundSpecificAPs"); - List apList = new List(); - Interop.WiFi.HandleCallback callback = (IntPtr apHandle, IntPtr userData) => + int ret = nativeForeach(GetSafeHandle(), callback, IntPtr.Zero); + if (capturedException != null) { - if (apHandle != IntPtr.Zero) - { - IntPtr clonedHandle; - Interop.WiFi.AP.Clone(out clonedHandle, apHandle); - WiFiAP apItem = new WiFiAP(clonedHandle); - apList.Add(apItem); - return true; - } - return false; - - }; - - int ret = Interop.WiFi.GetForeachFoundSpecificAPs(GetSafeHandle(), callback, IntPtr.Zero); - CheckReturnValue(ret, "GetForeachFoundSpecificAPs", PrivilegeNetworkGet); - - return apList; + throw capturedException; + } + CheckReturnValue(ret, opName, privilege); + return list; } - internal IEnumerable GetFoundBssids() - { - Log.Info(Globals.LogTag, "GetFoundBssids"); - List apList = new List(); - Interop.WiFi.HandleCallback callback = (IntPtr apHandle, IntPtr userData) => - { - if (apHandle != IntPtr.Zero) + internal IEnumerable GetFoundAPs() => + EnumerateForeach("GetForeachFoundAPs", PrivilegeNetworkGet, + (wifi, cb, ud) => Interop.WiFi.GetForeachFoundAPs(wifi, cb, ud), + apHandle => { - IntPtr clonedHandle; - Interop.WiFi.AP.Clone(out clonedHandle, apHandle); - WiFiAP apItem = new WiFiAP(clonedHandle); - apList.Add(apItem); - return true; - } - return false; - }; - - int ret = Interop.WiFi.GetForeachFoundBssids(GetSafeHandle(), callback, IntPtr.Zero); - CheckReturnValue(ret, "GetForeachFoundBssids", PrivilegeNetworkGet); + int ret = Interop.WiFi.AP.Clone(out IntPtr clonedHandle, apHandle); + if (ret != (int)WiFiError.None) + { + WiFiErrorFactory.ThrowWiFiException(ret, "Failed to clone AP handle"); + } + return new WiFiAP(clonedHandle); + }); - return apList; - } + internal IEnumerable GetFoundSpecificAPs() => + EnumerateForeach("GetForeachFoundSpecificAPs", PrivilegeNetworkGet, + (wifi, cb, ud) => Interop.WiFi.GetForeachFoundSpecificAPs(wifi, cb, ud), + apHandle => + { + int ret = Interop.WiFi.AP.Clone(out IntPtr clonedHandle, apHandle); + if (ret != (int)WiFiError.None) + { + WiFiErrorFactory.ThrowWiFiException(ret, "Failed to clone AP handle"); + } + return new WiFiAP(clonedHandle); + }); - internal IEnumerable GetWiFiConfigurations() - { - Log.Debug(Globals.LogTag, "GetWiFiConfigurations"); - List configList = new List(); - Interop.WiFi.HandleCallback callback = (IntPtr configHandle, IntPtr userData) => - { - if (configHandle != IntPtr.Zero) + internal IEnumerable GetFoundBssids() => + EnumerateForeach("GetForeachFoundBssids", PrivilegeNetworkGet, + (wifi, cb, ud) => Interop.WiFi.GetForeachFoundBssids(wifi, cb, ud), + apHandle => { - IntPtr clonedConfig; - Interop.WiFi.Config.Clone(configHandle, out clonedConfig); - WiFiConfiguration configItem = new WiFiConfiguration(clonedConfig); - configList.Add(configItem); - return true; - } - return false; - }; + int ret = Interop.WiFi.AP.Clone(out IntPtr clonedHandle, apHandle); + if (ret != (int)WiFiError.None) + { + WiFiErrorFactory.ThrowWiFiException(ret, "Failed to clone AP handle"); + } + return new WiFiAP(clonedHandle); + }); - int ret = Interop.WiFi.Config.GetForeachConfiguration(GetSafeHandle(), callback, IntPtr.Zero); - CheckReturnValue(ret, "GetForeachConfiguration", PrivilegeNetworkProfile); - return configList; - } + internal IEnumerable GetWiFiConfigurations() => + EnumerateForeach("GetForeachConfiguration", PrivilegeNetworkProfile, + (wifi, cb, ud) => Interop.WiFi.Config.GetForeachConfiguration(wifi, cb, ud), + configHandle => + { + int ret = Interop.WiFi.Config.Clone(configHandle, out IntPtr clonedConfig); + if (ret != (int)WiFiError.None) + { + WiFiErrorFactory.ThrowWiFiException(ret, "Failed to clone WiFi configuration"); + } + return new WiFiConfiguration(clonedConfig); + }); internal void SaveWiFiNetworkConfiguration(WiFiConfiguration config) {