Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. How to get allocated blocks for VHDx? queryChangesVirtualDisk gives ACCESS DENIED.

How to get allocated blocks for VHDx? queryChangesVirtualDisk gives ACCESS DENIED.

Scheduled Pinned Locked Moved C / C++ / MFC
databasehelptutorialquestionannouncement
12 Posts 3 Posters 2 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • C cazorla19

    I am trying out VirtualDisk APIs, So far I am able to Open a VHDX file, get some of the properties by using GetVirtualDiskInformation. But I am not able to get RCT information and ChangedAreas. 1)Opendisk is done with VIRTUAL_DISK_ACCESS_GET_INFO flag. 2)GetVirtualDiskInformation a. Works fine when version flag is set to GET_VIRTUAL_DISK_INFO_SIZE, able to fetch sector size and other information b. Gives ERROR_INSUFFICIENT_BUFFER(122) when version flag is set to GET_VIRTUAL_DISK_INFO_CHANGE_TRACKING_STATE to access diskInfo->ChangeTrackingState.MostRecentId

    PGET\_VIRTUAL\_DISK\_INFO diskInfo;
    ULONG diskInfoSize = sizeof(GET\_VIRTUAL\_DISK\_INFO);
    std::wcout << "size of diskinfo structure " << diskInfoSize << std::endl;
    diskInfo = (PGET\_VIRTUAL\_DISK\_INFO)malloc(diskInfoSize);
    
    diskInfo->Version = GET\_VIRTUAL\_DISK\_INFO\_SIZE;
    
    res = GetVirtualDiskInformation(vhdHandle, &diskInfoSize, diskInfo, NULL);
    long physicalSize = diskInfo->Size.PhysicalSize;
    long virtualSize = diskInfo->Size.VirtualSize;
    long sectorSize = diskInfo->Size.SectorSize;
    long blockSize = diskInfo->Size.BlockSize;
    std::wcout << "physicalSize :" << physicalSize << std::endl;
    std::wcout << "virtualSize :" << virtualSize << std::endl;
    std::wcout << "sectorSize :" << sectorSize << std::endl;
    std::wcout << "blockSize :" << blockSize << std::endl;
    
    diskInfo->Version = GET\_VIRTUAL\_DISK\_INFO\_CHANGE\_TRACKING\_STATE;
    
    res = GetVirtualDiskInformation(vhdHandle, &diskInfoSize, diskInfo, NULL);
    std::wcout << "\\nrct id:" << diskInfo->ChangeTrackingState.MostRecentId << std::endl;
    

    3)queryChangesVirtualDisk gives ACCESS DENIED.

    ULONG64   byteOffset = 0L;
    ULONG64   byteLength = 19327352832;
    QUERY\_CHANGES\_VIRTUAL\_DISK\_RANGE\* changedAreas = NULL;
    ULONG     rangeCount = 0L;
    ULONG64   processedLength = 0L;
    res = QueryChangesVirtualDisk(vhdHandle, "rctX:c2eb01d9:ccb1:405d:acb6:f0e76d055906:00000001", 
        byteOffset, byteLength,
        QUERY\_CHANGES\_VIRTUAL\_DISK\_FLAG\_NONE,
        changedAreas, &rangeCount, &processedLength);
    

    Can someone please give some ideas on what I am doing wrong?

    L Offline
    L Offline
    Lost User
    wrote on last edited by
    #2

    Quote:

    This value is not supported before Windows 10 and Windows Server 2016.

    It was only in wine that he laid down no limit for himself, but he did not allow himself to be confused by it. ― Confucian Analects: Rules of Confucius about his food

    C 1 Reply Last reply
    0
    • C cazorla19

      I am trying out VirtualDisk APIs, So far I am able to Open a VHDX file, get some of the properties by using GetVirtualDiskInformation. But I am not able to get RCT information and ChangedAreas. 1)Opendisk is done with VIRTUAL_DISK_ACCESS_GET_INFO flag. 2)GetVirtualDiskInformation a. Works fine when version flag is set to GET_VIRTUAL_DISK_INFO_SIZE, able to fetch sector size and other information b. Gives ERROR_INSUFFICIENT_BUFFER(122) when version flag is set to GET_VIRTUAL_DISK_INFO_CHANGE_TRACKING_STATE to access diskInfo->ChangeTrackingState.MostRecentId

      PGET\_VIRTUAL\_DISK\_INFO diskInfo;
      ULONG diskInfoSize = sizeof(GET\_VIRTUAL\_DISK\_INFO);
      std::wcout << "size of diskinfo structure " << diskInfoSize << std::endl;
      diskInfo = (PGET\_VIRTUAL\_DISK\_INFO)malloc(diskInfoSize);
      
      diskInfo->Version = GET\_VIRTUAL\_DISK\_INFO\_SIZE;
      
      res = GetVirtualDiskInformation(vhdHandle, &diskInfoSize, diskInfo, NULL);
      long physicalSize = diskInfo->Size.PhysicalSize;
      long virtualSize = diskInfo->Size.VirtualSize;
      long sectorSize = diskInfo->Size.SectorSize;
      long blockSize = diskInfo->Size.BlockSize;
      std::wcout << "physicalSize :" << physicalSize << std::endl;
      std::wcout << "virtualSize :" << virtualSize << std::endl;
      std::wcout << "sectorSize :" << sectorSize << std::endl;
      std::wcout << "blockSize :" << blockSize << std::endl;
      
      diskInfo->Version = GET\_VIRTUAL\_DISK\_INFO\_CHANGE\_TRACKING\_STATE;
      
      res = GetVirtualDiskInformation(vhdHandle, &diskInfoSize, diskInfo, NULL);
      std::wcout << "\\nrct id:" << diskInfo->ChangeTrackingState.MostRecentId << std::endl;
      

      3)queryChangesVirtualDisk gives ACCESS DENIED.

      ULONG64   byteOffset = 0L;
      ULONG64   byteLength = 19327352832;
      QUERY\_CHANGES\_VIRTUAL\_DISK\_RANGE\* changedAreas = NULL;
      ULONG     rangeCount = 0L;
      ULONG64   processedLength = 0L;
      res = QueryChangesVirtualDisk(vhdHandle, "rctX:c2eb01d9:ccb1:405d:acb6:f0e76d055906:00000001", 
          byteOffset, byteLength,
          QUERY\_CHANGES\_VIRTUAL\_DISK\_FLAG\_NONE,
          changedAreas, &rangeCount, &processedLength);
      

      Can someone please give some ideas on what I am doing wrong?

      L Offline
      L Offline
      Lost User
      wrote on last edited by
      #3

      Hi, I do see at least one problem in your code:

      ULONG diskInfoSize = sizeof(GET_VIRTUAL_DISK_INFO);

      should be changed to:

      ULONG diskInfoSize = sizeof(GET_VIRTUAL_DISK_INFO) + sizeof(GUID);

      cazorla19 wrote:

      queryChangesVirtualDisk gives ACCESS DENIED.

      Could you show me the flags you are passing to OpenVirtualDisk? Best Wishes, -David Delaune

      C 1 Reply Last reply
      0
      • L Lost User

        Hi, I do see at least one problem in your code:

        ULONG diskInfoSize = sizeof(GET_VIRTUAL_DISK_INFO);

        should be changed to:

        ULONG diskInfoSize = sizeof(GET_VIRTUAL_DISK_INFO) + sizeof(GUID);

        cazorla19 wrote:

        queryChangesVirtualDisk gives ACCESS DENIED.

        Could you show me the flags you are passing to OpenVirtualDisk? Best Wishes, -David Delaune

        C Offline
        C Offline
        cazorla19
        wrote on last edited by
        #4

        Hi David, I have tried OpenVirtualDisk with VIRTUAL_DISK_ACCESS_GET_INFO as suggested in msdn portal. I also tried with VIRTUAL_DISK_ACCESS_READ, both times I got same error.

        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\_UNKNOWN;
        storageType.VendorId = VIRTUAL\_STORAGE\_TYPE\_VENDOR\_UNKNOWN;
        

        DWORD res = OpenVirtualDisk(&storageType, path,
        VIRTUAL_DISK_ACCESS_GET_INFO,
        OPEN_VIRTUAL_DISK_FLAG_NONE,
        &openParameters,
        &vhdHandle);

        Also, I changed diskInfoSize as suggested but still got the same 'insufficient buffer size' error.

        ULONG diskInfoSize = sizeof(GET_VIRTUAL_DISK_INFO) + sizeof(GUID);

        Increasing the diskinfo size definitely helped me in getting rct id using GetVirtualDiskInformation,

        WCHAR changeTrackingInfo\[2048\];
        ZeroMemory(changeTrackingInfo, sizeof(changeTrackingInfo));
        
        PGET\_VIRTUAL\_DISK\_INFO diskInfo;
        ULONG diskInfoSize = sizeof(GET\_VIRTUAL\_DISK\_INFO) + sizeof(changeTrackingInfo);
        

        queryChangesVirtualDisk gives ACCESS DENIED is not resolved. Regards, Hari

        L 1 Reply Last reply
        0
        • L Lost User

          Quote:

          This value is not supported before Windows 10 and Windows Server 2016.

          It was only in wine that he laid down no limit for himself, but he did not allow himself to be confused by it. ― Confucian Analects: Rules of Confucius about his food

          C Offline
          C Offline
          cazorla19
          wrote on last edited by
          #5

          Hi Gerry, I am trying in a Windows2016 hyperV, and guest VM has windows 10. Also, I am able to get changed blocks by using WMI queries. But VHD API is giving ACCESS_DENIED_ERROR. Regards, Hari

          L 1 Reply Last reply
          0
          • C cazorla19

            Hi Gerry, I am trying in a Windows2016 hyperV, and guest VM has windows 10. Also, I am able to get changed blocks by using WMI queries. But VHD API is giving ACCESS_DENIED_ERROR. Regards, Hari

            L Offline
            L Offline
            Lost User
            wrote on last edited by
            #6

            The first thing I'd do is confirm "without" a VM. And then I'd try Oracle's VmBox. Then try running as "admin" in the VM, etc.

            It was only in wine that he laid down no limit for himself, but he did not allow himself to be confused by it. ― Confucian Analects: Rules of Confucius about his food

            1 Reply Last reply
            0
            • C cazorla19

              Hi David, I have tried OpenVirtualDisk with VIRTUAL_DISK_ACCESS_GET_INFO as suggested in msdn portal. I also tried with VIRTUAL_DISK_ACCESS_READ, both times I got same error.

              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\_UNKNOWN;
              storageType.VendorId = VIRTUAL\_STORAGE\_TYPE\_VENDOR\_UNKNOWN;
              

              DWORD res = OpenVirtualDisk(&storageType, path,
              VIRTUAL_DISK_ACCESS_GET_INFO,
              OPEN_VIRTUAL_DISK_FLAG_NONE,
              &openParameters,
              &vhdHandle);

              Also, I changed diskInfoSize as suggested but still got the same 'insufficient buffer size' error.

              ULONG diskInfoSize = sizeof(GET_VIRTUAL_DISK_INFO) + sizeof(GUID);

              Increasing the diskinfo size definitely helped me in getting rct id using GetVirtualDiskInformation,

              WCHAR changeTrackingInfo\[2048\];
              ZeroMemory(changeTrackingInfo, sizeof(changeTrackingInfo));
              
              PGET\_VIRTUAL\_DISK\_INFO diskInfo;
              ULONG diskInfoSize = sizeof(GET\_VIRTUAL\_DISK\_INFO) + sizeof(changeTrackingInfo);
              

              queryChangesVirtualDisk gives ACCESS DENIED is not resolved. Regards, Hari

              L Offline
              L Offline
              Lost User
              wrote on last edited by
              #7

              Hi Hari, Kinda looks like you are breaking the rules of nearly everything in the Remarks section for the OpenVirtualDisk function for a permanently attached virtual disk. This is working for me, code is ugly, there is no error handling... it's just a code sample:

              #include
              #include
              #include
              #include
              #include
              #include
              #include

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

              const GUID VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT = {0xec984aec, 0xa0f9, 0x47e9, 0x90, 0x1f, 0x71, 0x41, 0x5a, 0x66, 0x34, 0x5b};
              const GUID VIRTUAL_STORAGE_TYPE_VENDOR_UNKNOWN = { 0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

              int main()
              {
              HANDLE vhdHandle = NULL;
              VIRTUAL_STORAGE_TYPE storageType = {};
              ULONG status = 0L;

              //storageType.DeviceId = VIRTUAL\_STORAGE\_TYPE\_DEVICE\_VHDX;
              //storageType.VendorId = VIRTUAL\_STORAGE\_TYPE\_VENDOR\_MICROSOFT;
              storageType.DeviceId = VIRTUAL\_STORAGE\_TYPE\_DEVICE\_UNKNOWN;
              storageType.VendorId = VIRTUAL\_STORAGE\_TYPE\_VENDOR\_UNKNOWN;
              
              PCWSTR virtualDiskPath = L"D:\\\\VirtualMachines\\\\x64\_Windows8.1\\\\x64\_Windows8.1\\\\Virtual Hard Disks\\\\x64\_Windows8.1.vhdx";
              
              OPEN\_VIRTUAL\_DISK\_PARAMETERS\* pOpenParameter = NULL;
              
              status = OpenVirtualDisk(&storageType, virtualDiskPath,VIRTUAL\_DISK\_ACCESS\_ATTACH\_RW | VIRTUAL\_DISK\_ACCESS\_GET\_INFO | VIRTUAL\_DISK\_ACCESS\_DETACH,OPEN\_VIRTUAL\_DISK\_FLAG\_NONE, pOpenParameter, &vhdHandle);
              
              if (ERROR\_SUCCESS == status)
              {
              	DWORD sizeUsed = GET\_VIRTUAL\_DISK\_INFO\_SIZE;
              	WCHAR changeTrackingInfo\[sizeof(GET\_VIRTUAL\_DISK\_INFO) + sizeof(GUID)\];
              	::ZeroMemory(changeTrackingInfo, sizeof(changeTrackingInfo));
              	PGET\_VIRTUAL\_DISK\_INFO virtualDiskInfo = (GET\_VIRTUAL\_DISK\_INFO\*)changeTrackingInfo;
              	virtualDiskInfo->Version = (GET\_VIRTUAL\_DISK\_INFO\_VERSION)GET\_VIRTUAL\_DISK\_INFO\_CHANGE\_TRACKING\_STATE;
              	ULONG virtualDiskInfoSize = sizeof(changeTrackingInfo);
              
              	status = GetVirtualDiskInformation(vhdHandle, &virtualDiskInfoSize, virtualDiskInfo, &sizeUsed);
              
              	if (ERROR\_SUCCESS == status)
              	{
              		ULONG64 virtualDiskSize = virtualDiskInfo->Size.VirtualSize;
              
              		printf("Disk Infomation:\\n");
              		GUID virtualDiskGuid = virtualDiskInfo->Identifier;
              		wchar\_t szGUID\[64\] = { 0 };
              		StringFromGUID2(virtualDiskGuid, szGUID, 64);
              		wprintf(L"ChangeTrackingState.Enabled:%d\\n", vi
              
              C 1 Reply Last reply
              0
              • L Lost User

                Hi Hari, Kinda looks like you are breaking the rules of nearly everything in the Remarks section for the OpenVirtualDisk function for a permanently attached virtual disk. This is working for me, code is ugly, there is no error handling... it's just a code sample:

                #include
                #include
                #include
                #include
                #include
                #include
                #include

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

                const GUID VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT = {0xec984aec, 0xa0f9, 0x47e9, 0x90, 0x1f, 0x71, 0x41, 0x5a, 0x66, 0x34, 0x5b};
                const GUID VIRTUAL_STORAGE_TYPE_VENDOR_UNKNOWN = { 0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

                int main()
                {
                HANDLE vhdHandle = NULL;
                VIRTUAL_STORAGE_TYPE storageType = {};
                ULONG status = 0L;

                //storageType.DeviceId = VIRTUAL\_STORAGE\_TYPE\_DEVICE\_VHDX;
                //storageType.VendorId = VIRTUAL\_STORAGE\_TYPE\_VENDOR\_MICROSOFT;
                storageType.DeviceId = VIRTUAL\_STORAGE\_TYPE\_DEVICE\_UNKNOWN;
                storageType.VendorId = VIRTUAL\_STORAGE\_TYPE\_VENDOR\_UNKNOWN;
                
                PCWSTR virtualDiskPath = L"D:\\\\VirtualMachines\\\\x64\_Windows8.1\\\\x64\_Windows8.1\\\\Virtual Hard Disks\\\\x64\_Windows8.1.vhdx";
                
                OPEN\_VIRTUAL\_DISK\_PARAMETERS\* pOpenParameter = NULL;
                
                status = OpenVirtualDisk(&storageType, virtualDiskPath,VIRTUAL\_DISK\_ACCESS\_ATTACH\_RW | VIRTUAL\_DISK\_ACCESS\_GET\_INFO | VIRTUAL\_DISK\_ACCESS\_DETACH,OPEN\_VIRTUAL\_DISK\_FLAG\_NONE, pOpenParameter, &vhdHandle);
                
                if (ERROR\_SUCCESS == status)
                {
                	DWORD sizeUsed = GET\_VIRTUAL\_DISK\_INFO\_SIZE;
                	WCHAR changeTrackingInfo\[sizeof(GET\_VIRTUAL\_DISK\_INFO) + sizeof(GUID)\];
                	::ZeroMemory(changeTrackingInfo, sizeof(changeTrackingInfo));
                	PGET\_VIRTUAL\_DISK\_INFO virtualDiskInfo = (GET\_VIRTUAL\_DISK\_INFO\*)changeTrackingInfo;
                	virtualDiskInfo->Version = (GET\_VIRTUAL\_DISK\_INFO\_VERSION)GET\_VIRTUAL\_DISK\_INFO\_CHANGE\_TRACKING\_STATE;
                	ULONG virtualDiskInfoSize = sizeof(changeTrackingInfo);
                
                	status = GetVirtualDiskInformation(vhdHandle, &virtualDiskInfoSize, virtualDiskInfo, &sizeUsed);
                
                	if (ERROR\_SUCCESS == status)
                	{
                		ULONG64 virtualDiskSize = virtualDiskInfo->Size.VirtualSize;
                
                		printf("Disk Infomation:\\n");
                		GUID virtualDiskGuid = virtualDiskInfo->Identifier;
                		wchar\_t szGUID\[64\] = { 0 };
                		StringFromGUID2(virtualDiskGuid, szGUID, 64);
                		wprintf(L"ChangeTrackingState.Enabled:%d\\n", vi
                
                C Offline
                C Offline
                cazorla19
                wrote on last edited by
                #8

                Many thanks for your inputs. Tried your sample code in my environment, OpenVirtualDisk failed with 32 ERROR_SHARING_VIOLATION. Steps I have followed till now, 1. Create a production snapshot on the VM. 2. Convert the snapshot to the reference point(snapshot gets merged automatically) using wmi commands. 3. Added some files to VM disk. 4. Create another production snapshot on the VM so that any changes in VM will be written to avhdx file. 5. Try to open the parent vhdx using VHD APIs. 6. Get a resilient change tracking identifier using ChangeTrackingState.MostRecentId 7. Query for changed areas using VHD API QueryChangesVirtualDisk. So far I am able to get till step six by passing only VIRTUAL_DISK_ACCESS_GET_INFO flag for OpenVirtualDisk. step 7 gives ACCESS_DENIED.

                void openDiskEx()
                {
                HANDLE vhdHandle = NULL;
                VIRTUAL_STORAGE_TYPE storageType = {};
                ULONG status = 0L;

                storageType.DeviceId = VIRTUAL\_STORAGE\_TYPE\_DEVICE\_UNKNOWN;
                storageType.VendorId = VIRTUAL\_STORAGE\_TYPE\_VENDOR\_UNKNOWN;
                
                PCWSTR virtualDiskPath = L"C:\\\\Hyper-V\\\\Virtual Hard Disks\\\\Lacazette\\\\Windows2016.vhdx";
                
                OPEN\_VIRTUAL\_DISK\_PARAMETERS\* pOpenParameter = NULL;
                
                status = OpenVirtualDisk(&storageType, virtualDiskPath, VIRTUAL\_DISK\_ACCESS\_ATTACH\_RW | VIRTUAL\_DISK\_ACCESS\_GET\_INFO | VIRTUAL\_DISK\_ACCESS\_DETACH, OPEN\_VIRTUAL\_DISK\_FLAG\_NONE, pOpenParameter, &vhdHandle);
                std::cout << "opendisk:" << status<< std::endl;
                if (ERROR\_SUCCESS == status)
                {
                    DWORD sizeUsed = GET\_VIRTUAL\_DISK\_INFO\_SIZE;
                    WCHAR changeTrackingInfo\[sizeof(GET\_VIRTUAL\_DISK\_INFO) + sizeof(GUID)\];
                    ::ZeroMemory(changeTrackingInfo, sizeof(changeTrackingInfo));
                    PGET\_VIRTUAL\_DISK\_INFO virtualDiskInfo = (GET\_VIRTUAL\_DISK\_INFO\*)changeTrackingInfo;
                    virtualDiskInfo->Version = (GET\_VIRTUAL\_DISK\_INFO\_VERSION)GET\_VIRTUAL\_DISK\_INFO\_CHANGE\_TRACKING\_STATE;
                    ULONG virtualDiskInfoSize = sizeof(changeTrackingInfo);
                
                    status = GetVirtualDiskInformation(vhdHandle, &virtualDiskInfoSize, virtualDiskInfo, &sizeUsed);
                    std::cout << "GetVirtualDiskInformation:" << status << std::endl;
                    if (ERROR\_SUCCESS == status)
                    {
                        ULONG64 virtualDiskSize = virtualDiskInfo->Size.VirtualSize;
                        printf("Disk Infomation:\\n");
                        GUID virtualDiskGuid = virtualDiskInfo->Identifier;
                        wchar\_t szGUID\[64\] = { 0 };
                        StringFromGUID2(virtualDiskGuid, szGUID, 64);
                        wprintf(L"ChangeTrackingState.Enabled:%d
                
                L 1 Reply Last reply
                0
                • C cazorla19

                  Many thanks for your inputs. Tried your sample code in my environment, OpenVirtualDisk failed with 32 ERROR_SHARING_VIOLATION. Steps I have followed till now, 1. Create a production snapshot on the VM. 2. Convert the snapshot to the reference point(snapshot gets merged automatically) using wmi commands. 3. Added some files to VM disk. 4. Create another production snapshot on the VM so that any changes in VM will be written to avhdx file. 5. Try to open the parent vhdx using VHD APIs. 6. Get a resilient change tracking identifier using ChangeTrackingState.MostRecentId 7. Query for changed areas using VHD API QueryChangesVirtualDisk. So far I am able to get till step six by passing only VIRTUAL_DISK_ACCESS_GET_INFO flag for OpenVirtualDisk. step 7 gives ACCESS_DENIED.

                  void openDiskEx()
                  {
                  HANDLE vhdHandle = NULL;
                  VIRTUAL_STORAGE_TYPE storageType = {};
                  ULONG status = 0L;

                  storageType.DeviceId = VIRTUAL\_STORAGE\_TYPE\_DEVICE\_UNKNOWN;
                  storageType.VendorId = VIRTUAL\_STORAGE\_TYPE\_VENDOR\_UNKNOWN;
                  
                  PCWSTR virtualDiskPath = L"C:\\\\Hyper-V\\\\Virtual Hard Disks\\\\Lacazette\\\\Windows2016.vhdx";
                  
                  OPEN\_VIRTUAL\_DISK\_PARAMETERS\* pOpenParameter = NULL;
                  
                  status = OpenVirtualDisk(&storageType, virtualDiskPath, VIRTUAL\_DISK\_ACCESS\_ATTACH\_RW | VIRTUAL\_DISK\_ACCESS\_GET\_INFO | VIRTUAL\_DISK\_ACCESS\_DETACH, OPEN\_VIRTUAL\_DISK\_FLAG\_NONE, pOpenParameter, &vhdHandle);
                  std::cout << "opendisk:" << status<< std::endl;
                  if (ERROR\_SUCCESS == status)
                  {
                      DWORD sizeUsed = GET\_VIRTUAL\_DISK\_INFO\_SIZE;
                      WCHAR changeTrackingInfo\[sizeof(GET\_VIRTUAL\_DISK\_INFO) + sizeof(GUID)\];
                      ::ZeroMemory(changeTrackingInfo, sizeof(changeTrackingInfo));
                      PGET\_VIRTUAL\_DISK\_INFO virtualDiskInfo = (GET\_VIRTUAL\_DISK\_INFO\*)changeTrackingInfo;
                      virtualDiskInfo->Version = (GET\_VIRTUAL\_DISK\_INFO\_VERSION)GET\_VIRTUAL\_DISK\_INFO\_CHANGE\_TRACKING\_STATE;
                      ULONG virtualDiskInfoSize = sizeof(changeTrackingInfo);
                  
                      status = GetVirtualDiskInformation(vhdHandle, &virtualDiskInfoSize, virtualDiskInfo, &sizeUsed);
                      std::cout << "GetVirtualDiskInformation:" << status << std::endl;
                      if (ERROR\_SUCCESS == status)
                      {
                          ULONG64 virtualDiskSize = virtualDiskInfo->Size.VirtualSize;
                          printf("Disk Infomation:\\n");
                          GUID virtualDiskGuid = virtualDiskInfo->Identifier;
                          wchar\_t szGUID\[64\] = { 0 };
                          StringFromGUID2(virtualDiskGuid, szGUID, 64);
                          wprintf(L"ChangeTrackingState.Enabled:%d
                  
                  L Offline
                  L Offline
                  Lost User
                  wrote on last edited by
                  #9

                  cazorla19 wrote:

                  OpenVirtualDisk failed with 32 ERROR_SHARING_VIOLATION.

                  That obviously means that the virtual disk is locked/mounted and being used by another process. Are you trying to read the change tracking on running Hyper-V virtual machine? I don't think you can do that.

                  C 1 Reply Last reply
                  0
                  • L Lost User

                    cazorla19 wrote:

                    OpenVirtualDisk failed with 32 ERROR_SHARING_VIOLATION.

                    That obviously means that the virtual disk is locked/mounted and being used by another process. Are you trying to read the change tracking on running Hyper-V virtual machine? I don't think you can do that.

                    C Offline
                    C Offline
                    cazorla19
                    wrote on last edited by
                    #10

                    Yes, I am trying to read the change tracking information when the Virtual machine is online.

                    L 1 Reply Last reply
                    0
                    • C cazorla19

                      Yes, I am trying to read the change tracking information when the Virtual machine is online.

                      L Offline
                      L Offline
                      Lost User
                      wrote on last edited by
                      #11

                      Ok, If you can't read the change tracking information from an Administrator account with both SE_BACKUP_NAME and SE_MANAGE_VOLUME_NAME privileges then I don't think it will be possible. Also since the virtual drive is mounted you should change the access mask from VIRTUAL_DISK_ACCESS_ATTACH_RW to VIRTUAL_DISK_ACCESS_ATTACH_RO. I am actually in a Hyper-V environment right now so if I get some time later today I will look into it more. The code sample I gave you is working for me on my offline virtual machines. Best Wishes, -David Delaune

                      1 Reply Last reply
                      0
                      • C cazorla19

                        I am trying out VirtualDisk APIs, So far I am able to Open a VHDX file, get some of the properties by using GetVirtualDiskInformation. But I am not able to get RCT information and ChangedAreas. 1)Opendisk is done with VIRTUAL_DISK_ACCESS_GET_INFO flag. 2)GetVirtualDiskInformation a. Works fine when version flag is set to GET_VIRTUAL_DISK_INFO_SIZE, able to fetch sector size and other information b. Gives ERROR_INSUFFICIENT_BUFFER(122) when version flag is set to GET_VIRTUAL_DISK_INFO_CHANGE_TRACKING_STATE to access diskInfo->ChangeTrackingState.MostRecentId

                        PGET\_VIRTUAL\_DISK\_INFO diskInfo;
                        ULONG diskInfoSize = sizeof(GET\_VIRTUAL\_DISK\_INFO);
                        std::wcout << "size of diskinfo structure " << diskInfoSize << std::endl;
                        diskInfo = (PGET\_VIRTUAL\_DISK\_INFO)malloc(diskInfoSize);
                        
                        diskInfo->Version = GET\_VIRTUAL\_DISK\_INFO\_SIZE;
                        
                        res = GetVirtualDiskInformation(vhdHandle, &diskInfoSize, diskInfo, NULL);
                        long physicalSize = diskInfo->Size.PhysicalSize;
                        long virtualSize = diskInfo->Size.VirtualSize;
                        long sectorSize = diskInfo->Size.SectorSize;
                        long blockSize = diskInfo->Size.BlockSize;
                        std::wcout << "physicalSize :" << physicalSize << std::endl;
                        std::wcout << "virtualSize :" << virtualSize << std::endl;
                        std::wcout << "sectorSize :" << sectorSize << std::endl;
                        std::wcout << "blockSize :" << blockSize << std::endl;
                        
                        diskInfo->Version = GET\_VIRTUAL\_DISK\_INFO\_CHANGE\_TRACKING\_STATE;
                        
                        res = GetVirtualDiskInformation(vhdHandle, &diskInfoSize, diskInfo, NULL);
                        std::wcout << "\\nrct id:" << diskInfo->ChangeTrackingState.MostRecentId << std::endl;
                        

                        3)queryChangesVirtualDisk gives ACCESS DENIED.

                        ULONG64   byteOffset = 0L;
                        ULONG64   byteLength = 19327352832;
                        QUERY\_CHANGES\_VIRTUAL\_DISK\_RANGE\* changedAreas = NULL;
                        ULONG     rangeCount = 0L;
                        ULONG64   processedLength = 0L;
                        res = QueryChangesVirtualDisk(vhdHandle, "rctX:c2eb01d9:ccb1:405d:acb6:f0e76d055906:00000001", 
                            byteOffset, byteLength,
                            QUERY\_CHANGES\_VIRTUAL\_DISK\_FLAG\_NONE,
                            changedAreas, &rangeCount, &processedLength);
                        

                        Can someone please give some ideas on what I am doing wrong?

                        D Offline
                        D Offline
                        DingHuaming
                        wrote on last edited by
                        #12

                        hi, have you resolve the problem?

                        1 Reply Last reply
                        0
                        Reply
                        • Reply as topic
                        Log in to reply
                        • Oldest to Newest
                        • Newest to Oldest
                        • Most Votes


                        • Login

                        • Don't have an account? Register

                        • Login or register to search.
                        • First post
                          Last post
                        0
                        • Categories
                        • Recent
                        • Tags
                        • Popular
                        • World
                        • Users
                        • Groups