/// <exception cref="System.IO.IOException"></exception> /// <exception cref="System.IO.InvalidDataException"></exception> /// <exception cref="System.NotImplementedException"></exception> /// <exception cref="System.UnauthorizedAccessException"></exception> public VirtualHardDisk(string virtualHardDiskPath) : base(virtualHardDiskPath) { // We can't read the VHD footer using this.ReadSector() because it's out of the disk boundaries m_file = new RawDiskImage(virtualHardDiskPath, BytesPerDiskSector); byte[] buffer = m_file.ReadSector(m_file.Size / BytesPerDiskSector - 1); m_vhdFooter = new VHDFooter(buffer); if (!m_vhdFooter.IsValid) { // check to see if a header is present (dynamic VHD) and use it instead buffer = m_file.ReadSector(0); m_vhdFooter = new VHDFooter(buffer); if (!m_vhdFooter.IsValid) { throw new InvalidDataException("Invalid VHD footer"); } } if (m_vhdFooter.DiskType == VirtualHardDiskType.Fixed) { } else if (m_vhdFooter.DiskType == VirtualHardDiskType.Dynamic) { buffer = m_file.ReadSectors(1, 2); m_dynamicHeader = new DynamicDiskHeader(buffer); m_blockAllocationTable = BlockAllocationTable.ReadBlockAllocationTable(virtualHardDiskPath, m_dynamicHeader); } else { throw new NotImplementedException("Differencing VHD is not supported"); } SetGeometry(); }
/// <param name="size">In bytes</param> /// <exception cref="System.IO.IOException"></exception> /// <exception cref="System.UnauthorizedAccessException"></exception> public static VirtualHardDisk Create(string path, long size) { VHDFooter footer = new VHDFooter(); footer.OriginalSize = (ulong)size; footer.CurrentSize = (ulong)size; footer.SetCurrentTimeStamp(); footer.SetDiskGeometry((ulong)size / BytesPerDiskSector); RawDiskImage diskImage = RawDiskImage.Create(path, size + VHDFooter.Length, BytesPerDiskSector); diskImage.WriteSectors(size / BytesPerDiskSector, footer.GetBytes()); return(new VirtualHardDisk(path)); }
/// <param name="diskSize">In bytes</param> /// <exception cref="System.IO.IOException"></exception> /// <exception cref="System.UnauthorizedAccessException"></exception> public static VirtualHardDisk CreateFixedDisk(string path, long diskSize) { if (diskSize % BytesPerDiskSector > 0) { throw new ArgumentException("diskSize must be a multiple of sector size"); } VHDFooter footer = new VHDFooter(); footer.OriginalSize = (ulong)diskSize; footer.CurrentSize = (ulong)diskSize; footer.SetCurrentTimeStamp(); footer.SetDiskGeometry((ulong)diskSize / BytesPerDiskSector); RawDiskImage diskImage = RawDiskImage.Create(path, diskSize + VHDFooter.Length, BytesPerDiskSector); diskImage.WriteSectors(diskSize / BytesPerDiskSector, footer.GetBytes()); return(new VirtualHardDisk(path)); }
/// <param name="diskSize">In bytes</param> /// <exception cref="System.IO.IOException"></exception> /// <exception cref="System.UnauthorizedAccessException"></exception> public static VirtualHardDisk CreateDynamicDisk(string path, long diskSize) { const int BlockSizeInBytes = 4096 * BytesPerDiskSector; if (diskSize % BlockSizeInBytes > 0) { // All blocks within a given image must be the same size throw new ArgumentException("Dynamic VHD disk size must be a multiple of 2MiB"); } VHDFooter footer = new VHDFooter(); footer.OriginalSize = (ulong)diskSize; footer.CurrentSize = (ulong)diskSize; footer.SetCurrentTimeStamp(); footer.SetDiskGeometry((ulong)diskSize / BytesPerDiskSector); footer.DiskType = VirtualHardDiskType.Dynamic; DynamicDiskHeader header = new DynamicDiskHeader(); header.TableOffset = VHDFooter.Length + DynamicDiskHeader.Length; header.BlockSize = BlockSizeInBytes; header.MaxTableEntries = (uint)Math.Ceiling((double)diskSize / BlockSizeInBytes); BlockAllocationTable blockAllocationTable = new BlockAllocationTable(header.MaxTableEntries); byte[] footerBytes = footer.GetBytes(); byte[] headerBytes = header.GetBytes(); byte[] blockAllocationTableBytes = blockAllocationTable.GetBytes(); int fileSize = VHDFooter.Length + DynamicDiskHeader.Length + blockAllocationTableBytes.Length + VHDFooter.Length; RawDiskImage diskImage = RawDiskImage.Create(path, fileSize, BytesPerDiskSector); diskImage.WriteSectors(0, footerBytes); diskImage.WriteSectors(1, headerBytes); diskImage.WriteSectors(3, blockAllocationTableBytes); diskImage.WriteSectors(fileSize / BytesPerDiskSector - 1, footerBytes); return(new VirtualHardDisk(path)); }
/// <param name="length">In bytes</param> /// <exception cref="System.IO.IOException"></exception> /// <exception cref="System.UnauthorizedAccessException"></exception> public static VirtualHardDisk Create(string path, long length) { bool hasManageVolumePrivilege = SecurityUtils.ObtainManageVolumePrivilege(); FileStream stream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None); try { stream.SetLength(length + 512); // VHD footer is 512 bytes if (hasManageVolumePrivilege) { FileStreamUtils.SetValidLength(stream, length + 512); } } catch (IOException) { stream.Close(); try { // Delete the incomplete file File.Delete(path); } catch (IOException) { } throw; } VHDFooter footer = new VHDFooter(); footer.OriginalSize = (ulong)length; footer.CurrentSize = (ulong)length; footer.SetCurrentTimeStamp(); footer.SetDiskGeometry((ulong)length / DiskImage.DEFAULT_BYTES_PER_SECTOR); stream.Seek(length, SeekOrigin.Begin); stream.Write(footer.GetBytes(), 0, VHDFooter.Length); stream.Close(); return(new VirtualHardDisk(path)); }