/// <summary> /// /// </summary> /// <param name="table"></param> /// <param name="foreignKeyMetadata"></param> /// <returns></returns> private ForeignKeyInfo GetForeignKey(MetadataTableInfo table, ForeignKeyMetadata foreignKeyMetadata) { var foreignKey = new ForeignKeyInfo(); foreignKey.Name = foreignKeyMetadata.Name; foreignKey.Column = table.GetColumn(foreignKeyMetadata.Column.Name); foreignKey.Table = table; foreignKey.ReferenceTable = GetReferenceTable(foreignKeyMetadata); foreignKey.ReferenceColumn = GetReferenceColumn(foreignKey, foreignKeyMetadata); MigrateManager.CorrectName(foreignKey); return(foreignKey); }
/// <summary> /// /// </summary> /// <param name="tableMetadata"></param> /// <returns></returns> private MetadataTableInfo GetTableInfo(TableMetadata tableMetadata) { var databaseTablesManager = MigrateManager.ServicesContainer.GetService <IDatabaseTablesManager>(); var tableInfo = new MetadataTableInfo(); tableInfo.TableMetadata = tableMetadata; tableInfo.Name = tableMetadata.Name; tableInfo.Description = tableMetadata.Decription; tableInfo.Schema = tableMetadata.Schema ?? databaseTablesManager?.DefaultSchema; MigrateManager.CorrectName(tableInfo); tableInfo.Columns = GetColumns(tableInfo, tableMetadata); tableInfo.PrimaryKey = GetPrimaryKey(tableInfo, tableMetadata); tableInfo.TableValues = GetTableValues(tableInfo, tableMetadata); return(tableInfo); }
/// <summary> /// /// </summary> /// <param name="tableInfo"></param> /// <param name="tableMetadata"></param> /// <returns></returns> private PrimaryKeyInfo GetPrimaryKey(MetadataTableInfo tableInfo, TableMetadata tableMetadata) { var primaryKeyMetadata = tableMetadata.PrimaryKey; if (primaryKeyMetadata == null) { return(null); } var primaryKey = new PrimaryKeyInfo(); primaryKey.Table = tableInfo; primaryKey.Name = primaryKeyMetadata.Name; primaryKey.PrimaryColumn = tableInfo.GetColumn(primaryKeyMetadata.PrimaryColumn?.Name); MigrateManager.CorrectName(primaryKey); return(primaryKey); }
/// <summary> /// Modifies a CLI assembly produced by <see cref="AssemblyBuilder"/> /// to make it a portable class library (huge hack!). /// </summary> /// <param name="stream">A read-write stream to the CLI assembly to be modified.</param> public static void PatchReflectionEmitAssembly(Stream stream) { Contract.Requires(stream != null); Contract.Requires(stream.CanRead && stream.CanWrite && stream.CanSeek); // Read the DOS header var dosHeader = stream.ReadStruct <IMAGE_DOS_HEADER>(); if (dosHeader.e_magic != IMAGE_DOS_HEADER.IMAGE_DOS_SIGNATURE) { throw new InvalidDataException("Invalid DOS header."); } // Read the NT header stream.Position = dosHeader.e_lfanew; var ntHeadersSignature = stream.ReadStruct <uint>(); if (ntHeadersSignature != IMAGE_NT_HEADERS.IMAGE_NT_SIGNATURE) { throw new InvalidDataException("Invalid NT header."); } // Read the file header var fileHeader = stream.ReadStruct <IMAGE_FILE_HEADER>(); // Read the optional header long optionalHeaderPosition = stream.Position; var optionalHeaderMagic = stream.ReadStruct <ushort>(); if (optionalHeaderMagic != IMAGE_OPTIONAL_HEADER32.IMAGE_NT_OPTIONAL_HDR_MAGIC) { throw new InvalidDataException("Unsupported non-32 bit NT optional header."); } stream.Position = optionalHeaderPosition; var optionalHeader = stream.ReadStruct <IMAGE_OPTIONAL_HEADER32>(); Contract.Assert(optionalHeader.MajorOperatingSystemVersion == 4); Contract.Assert(optionalHeader.NumberOfRvaAndSizes == IMAGE_OPTIONAL_HEADER.IMAGE_NUMBEROF_DIRECTORY_ENTRIES); Contract.Assert(optionalHeader.Subsystem == 3); // Read the section headers var sectionHeaders = new IMAGE_SECTION_HEADER[fileHeader.NumberOfSections]; for (int i = 0; i < sectionHeaders.Length; ++i) { sectionHeaders[i] = stream.ReadStruct <IMAGE_SECTION_HEADER>(); } // Read the CLR header var comDescriptorVirtualAddress = optionalHeader.DataDirectory[IMAGE_DATA_DIRECTORY.IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress; stream.Position = VirtualAddressToFilePosition(comDescriptorVirtualAddress, sectionHeaders); var cor20Header = stream.ReadStruct <IMAGE_COR20_HEADER>(); // Read the metadata header var metadataHeaderVirtualAddress = cor20Header.MetaData.VirtualAddress; var metadataHeaderPosition = VirtualAddressToFilePosition(metadataHeaderVirtualAddress, sectionHeaders); stream.Position = metadataHeaderPosition; var metadataRootPart1 = stream.ReadStruct <MetadataRoot_BeforeVersion>(); if (metadataRootPart1.Signature != MetadataRoot_BeforeVersion.StandardSignature) { throw new InvalidDataException("Invalid metadata root signature."); } string metadataVersionString = stream.ReadNullPaddedString((metadataRootPart1.Length + 3U) & ~3U); var metadataRootPart2 = stream.ReadStruct <MetadataRoot_AfterVersion>(); // Read the stream headers var metadataStreamHeaders = new Dictionary <string, StreamHeader>(StringComparer.Ordinal); for (int i = 0; i < metadataRootPart2.Streams; ++i) { var metadataStreamHeader = stream.ReadStruct <StreamHeader>(); var metadataStreamName = stream.ReadPaddedNullTerminatedString(4); metadataStreamHeaders.Add(metadataStreamName, metadataStreamHeader); } // Read the metadata table stream header stream.Position = metadataHeaderPosition + metadataStreamHeaders["#~"].Offset; var metadataTablesStreamHeader = stream.ReadStruct <MetadataTablesStreamHeader>(); if (metadataTablesStreamHeader.MajorVersion != 2 || metadataTablesStreamHeader.MinorVersion != 0) { throw new InvalidDataException("Unsupported metadata tables stream version."); } var metadataTableInfos = new MetadataTableInfo[64]; for (int i = 0; i < metadataTableInfos.Length; ++i) { if ((metadataTablesStreamHeader.Valid & (1UL << i)) != 0) { metadataTableInfos[i].RowCount = stream.ReadStruct <uint>(); } } var metadataTablesStartPosition = stream.Position; // Compute the size of the metadata rows and their offset uint stringIndexSize = (metadataTablesStreamHeader.HeapSizes & 0x01) == 0 ? 2U : 4U; uint blobIndexSize = (metadataTablesStreamHeader.HeapSizes & 0x04) == 0 ? 2U : 4U; FillMetadataTableInfos(ref metadataTablesStreamHeader, metadataTableInfos); // Read the assembly reference tables var assemblyReferenceTableInfo = metadataTableInfos[(int)Table.AssemblyReference]; stream.Position = metadataTablesStartPosition + assemblyReferenceTableInfo.Offset; for (uint i = 0; i < assemblyReferenceTableInfo.RowCount; ++i) { var rowPosition = stream.Position; ushort majorVersion = stream.ReadStruct <ushort>(); ushort minorVersion = stream.ReadStruct <ushort>(); ushort buildNumber = stream.ReadStruct <ushort>(); ushort revisionNumber = stream.ReadStruct <ushort>(); var version = new Version(majorVersion, minorVersion, buildNumber, revisionNumber); uint flags = stream.ReadStruct <uint>(); uint publicKeyOrTokenIndex = blobIndexSize == 2 ? stream.ReadStruct <ushort>() : stream.ReadStruct <uint>(); uint nameIndex = stringIndexSize == 2 ? stream.ReadStruct <ushort>() : stream.ReadStruct <uint>(); uint cultureIndex = stringIndexSize == 2 ? stream.ReadStruct <ushort>() : stream.ReadStruct <uint>(); uint hashValueIndex = stringIndexSize == 2 ? stream.ReadStruct <ushort>() : stream.ReadStruct <uint>(); var nextRowPosition = stream.Position; if (version == nonportableMscorlibVersion && flags == nonportableMscorlibFlags) { // Looks like mscorlib, let's make sure long nameStringPosition = metadataHeaderPosition + metadataStreamHeaders["#Strings"].Offset + nameIndex; long publicKeyBlobPosition = metadataHeaderPosition + metadataStreamHeaders["#Blob"].Offset + publicKeyOrTokenIndex; stream.Position = nameStringPosition; var name = stream.ReadPaddedNullTerminatedString(1); stream.Position = publicKeyBlobPosition; var publicKeyBlob = stream.ReadBytes(nonportableMscorlibPublicKeyBlob.Length); if (name == "mscorlib" && Equals(publicKeyBlob, nonportableMscorlibPublicKeyBlob)) { // It is indeed the mscorlib we want to patch! // Patch the version number and assembly flags stream.Position = rowPosition; stream.WriteStruct((ushort)portableMscorlibVersion.Major); stream.WriteStruct((ushort)portableMscorlibVersion.Minor); stream.WriteStruct((ushort)portableMscorlibVersion.Build); stream.WriteStruct((ushort)portableMscorlibVersion.Revision); stream.WriteStruct <uint>(portableMscorlibFlags); // Update the public key token stream.Position = publicKeyBlobPosition; stream.Write(portableMscorlibPublicKeyBlob, 0, portableMscorlibPublicKeyBlob.Length); // Done! return; } else { stream.Position = nextRowPosition; } } } throw new InvalidDataException("mscorlib assembly reference not found."); }
protected override void DoRun() { using (DiskImageFile vhdxFile = new DiskImageFile(_vhdxFile.Value, FileAccess.Read)) { DiskImageFileInfo info = vhdxFile.Information; FileInfo fileInfo = new FileInfo(_vhdxFile.Value); Console.WriteLine("File Info"); Console.WriteLine("---------"); Console.WriteLine(" File Name: {0}", fileInfo.FullName); Console.WriteLine(" File Size: {0} ({1} bytes)", Utilities.ApproximateDiskSize(fileInfo.Length), fileInfo.Length); Console.WriteLine(" File Creation Time: {0} (UTC)", fileInfo.CreationTimeUtc); Console.WriteLine(" File Write Time: {0} (UTC)", fileInfo.LastWriteTimeUtc); Console.WriteLine(); Console.WriteLine("VHDX File Info"); Console.WriteLine("--------------"); Console.WriteLine(" Signature: {0:x8}", info.Signature); Console.WriteLine(" Creator: {0:x8}", info.Creator); Console.WriteLine(" Block Size: {0} (0x{0:X8})", info.BlockSize); Console.WriteLine("Leave Blocks Alloced: {0}", info.LeaveBlocksAllocated); Console.WriteLine(" Has Parent: {0}", info.HasParent); Console.WriteLine(" Disk Size: {0} ({1} (0x{1:X8}))", Utilities.ApproximateDiskSize(info.DiskSize), info.DiskSize); Console.WriteLine(" Logical Sector Size: {0} (0x{0:X8})", info.LogicalSectorSize); Console.WriteLine("Physical Sector Size: {0} (0x{0:X8})", info.PhysicalSectorSize); Console.WriteLine(" Parent Locator Type: {0}", info.ParentLocatorType); WriteParentLocations(info); Console.WriteLine(); WriteHeaderInfo(info.FirstHeader); WriteHeaderInfo(info.SecondHeader); if (info.ActiveHeader.LogGuid != Guid.Empty) { Console.WriteLine("Log Info (Active Sequence)"); Console.WriteLine("--------------------------"); foreach (var entry in info.ActiveLogSequence) { Console.WriteLine(" Log Entry"); Console.WriteLine(" ---------"); Console.WriteLine(" Sequence Number: {0}", entry.SequenceNumber); Console.WriteLine(" Tail: {0}", entry.Tail); Console.WriteLine(" Flushed File Offset: {0} (0x{0:X8})", entry.FlushedFileOffset); Console.WriteLine(" Last File Offset: {0} (0x{0:X8})", entry.LastFileOffset); Console.WriteLine(" File Extents: {0}", entry.IsEmpty ? "<none>" : ""); foreach (var extent in entry.ModifiedExtents) { Console.WriteLine(" {0} +{1} (0x{0:X8} +0x{1:X8})", extent.Offset, extent.Count); } Console.WriteLine(); } } RegionTableInfo regionTable = info.RegionTable; Console.WriteLine("Region Table Info"); Console.WriteLine("-----------------"); Console.WriteLine(" Signature: {0}", regionTable.Signature); Console.WriteLine(" Checksum: {0:x8}", regionTable.Checksum); Console.WriteLine(" Entry Count: {0}", regionTable.Count); Console.WriteLine(); foreach (var entry in regionTable) { Console.WriteLine("Region Table Entry Info"); Console.WriteLine("-----------------------"); Console.WriteLine(" Guid: {0}", entry.Guid); Console.WriteLine(" Well-Known Name: {0}", entry.WellKnownName); Console.WriteLine(" File Offset: {0} (0x{0:X8})", entry.FileOffset); Console.WriteLine(" Length: {0} (0x{0:X8})", entry.Length); Console.WriteLine(" Is Required: {0}", entry.IsRequired); Console.WriteLine(); } MetadataTableInfo metadataTable = info.MetadataTable; Console.WriteLine("Metadata Table Info"); Console.WriteLine("-------------------"); Console.WriteLine(" Signature: {0}", metadataTable.Signature); Console.WriteLine(" Entry Count: {0}", metadataTable.Count); Console.WriteLine(); foreach (var entry in metadataTable) { Console.WriteLine("Metadata Table Entry Info"); Console.WriteLine("-------------------------"); Console.WriteLine(" Item Id: {0}", entry.ItemId); Console.WriteLine(" Well-Known Name: {0}", entry.WellKnownName); Console.WriteLine(" Offset: {0} (0x{0:X8})", entry.Offset); Console.WriteLine(" Length: {0} (0x{0:X8})", entry.Length); Console.WriteLine(" Is User: {0}", entry.IsUser); Console.WriteLine(" Is Required: {0}", entry.IsRequired); Console.WriteLine(" Is Virtual Disk: {0}", entry.IsVirtualDisk); Console.WriteLine(); } } }
/// <summary> /// /// </summary> /// <param name="table"></param> /// <returns></returns> private List <ForeignKeyInfo> GetForeignKeys(MetadataTableInfo table) { var forignKeys = table.TableMetadata.ForeignKeys; return(forignKeys.Select(s => GetForeignKey(table, s)).ToList(w => w != null)); }