Windows VHD Create, Attach, get Disk serial number

 

// create_vhd.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <Windows.h>
#include <Shlwapi.h>
#include <initguid.h>
#include <virtdisk.h>
#include <sddl.h>

DWORD
SampleCreateVirtualDisk(
    _In_        LPCWSTR                     VirtualDiskPath,
    _In_opt_    LPCWSTR                     ParentPath,
    _In_        CREATE_VIRTUAL_DISK_FLAG    Flags,
    _In_        ULONGLONG                   FileSize,
    _In_        DWORD                       BlockSize,
    _In_        DWORD                       LogicalSectorSize,
    _In_        DWORD                       PhysicalSectorSize)
{
    VIRTUAL_STORAGE_TYPE storageType;
    CREATE_VIRTUAL_DISK_PARAMETERS parameters;
    HANDLE vhdHandle = INVALID_HANDLE_VALUE;
    DWORD opStatus;
    GUID uniqueId;

    if (RPC_S_OK != UuidCreate((UUID*)&uniqueId))
    {
        opStatus = ERROR_NOT_ENOUGH_MEMORY;
        goto Cleanup;
    }

    //
    // Specify UNKNOWN for both device and vendor so the system will use the
    // file extension to determine the correct VHD format.
    //

    storageType.DeviceId = VIRTUAL_STORAGE_TYPE_DEVICE_UNKNOWN;
    storageType.VendorId = VIRTUAL_STORAGE_TYPE_VENDOR_UNKNOWN;

    memset(&parameters, 0, sizeof(parameters));

    //
    // CREATE_VIRTUAL_DISK_VERSION_2 allows specifying a richer set a values and returns
    // a V2 handle.
    //
    // VIRTUAL_DISK_ACCESS_NONE is the only acceptable access mask for V2 handle opens.
    //
    // Valid BlockSize values are as follows (use 0 to indicate default value):
    //      Fixed VHD: 0
    //      Dynamic VHD: 512kb, 2mb (default)
    //      Differencing VHD: 512kb, 2mb (if parent is fixed, default is 2mb; if parent is dynamic or differencing, default is parent blocksize)
    //      Fixed VHDX: 0
    //      Dynamic VHDX: 1mb, 2mb, 4mb, 8mb, 16mb, 32mb (default), 64mb, 128mb, 256mb
    //      Differencing VHDX: 1mb, 2mb (default), 4mb, 8mb, 16mb, 32mb, 64mb, 128mb, 256mb
    //
    // Valid LogicalSectorSize values are as follows (use 0 to indicate default value):
    //      VHD: 512 (default)
    //      VHDX: 512 (for fixed or dynamic, default is 512; for differencing, default is parent logicalsectorsize), 4096
    //
    // Valid PhysicalSectorSize values are as follows (use 0 to indicate default value):
    //      VHD: 512 (default)
    //      VHDX: 512, 4096 (for fixed or dynamic, default is 4096; for differencing, default is parent physicalsectorsize)
    //
    parameters.Version = CREATE_VIRTUAL_DISK_VERSION_2;
    parameters.Version2.UniqueId = uniqueId;
    parameters.Version2.MaximumSize = FileSize;
    parameters.Version2.BlockSizeInBytes = BlockSize;
    parameters.Version2.SectorSizeInBytes = LogicalSectorSize;
    parameters.Version2.PhysicalSectorSizeInBytes = PhysicalSectorSize;
    parameters.Version2.ParentPath = ParentPath;

    opStatus = CreateVirtualDisk(
        &storageType,
        VirtualDiskPath,
        VIRTUAL_DISK_ACCESS_NONE,
        NULL,
        Flags,
        0,
        &parameters,
        NULL,
        &vhdHandle);

    if (opStatus != ERROR_SUCCESS)
    {
        goto Cleanup;
    }

Cleanup:

    if (opStatus == ERROR_SUCCESS)
    {
        wprintf(L"Create success\n");
    }
    else
    {
        wprintf(L"Create error = %u\n", opStatus);
    }

    if (vhdHandle != INVALID_HANDLE_VALUE)
    {
        printf("%s: Handle closed.\n", __func__);
        CloseHandle(vhdHandle);
    }

    return opStatus;
}


int make_vhd()
{
    GUID myGUID;
    HRESULT h = CoCreateGuid(&myGUID);
    if (h != S_OK)
        printf("Failed to generate GUID.\n");

    OLECHAR* guidString;
    StringFromCLSID(myGUID, &guidString);
    printf("%ls\n", guidString);

    VIRTUAL_STORAGE_TYPE           VirtualStorageType;
    VirtualStorageType.DeviceId = VIRTUAL_STORAGE_TYPE_DEVICE_UNKNOWN;
    VirtualStorageType.VendorId = VIRTUAL_STORAGE_TYPE_VENDOR_UNKNOWN;

    PCWSTR                          Path = L"c:\\vhd_test.vhd";

    VIRTUAL_DISK_ACCESS_MASK        VirtualDiskAccessMask = VIRTUAL_DISK_ACCESS_NONE;

    PSECURITY_DESCRIPTOR            SecurityDescriptor = NULL;

    CREATE_VIRTUAL_DISK_FLAG        Flags = CREATE_VIRTUAL_DISK_FLAG_FULL_PHYSICAL_ALLOCATION;
    //CREATE_VIRTUAL_DISK_FLAG        Flags = CREATE_VIRTUAL_DISK_FLAG_NONE;

    ULONG                           ProviderSpecificFlags = 0;

    printf("sizeof(PCREATE_VIRTUAL_DISK_PARAMETERS) %zd\n", sizeof(_CREATE_VIRTUAL_DISK_PARAMETERS));
    PCREATE_VIRTUAL_DISK_PARAMETERS Parameters = (PCREATE_VIRTUAL_DISK_PARAMETERS)malloc(sizeof(_CREATE_VIRTUAL_DISK_PARAMETERS));
    memset(Parameters, 0, sizeof(_CREATE_VIRTUAL_DISK_PARAMETERS));

    Parameters->Version = CREATE_VIRTUAL_DISK_VERSION_2;

    Parameters->Version2.UniqueId = myGUID;
    StringFromCLSID(Parameters->Version2.UniqueId, &guidString);
    printf("Parameters->Version2.UniqueId %ls\n", guidString);

    Parameters->Version2.MaximumSize = 0x200000000;
    Parameters->Version2.BlockSizeInBytes = 0;
    Parameters->Version2.SectorSizeInBytes = 0;
    Parameters->Version2.PhysicalSectorSizeInBytes = 0;
    Parameters->Version2.OpenFlags = OPEN_VIRTUAL_DISK_FLAG_NONE;
    Parameters->Version2.ParentPath = NULL;
    Parameters->Version2.SourcePath = NULL;

    LPOVERLAPPED                    Overlapped = NULL;

    PHANDLE                         Handle = NULL;

    DWORD ret = CreateVirtualDisk(
        &VirtualStorageType,
        Path,
        VirtualDiskAccessMask,
        SecurityDescriptor,
        Flags,
        ProviderSpecificFlags,
        Parameters,
        Overlapped,
        Handle
    );

    if(ret != ERROR_SUCCESS)
    {
        printf("%s: CreateVirtualDisk failed (%d)\n", __func__, ret);
    }

    return 0;
}

DWORD
SampleAttachVirtualDisk(
    _In_    LPCWSTR     VirtualDiskPath,
    _In_    BOOLEAN     ReadOnly)
{
    OPEN_VIRTUAL_DISK_PARAMETERS openParameters;
    VIRTUAL_DISK_ACCESS_MASK accessMask;
    ATTACH_VIRTUAL_DISK_PARAMETERS attachParameters;
    PSECURITY_DESCRIPTOR sd;
    VIRTUAL_STORAGE_TYPE storageType;
    LPCTSTR extension;
    HANDLE vhdHandle;
    ATTACH_VIRTUAL_DISK_FLAG attachFlags;
    DWORD opStatus;

    vhdHandle = INVALID_HANDLE_VALUE;
    sd = NULL;

    //
    // Specify UNKNOWN for both device and vendor so the system will use the
    // file extension to determine the correct VHD format.
    //

    storageType.DeviceId = VIRTUAL_STORAGE_TYPE_DEVICE_UNKNOWN;
    storageType.VendorId = VIRTUAL_STORAGE_TYPE_VENDOR_UNKNOWN;

    memset(&openParameters, 0, sizeof(openParameters));

    extension = ::PathFindExtension(VirtualDiskPath);

    if (extension != NULL && _wcsicmp(extension, L".iso") == 0)
    {
        //
        // ISO files can only be mounted read-only and using the V1 API.
        //

        if (ReadOnly != TRUE)
        {
            opStatus = ERROR_NOT_SUPPORTED;
            goto Cleanup;
        }

        openParameters.Version = OPEN_VIRTUAL_DISK_VERSION_1;
        accessMask = VIRTUAL_DISK_ACCESS_READ;
    }
    else
    {
        //
        // VIRTUAL_DISK_ACCESS_NONE is the only acceptable access mask for V2 handle opens.
        //

        openParameters.Version = OPEN_VIRTUAL_DISK_VERSION_2;
        openParameters.Version2.GetInfoOnly = FALSE;
        accessMask = VIRTUAL_DISK_ACCESS_NONE;
    }

    //
    // Open the VHD or ISO.
    //
    // OPEN_VIRTUAL_DISK_FLAG_NONE bypasses any special handling of the open.
    //

    opStatus = OpenVirtualDisk(
        &storageType,
        VirtualDiskPath,
        accessMask,
        OPEN_VIRTUAL_DISK_FLAG_NONE,
        &openParameters,
        &vhdHandle);

    if (opStatus != ERROR_SUCCESS)
    {
        goto Cleanup;
    }

    //
    // Create the world-RW SD.
    //

    if (!::ConvertStringSecurityDescriptorToSecurityDescriptor(
        L"O:BAG:BAD:(A;;GA;;;WD)",
        SDDL_REVISION_1,
        &sd,
        NULL))
    {
        opStatus = ::GetLastError();
        goto Cleanup;
    }

    //
    // Attach the VHD/VHDX or ISO.
    //

    memset(&attachParameters, 0, sizeof(attachParameters));
    attachParameters.Version = ATTACH_VIRTUAL_DISK_VERSION_1;

    //
    // A "Permanent" surface persists even when the handle is closed.
    //

    attachFlags = ATTACH_VIRTUAL_DISK_FLAG_PERMANENT_LIFETIME;

    if (ReadOnly)
    {
        // ATTACH_VIRTUAL_DISK_FLAG_READ_ONLY specifies a read-only mount.
        attachFlags |= ATTACH_VIRTUAL_DISK_FLAG_READ_ONLY;
    }

    opStatus = AttachVirtualDisk(
        vhdHandle,
        sd,
        attachFlags,
        0,
        &attachParameters,
        NULL);

    if (opStatus != ERROR_SUCCESS)
    {
        goto Cleanup;
    }

Cleanup:

    if (opStatus == ERROR_SUCCESS)
    {
        wprintf(L"Attach success\n");
    }
    else
    {
        wprintf(L"Attach error = %u\n", opStatus);
    }

    if (sd != NULL)
    {
        LocalFree(sd);
        sd = NULL;
    }

    if (vhdHandle != INVALID_HANDLE_VALUE)
    {
        printf("%s: Handle closed.\n", __func__);
        CloseHandle(vhdHandle);
    }

    return opStatus;
}

HANDLE DoOpenVHD(LPCWSTR VirtualDiskPath, BOOL GetInfoOnly)
{
    HANDLE vhdHandle;
    OPEN_VIRTUAL_DISK_PARAMETERS openParameters;
    openParameters.Version = OPEN_VIRTUAL_DISK_VERSION_2;
    openParameters.Version2.GetInfoOnly = GetInfoOnly;

    VIRTUAL_STORAGE_TYPE storageType;
    storageType.DeviceId = VIRTUAL_STORAGE_TYPE_DEVICE_UNKNOWN;
    storageType.VendorId = VIRTUAL_STORAGE_TYPE_VENDOR_UNKNOWN;

    int ret = OpenVirtualDisk(&storageType, VirtualDiskPath,
        VIRTUAL_DISK_ACCESS_NONE, OPEN_VIRTUAL_DISK_FLAG_NONE,
        &openParameters, &vhdHandle);
    if (ret != ERROR_SUCCESS) {
        // If return value of OpenVirtualDisk isn't ERROR_SUCCESS, there was a problem opening the VHD
        printf("Failed to open VHD %ls. (%d)\n", VirtualDiskPath, ret);
        return NULL;
    }
    return vhdHandle;
}

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

    printf("physicalDrive %ls\n", physicalDrive);

    if (vhdHandle != INVALID_HANDLE_VALUE)
    {
        printf("%s: Handle closed.\n", __func__);
        CloseHandle(vhdHandle);
    }
    
    char name[1024];
    memset(name, 0, 1024);
    snprintf(name, 1024, "%ls", physicalDrive);
    DWORD driveNumber = name[strlen(name) - 1] - '0';
    printf("Drive idx %d\n", driveNumber);
    return driveNumber;
}

int __cdecl wmain(_In_ int argc, _In_reads_(argc) WCHAR *argv[])
{
    int rc = 0;
    LPCWSTR virtualDiskPath = argv[1];
    LPCWSTR parentPath = NULL;

    ULONGLONG fileSize = _wtoi64(argv[2]);
    DWORD blockSize = _wtoi(argv[3]);
    DWORD logicalSectorSize = _wtoi(argv[4]);
    DWORD physicalSectorSize = _wtoi(argv[5]);

    /*rc = SampleCreateVirtualDisk(
        virtualDiskPath,
        parentPath,
        CREATE_VIRTUAL_DISK_FLAG_FULL_PHYSICAL_ALLOCATION,
        fileSize,
        blockSize,
        logicalSectorSize,
        physicalSectorSize);

    printf("SampleCreateVirtualDisk %d\n", rc);

    rc = SampleAttachVirtualDisk(virtualDiskPath, FALSE);
    printf("SampleAttachVirtualDisk %d\n", rc);*/

    //wchar_t physicalDrive[MAX_PATH];
    //ULONG bufferSize = sizeof(physicalDrive);
    HANDLE vhdHandle = DoOpenVHD(virtualDiskPath, TRUE);
    int drive_idx = getPhyDrive(vhdHandle);
    /*char name[1024];
    memset(name, 0, 1024);
    snprintf(name, 1024, "%ls", physicalDrive);
    DWORD driveNumber = name[strlen(name) - 1] - '0';
    printf("Drive idx %d\n", driveNumber);*/
    //MountVol(drive_idx);

    getchar();
    return 0;
}

 

Guess you like

Origin www.cnblogs.com/liujx2019/p/12750526.html