Index: /trunk/src/VBox/Devices/Storage/VmdkHDDCore.cpp
===================================================================
--- /trunk/src/VBox/Devices/Storage/VmdkHDDCore.cpp	(revision 32882)
+++ /trunk/src/VBox/Devices/Storage/VmdkHDDCore.cpp	(revision 32883)
@@ -538,6 +538,4 @@
 *******************************************************************************/
 
-static void vmdkFreeGrainDirectory(PVMDKEXTENT pExtent);
-
 static void vmdkFreeExtentData(PVMDKIMAGE pImage, PVMDKEXTENT pExtent,
                                bool fDelete);
@@ -999,5 +997,6 @@
         DeflateState.pvCompGrain = pExtent->pvCompGrain;
 
-        rc = RTZipCompCreate(&pZip, &DeflateState, vmdkFileDeflateHelper, RTZIPTYPE_ZLIB, RTZIPLEVEL_DEFAULT);
+        rc = RTZipCompCreate(&pZip, &DeflateState, vmdkFileDeflateHelper,
+                             RTZIPTYPE_ZLIB, RTZIPLEVEL_DEFAULT);
         if (RT_FAILURE(rc))
             return rc;
@@ -1034,4 +1033,5 @@
                 return rc;
 
+/** @todo remove this code */
             /* Set the file size to remove old garbage in case the block is
              * rewritten. Cannot cause data loss as the code calling this
@@ -1167,9 +1167,93 @@
 }
 
+/**
+ * Internal: free all buffers associated with grain directories.
+ */
+static void vmdkFreeGrainDirectory(PVMDKEXTENT pExtent)
+{
+    if (pExtent->pGD)
+    {
+        RTMemFree(pExtent->pGD);
+        pExtent->pGD = NULL;
+    }
+    if (pExtent->pRGD)
+    {
+        RTMemFree(pExtent->pRGD);
+        pExtent->pRGD = NULL;
+    }
+    if (pExtent->pvCompGrain)
+    {
+        RTMemFree(pExtent->pvCompGrain);
+        pExtent->pvCompGrain = NULL;
+    }
+    if (pExtent->pvGrain)
+    {
+        RTMemFree(pExtent->pvGrain);
+        pExtent->pvGrain = NULL;
+    }
+}
+
+/**
+ * Internal: allocate all buffers associated with grain directories. This
+ * includes the compressed/uncompressed buffers for streamOptimized images.
+ */
+static int vmdkAllocGrainDirectory(PVMDKIMAGE pImage, PVMDKEXTENT pExtent)
+{
+    size_t cbGD = pExtent->cGDEntries * sizeof(uint32_t);
+    uint32_t *pGD = NULL, *pRGD = NULL;
+
+    pGD = (uint32_t *)RTMemAllocZ(cbGD);
+    if (!pGD)
+    {
+        rc = VERR_NO_MEMORY;
+        goto out;
+    }
+    pExtent->pGD = pGD;
+
+    if (pExtent->uSectorRGD)
+    {
+        pRGD = (uint32_t *)RTMemAllocZ(cbGD);
+        if (!pRGD)
+        {
+            rc = VERR_NO_MEMORY;
+            goto out;
+        }
+        pExtent->pRGD = pRGD;
+    }
+
+    if (pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED)
+    {
+        /* streamOptimized extents need a compressed grain buffer, which must
+         * be big enough to hold uncompressible data (which needs ~8 bytes
+         * more than the uncompressed data), the marker and padding. */
+        pExtent->cbCompGrain = RT_ALIGN_Z(  VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain)
+                                          + 8 + sizeof(VMDKMARKER), 512);
+        pExtent->pvCompGrain = RTMemAlloc(pExtent->cbCompGrain);
+        if (!pExtent->pvCompGrain)
+        {
+            rc = VERR_NO_MEMORY;
+            goto out;
+        }
+
+        /* streamOptimized extents need a decompressed grain buffer. */
+        pExtent->pvGrain = RTMemAlloc(VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain));
+        if (!pExtent->pvGrain)
+        {
+            rc = VERR_NO_MEMORY;
+            goto out;
+        }
+    }
+
+out:
+    if (RT_FAILURE(rc))
+        vmdkFreeGrainDirectory(pExtent);
+    return rc;
+}
+
 static int vmdkReadGrainDirectory(PVMDKIMAGE pImage, PVMDKEXTENT pExtent)
 {
     int rc = VINF_SUCCESS;
     unsigned i;
-    uint32_t *pGD = NULL, *pRGD = NULL, *pGDTmp, *pRGDTmp;
+    uint32_t *pGDTmp, *pRGDTmp;
     size_t cbGD = pExtent->cGDEntries * sizeof(uint32_t);
 
@@ -1177,11 +1261,8 @@
         goto out;
 
-    pGD = (uint32_t *)RTMemAllocZ(cbGD);
-    if (!pGD)
-    {
-        rc = VERR_NO_MEMORY;
-        goto out;
-    }
-    pExtent->pGD = pGD;
+    rc = vmdkAllocGrainDirectory(pImage, pExtent);
+    if (RT_FAILED(rc))
+        goto out;
+
     /* The VMDK 1.1 spec seems to talk about compressed grain directories,
      * but in reality they are not compressed. */
@@ -1200,10 +1281,4 @@
     if (pExtent->uSectorRGD)
     {
-        pRGD = (uint32_t *)RTMemAllocZ(cbGD);
-        if (!pRGD)
-        {
-            rc = VERR_NO_MEMORY;
-            goto out;
-        }
         pExtent->pRGD = pRGD;
         /* The VMDK 1.1 spec seems to talk about compressed grain directories,
@@ -1343,24 +1418,4 @@
         RTMemTmpFree(pTmpGT);
 
-        /* streamOptimized extents need a compressed grain buffer, which must
-         * be big enough to hold uncompressible data (which needs ~8 bytes
-         * more than the uncompressed data), the marker and padding. */
-        pExtent->cbCompGrain = RT_ALIGN_Z(  VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain)
-                                          + 8 + sizeof(VMDKMARKER), 512);
-        pExtent->pvCompGrain = RTMemAlloc(pExtent->cbCompGrain);
-        if (!pExtent->pvCompGrain)
-        {
-            rc = VERR_NO_MEMORY;
-            goto out;
-        }
-
-        /* streamOptimized extents need a decompressed grain buffer. */
-        pExtent->pvGrain = RTMemAlloc(VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain));
-        if (!pExtent->pvGrain)
-        {
-            rc = VERR_NO_MEMORY;
-            goto out;
-        }
-
         if (uLastGrainSector)
         {
@@ -1394,5 +1449,4 @@
     int rc = VINF_SUCCESS;
     unsigned i;
-    uint32_t *pGD = NULL, *pRGD = NULL;
     size_t cbGD = pExtent->cGDEntries * sizeof(uint32_t);
     size_t cbGDRounded = RT_ALIGN_64(pExtent->cGDEntries * sizeof(uint32_t), 512);
@@ -1405,24 +1459,4 @@
         cbGTRounded = 0;
 
-    pGD = (uint32_t *)RTMemAllocZ(cbGD);
-    if (!pGD)
-    {
-        rc = VERR_NO_MEMORY;
-        goto out;
-    }
-    pExtent->pGD = pGD;
-    if (!(pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED))
-    {
-        pRGD = (uint32_t *)RTMemAllocZ(cbGD);
-        if (!pRGD)
-        {
-            rc = VERR_NO_MEMORY;
-            goto out;
-        }
-        pExtent->pRGD = pRGD;
-    }
-    else
-        pExtent->pRGD = NULL;
-
     if (uStartSector != VMDK_GD_AT_END)
     {
@@ -1462,4 +1496,8 @@
         pExtent->uSectorGD = uStartSector;
     }
+
+    rc = vmdkAllocGrainDirectory(pImage, pExtent);
+    if (RT_FAILED(rc))
+        goto out;
 
     if (fPreAlloc)
@@ -1507,45 +1545,8 @@
     pExtent->cOverheadSectors = VMDK_BYTE2SECTOR(cbOverhead);
 
-    /* streamOptimized extents need a compressed grain buffer, which must
-     * be big enough to hold uncompressible data (which needs ~8 bytes
-     * more than the uncompressed data), the marker and padding. */
-    pExtent->cbCompGrain = RT_ALIGN_Z(  VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain)
-                                      + 8 + sizeof(VMDKMARKER), 512);
-    pExtent->pvCompGrain = RTMemAlloc(pExtent->cbCompGrain);
-    if (!pExtent->pvCompGrain)
-    {
-        rc = VERR_NO_MEMORY;
-        goto out;
-    }
-
-    /* streamOptimized extents need a grain decompress buffer. */
-    if (pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED)
-    {
-        pExtent->pvGrain = RTMemAlloc(VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain));
-        if (!pExtent->pvGrain)
-        {
-            rc = VERR_NO_MEMORY;
-            goto out;
-        }
-    }
-
 out:
     if (RT_FAILURE(rc))
         vmdkFreeGrainDirectory(pExtent);
     return rc;
-}
-
-static void vmdkFreeGrainDirectory(PVMDKEXTENT pExtent)
-{
-    if (pExtent->pGD)
-    {
-        RTMemFree(pExtent->pGD);
-        pExtent->pGD = NULL;
-    }
-    if (pExtent->pRGD)
-    {
-        RTMemFree(pExtent->pRGD);
-        pExtent->pRGD = NULL;
-    }
 }
 
@@ -4519,17 +4520,17 @@
     }
 
+    if (pfnProgress)
+        pfnProgress(pvUser, uPercentStart + uPercentSpan * 70 / 100);
+
+    rc = vmdkWriteDescriptor(pImage);
+    if (RT_FAILURE(rc))
+    {
+        rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write VMDK descriptor in '%s'"), pImage->pszFilename);
+        goto out;
+    }
+
     /* Skip over the overhead area. */
     rc = vmdkFileSetSize(pImage, pExtent->pFile,
                          VMDK_SECTOR2BYTE(pExtent->cOverheadSectors));
-
-    if (pfnProgress)
-        pfnProgress(pvUser, uPercentStart + uPercentSpan * 70 / 100);
-
-    rc = vmdkWriteDescriptor(pImage);
-    if (RT_FAILURE(rc))
-    {
-        rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write VMDK descriptor in '%s'"), pImage->pszFilename);
-        goto out;
-    }
 
 out:
