private VhdFile Create(Stream stream, string vhdDirectory) { var reader = new BinaryReader(stream, Encoding.Unicode); try { var dataReader = new VhdDataReader(reader); var footer = new VhdFooterFactory(dataReader).CreateFooter(); VhdHeader header = null; BlockAllocationTable blockAllocationTable = null; VhdFile parent = null; if (footer.DiskType != DiskType.Fixed) { header = new VhdHeaderFactory(dataReader, footer).CreateHeader(); blockAllocationTable = new BlockAllocationTableFactory(dataReader, header).Create(); if (footer.DiskType == DiskType.Differencing) { var parentPath = vhdDirectory == null ? header.ParentPath : Path.Combine(vhdDirectory, header.GetRelativeParentPath()); parent = Create(parentPath); } } return(new VhdFile(footer, header, blockAllocationTable, parent, stream)); } catch (EndOfStreamException) { throw new VhdParsingException("unsupported format"); } }
public VhdHeader CreateHeader() { if (footer.DiskType != DiskType.Dynamic && footer.DiskType != DiskType.Differencing) { return(null); } try { var attributeHelper = new AttributeHelper <VhdHeader>(); var header = new VhdHeader(); header.Cookie = ReadHeaderCookie(attributeHelper.GetAttribute(() => header.Cookie)); header.DataOffset = ReadDataOffset(attributeHelper.GetAttribute(() => header.DataOffset)); header.TableOffset = ReadBATOffset(attributeHelper.GetAttribute(() => header.TableOffset)); header.HeaderVersion = ReaderHeaderVersion(attributeHelper.GetAttribute(() => header.HeaderVersion)); header.MaxTableEntries = ReadMaxTableEntries(attributeHelper.GetAttribute(() => header.MaxTableEntries)); header.BlockSize = ReadBlockSize(attributeHelper.GetAttribute(() => header.BlockSize)); header.CheckSum = ReadCheckSum(attributeHelper.GetAttribute(() => header.CheckSum)); header.ParentUniqueId = ReadParentUniqueId(attributeHelper.GetAttribute(() => header.ParentUniqueId)); header.ParentTimeStamp = ReadParentTimeStamp(attributeHelper.GetAttribute(() => header.ParentTimeStamp)); header.Reserverd1 = ReadReserved1(attributeHelper.GetAttribute(() => header.Reserverd1)); header.ParentPath = ReadParentPath(attributeHelper.GetAttribute(() => header.ParentPath)); header.ParentLocators = ReadParentLocators(attributeHelper.GetAttribute(() => header.ParentLocators)); header.RawData = ReadRawData(attributeHelper.GetAttribute(() => header.RawData)); return(header); } catch (EndOfStreamException e) { throw new VhdParsingException("unsupported format", e); } }
public static HardDisk Create(HardDisk hdd) { byte[] headBytes = hdd.ReadBytes(hdd.Length - 512, 512); VhdHeader head = Program.ToStructFromBigEndian <VhdHeader>(headBytes); if (head.CookieStr != "conectix") { throw new Exception("missing magic string"); } if (head.FileFormatVersion != 0x00010000) { throw new Exception("upsupported version"); } //TODO: validate checksum if (head.DiskType == DiskType.Fixed) { return(new FixedVhd(hdd, in head)); } else if (head.DiskType == DiskType.Dynamic) { return(new DynamicVhd(hdd, in head)); } else { throw new Exception("Only fixed size VHDs are supported."); } }
private IEnumerable <CompletionPort> CreateAsync(AsyncMachine <VhdFile> machine, StreamSource streamSource) { var disposer = new Action(() => { if (streamSource.DisposeOnException) { streamSource.Stream.Dispose(); } }); var reader = TryCatch(() => new BinaryReader(streamSource.Stream, Encoding.Unicode), disposer); var dataReader = TryCatch(() => new VhdDataReader(reader), disposer); var footerFactory = TryCatch(() => new VhdFooterFactory(dataReader), disposer); footerFactory.BeginCreateFooter(machine.CompletionCallback, null); yield return(CompletionPort.SingleOperation); var footer = TryCatch <VhdFooter>(footerFactory.EndCreateFooter, disposer, machine.CompletionResult); VhdHeader header = null; BlockAllocationTable blockAllocationTable = null; VhdFile parent = null; if (footer.DiskType != DiskType.Fixed) { var headerFactory = new VhdHeaderFactory(dataReader, footer); headerFactory.BeginCreateHeader(machine.CompletionCallback, null); yield return(CompletionPort.SingleOperation); header = TryCatch <VhdHeader>(headerFactory.EndCreateHeader, disposer, machine.CompletionResult); var tableFactory = new BlockAllocationTableFactory(dataReader, header); tableFactory.BeginCreate(machine.CompletionCallback, null); yield return(CompletionPort.SingleOperation); blockAllocationTable = TryCatch <BlockAllocationTable>(tableFactory.EndCreate, disposer, machine.CompletionResult); if (footer.DiskType == DiskType.Differencing) { var parentPath = streamSource.VhdDirectory == null ? header.ParentPath : Path.Combine(streamSource.VhdDirectory, header.GetRelativeParentPath()); BeginCreate(parentPath, machine.CompletionCallback, null); yield return(CompletionPort.SingleOperation); parent = TryCatch <VhdFile>(EndCreate, disposer, machine.CompletionResult); } } machine.ParameterValue = new VhdFile(footer, header, blockAllocationTable, parent, streamSource.Stream); }
private VhdFile Create(StreamSource streamSource) { var disposer = new Action(() => { if (streamSource.DisposeOnException) { streamSource.Stream.Dispose(); } }); bool throwing = false; try { var reader = new BinaryReader(streamSource.Stream, Encoding.Unicode); var dataReader = new VhdDataReader(reader); var footer = new VhdFooterFactory(dataReader).CreateFooter(); VhdHeader header = null; BlockAllocationTable blockAllocationTable = null; VhdFile parent = null; if (footer.DiskType != DiskType.Fixed) { header = new VhdHeaderFactory(dataReader, footer).CreateHeader(); blockAllocationTable = new BlockAllocationTableFactory(dataReader, header).Create(); if (footer.DiskType == DiskType.Differencing) { string parentPath = GetParentPath(streamSource.VhdDirectory, header); parent = Create(parentPath); } } return(new VhdFile(footer, header, blockAllocationTable, parent, streamSource.Stream)); } catch (Exception e) { throwing = true; throw new VhdParsingException("unsupported format", e); } finally { if (throwing) { disposer(); } } }
private string GetParentPath(string vhdDirectory, VhdHeader header) { string parentPath; if (vhdDirectory == null) { parentPath = vhdDirectory; } else { string relativeParentPath = header.GetRelativeParentPath(); if (relativeParentPath != null) { parentPath = Path.Combine(vhdDirectory, relativeParentPath); } else { parentPath = header.GetAbsoluteParentPath(); } } return(parentPath); }
public BlockAllocationTableFactory(VhdDataReader dataReader, VhdHeader header) { this.dataReader = dataReader; this.header = header; }
private IEnumerable <CompletionPort> CreateVhdHeader(AsyncMachine <VhdHeader> machine) { if (footer.DiskType != DiskType.Dynamic && footer.DiskType != DiskType.Differencing) { machine.ParameterValue = null; yield break; } var attributeHelper = new AttributeHelper <VhdHeader>(); var header = new VhdHeader(); BeginReadHeaderCookie(attributeHelper.GetAttribute(() => header.Cookie), machine.CompletionCallback, null); yield return(CompletionPort.SingleOperation); header.Cookie = TryCatch <VhdCookie>(EndReadHeaderCookie, machine.CompletionResult); BeginReadDataOffset(attributeHelper.GetAttribute(() => header.DataOffset), machine.CompletionCallback, null); yield return(CompletionPort.SingleOperation); header.DataOffset = TryCatch <long>(EndReadDataOffset, machine.CompletionResult); BeginReadBATOffset(attributeHelper.GetAttribute(() => header.TableOffset), machine.CompletionCallback, null); yield return(CompletionPort.SingleOperation); header.TableOffset = TryCatch <long>(EndReadBATOffset, machine.CompletionResult); BeginReadHeaderVersion(attributeHelper.GetAttribute(() => header.HeaderVersion), machine.CompletionCallback, null); yield return(CompletionPort.SingleOperation); header.HeaderVersion = TryCatch <VhdHeaderVersion>(EndReadHeaderVersion, machine.CompletionResult); BeginReadMaxTableEntries(attributeHelper.GetAttribute(() => header.MaxTableEntries), machine.CompletionCallback, null); yield return(CompletionPort.SingleOperation); header.MaxTableEntries = TryCatch <uint>(EndReadMaxTableEntries, machine.CompletionResult); BeginReadBlockSize(attributeHelper.GetAttribute(() => header.BlockSize), machine.CompletionCallback, null); yield return(CompletionPort.SingleOperation); header.BlockSize = TryCatch <uint>(EndReadBlockSize, machine.CompletionResult); BeginReadCheckSum(attributeHelper.GetAttribute(() => header.CheckSum), machine.CompletionCallback, null); yield return(CompletionPort.SingleOperation); header.CheckSum = TryCatch <uint>(EndReadCheckSum, machine.CompletionResult); BeginReadParentUniqueId(attributeHelper.GetAttribute(() => header.ParentUniqueId), machine.CompletionCallback, null); yield return(CompletionPort.SingleOperation); header.ParentUniqueId = TryCatch <Guid>(EndReadParentUniqueId, machine.CompletionResult); BeginReadParentTimeStamp(attributeHelper.GetAttribute(() => header.ParentTimeStamp), machine.CompletionCallback, null); yield return(CompletionPort.SingleOperation); header.ParentTimeStamp = TryCatch <DateTime>(EndReadParentTimeStamp, machine.CompletionResult); BeginReadReserved1(attributeHelper.GetAttribute(() => header.Reserverd1), machine.CompletionCallback, null); yield return(CompletionPort.SingleOperation); header.Reserverd1 = TryCatch <uint>(EndReadReserved1, machine.CompletionResult); BeginReadParentPath(attributeHelper.GetAttribute(() => header.ParentPath), machine.CompletionCallback, null); yield return(CompletionPort.SingleOperation); header.ParentPath = TryCatch <string>(EndReadParentPath, machine.CompletionResult); BeginReadParentLocators(attributeHelper.GetAttribute(() => header.ParentLocators), machine.CompletionCallback, null); yield return(CompletionPort.SingleOperation); header.ParentLocators = TryCatch <IList <ParentLocator> >(EndReadParentLocators, machine.CompletionResult); BeginReadRawData(attributeHelper.GetAttribute(() => header.RawData), machine.CompletionCallback, null); yield return(CompletionPort.SingleOperation); header.RawData = TryCatch <byte[]>(EndReadRawData, machine.CompletionResult); machine.ParameterValue = header; }