12

Windows 7 API 関数を使用して仮想ハード ドライブ (.VHD) をマウントしようとしていますが、関連する関数が見つかりません。存在しますか?

参考までに、Visual Studio 2010 を使用して C++ でプログラミングしています。

前もって感謝します ;)

4

2 に答える 2

18

これは古い質問ですが、まだ答えがないので、誰かが私のようにつまずいた場合に備えて提供します.

VHD のアタッチ

MSDN の完全なリファレンス [VHD リファレンス]: 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 が正常に接続されました。他の物理ディスクと同じように表示され、VHD に含まれるボリュームにドライブ文字が自動的に割り当てられます。マウントに使用するドライブ文字を選択したい場合は、読み続けてください。

ドライブ文字の割り当て

まず、ATTACH_VIRTUAL_DISK_FLAG_NO_DRIVE_LETTERAttachVirtualDisk 呼び出しにフラグを追加して、この自動文字割り当てが行われないようにします。次に、VHD ボリュームのボリューム パスを見つける必要があります [次の形式です: \\?\Volume{GUID}]:

wchar_t physicalDrive[MAX_PATH];
ULONG bufferSize = sizeof(physicalDrive);
GetVirtualDiskPhysicalPath(vhdHandle, &bufferSize, physicalDrive);

これで、接続された VHD の物理パスが次の形式で物理ドライブに表示されます: \\.\PhysicalDrive# # は、FindFirstVolume/FindNextVolume で VHD ボリュームを見つけるために必要なドライブ番号です。数値を抽出して整数に変換すると、次のコードの準備が整います。

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);

これらのインクルードとこのライブラリへのリンクを忘れないでください。

#define WINVER _WIN32_WINNT_WIN7
#include <windows.h>
#include <winioctl.h>
#include <virtdisk.h>

#pragma comment(lib, "virtdisk.lib")

免責事項: これは私が C# コードベースで行っていたことです。質問のためにコードを C/C++ に変換しましたが、実際にコンパイルしようとはしていません。コードにエラーが見つかった場合は、編集するか、私に知らせてください。

編集: タイプミス、includes と lib、FindVolumeClose を忘れた、高度の警告

于 2014-12-22T23:00:34.280 に答える