private void InternalDispose() { this.disposeRequested = true; if (Interlocked.CompareExchange(ref this.status, 2, 0) == 0) { if (this.handlePingV4 != null) { this.handlePingV4.Close(); this.handlePingV4 = null; } if (this.handlePingV6 != null) { this.handlePingV6.Close(); this.handlePingV6 = null; } this.UnregisterWaitHandle(); if (this.pingEvent != null) { this.pingEvent.Close(); this.pingEvent = null; } if (this.replyBuffer != null) { this.replyBuffer.Close(); this.replyBuffer = null; } if (this.asyncFinished != null) { this.asyncFinished.Close(); this.asyncFinished = null; } } }
// Cancels pending async requests, closes the handles. private void InternalDispose() { _disposeRequested = true; if (Interlocked.CompareExchange(ref _status, Disposed, Free) != Free) { // Already disposed, or Finish will call Dispose again once Free. return; } if (_handlePingV4 != null) { _handlePingV4.Dispose(); _handlePingV4 = null; } if (_handlePingV6 != null) { _handlePingV6.Dispose(); _handlePingV6 = null; } UnregisterWaitHandle(); if (pingEvent != null) { pingEvent.Dispose(); pingEvent = null; } if (_replyBuffer != null) { _replyBuffer.Dispose(); _replyBuffer = null; } if (_asyncFinished != null) { _asyncFinished.Dispose(); _asyncFinished = null; } }
//cancel pending async requests, close the handles private void InternalDispose() { disposeRequested = true; if (Interlocked.CompareExchange(ref status, Disposed, Free) != Free) { // Already disposed, or Finish will call Dispose again once Free return; } if (handlePingV4 != null) { handlePingV4.Close(); handlePingV4 = null; } if (handlePingV6 != null) { handlePingV6.Close(); handlePingV6 = null; } UnregisterWaitHandle(); if (pingEvent != null) { pingEvent.Close(); pingEvent = null; } if (replyBuffer != null) { replyBuffer.Close(); replyBuffer = null; } if (asyncFinished != null) { asyncFinished.Close(); asyncFinished = null; } }
private PingReply InternalSend(IPAddress address, byte[] buffer, int timeout, PingOptions options, bool async) { int num; PingReply reply; this.ipv6 = address.AddressFamily == AddressFamily.InterNetworkV6; this.sendSize = buffer.Length; if (!this.ipv6 && (this.handlePingV4 == null)) { this.handlePingV4 = UnsafeNetInfoNativeMethods.IcmpCreateFile(); if (this.handlePingV4.IsInvalid) { this.handlePingV4 = null; throw new Win32Exception(); } } else if (this.ipv6 && (this.handlePingV6 == null)) { this.handlePingV6 = UnsafeNetInfoNativeMethods.Icmp6CreateFile(); if (this.handlePingV6.IsInvalid) { this.handlePingV6 = null; throw new Win32Exception(); } } IPOptions options2 = new IPOptions(options); if (this.replyBuffer == null) { this.replyBuffer = SafeLocalFree.LocalAlloc(0x100ff); } try { if (async) { if (this.pingEvent == null) { this.pingEvent = new ManualResetEvent(false); } else { this.pingEvent.Reset(); } this.registeredWait = ThreadPool.RegisterWaitForSingleObject(this.pingEvent, new WaitOrTimerCallback(Ping.PingCallback), this, -1, true); } this.SetUnmanagedStructures(buffer); if (!this.ipv6) { if (async) { num = (int)UnsafeNetInfoNativeMethods.IcmpSendEcho2(this.handlePingV4, this.pingEvent.SafeWaitHandle, IntPtr.Zero, IntPtr.Zero, (uint)address.m_Address, this.requestBuffer, (ushort)buffer.Length, ref options2, this.replyBuffer, 0x100ff, (uint)timeout); } else { num = (int)UnsafeNetInfoNativeMethods.IcmpSendEcho2(this.handlePingV4, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, (uint)address.m_Address, this.requestBuffer, (ushort)buffer.Length, ref options2, this.replyBuffer, 0x100ff, (uint)timeout); } } else { SocketAddress address2 = new IPEndPoint(address, 0).Serialize(); byte[] sourceSocketAddress = new byte[0x1c]; if (async) { num = (int)UnsafeNetInfoNativeMethods.Icmp6SendEcho2(this.handlePingV6, this.pingEvent.SafeWaitHandle, IntPtr.Zero, IntPtr.Zero, sourceSocketAddress, address2.m_Buffer, this.requestBuffer, (ushort)buffer.Length, ref options2, this.replyBuffer, 0x100ff, (uint)timeout); } else { num = (int)UnsafeNetInfoNativeMethods.Icmp6SendEcho2(this.handlePingV6, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, sourceSocketAddress, address2.m_Buffer, this.requestBuffer, (ushort)buffer.Length, ref options2, this.replyBuffer, 0x100ff, (uint)timeout); } } } catch { this.UnregisterWaitHandle(); throw; } if (num == 0) { num = Marshal.GetLastWin32Error(); if (async && (num == 0x3e5L)) { return(null); } this.FreeUnmanagedStructures(); this.UnregisterWaitHandle(); if ((async || (num < 0x2afa)) || (num > 0x2b25)) { throw new Win32Exception(num); } return(new PingReply((IPStatus)num)); } if (async) { return(null); } this.FreeUnmanagedStructures(); if (this.ipv6) { Icmp6EchoReply reply2 = (Icmp6EchoReply)Marshal.PtrToStructure(this.replyBuffer.DangerousGetHandle(), typeof(Icmp6EchoReply)); reply = new PingReply(reply2, this.replyBuffer.DangerousGetHandle(), this.sendSize); } else { IcmpEchoReply reply3 = (IcmpEchoReply)Marshal.PtrToStructure(this.replyBuffer.DangerousGetHandle(), typeof(IcmpEchoReply)); reply = new PingReply(reply3); } GC.KeepAlive(this.replyBuffer); return(reply); }
internal static extern uint IcmpSendEcho2(SafeCloseIcmpHandle icmpHandle, SafeWaitHandle Event, IntPtr apcRoutine, IntPtr apcContext, uint ipAddress, [In] SafeLocalFree data, ushort dataSize, ref IPOptions options, SafeLocalFree replyBuffer, uint replySize, uint timeout);
internal static extern uint Icmp6SendEcho2(SafeCloseIcmpHandle icmpHandle, IntPtr Event, IntPtr apcRoutine, IntPtr apcContext, byte[] sourceSocketAddress, byte[] destSocketAddress, [In] SafeLocalFree data, ushort dataSize, ref IPOptions options, SafeLocalFree replyBuffer, uint replySize, uint timeout);
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);
internal static partial uint IcmpSendEcho2(SafeCloseIcmpHandle icmpHandle, SafeWaitHandle Event, IntPtr apcRoutine, IntPtr apcContext, uint ipAddress, SafeLocalAllocHandle data, ushort dataSize, ref IP_OPTION_INFORMATION options, SafeLocalAllocHandle replyBuffer, uint replySize, uint timeout);
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); }
// internal method responsible for sending echo request on win2k and higher 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 = UnsafeNetInfoNativeMethods.IcmpCreateFile(); if (handlePingV4.IsInvalid) { handlePingV4 = null; throw new Win32Exception(); // Gets last error } } else if (ipv6 && handlePingV6 == null) { handlePingV6 = UnsafeNetInfoNativeMethods.Icmp6CreateFile(); if (handlePingV6.IsInvalid) { handlePingV6 = null; throw new Win32Exception(); // Gets last error } } //setup the options IPOptions ipOptions = new IPOptions(options); //setup the reply buffer if (replyBuffer == null) { replyBuffer = SafeLocalFree.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); } //Copy user dfata into the native world SetUnmanagedStructures(buffer); if (!ipv6) { if (async) { error = (int)UnsafeNetInfoNativeMethods.IcmpSendEcho2(handlePingV4, pingEvent.SafeWaitHandle, IntPtr.Zero, IntPtr.Zero, (uint)address.m_Address, requestBuffer, (ushort)buffer.Length, ref ipOptions, replyBuffer, MaxUdpPacket, (uint)timeout); } else { error = (int)UnsafeNetInfoNativeMethods.IcmpSendEcho2(handlePingV4, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, (uint)address.m_Address, requestBuffer, (ushort)buffer.Length, ref ipOptions, replyBuffer, MaxUdpPacket, (uint)timeout); } } else { IPEndPoint ep = new IPEndPoint(address, 0); SocketAddress remoteAddr = ep.Serialize(); byte[] sourceAddr = new byte[28]; if (async) { error = (int)UnsafeNetInfoNativeMethods.Icmp6SendEcho2(handlePingV6, pingEvent.SafeWaitHandle, IntPtr.Zero, IntPtr.Zero, sourceAddr, remoteAddr.m_Buffer, requestBuffer, (ushort)buffer.Length, ref ipOptions, replyBuffer, MaxUdpPacket, (uint)timeout); } else { error = (int)UnsafeNetInfoNativeMethods.Icmp6SendEcho2(handlePingV6, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, sourceAddr, remoteAddr.m_Buffer, requestBuffer, (ushort)buffer.Length, ref ipOptions, replyBuffer, MaxUdpPacket, (uint)timeout); } } } catch { UnregisterWaitHandle(); throw; } //need this if something is bogus. if (error == 0) { error = (int)Marshal.GetLastWin32Error(); // Only skip Async IO Pending error value if (async && error == UnsafeNclNativeMethods.ErrorCodes.ERROR_IO_PENDING) { return(null); // Expected async return value } // Cleanup FreeUnmanagedStructures(); UnregisterWaitHandle(); if (async || // No IPStatus async errors error < (int)IPStatus.DestinationNetworkUnreachable || // Min error > (int)IPStatus.DestinationScopeMismatch) // Max // Out of IPStatus range { throw new Win32Exception(error); } return(new PingReply((IPStatus)error)); // Synchronous IPStatus errors } if (async) { return(null); } FreeUnmanagedStructures(); //return the reply PingReply reply; if (ipv6) { Icmp6EchoReply icmp6Reply = (Icmp6EchoReply)Marshal.PtrToStructure(replyBuffer.DangerousGetHandle(), typeof(Icmp6EchoReply)); reply = new PingReply(icmp6Reply, replyBuffer.DangerousGetHandle(), sendSize); } else { IcmpEchoReply icmpReply = (IcmpEchoReply)Marshal.PtrToStructure(replyBuffer.DangerousGetHandle(), typeof(IcmpEchoReply)); 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); }
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; }