public void Dispose() { if (this.isDisposed) { return; } if (this.tableStream != null) { foreach (var table in this.tableStream.Values) { table.Dispose(); } this.tableStream._Clear(); } if (this.sourceImage != null) { this.sourceImage.Dispose(); } if (this.blob != null) { this.blob.Dispose(); this.blob = null; } if (this.strings != null) { this.strings.Dispose(); this.strings = null; } if (this.propertySemantics != null) { this.propertySemantics = null; } if (this.eventSemantics != null) { this.eventSemantics = null; } this.isDisposed = true; }
/// <summary> /// Reads the root structure from the metadata. /// </summary> /// <param name="header">The <see cref="CliHeader"/> which denotes the location of the information.</param> /// <param name="originalStream">The <see cref="FileStream"/> being read from.</param> /// <param name="reader">The <see cref="EndianAwareBinaryReader"/> which handles reads.</param> /// <param name="relativeVirtualAddress">The <see cref="UInt32"/> value which denotes the relative /// virtual address of the metadata header.</param> /// <param name="sourceImage"></param> internal void Read(CliHeader header, FileStream originalStream, EndianAwareBinaryReader reader, uint relativeVirtualAddress, PEImage sourceImage) { this.originalStream = originalStream; this.header = header; this.streamPosition = relativeVirtualAddress; this.signature = reader.ReadUInt32(); if (this.signature != metadataSignature) { throw new BadImageFormatException(); } this.depreciatedVersion.Read(reader); this.reserved = reader.ReadUInt32(); this.realVersionLength = reader.ReadInt32(); byte[] version = new byte[(this.realVersionLength + 3) & ~3];//Make it a multiple of four. reader.Read(version, 0, version.Length); this.version = version; this.reservedFlags = reader.ReadUInt16(); int streamCount = 0; streamCount = reader.ReadUInt16(); this.sourceImage = sourceImage; for (int i = 0; i < streamCount; i++) { var currentHeader = new CliMetadataStreamHeader(); currentHeader.Read(reader, sourceImage); switch (currentHeader.Name) { case "#Strings": if (this.strings != null) { goto sectionExists; } this.strings = new CliMetadataStringsHeaderAndHeap(currentHeader, sourceImage.SyncObject); this.ScanAndReadSection(sourceImage, strings, this.strings.Read); break; case "#Blob": if (this.blob != null) { goto sectionExists; } this.blob = new CliMetadataBlobHeaderAndHeap(currentHeader, this); this.ScanAndReadSection(sourceImage, blob, this.blob.Read); break; case "#US": if (this.userStrings != null) { goto sectionExists; } this.userStrings = new CliMetadataUserStringsHeaderAndHeap(currentHeader, sourceImage.SyncObject); this.ScanAndReadSection(sourceImage, this.userStrings, this.userStrings.Read); break; case "#GUID": if (this.guids != null) { goto sectionExists; } this.guids = new CliMetadataGuidHeaderAndHeap(currentHeader, sourceImage.SyncObject); this.ScanAndReadSection(sourceImage, guids, this.guids.Read); break; case "#-": //https://github.com/jbevain/cecil/blob/8b689ecdc890cbf3715ba8775de1d713d71f09f3/Mono.Cecil.PE/ImageReader.cs#L359 case "#~": if (this.tableStream != null) { goto sectionExists; } this.tableStream = new CliMetadataTableStreamAndHeader(currentHeader); this.ScanAndReadSection(sourceImage, tableStream, sdReader => this.tableStream.Read(sdReader, this)); break; } continue; sectionExists: throw new BadImageFormatException(string.Format("Duplicate {0} section encountered.", currentHeader.Name)); } if (this.tableStream == null) { throw new BadImageFormatException("#~ or #- stream not present in image."); } }