private static String ReadSysString(Stream stream, SysStringContainer sysStrings, Boolean[] streamWidths, Byte[] tmpArray) { return(sysStrings.GetString((Int32)stream.ReadHeapIndex(streamWidths[SYS_STR_WIDTH_INDEX], tmpArray))); }
internal MetaDataReader(Stream stream, out String versionStr) { var mdRoot = stream.Position; // Prepare variables var utf8 = MetaDataConstants.SYS_STRING_ENCODING; var tmpArray = new Byte[8]; // Skip signature, major & minor version, and reserved stream.SeekFromCurrent(12); // Read version string var versionStrByteLen = stream.ReadU32(tmpArray); versionStr = stream.ReadZeroTerminatedString(versionStrByteLen, utf8); // Skip flags stream.SeekFromCurrent(2); // Amount of streams var amountOfStreams = stream.ReadU16(tmpArray); // Stream headers var streamDic = new Dictionary <String, Tuple <UInt32, UInt32> >(); //var totalRead = 12 // Sig, major & minor version, reserved // + versionStrByteLen // Version string // + 4; // Flags, amount of streams for (var i = 0; i < amountOfStreams; ++i) { var offset = stream.ReadU32(tmpArray); var size = stream.ReadU32(tmpArray); //UInt32 streamStringBytesLen; streamDic.Add(stream.ReadAlignedASCIIString(32), Tuple.Create(offset, size)); //totalRead += streamStringBytesLen + 8; } // Read all streams except table stream SysStringContainer sysStrings = null; GUIDContainer guids = null; BLOBContainer blobs = null; foreach (var kvp in streamDic) { stream.SeekFromBegin(mdRoot + kvp.Value.Item1); switch (kvp.Key) { case Consts.SYS_STRING_STREAM_NAME: sysStrings = new SysStringContainer(stream, kvp.Value.Item2); break; case Consts.USER_STRING_STREAM_NAME: this.userStrings = new UserStringContainer(stream, kvp.Value.Item2); break; case Consts.GUID_STREAM_NAME: guids = new GUIDContainer(stream, kvp.Value.Item2); break; case Consts.BLOB_STREAM_NAME: blobs = new BLOBContainer(stream, kvp.Value.Item2); break; } } // Read table stream stream.SeekFromBegin(mdRoot + streamDic[Consts.TABLE_STREAM_NAME].Item1 + 6 // Skip reserved + major & minor versions ); // Stream index sizes var b = stream.ReadByteFromStream(); var streamWidths = new Boolean[MAX_WIDTH_INDEX]; streamWidths[SYS_STR_WIDTH_INDEX] = (b & WIDE_SYS_STRING_FLAG) != 0; streamWidths[GUID_WIDTH_INDEX] = (b & WIDE_GUID_FLAG) != 0; streamWidths[BLOB_WIDTH_INDEX] = (b & WIDE_BLOB_FLAG) != 0; stream.SeekFromCurrent(1); // Skip reserved // Present tables var presentTableMask = stream.ReadU64(tmpArray); stream.SeekFromCurrent(8); // Skip sorted // Table row count var tableSizes = Enumerable.Range(0, TablesUtils.AMOUNT_OF_TABLES) .Select( val => { UInt32 size; if (((UInt32)(presentTableMask >> val)) % 2 == 1) { size = stream.ReadU32(tmpArray); } else { size = 0; } return(size); }).ToArray(); // Read actual tables var tRefSizes = MetaDataConstants.GetCodedTableIndexSizes(tableSizes); foreach (var curTable in Enumerable.Range(0, TablesUtils.AMOUNT_OF_TABLES)) { switch ((Tables)curTable) { // VS2012 evaluates positional arguments from left to right, so creating Tuple inside lambda should work correctly // This is not so in VS2010 ( see http://msdn.microsoft.com/en-us/library/hh678682.aspx ) case Tables.Module: ReadTable(ref this.module, curTable, tableSizes, () => Tuple.Create( stream.ReadU16(tmpArray), ReadSysString(stream, sysStrings, streamWidths, tmpArray), ReadGUID(stream, guids, streamWidths, tmpArray), ReadGUID(stream, guids, streamWidths, tmpArray), ReadGUID(stream, guids, streamWidths, tmpArray)) ); break; case Tables.TypeRef: ReadTable(ref this.typeRef, curTable, tableSizes, () => Tuple.Create( MetaDataConstants.ReadCodedTableIndex(stream, CodedTableIndexKind.ResolutionScope, tRefSizes, tmpArray, false), ReadSysString(stream, sysStrings, streamWidths, tmpArray), ReadSysString(stream, sysStrings, streamWidths, tmpArray) )); break; case Tables.TypeDef: ReadTable(ref this.typeDef, curTable, tableSizes, () => Tuple.Create( (TypeAttributes)stream.ReadU32(tmpArray), ReadSysString(stream, sysStrings, streamWidths, tmpArray), ReadSysString(stream, sysStrings, streamWidths, tmpArray), MetaDataConstants.ReadCodedTableIndex(stream, CodedTableIndexKind.TypeDefOrRef, tRefSizes, tmpArray, false), MetaDataConstants.ReadSimpleTableIndex(stream, Tables.Field, tableSizes, tmpArray), MetaDataConstants.ReadSimpleTableIndex(stream, Tables.MethodDef, tableSizes, tmpArray) )); break; case Tables.Field: ReadTable(ref this.field, curTable, tableSizes, () => Tuple.Create( (FieldAttributes)stream.ReadU16(tmpArray), ReadSysString(stream, sysStrings, streamWidths, tmpArray), ReadBLOB(stream, blobs, streamWidths, tmpArray) )); break; case Tables.MethodDef: ReadTable(ref this.methodDef, curTable, tableSizes, () => Tuple.Create( stream.ReadU32(tmpArray), (MethodImplAttributes)stream.ReadU16(tmpArray), (MethodAttributes)stream.ReadU16(tmpArray), ReadSysString(stream, sysStrings, streamWidths, tmpArray), ReadBLOB(stream, blobs, streamWidths, tmpArray), MetaDataConstants.ReadSimpleTableIndex(stream, Tables.Parameter, tableSizes, tmpArray) )); break; case Tables.Parameter: ReadTable(ref this.param, curTable, tableSizes, () => Tuple.Create( (ParameterAttributes)stream.ReadU16(tmpArray), stream.ReadU16(tmpArray), ReadSysString(stream, sysStrings, streamWidths, tmpArray) )); break; case Tables.InterfaceImpl: ReadTable(ref this.interfaceImpl, curTable, tableSizes, () => Tuple.Create( MetaDataConstants.ReadSimpleTableIndex(stream, Tables.TypeDef, tableSizes, tmpArray), MetaDataConstants.ReadCodedTableIndex(stream, CodedTableIndexKind.TypeDefOrRef, tRefSizes, tmpArray).Value )); break; case Tables.MemberRef: ReadTable(ref this.memberRef, curTable, tableSizes, () => Tuple.Create( MetaDataConstants.ReadCodedTableIndex(stream, CodedTableIndexKind.MemberRefParent, tRefSizes, tmpArray).Value, ReadSysString(stream, sysStrings, streamWidths, tmpArray), ReadBLOB(stream, blobs, streamWidths, tmpArray) )); break; case Tables.Constant: ReadTable(ref this.constant, curTable, tableSizes, () => Tuple.Create( stream.ReadU16(tmpArray), MetaDataConstants.ReadCodedTableIndex(stream, CodedTableIndexKind.HasConstant, tRefSizes, tmpArray).Value, ReadBLOB(stream, blobs, streamWidths, tmpArray) )); break; case Tables.CustomAttribute: ReadTable(ref this.customAttribute, curTable, tableSizes, () => Tuple.Create( MetaDataConstants.ReadCodedTableIndex(stream, CodedTableIndexKind.HasCustomAttribute, tRefSizes, tmpArray).Value, MetaDataConstants.ReadCodedTableIndex(stream, CodedTableIndexKind.CustomAttributeType, tRefSizes, tmpArray).Value, ReadBLOB(stream, blobs, streamWidths, tmpArray) )); break; case Tables.FieldMarshal: ReadTable(ref this.fieldMarshal, curTable, tableSizes, () => Tuple.Create( MetaDataConstants.ReadCodedTableIndex(stream, CodedTableIndexKind.HasFieldMarshal, tRefSizes, tmpArray).Value, ReadBLOB(stream, blobs, streamWidths, tmpArray) )); break; case Tables.DeclSecurity: ReadTable(ref this.declSecurity, curTable, tableSizes, () => Tuple.Create( stream.ReadU16(tmpArray), MetaDataConstants.ReadCodedTableIndex(stream, CodedTableIndexKind.HasDeclSecurity, tRefSizes, tmpArray).Value, ReadBLOB(stream, blobs, streamWidths, tmpArray) )); break; case Tables.ClassLayout: ReadTable(ref this.classLayout, curTable, tableSizes, () => Tuple.Create( stream.ReadU16(tmpArray), stream.ReadU32(tmpArray), MetaDataConstants.ReadSimpleTableIndex(stream, Tables.TypeDef, tableSizes, tmpArray) )); break; case Tables.FieldLayout: ReadTable(ref this.fieldLayout, curTable, tableSizes, () => Tuple.Create( stream.ReadU32(tmpArray), MetaDataConstants.ReadSimpleTableIndex(stream, Tables.Field, tableSizes, tmpArray) )); break; case Tables.StandaloneSignature: ReadTable(ref this.standaloneSig, curTable, tableSizes, () => ReadBLOB(stream, blobs, streamWidths, tmpArray)); break; case Tables.EventMap: ReadTable(ref this.eventMap, curTable, tableSizes, () => Tuple.Create( MetaDataConstants.ReadSimpleTableIndex(stream, Tables.TypeDef, tableSizes, tmpArray), MetaDataConstants.ReadSimpleTableIndex(stream, Tables.Event, tableSizes, tmpArray) )); break; case Tables.Event: ReadTable(ref this.events, curTable, tableSizes, () => Tuple.Create( (EventAttributes)stream.ReadU16(tmpArray), ReadSysString(stream, sysStrings, streamWidths, tmpArray), MetaDataConstants.ReadCodedTableIndex(stream, CodedTableIndexKind.TypeDefOrRef, tRefSizes, tmpArray).Value )); break; case Tables.PropertyMap: ReadTable(ref this.propertyMap, curTable, tableSizes, () => Tuple.Create( MetaDataConstants.ReadSimpleTableIndex(stream, Tables.TypeDef, tableSizes, tmpArray), MetaDataConstants.ReadSimpleTableIndex(stream, Tables.Property, tableSizes, tmpArray) )); break; case Tables.Property: ReadTable(ref this.property, curTable, tableSizes, () => Tuple.Create( (PropertyAttributes)stream.ReadU16(tmpArray), ReadSysString(stream, sysStrings, streamWidths, tmpArray), ReadBLOB(stream, blobs, streamWidths, tmpArray) )); break; case Tables.MethodSemantics: ReadTable(ref this.methodSemantics, curTable, tableSizes, () => Tuple.Create( (MethodSemanticsAttributes)stream.ReadU16(tmpArray), MetaDataConstants.ReadSimpleTableIndex(stream, Tables.MethodDef, tableSizes, tmpArray), MetaDataConstants.ReadCodedTableIndex(stream, CodedTableIndexKind.HasSemantics, tRefSizes, tmpArray).Value )); break; case Tables.MethodImpl: ReadTable(ref this.methodImpl, curTable, tableSizes, () => Tuple.Create( MetaDataConstants.ReadSimpleTableIndex(stream, Tables.TypeDef, tableSizes, tmpArray), MetaDataConstants.ReadCodedTableIndex(stream, CodedTableIndexKind.MethodDefOrRef, tRefSizes, tmpArray).Value, MetaDataConstants.ReadCodedTableIndex(stream, CodedTableIndexKind.MethodDefOrRef, tRefSizes, tmpArray).Value )); break; case Tables.ModuleRef: ReadTable(ref this.moduleRef, curTable, tableSizes, () => ReadSysString(stream, sysStrings, streamWidths, tmpArray)); break; case Tables.TypeSpec: ReadTable(ref this.typeSpec, curTable, tableSizes, () => ReadBLOB(stream, blobs, streamWidths, tmpArray)); break; case Tables.ImplMap: ReadTable(ref this.implMap, curTable, tableSizes, () => Tuple.Create( (PInvokeAttributes)stream.ReadU16(tmpArray), MetaDataConstants.ReadCodedTableIndex(stream, CodedTableIndexKind.MemberForwarded, tRefSizes, tmpArray).Value, ReadSysString(stream, sysStrings, streamWidths, tmpArray), MetaDataConstants.ReadSimpleTableIndex(stream, Tables.ModuleRef, tableSizes, tmpArray) )); break; case Tables.FieldRVA: ReadTable(ref this.fieldRVA, curTable, tableSizes, () => Tuple.Create( stream.ReadU32(tmpArray), MetaDataConstants.ReadSimpleTableIndex(stream, Tables.Field, tableSizes, tmpArray) )); break; case Tables.Assembly: ReadTable(ref this.assembly, curTable, tableSizes, () => Tuples.Create( (AssemblyHashAlgorithm)stream.ReadU32(tmpArray), stream.ReadU16(tmpArray), stream.ReadU16(tmpArray), stream.ReadU16(tmpArray), stream.ReadU16(tmpArray), (AssemblyFlags)stream.ReadU32(tmpArray), ReadBLOB(stream, blobs, streamWidths, tmpArray), ReadSysString(stream, sysStrings, streamWidths, tmpArray), ReadSysString(stream, sysStrings, streamWidths, tmpArray) )); break; case Tables.AssemblyRef: ReadTable(ref this.assemblyRef, curTable, tableSizes, () => Tuples.Create( stream.ReadU16(tmpArray), stream.ReadU16(tmpArray), stream.ReadU16(tmpArray), stream.ReadU16(tmpArray), (AssemblyFlags)stream.ReadU32(tmpArray), ReadBLOB(stream, blobs, streamWidths, tmpArray), ReadSysString(stream, sysStrings, streamWidths, tmpArray), ReadSysString(stream, sysStrings, streamWidths, tmpArray), ReadBLOB(stream, blobs, streamWidths, tmpArray) )); break; case Tables.File: ReadTable(ref this.file, curTable, tableSizes, () => Tuple.Create( (FileAttributes)stream.ReadU32(tmpArray), ReadSysString(stream, sysStrings, streamWidths, tmpArray), ReadBLOB(stream, blobs, streamWidths, tmpArray) )); break; case Tables.ExportedType: ReadTable(ref this.exportedType, curTable, tableSizes, () => Tuple.Create( (TypeAttributes)stream.ReadU32(tmpArray), stream.ReadU32(tmpArray), ReadSysString(stream, sysStrings, streamWidths, tmpArray), ReadSysString(stream, sysStrings, streamWidths, tmpArray), MetaDataConstants.ReadCodedTableIndex(stream, CodedTableIndexKind.Implementation, tRefSizes, tmpArray).Value )); break; case Tables.ManifestResource: ReadTable(ref this.manifestResource, curTable, tableSizes, () => Tuple.Create( stream.ReadU32(tmpArray), (ManifestResourceAttributes)stream.ReadU32(tmpArray), ReadSysString(stream, sysStrings, streamWidths, tmpArray), MetaDataConstants.ReadCodedTableIndex(stream, CodedTableIndexKind.Implementation, tRefSizes, tmpArray, false) )); break; case Tables.NestedClass: ReadTable(ref this.nestedClass, curTable, tableSizes, () => Tuple.Create( MetaDataConstants.ReadSimpleTableIndex(stream, Tables.TypeDef, tableSizes, tmpArray), MetaDataConstants.ReadSimpleTableIndex(stream, Tables.TypeDef, tableSizes, tmpArray) )); break; case Tables.GenericParameter: ReadTable(ref this.genericParam, curTable, tableSizes, () => Tuple.Create( stream.ReadU16(tmpArray), (GenericParameterAttributes)stream.ReadU16(tmpArray), MetaDataConstants.ReadCodedTableIndex(stream, CodedTableIndexKind.TypeOrMethodDef, tRefSizes, tmpArray).Value, ReadSysString(stream, sysStrings, streamWidths, tmpArray) )); break; case Tables.MethodSpec: ReadTable(ref this.methodSpec, curTable, tableSizes, () => Tuple.Create( MetaDataConstants.ReadCodedTableIndex(stream, CodedTableIndexKind.MethodDefOrRef, tRefSizes, tmpArray).Value, ReadBLOB(stream, blobs, streamWidths, tmpArray) )); break; case Tables.GenericParameterConstraint: ReadTable(ref this.genericParamConstraint, curTable, tableSizes, () => Tuple.Create( MetaDataConstants.ReadSimpleTableIndex(stream, Tables.GenericParameter, tableSizes, tmpArray), MetaDataConstants.ReadCodedTableIndex(stream, CodedTableIndexKind.TypeDefOrRef, tRefSizes, tmpArray).Value )); break; case Tables.FieldPtr: case Tables.MethodPtr: case Tables.ParameterPtr: case Tables.EventPtr: case Tables.PropertyPtr: case Tables.EncLog: case Tables.EncMap: case Tables.AssemblyProcessor: case Tables.AssemblyOS: case Tables.AssemblyRefProcessor: case Tables.AssemblyRefOS: // Skip break; default: throw new BadImageFormatException("Unknown table: " + curTable); } } }