public void FileStream()
        {
            string filePath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());

            try
            {
                var array = new byte[StreamMemoryBlockProvider.MemoryMapThreshold + 1];
                for (int i = 0; i < array.Length; i++)
                {
                    array[i] = 0x12;
                }

                File.WriteAllBytes(filePath, array);

                foreach (bool useAsync in new[] { true, false })
                {
                    using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, useAsync))
                    {
                        Assert.True(FileStreamReadLightUp.IsFileStream(stream));

                        using (var provider = new StreamMemoryBlockProvider(stream, imageStart: 0, imageSize: array.Length, isFileStream: true, leaveOpen: false))
                        {
                            // large:
                            using (var block = provider.GetMemoryBlock())
                            {
                                Assert.IsType <MemoryMappedFileBlock>(block);
                                Assert.Equal(array.Length, block.Size);
                                AssertEx.Equal(array, block.GetContent());
                            }

                            // we didn't use the stream for reading
                            Assert.Equal(0, stream.Position);

                            // small:
                            using (var block = provider.GetMemoryBlock(1, 2))
                            {
                                Assert.IsType <NativeHeapMemoryBlock>(block);
                                Assert.Equal(2, block.Size);
                                AssertEx.Equal(new byte[] { 0x12, 0x12 }, block.GetContent());
                            }

                            Assert.Equal(3, stream.Position);
                        }

                        Assert.Throws <ObjectDisposedException>(() => stream.Position);
                    }
                }
            }
            finally
            {
                File.Delete(filePath);
            }
        }
示例#2
0
        /// <summary>
        /// Creates a provider for a stream of the specified size beginning at its current position.
        /// </summary>
        /// <param name="stream">Stream.</param>
        /// <param name="size">Size of the metadata blob in the stream. If not specified the metadata blob is assumed to span to the end of the stream.</param>
        /// <param name="options">
        /// Options specifying how sections of the image are read from the stream.
        ///
        /// Unless <see cref="MetadataStreamOptions.LeaveOpen"/> is specified, ownership of the stream is transferred to the <see cref="MetadataReaderProvider"/>
        /// upon successful argument validation. It will be disposed by the <see cref="MetadataReaderProvider"/> and the caller must not manipulate it.
        ///
        /// Unless <see cref="MetadataStreamOptions.PrefetchMetadata"/> is specified no data
        /// is read from the stream during the construction of the <see cref="MetadataReaderProvider"/>. Furthermore, the stream must not be manipulated
        /// by caller while the <see cref="MetadataReaderProvider"/> is alive and undisposed.
        ///
        /// If <see cref="MetadataStreamOptions.PrefetchMetadata"/>, the <see cref="MetadataReaderProvider"/>
        /// will have read all of the data requested during construction. As such, if <see cref="MetadataStreamOptions.LeaveOpen"/> is also
        /// specified, the caller retains full ownership of the stream and is assured that it will not be manipulated by the <see cref="MetadataReaderProvider"/>
        /// after construction.
        /// </param>
        /// <exception cref="ArgumentNullException"><paramref name="stream"/> is null.</exception>
        /// <exception cref="ArgumentException"><paramref name="stream"/> doesn't support read and seek operations.</exception>
        /// <exception cref="ArgumentOutOfRangeException">Size is negative or extends past the end of the stream.</exception>
        /// <exception cref="IOException">Error reading from the stream (only when <see cref="MetadataStreamOptions.PrefetchMetadata"/> is specified).</exception>
        public static MetadataReaderProvider FromMetadataStream(Stream stream, MetadataStreamOptions options = MetadataStreamOptions.Default, int size = 0)
        {
            if (stream == null)
            {
                throw new ArgumentNullException(nameof(stream));
            }

            if (!stream.CanRead || !stream.CanSeek)
            {
                throw new ArgumentException(SR.StreamMustSupportReadAndSeek, nameof(stream));
            }

            if (!options.IsValid())
            {
                throw new ArgumentOutOfRangeException(nameof(options));
            }

            long start      = stream.Position;
            int  actualSize = StreamExtensions.GetAndValidateSize(stream, size, nameof(stream));

            MetadataReaderProvider result;
            bool closeStream = true;

            try
            {
                bool isFileStream = FileStreamReadLightUp.IsFileStream(stream);

                if ((options & MetadataStreamOptions.PrefetchMetadata) == 0)
                {
                    result      = new MetadataReaderProvider(new StreamMemoryBlockProvider(stream, start, actualSize, isFileStream, (options & MetadataStreamOptions.LeaveOpen) != 0));
                    closeStream = false;
                }
                else
                {
                    // Read in the entire image or metadata blob:
                    result = new MetadataReaderProvider(StreamMemoryBlockProvider.ReadMemoryBlockNoLock(stream, isFileStream, start, actualSize));

                    // We read all we need, the stream is going to be closed.
                }
            }
            finally
            {
                if (closeStream && (options & MetadataStreamOptions.LeaveOpen) == 0)
                {
                    stream.Dispose();
                }
            }

            return(result);
        }
示例#3
0
        public void Stream()
        {
            var array = new byte[] { 1, 2, 3, 4 };

            using (var stream = new MemoryStream(array))
            {
                Assert.False(FileStreamReadLightUp.IsFileStream(stream));

                using (var provider = new StreamMemoryBlockProvider(stream, 0, array.Length, isFileStream: false, leaveOpen: true))
                {
                    using (var block = provider.GetMemoryBlock())
                    {
                        Assert.IsType <NativeHeapMemoryBlock>(block);
                        Assert.Equal(4, block.Size);
                        AssertEx.Equal(new byte[] { }, block.GetContentUnchecked(0, 0));
                        AssertEx.Equal(new byte[] { 3, 4 }, block.GetContentUnchecked(2, 2));
                        AssertEx.Equal(new byte[] { 1, 2, 3 }, block.GetContentUnchecked(0, 3));
                    }

                    Assert.Equal(4, stream.Position);

                    using (var block = provider.GetMemoryBlock(1, 2))
                    {
                        Assert.IsType <NativeHeapMemoryBlock>(block);
                        Assert.Equal(2, block.Size);
                        AssertEx.Equal(new byte[] { 2, 3 }, block.GetContentUnchecked(0, 2));
                        AssertEx.Equal(new byte[] { 3 }, block.GetContentUnchecked(1, 1));
                        AssertEx.Equal(new byte[] { }, block.GetContentUnchecked(2, 0));
                    }

                    Assert.Equal(3, stream.Position);
                }

                using (var provider = new StreamMemoryBlockProvider(stream, 0, array.Length, isFileStream: false, leaveOpen: false))
                {
                    using (var block = provider.GetMemoryBlock())
                    {
                        Assert.IsType <NativeHeapMemoryBlock>(block);
                        Assert.Equal(4, block.Size);
                        AssertEx.Equal(new byte[] { }, block.GetContentUnchecked(0, 0));
                        AssertEx.Equal(new byte[] { 3, 4 }, block.GetContentUnchecked(2, 2));
                        AssertEx.Equal(new byte[] { 1, 2, 3 }, block.GetContentUnchecked(0, 3));
                    }

                    Assert.Equal(4, stream.Position);
                }

                Assert.Throws <ObjectDisposedException>(() => stream.Position);
            }
        }
        public void Stream()
        {
            var array = new byte[] { 1, 2, 3, 4 };
            using (var stream = new MemoryStream(array))
            {
                Assert.False(FileStreamReadLightUp.IsFileStream(stream));

                using (var provider = new StreamMemoryBlockProvider(stream, 0, array.Length, isFileStream: false, leaveOpen: true))
                {
                    using (var block = provider.GetMemoryBlock())
                    {
                        Assert.IsType<NativeHeapMemoryBlock>(block);
                        Assert.Equal(4, block.Size);
                        AssertEx.Equal(new byte[] { }, block.GetContentUnchecked(0, 0));
                        AssertEx.Equal(new byte[] { 3, 4 }, block.GetContentUnchecked(2, 2));
                        AssertEx.Equal(new byte[] { 1, 2, 3 }, block.GetContentUnchecked(0, 3));
                    }

                    Assert.Equal(4, stream.Position);

                    using (var block = provider.GetMemoryBlock(1, 2))
                    {
                        Assert.IsType<NativeHeapMemoryBlock>(block);
                        Assert.Equal(2, block.Size);
                        AssertEx.Equal(new byte[] { 2, 3 }, block.GetContentUnchecked(0, 2));
                        AssertEx.Equal(new byte[] { 3 }, block.GetContentUnchecked(1, 1));
                        AssertEx.Equal(new byte[] { }, block.GetContentUnchecked(2, 0));
                    }

                    Assert.Equal(3, stream.Position);
                }

                using (var provider = new StreamMemoryBlockProvider(stream, 0, array.Length, isFileStream: false, leaveOpen: false))
                {
                    using (var block = provider.GetMemoryBlock())
                    {
                        Assert.IsType<NativeHeapMemoryBlock>(block);
                        Assert.Equal(4, block.Size);
                        AssertEx.Equal(new byte[] { }, block.GetContentUnchecked(0, 0));
                        AssertEx.Equal(new byte[] { 3, 4 }, block.GetContentUnchecked(2, 2));
                        AssertEx.Equal(new byte[] { 1, 2, 3 }, block.GetContentUnchecked(0, 3));
                    }

                    Assert.Equal(4, stream.Position);
                }

                Assert.Throws<ObjectDisposedException>(() => stream.Position);
            }
        }
示例#5
0
        /// <summary>
        /// Creates a Portable Executable reader over a PE image of the given size beginning at the stream's current position.
        /// </summary>
        /// <param name="peStream">PE image stream.</param>
        /// <param name="size">PE image size.</param>
        /// <param name="options">
        /// Options specifying how sections of the PE image are read from the stream.
        ///
        /// Unless <see cref="PEStreamOptions.LeaveOpen"/> is specified, ownership of the stream is transferred to the <see cref="PEReader"/>
        /// upon successful argument validation. It will be disposed by the <see cref="PEReader"/> and the caller must not manipulate it.
        ///
        /// Unless <see cref="PEStreamOptions.PrefetchMetadata"/> or <see cref="PEStreamOptions.PrefetchEntireImage"/> is specified no data
        /// is read from the stream during the construction of the <see cref="PEReader"/>. Furthermore, the stream must not be manipulated
        /// by caller while the <see cref="PEReader"/> is alive and undisposed.
        ///
        /// If <see cref="PEStreamOptions.PrefetchMetadata"/> or <see cref="PEStreamOptions.PrefetchEntireImage"/>, the <see cref="PEReader"/>
        /// will have read all of the data requested during construction. As such, if <see cref="PEStreamOptions.LeaveOpen"/> is also
        /// specified, the caller retains full ownership of the stream and is assured that it will not be manipulated by the <see cref="PEReader"/>
        /// after construction.
        /// </param>
        /// <exception cref="ArgumentOutOfRangeException">Size is negative or extends past the end of the stream.</exception>
        /// <exception cref="IOException">Error reading from the stream (only when prefetching data).</exception>
        /// <exception cref="BadImageFormatException"><see cref="PEStreamOptions.PrefetchMetadata"/> is specified and the PE headers of the image are invalid.</exception>
        public unsafe PEReader(Stream peStream, PEStreamOptions options, int size)
        {
            if (peStream == null)
            {
                throw new ArgumentNullException(nameof(peStream));
            }

            if (!peStream.CanRead || !peStream.CanSeek)
            {
                throw new ArgumentException(SR.StreamMustSupportReadAndSeek, nameof(peStream));
            }

            if (!options.IsValid())
            {
                throw new ArgumentOutOfRangeException(nameof(options));
            }

            IsLoadedImage = (options & PEStreamOptions.IsLoadedImage) != 0;

            long start      = peStream.Position;
            int  actualSize = StreamExtensions.GetAndValidateSize(peStream, size, nameof(peStream));

            bool closeStream = true;

            try
            {
                bool isFileStream = FileStreamReadLightUp.IsFileStream(peStream);

                if ((options & (PEStreamOptions.PrefetchMetadata | PEStreamOptions.PrefetchEntireImage)) == 0)
                {
                    _peImage    = new StreamMemoryBlockProvider(peStream, start, actualSize, isFileStream, (options & PEStreamOptions.LeaveOpen) != 0);
                    closeStream = false;
                }
                else
                {
                    // Read in the entire image or metadata blob:
                    if ((options & PEStreamOptions.PrefetchEntireImage) != 0)
                    {
                        var imageBlock = StreamMemoryBlockProvider.ReadMemoryBlockNoLock(peStream, isFileStream, start, actualSize);
                        _lazyImageBlock = imageBlock;
                        _peImage        = new ExternalMemoryBlockProvider(imageBlock.Pointer, imageBlock.Size);

                        // if the caller asked for metadata initialize the PE headers (calculates metadata offset):
                        if ((options & PEStreamOptions.PrefetchMetadata) != 0)
                        {
                            InitializePEHeaders();
                        }
                    }
                    else
                    {
                        // The peImage is left null, but the lazyMetadataBlock is initialized up front.
                        _lazyPEHeaders     = new PEHeaders(peStream);
                        _lazyMetadataBlock = StreamMemoryBlockProvider.ReadMemoryBlockNoLock(peStream, isFileStream, _lazyPEHeaders.MetadataStartOffset, _lazyPEHeaders.MetadataSize);
                    }
                    // We read all we need, the stream is going to be closed.
                }
            }
            finally
            {
                if (closeStream && (options & PEStreamOptions.LeaveOpen) == 0)
                {
                    peStream.Dispose();
                }
            }
        }
        public void FileStream()
        {
            string filePath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
            try
            {
                var array = new byte[StreamMemoryBlockProvider.MemoryMapThreshold + 1];
                for (int i = 0; i < array.Length; i++)
                {
                    array[i] = 0x12;
                }

                File.WriteAllBytes(filePath, array);

                foreach (bool useAsync in new[] { true, false })
                {
                    using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, useAsync))
                    {
                        Assert.True(FileStreamReadLightUp.IsFileStream(stream));

                        using (var provider = new StreamMemoryBlockProvider(stream, imageStart: 0, imageSize: array.Length, isFileStream: true, leaveOpen: false))
                        {
                            // large:
                            using (var block = provider.GetMemoryBlock())
                            {
                                Assert.IsType<MemoryMappedFileBlock>(block);
                                Assert.Equal(array.Length, block.Size);
                                Assert.Equal(array, block.GetContent());
                            }

                            // we didn't use the stream for reading
                            Assert.Equal(0, stream.Position);

                            // small:
                            using (var block = provider.GetMemoryBlock(1, 2))
                            {
                                Assert.IsType<NativeHeapMemoryBlock>(block);
                                Assert.Equal(2, block.Size);
                                Assert.Equal(new byte[] { 0x12, 0x12 }, block.GetContent());
                            }

                            Assert.Equal(3, stream.Position);
                        }

                        Assert.Throws<ObjectDisposedException>(() => stream.Position);
                    }
                }
            }
            finally
            {
                File.Delete(filePath);
            }
        }
示例#7
0
        private unsafe PEReader(Stream peStream, PEStreamOptions options, int?sizeOpt)
        {
            if (peStream == null)
            {
                throw new ArgumentNullException("peStream");
            }

            if (!peStream.CanRead || !peStream.CanSeek)
            {
                throw new ArgumentException(MetadataResources.StreamMustSupportReadAndSeek, "peStream");
            }

            if (!options.IsValid())
            {
                throw new ArgumentOutOfRangeException("options");
            }

            long start = peStream.Position;
            int  size  = PEBinaryReader.GetAndValidateSize(peStream, sizeOpt);

            bool closeStream = true;

            try
            {
                bool isFileStream = FileStreamReadLightUp.IsFileStream(peStream);

                if ((options & (PEStreamOptions.PrefetchMetadata | PEStreamOptions.PrefetchEntireImage)) == 0)
                {
                    this.peImage = new StreamMemoryBlockProvider(peStream, start, size, isFileStream, (options & PEStreamOptions.LeaveOpen) != 0);
                    closeStream  = false;
                }
                else
                {
                    // Read in the entire image or metadata blob:
                    if ((options & PEStreamOptions.PrefetchEntireImage) != 0)
                    {
                        var imageBlock = StreamMemoryBlockProvider.ReadMemoryBlockNoLock(peStream, isFileStream, 0, (int)Math.Min(peStream.Length, int.MaxValue));
                        this.lazyImageBlock = imageBlock;
                        this.peImage        = new ExternalMemoryBlockProvider(imageBlock.Pointer, imageBlock.Size);

                        // if the caller asked for metadata initialize the PE headers (calculates metadata offset):
                        if ((options & PEStreamOptions.PrefetchMetadata) != 0)
                        {
                            InitializePEHeaders();
                        }
                    }
                    else
                    {
                        // The peImage is left null, but the lazyMetadataBlock is initialized up front.
                        this.lazyPEHeaders     = new PEHeaders(peStream);
                        this.lazyMetadataBlock = StreamMemoryBlockProvider.ReadMemoryBlockNoLock(peStream, isFileStream, lazyPEHeaders.MetadataStartOffset, lazyPEHeaders.MetadataSize);
                    }
                    // We read all we need, the stream is going to be closed.
                }
            }
            finally
            {
                if (closeStream && (options & PEStreamOptions.LeaveOpen) == 0)
                {
                    peStream.Dispose();
                }
            }
        }