private void Create(VirtualDiskType type, long size, VirtualDiskCreateOptions options, int blockSize, int sectorSize, bool createAsync) { var parameters = new NativeMethods.CREATE_VIRTUAL_DISK_PARAMETERS(); parameters.Version = NativeMethods.CREATE_VIRTUAL_DISK_VERSION.CREATE_VIRTUAL_DISK_VERSION_1; if (blockSize == 0) { //parameters.Version1.BlockSizeInBytes = NativeMethods.CREATE_VIRTUAL_DISK_PARAMETERS_DEFAULT_BLOCK_SIZE; //blocks if you set it parameters.Version1.BlockSizeInBytes = 0; } else { parameters.Version1.BlockSizeInBytes = blockSize; } parameters.Version1.MaximumSize = size; parameters.Version1.ParentPath = IntPtr.Zero; if (sectorSize == 0) { parameters.Version1.SectorSizeInBytes = NativeMethods.CREATE_VIRTUAL_DISK_PARAMETERS_DEFAULT_SECTOR_SIZE; } else { parameters.Version1.SectorSizeInBytes = sectorSize; } parameters.Version1.SourcePath = IntPtr.Zero; parameters.Version1.UniqueId = Guid.Empty; var storageType = new NativeMethods.VIRTUAL_STORAGE_TYPE(); switch (type) { case VirtualDiskType.AutoDetect: if (this.FileName.EndsWith(".iso", StringComparison.OrdinalIgnoreCase)) { throw new InvalidOperationException("Cannot create iso file."); } else if (this.FileName.EndsWith(".vhdx", StringComparison.OrdinalIgnoreCase)) { storageType.DeviceId = NativeMethods.VIRTUAL_STORAGE_TYPE_DEVICE_VHDX; } else { storageType.DeviceId = NativeMethods.VIRTUAL_STORAGE_TYPE_DEVICE_VHD; } break; case VirtualDiskType.Vhd: storageType.DeviceId = NativeMethods.VIRTUAL_STORAGE_TYPE_DEVICE_VHD; break; case VirtualDiskType.Vhdx: storageType.DeviceId = NativeMethods.VIRTUAL_STORAGE_TYPE_DEVICE_VHDX; break; case VirtualDiskType.Iso: throw new InvalidOperationException("Cannot create iso file."); } storageType.VendorId = NativeMethods.VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT; int res; if (createAsync) { this._createOverlapEvent = new ManualResetEvent(false); this._createOverlap = new NativeOverlapped(); this._createOverlap.OffsetLow = 0; this._createOverlap.OffsetHigh = 0; #pragma warning disable 0618 this._createOverlap.EventHandle = this._createOverlapEvent.Handle; #pragma warning restore 0618 res = NativeMethods.CreateVirtualDisk(ref storageType, this.FileName, NativeMethods.VIRTUAL_DISK_ACCESS_MASK.VIRTUAL_DISK_ACCESS_ALL, IntPtr.Zero, (NativeMethods.CREATE_VIRTUAL_DISK_FLAG)options, 0, ref parameters, ref _createOverlap, ref _handle); } else { res = NativeMethods.CreateVirtualDisk(ref storageType, this.FileName, NativeMethods.VIRTUAL_DISK_ACCESS_MASK.VIRTUAL_DISK_ACCESS_ALL, IntPtr.Zero, (NativeMethods.CREATE_VIRTUAL_DISK_FLAG)options, 0, ref parameters, IntPtr.Zero, ref _handle); } if (res == NativeMethods.ERROR_SUCCESS) { } else if (res == NativeMethods.ERROR_IO_PENDING) { } else { _handle.SetHandleAsInvalid(); if ((res == NativeMethods.ERROR_FILE_NOT_FOUND) || (res == NativeMethods.ERROR_PATH_NOT_FOUND)) { throw new FileNotFoundException("File not found."); } else if (res == NativeMethods.ERROR_FILE_CORRUPT) { throw new InvalidDataException("File type not recognized."); } else if (res == NativeMethods.ERROR_FILE_EXISTS) { throw new IOException("File already exists."); } else if (res == NativeMethods.ERROR_FILE_SYSTEM_LIMITATION) { throw new IOException("Virtual disk creation could not be completed due to a file system limitation."); } else if (res == NativeMethods.ERROR_INVALID_PARAMETER) { throw new ArgumentException("Invalid parameter.", "size"); } else { throw new Win32Exception(res); } } }
/// <summary> /// Opens connection to file. /// </summary> /// <param name="fileAccess">Defines required access.</param> /// <param name="type">Disk type.</param> /// <exception cref="System.ComponentModel.Win32Exception">Native error.</exception> /// <exception cref="System.IO.FileNotFoundException">File not found.</exception> /// <exception cref="System.IO.InvalidDataException">File type not recognized.</exception> private void Open(VirtualDiskAccessMask fileAccess, VirtualDiskType type) { var parameters = new NativeMethods.OPEN_VIRTUAL_DISK_PARAMETERS(); parameters.Version = NativeMethods.OPEN_VIRTUAL_DISK_VERSION.OPEN_VIRTUAL_DISK_VERSION_1; parameters.Version1.RWDepth = NativeMethods.OPEN_VIRTUAL_DISK_RW_DEPTH_DEFAULT; var storageType = new NativeMethods.VIRTUAL_STORAGE_TYPE(); switch (type) { case VirtualDiskType.AutoDetect: if (this.FileName.EndsWith(".iso", StringComparison.OrdinalIgnoreCase)) { storageType.DeviceId = NativeMethods.VIRTUAL_STORAGE_TYPE_DEVICE_ISO; fileAccess = ((fileAccess & VirtualDiskAccessMask.GetInfo) == VirtualDiskAccessMask.GetInfo) ? VirtualDiskAccessMask.GetInfo : 0; fileAccess |= VirtualDiskAccessMask.AttachReadOnly; this.DiskType = VirtualDiskType.Iso; } else if (this.FileName.EndsWith(".vhdx", StringComparison.OrdinalIgnoreCase)) { storageType.DeviceId = NativeMethods.VIRTUAL_STORAGE_TYPE_DEVICE_VHDX; this.DiskType = VirtualDiskType.Vhdx; } else { storageType.DeviceId = NativeMethods.VIRTUAL_STORAGE_TYPE_DEVICE_VHD; this.DiskType = VirtualDiskType.Vhd; } break; case VirtualDiskType.Iso: storageType.DeviceId = NativeMethods.VIRTUAL_STORAGE_TYPE_DEVICE_ISO; fileAccess = ((fileAccess & VirtualDiskAccessMask.GetInfo) == VirtualDiskAccessMask.GetInfo) ? VirtualDiskAccessMask.GetInfo : 0; fileAccess |= VirtualDiskAccessMask.AttachReadOnly; this.DiskType = VirtualDiskType.Iso; break; case VirtualDiskType.Vhd: storageType.DeviceId = NativeMethods.VIRTUAL_STORAGE_TYPE_DEVICE_VHD; this.DiskType = VirtualDiskType.Vhd; break; case VirtualDiskType.Vhdx: storageType.DeviceId = NativeMethods.VIRTUAL_STORAGE_TYPE_DEVICE_VHDX; this.DiskType = VirtualDiskType.Vhdx; break; } storageType.VendorId = NativeMethods.VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT; int res = NativeMethods.OpenVirtualDisk(ref storageType, this.FileName, (NativeMethods.VIRTUAL_DISK_ACCESS_MASK)fileAccess, NativeMethods.OPEN_VIRTUAL_DISK_FLAG.OPEN_VIRTUAL_DISK_FLAG_NONE, ref parameters, ref _handle); if (res == NativeMethods.ERROR_SUCCESS) { } else { _handle.SetHandleAsInvalid(); if ((res == NativeMethods.ERROR_FILE_NOT_FOUND) || (res == NativeMethods.ERROR_PATH_NOT_FOUND)) { throw new FileNotFoundException("File not found."); } else if (res == NativeMethods.ERROR_ACCESS_DENIED) { throw new IOException("Access is denied."); } else if (res == NativeMethods.ERROR_FILE_CORRUPT) { throw new InvalidDataException("File type not recognized."); } else { throw new Win32Exception(res); } } }
public void CreateAsync(long size, VirtualDiskCreateOptions options, int blockSize, int sectorSize, VirtualDiskType type) { this.Create(type, size, options, blockSize, sectorSize, true); }