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); } }
/// <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); }
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); } }
/// <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); } }
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(); } } }