Пример #1
0
        private void ReadMetadata(VHDX_REGION_TABLE_ENTRY metadataRegion, out VHDX_FILE_PARAMETERS outFileParams, out Int64 outVirtualDiskSize, out uint outLogicalSectorSize)
        {
            if (metadataRegion.Length < METADATA_TABLE_SIZE)
            {
                throw new Exception("Metadata region is too small to contain metadata table!");
            }
            var metadataBytes = mHdd.ReadBytes(checked ((long)metadataRegion.FileOffset), checked ((int)metadataRegion.Length));

            var metadataHeader = Program.ToStruct <VHDX_METADATA_TABLE_HEADER>(metadataBytes, 0);

            if (metadataHeader.Signature != METADATA_TABLE_SIG)
            {
                throw new Exception("Bad metadata header sig.");
            }
            if (metadataHeader.EntryCount > MAX_TABLE_ENTRIES)
            {
                throw new Exception("Too many metadata entries.");
            }
            VHDX_FILE_PARAMETERS?fileParams = null;
            UInt64?virtualDiskSize          = null;
            UInt32?logicalSectorSize        = null;

            for (int i = 0; i < metadataHeader.EntryCount; i++)
            {
                int readOffset = Program.SizeOf <VHDX_METADATA_TABLE_HEADER>()
                                 + i * Program.SizeOf <VHDX_METADATA_TABLE_ENTRY>();
                var entry = Program.ToStruct <VHDX_METADATA_TABLE_ENTRY>(metadataBytes, readOffset);

                if (entry.IsUser)
                {
                    if (entry.IsRequired)
                    {
                        throw new Exception($"Unknown required metadata item: {entry.ItemId}");
                    }
                    else
                    {
                        continue;
                    }
                }
                else if (entry.IsRequired && !sKnownMetadataItems.Contains(entry.ItemId))
                {
                    throw new Exception($"Unknown required metadata item: {entry.ItemId}");
                }

                //the ArraySegment overload of ToStruct will make sure the entry size matches the data item
                var entryBytes = new ArraySegment <byte>(metadataBytes, checked ((int)entry.Offset), checked ((int)entry.Length));
                if (entry.ItemId == METADATA_FILE_PARAMS)
                {
                    fileParams = Program.ToStruct <VHDX_FILE_PARAMETERS>(entryBytes);
                }
                else if (entry.ItemId == METADATA_VIRTUAL_DISK_SIZE)
                {
                    virtualDiskSize = Program.ToStruct <UInt64>(entryBytes);
                }
                else if (entry.ItemId == METADATA_LOGICAL_SECTOR_SIZE)
                {
                    logicalSectorSize = Program.ToStruct <UInt32>(entryBytes);
                }
            }

            if (!fileParams.HasValue || !virtualDiskSize.HasValue || !logicalSectorSize.HasValue)
            {
                throw new Exception("Missing required metadata!");
            }

            outFileParams        = fileParams.Value;
            outVirtualDiskSize   = checked ((long)virtualDiskSize.Value);
            outLogicalSectorSize = logicalSectorSize.Value;
        }
Пример #2
0
        private void ReadMetadata(VHDX_REGION_TABLE_ENTRY metadataRegion, out VHDX_FILE_PARAMETERS outFileParams, out Int64 outVirtualDiskSize, out uint outLogicalSectorSize)
        {
            if (metadataRegion.Length < METADATA_TABLE_SIZE)
                throw new Exception("Metadata region is too small to contain metadata table!");
            var metadataBytes = mHdd.ReadBytes(checked((long)metadataRegion.FileOffset), checked((int)metadataRegion.Length));

            var metadataHeader = Program.ToStruct<VHDX_METADATA_TABLE_HEADER>(metadataBytes, 0);
            if (metadataHeader.Signature != METADATA_TABLE_SIG)
                throw new Exception("Bad metadata header sig.");
            if (metadataHeader.EntryCount > MAX_TABLE_ENTRIES)
                throw new Exception("Too many metadata entries.");
            VHDX_FILE_PARAMETERS? fileParams = null;
            UInt64? virtualDiskSize = null;
            UInt32? logicalSectorSize = null;
            for (int i = 0; i < metadataHeader.EntryCount; i++)
            {
                int readOffset = Program.SizeOf<VHDX_METADATA_TABLE_HEADER>()
                                 + i * Program.SizeOf<VHDX_METADATA_TABLE_ENTRY>();
                var entry = Program.ToStruct<VHDX_METADATA_TABLE_ENTRY>(metadataBytes, readOffset);

                if (entry.IsUser)
                {
                    if (entry.IsRequired)
                        throw new Exception($"Unknown required metadata item: {entry.ItemId}");
                    else
                        continue;
                }
                else if (entry.IsRequired && !sKnownMetadataItems.Contains(entry.ItemId))
                    throw new Exception($"Unknown required metadata item: {entry.ItemId}");

                //the ArraySegment overload of ToStruct will make sure the entry size matches the data item
                var entryBytes = new ArraySegment<byte>(metadataBytes, checked((int)entry.Offset), checked((int)entry.Length));
                if (entry.ItemId == METADATA_FILE_PARAMS)
                {
                    fileParams = Program.ToStruct<VHDX_FILE_PARAMETERS>(entryBytes);
                }
                else if (entry.ItemId == METADATA_VIRTUAL_DISK_SIZE)
                {
                    virtualDiskSize = Program.ToStruct<UInt64>(entryBytes);
                }
                else if (entry.ItemId == METADATA_LOGICAL_SECTOR_SIZE)
                {
                    logicalSectorSize = Program.ToStruct<UInt32>(entryBytes);
                }
            }

            if (!fileParams.HasValue || !virtualDiskSize.HasValue || !logicalSectorSize.HasValue)
                throw new Exception("Missing required metadata!");

            outFileParams = fileParams.Value;
            outVirtualDiskSize = checked((long)virtualDiskSize.Value);
            outLogicalSectorSize = logicalSectorSize.Value;
        }