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; }
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; }