// 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(¶meters, 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, ¶meters, NULL, &vhdHandle); if (opStatus != ERROR_SUCCESS) { goto Cleanup; } Cleanup: if (opStatus == ERROR_SUCCESS) { wprintf(L"Create success "); } else { wprintf(L"Create error = %u ", opStatus); } if (vhdHandle != INVALID_HANDLE_VALUE) { printf("%s: Handle closed. ", __func__); CloseHandle(vhdHandle); } return opStatus; } int make_vhd() { GUID myGUID; HRESULT h = CoCreateGuid(&myGUID); if (h != S_OK) printf("Failed to generate GUID. "); OLECHAR* guidString; StringFromCLSID(myGUID, &guidString); printf("%ls ", 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 ", 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 ", 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) ", __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 "); } else { wprintf(L"Attach error = %u ", opStatus); } if (sd != NULL) { LocalFree(sd); sd = NULL; } if (vhdHandle != INVALID_HANDLE_VALUE) { printf("%s: Handle closed. ", __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) ", 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 ", physicalDrive); if (vhdHandle != INVALID_HANDLE_VALUE) { printf("%s: Handle closed. ", __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 ", 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 ", rc); rc = SampleAttachVirtualDisk(virtualDiskPath, FALSE); printf("SampleAttachVirtualDisk %d ", 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 ", driveNumber);*/ //MountVol(drive_idx); getchar(); return 0; }