private void GetPerAdapterInfo(uint index) { if (index != 0) { uint size = 0; SafeLocalAllocHandle buffer = null; uint result = Interop.IpHlpApi.GetPerAdapterInfo(index, SafeLocalAllocHandle.Zero, ref size); while (result == Interop.IpHlpApi.ERROR_BUFFER_OVERFLOW) { // Now we allocate the buffer and read the network parameters. using (buffer = SafeLocalAllocHandle.LocalAlloc((int)size)) { result = Interop.IpHlpApi.GetPerAdapterInfo(index, buffer, ref size); if (result == Interop.IpHlpApi.ERROR_SUCCESS) { Interop.IpHlpApi.IpPerAdapterInfo ipPerAdapterInfo = Marshal.PtrToStructure <Interop.IpHlpApi.IpPerAdapterInfo>(buffer.DangerousGetHandle()); _autoConfigEnabled = ipPerAdapterInfo.autoconfigEnabled; _autoConfigActive = ipPerAdapterInfo.autoconfigActive; } } } if (result != Interop.IpHlpApi.ERROR_SUCCESS) { throw new NetworkInformationException((int)result); } } }
// Any exceptions that escape synchronously will be caught by the caller and wrapped in a PingException. // We do not need to or want to capture such exceptions into the returned task. private Task <PingReply> DoSendPingCore(IPAddress address, byte[] buffer, int timeout, PingOptions options, bool isAsync) { TaskCompletionSource <PingReply> tcs = null; if (isAsync) { _taskCompletionSource = tcs = new TaskCompletionSource <PingReply>(); } _ipv6 = (address.AddressFamily == AddressFamily.InterNetworkV6); _sendSize = buffer.Length; // Cache correct handle. InitialiseIcmpHandle(); if (_replyBuffer == null) { _replyBuffer = SafeLocalAllocHandle.LocalAlloc(MaxUdpPacket); } int error; try { if (isAsync) { RegisterWaitHandle(); } SetUnmanagedStructures(buffer); error = SendEcho(address, buffer, timeout, options, isAsync); } catch { Cleanup(isAsync, isComplete: false); throw; } if (error == 0) { error = Marshal.GetLastWin32Error(); // Only skip Async IO Pending error value. if (!isAsync || error != Interop.IpHlpApi.ERROR_IO_PENDING) { Cleanup(isAsync, isComplete: false); throw new Win32Exception(error); } } if (isAsync) { return(tcs.Task); } Cleanup(isAsync: false, isComplete: true); return(Task.FromResult(CreatePingReply())); }
internal static NetworkInterface[] GetNetworkInterfaces() { Contract.Ensures(Contract.Result <NetworkInterface[]>() != null); AddressFamily family = AddressFamily.Unspecified; uint bufferSize = 0; SafeLocalAllocHandle buffer = null; // TODO: #2485: This will probably require changes in the PAL for HostInformation. Interop.IpHlpApi.FIXED_INFO fixedInfo = HostInformationPal.GetFixedInfo(); List <SystemNetworkInterface> interfaceList = new List <SystemNetworkInterface>(); Interop.IpHlpApi.GetAdaptersAddressesFlags flags = Interop.IpHlpApi.GetAdaptersAddressesFlags.IncludeGateways | Interop.IpHlpApi.GetAdaptersAddressesFlags.IncludeWins; // Figure out the right buffer size for the adapter information. uint result = Interop.IpHlpApi.GetAdaptersAddresses( family, (uint)flags, IntPtr.Zero, SafeLocalAllocHandle.Zero, ref bufferSize); while (result == Interop.IpHlpApi.ERROR_BUFFER_OVERFLOW) { // Allocate the buffer and get the adapter info. using (buffer = SafeLocalAllocHandle.LocalAlloc((int)bufferSize)) { result = Interop.IpHlpApi.GetAdaptersAddresses( family, (uint)flags, IntPtr.Zero, buffer, ref bufferSize); // If succeeded, we're going to add each new interface. if (result == Interop.IpHlpApi.ERROR_SUCCESS) { // Linked list of interfaces. IntPtr ptr = buffer.DangerousGetHandle(); while (ptr != IntPtr.Zero) { // Traverse the list, marshal in the native structures, and create new NetworkInterfaces. Interop.IpHlpApi.IpAdapterAddresses adapterAddresses = Marshal.PtrToStructure <Interop.IpHlpApi.IpAdapterAddresses>(ptr); interfaceList.Add(new SystemNetworkInterface(fixedInfo, adapterAddresses)); ptr = adapterAddresses.next; } } } } // If we don't have any interfaces detected, return empty. if (result == Interop.IpHlpApi.ERROR_NO_DATA || result == Interop.IpHlpApi.ERROR_INVALID_PARAMETER) { return(new SystemNetworkInterface[0]); } // Otherwise we throw on an error. if (result != Interop.IpHlpApi.ERROR_SUCCESS) { throw new NetworkInformationException((int)result); } return(interfaceList.ToArray()); }
// Copies _requestBuffer into unmanaged memory for async icmpsendecho APIs. private unsafe void SetUnmanagedStructures(byte[] buffer) { _requestBuffer = SafeLocalAllocHandle.LocalAlloc(buffer.Length); byte *dst = (byte *)_requestBuffer.DangerousGetHandle(); for (int i = 0; i < buffer.Length; ++i) { dst[i] = buffer[i]; } }
// Any exceptions that escape synchronously will be caught by the caller and wrapped in a PingException. // We do not need to or want to capture such exceptions into the returned task. private Task <PingReply> DoSendPingCore(IPAddress address, byte[] buffer, int timeout, PingOptions?options, bool isAsync) { TaskCompletionSource <PingReply>?tcs = null; if (isAsync) { _taskCompletionSource = tcs = new TaskCompletionSource <PingReply>(); } _ipv6 = (address.AddressFamily == AddressFamily.InterNetworkV6); _sendSize = buffer.Length; // Cache correct handle. InitialiseIcmpHandle(); if (_replyBuffer == null) { _replyBuffer = SafeLocalAllocHandle.LocalAlloc(MaxUdpPacket); } int error; try { if (isAsync) { RegisterWaitHandle(); } SetUnmanagedStructures(buffer); error = SendEcho(address, buffer, timeout, options, isAsync); } catch { Cleanup(isAsync); throw; } if (error == 0) { error = Marshal.GetLastPInvokeError(); // Only skip Async IO Pending error value. if (!isAsync || error != Interop.IpHlpApi.ERROR_IO_PENDING) { Cleanup(isAsync); IPStatus status = GetStatusFromCode(error); return(Task.FromResult(new PingReply(address, default, status, default, Array.Empty <byte>())));
internal static NetworkInterface[] GetNetworkInterfaces() { AddressFamily family = AddressFamily.Unspecified; uint outBufLen = 0; Interop.FIXED_INFO fixedInfo = HostInformationPal.GetFixedInfo(); List <SystemNetworkInterface> networkInterfaceList = new List <SystemNetworkInterface>(); Interop.GetAdaptersAddressesFlags adaptersAddressesFlags = Interop.GetAdaptersAddressesFlags.IncludeWins | Interop.GetAdaptersAddressesFlags.IncludeGateways | Interop.GetAdaptersAddressesFlags.IncludeAllInterfaces; uint adaptersAddresses = Interop.GetAdaptersAddresses(family, (uint)adaptersAddressesFlags, IntPtr.Zero, SafeLocalAllocHandle.Zero, ref outBufLen); while ((int)adaptersAddresses == 111) { SafeLocalAllocHandle adapterAddresses; using (adapterAddresses = SafeLocalAllocHandle.LocalAlloc((int)outBufLen)) { adaptersAddresses = Interop.GetAdaptersAddresses(family, (uint)adaptersAddressesFlags, IntPtr.Zero, adapterAddresses, ref outBufLen); Interop.IpAdapterAddresses structure; if ((int)adaptersAddresses == 0) { for (IntPtr ptr = adapterAddresses.DangerousGetHandle(); ptr != IntPtr.Zero; ptr = structure.next) { structure = Marshal.PtrToStructure <Interop.IpAdapterAddresses>(ptr); var a = new SystemNetworkInterface(fixedInfo, structure); networkInterfaceList.Add(a); } } } } if ((int)adaptersAddresses == 232 || (int)adaptersAddresses == 87) { return((NetworkInterface[])Array.Empty <SystemNetworkInterface>()); } if ((int)adaptersAddresses != 0) { throw new NetworkInformationException((int)adaptersAddresses); } return((NetworkInterface[])networkInterfaceList.ToArray()); }
/// <summary>Initialize the VideoFrameReader.</summary> /// <param name="path">The path to the video to load.</param> public VideoFrameReader(string path) { if (path == null) { throw new ArgumentNullException(path); } // Load the video, determine the size of a frame in the video, // determine the length of the video, and calculate the number of frames in it. _mediaDetector = LoadVideo(path, out _mediaType); _frameSize = GetFrameSize(_mediaType); _streamLength = _mediaDetector.StreamLength; _numberOfFrames = (int)(_streamLength * _mediaDetector.FrameRate); // Create an unmanaged buffer to use in the frame extraction process. // We need a buffer large enough to store three bytes per pixel (RGB) // plus the size of a BITMAPINFOHEADER structure. _headerSize = Marshal.SizeOf(typeof(BITMAPINFOHEADER)); _bufferSize = (_frameSize.Width * _frameSize.Height * 3) + _headerSize; _frameBuffer = SafeLocalAllocHandle.LocalAlloc(_bufferSize); }
// Any exceptions that escape synchronously will be caught by the caller and wrapped in a PingException. // We do not need to or want to capture such exceptions into the returned task. private Task <PingReply> SendPingAsyncCore(IPAddress address, byte[] buffer, int timeout, PingOptions options) { var tcs = new TaskCompletionSource <PingReply>(); _taskCompletionSource = tcs; _ipv6 = (address.AddressFamily == AddressFamily.InterNetworkV6); _sendSize = buffer.Length; // Get and cache correct handle. if (!_ipv6 && _handlePingV4 == null) { _handlePingV4 = Interop.IpHlpApi.IcmpCreateFile(); if (_handlePingV4.IsInvalid) { _handlePingV4 = null; throw new Win32Exception(); // Gets last error. } } else if (_ipv6 && _handlePingV6 == null) { _handlePingV6 = Interop.IpHlpApi.Icmp6CreateFile(); if (_handlePingV6.IsInvalid) { _handlePingV6 = null; throw new Win32Exception(); // Gets last error. } } var ipOptions = new Interop.IpHlpApi.IPOptions(options); if (_replyBuffer == null) { _replyBuffer = SafeLocalAllocHandle.LocalAlloc(MaxUdpPacket); } // Queue the event. int error; try { if (_pingEvent == null) { _pingEvent = new ManualResetEvent(false); } else { _pingEvent.Reset(); } _registeredWait = ThreadPool.RegisterWaitForSingleObject(_pingEvent, (state, _) => ((Ping)state).PingCallback(), this, -1, true); SetUnmanagedStructures(buffer); if (!_ipv6) { SafeWaitHandle pingEventSafeWaitHandle = _pingEvent.GetSafeWaitHandle(); error = (int)Interop.IpHlpApi.IcmpSendEcho2( _handlePingV4, pingEventSafeWaitHandle, IntPtr.Zero, IntPtr.Zero, (uint)address.GetAddress(), _requestBuffer, (ushort)buffer.Length, ref ipOptions, _replyBuffer, MaxUdpPacket, (uint)timeout); } else { IPEndPoint ep = new IPEndPoint(address, 0); SystemNet.Internals.SocketAddress remoteAddr = IPEndPointExtensions.Serialize(ep); byte[] sourceAddr = new byte[28]; SafeWaitHandle pingEventSafeWaitHandle = _pingEvent.GetSafeWaitHandle(); error = (int)Interop.IpHlpApi.Icmp6SendEcho2( _handlePingV6, pingEventSafeWaitHandle, IntPtr.Zero, IntPtr.Zero, sourceAddr, remoteAddr.Buffer, _requestBuffer, (ushort)buffer.Length, ref ipOptions, _replyBuffer, MaxUdpPacket, (uint)timeout); } } catch { UnregisterWaitHandle(); throw; } if (error == 0) { error = Marshal.GetLastWin32Error(); // Only skip Async IO Pending error value. if (error != Interop.IpHlpApi.ERROR_IO_PENDING) { // Cleanup. FreeUnmanagedStructures(); UnregisterWaitHandle(); throw new Win32Exception(error); } } return(tcs.Task); }
private void WriteCore(byte[] buffer, int offset, int size) { Interop.HttpApi.HTTP_FLAGS flags = ComputeLeftToWrite(); if (size == 0 && _leftToWrite != 0) { return; } if (_leftToWrite >= 0 && size > _leftToWrite) { throw new ProtocolViolationException(SR.net_entitytoobig); } uint statusCode; uint dataToWrite = (uint)size; SafeLocalAllocHandle?bufferAsIntPtr = null; IntPtr pBufferAsIntPtr = IntPtr.Zero; bool sentHeaders = _httpContext.Response.SentHeaders; try { if (size == 0) { statusCode = _httpContext.Response.SendHeaders(null, null, flags, false); } else { fixed(byte *pDataBuffer = buffer) { byte *pBuffer = pDataBuffer; if (_httpContext.Response.BoundaryType == BoundaryType.Chunked) { string chunkHeader = size.ToString("x", CultureInfo.InvariantCulture); dataToWrite = dataToWrite + (uint)(chunkHeader.Length + 4); bufferAsIntPtr = SafeLocalAllocHandle.LocalAlloc((int)dataToWrite); pBufferAsIntPtr = bufferAsIntPtr.DangerousGetHandle(); for (int i = 0; i < chunkHeader.Length; i++) { Marshal.WriteByte(pBufferAsIntPtr, i, (byte)chunkHeader[i]); } Marshal.WriteInt16(pBufferAsIntPtr, chunkHeader.Length, 0x0A0D); Marshal.Copy(buffer, offset, pBufferAsIntPtr + chunkHeader.Length + 2, size); Marshal.WriteInt16(pBufferAsIntPtr, (int)(dataToWrite - 2), 0x0A0D); pBuffer = (byte *)pBufferAsIntPtr; offset = 0; } Interop.HttpApi.HTTP_DATA_CHUNK dataChunk = default; dataChunk.DataChunkType = Interop.HttpApi.HTTP_DATA_CHUNK_TYPE.HttpDataChunkFromMemory; dataChunk.pBuffer = (byte *)(pBuffer + offset); dataChunk.BufferLength = dataToWrite; flags |= _leftToWrite == size ? Interop.HttpApi.HTTP_FLAGS.NONE : Interop.HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_MORE_DATA; if (!sentHeaders) { statusCode = _httpContext.Response.SendHeaders(&dataChunk, null, flags, false); } else { if (NetEventSource.Log.IsEnabled()) { NetEventSource.Info(this, "Calling Interop.HttpApi.HttpSendResponseEntityBody"); } statusCode = Interop.HttpApi.HttpSendResponseEntityBody( _httpContext.RequestQueueHandle, _httpContext.RequestId, (uint)flags, 1, &dataChunk, null, SafeLocalAllocHandle.Zero, 0, null, null); if (NetEventSource.Log.IsEnabled()) { NetEventSource.Info(this, "Call to Interop.HttpApi.HttpSendResponseEntityBody returned:" + statusCode); } if (_httpContext.Listener !.IgnoreWriteExceptions) { if (NetEventSource.Log.IsEnabled()) { NetEventSource.Info(this, "Write() suppressing error"); } statusCode = Interop.HttpApi.ERROR_SUCCESS; } } } } } finally { // free unmanaged buffer bufferAsIntPtr?.Close(); } if (statusCode != Interop.HttpApi.ERROR_SUCCESS && statusCode != Interop.HttpApi.ERROR_HANDLE_EOF) { Exception exception = new HttpListenerException((int)statusCode); if (NetEventSource.Log.IsEnabled()) { NetEventSource.Error(this, exception.ToString()); } _closed = true; _httpContext.Abort(); throw exception; } UpdateAfterWrite(dataToWrite); if (NetEventSource.Log.IsEnabled()) { NetEventSource.DumpBuffer(this, buffer, offset, (int)dataToWrite); } }
/// Gets the active UDP listeners. Uses the native GetUdpTable API. public override IPEndPoint[] GetActiveUdpListeners() { uint size = 0; uint result = 0; SafeLocalAllocHandle buffer = null; List <IPEndPoint> udpListeners = new List <IPEndPoint>(); // Check if it support IPv4 for IPv6 only modes. if (Socket.OSSupportsIPv4) { // Get the buffer size needed. result = Interop.IpHlpApi.GetUdpTable(SafeLocalAllocHandle.Zero, ref size, true); while (result == Interop.IpHlpApi.ERROR_INSUFFICIENT_BUFFER) { // Allocate the buffer and get the UDP table. using (buffer = SafeLocalAllocHandle.LocalAlloc((int)size)) { result = Interop.IpHlpApi.GetUdpTable(buffer, ref size, true); if (result == Interop.IpHlpApi.ERROR_SUCCESS) { // The table info just gives us the number of rows. IntPtr newPtr = buffer.DangerousGetHandle(); Interop.IpHlpApi.MibUdpTable udpTableInfo = Marshal.PtrToStructure <Interop.IpHlpApi.MibUdpTable>(newPtr); if (udpTableInfo.numberOfEntries > 0) { // Skip over the tableinfo to get the inline rows. newPtr = (IntPtr)((long)newPtr + Marshal.SizeOf(udpTableInfo.numberOfEntries)); for (int i = 0; i < udpTableInfo.numberOfEntries; i++) { Interop.IpHlpApi.MibUdpRow udpRow = Marshal.PtrToStructure <Interop.IpHlpApi.MibUdpRow>(newPtr); int localPort = udpRow.localPort1 << 8 | udpRow.localPort2; udpListeners.Add(new IPEndPoint(udpRow.localAddr, (int)localPort)); // We increment the pointer to the next row. newPtr = (IntPtr)((long)newPtr + Marshal.SizeOf(udpRow)); } } } } } // If we don't have any ipv4 interfaces detected, just continue. if (result != Interop.IpHlpApi.ERROR_SUCCESS && result != Interop.IpHlpApi.ERROR_NO_DATA) { throw new NetworkInformationException((int)result); } } if (Socket.OSSupportsIPv6) { // Get the buffer size needed. size = 0; result = Interop.IpHlpApi.GetExtendedUdpTable(SafeLocalAllocHandle.Zero, ref size, true, (uint)AddressFamily.InterNetworkV6, Interop.IpHlpApi.UdpTableClass.UdpTableOwnerPid, 0); while (result == Interop.IpHlpApi.ERROR_INSUFFICIENT_BUFFER) { // Allocate the buffer and get the UDP table. using (buffer = SafeLocalAllocHandle.LocalAlloc((int)size)) { result = Interop.IpHlpApi.GetExtendedUdpTable(buffer, ref size, true, (uint)AddressFamily.InterNetworkV6, Interop.IpHlpApi.UdpTableClass.UdpTableOwnerPid, 0); if (result == Interop.IpHlpApi.ERROR_SUCCESS) { // The table info just gives us the number of rows. IntPtr newPtr = buffer.DangerousGetHandle(); Interop.IpHlpApi.MibUdp6TableOwnerPid udp6TableOwnerPid = Marshal.PtrToStructure <Interop.IpHlpApi.MibUdp6TableOwnerPid>(newPtr); if (udp6TableOwnerPid.numberOfEntries > 0) { // Skip over the tableinfo to get the inline rows. newPtr = (IntPtr)((long)newPtr + Marshal.SizeOf(udp6TableOwnerPid.numberOfEntries)); for (int i = 0; i < udp6TableOwnerPid.numberOfEntries; i++) { Interop.IpHlpApi.MibUdp6RowOwnerPid udp6RowOwnerPid = Marshal.PtrToStructure <Interop.IpHlpApi.MibUdp6RowOwnerPid>(newPtr); int localPort = udp6RowOwnerPid.localPort1 << 8 | udp6RowOwnerPid.localPort2; udpListeners.Add(new IPEndPoint(new IPAddress(udp6RowOwnerPid.localAddr, udp6RowOwnerPid.localScopeId), localPort)); // We increment the pointer to the next row. newPtr = (IntPtr)((long)newPtr + Marshal.SizeOf(udp6RowOwnerPid)); } } } } } // If we don't have any ipv6 interfaces detected, just continue. if (result != Interop.IpHlpApi.ERROR_SUCCESS && result != Interop.IpHlpApi.ERROR_NO_DATA) { throw new NetworkInformationException((int)result); } } return(udpListeners.ToArray()); }
/// /// Gets the active TCP connections. Uses the native GetTcpTable API. private List <SystemTcpConnectionInformation> GetAllTcpConnections() { uint size = 0; uint result = 0; SafeLocalAllocHandle buffer = null; List <SystemTcpConnectionInformation> tcpConnections = new List <SystemTcpConnectionInformation>(); // Check if it supports IPv4 for IPv6 only modes. if (Socket.OSSupportsIPv4) { // Get the buffer size needed. result = Interop.IpHlpApi.GetTcpTable(SafeLocalAllocHandle.Zero, ref size, true); while (result == Interop.IpHlpApi.ERROR_INSUFFICIENT_BUFFER) { // Allocate the buffer and get the TCP table. using (buffer = SafeLocalAllocHandle.LocalAlloc((int)size)) { result = Interop.IpHlpApi.GetTcpTable(buffer, ref size, true); if (result == Interop.IpHlpApi.ERROR_SUCCESS) { // The table info just gives us the number of rows. IntPtr newPtr = buffer.DangerousGetHandle(); Interop.IpHlpApi.MibTcpTable tcpTableInfo = Marshal.PtrToStructure <Interop.IpHlpApi.MibTcpTable>(newPtr); if (tcpTableInfo.numberOfEntries > 0) { // Skip over the tableinfo to get the inline rows. newPtr = (IntPtr)((long)newPtr + Marshal.SizeOf(tcpTableInfo.numberOfEntries)); for (int i = 0; i < tcpTableInfo.numberOfEntries; i++) { Interop.IpHlpApi.MibTcpRow tcpRow = Marshal.PtrToStructure <Interop.IpHlpApi.MibTcpRow>(newPtr); tcpConnections.Add(new SystemTcpConnectionInformation(tcpRow)); // Increment the pointer to the next row. newPtr = (IntPtr)((long)newPtr + Marshal.SizeOf(tcpRow)); } } } } } // If we don't have any ipv4 interfaces detected, just continue. if (result != Interop.IpHlpApi.ERROR_SUCCESS && result != Interop.IpHlpApi.ERROR_NO_DATA) { throw new NetworkInformationException((int)result); } } if (Socket.OSSupportsIPv6) { // Get the buffer size needed. size = 0; result = Interop.IpHlpApi.GetExtendedTcpTable(SafeLocalAllocHandle.Zero, ref size, true, (uint)AddressFamily.InterNetworkV6, Interop.IpHlpApi.TcpTableClass.TcpTableOwnerPidAll, 0); while (result == Interop.IpHlpApi.ERROR_INSUFFICIENT_BUFFER) { // Allocate the buffer and get the TCP table. using (buffer = SafeLocalAllocHandle.LocalAlloc((int)size)) { result = Interop.IpHlpApi.GetExtendedTcpTable(buffer, ref size, true, (uint)AddressFamily.InterNetworkV6, Interop.IpHlpApi.TcpTableClass.TcpTableOwnerPidAll, 0); if (result == Interop.IpHlpApi.ERROR_SUCCESS) { // The table info just gives us the number of rows. IntPtr newPtr = buffer.DangerousGetHandle(); Interop.IpHlpApi.MibTcp6TableOwnerPid tcpTable6OwnerPid = Marshal.PtrToStructure <Interop.IpHlpApi.MibTcp6TableOwnerPid>(newPtr); if (tcpTable6OwnerPid.numberOfEntries > 0) { // Skip over the tableinfo to get the inline rows. newPtr = (IntPtr)((long)newPtr + Marshal.SizeOf(tcpTable6OwnerPid.numberOfEntries)); for (int i = 0; i < tcpTable6OwnerPid.numberOfEntries; i++) { Interop.IpHlpApi.MibTcp6RowOwnerPid tcp6RowOwnerPid = Marshal.PtrToStructure <Interop.IpHlpApi.MibTcp6RowOwnerPid>(newPtr); tcpConnections.Add(new SystemTcpConnectionInformation(tcp6RowOwnerPid)); // We increment the pointer to the next row. newPtr = (IntPtr)((long)newPtr + Marshal.SizeOf(tcp6RowOwnerPid)); } } } } } // If we don't have any ipv6 interfaces detected, just continue. if (result != Interop.IpHlpApi.ERROR_SUCCESS && result != Interop.IpHlpApi.ERROR_NO_DATA) { throw new NetworkInformationException((int)result); } } return(tcpConnections); }
private PingReply InternalSend(IPAddress address, byte[] buffer, int timeout, PingOptions options, bool async) { _ipv6 = (address.AddressFamily == AddressFamily.InterNetworkV6) ? true : false; _sendSize = buffer.Length; // Get and cache correct handle. if (!_ipv6 && _handlePingV4 == null) { _handlePingV4 = Interop.IpHlpApi.IcmpCreateFile(); if (_handlePingV4.IsInvalid) { _handlePingV4 = null; throw new Win32Exception(); // Gets last error. } } else if (_ipv6 && _handlePingV6 == null) { _handlePingV6 = Interop.IpHlpApi.Icmp6CreateFile(); if (_handlePingV6.IsInvalid) { _handlePingV6 = null; throw new Win32Exception(); // Gets last error. } } var ipOptions = new Interop.IpHlpApi.IPOptions(options); if (_replyBuffer == null) { _replyBuffer = SafeLocalAllocHandle.LocalAlloc(MaxUdpPacket); } // Queue the event. int error; try { if (async) { if (pingEvent == null) { pingEvent = new ManualResetEvent(false); } else { pingEvent.Reset(); } _registeredWait = ThreadPool.RegisterWaitForSingleObject(pingEvent, new WaitOrTimerCallback(PingCallback), this, -1, true); } SetUnmanagedStructures(buffer); if (!_ipv6) { if (async) { SafeWaitHandle pingEventSafeWaitHandle = pingEvent.GetSafeWaitHandle(); error = (int)Interop.IpHlpApi.IcmpSendEcho2( _handlePingV4, pingEventSafeWaitHandle, IntPtr.Zero, IntPtr.Zero, (uint)address.GetAddress(), _requestBuffer, (ushort)buffer.Length, ref ipOptions, _replyBuffer, MaxUdpPacket, (uint)timeout); } else { error = (int)Interop.IpHlpApi.IcmpSendEcho2( _handlePingV4, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, (uint)address.GetAddress(), _requestBuffer, (ushort)buffer.Length, ref ipOptions, _replyBuffer, MaxUdpPacket, (uint)timeout); } } else { IPEndPoint ep = new IPEndPoint(address, 0); Internals.SocketAddress remoteAddr = IPEndPointExtensions.Serialize(ep); byte[] sourceAddr = new byte[28]; if (async) { SafeWaitHandle pingEventSafeWaitHandle = pingEvent.GetSafeWaitHandle(); error = (int)Interop.IpHlpApi.Icmp6SendEcho2( _handlePingV6, pingEventSafeWaitHandle, IntPtr.Zero, IntPtr.Zero, sourceAddr, remoteAddr.Buffer, _requestBuffer, (ushort)buffer.Length, ref ipOptions, _replyBuffer, MaxUdpPacket, (uint)timeout); } else { error = (int)Interop.IpHlpApi.Icmp6SendEcho2( _handlePingV6, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, sourceAddr, remoteAddr.Buffer, _requestBuffer, (ushort)buffer.Length, ref ipOptions, _replyBuffer, MaxUdpPacket, (uint)timeout); } } } catch { UnregisterWaitHandle(); throw; } if (error == 0) { error = Marshal.GetLastWin32Error(); // Only skip Async IO Pending error value. if (async && error == Interop.IpHlpApi.ERROR_IO_PENDING) { // Expected async return value. return(null); } // Cleanup. FreeUnmanagedStructures(); UnregisterWaitHandle(); if (async || // No IPStatus async errors. error < (int)IPStatus.DestinationNetworkUnreachable || // Min error > (int)IPStatus.DestinationScopeMismatch) // Max or Out of IPStatus range. { throw new Win32Exception(error); } return(new PingReply((IPStatus)error)); // Synchronous IPStatus errors. } if (async) { return(null); } FreeUnmanagedStructures(); PingReply reply; if (_ipv6) { Interop.IpHlpApi.Icmp6EchoReply icmp6Reply = Marshal.PtrToStructure <Interop.IpHlpApi.Icmp6EchoReply>(_replyBuffer.DangerousGetHandle()); reply = new PingReply(icmp6Reply, _replyBuffer.DangerousGetHandle(), _sendSize); } else { Interop.IpHlpApi.IcmpEchoReply icmpReply = Marshal.PtrToStructure <Interop.IpHlpApi.IcmpEchoReply>(_replyBuffer.DangerousGetHandle()); reply = new PingReply(icmpReply); } // IcmpEchoReply still has an unsafe IntPtr reference into replybuffer // and replybuffer was being freed prematurely by the GC, causing AccessViolationExceptions. GC.KeepAlive(_replyBuffer); return(reply); }