Exemple #1
0
        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);
                }
            }
        }
Exemple #2
0
        // 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()));
        }
Exemple #3
0
        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());
        }
Exemple #4
0
        // 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];
            }
        }
Exemple #5
0
        // 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());
        }
Exemple #7
0
        /// <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);
        }
Exemple #8
0
        // 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);
        }
Exemple #9
0
        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);
            }
        }
Exemple #10
0
        /// 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());
        }
Exemple #11
0
        ///
        /// 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);
        }
Exemple #12
0
        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);
        }