Index: /trunk/include/VBox/vd-image-backend.h
===================================================================
--- /trunk/include/VBox/vd-image-backend.h	(revision 66109)
+++ /trunk/include/VBox/vd-image-backend.h	(revision 66110)
@@ -324,4 +324,23 @@
 
     /**
+     * Returns a region list for the disk image if supported, optional.
+     *
+     * @returns VBox status code.
+     * @retval  VERR_NOT_SUPPORTED if region lists are not supported for this kind of image.
+     * @param   pBackendData    Opaque state data for this image.
+     * @param   ppRegionList    Where to store the pointer to the region list on success.
+     */
+    DECLR3CALLBACKMEMBER(int, pfnQueryRegions, (void *pBackendData, PCVDREGIONLIST *ppRegionList));
+
+    /**
+     * Releases the region list acquired with VDIMAGEBACKEND::pfnQueryRegions() before.
+     *
+     * @returns nothing.
+     * @param   pBackendData    Opaque state data for this image.
+     * @param   pRegionList     The region list to release.
+     */
+    DECLR3CALLBACKMEMBER(void, pfnRegionListRelease, (void *pBackendData, PCVDREGIONLIST pRegionList));
+
+    /**
      * Get the image flags of a disk image.
      *
@@ -589,5 +608,5 @@
 
 /** The current version of the VDIMAGEBACKEND structure. */
-#define VD_IMGBACKEND_VERSION                   VD_VERSION_MAKE(0xff01, 1, 0)
+#define VD_IMGBACKEND_VERSION                   VD_VERSION_MAKE(0xff01, 2, 0)
 
 /** @copydoc VDIMAGEBACKEND::pfnComposeLocation */
Index: /trunk/include/VBox/vd.h
===================================================================
--- /trunk/include/VBox/vd.h	(revision 66109)
+++ /trunk/include/VBox/vd.h	(revision 66110)
@@ -494,4 +494,106 @@
 /** Pointer to constant disk geometry. */
 typedef const VDGEOMETRY *PCVDGEOMETRY;
+
+/**
+ * Disk region data form known to us from various standards.
+ */
+typedef enum VDREGIONDATAFORM
+{
+    /** Invalid data form. */
+    VDREGIONDATAFORM_INVALID = 0,
+    /** Raw data, no standardized format. */
+    VDREGIONDATAFORM_RAW,
+    /** CD-DA (audio CD), 2352 bytes of data. */
+    VDREGIONDATAFORM_CDDA,
+    /** CDDA data is pause. */
+    VDREGIONDATAFORM_CDDA_PAUSE,
+    /** Mode 1 with 2048 bytes sector size. */
+    VDREGIONDATAFORM_MODE1_2048,
+    /** Mode 1 with 2352 bytes sector size. */
+    VDREGIONDATAFORM_MODE1_2352,
+    /** Mode 1 with 0 bytes sector size (generated by the drive). */
+    VDREGIONDATAFORM_MODE1_0,
+    /** XA Mode with 2336 bytes sector size. */
+    VDREGIONDATAFORM_XA_2336,
+    /** XA Mode with 2352 bytes sector size. */
+    VDREGIONDATAFORM_XA_2352,
+    /** XA Mode with 0 bytes sector size (generated by the drive). */
+    VDREGIONDATAFORM_XA_0,
+    /** Mode 2 with 2336 bytes sector size. */
+    VDREGIONDATAFORM_MODE2_2336,
+    /** Mode 2 with 2352 bytes sector size. */
+    VDREGIONDATAFORM_MODE2_2352,
+    /** Mode 2 with 0 bytes sector size (generated by the drive). */
+    VDREGIONDATAFORM_MODE2_0
+} VDREGIONDATAFORM;
+
+/**
+ * Disk region metadata forms known to us.
+ */
+typedef enum VDREGIONMETADATAFORM
+{
+    /** Invalid metadata form. */
+    VDREGIONMETADATAFORM_INVALID = 0,
+    /** No metadata assined to the region. */
+    VDREGIONMETADATAFORM_NONE,
+    /** Raw metadata, no standardized format. */
+    VDREGIONMETADATAFORM_RAW
+} VDREGIONMETADATAFORM;
+
+/**
+ * Disk region descriptor.
+ */
+typedef struct VDREGIONDESC
+{
+    /** Start of the region in bytes or LBA number (depending on the flag in the
+     * list header). */
+    uint64_t                 offRegion;
+    /** Overall size of the region in bytes or number of blocks (depending on the
+     * flag in the list header). */
+    uint64_t                 cRegionBlocksOrBytes;
+    /** Size of one block in bytes, containing user and metadata. */
+    uint64_t                 cbBlock;
+    /** User data form of the block. */
+    VDREGIONDATAFORM         enmDataForm;
+    /** Metadata form of the block. */
+    VDREGIONMETADATAFORM     enmMetadataForm;
+    /** Size of the data block in bytes. */
+    uint64_t                 cbData;
+    /** Size of the metadata in a block in bytes. */
+    uint64_t                 cbMetadata;
+} VDREGIONDESC;
+/** Pointer to a region descriptor. */
+typedef VDREGIONDESC *PVDREGIONDESC;
+/** Pointer to a constant region descriptor. */
+typedef const VDREGIONDESC PCVDREGIONDESC;
+
+/**
+ * Disk region list.
+ */
+typedef struct VDREGIONLIST
+{
+    /** Flags valid for the region list. */
+    uint32_t                 fFlags;
+    /** Number of regions in the descriptor array. */
+    uint32_t                 cRegions;
+    /** Region descriptors - variable in size. */
+    VDREGIONDESC             aRegions[RT_FLEXIBLE_ARRAY];
+} VDREGIONLIST;
+/** Pointer to a region list. */
+typedef VDREGIONLIST *PVDREGIONLIST;
+/** Pointer to a constant region list. */
+typedef const VDREGIONLIST *PCVDREGIONLIST;
+/** Pointer to a region list pointer. */
+typedef PVDREGIONLIST *PPVDREGIONLIST;
+
+/** @name Valid region list flags.
+ * @{
+ */
+/** When set the region start offset and size are given in numbers of blocks
+ * instead of byte offsets and sizes. */
+#define VD_REGION_LIST_F_LOC_SIZE_BLOCKS     RT_BIT_32(0)
+/** Mask of all valid flags. */
+#define VD_REGION_LIST_F_VALID               (VD_REGION_LIST_F_LOC_SIZE_BLOCKS)
+/** @} */
 
 /**
@@ -1129,4 +1231,27 @@
 
 /**
+ * Queries the available regions of an image in the given VD container.
+ *
+ * @return  VBox status code.
+ * @retval  VERR_VD_IMAGE_NOT_FOUND if image with specified number was not opened.
+ * @retval  VERR_NOT_SUPPORTED if the image backend doesn't support region lists.
+ * @param   pDisk           Pointer to HDD container.
+ * @param   nImage          Image number, counts from 0. 0 is always base image of container.
+ * @param   fFlags          Combination of VD_REGION_LIST_F_* flags.
+ * @param   ppRegionList    Where to store the pointer to the region list on success, must be freed
+ *                          with VDRegionListFree().
+ */
+VBOXDDU_DECL(int) VDQueryRegions(PVBOXHDD pDisk, unsigned nImage, uint32_t fFlags,
+                                 PPVDREGIONLIST ppRegionList);
+
+/**
+ * Frees a region list previously queried with VDQueryRegions().
+ *
+ * @return  nothing.
+ * @param   pRegionList     The region list to free.
+ */
+VBOXDDU_DECL(void) VDRegionListFree(PVDREGIONLIST pRegionList);
+
+/**
  * Get version of image in HDD container.
  *
Index: /trunk/src/VBox/Storage/DMG.cpp
===================================================================
--- /trunk/src/VBox/Storage/DMG.cpp	(revision 66109)
+++ /trunk/src/VBox/Storage/DMG.cpp	(revision 66110)
@@ -2452,4 +2452,8 @@
     /* pfnSetLCHSGeometry */
     dmgSetLCHSGeometry,
+    /* pfnQueryRegions */
+    NULL,
+    /* pfnRegionListRelease */
+    NULL,
     /* pfnGetImageFlags */
     dmgGetImageFlags,
Index: /trunk/src/VBox/Storage/ISCSI.cpp
===================================================================
--- /trunk/src/VBox/Storage/ISCSI.cpp	(revision 66109)
+++ /trunk/src/VBox/Storage/ISCSI.cpp	(revision 66110)
@@ -5542,4 +5542,8 @@
     /* pfnSetLCHSGeometry */
     iscsiSetLCHSGeometry,
+    /* pfnQueryRegions */
+    NULL,
+    /* pfnRegionListRelease */
+    NULL,
     /* pfnGetImageFlags */
     iscsiGetImageFlags,
Index: /trunk/src/VBox/Storage/Parallels.cpp
===================================================================
--- /trunk/src/VBox/Storage/Parallels.cpp	(revision 66109)
+++ /trunk/src/VBox/Storage/Parallels.cpp	(revision 66110)
@@ -1113,4 +1113,8 @@
     /* pfnSetLCHSGeometry */
     parallelsSetLCHSGeometry,
+    /* pfnQueryRegions */
+    NULL,
+    /* pfnRegionListRelease */
+    NULL,
     /* pfnGetImageFlags */
     parallelsGetImageFlags,
Index: /trunk/src/VBox/Storage/QCOW.cpp
===================================================================
--- /trunk/src/VBox/Storage/QCOW.cpp	(revision 66109)
+++ /trunk/src/VBox/Storage/QCOW.cpp	(revision 66110)
@@ -2383,4 +2383,8 @@
     /* pfnSetLCHSGeometry */
     qcowSetLCHSGeometry,
+    /* pfnQueryRegions */
+    NULL,
+    /* pfnRegionListRelease */
+    NULL,
     /* pfnGetImageFlags */
     qcowGetImageFlags,
Index: /trunk/src/VBox/Storage/QED.cpp
===================================================================
--- /trunk/src/VBox/Storage/QED.cpp	(revision 66109)
+++ /trunk/src/VBox/Storage/QED.cpp	(revision 66110)
@@ -2436,4 +2436,8 @@
     /* pfnSetLCHSGeometry */
     qedSetLCHSGeometry,
+    /* pfnQueryRegions */
+    NULL,
+    /* pfnRegionListRelease */
+    NULL,
     /* pfnGetImageFlags */
     qedGetImageFlags,
Index: /trunk/src/VBox/Storage/RAW.cpp
===================================================================
--- /trunk/src/VBox/Storage/RAW.cpp	(revision 66109)
+++ /trunk/src/VBox/Storage/RAW.cpp	(revision 66110)
@@ -267,4 +267,10 @@
                 else
                     rc = vdIfError(pImage->pIfError, VERR_DISK_FULL, RT_SRC_POS, N_("Raw: disk would overflow creating image '%s'"), pImage->pszFilename);
+            }
+            else
+            {
+                rc = vdIfIoIntFileSetSize(pImage->pIfIo, pImage->pStorage, cbSize);
+                if (RT_SUCCESS(rc))
+                    pImage->cbSize = cbSize;
             }
         }
@@ -1001,4 +1007,8 @@
     /* pfnSetLCHSGeometry */
     rawSetLCHSGeometry,
+    /* pfnQueryRegions */
+    NULL,
+    /* pfnRegionListRelease */
+    NULL,
     /* pfnGetImageFlags */
     rawGetImageFlags,
Index: /trunk/src/VBox/Storage/VD.cpp
===================================================================
--- /trunk/src/VBox/Storage/VD.cpp	(revision 66109)
+++ /trunk/src/VBox/Storage/VD.cpp	(revision 66110)
@@ -5784,4 +5784,56 @@
 
     RTSemEventSignal(hEvent);
+}
+
+/**
+ * Creates a new region list from the given one converting to match the flags if necessary.
+ *
+ * @returns VBox status code.
+ * @param   pRegionList     The region list to convert from.
+ * @param   fFlags          The flags for the new region list.
+ * @param   ppRegionList    Where to store the new region list on success.
+ */
+static int vdRegionListConv(PCVDREGIONLIST pRegionList, uint32_t fFlags, PPVDREGIONLIST ppRegionList)
+{
+    int rc = VINF_SUCCESS;
+    PVDREGIONLIST pRegionListNew = (PVDREGIONLIST)RTMemDup(pRegionList, RT_UOFFSETOF(VDREGIONLIST, aRegions[pRegionList->cRegions]));
+    if (RT_LIKELY(pRegionListNew))
+    {
+        /* Do we have to convert anything? */
+        if (pRegionList->fFlags != fFlags)
+        {
+            uint64_t offRegionNext = 0;
+
+            pRegionListNew->fFlags = fFlags;
+            for (unsigned i = 0; i < pRegionListNew->cRegions; i++)
+            {
+                PVDREGIONDESC pRegion = &pRegionListNew->aRegions[i];
+
+                if (   (fFlags & VD_REGION_LIST_F_LOC_SIZE_BLOCKS)
+                    && !(pRegionList->fFlags & VD_REGION_LIST_F_LOC_SIZE_BLOCKS))
+                {
+                    Assert(!(pRegion->cRegionBlocksOrBytes % pRegion->cbBlock));
+
+                    /* Convert from bytes to logical blocks. */
+                    pRegion->offRegion            = offRegionNext;
+                    pRegion->cRegionBlocksOrBytes = pRegion->cRegionBlocksOrBytes / pRegion->cbBlock;
+                    offRegionNext += pRegion->cRegionBlocksOrBytes;
+                }
+                else
+                {
+                    /* Convert from logical blocks to bytes. */
+                    pRegion->offRegion            = offRegionNext;
+                    pRegion->cRegionBlocksOrBytes = pRegion->cRegionBlocksOrBytes * pRegion->cbBlock;
+                    offRegionNext += pRegion->cRegionBlocksOrBytes;
+                }
+            }
+        }
+
+        *ppRegionList = pRegionListNew;
+    }
+    else
+        rc = VERR_NO_MEMORY;
+
+    return rc;
 }
 
@@ -10042,4 +10094,117 @@
 
 /**
+ * Queries the available regions of an image in the given VD container.
+ *
+ * @return  VBox status code.
+ * @retval  VERR_VD_IMAGE_NOT_FOUND if image with specified number was not opened.
+ * @retval  VERR_NOT_SUPPORTED if the image backend doesn't support region lists.
+ * @param   pDisk           Pointer to HDD container.
+ * @param   nImage          Image number, counts from 0. 0 is always base image of container.
+ * @param   fFlags          Combination of VD_REGION_LIST_F_* flags.
+ * @param   ppRegionList    Where to store the pointer to the region list on success, must be freed
+ *                          with VDRegionListFree().
+ */
+VBOXDDU_DECL(int) VDQueryRegions(PVBOXHDD pDisk, unsigned nImage, uint32_t fFlags,
+                                 PPVDREGIONLIST ppRegionList)
+{
+    int rc = VINF_SUCCESS;
+    int rc2;
+    bool fLockRead = false;
+
+    LogFlowFunc(("pDisk=%#p nImage=%u fFlags=%#x ppRegionList=%#p\n",
+                 pDisk, nImage, fFlags, ppRegionList));
+    do
+    {
+        /* sanity check */
+        AssertPtrBreakStmt(pDisk, rc = VERR_INVALID_PARAMETER);
+        AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));
+
+        /* Check arguments. */
+        AssertMsgBreakStmt(VALID_PTR(ppRegionList),
+                           ("ppRegionList=%#p\n", ppRegionList),
+                           rc = VERR_INVALID_PARAMETER);
+
+        rc2 = vdThreadStartRead(pDisk);
+        AssertRC(rc2);
+        fLockRead = true;
+
+        PVDIMAGE pImage = vdGetImageByNumber(pDisk, nImage);
+        AssertPtrBreakStmt(pImage, rc = VERR_VD_IMAGE_NOT_FOUND);
+
+        if (pImage->Backend->pfnQueryRegions)
+        {
+            PCVDREGIONLIST pRegionList = NULL;
+            rc = pImage->Backend->pfnQueryRegions(pImage->pBackendData, &pRegionList);
+            if (RT_SUCCESS(rc))
+            {
+                rc = vdRegionListConv(pRegionList, fFlags, ppRegionList);
+
+                AssertPtr(pImage->Backend->pfnRegionListRelease);
+                pImage->Backend->pfnRegionListRelease(pImage->pBackendData, pRegionList);
+            }
+        }
+        else
+            rc = VERR_NOT_SUPPORTED;
+
+        if (rc == VERR_NOT_SUPPORTED)
+        {
+            /*
+             * Create a list with a single region containing the data gathered from the
+             * image and sector size.
+             */
+            PVDREGIONLIST pRegionList = (PVDREGIONLIST)RTMemAllocZ(RT_UOFFSETOF(VDREGIONLIST, aRegions[1]));
+            if (RT_LIKELY(pRegionList))
+            {
+                uint32_t cbSector = pImage->Backend->pfnGetSectorSize(pImage->pBackendData);
+                uint64_t cbImage = pImage->Backend->pfnGetSize(pImage->pBackendData);
+
+                pRegionList->cRegions = 1;
+                pRegionList->fFlags   = fFlags;
+
+                /*
+                 * Single region starting at the first byte/block covering the whole image,
+                 * block size equals sector size and contains no metadata.
+                 */
+                PVDREGIONDESC pRegion = &pRegionList->aRegions[0];
+                pRegion->offRegion       = 0; /* Disk start. */
+                pRegion->cbBlock         = cbSector;
+                pRegion->enmDataForm     = VDREGIONDATAFORM_RAW;
+                pRegion->enmMetadataForm = VDREGIONMETADATAFORM_NONE;
+                pRegion->cbData          = cbSector;
+                pRegion->cbMetadata      = 0;
+                if (fFlags & VD_REGION_LIST_F_LOC_SIZE_BLOCKS)
+                    pRegion->cRegionBlocksOrBytes = cbImage / cbSector;
+                else
+                    pRegion->cRegionBlocksOrBytes = cbImage;
+
+                *ppRegionList  = pRegionList;
+            }
+            else
+                rc = VERR_NO_MEMORY;
+        }
+    } while (0);
+
+    if (RT_UNLIKELY(fLockRead))
+    {
+        rc2 = vdThreadFinishRead(pDisk);
+        AssertRC(rc2);
+    }
+
+    LogFlowFunc((": %Rrc\n", rc));
+    return rc;
+}
+
+/**
+ * Frees a region list previously queried with VDQueryRegions().
+ *
+ * @return  nothing.
+ * @param   pRegionList     The region list to free.
+ */
+VBOXDDU_DECL(void) VDRegionListFree(PVDREGIONLIST pRegionList)
+{
+    RTMemFree(pRegionList);
+}
+
+/**
  * Get version of image in HDD container.
  *
Index: /trunk/src/VBox/Storage/VDI.cpp
===================================================================
--- /trunk/src/VBox/Storage/VDI.cpp	(revision 66109)
+++ /trunk/src/VBox/Storage/VDI.cpp	(revision 66110)
@@ -3138,4 +3138,8 @@
     /* pfnSetLCHSGeometry */
     vdiSetLCHSGeometry,
+    /* pfnQueryRegions */
+    NULL,
+    /* pfnRegionListRelease */
+    NULL,
     /* pfnGetImageFlags */
     vdiGetImageFlags,
Index: /trunk/src/VBox/Storage/VHD.cpp
===================================================================
--- /trunk/src/VBox/Storage/VHD.cpp	(revision 66109)
+++ /trunk/src/VBox/Storage/VHD.cpp	(revision 66110)
@@ -3058,4 +3058,8 @@
     /* pfnSetLCHSGeometry */
     vhdSetLCHSGeometry,
+    /* pfnQueryRegions */
+    NULL,
+    /* pfnRegionListRelease */
+    NULL,
     /* pfnGetImageFlags */
     vhdGetImageFlags,
Index: /trunk/src/VBox/Storage/VHDX.cpp
===================================================================
--- /trunk/src/VBox/Storage/VHDX.cpp	(revision 66109)
+++ /trunk/src/VBox/Storage/VHDX.cpp	(revision 66110)
@@ -2534,4 +2534,8 @@
     /* pfnSetLCHSGeometry */
     vhdxSetLCHSGeometry,
+    /* pfnQueryRegions */
+    NULL,
+    /* pfnRegionListRelease */
+    NULL,
     /* pfnGetImageFlags */
     vhdxGetImageFlags,
Index: /trunk/src/VBox/Storage/VMDK.cpp
===================================================================
--- /trunk/src/VBox/Storage/VMDK.cpp	(revision 66109)
+++ /trunk/src/VBox/Storage/VMDK.cpp	(revision 66110)
@@ -6415,4 +6415,8 @@
     /* pfnSetLCHSGeometry */
     vmdkSetLCHSGeometry,
+    /* pfnQueryRegions */
+    NULL,
+    /* pfnRegionListRelease */
+    NULL,
     /* pfnGetImageFlags */
     vmdkGetImageFlags,
