I am trying to mount a Virtual Hard Drive (.VHD) using the Windows 7 API function, but I can't find the relevant function, does one exist?
I am programming in C++ using Visual Studio 2010, for information.
Thanks in advance ;)
I am trying to mount a Virtual Hard Drive (.VHD) using the Windows 7 API function, but I can't find the relevant function, does one exist?
I am programming in C++ using Visual Studio 2010, for information.
Thanks in advance ;)
This is an old question but it still has no answer so I'll provide one in case someone stumble upon it like I did.
For the complete Reference on MSDN [VHD Reference]: http://msdn.microsoft.com/en-us/library/windows/desktop/dd323700(v=vs.85).aspx
OPEN_VIRTUAL_DISK_PARAMETERS openParameters;
openParameters.Version = OPEN_VIRTUAL_DISK_VERSION_1;
openParameters.Version1.RWDepth = OPEN_VIRTUAL_DISK_RW_DEPTH_DEFAULT;
VIRTUAL_STORAGE_TYPE storageType;
storageType.DeviceID = VIRTUAL_STORAGE_TYPE_DEVICE_VHD;
storageType.VendorId = VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT;
ATTACH_VIRTUAL_DISK_PARAMETERS attachParameters;
attachParameters.Version = ATTACH_VIRTUAL_DISK_VERSION_1;
HANDLE vhdHandle;
if (OpenVirtualDisk(&openStorageType, "{VHD PATH GOES HERE}",
VIRTUAL_DISK_ACCESS_ALL, OPEN_VIRTUAL_DISK_FLAG_NONE,
&openParameters, &vhdHandle) != ERROR_SUCCESS) {
// If return value of OpenVirtualDisk isn't ERROR_SUCCESS, there was a problem opening the VHD
}
// Warning: AttachVirtualDisk requires elevation
if (AttachVirtualDisk(vhdHandle, 0, ATTACH_VIRTUAL_DISK_FLAG_PERMANENT_LIFETIME,
0, &attachParameters, 0) != ERROR_SUCCESS) {
// If return value of AttachVirtualDisk isn't ERROR_SUCCESS, there was a problem attach the disk
}
VHD successfully attached, now it'll show up like any other physical disks and a drive letter will automatically be assigned to the volume(s) contained in the VHD. If you'd like to choose what drive letter is used to mount it, keep reading.
First, add the ATTACH_VIRTUAL_DISK_FLAG_NO_DRIVE_LETTER
flag to your AttachVirtualDisk call so it won't do this automatic letter assigning. Next, you'll have to find the volume path of the VHD volumes [it has this format: \\?\Volume{GUID}]:
wchar_t physicalDrive[MAX_PATH];
ULONG bufferSize = sizeof(physicalDrive);
GetVirtualDiskPhysicalPath(vhdHandle, &bufferSize, physicalDrive);
Now you'll have the physical path of your attached VHD in physical drive in the following format: \\.\PhysicalDrive# where # is the drive number you'll need to find your VHD volumes with FindFirstVolume/FindNextVolume. Extract the number and convert it to an integer and you'll be ready for the next piece of code:
char volumeName[MAX_PATH];
DWORD bytesReturned;
VOLUME_DISK_EXTENTS diskExtents;
HANDLE hFVol = FindFirstVolume(volumeName, sizeof(volumeName));
bool hadTrailingBackslash = false;
do {
// I had a problem where CreateFile complained about the trailing \ and
// SetVolumeMountPoint desperately wanted the backslash there. I ended up
// doing this to get it working but I'm not a fan and I'd greatly
// appreciate it if someone has any further info on this matter
int backslashPos = strlen(volumeName) - 1;
if (hadTrailingBackslash = volumeName[backslashPos] == '\\') {
volumeName[backslashPos] = 0;
}
HANDLE hVol = CreateFile(volumeName, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if (hVol == INVALID_HANDLE_VALUE) {
return;
}
DeviceIoControl(hVol, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL,
0, &diskExtents, sizeof(diskExtents), &bytesReturned, NULL);
// If the volume were to span across multiple physical disks, you'd find
// more than one Extents here but we don't have to worry about that with VHD
// Note that 'driveNumber' would be the integer you extracted out of
// 'physicalDrive' in the previous snippet
if (diskExtents.Extents[0].DiskNumber == driveNumber) {
if (hadTrailingBackslash) {
volumeName[backslashPos] = '\\';
}
// Found volume that's on the VHD, let's mount it with a letter of our choosing.
// Warning: SetVolumeMountPoint requires elevation
SetVolumeMountPoint("H:\\", volumeName);
}
} while (FindNextVolume(hFVol, volumeName, sizeof(volumeName)));
FindVolumeClose(hFVol);
Don't forget these includes and link to this library:
#define WINVER _WIN32_WINNT_WIN7
#include <windows.h>
#include <winioctl.h>
#include <virtdisk.h>
#pragma comment(lib, "virtdisk.lib")
Disclaimer: This is something I was doing in a C# codebase, I translated the code to C/C++ because of the question but haven't tried to actually compile it. If you find errors in the code, please edit it or let me know so I can do it.
Edits: Typos, includes and lib, forgot FindVolumeClose, elevation warnings
As requested, I'm posting the C# code. For more information, see my other answer. The code uses the same API from virtdisk.dll, I don't think it's possible to do with the managed API but if I'm wrong please let me know.
Alright first thing first, interop declarations:
private const Int32 ERROR_SUCCESS = 0;
private const int OPEN_VIRTUAL_DISK_RW_DEPTH_DEFAULT = 1;
private const int VIRTUAL_STORAGE_TYPE_DEVICE_VHD = 2;
private IntPtr INVALID_HANDLE_VALUE = (IntPtr) (-1);
private static readonly Guid VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT = new Guid("EC984AEC-A0F9-47e9-901F-71415A66345B");
enum ComClassContext : uint {
CLSCTX_INPROC_SERVER = 0x1,
CLSCTX_INPROC_HANDLER = 0x2,
CLSCTX_LOCAL_SERVER = 0x4,
CLSCTX_INPROC_SERVER16 = 0x8,
CLSCTX_REMOTE_SERVER = 0x10,
CLSCTX_INPROC_HANDLER16 = 0x20,
CLSCTX_RESERVED1 = 0x40,
CLSCTX_RESERVED2 = 0x80,
CLSCTX_RESERVED3 = 0x100,
CLSCTX_RESERVED4 = 0x200,
CLSCTX_NO_CODE_DOWNLOAD = 0x400,
CLSCTX_RESERVED5 = 0x800,
CLSCTX_NO_CUSTOM_MARSHAL = 0x1000,
CLSCTX_ENABLE_CODE_DOWNLOAD = 0x2000,
CLSCTX_NO_FAILURE_LOG = 0x4000,
CLSCTX_DISABLE_AAA = 0x8000,
CLSCTX_ENABLE_AAA = 0x10000,
CLSCTX_FROM_DEFAULT_CONTEXT = 0x20000,
CLSCTX_ACTIVATE_32_BIT_SERVER = 0x40000,
CLSCTX_ACTIVATE_64_BIT_SERVER = 0x80000,
CLSCTX_ENABLE_CLOAKING = 0x100000,
CLSCTX_APPCONTAINER = 0x400000,
CLSCTX_ACTIVATE_AAA_AS_IU = 0x800000,
CLSCTX_PS_DLL = 0x80000000
};
private enum IO_CONTROL_CODE : uint {
GET_VOLUME_DISK_EXTENTS = 5636096,
STORAGE_DEVICE_NUMBER = 2953344
}
private enum ATTACH_VIRTUAL_DISK_FLAG : int {
ATTACH_VIRTUAL_DISK_FLAG_NONE = 0x00000000,
ATTACH_VIRTUAL_DISK_FLAG_READ_ONLY = 0x00000001,
ATTACH_VIRTUAL_DISK_FLAG_NO_DRIVE_LETTER = 0x00000002,
ATTACH_VIRTUAL_DISK_FLAG_PERMANENT_LIFETIME = 0x00000004,
ATTACH_VIRTUAL_DISK_FLAG_NO_LOCAL_HOST = 0x00000008
}
private enum ATTACH_VIRTUAL_DISK_VERSION : int {
ATTACH_VIRTUAL_DISK_VERSION_UNSPECIFIED = 0,
ATTACH_VIRTUAL_DISK_VERSION_1 = 1
}
private enum OPEN_VIRTUAL_DISK_FLAG : int {
OPEN_VIRTUAL_DISK_FLAG_NONE = 0x00000000,
OPEN_VIRTUAL_DISK_FLAG_NO_PARENTS = 0x00000001,
OPEN_VIRTUAL_DISK_FLAG_BLANK_FILE = 0x00000002,
OPEN_VIRTUAL_DISK_FLAG_BOOT_DRIVE = 0x00000004
}
private enum OPEN_VIRTUAL_DISK_VERSION : int {
OPEN_VIRTUAL_DISK_VERSION_1 = 1
}
private enum VIRTUAL_DISK_ACCESS_MASK : int {
VIRTUAL_DISK_ACCESS_ATTACH_RO = 0x00010000,
VIRTUAL_DISK_ACCESS_ATTACH_RW = 0x00020000,
VIRTUAL_DISK_ACCESS_DETACH = 0x00040000,
VIRTUAL_DISK_ACCESS_GET_INFO = 0x00080000,
VIRTUAL_DISK_ACCESS_CREATE = 0x00100000,
VIRTUAL_DISK_ACCESS_METAOPS = 0x00200000,
VIRTUAL_DISK_ACCESS_READ = 0x000d0000,
VIRTUAL_DISK_ACCESS_ALL = 0x003f0000,
VIRTUAL_DISK_ACCESS_WRITABLE = 0x00320000
}
private enum DETACH_VIRTUAL_DISK_FLAG : int {
DETACH_VIRTUAL_DISK_FLAG_NONE = 0x00000000
}
private enum GET_VIRTUAL_DISK_INFO_VERSION {
GET_VIRTUAL_DISK_INFO_UNSPECIFIED = 0,
GET_VIRTUAL_DISK_INFO_SIZE = 1,
GET_VIRTUAL_DISK_INFO_IDENTIFIER = 2,
GET_VIRTUAL_DISK_INFO_PARENT_LOCATION = 3,
GET_VIRTUAL_DISK_INFO_PARENT_IDENTIFIER = 4,
GET_VIRTUAL_DISK_INFO_PARENT_TIMESTAMP = 5,
GET_VIRTUAL_DISK_INFO_VIRTUAL_STORAGE_TYPE = 6,
GET_VIRTUAL_DISK_INFO_PROVIDER_SUBTYPE = 7,
GET_VIRTUAL_DISK_INFO_IS_4K_ALIGNED = 8,
GET_VIRTUAL_DISK_INFO_PHYSICAL_DISK = 9,
GET_VIRTUAL_DISK_INFO_VHD_PHYSICAL_SECTOR_SIZE = 10, // 0xA
GET_VIRTUAL_DISK_INFO_SMALLEST_SAFE_VIRTUAL_SIZE = 11,
GET_VIRTUAL_DISK_INFO_FRAGMENTATION = 12
}
private enum GENERIC_ACCESS_RIGHTS_FLAGS : uint {
GENERIC_READ = 0x80000000,
GENERIC_WRITE = 0x40000000,
GENERIC_EXECUTE = 0x20000000,
GENERIC_ALL = 0x10000000
}
private enum FILE_SHARE_MODE_FLAGS : int {
FILE_SHARE_READ = 0x00000001,
FILE_SHARE_WRITE = 0x00000002
}
private enum CREATION_DISPOSITION_FLAGS : int {
CREATE_NEW = 1,
CREATE_ALWAYS = 2,
OPEN_EXISTING = 3,
OPEN_ALWAYS = 4,
TRUNCATE_EXISTING = 5
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
struct DISK_EXTENT {
public Int32 diskNumber;
public Int64 startingOffset;
public Int64 extentLength;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
private struct VOLUME_DISK_EXTENTS {
public Int32 numberOfDiskExtents;
public DISK_EXTENT[] extents;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
private struct ATTACH_VIRTUAL_DISK_PARAMETERS {
public ATTACH_VIRTUAL_DISK_VERSION version;
public ATTACH_VIRTUAL_DISK_PARAMETERS_Version1 version1;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
private struct ATTACH_VIRTUAL_DISK_PARAMETERS_Version1 {
public Int32 reserved;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
private struct OPEN_VIRTUAL_DISK_PARAMETERS {
public OPEN_VIRTUAL_DISK_VERSION version;
public OPEN_VIRTUAL_DISK_PARAMETERS_Version1 version1;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
private struct OPEN_VIRTUAL_DISK_PARAMETERS_Version1 {
public Int32 rwDepth;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
private struct VIRTUAL_STORAGE_TYPE {
public Int32 deviceId;
public Guid vendorId;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
private struct STORAGE_DEVICE_NUMBER {
public Int32 deviceType;
public Int32 deviceNumber;
public Int32 partitionNumber;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
private struct GET_VIRTUAL_DISK_INFO_SIZE {
public GET_VIRTUAL_DISK_INFO_VERSION version;
public UInt64 virtualSize;
public UInt64 physicalSize;
public UInt32 blockSize;
public UInt32 sectorSize;
}
[DllImport("virtdisk.dll", CharSet = CharSet.Unicode)]
private static extern Int32 AttachVirtualDisk(IntPtr virtualDiskHandle, IntPtr securityDescriptor, ATTACH_VIRTUAL_DISK_FLAG flags, Int32 providerSpecificFlags, ref ATTACH_VIRTUAL_DISK_PARAMETERS parameters, IntPtr overlapped);
[DllImport("virtdisk.dll", CharSet = CharSet.Unicode)]
private static extern Int32 DetachVirtualDisk(IntPtr virtualDiskHandle, DETACH_VIRTUAL_DISK_FLAG flags, Int32 providerSpecificFlags);
[DllImportAttribute("kernel32.dll", SetLastError = true)]
[return: MarshalAsAttribute(UnmanagedType.Bool)]
private static extern Boolean CloseHandle(IntPtr hObject);
[DllImport("virtdisk.dll", CharSet = CharSet.Unicode)]
private static extern Int32 OpenVirtualDisk(ref VIRTUAL_STORAGE_TYPE virtualStorageType, String path, VIRTUAL_DISK_ACCESS_MASK virtualDiskAccessMask, OPEN_VIRTUAL_DISK_FLAG flags, ref OPEN_VIRTUAL_DISK_PARAMETERS parameters, ref IntPtr handle);
[DllImport("virtdisk.dll", CharSet = CharSet.Unicode)]
private static extern Int32 GetVirtualDiskPhysicalPath(IntPtr virtualDiskHandle, ref Int32 diskPathSizeInBytes, [MarshalAs(UnmanagedType.LPWStr)] StringBuilder diskPath);
[DllImport("virtdisk.dll", CharSet = CharSet.Unicode)]
private static extern Int32 GetVirtualDiskInformation(IntPtr virtualDiskHandle, ref UInt32 virtualDiskInfoSize, ref GET_VIRTUAL_DISK_INFO_SIZE virtualDiskInfo, IntPtr sizeUsed);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
private static extern IntPtr FindFirstVolume([MarshalAs(UnmanagedType.LPTStr)] StringBuilder volumeName, Int32 bufferLength);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool FindVolumeClose(IntPtr findVolumeHandle);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool FindNextVolume(IntPtr findVolumeHandle, [MarshalAs(UnmanagedType.LPTStr)] StringBuilder volumeName, Int32 bufferLength);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern IntPtr CreateFile([MarshalAs(UnmanagedType.LPTStr)] string fileName, GENERIC_ACCESS_RIGHTS_FLAGS desiredAccess, FILE_SHARE_MODE_FLAGS shareMode, IntPtr securityAttribute, CREATION_DISPOSITION_FLAGS creationDisposition, Int32 flagsAndAttributes, IntPtr templateFile);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool DeviceIoControl(IntPtr deviceHandle, IO_CONTROL_CODE controlCode, IntPtr inBuffer, uint inBufferSize, ref STORAGE_DEVICE_NUMBER outBuffer, uint outBufferSize, ref uint bytesReturned, IntPtr overlapped);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool SetVolumeMountPoint([MarshalAs(UnmanagedType.LPTStr)] string mountPoint, [MarshalAs(UnmanagedType.LPTStr)] string volumeName);
var attachParameters = new ATTACH_VIRTUAL_DISK_PARAMETERS() {
version = ATTACH_VIRTUAL_DISK_VERSION.ATTACH_VIRTUAL_DISK_VERSION_1
};
var openParameters = new OPEN_VIRTUAL_DISK_PARAMETERS() {
version = OPEN_VIRTUAL_DISK_VERSION.OPEN_VIRTUAL_DISK_VERSION_1,
version1 = {
rwDepth = OPEN_VIRTUAL_DISK_RW_DEPTH_DEFAULT
}
};
var openStorageType = new VIRTUAL_STORAGE_TYPE() {
deviceId = VIRTUAL_STORAGE_TYPE_DEVICE_VHD,
vendorId = VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT
};
IntPtr vhdHandle;
if (OpenVirtualDisk(ref openStorageType, vhdPath, VIRTUAL_DISK_ACCESS_MASK.VIRTUAL_DISK_ACCESS_ALL,
OPEN_VIRTUAL_DISK_FLAG.OPEN_VIRTUAL_DISK_FLAG_NONE, ref openParameters,
ref this._vhdHandle) != ERROR_SUCCESS) {
throw new CannotMountException("The VHD cannot be accessed [OpenVirtualDisk failed]");
}
if (AttachVirtualDisk(
this._vhdHandle, IntPtr.Zero,
ATTACH_VIRTUAL_DISK_FLAG.ATTACH_VIRTUAL_DISK_FLAG_PERMANENT_LIFETIME | ATTACH_VIRTUAL_DISK_FLAG.ATTACH_VIRTUAL_DISK_FLAG_NO_DRIVE_LETTER,
0, ref attachParameters, IntPtr.Zero
) != ERROR_SUCCESS) {
this._closeVhd();
throw new CannotMountException("The VHD cannot be accessed to install the drivers [AttachVirtualDisk failed]");
}
First, let's find the vhd path:
private int _findVhdPhysicalDriveNumber(vhdHandle) {
int driveNumber;
int bufferSize = 260;
StringBuilder vhdPhysicalPath = new StringBuilder(bufferSize);
GetVirtualDiskPhysicalPath(vhdHandle, ref bufferSize, vhdPhysicalPath);
Int32.TryParse(Regex.Match(vhdPhysicalPath.ToString(), @"\d+").Value, out driveNumber);
return driveNumber;
}
private string _findVhdVolumePath(vhdHandle) {
int vhdPhysicalDrive = this._findVhdPhysicalDriveNumber(vhdHandle);
StringBuilder volumeName = new StringBuilder(260);
IntPtr findVolumeHandle;
IntPtr volumeHandle;
STORAGE_DEVICE_NUMBER deviceNumber = new STORAGE_DEVICE_NUMBER();
uint bytesReturned = 0;
bool found = false;
findVolumeHandle = FindFirstVolume(volumeName, volumeName.Capacity);
do {
int backslashPos = volumeName.Length - 1;
if (volumeName[backslashPos] == '\\') {
volumeName.Length--;
}
volumeHandle = CreateFile(volumeName.ToString(), 0, FILE_SHARE_MODE_FLAGS.FILE_SHARE_READ | FILE_SHARE_MODE_FLAGS.FILE_SHARE_WRITE,
IntPtr.Zero, CREATION_DISPOSITION_FLAGS.OPEN_EXISTING, 0, IntPtr.Zero);
if (volumeHandle == INVALID_HANDLE_VALUE) {
continue;
}
DeviceIoControl(volumeHandle, IO_CONTROL_CODE.STORAGE_DEVICE_NUMBER, IntPtr.Zero, 0,
ref deviceNumber, (uint) Marshal.SizeOf(deviceNumber), ref bytesReturned, IntPtr.Zero);
if (deviceNumber.deviceNumber == vhdPhysicalDrive) {
found = true;
break;
}
} while (FindNextVolume(findVolumeHandle, volumeName, volumeName.Capacity));
FindVolumeClose(findVolumeHandle);
//************************
return found ? volumeName.ToString() : ""; //when It returns "" then the error occurs
}
We can now mount the VHD to a drive letter of our choosing (or any folder for that matter, see https://msdn.microsoft.com/en-ca/library/windows/desktop/aa365561(v=vs.85).aspx) mountPoint can be a drive letter in this format: X:\ or a path to an empty folder
private void _mountVhdToDriveLetter(string vhdVolumePath, string mountPoint) {
//Autoplay cancelAutoplay = new Autoplay();
this._mountedDriveLetter = mountPoint;
if (vhdVolumePath[vhdVolumePath.Length - 1] != '\\') { //**
vhdVolumePath += '\\';
}
if (!SetVolumeMountPoint(mountPoint, vhdVolumePath)) {
throw new CannotMountException("The VHD cannot be accessed to install the drivers [SetVolumeMountPoint failed]");
}
}
That should be it.
Disclaimer: I've extracted these snippets from a larger codebase and tried to remove dependencies from other components however since I don't have Visual Studio on this machine I haven't compiled it. Please let me know if I've made a mistake so that I can correct it.
This answer is slight modification to the one posted by Pixy (Accepted answer). One thing that I don't like about it is the use of do-while loop when winapi are available for it. You can get same effect using "GetVolumeNameForVolumeMountPointW". Below snippet is for mounting ISO, but you can add similar code for VHD. VERIFY and Log statement can be replaced with assert/return and printf/cout respectively.
VIRTUAL_STORAGE_TYPE openStorageType;
OPEN_VIRTUAL_DISK_PARAMETERS openParameters;
ATTACH_VIRTUAL_DISK_PARAMETERS attachParameters;
openStorageType.DeviceId = VIRTUAL_STORAGE_TYPE_DEVICE_ISO;
openStorageType.VendorId = VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT;
openParameters.Version = OPEN_VIRTUAL_DISK_VERSION_1;
openParameters.Version1.RWDepth = 0;
attachParameters.Version = ATTACH_VIRTUAL_DISK_VERSION_1;
VERIFY_ARE_EQUAL (OpenVirtualDisk(&openStorageType, isoFile, VIRTUAL_DISK_ACCESS_READ | VIRTUAL_DISK_ACCESS_ATTACH_RO , OPEN_VIRTUAL_DISK_FLAG_NONE,
&openParameters, &mountHandle), static_cast<DWORD>(ERROR_SUCCESS) );
VERIFY_ARE_EQUAL (AttachVirtualDisk(mountHandle, 0, ATTACH_VIRTUAL_DISK_FLAG_READ_ONLY | ATTACH_VIRTUAL_DISK_FLAG_PERMANENT_LIFETIME | ATTACH_VIRTUAL_DISK_FLAG_NO_DRIVE_LETTER,
0, &attachParameters, 0), static_cast<DWORD>(ERROR_SUCCESS) );
WCHAR physicalDrive[MAX_PATH];
ULONG bufferSize = sizeof(physicalDrive);
VERIFY_ARE_EQUAL (GetVirtualDiskPhysicalPath(mountHandle, &bufferSize, physicalDrive), static_cast<DWORD>(ERROR_SUCCESS) );
bufferSize = wcslen(physicalDrive);
if (physicalDrive[bufferSize - 1] != L'\\')
{
physicalDrive[bufferSize] = L'\\';
physicalDrive[bufferSize+1] = L'\0';
}
Log::Comment(physicalDrive, L"Physical drive");
WCHAR physicalDriveVolumeName[MAX_PATH] = {0};
if (!GetVolumeNameForVolumeMountPointW (physicalDrive, physicalDriveVolumeName, MAX_PATH))
{
VERIFY_ARE_EQUAL(static_cast<DWORD>(ERROR_SUCCESS), GetLastError());
}
bufferSize = wcslen(physicalDriveVolumeName);
if (physicalDriveVolumeName[bufferSize - 1] != L'\\')
{
physicalDriveVolumeName[bufferSize] = L'\\';
physicalDriveVolumeName[bufferSize+1] = L'\0';
}
Log::Comment(physicalDriveVolumeName, L"Physical volume name");
if (!SetVolumeMountPoint(path, physicalDriveVolumeName)) // Here path can be X:\ (Mount point) or X:\mount\ (Reparse point)
{
VERIFY_ARE_EQUAL(static_cast<DWORD>(ERROR_SUCCESS), GetLastError());
}