diff --git a/src/libraries/Common/src/Interop/Windows/IpHlpApi/Interop.FIXED_INFO.cs b/src/libraries/Common/src/Interop/Windows/IpHlpApi/Interop.FIXED_INFO.cs index 50903914e37aafe3c28441bb300030f83fce7dcd..6e8f1a2149c95dfb4632ee6469369c69613e90b3 100644 --- a/src/libraries/Common/src/Interop/Windows/IpHlpApi/Interop.FIXED_INFO.cs +++ b/src/libraries/Common/src/Interop/Windows/IpHlpApi/Interop.FIXED_INFO.cs @@ -12,21 +12,34 @@ internal static partial class IpHlpApi public const int MAX_DOMAIN_NAME_LEN = 128; public const int MAX_SCOPE_ID_LEN = 256; - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] - public struct FIXED_INFO + [StructLayout(LayoutKind.Sequential)] + public unsafe struct FIXED_INFO { - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_HOSTNAME_LEN + 4)] - public string hostName; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_DOMAIN_NAME_LEN + 4)] - public string domainName; + private fixed byte _hostName[MAX_HOSTNAME_LEN + 4]; + public string HostName => CreateString(ref _hostName[0], MAX_HOSTNAME_LEN + 4); + + private fixed byte _domainName[MAX_DOMAIN_NAME_LEN + 4]; + public string DomainName => CreateString(ref _domainName[0], MAX_DOMAIN_NAME_LEN + 4); + public IntPtr currentDnsServer; // IpAddressList* public IP_ADDR_STRING DnsServerList; public uint nodeType; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_SCOPE_ID_LEN + 4)] - public string scopeId; - public bool enableRouting; - public bool enableProxy; - public bool enableDns; + + private fixed byte _scopeId[MAX_SCOPE_ID_LEN + 4]; + public string ScopeId => CreateString(ref _scopeId[0], MAX_SCOPE_ID_LEN + 4); + + public uint enableRouting; + public uint enableProxy; + public uint enableDns; + + private static string CreateString(ref byte firstByte, int maxLength) + { + fixed (byte* ptr = &firstByte) + { + int terminator = new ReadOnlySpan(ptr, maxLength).IndexOf((byte)0); + return Marshal.PtrToStringAnsi((IntPtr)ptr, (terminator >= 0) ? terminator : maxLength); + } + } } } } diff --git a/src/libraries/Common/src/Interop/Windows/IpHlpApi/Interop.ICMP.cs b/src/libraries/Common/src/Interop/Windows/IpHlpApi/Interop.ICMP.cs index 1a56dd11dd0d844789a7626e2e66a8f16ddf1b65..1223defd9ae746ae5710a51bc8c099a5f79ed2c3 100644 --- a/src/libraries/Common/src/Interop/Windows/IpHlpApi/Interop.ICMP.cs +++ b/src/libraries/Common/src/Interop/Windows/IpHlpApi/Interop.ICMP.cs @@ -13,7 +13,7 @@ internal static partial class IpHlpApi internal const int IP_STATUS_BASE = 11000; [StructLayout(LayoutKind.Sequential)] - internal struct IPOptions + internal struct IP_OPTION_INFORMATION { internal byte ttl; internal byte tos; @@ -21,7 +21,7 @@ internal struct IPOptions internal byte optionsSize; internal IntPtr optionsData; - internal IPOptions(PingOptions? options) + internal IP_OPTION_INFORMATION(PingOptions? options) { ttl = 128; tos = 0; @@ -42,7 +42,7 @@ internal IPOptions(PingOptions? options) } [StructLayout(LayoutKind.Sequential)] - internal struct IcmpEchoReply + internal struct ICMP_ECHO_REPLY { internal uint address; internal uint status; @@ -50,31 +50,30 @@ internal struct IcmpEchoReply internal ushort dataSize; internal ushort reserved; internal IntPtr data; - internal IPOptions options; + internal IP_OPTION_INFORMATION options; } [StructLayout(LayoutKind.Sequential, Pack = 1)] - internal struct Ipv6Address + internal unsafe struct IPV6_ADDRESS_EX { - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] - internal byte[] Goo; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] + internal ushort port; + internal uint flowinfo; + // Replying address. - internal byte[] Address; + private fixed byte _Address[16]; + internal byte[] Address => MemoryMarshal.CreateReadOnlySpan(ref _Address[0], 16).ToArray(); + internal uint ScopeID; } [StructLayout(LayoutKind.Sequential)] - internal struct Icmp6EchoReply + internal struct ICMPV6_ECHO_REPLY { - internal Ipv6Address Address; + internal IPV6_ADDRESS_EX Address; // Reply IP_STATUS. internal uint Status; // RTT in milliseconds. internal uint RoundTripTime; - internal IntPtr data; - // internal IPOptions options; - // internal IntPtr data; data os after tjos } internal sealed class SafeCloseIcmpHandle : SafeHandleZeroOrMinusOneIsInvalid @@ -101,10 +100,10 @@ protected override bool ReleaseHandle() [LibraryImport(Interop.Libraries.IpHlpApi, SetLastError = true)] internal static partial uint IcmpSendEcho2(SafeCloseIcmpHandle icmpHandle, SafeWaitHandle Event, IntPtr apcRoutine, IntPtr apcContext, - uint ipAddress, SafeLocalAllocHandle data, ushort dataSize, ref IPOptions options, SafeLocalAllocHandle replyBuffer, uint replySize, uint timeout); + uint ipAddress, SafeLocalAllocHandle data, ushort dataSize, ref IP_OPTION_INFORMATION options, SafeLocalAllocHandle replyBuffer, uint replySize, uint timeout); [LibraryImport(Interop.Libraries.IpHlpApi, SetLastError = true)] internal static partial uint Icmp6SendEcho2(SafeCloseIcmpHandle icmpHandle, SafeWaitHandle Event, IntPtr apcRoutine, IntPtr apcContext, - byte[] sourceSocketAddress, byte[] destSocketAddress, SafeLocalAllocHandle data, ushort dataSize, ref IPOptions options, SafeLocalAllocHandle replyBuffer, uint replySize, uint timeout); + byte[] sourceSocketAddress, byte[] destSocketAddress, SafeLocalAllocHandle data, ushort dataSize, ref IP_OPTION_INFORMATION options, SafeLocalAllocHandle replyBuffer, uint replySize, uint timeout); } } diff --git a/src/libraries/Common/src/Interop/Windows/IpHlpApi/Interop.IP_ADDR_STRING.cs b/src/libraries/Common/src/Interop/Windows/IpHlpApi/Interop.IP_ADDR_STRING.cs index 8f24e28dba957b2d355a12917a8e06a46b6389da..0f2d318e7f101bc2c03d46317ac8c7bae64c9d08 100644 --- a/src/libraries/Common/src/Interop/Windows/IpHlpApi/Interop.IP_ADDR_STRING.cs +++ b/src/libraries/Common/src/Interop/Windows/IpHlpApi/Interop.IP_ADDR_STRING.cs @@ -8,14 +8,12 @@ internal static partial class Interop { internal static partial class IpHlpApi { - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] - public struct IP_ADDR_STRING + [StructLayout(LayoutKind.Sequential)] + public unsafe struct IP_ADDR_STRING { - public IntPtr Next; // struct _IpAddressList* - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)] - public string IpAddress; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)] - public string IpMask; + public IP_ADDR_STRING* Next; + public fixed byte IpAddress[16]; + public fixed byte IpMask[16]; public uint Context; } } diff --git a/src/libraries/Common/src/Interop/Windows/IpHlpApi/Interop.NetworkInformation.cs b/src/libraries/Common/src/Interop/Windows/IpHlpApi/Interop.NetworkInformation.cs index 3f0cd7444fdf45ddd9213f6f7b3ed47497b53f02..71e67116e4ebe291f3c2598482156d575b865a35 100644 --- a/src/libraries/Common/src/Interop/Windows/IpHlpApi/Interop.NetworkInformation.cs +++ b/src/libraries/Common/src/Interop/Windows/IpHlpApi/Interop.NetworkInformation.cs @@ -157,14 +157,7 @@ internal unsafe struct IpAdapterAddresses private fixed byte _address[MAX_ADAPTER_ADDRESS_LENGTH]; private uint _addressLength; - internal byte[] Address - { - get - { - fixed (byte* pAddress = _address) - return new ReadOnlySpan(pAddress, (int)_addressLength).ToArray(); - } - } + internal byte[] Address => MemoryMarshal.CreateReadOnlySpan(ref _address[0], (int)_addressLength).ToArray(); internal AdapterFlags flags; internal uint mtu; @@ -173,14 +166,7 @@ internal byte[] Address internal uint ipv6Index; private fixed uint _zoneIndices[16]; - internal uint[] ZoneIndices - { - get - { - fixed (uint* pZoneIndices = _zoneIndices) - return new ReadOnlySpan(pZoneIndices, 16).ToArray(); - } - } + internal uint[] ZoneIndices => MemoryMarshal.CreateReadOnlySpan(ref _zoneIndices[0], 16).ToArray(); internal IntPtr firstPrefix; diff --git a/src/libraries/Common/src/System/Net/NetworkInformation/HostInformationPal.Windows.cs b/src/libraries/Common/src/System/Net/NetworkInformation/HostInformationPal.Windows.cs index bfd4127724ac74c0c7860f5cf88ff1ca15c18419..6035b9e6ef24d90c0f110cb18d1cb81327676b47 100644 --- a/src/libraries/Common/src/System/Net/NetworkInformation/HostInformationPal.Windows.cs +++ b/src/libraries/Common/src/System/Net/NetworkInformation/HostInformationPal.Windows.cs @@ -12,61 +12,113 @@ namespace System.Net.NetworkInformation internal static class HostInformationPal { // Changing this information requires a reboot, so it's safe to cache. - private static Interop.IpHlpApi.FIXED_INFO s_fixedInfo; - private static bool s_fixedInfoInitialized; + private static string? s_hostName; + private static string? s_domainName; + private static uint s_nodeType; + private static string? s_scopeId; + private static bool s_enableRouting; + private static bool s_enableProxy; + private static bool s_enableDns; + + private static volatile bool s_initialized; private static object s_syncObject = new object(); public static string GetHostName() { - return FixedInfo.hostName; + EnsureInitialized(); + return s_hostName!; } public static string GetDomainName() { - return FixedInfo.domainName; + EnsureInitialized(); + return s_domainName!; + } + + public static uint GetNodeType() + { + EnsureInitialized(); + return s_nodeType; + } + + public static string GetScopeId() + { + EnsureInitialized(); + return s_scopeId!; + } + + public static bool GetEnableRouting() + { + EnsureInitialized(); + return s_enableRouting; } - private static unsafe Interop.IpHlpApi.FIXED_INFO GetFixedInfo() + public static bool GetEnableProxy() { - uint size = 0; - Interop.IpHlpApi.FIXED_INFO fixedInfo = default; + EnsureInitialized(); + return s_enableProxy; + } - // First we need to get the size of the buffer - uint result = Interop.IpHlpApi.GetNetworkParams(IntPtr.Zero, &size); + public static bool GetEnableDns() + { + EnsureInitialized(); + return s_enableDns; + } - while (result == Interop.IpHlpApi.ERROR_BUFFER_OVERFLOW) + private static void EnsureInitialized() + { + if (!s_initialized) + Initialize(); + } + + private static unsafe void Initialize() + { + lock (s_syncObject) { - IntPtr buffer = Marshal.AllocHGlobal((int)size); - try + if (s_initialized) + return; + + uint size = 0; + + // First we need to get the size of the buffer + uint result = Interop.IpHlpApi.GetNetworkParams(IntPtr.Zero, &size); + + while (result == Interop.IpHlpApi.ERROR_BUFFER_OVERFLOW) { - result = Interop.IpHlpApi.GetNetworkParams(buffer, &size); - if (result == Interop.IpHlpApi.ERROR_SUCCESS) + IntPtr buffer = Marshal.AllocHGlobal((int)size); + try { - fixedInfo = Marshal.PtrToStructure(buffer); + result = Interop.IpHlpApi.GetNetworkParams(buffer, &size); + if (result == Interop.IpHlpApi.ERROR_SUCCESS) + { + Interop.IpHlpApi.FIXED_INFO* pFixedInfo = (Interop.IpHlpApi.FIXED_INFO*)buffer; + + s_hostName = pFixedInfo->HostName; + s_domainName = pFixedInfo->DomainName; + + s_hostName = pFixedInfo->HostName; + s_domainName = pFixedInfo->DomainName; + s_nodeType = pFixedInfo->nodeType; + s_scopeId = pFixedInfo->ScopeId; + s_enableRouting = pFixedInfo->enableRouting != 0; + s_enableProxy = pFixedInfo->enableProxy != 0; + s_enableDns = pFixedInfo->enableDns != 0; + + s_initialized = true; + } + } + finally + { + Marshal.FreeHGlobal(buffer); } } - finally + + // If the result include there being no information, we'll still throw + if (result != Interop.IpHlpApi.ERROR_SUCCESS) { - Marshal.FreeHGlobal(buffer); + throw new Win32Exception((int)result); } } - - // If the result include there being no information, we'll still throw - if (result != Interop.IpHlpApi.ERROR_SUCCESS) - { - throw new Win32Exception((int)result); - } - - return fixedInfo; - } - - public static ref readonly Interop.IpHlpApi.FIXED_INFO FixedInfo - { - get - { - LazyInitializer.EnsureInitialized(ref s_fixedInfo, ref s_fixedInfoInitialized, ref s_syncObject, () => GetFixedInfo()); - return ref s_fixedInfo; - } } } } diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemIPGlobalProperties.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemIPGlobalProperties.cs index aece4dab54725d1fa5fa20e2b170c2e574376d7a..b460cef6f6a6b2ce83a4166e3f5dcbdb5bdabc27 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemIPGlobalProperties.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemIPGlobalProperties.cs @@ -19,7 +19,7 @@ public override string HostName { get { - return HostInformationPal.FixedInfo.hostName; + return HostInformationPal.GetHostName(); } } @@ -28,7 +28,7 @@ public override string DomainName { get { - return HostInformationPal.FixedInfo.domainName; + return HostInformationPal.GetDomainName(); } } @@ -48,7 +48,7 @@ public override NetBiosNodeType NodeType { get { - return (NetBiosNodeType)HostInformationPal.FixedInfo.nodeType; + return (NetBiosNodeType)HostInformationPal.GetNodeType(); } } @@ -57,7 +57,7 @@ public override string DhcpScopeName { get { - return HostInformationPal.FixedInfo.scopeId; + return HostInformationPal.GetScopeId(); } } @@ -66,7 +66,7 @@ public override bool IsWinsProxy { get { - return (HostInformationPal.FixedInfo.enableProxy); + return HostInformationPal.GetEnableProxy(); } } diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemIPInterfaceProperties.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemIPInterfaceProperties.cs index fbdd43df85ca24802d157b081899d3a087add94b..a12a08cc05b9c97c62c4f796337cddf0cee7b87e 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemIPInterfaceProperties.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemIPInterfaceProperties.cs @@ -26,11 +26,11 @@ internal sealed class SystemIPInterfaceProperties : IPInterfaceProperties private readonly GatewayIPAddressInformationCollection _gatewayAddresses; private readonly InternalIPAddressCollection _dhcpServers; - internal SystemIPInterfaceProperties(in Interop.IpHlpApi.FIXED_INFO fixedInfo, in Interop.IpHlpApi.IpAdapterAddresses ipAdapterAddresses) + internal SystemIPInterfaceProperties(in Interop.IpHlpApi.IpAdapterAddresses ipAdapterAddresses) { _adapterFlags = ipAdapterAddresses.flags; _dnsSuffix = ipAdapterAddresses.DnsSuffix; - _dnsEnabled = fixedInfo.enableDns; + _dnsEnabled = HostInformationPal.GetEnableDns(); _dynamicDnsEnabled = ((ipAdapterAddresses.flags & Interop.IpHlpApi.AdapterFlags.DnsEnabled) > 0); _multicastAddresses = SystemMulticastIPAddressInformation.ToMulticastIpAddressInformationCollection( @@ -58,7 +58,7 @@ internal SystemIPInterfaceProperties(in Interop.IpHlpApi.FIXED_INFO fixedInfo, i if ((_adapterFlags & Interop.IpHlpApi.AdapterFlags.IPv4Enabled) != 0) { - _ipv4Properties = new SystemIPv4InterfaceProperties(fixedInfo, ipAdapterAddresses); + _ipv4Properties = new SystemIPv4InterfaceProperties(ipAdapterAddresses); } if ((_adapterFlags & Interop.IpHlpApi.AdapterFlags.IPv6Enabled) != 0) diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemIPv4InterfaceProperties.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemIPv4InterfaceProperties.cs index e96e1cdb59e8c57d04e6e705d956437c8ea1111d..08670e0cad4f69c27200250d8b5e756271bb899e 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemIPv4InterfaceProperties.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemIPv4InterfaceProperties.cs @@ -18,10 +18,10 @@ internal sealed class SystemIPv4InterfaceProperties : IPv4InterfaceProperties private bool _autoConfigEnabled; private bool _autoConfigActive; - internal SystemIPv4InterfaceProperties(Interop.IpHlpApi.FIXED_INFO fixedInfo, Interop.IpHlpApi.IpAdapterAddresses ipAdapterAddresses) + internal SystemIPv4InterfaceProperties(in Interop.IpHlpApi.IpAdapterAddresses ipAdapterAddresses) { _index = ipAdapterAddresses.index; - _routingEnabled = fixedInfo.enableRouting; + _routingEnabled = HostInformationPal.GetEnableRouting(); _dhcpEnabled = ((ipAdapterAddresses.flags & Interop.IpHlpApi.AdapterFlags.DhcpEnabled) != 0); _haveWins = (ipAdapterAddresses.firstWinsServerAddress != IntPtr.Zero); diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemNetworkInterface.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemNetworkInterface.cs index e04e9e6274279505be6fb9fbf78a711123346c5f..c80e1cd206bde86ecc5c106d84c4f436a5d5722f 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemNetworkInterface.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemNetworkInterface.cs @@ -84,7 +84,6 @@ internal static unsafe NetworkInterface[] GetNetworkInterfaces() AddressFamily family = AddressFamily.Unspecified; uint bufferSize = 0; - ref readonly Interop.IpHlpApi.FIXED_INFO fixedInfo = ref HostInformationPal.FixedInfo; List interfaceList = new List(); Interop.IpHlpApi.GetAdaptersAddressesFlags flags = @@ -113,7 +112,7 @@ internal static unsafe NetworkInterface[] GetNetworkInterfaces() while (adapterAddresses != null) { // Traverse the list, marshal in the native structures, and create new NetworkInterfaces. - interfaceList.Add(new SystemNetworkInterface(in fixedInfo, in *adapterAddresses)); + interfaceList.Add(new SystemNetworkInterface(in *adapterAddresses)); adapterAddresses = adapterAddresses->next; } } @@ -139,7 +138,7 @@ internal static unsafe NetworkInterface[] GetNetworkInterfaces() return interfaceList.ToArray(); } - internal SystemNetworkInterface(in Interop.IpHlpApi.FIXED_INFO fixedInfo, in Interop.IpHlpApi.IpAdapterAddresses ipAdapterAddresses) + internal SystemNetworkInterface(in Interop.IpHlpApi.IpAdapterAddresses ipAdapterAddresses) { // Store the common API information. _id = ipAdapterAddresses.AdapterName; @@ -157,7 +156,7 @@ internal SystemNetworkInterface(in Interop.IpHlpApi.FIXED_INFO fixedInfo, in Int _ipv6Index = ipAdapterAddresses.ipv6Index; _adapterFlags = ipAdapterAddresses.flags; - _interfaceProperties = new SystemIPInterfaceProperties(fixedInfo, ipAdapterAddresses); + _interfaceProperties = new SystemIPInterfaceProperties(ipAdapterAddresses); } public override string Id { get { return _id; } } diff --git a/src/libraries/System.Net.Ping/src/System/Net/NetworkInformation/Ping.Windows.cs b/src/libraries/System.Net.Ping/src/System/Net/NetworkInformation/Ping.Windows.cs index 574d5577a2cccc025d8811c0d61367416c1c0c3e..73a38d927713f56b79aab967cf7ab154a2703eae 100644 --- a/src/libraries/System.Net.Ping/src/System/Net/NetworkInformation/Ping.Windows.cs +++ b/src/libraries/System.Net.Ping/src/System/Net/NetworkInformation/Ping.Windows.cs @@ -14,7 +14,7 @@ namespace System.Net.NetworkInformation { public partial class Ping { - private const int MaxUdpPacket = 0xFFFF + 256; // Marshal.SizeOf(typeof(Icmp6EchoReply)) * 2 + ip header info; + private const int MaxUdpPacket = 0xFFFF + 256; // Marshal.SizeOf(typeof(ICMPV6_ECHO_REPLY)) * 2 + ip header info; private static readonly SafeWaitHandle s_nullSafeWaitHandle = new SafeWaitHandle(IntPtr.Zero, true); @@ -165,7 +165,7 @@ private void InitialiseIcmpHandle() private int SendEcho(IPAddress address, byte[] buffer, int timeout, PingOptions? options, bool isAsync) { - Interop.IpHlpApi.IPOptions ipOptions = new Interop.IpHlpApi.IPOptions(options); + Interop.IpHlpApi.IP_OPTION_INFORMATION ipOptions = new Interop.IpHlpApi.IP_OPTION_INFORMATION(options); if (!_ipv6) { return (int)Interop.IpHlpApi.IcmpSendEcho2( @@ -203,19 +203,19 @@ private int SendEcho(IPAddress address, byte[] buffer, int timeout, PingOptions? (uint)timeout); } - private PingReply CreatePingReply() + private unsafe PingReply CreatePingReply() { SafeLocalAllocHandle buffer = _replyBuffer!; // Marshals and constructs new reply. if (_ipv6) { - Interop.IpHlpApi.Icmp6EchoReply icmp6Reply = Marshal.PtrToStructure(buffer.DangerousGetHandle()); - return CreatePingReplyFromIcmp6EchoReply(icmp6Reply, buffer.DangerousGetHandle(), _sendSize); + ref Interop.IpHlpApi.ICMPV6_ECHO_REPLY icmp6Reply = ref *(Interop.IpHlpApi.ICMPV6_ECHO_REPLY*)buffer.DangerousGetHandle(); + return CreatePingReplyFromIcmp6EchoReply(in icmp6Reply, buffer.DangerousGetHandle(), _sendSize); } - Interop.IpHlpApi.IcmpEchoReply icmpReply = Marshal.PtrToStructure(buffer.DangerousGetHandle()); - return CreatePingReplyFromIcmpEchoReply(icmpReply); + ref Interop.IpHlpApi.ICMP_ECHO_REPLY icmpReply = ref *(Interop.IpHlpApi.ICMP_ECHO_REPLY*)buffer.DangerousGetHandle(); + return CreatePingReplyFromIcmpEchoReply(in icmpReply); } private void Cleanup(bool isAsync) @@ -337,7 +337,7 @@ private static IPStatus GetStatusFromCode(int statusCode) return (IPStatus)statusCode; } - private static PingReply CreatePingReplyFromIcmpEchoReply(Interop.IpHlpApi.IcmpEchoReply reply) + private static PingReply CreatePingReplyFromIcmpEchoReply(in Interop.IpHlpApi.ICMP_ECHO_REPLY reply) { const int DontFragmentFlag = 2; @@ -366,7 +366,7 @@ private static PingReply CreatePingReplyFromIcmpEchoReply(Interop.IpHlpApi.IcmpE return new PingReply(address, options, ipStatus, rtt, buffer); } - private static PingReply CreatePingReplyFromIcmp6EchoReply(Interop.IpHlpApi.Icmp6EchoReply reply, IntPtr dataPtr, int sendSize) + private static PingReply CreatePingReplyFromIcmp6EchoReply(in Interop.IpHlpApi.ICMPV6_ECHO_REPLY reply, IntPtr dataPtr, int sendSize) { IPAddress address = new IPAddress(reply.Address.Address, reply.Address.ScopeID); IPStatus ipStatus = GetStatusFromCode((int)reply.Status);