Beispiel #1
0
        /// <summary>
        /// Open the specified disk image file.
        /// </summary>
        /// <param name="imageFile">The vhd or vhdx file to open.</param>
        /// <param name="openReadOnly">Open as read-only.</param>
        /// <returns></returns>
        /// <remarks></remarks>
        public bool Open(string imageFile, bool openReadOnly)
        {
            bool   OpenRet = default;
            string ext     = Path.GetExtension(imageFile).ToLower();
            VIRTUAL_STORAGE_TYPE vst;

            if (_Handle != IntPtr.Zero)
            {
                Close();
            }

            var vdp1 = new OPEN_VIRTUAL_DISK_PARAMETERS_V1();
            var vdp2 = new OPEN_VIRTUAL_DISK_PARAMETERS_V2();

            uint r;

            var am = VIRTUAL_DISK_ACCESS_MASK.VIRTUAL_DISK_ACCESS_GET_INFO | VIRTUAL_DISK_ACCESS_MASK.VIRTUAL_DISK_ACCESS_DETACH;

            if (!openReadOnly)
            {
                am = am | VIRTUAL_DISK_ACCESS_MASK.VIRTUAL_DISK_ACCESS_ATTACH_RW;
            }

            vdp2.Version        = OPEN_VIRTUAL_DISK_VERSION.OPEN_VIRTUAL_DISK_VERSION_2;
            vdp2.ResiliencyGuid = Guid.NewGuid();
            vdp2.ReadOnly       = false;
            vdp2.GetInfoOnly    = false;

            vdp1.RWDepth = 1U;
            vdp1.Version = OPEN_VIRTUAL_DISK_VERSION.OPEN_VIRTUAL_DISK_VERSION_1;

            vst.VendorId = VirtDisk.VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT;

            switch (ext.ToLower() ?? "")
            {
            case ".vhd":
                vst.DeviceId = VirtDisk.VIRTUAL_STORAGE_TYPE_DEVICE_VHD;
                r            = VirtDisk.OpenVirtualDisk(vst, imageFile, am, OPEN_VIRTUAL_DISK_FLAG.OPEN_VIRTUAL_DISK_FLAG_NONE, vdp1, ref _Handle);
                break;

            case ".vhdx":
                vst.DeviceId = VirtDisk.VIRTUAL_STORAGE_TYPE_DEVICE_VHDX;
                r            = VirtDisk.OpenVirtualDisk(vst, imageFile, am, OPEN_VIRTUAL_DISK_FLAG.OPEN_VIRTUAL_DISK_FLAG_NONE, vdp1, ref _Handle);
                break;

            default:
                return(false);
            }

            if (r == 0L)
            {
                _ImageFile = imageFile;
            }

            OpenRet = r == 0L;
            return(OpenRet);
        }
Beispiel #2
0
        /// <summary>
        /// Dismount the drive.
        /// </summary>
        /// <returns></returns>
        /// <remarks></remarks>
        public bool Detach()
        {
            if (!Attached)
            {
                return(false);
            }

            uint r = VirtDisk.DetachVirtualDisk(_Handle, DETACH_VIRTUAL_DISK_FLAG.DETACH_VIRTUAL_DISK_FLAG_NONE, 0U);

            return(r == 0L);
        }
Beispiel #3
0
        public override bool UnmountCurrentDiskImage()
        {
            if (mountedHandle != null)
            {
                Win32Error error = VirtDisk.DetachVirtualDisk(mountedHandle, VirtDisk.DETACH_VIRTUAL_DISK_FLAG.DETACH_VIRTUAL_DISK_FLAG_NONE, 0);

                if (error.Failed)
                {
                    AutoMounter.Plugin.LogInfo($"WinVirtDisk: Failed to unmount disk from system {mountedHandle.ToString()}, {error.ToString()}");
                    AutoMounter.API.Dialogs.ShowErrorMessage("Failed to unmount disk from system", "AutoMounter");
                }
                mountedHandle.Close();
                mountedHandle = null;
            }
            return(true);
        }
Beispiel #4
0
        /// <summary>
        /// Mount the virtual drive, permanently.  The virtual drive will stay mounted beyond the lifetime of this instance.
        /// </summary>
        /// <param name="makePermanent"></param>
        /// <returns></returns>
        /// <remarks></remarks>
        public bool Attach(bool makePermanent)
        {
            if (_Handle == IntPtr.Zero || Attached)
            {
                return(false);
            }

            var mm = new MemPtr(8L);

            mm.ByteAt(0L) = 1;

            uint r = VirtDisk.AttachVirtualDisk(_Handle, IntPtr.Zero, makePermanent ? ATTACH_VIRTUAL_DISK_FLAG.ATTACH_VIRTUAL_DISK_FLAG_PERMANENT_LIFETIME : ATTACH_VIRTUAL_DISK_FLAG.ATTACH_VIRTUAL_DISK_FLAG_NONE, 0U, mm.Handle, IntPtr.Zero);

            mm.Free();

            return(r == 0L);
        }
Beispiel #5
0
        /// <summary>
        /// Creates a new virtual disk device file.
        /// </summary>
        /// <param name="imageFile">Full path to the destination image, including file extension (.vhd or .vhdx)</param>
        /// <param name="diskSize">The virtual size of the new disk.</param>
        /// <param name="fixedSize">Indicates whether or not the size is fixed or virtual.</param>
        /// <param name="id">Receives the Guid for the new drive.</param>
        /// <param name="resiliencyId">The Resiliancy Guid.</param>
        /// <param name="blockSize">The transfer block size.</param>
        /// <param name="sectorSize">The virtual sector size.</param>
        /// <param name="sourcePath">The cloning source (if any).</param>
        /// <param name="sourceDiskType">The cloning source disk type (if applicable).</param>
        /// <returns>A new VirtualDisk object.</returns>
        /// <remarks></remarks>
        public static VirtualDisk Create(string imageFile, long diskSize, bool fixedSize, ref Guid id, ref Guid resiliencyId, int blockSize = 2097152, int sectorSize = 512, string sourcePath = null, VirtualStorageType sourceDiskType = VirtualStorageType.Unknown)
        {
            VirtualDisk CreateRet = default;

            string ext = Path.GetExtension(imageFile).ToLower();

            var cp2 = new CREATE_VIRTUAL_DISK_PARAMETERS_V2();
            var cp1 = new CREATE_VIRTUAL_DISK_PARAMETERS_V1();

            VIRTUAL_STORAGE_TYPE vst;

            var    r         = default(uint);
            IntPtr handleNew = new IntPtr();

            vst.VendorId = VirtDisk.VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT;

            switch (ext ?? "")
            {
            case ".vhd":
            {
                cp1.BlockSizeInBytes  = (uint)blockSize;
                cp1.Version           = CREATE_VIRTUAL_DISK_VERSION.CREATE_VIRTUAL_DISK_VERSION_1;
                cp1.MaximumSize       = (ulong)diskSize;
                cp1.UniqueId          = id;
                cp1.SourcePath        = sourcePath;
                cp1.SectorSizeInBytes = 512;
                vst.DeviceId          = VirtDisk.VIRTUAL_STORAGE_TYPE_DEVICE_VHD;

                r = VirtDisk.CreateVirtualDisk(vst, imageFile, VIRTUAL_DISK_ACCESS_MASK.VIRTUAL_DISK_ACCESS_ALL, IntPtr.Zero, fixedSize ? CREATE_VIRTUAL_DISK_FLAGS.CREATE_VIRTUAL_DISK_FLAG_FULL_PHYSICAL_ALLOCATION : CREATE_VIRTUAL_DISK_FLAGS.CREATE_VIRTUAL_DISK_FLAG_NONE, 0U, cp1, IntPtr.Zero, ref handleNew);

                break;
            }

            case ".vhdx":
            {
                cp2.BlockSizeInBytes = (uint)blockSize;
                cp2.Version          = CREATE_VIRTUAL_DISK_VERSION.CREATE_VIRTUAL_DISK_VERSION_2;
                cp2.MaximumSize      = (ulong)diskSize;
                cp2.UniqueId         = id;
                cp2.SourcePath       = sourcePath;
                if (sourcePath is object)
                {
                    cp2.SourceVirtualStorageType.DeviceId = (uint)sourceDiskType;
                    cp2.SourceVirtualStorageType.VendorId = VirtDisk.VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT;
                }

                int x = Marshal.SizeOf(cp2);

                cp2.SectorSizeInBytes = sectorSize;

                if (resiliencyId != Guid.Empty)
                {
                    cp2.ResiliencyGuid = resiliencyId;
                    // Else
                    // cp2.ResiliencyGuid = Guid.NewGuid
                    // resiliencyId = cp2.ResiliencyGuid
                }

                cp2.OpenFlags = OPEN_VIRTUAL_DISK_FLAG.OPEN_VIRTUAL_DISK_FLAG_NONE;
                vst.DeviceId  = VirtDisk.VIRTUAL_STORAGE_TYPE_DEVICE_VHDX;

                r = VirtDisk.CreateVirtualDisk(vst, imageFile, VIRTUAL_DISK_ACCESS_MASK.VIRTUAL_DISK_ACCESS_NONE, IntPtr.Zero, fixedSize ? CREATE_VIRTUAL_DISK_FLAGS.CREATE_VIRTUAL_DISK_FLAG_FULL_PHYSICAL_ALLOCATION : CREATE_VIRTUAL_DISK_FLAGS.CREATE_VIRTUAL_DISK_FLAG_NONE, 0U, cp2, IntPtr.Zero, ref handleNew);
                break;
            }
            }

            if (r != 0L)
            {
                CreateRet = null;
            }
            else
            {
                CreateRet            = new VirtualDisk();
                CreateRet._Handle    = handleNew;
                CreateRet._ImageFile = imageFile;
            }

            return(CreateRet);
        }
Beispiel #6
0
        public override bool MountDiskImage()
        {
            if (Path.GetExtension(DiskImage).ToLower() != ".iso")
            {
                AutoMounter.Plugin.LogInfo($"WinVirtDisk: Failed to open ISO as VirtualDisk, not an ISO - {DiskImage}");
                return(false);
            }

            // Check file exists! Probably should return some nice error message...
            if (!File.Exists(DiskImage))
            {
                AutoMounter.Plugin.LogInfo($"WinVirtDisk: Failed to open ISO as VirtualDisk, ISO does not exist on disk {DiskImage}");
                return(false);
            }

            if (!AutoMountHelpers.IsDriveLetterFree(RequestedDriveLetter))
            {
                AutoMounter.Plugin.LogInfo($"WinVirtDisk: Failed to open ISO as VirtualDisk, Drive Letter in use {RequestedDriveLetter}");
                AutoMounter.API.Dialogs.ShowErrorMessage("Failed to open ISO as VirtualDisk, Drive Letter is in use", "AutoMounter");
                return(false);
            }


            VirtDisk.VIRTUAL_STORAGE_TYPE type = new VirtDisk.VIRTUAL_STORAGE_TYPE(VirtDisk.VIRTUAL_STORAGE_TYPE_DEVICE_TYPE.VIRTUAL_STORAGE_TYPE_DEVICE_ISO);
            Win32Error error = VirtDisk.OpenVirtualDisk(
                ref type,
                DiskImage,
                VirtDisk.VIRTUAL_DISK_ACCESS_MASK.VIRTUAL_DISK_ACCESS_READ,
                VirtDisk.OPEN_VIRTUAL_DISK_FLAG.OPEN_VIRTUAL_DISK_FLAG_NONE,
                null,
                out mountedHandle);

            // Opened successfully
            if (error.Succeeded)
            {
                VirtDisk.ATTACH_VIRTUAL_DISK_PARAMETERS param = VirtDisk.ATTACH_VIRTUAL_DISK_PARAMETERS.Default;

                // Attach disk (no drive letter)
                error = VirtDisk.AttachVirtualDisk(
                    mountedHandle,
                    NullSafeHandle.Null(),
                    VirtDisk.ATTACH_VIRTUAL_DISK_FLAG.ATTACH_VIRTUAL_DISK_FLAG_NO_DRIVE_LETTER |
                    VirtDisk.ATTACH_VIRTUAL_DISK_FLAG.ATTACH_VIRTUAL_DISK_FLAG_READ_ONLY, // NO_DRIVE_LETTER at a later date
                    0,
                    ref param,
                    IntPtr.Zero);

                if (error.Succeeded)
                {
                    // Try and assign the requested drive letter to the mounted image
                    if (AssignDriveLetter(RequestedDriveLetter, mountedHandle))
                    {
                        return(true);
                    }
                    else
                    {
                        AutoMounter.Plugin.LogInfo($"WinVirtDisk: Failed to open ISO as VirtualDisk, Unable to mount to drive letter {RequestedDriveLetter}");
                        AutoMounter.API.Dialogs.ShowErrorMessage("Failed to open ISO as VirtualDisk, Unable to mount to assigned drive letter", "AutoMounter");
                        UnmountCurrentDiskImage();
                        return(false);
                    }
                }
                else
                {
                    AutoMounter.Plugin.LogInfo($"WinVirtDisk: Failed to open ISO as VirtualDisk {error.ToString()}, AttachVirtualDisk Fail");
                    AutoMounter.API.Dialogs.ShowErrorMessage("Failed to open ISO as VirtualDisk, AttachVirtualDisk Fail", "AutoMounter");
                    UnmountCurrentDiskImage();
                    return(false);
                }
            }
            else
            {
                AutoMounter.Plugin.LogInfo($"WinVirtDisk: Failed to open ISO as VirtualDisk {error.ToString()}, OpenVirtualDisk Fail");
                AutoMounter.API.Dialogs.ShowErrorMessage("Failed to open ISO as VirtualDisk, OpenVirtualDisk Fail", "AutoMounter");
                UnmountCurrentDiskImage();
                return(false);
            }
        }
Beispiel #7
0
        private bool AssignDriveLetter(string driveLetter, SafeFileHandle mountedHandle)
        {
            int           buffsize     = 128;
            StringBuilder physicalPath = new StringBuilder(128);
            Win32Error    error        = VirtDisk.GetVirtualDiskPhysicalPath(mountedHandle, ref buffsize, physicalPath);
            // Find number on end of physical drive string \\.\CDROM1
            int driveNumber = Convert.ToInt32(Regex.Match(physicalPath.ToString(), @"\d+").Value);
            STORAGE_DEVICE_NUMBER deviceNumber = new STORAGE_DEVICE_NUMBER();
            // driveNumber should now contain the virtual CDROM drive number

            StringBuilder volumeName = new StringBuilder(128);

            Kernel32.SafeVolumeSearchHandle srchHandle = Kernel32.FindFirstVolume(volumeName, (uint)128);


            bool found = false;

            while (!found)
            {
                if (volumeName[volumeName.Length - 1] == '\\')
                {
                    volumeName.Remove(volumeName.Length - 1, 1);
                }

                SafeFileHandle fileHandle = Kernel32.CreateFile(volumeName.ToString(), Kernel32.FileAccess.FILE_LIST_DIRECTORY, FileShare.Read, null, FileMode.Open, 0);
                if (!fileHandle.IsInvalid)
                {
                    // Valid
                    Kernel32.DeviceIoControl <STORAGE_DEVICE_NUMBER>(fileHandle, Kernel32.IOControlCode.IOCTL_STORAGE_GET_DEVICE_NUMBER, out deviceNumber);
                    // Check device stats, should be a CDROM drive, then we should be ok to assume the disk number is ours...
                    if (deviceNumber.deviceType == 2)
                    {
                        // Is a CDROM drive
                        if (deviceNumber.deviceNumber == driveNumber)
                        {
                            // Got it!
                            break;
                        }
                    }
                }

                if (!Kernel32.FindNextVolume(srchHandle, volumeName, (uint)128))
                {
                    break;
                }
            }

            srchHandle.Close();
            // volumeName is now our mounted CDROM drive

            // WinAPI requires backslash on back of drive letter
            if (!driveLetter.Contains("\\"))
            {
                driveLetter += "\\";
            }

            bool mounted = Kernel32.SetVolumeMountPoint(driveLetter, volumeName.Append("\\").ToString());

            if (mounted)
            {
                AutoMounter.Plugin.LogInfo($"WinVirtDisk: Mounted ISO to {driveLetter} on device {volumeName}");
                return(true);
            }
            else
            {
                AutoMounter.Log.Info("AutoMounter: Failed setting volume mount point");
                return(false);
            }
        }