diff --git a/PInvoke/NetListMgr/NetListMgr.cs b/PInvoke/NetListMgr/NetListMgr.cs index 6a0fb3d0..bc01c3a6 100644 --- a/PInvoke/NetListMgr/NetListMgr.cs +++ b/PInvoke/NetListMgr/NetListMgr.cs @@ -402,7 +402,7 @@ namespace Vanara.PInvoke.NetListMgr } /// Use this interface to notify an application of cost and data plan status change events for a connection. - [ComImport, Guid("DCB0000B-570F-4A9B-8D69-199FDBA5723B"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), CoClass(typeof(NetworkListManager))] + [ComImport, Guid("DCB0000B-570F-4A9B-8D69-199FDBA5723B"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] [PInvokeData("Netlistmgr.h")] public interface INetworkConnectionCostEvents { @@ -412,18 +412,20 @@ namespace Vanara.PInvoke.NetListMgr /// A DWORD value that represents the new cost of the connection. The lowest 16 bits represent the cost level, and the highest 16 bits represent the /// flags. Possible values are defined by the enumeration. /// - void ConnectionCostChanged([In] Guid connectionId, [In] NLM_CONNECTION_COST newCost); + [PreserveSig] + HRESULT ConnectionCostChanged([In] Guid connectionId, [In] NLM_CONNECTION_COST newCost); /// The ConnectionDataPlanStatusChanged method notifies an application of a data plan status change on a connection. /// A unique ID that identifies the connection on which the data plan status change event occurred. - void ConnectionDataPlanStatusChanged([In] Guid connectionId); + [PreserveSig] + HRESULT ConnectionDataPlanStatusChanged([In] Guid connectionId); } /// /// The INetworkConnectionEvents interface is a message sink interface that a client implements to get network connection-related events. Applications /// that are interested in lower-level events (such as authentication changes) must implement this interface. /// - [ComImport, Guid("DCB00007-570F-4A9B-8D69-199FDBA5723B"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), TypeLibType(TypeLibTypeFlags.FOleAutomation), CoClass(typeof(NetworkListManager))] + [ComImport, Guid("DCB00007-570F-4A9B-8D69-199FDBA5723B"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), TypeLibType(TypeLibTypeFlags.FOleAutomation)] [PInvokeData("Netlistmgr.h")] public interface INetworkConnectionEvents { @@ -432,14 +434,16 @@ namespace Vanara.PInvoke.NetListMgr /// /// A GUID that identifies the network connection on which the event occurred. /// NLM_CONNECTIVITY enumeration value that specifies the new connectivity for this network connection. - void NetworkConnectionConnectivityChanged([In] Guid connectionId, [In] NLM_CONNECTIVITY newConnectivity); + [PreserveSig] + HRESULT NetworkConnectionConnectivityChanged([In] Guid connectionId, [In] NLM_CONNECTIVITY newConnectivity); /// /// The NetworkConnectionPropertyChanged method notifies a client when property change events related to a specific network connection occur. /// /// A GUID that identifies the network connection on which the event occurred. /// The NLM_CONNECTION_PROPERTY_CHANGE flags for this connection. - void NetworkConnectionPropertyChanged([In] Guid connectionId, [In] NLM_CONNECTION_PROPERTY_CHANGE Flags); + [PreserveSig] + HRESULT NetworkConnectionPropertyChanged([In] Guid connectionId, [In] NLM_CONNECTION_PROPERTY_CHANGE Flags); } /// @@ -463,7 +467,7 @@ namespace Vanara.PInvoke.NetListMgr /// An structure containing the destination IPv4/IPv6 address. If NULL, this method will instead return the cost associated with the /// preferred connection used for machine Internet connectivity. /// - void GetCost(out NLM_CONNECTION_COST pCost, [In] IntPtr pDestIPAddr); + void GetCost(out NLM_CONNECTION_COST pCost, [In, Optional] NLM_SOCKADDR pDestIPAddr); /// /// The GetDataPlanStatus retrieves the data plan status for either a machine-wide internet connection , or the first-hop of routing to a specific @@ -478,7 +482,7 @@ namespace Vanara.PInvoke.NetListMgr /// An structure containing the destination IPv4/IPv6 or tunnel address. If NULL, this method returns the cost associated with the /// preferred connection used for machine Internet connectivity. /// - void GetDataPlanStatus(out NLM_DATAPLAN_STATUS pDataPlanStatus, [In] IntPtr pDestIPAddr); + void GetDataPlanStatus(out NLM_DATAPLAN_STATUS pDataPlanStatus, [In, Optional] NLM_SOCKADDR pDestIPAddr); /// /// The SetDestinationAddresses method registers specified destination IPv4/IPv6 addresses to receive cost or data plan status change notifications. @@ -488,11 +492,11 @@ namespace Vanara.PInvoke.NetListMgr /// A structure containing a list of destination IPv4/IPv6 addresses to register for cost or data plan status change notification. /// /// If true, pDestIPAddrList will be appended to the existing address list; otherwise the existing list will be overwritten. - void SetDestinationAddresses([In] uint length, [In] IntPtr pDestIPAddrList, [In] bool bAppend); + void SetDestinationAddresses([In] uint length, [In, Optional, MarshalAs(UnmanagedType.LPArray)] NLM_SOCKADDR[] pDestIPAddrList, [In] bool bAppend); } /// Use this interface to notify an application of machine-wide cost and data plan related events. - [ComImport, Guid("DCB00009-570F-4A9B-8D69-199FDBA5723B"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), CoClass(typeof(NetworkListManager))] + [ComImport, Guid("DCB00009-570F-4A9B-8D69-199FDBA5723B"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] [PInvokeData("Netlistmgr.h")] public interface INetworkCostManagerEvents { @@ -508,7 +512,8 @@ namespace Vanara.PInvoke.NetListMgr /// An structure containing an IPv4/IPv6 address that identifies the destination on which the event occurred. If destAddr is NULL, the /// change is a machine-wide Internet connectivity change. /// - void CostChanged([In] NLM_CONNECTION_COST newCost, in NLM_SOCKADDR pDestAddr); + [PreserveSig] + HRESULT CostChanged([In] NLM_CONNECTION_COST newCost, [In, Optional] NLM_SOCKADDR pDestAddr); /// /// The DataPlanStatusChanged method is called to indicate a change to the status of a data plan associated with either a connection used for @@ -518,34 +523,39 @@ namespace Vanara.PInvoke.NetListMgr /// An structure containing an IPv4/IPv6 address that identifies the destination for which the event occurred. If destAddr is NULL, the /// change is a machine-wide Internet connectivity change. /// - void DataPlanStatusChanged(in NLM_SOCKADDR pDestAddr); + [PreserveSig] + HRESULT DataPlanStatusChanged([In, Optional] NLM_SOCKADDR pDestAddr); } /// /// INetworkEvents is a notification sink interface that a client implements to get network related events. These APIs are all callback functions that /// are called automatically when the respective events are raised. /// - [ComImport, Guid("DCB00004-570F-4A9B-8D69-199FDBA5723B"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), TypeLibType(TypeLibTypeFlags.FOleAutomation), CoClass(typeof(NetworkListManager))] + [ComImport, Guid("DCB00004-570F-4A9B-8D69-199FDBA5723B"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), TypeLibType(TypeLibTypeFlags.FOleAutomation)] [PInvokeData("Netlistmgr.h")] public interface INetworkEvents { /// The NetworkAdded method is called when a new network is added. The GUID of the new network is provided. /// A GUID that specifies the new network that was added. - void NetworkAdded([In] Guid networkId); + [PreserveSig] + HRESULT NetworkAdded([In] Guid networkId); /// The NetworkDeleted method is called when a network is deleted. /// GUID that contains the network ID of the network that was deleted. - void NetworkDeleted([In] Guid networkId); + [PreserveSig] + HRESULT NetworkDeleted([In] Guid networkId); /// The NetworkConnectivityChanged method is called when network connectivity related changes occur. /// A GUID that specifies the new network that was added. /// NLM_CONNECTIVITY enumeration value that contains the new connectivity of this network - void NetworkConnectivityChanged([In] Guid networkId, [In] NLM_CONNECTIVITY newConnectivity); + [PreserveSig] + HRESULT NetworkConnectivityChanged([In] Guid networkId, [In] NLM_CONNECTIVITY newConnectivity); /// The NetworkPropertyChanged method is called when a network property change is detected. /// GUID that specifies the network on which this event occurred. /// NLM_NETWORK_PROPERTY_CHANGE enumeration value that specifies the network property that changed. - void NetworkPropertyChanged([In] Guid networkId, [In] NLM_NETWORK_PROPERTY_CHANGE Flags); + [PreserveSig] + HRESULT NetworkPropertyChanged([In] Guid networkId, [In] NLM_NETWORK_PROPERTY_CHANGE Flags); } /// The INetworkListManager interface provides a set of methods to perform network list management functions. @@ -626,13 +636,14 @@ namespace Vanara.PInvoke.NetListMgr /// INetworkListManagerEvents is a message sink interface that a client implements to get overall machine state related events. Applications that are /// interested on higher-level events, for example internet connectivity, implement this interface. /// - [ComImport, Guid("DCB00001-570F-4A9B-8D69-199FDBA5723B"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), CoClass(typeof(NetworkListManager)), TypeLibType(TypeLibTypeFlags.FOleAutomation)] + [ComImport, Guid("DCB00001-570F-4A9B-8D69-199FDBA5723B"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), TypeLibType(TypeLibTypeFlags.FOleAutomation)] [PInvokeData("Netlistmgr.h")] public interface INetworkListManagerEvents { /// Called when network connectivity related changes occur. /// An NLM_CONNECTIVITY enumeration value that contains the new connectivity settings of the machine. - void ConnectivityChanged([In] NLM_CONNECTIVITY newConnectivity); + [PreserveSig] + HRESULT ConnectivityChanged([In] NLM_CONNECTIVITY newConnectivity); } /// The NetworkListManager class is the base CoClass for all interfaces. @@ -755,12 +766,12 @@ namespace Vanara.PInvoke.NetListMgr /// The structure contains the IPv4/IPv6 destination address. [StructLayout(LayoutKind.Sequential, Pack = 1)] [PInvokeData("Netlistmgr.h", MSDNShortId = "hh448266")] - public struct NLM_SOCKADDR + public sealed class NLM_SOCKADDR { private const int dataSize = 128; /// An IPv4/IPv6 destination address. - [MarshalAs(UnmanagedType.ByValArray, SizeConst = dataSize)] public byte[] data; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = dataSize)] public byte[] data = new byte[dataSize]; /// Creates a from an instance. /// The IP address to encapsulate. @@ -770,7 +781,7 @@ namespace Vanara.PInvoke.NetListMgr const ushort AF_INET = 2; const ushort AF_INET6 = 23; - if (address == null) throw new ArgumentNullException(nameof(address)); + if (address == null) return null; var sockAddr = new NLM_SOCKADDR { data = new byte[dataSize] }; diff --git a/System/Network/NetworkListManager.cs b/System/Network/NetworkListManager.cs index a57546fa..27f6dc14 100644 --- a/System/Network/NetworkListManager.cs +++ b/System/Network/NetworkListManager.cs @@ -4,8 +4,6 @@ using System.Collections.Generic; using System.Linq; using System.Net; using System.Runtime.InteropServices; -using System.Runtime.InteropServices.ComTypes; -using Vanara.InteropServices; using Vanara.PInvoke.NetListMgr; namespace Vanara.Network @@ -65,9 +63,9 @@ namespace Vanara.Network /// The cost of the connection. public static NLM_CONNECTION_COST GetConnectionCost(IPAddress destIPAddr = null) { - var ptr = destIPAddr != null ? new SafeCoTaskMemHandle(destIPAddr.GetAddressBytes()) : SafeCoTaskMemHandle.Null; + var addr = NLM_SOCKADDR.FromIPAddress(destIPAddr); var cost = NLM_CONNECTION_COST.NLM_CONNECTION_COST_UNKNOWN; - (costmgr ?? (costmgr = (INetworkCostManager)Manager))?.GetCost(out cost, (IntPtr)ptr); + (costmgr ?? (costmgr = (INetworkCostManager)Manager))?.GetCost(out cost, addr); return cost; } @@ -86,9 +84,9 @@ namespace Vanara.Network /// public static NLM_DATAPLAN_STATUS GetConnectionDataPlanStatus(IPAddress destIPAddr = null) { - var ptr = destIPAddr != null ? new SafeCoTaskMemHandle(destIPAddr.GetAddressBytes()) : SafeCoTaskMemHandle.Null; + var addr = NLM_SOCKADDR.FromIPAddress(destIPAddr); var cost = new NLM_DATAPLAN_STATUS(); - (costmgr ?? (costmgr = (INetworkCostManager)Manager))?.GetDataPlanStatus(out cost, (IntPtr)ptr); + (costmgr ?? (costmgr = (INetworkCostManager)Manager))?.GetDataPlanStatus(out cost, addr); return cost; } diff --git a/UnitTests/PInvoke/NetListMgr/NetListMgrTests.cs b/UnitTests/PInvoke/NetListMgr/NetListMgrTests.cs index 81f13d22..ed9d9b51 100644 --- a/UnitTests/PInvoke/NetListMgr/NetListMgrTests.cs +++ b/UnitTests/PInvoke/NetListMgr/NetListMgrTests.cs @@ -20,7 +20,6 @@ namespace Vanara.PInvoke.Tests { mgr = new INetworkListManager(); coster = new INetworkCostManager(); - //mgr = new NetworkListManagerClass(); } [Test] @@ -128,11 +127,11 @@ namespace Vanara.PInvoke.Tests public void GetCostTest() { NLM_CONNECTION_COST ret = 0; - Assert.That(() => coster.GetCost(out ret, IntPtr.Zero), Throws.Nothing); + Assert.That(() => coster.GetCost(out ret), Throws.Nothing); TestContext.WriteLine($"Cost:{ret}"); Assert.That((int)ret, Is.GreaterThan(0)); var status = new NLM_DATAPLAN_STATUS(); - Assert.That(() => coster.GetDataPlanStatus(out status, IntPtr.Zero), Throws.Nothing); + Assert.That(() => coster.GetDataPlanStatus(out status), Throws.Nothing); Assert.That(status.InterfaceGuid, Is.Not.EqualTo(Guid.Empty)); TestContext.WriteLine($"Guid:{status.InterfaceGuid}; Limit:{status.DataLimitInMegabytes:X}; Xfer:{status.MaxTransferSizeInMegabytes:X}"); }