未验证 提交 9dfdfbf1 编写于 作者: J Jan Kotas 提交者: GitHub

Replace the remaining uses of Marshal.PtrToStructure in core networking (#70900)

* Rename ICMP interop to match Windows SDK names
上级 0666d9d6
......@@ -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<byte>(ptr, maxLength).IndexOf((byte)0);
return Marshal.PtrToStringAnsi((IntPtr)ptr, (terminator >= 0) ? terminator : maxLength);
}
}
}
}
}
......@@ -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);
}
}
......@@ -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;
}
}
......
......@@ -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<byte>(pAddress, (int)_addressLength).ToArray();
}
}
internal byte[] Address => MemoryMarshal.CreateReadOnlySpan<byte>(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<uint>(pZoneIndices, 16).ToArray();
}
}
internal uint[] ZoneIndices => MemoryMarshal.CreateReadOnlySpan<uint>(ref _zoneIndices[0], 16).ToArray();
internal IntPtr firstPrefix;
......
......@@ -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<Interop.IpHlpApi.FIXED_INFO>(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;
}
}
}
}
......@@ -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();
}
}
......
......@@ -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)
......
......@@ -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);
......
......@@ -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<SystemNetworkInterface> interfaceList = new List<SystemNetworkInterface>();
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; } }
......
......@@ -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<Interop.IpHlpApi.Icmp6EchoReply>(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<Interop.IpHlpApi.IcmpEchoReply>(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);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册