/// <summary>Получить размер колонки в таблице</summary> /// <param name="type">Тип колонки</param> /// <returns>Размер колонки</returns> internal UInt32 SizeOfColumn(MetaColumnType type) { switch (type) { case MetaColumnType.UInt16: return(2); case MetaColumnType.UInt32: return(4); case MetaColumnType.String: return(this.Root.StreamTableHeader.StringIndexSize); case MetaColumnType.Blob: return(this.Root.StreamTableHeader.BlobIndexSize); case MetaColumnType.Guid: return(this.Root.StreamTableHeader.GuidIndexSize); default: if (MetaColumn.IsColumnCellPointer(type)) //Указатель на другую таблицу { return((UInt32)(this.Root.GetRowsCount((Cor.MetaTableType)type) < 65536 ? 2 : 4)); } //CodedToken MetaColumnType[] referredTypes = MetaTable.GetCodedTokenTypes(type); UInt32 maxRows = 0; foreach (MetaColumnType referredType in referredTypes) { if (referredType != MetaColumnType.UserString) //but what if there is a large user string table? { UInt32 rows = (UInt32)this.Root.GetRowsCount((Cor.MetaTableType)referredType); if (maxRows < rows) { maxRows = rows; } } } maxRows = maxRows << MetaCellCodedToken.CodedTokenBits[referredTypes.Length]; return((UInt32)(maxRows < 65536 ? 2 : 4)); } }
/// <summary>Получить описатель таблицы</summary> /// <param name="table">Таблица для получения колонок</param> /// <exception cref="T:NotSupportedException">Unknown table</exception> /// <exception cref="T:InvalidOperationException">Column names not equal column types</exception> /// <returns>Массив колонок в таблице</returns> private static MetaColumn[] GetTableDescription(Cor.MetaTableType table) { MetaColumnType[] columnType; String[] columnName; switch (table) { case Cor.MetaTableType.Module: columnType = new MetaColumnType[] { MetaColumnType.UInt16, MetaColumnType.String, MetaColumnType.Guid, MetaColumnType.Guid, MetaColumnType.Guid, }; columnName = new String[] { "Generation", "Name", "Mvid", "EncId", "EncBaseId", }; break; case Cor.MetaTableType.TypeRef: columnType = new MetaColumnType[] { MetaColumnType.ResolutionScope, MetaColumnType.String, MetaColumnType.String, }; columnName = new String[] { "ResolutionScope", "TypeName", "TypeNamespace" }; break; case Cor.MetaTableType.TypeDef: columnType = new MetaColumnType[] { MetaColumnType.UInt32, MetaColumnType.String, MetaColumnType.String, MetaColumnType.TypeDefOrRef, MetaColumnType.Field, MetaColumnType.MethodDef, }; columnName = new String[] { "Flags", "TypeName", "TypeNamespace", "Extends", "FieldList", "MethodList", }; break; case Cor.MetaTableType.FieldPtr: columnType = new MetaColumnType[] { MetaColumnType.Field, }; columnName = new String[] { "Field" }; break; case Cor.MetaTableType.Field: columnType = new MetaColumnType[] { MetaColumnType.UInt16, MetaColumnType.String, MetaColumnType.Blob, }; columnName = new String[] { "Flags", "Name", "Signature", }; break; case Cor.MetaTableType.MethodPtr: columnType = new MetaColumnType[] { MetaColumnType.MethodDef, }; columnName = new String[] { "Method", }; break; case Cor.MetaTableType.MethodDef: columnType = new MetaColumnType[] { MetaColumnType.UInt32, MetaColumnType.UInt16, MetaColumnType.UInt16, MetaColumnType.String, MetaColumnType.Blob, MetaColumnType.Param, }; columnName = new String[] { "RVA", "ImplFlags", "Flags", "Name", "Signature", "ParamList", }; break; case Cor.MetaTableType.ParamPtr: columnType = new MetaColumnType[] { MetaColumnType.Param, }; columnName = new String[] { "Param", }; break; case Cor.MetaTableType.Param: columnType = new MetaColumnType[] { MetaColumnType.UInt16, MetaColumnType.UInt16, MetaColumnType.String, }; columnName = new String[] { "Flags", "Sequence", "Name", }; break; case Cor.MetaTableType.InterfaceImpl: columnType = new MetaColumnType[] { MetaColumnType.TypeDef, MetaColumnType.TypeDefOrRef, }; columnName = new String[] { "Class", "Interface", }; break; case Cor.MetaTableType.MemberRef: columnType = new MetaColumnType[] { MetaColumnType.MemberRefParent, MetaColumnType.String, MetaColumnType.Blob, }; columnName = new String[] { "Class", "Name", "Signature", }; break; case Cor.MetaTableType.Constant: columnType = new MetaColumnType[] { MetaColumnType.UInt16, MetaColumnType.HasConstant, MetaColumnType.Blob, }; columnName = new String[] { "Type", "Parent", "Value", }; break; case Cor.MetaTableType.CustomAttribute: columnType = new MetaColumnType[] { MetaColumnType.HasCustomAttribute, MetaColumnType.CustomAttributeType, MetaColumnType.Blob, }; columnName = new String[] { "Parent", "Type", "Value", }; break; case Cor.MetaTableType.FieldMarshal: columnType = new MetaColumnType[] { MetaColumnType.HasFieldMarshal, MetaColumnType.Blob, }; columnName = new String[] { "Parent", "Native", }; break; case Cor.MetaTableType.DeclSecurity: columnType = new MetaColumnType[] { MetaColumnType.UInt16, MetaColumnType.HasDeclSecurity, MetaColumnType.Blob, }; columnName = new String[] { "Action", "Parent", "PermissionSet", }; break; case Cor.MetaTableType.ClassLayout: columnType = new MetaColumnType[] { MetaColumnType.UInt16, MetaColumnType.UInt32, MetaColumnType.TypeDef, }; columnName = new String[] { "PackingSize", "ClassSize", "Parent", }; break; case Cor.MetaTableType.FieldLayout: columnType = new MetaColumnType[] { MetaColumnType.UInt32, MetaColumnType.Field, }; columnName = new String[] { "Offset", "Field", }; break; case Cor.MetaTableType.StandAloneSig: columnType = new MetaColumnType[] { MetaColumnType.Blob, }; columnName = new String[] { "Signature", }; break; case Cor.MetaTableType.EventMap: columnType = new MetaColumnType[] { MetaColumnType.TypeDef, MetaColumnType.Event, }; columnName = new String[] { "Parent", "EventList", }; break; case Cor.MetaTableType.EventPtr: columnType = new MetaColumnType[] { MetaColumnType.Event, }; columnName = new String[] { "Event", }; break; case Cor.MetaTableType.Event: columnType = new MetaColumnType[] { MetaColumnType.UInt16, MetaColumnType.String, MetaColumnType.TypeDefOrRef, }; columnName = new String[] { "EventFlags", "Name", "EventType", }; break; case Cor.MetaTableType.PropertyMap: columnType = new MetaColumnType[] { MetaColumnType.TypeDef, MetaColumnType.Property, }; columnName = new String[] { "Parent", "PropertyList", }; break; case Cor.MetaTableType.PropertyPtr: columnType = new MetaColumnType[] { MetaColumnType.Property, }; columnName = new String[] { "Property", }; break; case Cor.MetaTableType.Property: columnType = new MetaColumnType[] { MetaColumnType.UInt16, MetaColumnType.String, MetaColumnType.Blob, }; columnName = new String[] { "Flags", "Name", "Type", }; break; case Cor.MetaTableType.MethodSemantics: columnType = new MetaColumnType[] { MetaColumnType.UInt16, MetaColumnType.MethodDef, MetaColumnType.HasSemantic, }; columnName = new String[] { "Semantic", "Method", "Association", }; break; case Cor.MetaTableType.MethodImpl: columnType = new MetaColumnType[] { MetaColumnType.TypeDef, MetaColumnType.MethodDefOrRef, MetaColumnType.MethodDefOrRef, }; columnName = new String[] { "Class", "MethodBody", "MethodDeclaration", }; break; case Cor.MetaTableType.ModuleRef: columnType = new MetaColumnType[] { MetaColumnType.String, }; columnName = new String[] { "Name", }; break; case Cor.MetaTableType.TypeSpec: columnType = new MetaColumnType[] { MetaColumnType.Blob, }; columnName = new String[] { "Signature", }; break; case Cor.MetaTableType.ImplMap: columnType = new MetaColumnType[] { MetaColumnType.UInt16, MetaColumnType.MemberForwarded, MetaColumnType.String, MetaColumnType.ModuleRef, }; columnName = new String[] { "MappingFlags", "MemberForwarded", "ImportName", "ImportScope", }; break; case Cor.MetaTableType.FieldRVA: columnType = new MetaColumnType[] { MetaColumnType.UInt32, MetaColumnType.Field, }; columnName = new String[] { "RVA", "Field", }; break; case Cor.MetaTableType.ENCLog: columnType = new MetaColumnType[] { MetaColumnType.UInt32, MetaColumnType.UInt32, }; columnName = new String[] { "Token", "FuncCode", }; break; case Cor.MetaTableType.ENCMap: columnType = new MetaColumnType[] { MetaColumnType.UInt32, }; columnName = new String[] { "Token", }; break; case Cor.MetaTableType.Assembly: columnType = new MetaColumnType[] { MetaColumnType.UInt32, MetaColumnType.UInt16, MetaColumnType.UInt16, MetaColumnType.UInt16, MetaColumnType.UInt16, MetaColumnType.UInt32, MetaColumnType.Blob, MetaColumnType.String, MetaColumnType.String, }; columnName = new String[] { "HashAlgId", "MajorVersion", "MinorVersion", "BuildNumber", "RevisionNumber", "Flags", "PublicKey", "Name", "Locale", }; break; case Cor.MetaTableType.AssemblyProcessor: columnType = new MetaColumnType[] { MetaColumnType.UInt32, }; columnName = new String[] { "Processor", }; break; case Cor.MetaTableType.AssemblyOS: columnType = new MetaColumnType[] { MetaColumnType.UInt32, MetaColumnType.UInt32, MetaColumnType.UInt32, }; columnName = new String[] { "OSPlatformId", "OSMajorVersion", "OSMinorVersion", }; break; case Cor.MetaTableType.AssemblyRef: columnType = new MetaColumnType[] { MetaColumnType.UInt16, MetaColumnType.UInt16, MetaColumnType.UInt16, MetaColumnType.UInt16, MetaColumnType.UInt32, MetaColumnType.Blob, MetaColumnType.String, MetaColumnType.String, MetaColumnType.Blob, }; columnName = new String[] { "MajorVersion", "MinorVersion", "BuildNumber", "RevisionNumber", "Flags", "PublicKeyOrToken", "Name", "Locale", "HashValue", }; break; case Cor.MetaTableType.AssemblyRefProcessor: columnType = new MetaColumnType[] { MetaColumnType.UInt32, MetaColumnType.AssemblyRef, }; columnName = new String[] { "Processor", "AssemblyRef", }; break; case Cor.MetaTableType.AssemblyRefOS: columnType = new MetaColumnType[] { MetaColumnType.UInt32, MetaColumnType.UInt32, MetaColumnType.UInt32, MetaColumnType.AssemblyRef, }; columnName = new String[] { "OSPlatformId", "OSMajorVersion", "OSMinorVersion", "AssemblyRef", }; break; case Cor.MetaTableType.File: columnType = new MetaColumnType[] { MetaColumnType.UInt32, MetaColumnType.String, MetaColumnType.Blob, }; columnName = new String[] { "Flags", "Name", "HashValue", }; break; case Cor.MetaTableType.ExportedType: columnType = new MetaColumnType[] { MetaColumnType.UInt32, MetaColumnType.UInt32, MetaColumnType.String, MetaColumnType.String, MetaColumnType.Implementation, }; columnName = new String[] { "Flags", "TypeDefId", "TypeName", "TypeNamespace", "Implementation", }; break; case Cor.MetaTableType.ManifestResource: columnType = new MetaColumnType[] { MetaColumnType.UInt32, MetaColumnType.UInt32, MetaColumnType.String, MetaColumnType.Implementation, }; columnName = new String[] { "Offset", "Flags", "Name", "Implementation", }; break; case Cor.MetaTableType.NestedClass: columnType = new MetaColumnType[] { MetaColumnType.TypeDef, MetaColumnType.TypeDef, }; columnName = new String[] { "NestedClass", "EnclosingClass", }; break; case Cor.MetaTableType.GenericParam: columnType = new MetaColumnType[] { MetaColumnType.UInt16, MetaColumnType.UInt16, MetaColumnType.TypeOrMethodDef, MetaColumnType.String, }; columnName = new String[] { "Number", "Flags", "Owner", "Name", }; break; case Cor.MetaTableType.MethodSpec: columnType = new MetaColumnType[] { MetaColumnType.MethodDefOrRef, MetaColumnType.Blob, }; columnName = new String[] { "Method", "Instantiation", }; break; case Cor.MetaTableType.GenericParamConstraint: columnType = new MetaColumnType[] { MetaColumnType.GenericParam, MetaColumnType.TypeDefOrRef, }; columnName = new String[] { "Owner", "Constraint", }; break; default: throw new NotSupportedException(); } if (columnType.Length != columnName.Length) { throw new InvalidOperationException("Length of column type and names must be equal"); } MetaColumn[] result = new MetaColumn[columnType.Length]; for (UInt16 loop = 0; loop < result.Length; loop++) { result[loop] = new MetaColumn(table, columnType[loop], columnName[loop], loop); } return(result); }
/// <summary>Create instance of MetaTable cell class</summary> /// <param name="table">Owner table</param> /// <param name="column">Owner column</param> /// <param name="rowIndex">Owner row index</param> /// <param name="reader">Image reader pointed to cell value</param> public MetaCell(MetaTable table, MetaColumn column, UInt32 rowIndex, BinaryReader reader) { if (table == null) { throw new ArgumentNullException("table"); } if (column == null) { throw new ArgumentNullException("column"); } if (reader == null) { throw new ArgumentNullException("reader"); } this._table = table; this._column = column; this._rowIndex = rowIndex; switch (this.Column.ColumnType) { case MetaColumnType.UInt16: this._rawValue = reader.ReadUInt16(); this._value = (UInt16)this.RawValue; break; case MetaColumnType.UInt32: this._rawValue = reader.ReadUInt32(); this._value = (UInt32)this.RawValue; break; case MetaColumnType.String: this._rawValue = this.Table.Root.StreamTableHeader.StringIndexSize == 2 ? (UInt32)reader.ReadUInt16() : reader.ReadUInt32(); this._value = this.Table.Root.Parent.StringHeap[(Int32)this.RawValue]; break; case MetaColumnType.Guid: this._rawValue = this.Table.Root.StreamTableHeader.GuidIndexSize == 2 ? (UInt32)reader.ReadUInt16() : reader.ReadUInt32(); this._value = this.Table.Root.Parent.GuidHeap[(Int32)this.RawValue]; break; case MetaColumnType.Blob: this._rawValue = this.Table.Root.StreamTableHeader.BlobIndexSize == 2 ? (UInt32)reader.ReadUInt16() : reader.ReadUInt32(); this._value = this.Table.Root.Parent.BlobHeap[(Int32)this.RawValue]; break; /*case MetaColumnType.UserString: * this._value = this.Table.Root.MetaData.USHeap[(Int32)this.RawValue]; * break;*/ default: if (this.Column.IsCellPointer) //Указатель на другую таблицу { MetaTable refTable = this.Table.Root[(Cor.MetaTableType) this.Column.ColumnType]; this._rawValue = ((refTable.RowsCount < 65536) ? reader.ReadUInt16() : reader.ReadUInt32()); this._value = new MetaCellPointer(this, this.RawValue); //TODO: Не понял необходимость сдвига исходя из типа таблицы. //this.RawValue = (((uint)this.Column.Type << 24) | ((refTable.RowsCount < 65536) ? reader.ReadUInt16() : reader.ReadUInt32())); } else if (this.Column.IsCodedToken) //Coded token { // Coded token (may need to be uncompressed from 2-byte form) UInt32 codedToken = this.Table.SizeOfColumn(this.Column.ColumnType) == 2 ? reader.ReadUInt16() : reader.ReadUInt32(); MetaColumnType[] columns = MetaTable.GetCodedTokenTypes(this.Column.ColumnType); Int32 tableIndex = ((Int32)codedToken) & ~(-1 << MetaCellCodedToken.CodedTokenBits[columns.Length]); Int32 index = ((Int32)codedToken) >> MetaCellCodedToken.CodedTokenBits[columns.Length]; Int32 token = MetaCellCodedToken.ToToken(columns[tableIndex], index); this._rawValue = (UInt32)token; this._value = new MetaCellCodedToken(this, (UInt32)index, columns[tableIndex]); //this._value = new MetaCellCodedToken(this, this.RawValue); } break; } }