Index: /trunk/include/VBox/VBoxHDD.h
===================================================================
--- /trunk/include/VBox/VBoxHDD.h	(revision 29648)
+++ /trunk/include/VBox/VBoxHDD.h	(revision 29649)
@@ -103,26 +103,27 @@
 
 /**
- * Auxiliary type for describing partitions on raw disks.
- */
-typedef struct VBOXHDDRAWPART
-{
-    /** Device to use for this partition. Can be the disk device if the offset
-     * field is set appropriately. If this is NULL, then this partition will
-     * not be accessible to the guest. The size of the partition must still
-     * be set correctly. */
+ * Auxiliary type for describing partitions on raw disks. The entries must be
+ * in ascending order (as far as uStart is concerned), and must not overlap.
+ * Note that this does not correspond 1:1 to partitions, it is describing the
+ * general meaning of contiguous areas on the disk.
+ */
+typedef struct VBOXHDDRAWPARTDESC
+{
+    /** Device to use for this partition/data area. Can be the disk device if
+     * the offset field is set appropriately. If this is NULL, then this
+     * partition will not be accessible to the guest. The size of the data area
+     * must still be set correctly. */
     const char      *pszRawDevice;
-    /** Offset where the partition data starts in this device. */
-    uint64_t        uPartitionStartOffset;
-    /** Offset where the partition data starts in the disk. */
-    uint64_t        uPartitionStart;
-    /** Size of the partition. */
-    uint64_t        cbPartition;
-    /** Size of the partitioning info to prepend. */
-    uint64_t        cbPartitionData;
-    /** Offset where the partitioning info starts in the disk. */
-    uint64_t        uPartitionDataStart;
-    /** Pointer to the partitioning info to prepend. */
+    /** Pointer to the partitioning info. NULL means this is a regular data
+     * area on disk, non-NULL denotes data which should be copied to the
+     * partition data overlay. */
     const void      *pvPartitionData;
-} VBOXHDDRAWPART, *PVBOXHDDRAWPART;
+    /** Offset where the data starts in this device. */
+    uint64_t        uStartOffset;
+    /** Offset where the data starts in the disk. */
+    uint64_t        uStart;
+    /** Size of the data area. */
+    uint64_t        cbData;
+} VBOXHDDRAWPARTDESC, *PVBOXHDDRAWPARTDESC;
 
 /**
@@ -140,8 +141,8 @@
      * For Linux e.g. /dev/sda, and for Windows e.g. \\\\.\\PhysicalDisk0. */
     const char      *pszRawDisk;
-    /** Number of entries in the partitions array. */
-    unsigned        cPartitions;
-    /** Pointer to the partitions array. */
-    PVBOXHDDRAWPART pPartitions;
+    /** Number of entries in the partition descriptor array. */
+    unsigned        cPartDescs;
+    /** Pointer to the partition descriptor array. */
+    PVBOXHDDRAWPARTDESC pPartDescs;
 } VBOXHDDRAW, *PVBOXHDDRAW;
 
Index: /trunk/src/VBox/Devices/Storage/VmdkHDDCore.cpp
===================================================================
--- /trunk/src/VBox/Devices/Storage/VmdkHDDCore.cpp	(revision 29648)
+++ /trunk/src/VBox/Devices/Storage/VmdkHDDCore.cpp	(revision 29649)
@@ -3481,32 +3481,19 @@
          * open all the (flat) raw disk partitions. */
 
-        /* First pass over the partitions to determine how many
-         * extents we need. One partition can require up to 4 extents.
-         * One to skip over unpartitioned space, one for the
-         * partitioning data, one to skip over unpartitioned space
-         * and one for the partition data. */
+        /* First pass over the partition data areas to determine how many
+         * extents we need. One data area can require up to 2 extents, as
+         * it might be necessary to skip over unpartitioned space. */
         unsigned cExtents = 0;
         uint64_t uStart = 0;
-        for (unsigned i = 0; i < pRaw->cPartitions; i++)
-        {
-            PVBOXHDDRAWPART pPart = &pRaw->pPartitions[i];
-            if (pPart->cbPartitionData)
-            {
-                if (uStart > pPart->uPartitionDataStart)
-                    return vmdkError(pImage, VERR_INVALID_PARAMETER, RT_SRC_POS, N_("VMDK: cannot go backwards for partitioning information in '%s'"), pImage->pszFilename);
-                else if (uStart != pPart->uPartitionDataStart)
-                    cExtents++;
-                uStart = pPart->uPartitionDataStart + pPart->cbPartitionData;
+        for (unsigned i = 0; i < pRaw->cPartDescs; i++)
+        {
+            PVBOXHDDRAWPARTDESC pPart = &pRaw->pPartDescs[i];
+            if (uStart > pPart->uStart)
+                return vmdkError(pImage, VERR_INVALID_PARAMETER, RT_SRC_POS, N_("VMDK: incorrect partition data area ordering set up by the caller in '%s'"), pImage->pszFilename);
+
+            if (uStart < pPart->uStart)
                 cExtents++;
-            }
-            if (pPart->cbPartition)
-            {
-                if (uStart > pPart->uPartitionStart)
-                    return vmdkError(pImage, VERR_INVALID_PARAMETER, RT_SRC_POS, N_("VMDK: cannot go backwards for partition data in '%s'"), pImage->pszFilename);
-                else if (uStart != pPart->uPartitionStart)
-                    cExtents++;
-                uStart = pPart->uPartitionStart + pPart->cbPartition;
-                cExtents++;
-            }
+            uStart = pPart->uStart + pPart->cbData;
+            cExtents++;
         }
         /* Another extent for filling up the rest of the image. */
@@ -3544,22 +3531,25 @@
         cExtents = 0;
         uStart = 0;
-        for (unsigned i = 0; i < pRaw->cPartitions; i++)
-        {
-            PVBOXHDDRAWPART pPart = &pRaw->pPartitions[i];
-            if (pPart->cbPartitionData)
+        for (unsigned i = 0; i < pRaw->cPartDescs; i++)
+        {
+            PVBOXHDDRAWPARTDESC pPart = &pRaw->pPartDescs[i];
+            pExtent = &pImage->pExtents[cExtents++];
+
+            if (uStart < pPart->uStart)
             {
-                if (uStart != pPart->uPartitionDataStart)
-                {
-                    pExtent = &pImage->pExtents[cExtents++];
-                    pExtent->pszBasename = NULL;
-                    pExtent->pszFullname = NULL;
-                    pExtent->enmType = VMDKETYPE_ZERO;
-                    pExtent->cNominalSectors = VMDK_BYTE2SECTOR(pPart->uPartitionDataStart - uStart);
-                    pExtent->uSectorOffset = 0;
-                    pExtent->enmAccess = VMDKACCESS_READWRITE;
-                    pExtent->fMetaDirty = false;
-                }
-                uStart = pPart->uPartitionDataStart + pPart->cbPartitionData;
+                pExtent->pszBasename = NULL;
+                pExtent->pszFullname = NULL;
+                pExtent->enmType = VMDKETYPE_ZERO;
+                pExtent->cNominalSectors = VMDK_BYTE2SECTOR(pPart->uStart - uStart);
+                pExtent->uSectorOffset = 0;
+                pExtent->enmAccess = VMDKACCESS_READWRITE;
+                pExtent->fMetaDirty = false;
+                /* go to next extent */
                 pExtent = &pImage->pExtents[cExtents++];
+            }
+            uStart = pPart->uStart + pPart->cbData;
+
+            if (pPart->pvPartitionData)
+            {
                 /* Set up basename for extent description. Can't use StrDup. */
                 size_t cbBasename = strlen(pszPartition) + 1;
@@ -3585,5 +3575,5 @@
                 pExtent->pszFullname = pszFullname;
                 pExtent->enmType = VMDKETYPE_FLAT;
-                pExtent->cNominalSectors = VMDK_BYTE2SECTOR(pPart->cbPartitionData);
+                pExtent->cNominalSectors = VMDK_BYTE2SECTOR(pPart->cbData);
                 pExtent->uSectorOffset = uPartOffset;
                 pExtent->enmAccess = VMDKACCESS_READWRITE;
@@ -3599,24 +3589,11 @@
                                      VMDK_SECTOR2BYTE(uPartOffset),
                                      pPart->pvPartitionData,
-                                     pPart->cbPartitionData, NULL);
+                                     pPart->cbData, NULL);
                 if (RT_FAILURE(rc))
                     return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not write partition data to '%s'"), pExtent->pszFullname);
-                uPartOffset += VMDK_BYTE2SECTOR(pPart->cbPartitionData);
+                uPartOffset += VMDK_BYTE2SECTOR(pPart->cbData);
             }
-            if (pPart->cbPartition)
+            else
             {
-                if (uStart != pPart->uPartitionStart)
-                {
-                    pExtent = &pImage->pExtents[cExtents++];
-                    pExtent->pszBasename = NULL;
-                    pExtent->pszFullname = NULL;
-                    pExtent->enmType = VMDKETYPE_ZERO;
-                    pExtent->cNominalSectors = VMDK_BYTE2SECTOR(pPart->uPartitionStart - uStart);
-                    pExtent->uSectorOffset = 0;
-                    pExtent->enmAccess = VMDKACCESS_READWRITE;
-                    pExtent->fMetaDirty = false;
-                }
-                uStart = pPart->uPartitionStart + pPart->cbPartition;
-                pExtent = &pImage->pExtents[cExtents++];
                 if (pPart->pszRawDevice)
                 {
@@ -3633,6 +3610,6 @@
                         return VERR_NO_MEMORY;
                     pExtent->enmType = VMDKETYPE_FLAT;
-                    pExtent->cNominalSectors = VMDK_BYTE2SECTOR(pPart->cbPartition);
-                    pExtent->uSectorOffset = VMDK_BYTE2SECTOR(pPart->uPartitionStartOffset);
+                    pExtent->cNominalSectors = VMDK_BYTE2SECTOR(pPart->cbData);
+                    pExtent->uSectorOffset = VMDK_BYTE2SECTOR(pPart->uStartOffset);
                     pExtent->enmAccess = VMDKACCESS_READWRITE;
                     pExtent->fMetaDirty = false;
@@ -3650,5 +3627,5 @@
                     pExtent->pszFullname = NULL;
                     pExtent->enmType = VMDKETYPE_ZERO;
-                    pExtent->cNominalSectors = VMDK_BYTE2SECTOR(pPart->cbPartition);
+                    pExtent->cNominalSectors = VMDK_BYTE2SECTOR(pPart->cbData);
                     pExtent->uSectorOffset = 0;
                     pExtent->enmAccess = VMDKACCESS_READWRITE;
Index: /trunk/src/VBox/Frontends/VBoxManage/VBoxInternalManage.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxManage/VBoxInternalManage.cpp	(revision 29648)
+++ /trunk/src/VBox/Frontends/VBoxManage/VBoxInternalManage.cpp	(revision 29649)
@@ -496,4 +496,14 @@
 }
 
+static int handleVDMessage(void *pvUser, const char *pszFormat, ...)
+{
+    NOREF(pvUser);
+    va_list args;
+    va_start(args, pszFormat);
+    int rc = RTPrintfV(pszFormat, args);
+    va_end(args);
+    return rc;
+}
+
 static int CmdSetHDUUID(int argc, char **argv, ComPtr<IVirtualBox> aVirtualBox, ComPtr<ISession> aSession)
 {
@@ -525,5 +535,5 @@
     vdInterfaceErrorCallbacks.enmInterface = VDINTERFACETYPE_ERROR;
     vdInterfaceErrorCallbacks.pfnError     = handleVDError;
-    vdInterfaceErrorCallbacks.pfnMessage   = NULL;
+    vdInterfaceErrorCallbacks.pfnMessage   = handleVDMessage;
 
     rc = VDInterfaceAdd(&vdInterfaceError, "VBoxManage_IError", VDINTERFACETYPE_ERROR,
@@ -557,14 +567,4 @@
 }
 
-
-static int handleVDMessage(void *pvUser, const char *pszFormat, ...)
-{
-    NOREF(pvUser);
-    va_list args;
-    va_start(args, pszFormat);
-    int rc = RTPrintfV(pszFormat, args);
-    va_end(args);
-    return rc;
-}
 
 static int CmdDumpHDInfo(int argc, char **argv, ComPtr<IVirtualBox> aVirtualBox, ComPtr<ISession> aSession)
@@ -769,30 +769,24 @@
     }
 
-    /* Now do a lot of consistency checking. */
-    uint64_t uPrevEnd = 0;
-    for (unsigned i = 0; i < pPart->cPartitions-1; i++)
-    {
-        if (pPart->aPartitions[i].cPartDataSectors)
-        {
-            if (pPart->aPartitions[i].uPartDataStart < uPrevEnd)
-            {
-                RTPrintf("Overlapping partition description areas. Aborting\n");
-                return VERR_INVALID_PARAMETER;
-            }
-            uPrevEnd = pPart->aPartitions[i].uPartDataStart + pPart->aPartitions[i].cPartDataSectors;
-        }
-        if (pPart->aPartitions[i].uStart < uPrevEnd)
-        {
-            RTPrintf("Overlapping partitions. Aborting\n");
-            return VERR_INVALID_PARAMETER;
-        }
-        if (!PARTTYPE_IS_EXTENDED(pPart->aPartitions[i].uType))
-            uPrevEnd = pPart->aPartitions[i].uStart + pPart->aPartitions[i].uSize;
-    }
-
     /* Fill out partitioning location info for MBR. */
     pPart->aPartitions[0].uPartDataStart = 0;
     pPart->aPartitions[0].cPartDataSectors = pPart->aPartitions[0].uStart;
 
+    /* Now do a some partition table consistency checking, to reject the most
+     * obvious garbage which can lead to trouble later. */
+    uint64_t uPrevEnd = 0;
+    for (unsigned i = 0; i < pPart->cPartitions-1; i++)
+    {
+        if (pPart->aPartitions[i].cPartDataSectors)
+            uPrevEnd = pPart->aPartitions[i].uPartDataStart + pPart->aPartitions[i].cPartDataSectors;
+        if (pPart->aPartitions[i].uStart < uPrevEnd)
+        {
+            RTPrintf("Overlapping partitions. Aborting\n");
+            return VERR_INVALID_PARAMETER;
+        }
+        if (!PARTTYPE_IS_EXTENDED(pPart->aPartitions[i].uType))
+            uPrevEnd = pPart->aPartitions[i].uStart + pPart->aPartitions[i].uSize;
+    }
+
     return VINF_SUCCESS;
 }
@@ -833,13 +827,11 @@
     HOSTPARTITIONS partitions;
     vrc = partRead(RawFile, &partitions);
-    if (RT_FAILURE(vrc))
-        return vrc;
+    /* Don't bail out on errors, print the table and return the result code. */
 
     RTPrintf("Number  Type   StartCHS       EndCHS      Size (MiB)  Start (Sect)\n");
     for (unsigned i = 0; i < partitions.cPartitions; i++)
     {
-        /* Suppress printing the extended partition. Otherwise people
-         * might add it to the list of partitions for raw partition
-         * access (which is not good). */
+        /* Don't show the extended partition, otherwise users might think they
+         * can add it to the list of partitions for raw partition access. */
         if (PARTTYPE_IS_EXTENDED(partitions.aPartitions[i].uType))
             continue;
@@ -858,5 +850,21 @@
     }
 
-    return 0;
+    return vrc;
+}
+
+static PVBOXHDDRAWPARTDESC appendPartDesc(uint32_t *pcPartDescs, PVBOXHDDRAWPARTDESC *ppPartDescs)
+{
+    (*pcPartDescs)++;
+    PVBOXHDDRAWPARTDESC p;
+    p = (PVBOXHDDRAWPARTDESC)RTMemRealloc(*ppPartDescs,
+                                          *pcPartDescs * sizeof(VBOXHDDRAWPARTDESC));
+    *ppPartDescs = p;
+    if (p)
+    {
+        p = p + *pcPartDescs - 1;
+        memset(p, '\0', sizeof(VBOXHDDRAWPARTDESC));
+    }
+
+    return p;
 }
 
@@ -874,6 +882,4 @@
     PVBOXHDD pDisk = NULL;
     VBOXHDDRAW RawDescriptor;
-    HOSTPARTITIONS partitions;
-    uint32_t uPartitions = 0;
     PVDINTERFACE pVDIfs = NULL;
 
@@ -1138,5 +1144,8 @@
         RawDescriptor.fRawDisk = false;
         RawDescriptor.pszRawDisk = NULL;
-        RawDescriptor.cPartitions = 0;
+        RawDescriptor.cPartDescs = 0;
+        RawDescriptor.pPartDescs = NULL;
+
+        uint32_t uPartitions = 0;
 
         const char *p = pszPartitions;
@@ -1163,4 +1172,5 @@
         }
 
+        HOSTPARTITIONS partitions;
         vrc = partRead(RawFile, &partitions);
         if (RT_FAILURE(vrc))
@@ -1186,94 +1196,29 @@
         }
 
-        RawDescriptor.cPartitions = partitions.cPartitions;
-        RawDescriptor.pPartitions = (PVBOXHDDRAWPART)RTMemAllocZ(partitions.cPartitions * sizeof(VBOXHDDRAWPART));
-        if (!RawDescriptor.pPartitions)
-        {
-            RTPrintf("Out of memory allocating the partition list for '%s'\n", rawdisk.raw());
-            vrc = VERR_NO_MEMORY;
-            goto out;
-        }
         for (unsigned i = 0; i < partitions.cPartitions; i++)
         {
-            if (uPartitions & RT_BIT(partitions.aPartitions[i].uIndex))
-            {
-                if (fRelative)
+            PVBOXHDDRAWPARTDESC pPartDesc = NULL;
+
+            /* first dump the MBR/EPT data area */
+            if (partitions.aPartitions[i].cPartDataSectors)
+            {
+                pPartDesc = appendPartDesc(&RawDescriptor.cPartDescs,
+                                           &RawDescriptor.pPartDescs);
+                if (!pPartDesc)
                 {
-#ifdef RT_OS_LINUX
-                    /* Refer to the correct partition and use offset 0. */
-                    char *pszRawName;
-                    vrc = RTStrAPrintf(&pszRawName, "%s%u", rawdisk.raw(),
-                                       partitions.aPartitions[i].uIndex);
-                    if (RT_FAILURE(vrc))
-                    {
-                        RTPrintf("Error creating reference to individual partition %u, rc=%Rrc\n",
-                                 partitions.aPartitions[i].uIndex, vrc);
-                        goto out;
-                    }
-                    RawDescriptor.pPartitions[i].pszRawDevice = pszRawName;
-                    RawDescriptor.pPartitions[i].uPartitionStartOffset = 0;
-                    RawDescriptor.pPartitions[i].uPartitionStart = partitions.aPartitions[i].uStart * 512;
-#elif defined(RT_OS_DARWIN)
-                    /* Refer to the correct partition and use offset 0. */
-                    char *pszRawName;
-                    vrc = RTStrAPrintf(&pszRawName, "%ss%u", rawdisk.raw(),
-                                       partitions.aPartitions[i].uIndex);
-                    if (RT_FAILURE(vrc))
-                    {
-                        RTPrintf("Error creating reference to individual partition %u, rc=%Rrc\n",
-                                 partitions.aPartitions[i].uIndex, vrc);
-                        goto out;
-                    }
-                    RawDescriptor.pPartitions[i].pszRawDevice = pszRawName;
-                    RawDescriptor.pPartitions[i].uPartitionStartOffset = 0;
-                    RawDescriptor.pPartitions[i].uPartitionStart = partitions.aPartitions[i].uStart * 512;
-#else
-                    /** @todo not implemented yet for Windows host. Treat just
-                     * like not specified (this code is actually never reached). */
-                    RawDescriptor.pPartitions[i].pszRawDevice = rawdisk.raw();
-                    RawDescriptor.pPartitions[i].uPartitionStartOffset = partitions.aPartitions[i].uStart * 512;
-                    RawDescriptor.pPartitions[i].uPartitionStart = partitions.aPartitions[i].uStart * 512;
-#endif
+                    RTPrintf("Out of memory allocating the partition list for '%s'\n", rawdisk.raw());
+                    vrc = VERR_NO_MEMORY;
+                    goto out;
                 }
-                else
-                {
-                    /* This is the "everything refers to the base raw device"
-                     * variant. This requires opening the base device in RW
-                     * mode even for creation. */
-                    RawDescriptor.pPartitions[i].pszRawDevice = rawdisk.raw();
-                    RawDescriptor.pPartitions[i].uPartitionStartOffset = partitions.aPartitions[i].uStart * 512;
-                    RawDescriptor.pPartitions[i].uPartitionStart = partitions.aPartitions[i].uStart * 512;
-                }
-            }
-            else
-            {
-                /* Suppress access to this partition. */
-                RawDescriptor.pPartitions[i].pszRawDevice = NULL;
-                RawDescriptor.pPartitions[i].uPartitionStartOffset = 0;
-                /* This is used in the plausibility check in the creation
-                 * code. In theory it's a dummy, but I don't want to make
-                 * the VMDK creatiion any more complicated than what it needs
-                 * to be. */
-                RawDescriptor.pPartitions[i].uPartitionStart = partitions.aPartitions[i].uStart * 512;
-            }
-            if (PARTTYPE_IS_EXTENDED(partitions.aPartitions[i].uType))
-            {
-                /* Suppress exporting the actual extended partition. Only
-                 * logical partitions should be processed. However completely
-                 * ignoring it leads to leaving out the MBR data. */
-                RawDescriptor.pPartitions[i].cbPartition = 0;
-            }
-            else
-                RawDescriptor.pPartitions[i].cbPartition =  partitions.aPartitions[i].uSize * 512;
-            RawDescriptor.pPartitions[i].uPartitionDataStart = partitions.aPartitions[i].uPartDataStart * 512;
-            /** @todo the clipping below isn't 100% accurate, as it should
-             * actually clip to the track size. However that's easier said
-             * than done as figuring out the track size is heuristics. */
-            RawDescriptor.pPartitions[i].cbPartitionData = RT_MIN(partitions.aPartitions[i].cPartDataSectors, 63) * 512;
-            if (RawDescriptor.pPartitions[i].cbPartitionData)
-            {
-                Assert (RawDescriptor.pPartitions[i].cbPartitionData -
-                        (size_t)RawDescriptor.pPartitions[i].cbPartitionData == 0);
-                void *pPartData = RTMemAlloc((size_t)RawDescriptor.pPartitions[i].cbPartitionData);
+
+                /** @todo the clipping below isn't 100% accurate, as it should
+                 * actually clip to the track size. However that's easier said
+                 * than done as figuring out the track size is heuristics. In
+                 * any case the clipping is adjusted later after sorting, to
+                 * prevent overlapping data areas on the resulting image. */
+                pPartDesc->cbData = RT_MIN(partitions.aPartitions[i].cPartDataSectors, 63) * 512;
+                pPartDesc->uStart = partitions.aPartitions[i].uPartDataStart * 512;
+                Assert(pPartDesc->cbData - (size_t)pPartDesc->cbData == 0);
+                void *pPartData = RTMemAlloc((size_t)pPartDesc->cbData);
                 if (!pPartData)
                 {
@@ -1282,5 +1227,6 @@
                     goto out;
                 }
-                vrc = RTFileReadAt(RawFile, partitions.aPartitions[i].uPartDataStart * 512, pPartData, (size_t)RawDescriptor.pPartitions[i].cbPartitionData, NULL);
+                vrc = RTFileReadAt(RawFile, partitions.aPartitions[i].uPartDataStart * 512,
+                                   pPartData, (size_t)pPartDesc->cbData, NULL);
                 if (RT_FAILURE(vrc))
                 {
@@ -1307,5 +1253,113 @@
                     }
                 }
-                RawDescriptor.pPartitions[i].pvPartitionData = pPartData;
+                pPartDesc->pvPartitionData = pPartData;
+            }
+
+            if (PARTTYPE_IS_EXTENDED(partitions.aPartitions[i].uType))
+            {
+                /* Suppress exporting the actual extended partition. Only
+                 * logical partitions should be processed. However completely
+                 * ignoring it leads to leaving out the EBR data. */
+                continue;
+            }
+
+            /* set up values for non-relative device names */
+            const char *pszRawName = rawdisk.raw();
+            uint64_t uStartOffset = partitions.aPartitions[i].uStart * 512;
+
+            pPartDesc = appendPartDesc(&RawDescriptor.cPartDescs,
+                                       &RawDescriptor.pPartDescs);
+            if (!pPartDesc)
+            {
+                RTPrintf("Out of memory allocating the partition list for '%s'\n", rawdisk.raw());
+                vrc = VERR_NO_MEMORY;
+                goto out;
+            }
+
+            if (uPartitions & RT_BIT(partitions.aPartitions[i].uIndex))
+            {
+                if (fRelative)
+                {
+#ifdef RT_OS_LINUX
+                    /* Refer to the correct partition and use offset 0. */
+                    char *psz;
+                    vrc = RTStrAPrintf(&psz, "%s%u", rawdisk.raw(),
+                                       partitions.aPartitions[i].uIndex);
+                    if (RT_FAILURE(vrc))
+                    {
+                        RTPrintf("Error creating reference to individual partition %u, rc=%Rrc\n",
+                                 partitions.aPartitions[i].uIndex, vrc);
+                        goto out;
+                    }
+                    pszRawName = psz;
+                    uStartOffset = 0;
+#elif defined(RT_OS_DARWIN)
+                    /* Refer to the correct partition and use offset 0. */
+                    char *psz;
+                    vrc = RTStrAPrintf(&psz, "%ss%u", rawdisk.raw(),
+                                       partitions.aPartitions[i].uIndex);
+                    if (RT_FAILURE(vrc))
+                    {
+                        RTPrintf("Error creating reference to individual partition %u, rc=%Rrc\n",
+                                 partitions.aPartitions[i].uIndex, vrc);
+                        goto out;
+                    }
+                    pszRawName = psz;
+                    uStartOffset = 0;
+#else
+                    /** @todo not implemented for other hosts. Treat just like
+                     * not specified (this code is actually never reached). */
+#endif
+                }
+
+                pPartDesc->pszRawDevice = pszRawName;
+                pPartDesc->uStartOffset = uStartOffset;
+            }
+            else
+            {
+                pPartDesc->pszRawDevice = NULL;
+                pPartDesc->uStartOffset = 0;
+            }
+
+            pPartDesc->uStart = partitions.aPartitions[i].uStart * 512;
+            pPartDesc->cbData = partitions.aPartitions[i].uSize * 512;
+        }
+
+        /* Sort data areas in ascending order of start. */
+        for (unsigned i = 0; i < RawDescriptor.cPartDescs-1; i++)
+        {
+            unsigned uMinIdx = i;
+            uint64_t uMinVal = RawDescriptor.pPartDescs[i].uStart;
+            for (unsigned j = i + 1; j < RawDescriptor.cPartDescs; j++)
+            {
+                if (RawDescriptor.pPartDescs[j].uStart < uMinVal)
+                {
+                    uMinIdx = j;
+                    uMinVal = RawDescriptor.pPartDescs[j].uStart;
+                }
+            }
+            if (uMinIdx != i)
+            {
+                /* Swap entries at index i and uMinIdx. */
+                VBOXHDDRAWPARTDESC tmp;
+                memcpy(&tmp, &RawDescriptor.pPartDescs[i], sizeof(tmp));
+                memcpy(&RawDescriptor.pPartDescs[i], &RawDescriptor.pPartDescs[uMinIdx], sizeof(tmp));
+                memcpy(&RawDescriptor.pPartDescs[uMinIdx], &tmp, sizeof(tmp));
+            }
+        }
+
+        /* Have a second go at MBR/EPT area clipping. Now that the data areas
+         * are sorted this is much easier to get 100% right. */
+        for (unsigned i = 0; i < RawDescriptor.cPartDescs-1; i++)
+        {
+            if (RawDescriptor.pPartDescs[i].pvPartitionData)
+            {
+                RawDescriptor.pPartDescs[i].cbData = RT_MIN(RawDescriptor.pPartDescs[i+1].uStart - RawDescriptor.pPartDescs[i].uStart, RawDescriptor.pPartDescs[i].cbData);
+                if (!RawDescriptor.pPartDescs[i].cbData)
+                {
+                    RTPrintf("MBR/EPT overlaps with data area\n");
+                    vrc = VERR_INVALID_PARAMETER;
+                    goto out;
+                }
             }
         }
@@ -1313,4 +1367,17 @@
 
     RTFileClose(RawFile);
+
+#ifdef DEBUG_klaus
+    RTPrintf("#            start         length    startoffset  partdataptr  device\n");
+    for (unsigned i = 0; i < RawDescriptor.cPartDescs; i++)
+    {
+        RTPrintf("%2u  %14RU64 %14RU64 %14RU64 %#18p %s\n", i,
+                 RawDescriptor.pPartDescs[i].uStart,
+                 RawDescriptor.pPartDescs[i].cbData,
+                 RawDescriptor.pPartDescs[i].uStartOffset,
+                 RawDescriptor.pPartDescs[i].pvPartitionData,
+                 RawDescriptor.pPartDescs[i].pszRawDevice);
+    }
+#endif
 
     VDINTERFACE      vdInterfaceError;
@@ -1319,5 +1386,5 @@
     vdInterfaceErrorCallbacks.enmInterface = VDINTERFACETYPE_ERROR;
     vdInterfaceErrorCallbacks.pfnError     = handleVDError;
-    vdInterfaceErrorCallbacks.pfnMessage   = NULL;
+    vdInterfaceErrorCallbacks.pfnMessage   = handleVDMessage;
 
     vrc = VDInterfaceAdd(&vdInterfaceError, "VBoxManage_IError", VDINTERFACETYPE_ERROR,
@@ -1357,17 +1424,14 @@
     if (pszPartitions)
     {
-        for (unsigned i = 0; i < partitions.cPartitions; i++)
-        {
-            if (uPartitions & RT_BIT(partitions.aPartitions[i].uIndex))
-            {
-                if (fRelative)
-                {
-#ifdef RT_OS_LINUX
-                    /* Free memory allocated above. */
-                    RTStrFree((char *)(void *)RawDescriptor.pPartitions[i].pszRawDevice);
-#endif /* RT_OS_LINUX */
-                }
-            }
-        }
+        for (unsigned i = 0; i < RawDescriptor.cPartDescs; i++)
+        {
+            /* Free memory allocated for relative device name. */
+            if (RawDescriptor.pPartDescs[i].pszRawDevice)
+                RTStrFree((char *)(void *)RawDescriptor.pPartDescs[i].pszRawDevice);
+            if (RawDescriptor.pPartDescs[i].pvPartitionData)
+                RTMemFree(RawDescriptor.pPartDescs[i].pvPartitionData);
+        }
+        if (RawDescriptor.pPartDescs)
+            RTMemFree(RawDescriptor.pPartDescs);
     }
 
@@ -1429,5 +1493,5 @@
     vdInterfaceErrorCallbacks.enmInterface = VDINTERFACETYPE_ERROR;
     vdInterfaceErrorCallbacks.pfnError     = handleVDError;
-    vdInterfaceErrorCallbacks.pfnMessage   = NULL;
+    vdInterfaceErrorCallbacks.pfnMessage   = handleVDMessage;
 
     int vrc = VDInterfaceAdd(&vdInterfaceError, "VBoxManage_IError", VDINTERFACETYPE_ERROR,
@@ -1511,5 +1575,5 @@
     vdInterfaceErrorCallbacks.enmInterface = VDINTERFACETYPE_ERROR;
     vdInterfaceErrorCallbacks.pfnError     = handleVDError;
-    vdInterfaceErrorCallbacks.pfnMessage   = NULL;
+    vdInterfaceErrorCallbacks.pfnMessage   = handleVDMessage;
 
     int vrc = VDInterfaceAdd(&vdInterfaceError, "VBoxManage_IError", VDINTERFACETYPE_ERROR,
@@ -1676,5 +1740,5 @@
     vdInterfaceErrorCallbacks.enmInterface = VDINTERFACETYPE_ERROR;
     vdInterfaceErrorCallbacks.pfnError     = handleVDError;
-    vdInterfaceErrorCallbacks.pfnMessage   = NULL;
+    vdInterfaceErrorCallbacks.pfnMessage   = handleVDMessage;
 
     vrc = VDInterfaceAdd(&vdInterfaceError, "VBoxManage_IError", VDINTERFACETYPE_ERROR,
