Index: trunk/src/VBox/Storage/VMDK.cpp
===================================================================
--- trunk/src/VBox/Storage/VMDK.cpp	(revision 38030)
+++ trunk/src/VBox/Storage/VMDK.cpp	(revision 38469)
@@ -410,8 +410,4 @@
     /** Descriptor file if applicable. */
     PVMDKFILE         pFile;
-    /** I/O interface. */
-    PVDINTERFACE      pInterfaceIO;
-    /** I/O interface callbacks. */
-    PVDINTERFACEIOINT pInterfaceIOCallbacks;
 
     /** Pointer to the per-disk VD interface list. */
@@ -421,7 +417,8 @@
 
     /** Error interface. */
-    PVDINTERFACE      pInterfaceError;
-    /** Error interface callbacks. */
-    PVDINTERFACEERROR pInterfaceErrorCallbacks;
+    PVDINTERFACEERROR pIfError;
+    /** I/O interface. */
+    PVDINTERFACEIOINT pIfIo;
+
 
     /** Pointer to the image extents. */
@@ -536,34 +533,4 @@
 
 /**
- * Internal: signal an error to the frontend.
- */
-DECLINLINE(int) vmdkError(PVMDKIMAGE pImage, int rc, RT_SRC_POS_DECL,
-                          const char *pszFormat, ...)
-{
-    va_list va;
-    va_start(va, pszFormat);
-    if (pImage->pInterfaceError && pImage->pInterfaceErrorCallbacks)
-        pImage->pInterfaceErrorCallbacks->pfnError(pImage->pInterfaceError->pvUser, rc, RT_SRC_POS_ARGS,
-                                                   pszFormat, va);
-    va_end(va);
-    return rc;
-}
-
-/**
- * Internal: signal an informational message to the frontend.
- */
-DECLINLINE(int) vmdkMessage(PVMDKIMAGE pImage, const char *pszFormat, ...)
-{
-    int rc = VINF_SUCCESS;
-    va_list va;
-    va_start(va, pszFormat);
-    if (pImage->pInterfaceError && pImage->pInterfaceErrorCallbacks)
-        rc = pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser,
-                                                          pszFormat, va);
-    va_end(va);
-    return rc;
-}
-
-/**
  * Internal: open a file (using a file descriptor cache to ensure each file
  * is only opened once - anything else can cause locking problems).
@@ -608,7 +575,6 @@
     pVmdkFile->fAsyncIO = fAsyncIO;
 
-    rc = pImage->pInterfaceIOCallbacks->pfnOpen(pImage->pInterfaceIO->pvUser,
-                                                pszFilename, fOpen,
-                                                &pVmdkFile->pStorage);
+    rc = vdIfIoIntFileOpen(pImage->pIfIo, pszFilename, fOpen,
+                           &pVmdkFile->pStorage);
     if (RT_SUCCESS(rc))
     {
@@ -660,9 +626,7 @@
             pImage->pFiles = pNext;
 
-        rc = pImage->pInterfaceIOCallbacks->pfnClose(pImage->pInterfaceIO->pvUser,
-                                                     pVmdkFile->pStorage);
+        rc = vdIfIoIntFileClose(pImage->pIfIo, pVmdkFile->pStorage);
         if (RT_SUCCESS(rc) && pVmdkFile->fDelete)
-            rc = pImage->pInterfaceIOCallbacks->pfnDelete(pImage->pInterfaceIO->pvUser,
-                                                          pVmdkFile->pszFilename);
+            rc = vdIfIoIntFileDelete(pImage->pIfIo, pVmdkFile->pszFilename);
         RTStrFree((char *)(void *)pVmdkFile->pszFilename);
         RTMemFree(pVmdkFile);
@@ -672,166 +636,4 @@
     return rc;
 }
-
-/**
- * Internal: rename a file (sync)
- */
-DECLINLINE(int) vmdkFileMove(PVMDKIMAGE pImage, const char *pszSrc,
-                             const char *pszDst, unsigned fMove)
-{
-    return pImage->pInterfaceIOCallbacks->pfnMove(pImage->pInterfaceIO->pvUser,
-                                                  pszSrc, pszDst, fMove);
-}
-
-/**
- * Internal: get the size of a file (sync/async)
- */
-DECLINLINE(int) vmdkFileGetSize(PVMDKIMAGE pImage, PVMDKFILE pVmdkFile,
-                                uint64_t *pcbSize)
-{
-    return pImage->pInterfaceIOCallbacks->pfnGetSize(pImage->pInterfaceIO->pvUser,
-                                                     pVmdkFile->pStorage,
-                                                     pcbSize);
-}
-
-/**
- * Internal: set the size of a file (sync/async)
- */
-DECLINLINE(int) vmdkFileSetSize(PVMDKIMAGE pImage, PVMDKFILE pVmdkFile,
-                                uint64_t cbSize)
-{
-    return pImage->pInterfaceIOCallbacks->pfnSetSize(pImage->pInterfaceIO->pvUser,
-                                                     pVmdkFile->pStorage,
-                                                     cbSize);
-}
-
-/**
- * Internal: read from a file (sync)
- */
-DECLINLINE(int) vmdkFileReadSync(PVMDKIMAGE pImage, PVMDKFILE pVmdkFile,
-                                 uint64_t uOffset, void *pvBuf,
-                                 size_t cbToRead, size_t *pcbRead)
-{
-    return pImage->pInterfaceIOCallbacks->pfnReadSync(pImage->pInterfaceIO->pvUser,
-                                                      pVmdkFile->pStorage, uOffset,
-                                                      pvBuf, cbToRead, pcbRead);
-}
-
-/**
- * Internal: write to a file (sync)
- */
-DECLINLINE(int) vmdkFileWriteSync(PVMDKIMAGE pImage, PVMDKFILE pVmdkFile,
-                                  uint64_t uOffset, const void *pvBuf,
-                                  size_t cbToWrite, size_t *pcbWritten)
-{
-    return pImage->pInterfaceIOCallbacks->pfnWriteSync(pImage->pInterfaceIO->pvUser,
-                                                       pVmdkFile->pStorage, uOffset,
-                                                       pvBuf, cbToWrite, pcbWritten);
-}
-
-/**
- * Internal: flush a file (sync)
- */
-DECLINLINE(int) vmdkFileFlush(PVMDKIMAGE pImage, PVMDKFILE pVmdkFile)
-{
-    return pImage->pInterfaceIOCallbacks->pfnFlushSync(pImage->pInterfaceIO->pvUser,
-                                                       pVmdkFile->pStorage);
-}
-
-/**
- * Internal: read user data (async)
- */
-DECLINLINE(int) vmdkFileReadUserAsync(PVMDKIMAGE pImage, PVMDKFILE pVmdkFile,
-                                      uint64_t uOffset, PVDIOCTX pIoCtx,
-                                      size_t cbRead)
-{
-    return pImage->pInterfaceIOCallbacks->pfnReadUserAsync(pImage->pInterfaceIO->pvUser,
-                                                           pVmdkFile->pStorage,
-                                                           uOffset, pIoCtx,
-                                                           cbRead);
-}
-
-/**
- * Internal: write user data (async)
- */
-DECLINLINE(int) vmdkFileWriteUserAsync(PVMDKIMAGE pImage, PVMDKFILE pVmdkFile,
-                                       uint64_t uOffset, PVDIOCTX pIoCtx,
-                                       size_t cbWrite,
-                                       PFNVDXFERCOMPLETED pfnComplete,
-                                       void *pvCompleteUser)
-{
-    return pImage->pInterfaceIOCallbacks->pfnWriteUserAsync(pImage->pInterfaceIO->pvUser,
-                                                            pVmdkFile->pStorage,
-                                                            uOffset, pIoCtx,
-                                                            cbWrite,
-                                                            pfnComplete,
-                                                            pvCompleteUser);
-}
-
-/**
- * Internal: read metadata (async)
- */
-DECLINLINE(int) vmdkFileReadMetaAsync(PVMDKIMAGE pImage, PVMDKFILE pVmdkFile,
-                                      uint64_t uOffset, void *pvBuffer,
-                                      size_t cbBuffer, PVDIOCTX pIoCtx,
-                                      PPVDMETAXFER ppMetaXfer,
-                                      PFNVDXFERCOMPLETED pfnComplete,
-                                      void *pvCompleteUser)
-{
-    return pImage->pInterfaceIOCallbacks->pfnReadMetaAsync(pImage->pInterfaceIO->pvUser,
-                                                           pVmdkFile->pStorage,
-                                                           uOffset, pvBuffer,
-                                                           cbBuffer, pIoCtx,
-                                                           ppMetaXfer,
-                                                           pfnComplete,
-                                                           pvCompleteUser);
-}
-
-/**
- * Internal: write metadata (async)
- */
-DECLINLINE(int) vmdkFileWriteMetaAsync(PVMDKIMAGE pImage, PVMDKFILE pVmdkFile,
-                                       uint64_t uOffset, void *pvBuffer,
-                                       size_t cbBuffer, PVDIOCTX pIoCtx,
-                                       PFNVDXFERCOMPLETED pfnComplete,
-                                       void *pvCompleteUser)
-{
-    return pImage->pInterfaceIOCallbacks->pfnWriteMetaAsync(pImage->pInterfaceIO->pvUser,
-                                                            pVmdkFile->pStorage,
-                                                            uOffset, pvBuffer,
-                                                            cbBuffer, pIoCtx,
-                                                            pfnComplete,
-                                                            pvCompleteUser);
-}
-
-/**
- * Internal: releases a metadata transfer handle (async)
- */
-DECLINLINE(void) vmdkFileMetaXferRelease(PVMDKIMAGE pImage, PVDMETAXFER pMetaXfer)
-{
-    pImage->pInterfaceIOCallbacks->pfnMetaXferRelease(pImage->pInterfaceIO->pvUser,
-                                                      pMetaXfer);
-}
-
-/**
- * Internal: flush a file (async)
- */
-DECLINLINE(int) vmdkFileFlushAsync(PVMDKIMAGE pImage, PVMDKFILE pVmdkFile,
-                                   PVDIOCTX pIoCtx)
-{
-    return pImage->pInterfaceIOCallbacks->pfnFlushAsync(pImage->pInterfaceIO->pvUser,
-                                                        pVmdkFile->pStorage, pIoCtx,
-                                                        NULL, NULL);
-}
-
-/**
- * Internal: sets the buffer to a specific byte (async)
- */
-DECLINLINE(int) vmdkFileIoCtxSet(PVMDKIMAGE pImage, PVDIOCTX pIoCtx,
-                                 int ch, size_t cbSet)
-{
-    return pImage->pInterfaceIOCallbacks->pfnIoCtxSet(pImage->pInterfaceIO->pvUser,
-                                                      pIoCtx, ch, cbSet);
-}
-
 
 static DECLCALLBACK(int) vmdkFileInflateHelper(void *pvUser, void *pvBuf, size_t cbBuf, size_t *pcbBuf)
@@ -888,6 +690,7 @@
         if (!pcvMarker)
         {
-            rc = vmdkFileReadSync(pImage, pExtent->pFile, uOffset, pMarker,
-                                  RT_OFFSETOF(VMDKMARKER, uType), NULL);
+            rc = vdIfIoIntFileReadSync(pImage->pIfIo, pExtent->pFile->pStorage,
+                                       uOffset, pMarker, RT_OFFSETOF(VMDKMARKER, uType),
+                                       NULL);
             if (RT_FAILURE(rc))
                 return rc;
@@ -909,12 +712,12 @@
 
         /* Compressed grain marker. Data follows immediately. */
-        rc = vmdkFileReadSync(pImage, pExtent->pFile,
-                              uOffset + RT_OFFSETOF(VMDKMARKER, uType),
-                                (uint8_t *)pExtent->pvCompGrain
-                              + RT_OFFSETOF(VMDKMARKER, uType),
-                                RT_ALIGN_Z(  cbCompSize
-                                           + RT_OFFSETOF(VMDKMARKER, uType),
-                                           512)
-                              - RT_OFFSETOF(VMDKMARKER, uType), NULL);
+        rc = vdIfIoIntFileReadSync(pImage->pIfIo, pExtent->pFile->pStorage,
+                                   uOffset + RT_OFFSETOF(VMDKMARKER, uType),
+                                    (uint8_t *)pExtent->pvCompGrain
+                                  + RT_OFFSETOF(VMDKMARKER, uType),
+                                   RT_ALIGN_Z(  cbCompSize
+                                              + RT_OFFSETOF(VMDKMARKER, uType),
+                                              512)
+                                   - RT_OFFSETOF(VMDKMARKER, uType), NULL);
 
         if (puLBA)
@@ -1021,6 +824,6 @@
             pMarker->cbSize = RT_H2LE_U32(  DeflateState.iOffset
                                           - RT_OFFSETOF(VMDKMARKER, uType));
-            rc = vmdkFileWriteSync(pImage, pExtent->pFile, uOffset, pMarker,
-                                   uSize, NULL);
+            rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pExtent->pFile->pStorage,
+                                        uOffset, pMarker, uSize, NULL);
             if (RT_FAILURE(rc))
                 return rc;
@@ -1258,11 +1061,11 @@
     /* The VMDK 1.1 spec seems to talk about compressed grain directories,
      * but in reality they are not compressed. */
-    rc = vmdkFileReadSync(pImage, pExtent->pFile,
-                          VMDK_SECTOR2BYTE(pExtent->uSectorGD),
-                          pExtent->pGD, cbGD, NULL);
+    rc = vdIfIoIntFileReadSync(pImage->pIfIo, pExtent->pFile->pStorage,
+                               VMDK_SECTOR2BYTE(pExtent->uSectorGD),
+                               pExtent->pGD, cbGD, NULL);
     AssertRC(rc);
     if (RT_FAILURE(rc))
     {
-        rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not read grain directory in '%s': %Rrc"), pExtent->pszFullname);
+        rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not read grain directory in '%s': %Rrc"), pExtent->pszFullname);
         goto out;
     }
@@ -1274,11 +1077,11 @@
         /* The VMDK 1.1 spec seems to talk about compressed grain directories,
          * but in reality they are not compressed. */
-        rc = vmdkFileReadSync(pImage, pExtent->pFile,
-                              VMDK_SECTOR2BYTE(pExtent->uSectorRGD),
-                              pExtent->pRGD, cbGD, NULL);
+        rc = vdIfIoIntFileReadSync(pImage->pIfIo, pExtent->pFile->pStorage,
+                                   VMDK_SECTOR2BYTE(pExtent->uSectorRGD),
+                                   pExtent->pRGD, cbGD, NULL);
         AssertRC(rc);
         if (RT_FAILURE(rc))
         {
-            rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not read redundant grain directory in '%s'"), pExtent->pszFullname);
+            rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not read redundant grain directory in '%s'"), pExtent->pszFullname);
             goto out;
         }
@@ -1317,15 +1120,15 @@
                 RTMemTmpFree(pTmpGT1);
                 RTMemTmpFree(pTmpGT2);
-                rc = vmdkError(pImage, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: inconsistent references to grain directory in '%s'"), pExtent->pszFullname);
+                rc = vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: inconsistent references to grain directory in '%s'"), pExtent->pszFullname);
                 goto out;
             }
             /* The VMDK 1.1 spec seems to talk about compressed grain tables,
              * but in reality they are not compressed. */
-            rc = vmdkFileReadSync(pImage, pExtent->pFile,
-                                  VMDK_SECTOR2BYTE(*pGDTmp),
-                                  pTmpGT1, cbGT, NULL);
+            rc = vdIfIoIntFileReadSync(pImage->pIfIo, pExtent->pFile->pStorage,
+                                       VMDK_SECTOR2BYTE(*pGDTmp),
+                                       pTmpGT1, cbGT, NULL);
             if (RT_FAILURE(rc))
             {
-                rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error reading grain table in '%s'"), pExtent->pszFullname);
+                rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error reading grain table in '%s'"), pExtent->pszFullname);
                 RTMemTmpFree(pTmpGT1);
                 RTMemTmpFree(pTmpGT2);
@@ -1334,10 +1137,10 @@
             /* The VMDK 1.1 spec seems to talk about compressed grain tables,
              * but in reality they are not compressed. */
-            rc = vmdkFileReadSync(pImage, pExtent->pFile,
-                                  VMDK_SECTOR2BYTE(*pRGDTmp),
-                                  pTmpGT2, cbGT, NULL);
+            rc = vdIfIoIntFileReadSync(pImage->pIfIo, pExtent->pFile->pStorage,
+                                       VMDK_SECTOR2BYTE(*pRGDTmp),
+                                       pTmpGT2, cbGT, NULL);
             if (RT_FAILURE(rc))
             {
-                rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error reading backup grain table in '%s'"), pExtent->pszFullname);
+                rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error reading backup grain table in '%s'"), pExtent->pszFullname);
                 RTMemTmpFree(pTmpGT1);
                 RTMemTmpFree(pTmpGT2);
@@ -1348,5 +1151,5 @@
                 RTMemTmpFree(pTmpGT1);
                 RTMemTmpFree(pTmpGT2);
-                rc = vmdkError(pImage, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: inconsistency between grain table and backup grain table in '%s'"), pExtent->pszFullname);
+                rc = vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: inconsistency between grain table and backup grain table in '%s'"), pExtent->pszFullname);
                 goto out;
             }
@@ -1401,5 +1204,5 @@
         cbOverhead = RT_ALIGN_64(cbOverhead,
                                  VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain));
-        rc = vmdkFileSetSize(pImage, pExtent->pFile, cbOverhead);
+        rc = vdIfIoIntFileSetSize(pImage->pIfIo, pExtent->pFile->pStorage, cbOverhead);
     }
     if (RT_FAILURE(rc))
@@ -1440,10 +1243,10 @@
                 uGTSectorLE = RT_H2LE_U64(uOffsetSectors);
                 /* Write the redundant grain directory entry to disk. */
-                rc = vmdkFileWriteSync(pImage, pExtent->pFile,
-                                       VMDK_SECTOR2BYTE(pExtent->uSectorRGD) + i * sizeof(uGTSectorLE),
-                                       &uGTSectorLE, sizeof(uGTSectorLE), NULL);
+                rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pExtent->pFile->pStorage,
+                                            VMDK_SECTOR2BYTE(pExtent->uSectorRGD) + i * sizeof(uGTSectorLE),
+                                            &uGTSectorLE, sizeof(uGTSectorLE), NULL);
                 if (RT_FAILURE(rc))
                 {
-                    rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write new redundant grain directory entry in '%s'"), pExtent->pszFullname);
+                    rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write new redundant grain directory entry in '%s'"), pExtent->pszFullname);
                     goto out;
                 }
@@ -1458,10 +1261,10 @@
             uGTSectorLE = RT_H2LE_U64(uOffsetSectors);
             /* Write the grain directory entry to disk. */
-            rc = vmdkFileWriteSync(pImage, pExtent->pFile,
-                                   VMDK_SECTOR2BYTE(pExtent->uSectorGD) + i * sizeof(uGTSectorLE),
-                                   &uGTSectorLE, sizeof(uGTSectorLE), NULL);
+            rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pExtent->pFile->pStorage,
+                                        VMDK_SECTOR2BYTE(pExtent->uSectorGD) + i * sizeof(uGTSectorLE),
+                                        &uGTSectorLE, sizeof(uGTSectorLE), NULL);
             if (RT_FAILURE(rc))
             {
-                rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write new grain directory entry in '%s'"), pExtent->pszFullname);
+                rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write new grain directory entry in '%s'"), pExtent->pszFullname);
                 goto out;
             }
@@ -1497,5 +1300,5 @@
         pszQ = (char *)strchr(pszStr, '"');
         if (pszQ == NULL)
-            return vmdkError(pImage, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: incorrectly quoted value in descriptor in '%s'"), pImage->pszFilename);
+            return vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: incorrectly quoted value in descriptor in '%s'"), pImage->pszFilename);
     }
 
@@ -1519,5 +1322,5 @@
     if (    pDescriptor->cLines >= VMDK_DESCRIPTOR_LINES_MAX - 1
         &&  pEnd - pDescriptor->aLines[0] > (ptrdiff_t)pDescriptor->cbDescAlloc - cbDiff)
-        return vmdkError(pImage, VERR_BUFFER_OVERFLOW, RT_SRC_POS, N_("VMDK: descriptor too big in '%s'"), pImage->pszFilename);
+        return vdIfError(pImage->pIfError, VERR_BUFFER_OVERFLOW, RT_SRC_POS, N_("VMDK: descriptor too big in '%s'"), pImage->pszFilename);
 
     memcpy(pEnd, pszLine, cbDiff);
@@ -1593,5 +1396,5 @@
             if (    pDescriptor->aLines[pDescriptor->cLines]
                 -   pDescriptor->aLines[0] > (ptrdiff_t)pDescriptor->cbDescAlloc - cbDiff)
-                return vmdkError(pImage, VERR_BUFFER_OVERFLOW, RT_SRC_POS, N_("VMDK: descriptor too big in '%s'"), pImage->pszFilename);
+                return vdIfError(pImage->pIfError, VERR_BUFFER_OVERFLOW, RT_SRC_POS, N_("VMDK: descriptor too big in '%s'"), pImage->pszFilename);
 
             memmove(pszTmp + cbNewVal, pszTmp + cbOldVal,
@@ -1636,5 +1439,5 @@
             || (  pDescriptor->aLines[pDescriptor->cLines]
                 - pDescriptor->aLines[0] > (ptrdiff_t)pDescriptor->cbDescAlloc - cbDiff))
-            return vmdkError(pImage, VERR_BUFFER_OVERFLOW, RT_SRC_POS, N_("VMDK: descriptor too big in '%s'"), pImage->pszFilename);
+            return vdIfError(pImage->pIfError, VERR_BUFFER_OVERFLOW, RT_SRC_POS, N_("VMDK: descriptor too big in '%s'"), pImage->pszFilename);
         for (unsigned i = pDescriptor->cLines + 1; i > uLast + 1; i--)
         {
@@ -1783,5 +1586,5 @@
         || (  pDescriptor->aLines[pDescriptor->cLines]
             - pDescriptor->aLines[0] > (ptrdiff_t)pDescriptor->cbDescAlloc - cbDiff))
-        return vmdkError(pImage, VERR_BUFFER_OVERFLOW, RT_SRC_POS, N_("VMDK: descriptor too big in '%s'"), pImage->pszFilename);
+        return vdIfError(pImage->pIfError, VERR_BUFFER_OVERFLOW, RT_SRC_POS, N_("VMDK: descriptor too big in '%s'"), pImage->pszFilename);
 
     for (unsigned i = pDescriptor->cLines + 1; i > uLast + 1; i--)
@@ -1925,5 +1728,5 @@
         if (cLine >= VMDK_DESCRIPTOR_LINES_MAX)
         {
-            rc = vmdkError(pImage, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: descriptor too big in '%s'"), pImage->pszFilename);
+            rc = vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: descriptor too big in '%s'"), pImage->pszFilename);
             goto out;
         }
@@ -1935,5 +1738,5 @@
                 if (*(pTmp + 1) != '\n')
                 {
-                    rc = vmdkError(pImage, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: unsupported end of line in descriptor in '%s'"), pImage->pszFilename);
+                    rc = vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: unsupported end of line in descriptor in '%s'"), pImage->pszFilename);
                     goto out;
                 }
@@ -1960,5 +1763,5 @@
         &&  strcmp(pDescriptor->aLines[0], "# Disk Descriptor File"))
     {
-        rc = vmdkError(pImage, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: descriptor does not start as expected in '%s'"), pImage->pszFilename);
+        rc = vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: descriptor does not start as expected in '%s'"), pImage->pszFilename);
         goto out;
     }
@@ -1980,5 +1783,5 @@
                 {
                     /* Incorrect ordering of entries. */
-                    rc = vmdkError(pImage, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: incorrect ordering of entries in descriptor in '%s'"), pImage->pszFilename);
+                    rc = vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: incorrect ordering of entries in descriptor in '%s'"), pImage->pszFilename);
                     goto out;
                 }
@@ -1995,5 +1798,5 @@
                 {
                     /* Incorrect ordering of entries. */
-                    rc = vmdkError(pImage, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: incorrect ordering of entries in descriptor in '%s'"), pImage->pszFilename);
+                    rc = vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: incorrect ordering of entries in descriptor in '%s'"), pImage->pszFilename);
                     goto out;
                 }
@@ -2010,5 +1813,5 @@
                 {
                     /* Incorrect ordering of entries. */
-                    rc = vmdkError(pImage, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: incorrect ordering of entries in descriptor in '%s'"), pImage->pszFilename);
+                    rc = vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: incorrect ordering of entries in descriptor in '%s'"), pImage->pszFilename);
                     goto out;
                 }
@@ -2155,7 +1958,7 @@
     rc = vmdkDescBaseGetU32(&pImage->Descriptor, "version", &uVersion);
     if (RT_FAILURE(rc))
-        return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error finding key 'version' in descriptor in '%s'"), pImage->pszFilename);
+        return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error finding key 'version' in descriptor in '%s'"), pImage->pszFilename);
     if (uVersion != 1)
-        return vmdkError(pImage, VERR_VD_VMDK_UNSUPPORTED_VERSION, RT_SRC_POS, N_("VMDK: unsupported format version in descriptor in '%s'"), pImage->pszFilename);
+        return vdIfError(pImage->pIfError, VERR_VD_VMDK_UNSUPPORTED_VERSION, RT_SRC_POS, N_("VMDK: unsupported format version in descriptor in '%s'"), pImage->pszFilename);
 
     /* Get image creation type and determine image flags. */
@@ -2164,5 +1967,5 @@
                             &pszCreateType);
     if (RT_FAILURE(rc))
-        return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot get image type from descriptor in '%s'"), pImage->pszFilename);
+        return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot get image type from descriptor in '%s'"), pImage->pszFilename);
     if (    !strcmp(pszCreateType, "twoGbMaxExtentSparse")
         ||  !strcmp(pszCreateType, "twoGbMaxExtentFlat"))
@@ -2186,5 +1989,5 @@
     {
         /* Monolithic image, must have only one extent (already opened). */
-        return vmdkError(pImage, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: monolithic image may only have one extent in '%s'"), pImage->pszFilename);
+        return vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: monolithic image may only have one extent in '%s'"), pImage->pszFilename);
     }
 
@@ -2219,7 +2022,7 @@
         }
         else
-            return vmdkError(pImage, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: parse error in extent description in '%s'"), pImage->pszFilename);
+            return vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: parse error in extent description in '%s'"), pImage->pszFilename);
         if (*pszLine++ != ' ')
-            return vmdkError(pImage, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: parse error in extent description in '%s'"), pImage->pszFilename);
+            return vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: parse error in extent description in '%s'"), pImage->pszFilename);
 
         /* Nominal size of the extent. */
@@ -2227,7 +2030,7 @@
                              &pImage->pExtents[i].cNominalSectors);
         if (RT_FAILURE(rc))
-            return vmdkError(pImage, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: parse error in extent description in '%s'"), pImage->pszFilename);
+            return vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: parse error in extent description in '%s'"), pImage->pszFilename);
         if (*pszLine++ != ' ')
-            return vmdkError(pImage, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: parse error in extent description in '%s'"), pImage->pszFilename);
+            return vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: parse error in extent description in '%s'"), pImage->pszFilename);
 
         /* Type of the extent. */
@@ -2258,5 +2061,5 @@
         }
         else
-            return vmdkError(pImage, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: parse error in extent description in '%s'"), pImage->pszFilename);
+            return vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: parse error in extent description in '%s'"), pImage->pszFilename);
 
         if (pImage->pExtents[i].enmType == VMDKETYPE_ZERO)
@@ -2266,5 +2069,5 @@
                 pszLine++;
             if (*pszLine != '\0')
-                return vmdkError(pImage, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: parse error in extent description in '%s'"), pImage->pszFilename);
+                return vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: parse error in extent description in '%s'"), pImage->pszFilename);
             pImage->pExtents[i].pszBasename = NULL;
         }
@@ -2273,5 +2076,5 @@
             /* All other extent types have basename and optional offset. */
             if (*pszLine++ != ' ')
-                return vmdkError(pImage, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: parse error in extent description in '%s'"), pImage->pszFilename);
+                return vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: parse error in extent description in '%s'"), pImage->pszFilename);
 
             /* Basename of the image. Surrounded by quotes. */
@@ -2290,10 +2093,10 @@
                                          &pImage->pExtents[i].uSectorOffset);
                     if (RT_FAILURE(rc))
-                        return vmdkError(pImage, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: parse error in extent description in '%s'"), pImage->pszFilename);
+                        return vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: parse error in extent description in '%s'"), pImage->pszFilename);
                 }
             }
 
             if (*pszLine != '\0')
-                return vmdkError(pImage, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: parse error in extent description in '%s'"), pImage->pszFilename);
+                return vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: parse error in extent description in '%s'"), pImage->pszFilename);
         }
     }
@@ -2306,5 +2109,5 @@
         pImage->PCHSGeometry.cCylinders = 0;
     else if (RT_FAILURE(rc))
-        return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error getting PCHS geometry from extent description in '%s'"), pImage->pszFilename);
+        return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error getting PCHS geometry from extent description in '%s'"), pImage->pszFilename);
     rc = vmdkDescDDBGetU32(pImage, &pImage->Descriptor,
                            VMDK_DDB_GEO_PCHS_HEADS,
@@ -2313,5 +2116,5 @@
         pImage->PCHSGeometry.cHeads = 0;
     else if (RT_FAILURE(rc))
-        return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error getting PCHS geometry from extent description in '%s'"), pImage->pszFilename);
+        return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error getting PCHS geometry from extent description in '%s'"), pImage->pszFilename);
     rc = vmdkDescDDBGetU32(pImage, &pImage->Descriptor,
                            VMDK_DDB_GEO_PCHS_SECTORS,
@@ -2320,5 +2123,5 @@
         pImage->PCHSGeometry.cSectors = 0;
     else if (RT_FAILURE(rc))
-        return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error getting PCHS geometry from extent description in '%s'"), pImage->pszFilename);
+        return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error getting PCHS geometry from extent description in '%s'"), pImage->pszFilename);
     if (    pImage->PCHSGeometry.cCylinders == 0
         ||  pImage->PCHSGeometry.cHeads == 0
@@ -2341,5 +2144,5 @@
         pImage->LCHSGeometry.cCylinders = 0;
     else if (RT_FAILURE(rc))
-        return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error getting LCHS geometry from extent description in '%s'"), pImage->pszFilename);
+        return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error getting LCHS geometry from extent description in '%s'"), pImage->pszFilename);
     rc = vmdkDescDDBGetU32(pImage, &pImage->Descriptor,
                            VMDK_DDB_GEO_LCHS_HEADS,
@@ -2348,5 +2151,5 @@
         pImage->LCHSGeometry.cHeads = 0;
     else if (RT_FAILURE(rc))
-        return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error getting LCHS geometry from extent description in '%s'"), pImage->pszFilename);
+        return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error getting LCHS geometry from extent description in '%s'"), pImage->pszFilename);
     rc = vmdkDescDDBGetU32(pImage, &pImage->Descriptor,
                            VMDK_DDB_GEO_LCHS_SECTORS,
@@ -2355,5 +2158,5 @@
         pImage->LCHSGeometry.cSectors = 0;
     else if (RT_FAILURE(rc))
-        return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error getting LCHS geometry from extent description in '%s'"), pImage->pszFilename);
+        return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error getting LCHS geometry from extent description in '%s'"), pImage->pszFilename);
     if (    pImage->LCHSGeometry.cCylinders == 0
         ||  pImage->LCHSGeometry.cHeads == 0
@@ -2383,5 +2186,5 @@
                                     VMDK_DDB_IMAGE_UUID, &pImage->ImageUuid);
             if (RT_FAILURE(rc))
-                return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error storing image UUID in descriptor in '%s'"), pImage->pszFilename);
+                return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error storing image UUID in descriptor in '%s'"), pImage->pszFilename);
         }
     }
@@ -2409,5 +2212,5 @@
                                     &pImage->ModificationUuid);
             if (RT_FAILURE(rc))
-                return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error storing image modification UUID in descriptor in '%s'"), pImage->pszFilename);
+                return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error storing image modification UUID in descriptor in '%s'"), pImage->pszFilename);
         }
     }
@@ -2433,5 +2236,5 @@
                                     VMDK_DDB_PARENT_UUID, &pImage->ParentUuid);
             if (RT_FAILURE(rc))
-                return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error storing parent UUID in descriptor in '%s'"), pImage->pszFilename);
+                return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error storing parent UUID in descriptor in '%s'"), pImage->pszFilename);
         }
     }
@@ -2457,5 +2260,5 @@
                                     &pImage->ParentModificationUuid);
             if (RT_FAILURE(rc))
-                return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error storing parent modification UUID in descriptor in '%s'"), pImage->pszFilename);
+                return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error storing parent modification UUID in descriptor in '%s'"), pImage->pszFilename);
         }
     }
@@ -2499,5 +2302,5 @@
             if (cbLimit)
             {
-                rc = vmdkError(pImage, VERR_BUFFER_OVERFLOW, RT_SRC_POS, N_("VMDK: descriptor too long in '%s'"), pImage->pszFilename);
+                rc = vdIfError(pImage->pIfError, VERR_BUFFER_OVERFLOW, RT_SRC_POS, N_("VMDK: descriptor too long in '%s'"), pImage->pszFilename);
                 break;
             }
@@ -2572,13 +2375,14 @@
     if (RT_SUCCESS(rc))
     {
-        rc = vmdkFileWriteSync(pImage, pDescFile, uOffset, pvDescriptor, cbLimit ? cbLimit : cbDescriptor, NULL);
+        rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pDescFile->pStorage, uOffset,
+                                    pvDescriptor, cbLimit ? cbLimit : cbDescriptor, NULL);
         if (RT_FAILURE(rc))
-            rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error writing descriptor in '%s'"), pImage->pszFilename);
+            rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error writing descriptor in '%s'"), pImage->pszFilename);
 
         if (RT_SUCCESS(rc) && !cbLimit)
         {
-            rc = vmdkFileSetSize(pImage, pDescFile, cbDescriptor);
+            rc = vdIfIoIntFileSetSize(pImage->pIfIo, pDescFile->pStorage, cbDescriptor);
             if (RT_FAILURE(rc))
-                rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error truncating descriptor in '%s'"), pImage->pszFilename);
+                rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error truncating descriptor in '%s'"), pImage->pszFilename);
         }
 
@@ -2625,15 +2429,18 @@
     if (RT_SUCCESS(rc))
     {
-        rc = vmdkFileWriteMetaAsync(pImage, pDescFile, uOffset, pvDescriptor, cbLimit ? cbLimit : cbDescriptor, pIoCtx, NULL, NULL);
+        rc = vdIfIoIntFileWriteMetaAsync(pImage->pIfIo, pDescFile->pStorage,
+                                         uOffset, pvDescriptor,
+                                         cbLimit ? cbLimit : cbDescriptor,
+                                         pIoCtx, NULL, NULL);
         if (   RT_FAILURE(rc)
             && rc != VERR_VD_ASYNC_IO_IN_PROGRESS)
-            rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error writing descriptor in '%s'"), pImage->pszFilename);
+            rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error writing descriptor in '%s'"), pImage->pszFilename);
     }
 
     if (RT_SUCCESS(rc) && !cbLimit)
     {
-        rc = vmdkFileSetSize(pImage, pDescFile, cbDescriptor);
+        rc = vdIfIoIntFileSetSize(pImage->pIfIo, pDescFile->pStorage, cbDescriptor);
         if (RT_FAILURE(rc))
-            rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error truncating descriptor in '%s'"), pImage->pszFilename);
+            rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error truncating descriptor in '%s'"), pImage->pszFilename);
     }
 
@@ -2654,10 +2461,10 @@
     if (RT_LE2H_U32(pHeader->magicNumber) != VMDK_SPARSE_MAGICNUMBER)
     {
-        rc = vmdkError(pImage, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: incorrect magic in sparse extent header in '%s'"), pExtent->pszFullname);
+        rc = vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: incorrect magic in sparse extent header in '%s'"), pExtent->pszFullname);
         return rc;
     }
     if (RT_LE2H_U32(pHeader->version) != 1 && RT_LE2H_U32(pHeader->version) != 3)
     {
-        rc = vmdkError(pImage, VERR_VD_VMDK_UNSUPPORTED_VERSION, RT_SRC_POS, N_("VMDK: incorrect version in sparse extent header in '%s', not a VMDK 1.0/1.1 conforming file"), pExtent->pszFullname);
+        rc = vdIfError(pImage->pIfError, VERR_VD_VMDK_UNSUPPORTED_VERSION, RT_SRC_POS, N_("VMDK: incorrect version in sparse extent header in '%s', not a VMDK 1.0/1.1 conforming file"), pExtent->pszFullname);
         return rc;
     }
@@ -2668,5 +2475,5 @@
              || pHeader->doubleEndLineChar2 != '\n') )
     {
-        rc = vmdkError(pImage, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: corrupted by CR/LF translation in '%s'"), pExtent->pszFullname);
+        rc = vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: corrupted by CR/LF translation in '%s'"), pExtent->pszFullname);
         return rc;
     }
@@ -2687,20 +2494,20 @@
 
     if (!fMagicAlreadyRead)
-        rc = vmdkFileReadSync(pImage, pExtent->pFile, 0, &Header,
-                              sizeof(Header), NULL);
+        rc = vdIfIoIntFileReadSync(pImage->pIfIo, pExtent->pFile->pStorage, 0,
+                                   &Header, sizeof(Header), NULL);
     else
     {
         Header.magicNumber = RT_H2LE_U32(VMDK_SPARSE_MAGICNUMBER);
-        rc = vmdkFileReadSync(pImage, pExtent->pFile,
-                              RT_OFFSETOF(SparseExtentHeader, version),
-                              &Header.version,
-                                sizeof(Header)
-                              - RT_OFFSETOF(SparseExtentHeader, version),
-                              NULL);
+        rc = vdIfIoIntFileReadSync(pImage->pIfIo, pExtent->pFile->pStorage,
+                                   RT_OFFSETOF(SparseExtentHeader, version),
+                                   &Header.version,
+                                     sizeof(Header)
+                                   - RT_OFFSETOF(SparseExtentHeader, version),
+                                   NULL);
     }
     AssertRC(rc);
     if (RT_FAILURE(rc))
     {
-        vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error reading extent header in '%s'"), pExtent->pszFullname);
+        vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error reading extent header in '%s'"), pExtent->pszFullname);
         rc = VERR_VD_VMDK_INVALID_HEADER;
         goto out;
@@ -2718,9 +2525,9 @@
             && !(pImage->uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL)))
     {
-        rc = vmdkFileGetSize(pImage, pExtent->pFile, &cbFile);
+        rc = vdIfIoIntFileGetSize(pImage->pIfIo, pExtent->pFile->pStorage, &cbFile);
         AssertRC(rc);
         if (RT_FAILURE(rc))
         {
-            rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot get size of '%s'"), pExtent->pszFullname);
+            rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot get size of '%s'"), pExtent->pszFullname);
             goto out;
         }
@@ -2735,11 +2542,11 @@
     {
         /* Read the footer, which comes before the end-of-stream marker. */
-        rc = vmdkFileReadSync(pImage, pExtent->pFile,
-                              cbFile - 2*512, &Header,
-                              sizeof(Header), NULL);
+        rc = vdIfIoIntFileReadSync(pImage->pIfIo, pExtent->pFile->pStorage,
+                                   cbFile - 2*512, &Header,
+                                   sizeof(Header), NULL);
         AssertRC(rc);
         if (RT_FAILURE(rc))
         {
-            vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error reading extent footer in '%s'"), pExtent->pszFullname);
+            vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error reading extent footer in '%s'"), pExtent->pszFullname);
             rc = VERR_VD_VMDK_INVALID_HEADER;
             goto out;
@@ -2760,5 +2567,5 @@
     if (pExtent->uDescriptorSector && !pExtent->cDescriptorSectors)
     {
-        rc = vmdkError(pImage, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: inconsistent embedded descriptor config in '%s'"), pExtent->pszFullname);
+        rc = vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: inconsistent embedded descriptor config in '%s'"), pExtent->pszFullname);
         goto out;
     }
@@ -2779,5 +2586,5 @@
             || !(pImage->uOpenFlags & VD_OPEN_FLAGS_SEQUENTIAL)))
     {
-        rc = vmdkError(pImage, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: cannot resolve grain directory offset in '%s'"), pExtent->pszFullname);
+        rc = vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: cannot resolve grain directory offset in '%s'"), pExtent->pszFullname);
         goto out;
     }
@@ -2788,5 +2595,5 @@
     if (!cSectorsPerGDE || cSectorsPerGDE > UINT32_MAX)
     {
-        rc = vmdkError(pImage, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: incorrect grain directory size in '%s'"), pExtent->pszFullname);
+        rc = vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: incorrect grain directory size in '%s'"), pExtent->pszFullname);
         goto out;
     }
@@ -2827,8 +2634,8 @@
      * area (flat images only). If not, it means the image is at least
      * truncated, or even seriously garbled. */
-    rc = vmdkFileGetSize(pImage, pExtent->pFile, &cbExtentSize);
+    rc = vdIfIoIntFileGetSize(pImage->pIfIo, pExtent->pFile->pStorage, &cbExtentSize);
     if (RT_FAILURE(rc))
     {
-        rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error getting size in '%s'"), pExtent->pszFullname);
+        rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error getting size in '%s'"), pExtent->pszFullname);
         goto out;
     }
@@ -2836,5 +2643,5 @@
         &&  (pExtent->enmType != VMDKETYPE_FLAT || pExtent->cNominalSectors + pExtent->uSectorOffset > VMDK_BYTE2SECTOR(cbExtentSize)))
     {
-        rc = vmdkError(pImage, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: file size is not a multiple of 512 in '%s', file is truncated or otherwise garbled"), pExtent->pszFullname);
+        rc = vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: file size is not a multiple of 512 in '%s', file is truncated or otherwise garbled"), pExtent->pszFullname);
         goto out;
     }
@@ -2848,5 +2655,5 @@
         ||  pExtent->cSectorsPerGrain < 8)
     {
-        rc = vmdkError(pImage, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: invalid extent grain size %u in '%s'"), pExtent->cSectorsPerGrain, pExtent->pszFullname);
+        rc = vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: invalid extent grain size %u in '%s'"), pExtent->cSectorsPerGrain, pExtent->pszFullname);
         goto out;
     }
@@ -2857,5 +2664,5 @@
         ||  pExtent->cGTEntries < VMDK_GT_CACHELINE_SIZE)
     {
-        rc = vmdkError(pImage, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: grain table cache size problem in '%s'"), pExtent->pszFullname);
+        rc = vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: grain table cache size problem in '%s'"), pExtent->pszFullname);
         goto out;
     }
@@ -2941,8 +2748,9 @@
     Header.compressAlgorithm = RT_H2LE_U16(pExtent->uCompression);
 
-    int rc = vmdkFileWriteSync(pImage, pExtent->pFile, uOffset, &Header, sizeof(Header), NULL);
+    int rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pExtent->pFile->pStorage,
+                                    uOffset, &Header, sizeof(Header), NULL);
     AssertRC(rc);
     if (RT_FAILURE(rc))
-        rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error writing extent header in '%s'"), pExtent->pszFullname);
+        rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error writing extent header in '%s'"), pExtent->pszFullname);
     return rc;
 }
@@ -3003,9 +2811,9 @@
     Header.compressAlgorithm = RT_H2LE_U16(pExtent->uCompression);
 
-    int rc = vmdkFileWriteMetaAsync(pImage, pExtent->pFile,
-                                    uOffset, &Header, sizeof(Header),
-                                    pIoCtx, NULL, NULL);
+    int rc = vdIfIoIntFileWriteMetaAsync(pImage->pIfIo, pExtent->pFile->pStorage,
+                                         uOffset, &Header, sizeof(Header),
+                                         pIoCtx, NULL, NULL);
     if (RT_FAILURE(rc) && (rc != VERR_VD_ASYNC_IO_IN_PROGRESS))
-        rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error writing extent header in '%s'"), pExtent->pszFullname);
+        rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error writing extent header in '%s'"), pExtent->pszFullname);
     return rc;
 }
@@ -3022,9 +2830,10 @@
     uint64_t cSectorsPerGDE;
 
-    int rc = vmdkFileReadSync(pImage, pExtent->pFile, 0, &Header, sizeof(Header), NULL);
+    int rc = vdIfIoIntFileReadSync(pImage->pIfIo, pExtent->pFile->pStorage, 0,
+                                   &Header, sizeof(Header), NULL);
     AssertRC(rc);
     if (RT_FAILURE(rc))
     {
-        vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error reading ESX sparse extent header in '%s'"), pExtent->pszFullname);
+        vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error reading ESX sparse extent header in '%s'"), pExtent->pszFullname);
         rc = VERR_VD_VMDK_INVALID_HEADER;
         goto out;
@@ -3211,14 +3020,7 @@
     pImage->uOpenFlags = uOpenFlags;
 
-    /* Try to get error interface. */
-    pImage->pInterfaceError = VDInterfaceGet(pImage->pVDIfsDisk, VDINTERFACETYPE_ERROR);
-    if (pImage->pInterfaceError)
-        pImage->pInterfaceErrorCallbacks = VDGetInterfaceError(pImage->pInterfaceError);
-
-    /* Get I/O interface. */
-    pImage->pInterfaceIO = VDInterfaceGet(pImage->pVDIfsImage, VDINTERFACETYPE_IOINT);
-    AssertPtrReturn(pImage->pInterfaceIO, VERR_INVALID_PARAMETER);
-    pImage->pInterfaceIOCallbacks = VDGetInterfaceIOInt(pImage->pInterfaceIO);
-    AssertPtrReturn(pImage->pInterfaceIOCallbacks, VERR_INVALID_PARAMETER);
+    pImage->pIfError = VDIfErrorGet(pImage->pVDIfsDisk);
+    pImage->pIfIo = VDIfIoIntGet(pImage->pVDIfsImage);
+    AssertPtrReturn(pImage->pIfIo, VERR_INVALID_PARAMETER);
 
     /*
@@ -3241,8 +3043,9 @@
 
     /* Read magic (if present). */
-    rc = vmdkFileReadSync(pImage, pFile, 0, &u32Magic, sizeof(u32Magic), NULL);
+    rc = vdIfIoIntFileReadSync(pImage->pIfIo, pFile->pStorage, 0,
+                               &u32Magic, sizeof(u32Magic), NULL);
     if (RT_FAILURE(rc))
     {
-        vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error reading the magic number in '%s'"), pImage->pszFilename);
+        vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error reading the magic number in '%s'"), pImage->pszFilename);
         rc = VERR_VD_VMDK_INVALID_HEADER;
         goto out;
@@ -3275,5 +3078,5 @@
         if (!pExtent->uDescriptorSector || !pExtent->cDescriptorSectors)
         {
-            rc = vmdkError(pImage, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: monolithic image without descriptor in '%s'"), pImage->pszFilename);
+            rc = vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: monolithic image without descriptor in '%s'"), pImage->pszFilename);
             goto out;
         }
@@ -3296,12 +3099,12 @@
             goto out;
         }
-        rc = vmdkFileReadSync(pImage, pExtent->pFile,
-                              VMDK_SECTOR2BYTE(pExtent->uDescriptorSector),
-                              pExtent->pDescData,
-                              VMDK_SECTOR2BYTE(pExtent->cDescriptorSectors), NULL);
+        rc = vdIfIoIntFileReadSync(pImage->pIfIo, pExtent->pFile->pStorage,
+                                   VMDK_SECTOR2BYTE(pExtent->uDescriptorSector),
+                                   pExtent->pDescData,
+                                   VMDK_SECTOR2BYTE(pExtent->cDescriptorSectors), NULL);
         AssertRC(rc);
         if (RT_FAILURE(rc))
         {
-            rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: read error for descriptor in '%s'"), pExtent->pszFullname);
+            rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: read error for descriptor in '%s'"), pExtent->pszFullname);
             goto out;
         }
@@ -3338,5 +3141,5 @@
          * and will result in the correct "truncated read" error handling. */
         uint64_t cbFileSize;
-        rc = vmdkFileGetSize(pImage, pFile, &cbFileSize);
+        rc = vdIfIoIntFileGetSize(pImage->pIfIo, pFile->pStorage, &cbFileSize);
         if (RT_FAILURE(rc))
             goto out;
@@ -3345,5 +3148,5 @@
         if (cbFileSize < 50)
         {
-            rc = vmdkError(pImage, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: descriptor in '%s' is too short"), pImage->pszFilename);
+            rc = vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: descriptor in '%s' is too short"), pImage->pszFilename);
             goto out;
         }
@@ -3367,12 +3170,12 @@
         memcpy(pImage->pDescData, &u32Magic, sizeof(u32Magic));
         size_t cbRead;
-        rc = vmdkFileReadSync(pImage, pImage->pFile, sizeof(u32Magic),
-                              pImage->pDescData + sizeof(u32Magic),
-                              RT_MIN(pImage->cbDescAlloc - sizeof(u32Magic),
-                                     cbFileSize - sizeof(u32Magic)),
-                              &cbRead);
+        rc = vdIfIoIntFileReadSync(pImage->pIfIo, pFile->pStorage, sizeof(u32Magic),
+                                   pImage->pDescData + sizeof(u32Magic),
+                                   RT_MIN(pImage->cbDescAlloc - sizeof(u32Magic),
+                                          cbFileSize - sizeof(u32Magic)),
+                                   &cbRead);
         if (RT_FAILURE(rc))
         {
-            rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: read error for descriptor in '%s'"), pImage->pszFilename);
+            rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: read error for descriptor in '%s'"), pImage->pszFilename);
             goto out;
         }
@@ -3382,5 +3185,5 @@
             /* Likely the read is truncated. Better fail a bit too early
              * (normally the descriptor is much smaller than our buffer). */
-            rc = vmdkError(pImage, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: cannot read descriptor in '%s'"), pImage->pszFilename);
+            rc = vdIfError(pImage->pIfError, VERR_VD_VMDK_INVALID_HEADER, RT_SRC_POS, N_("VMDK: cannot read descriptor in '%s'"), pImage->pszFilename);
             goto out;
         }
@@ -3595,5 +3398,5 @@
         rc = vmdkCreateExtents(pImage, 1);
         if (RT_FAILURE(rc))
-            return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new extent list in '%s'"), pImage->pszFilename);
+            return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not create new extent list in '%s'"), pImage->pszFilename);
         pExtent = &pImage->pExtents[0];
         /* Create raw disk descriptor file. */
@@ -3603,5 +3406,5 @@
                           false /* fAsyncIO */);
         if (RT_FAILURE(rc))
-            return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new file '%s'"), pImage->pszFilename);
+            return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not create new file '%s'"), pImage->pszFilename);
 
         /* Set up basename for extent description. Cannot use StrDup. */
@@ -3628,5 +3431,5 @@
                           false /* fAsyncIO */);
         if (RT_FAILURE(rc))
-            return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not open raw disk file '%s'"), pExtent->pszFullname);
+            return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not open raw disk file '%s'"), pExtent->pszFullname);
     }
     else
@@ -3645,5 +3448,5 @@
             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);
+                return vdIfError(pImage->pIfError, 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)
@@ -3658,5 +3461,5 @@
         rc = vmdkCreateExtents(pImage, cExtents);
         if (RT_FAILURE(rc))
-            return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new extent list in '%s'"), pImage->pszFilename);
+            return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not create new extent list in '%s'"), pImage->pszFilename);
 
         /* Create raw partition descriptor file. */
@@ -3666,5 +3469,5 @@
                           false /* fAsyncIO */);
         if (RT_FAILURE(rc))
-            return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new file '%s'"), pImage->pszFilename);
+            return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not create new file '%s'"), pImage->pszFilename);
 
         /* Create base filename for the partition table extent. */
@@ -3674,5 +3477,5 @@
         const char *pszExt = RTPathExt(pszBase);
         if (pszExt == NULL)
-            return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: invalid filename '%s'"), pImage->pszFilename);
+            return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: invalid filename '%s'"), pImage->pszFilename);
         char *pszBaseBase = RTStrDup(pszBase);
         if (!pszBaseBase)
@@ -3738,11 +3541,11 @@
                                   false /* fAsyncIO */);
                 if (RT_FAILURE(rc))
-                    return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new partition data file '%s'"), pExtent->pszFullname);
-                rc = vmdkFileWriteSync(pImage, pExtent->pFile,
-                                       VMDK_SECTOR2BYTE(uPartOffset),
-                                       pPart->pvPartitionData,
-                                       pPart->cbData, NULL);
+                    return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not create new partition data file '%s'"), pExtent->pszFullname);
+                rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pExtent->pFile->pStorage,
+                                            VMDK_SECTOR2BYTE(uPartOffset),
+                                            pPart->pvPartitionData,
+                                            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);
+                    return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not write partition data to '%s'"), pExtent->pszFullname);
                 uPartOffset += VMDK_BYTE2SECTOR(pPart->cbData);
             }
@@ -3774,5 +3577,5 @@
                                       false /* fAsyncIO */);
                     if (RT_FAILURE(rc))
-                        return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not open raw partition file '%s'"), pExtent->pszFullname);
+                        return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not open raw partition file '%s'"), pExtent->pszFullname);
                 }
                 else
@@ -3806,5 +3609,5 @@
                             "fullDevice" : "partitionedDevice");
     if (RT_FAILURE(rc))
-        return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not set the image type in '%s'"), pImage->pszFilename);
+        return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not set the image type in '%s'"), pImage->pszFilename);
     return rc;
 }
@@ -3833,5 +3636,5 @@
     rc = vmdkCreateExtents(pImage, cExtents);
     if (RT_FAILURE(rc))
-        return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new extent list in '%s'"), pImage->pszFilename);
+        return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not create new extent list in '%s'"), pImage->pszFilename);
 
     /* Basename strings needed for constructing the extent names. */
@@ -3848,5 +3651,5 @@
                           false /* fAsyncIO */);
         if (RT_FAILURE(rc))
-            return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new sparse descriptor file '%s'"), pImage->pszFilename);
+            return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not create new sparse descriptor file '%s'"), pImage->pszFilename);
     }
     else
@@ -3919,10 +3722,10 @@
                           false /* fAsyncIO */);
         if (RT_FAILURE(rc))
-            return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new file '%s'"), pExtent->pszFullname);
+            return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not create new file '%s'"), pExtent->pszFullname);
         if (uImageFlags & VD_IMAGE_FLAGS_FIXED)
         {
-            rc = vmdkFileSetSize(pImage, pExtent->pFile, cbExtent);
+            rc = vdIfIoIntFileSetSize(pImage->pIfIo, pExtent->pFile->pStorage, cbExtent);
             if (RT_FAILURE(rc))
-                return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not set size of new file '%s'"), pExtent->pszFullname);
+                return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not set size of new file '%s'"), pExtent->pszFullname);
 
             /* Fill image with zeroes. We do this for every fixed-size image since on some systems
@@ -3945,9 +3748,10 @@
                 unsigned cbChunk = (unsigned)RT_MIN(cbExtent, cbBuf);
 
-                rc = vmdkFileWriteSync(pImage, pExtent->pFile, uOff, pvBuf, cbChunk, NULL);
+                rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pExtent->pFile->pStorage,
+                                            uOff, pvBuf, cbChunk, NULL);
                 if (RT_FAILURE(rc))
                 {
                     RTMemFree(pvBuf);
-                    return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: writing block failed for '%s'"), pImage->pszFilename);
+                    return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: writing block failed for '%s'"), pImage->pszFilename);
                 }
 
@@ -4021,5 +3825,5 @@
                                           true /* fPreAlloc */);
             if (RT_FAILURE(rc))
-                return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new grain directory in '%s'"), pExtent->pszFullname);
+                return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not create new grain directory in '%s'"), pExtent->pszFullname);
         }
 
@@ -4037,5 +3841,5 @@
         rc = vmdkDescDDBSetStr(pImage, &pImage->Descriptor, "ddb.adapterType", "lsilogic");
         if (RT_FAILURE(rc))
-            return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not set controller type to lsilogic in '%s'"), pImage->pszFilename);
+            return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not set controller type to lsilogic in '%s'"), pImage->pszFilename);
     }
 
@@ -4062,5 +3866,5 @@
                             pszDescType);
     if (RT_FAILURE(rc))
-        return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not set the image type in '%s'"), pImage->pszFilename);
+        return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not set the image type in '%s'"), pImage->pszFilename);
     return rc;
 }
@@ -4078,5 +3882,5 @@
     rc = vmdkCreateExtents(pImage, 1);
     if (RT_FAILURE(rc))
-        return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new extent list in '%s'"), pImage->pszFilename);
+        return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not create new extent list in '%s'"), pImage->pszFilename);
 
     /* Basename strings needed for constructing the extent names. */
@@ -4116,5 +3920,5 @@
                       false /* fAsyncIO */);
     if (RT_FAILURE(rc))
-        return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new file '%s'"), pExtent->pszFullname);
+        return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not create new file '%s'"), pExtent->pszFullname);
 
     /* Place descriptor file information. */
@@ -4155,10 +3959,10 @@
                                   false /* fPreAlloc */);
     if (RT_FAILURE(rc))
-        return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new grain directory in '%s'"), pExtent->pszFullname);
+        return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not create new grain directory in '%s'"), pExtent->pszFullname);
 
     rc = vmdkDescBaseSetStr(pImage, &pImage->Descriptor, "createType",
                             "streamOptimized");
     if (RT_FAILURE(rc))
-        return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not set the image type in '%s'"), pImage->pszFilename);
+        return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not set the image type in '%s'"), pImage->pszFilename);
 
     return rc;
@@ -4180,14 +3984,7 @@
     pImage->uImageFlags = uImageFlags;
 
-    /* Try to get error interface. */
-    pImage->pInterfaceError = VDInterfaceGet(pImage->pVDIfsDisk, VDINTERFACETYPE_ERROR);
-    if (pImage->pInterfaceError)
-        pImage->pInterfaceErrorCallbacks = VDGetInterfaceError(pImage->pInterfaceError);
-
-    /* Get I/O interface. */
-    pImage->pInterfaceIO = VDInterfaceGet(pImage->pVDIfsImage, VDINTERFACETYPE_IOINT);
-    AssertPtrReturn(pImage->pInterfaceIO, VERR_INVALID_PARAMETER);
-    pImage->pInterfaceIOCallbacks = VDGetInterfaceIOInt(pImage->pInterfaceIO);
-    AssertPtrReturn(pImage->pInterfaceIOCallbacks, VERR_INVALID_PARAMETER);
+    pImage->pIfError = VDIfErrorGet(pImage->pVDIfsDisk);
+    pImage->pIfIo = VDIfIoIntGet(pImage->pVDIfsImage);
+    AssertPtrReturn(pImage->pIfIo, VERR_INVALID_PARAMETER);
 
     rc = vmdkCreateDescriptor(pImage, pImage->pDescData, pImage->cbDescAlloc,
@@ -4195,5 +3992,5 @@
     if (RT_FAILURE(rc))
     {
-        rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new descriptor in '%s'"), pImage->pszFilename);
+        rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not create new descriptor in '%s'"), pImage->pszFilename);
         goto out;
     }
@@ -4244,5 +4041,5 @@
         if (RT_FAILURE(rc))
         {
-            rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not insert the extent list into descriptor in '%s'"), pImage->pszFilename);
+            rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: could not insert the extent list into descriptor in '%s'"), pImage->pszFilename);
             goto out;
         }
@@ -4275,5 +4072,5 @@
     if (RT_FAILURE(rc))
     {
-        rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error storing image UUID in new descriptor in '%s'"), pImage->pszFilename);
+        rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error storing image UUID in new descriptor in '%s'"), pImage->pszFilename);
         goto out;
     }
@@ -4283,5 +4080,5 @@
     if (RT_FAILURE(rc))
     {
-        rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error storing parent image UUID in new descriptor in '%s'"), pImage->pszFilename);
+        rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error storing parent image UUID in new descriptor in '%s'"), pImage->pszFilename);
         goto out;
     }
@@ -4292,5 +4089,5 @@
     if (RT_FAILURE(rc))
     {
-        rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error storing modification UUID in new descriptor in '%s'"), pImage->pszFilename);
+        rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error storing modification UUID in new descriptor in '%s'"), pImage->pszFilename);
         goto out;
     }
@@ -4301,5 +4098,5 @@
     if (RT_FAILURE(rc))
     {
-        rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error storing parent modification UUID in new descriptor in '%s'"), pImage->pszFilename);
+        rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error storing parent modification UUID in new descriptor in '%s'"), pImage->pszFilename);
         goto out;
     }
@@ -4312,5 +4109,5 @@
     if (RT_FAILURE(rc))
     {
-        rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot set image comment in '%s'"), pImage->pszFilename);
+        rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot set image comment in '%s'"), pImage->pszFilename);
         goto out;
     }
@@ -4329,5 +4126,5 @@
         if (RT_FAILURE(rc))
         {
-            rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write VMDK header in '%s'"), pImage->pszFilename);
+            rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write VMDK header in '%s'"), pImage->pszFilename);
             goto out;
         }
@@ -4336,5 +4133,5 @@
         if (RT_FAILURE(rc))
         {
-            rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write VMDK descriptor in '%s'"), pImage->pszFilename);
+            rc = vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write VMDK descriptor in '%s'"), pImage->pszFilename);
             goto out;
         }
@@ -4371,5 +4168,5 @@
         RTStrFree(pszCommentEncoded);
     if (RT_FAILURE(rc))
-        return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error storing image comment in descriptor in '%s'"), pImage->pszFilename);
+        return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error storing image comment in descriptor in '%s'"), pImage->pszFilename);
     return VINF_SUCCESS;
 }
@@ -4429,6 +4226,6 @@
     pMarker->uSector = RT_H2LE_U64(VMDK_BYTE2SECTOR(pExtent->cGTEntries * sizeof(uint32_t)));
     pMarker->uType = RT_H2LE_U32(VMDK_MARKER_GT);
-    rc = vmdkFileWriteSync(pImage, pExtent->pFile, uFileOffset,
-                           aMarker, sizeof(aMarker), NULL);
+    rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pExtent->pFile->pStorage, uFileOffset,
+                                aMarker, sizeof(aMarker), NULL);
     AssertRC(rc);
     uFileOffset += 512;
@@ -4447,8 +4244,8 @@
             *pGTTmp = RT_H2LE_U32(*pGTTmp);
 
-        rc = vmdkFileWriteSync(pImage, pExtent->pFile, uFileOffset,
-                               &pImage->pGTCache->aGTCache[i].aGTData[0],
-                               VMDK_GT_CACHELINE_SIZE * sizeof(uint32_t),
-                               NULL);
+        rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pExtent->pFile->pStorage, uFileOffset,
+                                    &pImage->pGTCache->aGTCache[i].aGTData[0],
+                                    VMDK_GT_CACHELINE_SIZE * sizeof(uint32_t),
+                                    NULL);
         uFileOffset += VMDK_GT_CACHELINE_SIZE * sizeof(uint32_t);
         if (RT_FAILURE(rc))
@@ -4537,6 +4334,6 @@
                 pMarker->uSector = VMDK_BYTE2SECTOR(RT_ALIGN_64(RT_H2LE_U64(pExtent->cGDEntries * sizeof(uint32_t)), 512));
                 pMarker->uType = RT_H2LE_U32(VMDK_MARKER_GD);
-                rc = vmdkFileWriteSync(pImage, pExtent->pFile, uFileOffset,
-                                       aMarker, sizeof(aMarker), NULL);
+                rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pExtent->pFile->pStorage, uFileOffset,
+                                            aMarker, sizeof(aMarker), NULL);
                 AssertRC(rc);
                 uFileOffset += 512;
@@ -4547,8 +4344,8 @@
                 for (uint32_t i = 0; i < pExtent->cGDEntries; i++, pGDTmp++)
                     *pGDTmp = RT_H2LE_U32(*pGDTmp);
-                rc = vmdkFileWriteSync(pImage, pExtent->pFile, uFileOffset,
-                                       pExtent->pGD,
-                                       pExtent->cGDEntries * sizeof(uint32_t),
-                                       NULL);
+                rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pExtent->pFile->pStorage,
+                                            uFileOffset, pExtent->pGD,
+                                            pExtent->cGDEntries * sizeof(uint32_t),
+                                            NULL);
                 AssertRC(rc);
 
@@ -4563,6 +4360,6 @@
                 pMarker->uSector = VMDK_BYTE2SECTOR(512);
                 pMarker->uType = RT_H2LE_U32(VMDK_MARKER_FOOTER);
-                rc = vmdkFileWriteSync(pImage, pExtent->pFile, uFileOffset,
-                                       aMarker, sizeof(aMarker), NULL);
+                rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pExtent->pFile->pStorage,
+                                            uFileOffset, aMarker, sizeof(aMarker), NULL);
                 AssertRC(rc);
 
@@ -4574,6 +4371,6 @@
                 /* End-of-stream marker. */
                 memset(pMarker, '\0', sizeof(aMarker));
-                rc = vmdkFileWriteSync(pImage, pExtent->pFile, uFileOffset,
-                                       aMarker, sizeof(aMarker), NULL);
+                rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pExtent->pFile->pStorage,
+                                            uFileOffset, aMarker, sizeof(aMarker), NULL);
                 AssertRC(rc);
             }
@@ -4682,5 +4479,5 @@
                     && !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)
                     && !(pExtent->pszBasename[0] == RTPATH_SLASH))
-                    rc = vmdkFileFlush(pImage, pExtent->pFile);
+                    rc = vdIfIoIntFileFlushSync(pImage->pIfIo, pExtent->pFile->pStorage);
                 break;
             case VMDKETYPE_ZERO:
@@ -4781,9 +4578,9 @@
     {
         /* Cache miss, fetch data from disk. */
-        rc = vmdkFileReadSync(pImage, pExtent->pFile,
-                              VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),
-                              aGTDataTmp, sizeof(aGTDataTmp), NULL);
+        rc = vdIfIoIntFileReadSync(pImage->pIfIo, pExtent->pFile->pStorage,
+                                   VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),
+                                   aGTDataTmp, sizeof(aGTDataTmp), NULL);
         if (RT_FAILURE(rc))
-            return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot read grain table entry in '%s'"), pExtent->pszFullname);
+            return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot read grain table entry in '%s'"), pExtent->pszFullname);
         pGTCacheEntry->uExtent = pExtent->uExtent;
         pGTCacheEntry->uGTBlock = uGTBlock;
@@ -4835,11 +4632,11 @@
         /* Cache miss, fetch data from disk. */
         PVDMETAXFER pMetaXfer;
-        rc = vmdkFileReadMetaAsync(pImage, pExtent->pFile,
-                                   VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),
-                                   aGTDataTmp, sizeof(aGTDataTmp), pIoCtx, &pMetaXfer, NULL, NULL);
+        rc = vdIfIoIntFileReadMetaAsync(pImage->pIfIo, pExtent->pFile->pStorage,
+                                        VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),
+                                        aGTDataTmp, sizeof(aGTDataTmp), pIoCtx, &pMetaXfer, NULL, NULL);
         if (RT_FAILURE(rc))
             return rc;
         /* We can release the metadata transfer immediately. */
-        vmdkFileMetaXferRelease(pImage, pMetaXfer);
+        vdIfIoIntMetaXferRelease(pImage->pIfIo, pMetaXfer);
         pGTCacheEntry->uExtent = pExtent->uExtent;
         pGTCacheEntry->uGTBlock = uGTBlock;
@@ -4911,9 +4708,9 @@
              i++)
         {
-            rc = vmdkFileWriteSync(pImage, pExtent->pFile,
-                                   VMDK_SECTOR2BYTE(uGTSector) + i * sizeof(aGTDataTmp),
-                                   aGTDataTmp, sizeof(aGTDataTmp), NULL);
+            rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pExtent->pFile->pStorage,
+                                        VMDK_SECTOR2BYTE(uGTSector) + i * sizeof(aGTDataTmp),
+                                        aGTDataTmp, sizeof(aGTDataTmp), NULL);
             if (RT_FAILURE(rc))
-                return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write grain table allocation in '%s'"), pExtent->pszFullname);
+                return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write grain table allocation in '%s'"), pExtent->pszFullname);
         }
         pExtent->uAppendPosition = RT_ALIGN_64(  pExtent->uAppendPosition
@@ -4946,9 +4743,9 @@
                  i++)
             {
-                rc = vmdkFileWriteSync(pImage, pExtent->pFile,
-                                       VMDK_SECTOR2BYTE(uRGTSector) + i * sizeof(aGTDataTmp),
-                                       aGTDataTmp, sizeof(aGTDataTmp), NULL);
+                rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pExtent->pFile->pStorage,
+                                            VMDK_SECTOR2BYTE(uRGTSector) + i * sizeof(aGTDataTmp),
+                                            aGTDataTmp, sizeof(aGTDataTmp), NULL);
                 if (RT_FAILURE(rc))
-                    return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write backup grain table allocation in '%s'"), pExtent->pszFullname);
+                    return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write backup grain table allocation in '%s'"), pExtent->pszFullname);
             }
 
@@ -4962,17 +4759,17 @@
          * some unused sectors in the extent. */
         uint32_t uGTSectorLE = RT_H2LE_U64(uGTSector);
-        rc = vmdkFileWriteSync(pImage, pExtent->pFile,
-                               VMDK_SECTOR2BYTE(pExtent->uSectorGD) + uGDIndex * sizeof(uGTSectorLE),
-                               &uGTSectorLE, sizeof(uGTSectorLE), NULL);
+        rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pExtent->pFile->pStorage,
+                                    VMDK_SECTOR2BYTE(pExtent->uSectorGD) + uGDIndex * sizeof(uGTSectorLE),
+                                    &uGTSectorLE, sizeof(uGTSectorLE), NULL);
         if (RT_FAILURE(rc))
-            return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write grain directory entry in '%s'"), pExtent->pszFullname);
+            return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write grain directory entry in '%s'"), pExtent->pszFullname);
         if (pExtent->pRGD)
         {
             uint32_t uRGTSectorLE = RT_H2LE_U64(uRGTSector);
-            rc = vmdkFileWriteSync(pImage, pExtent->pFile,
-                                   VMDK_SECTOR2BYTE(pExtent->uSectorRGD) + uGDIndex * sizeof(uRGTSectorLE),
-                                   &uRGTSectorLE, sizeof(uRGTSectorLE), NULL);
+            rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pExtent->pFile->pStorage,
+                                        VMDK_SECTOR2BYTE(pExtent->uSectorRGD) + uGDIndex * sizeof(uRGTSectorLE),
+                                        &uRGTSectorLE, sizeof(uRGTSectorLE), NULL);
             if (RT_FAILURE(rc))
-                return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write backup grain directory entry in '%s'"), pExtent->pszFullname);
+                return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write backup grain directory entry in '%s'"), pExtent->pszFullname);
         }
 
@@ -4992,5 +4789,5 @@
     {
         if (cbWrite != VMDK_SECTOR2BYTE(pExtent->cSectorsPerGrain))
-            return vmdkError(pImage, VERR_INTERNAL_ERROR, RT_SRC_POS, N_("VMDK: not enough data for a compressed data block in '%s'"), pExtent->pszFullname);
+            return vdIfError(pImage->pIfError, VERR_INTERNAL_ERROR, RT_SRC_POS, N_("VMDK: not enough data for a compressed data block in '%s'"), pExtent->pszFullname);
 
         /* Invalidate cache, just in case some code incorrectly allows mixing
@@ -5005,5 +4802,5 @@
         {
             AssertRC(rc);
-            return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write allocated compressed data block in '%s'"), pExtent->pszFullname);
+            return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write allocated compressed data block in '%s'"), pExtent->pszFullname);
         }
         pExtent->uLastGrainAccess = uSector / pExtent->cSectorsPerGrain;
@@ -5012,8 +4809,8 @@
     else
     {
-        rc = vmdkFileWriteSync(pImage, pExtent->pFile, uFileOffset,
-                               pvBuf, cbWrite, NULL);
+        rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pExtent->pFile->pStorage,
+                                    uFileOffset, pvBuf, cbWrite, NULL);
         if (RT_FAILURE(rc))
-            return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write allocated data block in '%s'"), pExtent->pszFullname);
+            return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write allocated data block in '%s'"), pExtent->pszFullname);
         pExtent->uAppendPosition += cbWrite;
     }
@@ -5027,9 +4824,9 @@
     {
         /* Cache miss, fetch data from disk. */
-        rc = vmdkFileReadSync(pImage, pExtent->pFile,
-                              VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),
-                              aGTDataTmp, sizeof(aGTDataTmp), NULL);
+        rc = vdIfIoIntFileReadSync(pImage->pIfIo, pExtent->pFile->pStorage,
+                                   VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),
+                                   aGTDataTmp, sizeof(aGTDataTmp), NULL);
         if (RT_FAILURE(rc))
-            return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot read allocated grain table entry in '%s'"), pExtent->pszFullname);
+            return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot read allocated grain table entry in '%s'"), pExtent->pszFullname);
         pGTCacheEntry->uExtent = pExtent->uExtent;
         pGTCacheEntry->uGTBlock = uGTBlock;
@@ -5048,17 +4845,17 @@
     pGTCacheEntry->aGTData[uGTBlockIndex] = VMDK_BYTE2SECTOR(uFileOffset);
     /* Update grain table on disk. */
-    rc = vmdkFileWriteSync(pImage, pExtent->pFile,
-                           VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),
-                           aGTDataTmp, sizeof(aGTDataTmp), NULL);
+    rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pExtent->pFile->pStorage,
+                                VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),
+                                aGTDataTmp, sizeof(aGTDataTmp), NULL);
     if (RT_FAILURE(rc))
-        return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write updated grain table in '%s'"), pExtent->pszFullname);
+        return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write updated grain table in '%s'"), pExtent->pszFullname);
     if (pExtent->pRGD)
     {
         /* Update backup grain table on disk. */
-        rc = vmdkFileWriteSync(pImage, pExtent->pFile,
-                               VMDK_SECTOR2BYTE(uRGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),
-                               aGTDataTmp, sizeof(aGTDataTmp), NULL);
+        rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pExtent->pFile->pStorage,
+                                    VMDK_SECTOR2BYTE(uRGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),
+                                    aGTDataTmp, sizeof(aGTDataTmp), NULL);
         if (RT_FAILURE(rc))
-            return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write updated backup grain table in '%s'"), pExtent->pszFullname);
+            return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write updated backup grain table in '%s'"), pExtent->pszFullname);
     }
 #ifdef VBOX_WITH_VMDK_ESX
@@ -5164,5 +4961,5 @@
         pExtent->uGrainSectorAbs = 0;
         AssertRC(rc);
-        return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write compressed data block in '%s'"), pExtent->pszFullname);
+        return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write compressed data block in '%s'"), pExtent->pszFullname);
     }
     pExtent->uLastGrainAccess = uGrain;
@@ -5204,8 +5001,8 @@
         LogFlow(("Cache miss, fetch data from disk\n"));
         PVDMETAXFER pMetaXfer = NULL;
-        rc = vmdkFileReadMetaAsync(pImage, pExtent->pFile,
-                                   VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),
-                                   aGTDataTmp, sizeof(aGTDataTmp), pIoCtx,
-                                   &pMetaXfer, vmdkAllocGrainAsyncComplete, pGrainAlloc);
+        rc = vdIfIoIntFileReadMetaAsync(pImage->pIfIo, pExtent->pFile->pStorage,
+                                        VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),
+                                        aGTDataTmp, sizeof(aGTDataTmp), pIoCtx,
+                                        &pMetaXfer, vmdkAllocGrainAsyncComplete, pGrainAlloc);
         if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
         {
@@ -5217,6 +5014,6 @@
         }
         else if (RT_FAILURE(rc))
-            return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot read allocated grain table entry in '%s'"), pExtent->pszFullname);
-        vmdkFileMetaXferRelease(pImage, pMetaXfer);
+            return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot read allocated grain table entry in '%s'"), pExtent->pszFullname);
+        vdIfIoIntMetaXferRelease(pImage->pIfIo, pMetaXfer);
         pGTCacheEntry->uExtent = pExtent->uExtent;
         pGTCacheEntry->uGTBlock = uGTBlock;
@@ -5236,23 +5033,23 @@
     pGTCacheEntry->aGTData[uGTBlockIndex] = VMDK_BYTE2SECTOR(pGrainAlloc->uGrainOffset);
     /* Update grain table on disk. */
-    rc = vmdkFileWriteMetaAsync(pImage, pExtent->pFile,
-                                VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),
-                                aGTDataTmp, sizeof(aGTDataTmp), pIoCtx,
-                                vmdkAllocGrainAsyncComplete, pGrainAlloc);
+    rc = vdIfIoIntFileWriteMetaAsync(pImage->pIfIo, pExtent->pFile->pStorage,
+                                     VMDK_SECTOR2BYTE(uGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),
+                                     aGTDataTmp, sizeof(aGTDataTmp), pIoCtx,
+                                     vmdkAllocGrainAsyncComplete, pGrainAlloc);
     if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
         pGrainAlloc->cIoXfersPending++;
     else if (RT_FAILURE(rc))
-        return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write updated grain table in '%s'"), pExtent->pszFullname);
+        return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write updated grain table in '%s'"), pExtent->pszFullname);
     if (pExtent->pRGD)
     {
         /* Update backup grain table on disk. */
-        rc = vmdkFileWriteMetaAsync(pImage, pExtent->pFile,
-                                    VMDK_SECTOR2BYTE(uRGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),
-                                    aGTDataTmp, sizeof(aGTDataTmp), pIoCtx,
-                                    vmdkAllocGrainAsyncComplete, pGrainAlloc);
+        rc = vdIfIoIntFileWriteMetaAsync(pImage->pIfIo, pExtent->pFile->pStorage,
+                                         VMDK_SECTOR2BYTE(uRGTSector) + (uGTBlock % (pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE)) * sizeof(aGTDataTmp),
+                                         aGTDataTmp, sizeof(aGTDataTmp), pIoCtx,
+                                         vmdkAllocGrainAsyncComplete, pGrainAlloc);
         if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
             pGrainAlloc->cIoXfersPending++;
         else if (RT_FAILURE(rc))
-            return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write updated backup grain table in '%s'"), pExtent->pszFullname);
+            return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write updated backup grain table in '%s'"), pExtent->pszFullname);
     }
 #ifdef VBOX_WITH_VMDK_ESX
@@ -5364,8 +5161,8 @@
 
         memset(paGTDataTmp, '\0', cbGTDataTmp);
-        rc = vmdkFileWriteMetaAsync(pImage, pExtent->pFile,
-                                    VMDK_SECTOR2BYTE(uGTSector),
-                                    paGTDataTmp, cbGTDataTmp, pIoCtx,
-                                    vmdkAllocGrainAsyncComplete, pGrainAlloc);
+        rc = vdIfIoIntFileWriteMetaAsync(pImage->pIfIo, pExtent->pFile->pStorage,
+                                         VMDK_SECTOR2BYTE(uGTSector),
+                                         paGTDataTmp, cbGTDataTmp, pIoCtx,
+                                         vmdkAllocGrainAsyncComplete, pGrainAlloc);
         if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
             pGrainAlloc->cIoXfersPending++;
@@ -5373,5 +5170,5 @@
         {
             RTMemTmpFree(paGTDataTmp);
-            return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write grain table allocation in '%s'"), pExtent->pszFullname);
+            return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write grain table allocation in '%s'"), pExtent->pszFullname);
         }
         pExtent->uAppendPosition = RT_ALIGN_64(  pExtent->uAppendPosition
@@ -5399,8 +5196,8 @@
              * cache chunks. Allocate memory dynamically here or we flood the
              * metadata cache with very small entries. */
-            rc = vmdkFileWriteMetaAsync(pImage, pExtent->pFile,
-                                        VMDK_SECTOR2BYTE(uRGTSector),
-                                        paGTDataTmp, cbGTDataTmp, pIoCtx,
-                                        vmdkAllocGrainAsyncComplete, pGrainAlloc);
+            rc = vdIfIoIntFileWriteMetaAsync(pImage->pIfIo, pExtent->pFile->pStorage,
+                                             VMDK_SECTOR2BYTE(uRGTSector),
+                                             paGTDataTmp, cbGTDataTmp, pIoCtx,
+                                             vmdkAllocGrainAsyncComplete, pGrainAlloc);
             if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
                 pGrainAlloc->cIoXfersPending++;
@@ -5408,5 +5205,5 @@
             {
                 RTMemTmpFree(paGTDataTmp);
-                return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write backup grain table allocation in '%s'"), pExtent->pszFullname);
+                return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write backup grain table allocation in '%s'"), pExtent->pszFullname);
             }
 
@@ -5421,23 +5218,23 @@
          * some unused sectors in the extent. */
         uint32_t uGTSectorLE = RT_H2LE_U64(uGTSector);
-        rc = vmdkFileWriteMetaAsync(pImage, pExtent->pFile,
-                                    VMDK_SECTOR2BYTE(pExtent->uSectorGD) + uGDIndex * sizeof(uGTSectorLE),
-                                    &uGTSectorLE, sizeof(uGTSectorLE), pIoCtx,
-                                    vmdkAllocGrainAsyncComplete, pGrainAlloc);
+        rc = vdIfIoIntFileWriteMetaAsync(pImage->pIfIo, pExtent->pFile->pStorage,
+                                         VMDK_SECTOR2BYTE(pExtent->uSectorGD) + uGDIndex * sizeof(uGTSectorLE),
+                                         &uGTSectorLE, sizeof(uGTSectorLE), pIoCtx,
+                                         vmdkAllocGrainAsyncComplete, pGrainAlloc);
         if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
             pGrainAlloc->cIoXfersPending++;
         else if (RT_FAILURE(rc))
-            return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write grain directory entry in '%s'"), pExtent->pszFullname);
+            return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write grain directory entry in '%s'"), pExtent->pszFullname);
         if (pExtent->pRGD)
         {
             uint32_t uRGTSectorLE = RT_H2LE_U64(uRGTSector);
-            rc = vmdkFileWriteMetaAsync(pImage, pExtent->pFile,
-                                        VMDK_SECTOR2BYTE(pExtent->uSectorRGD) + uGDIndex * sizeof(uGTSectorLE),
-                                        &uRGTSectorLE, sizeof(uRGTSectorLE), pIoCtx,
-                                        vmdkAllocGrainAsyncComplete, pGrainAlloc);
+            rc = vdIfIoIntFileWriteMetaAsync(pImage->pIfIo, pExtent->pFile->pStorage,
+                                             VMDK_SECTOR2BYTE(pExtent->uSectorRGD) + uGDIndex * sizeof(uGTSectorLE),
+                                             &uRGTSectorLE, sizeof(uRGTSectorLE), pIoCtx,
+                                             vmdkAllocGrainAsyncComplete, pGrainAlloc);
             if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
                 pGrainAlloc->cIoXfersPending++;
             else if (RT_FAILURE(rc))
-                return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write backup grain directory entry in '%s'"), pExtent->pszFullname);
+                return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write backup grain directory entry in '%s'"), pExtent->pszFullname);
         }
 
@@ -5460,11 +5257,11 @@
 
     /* Write the data. Always a full grain, or we're in big trouble. */
-    rc = vmdkFileWriteUserAsync(pImage, pExtent->pFile,
-                                uFileOffset, pIoCtx, cbWrite,
-                                vmdkAllocGrainAsyncComplete, pGrainAlloc);
+    rc = vdIfIoIntFileWriteUserAsync(pImage->pIfIo, pExtent->pFile->pStorage,
+                                     uFileOffset, pIoCtx, cbWrite,
+                                     vmdkAllocGrainAsyncComplete, pGrainAlloc);
     if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
         pGrainAlloc->cIoXfersPending++;
     else if (RT_FAILURE(rc))
-        return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: cannot write allocated data block in '%s'"), pExtent->pszFullname);
+        return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: cannot write allocated data block in '%s'"), pExtent->pszFullname);
 
     pExtent->uAppendPosition += cbWrite;
@@ -5518,8 +5315,8 @@
         {
             RT_ZERO(Marker);
-            rc = vmdkFileReadSync(pImage, pExtent->pFile,
-                                  VMDK_SECTOR2BYTE(uGrainSectorAbs),
-                                  &Marker, RT_OFFSETOF(VMDKMARKER, uType),
-                                  NULL);
+            rc = vdIfIoIntFileReadSync(pImage->pIfIo, pExtent->pFile->pStorage,
+                                       VMDK_SECTOR2BYTE(uGrainSectorAbs),
+                                       &Marker, RT_OFFSETOF(VMDKMARKER, uType),
+                                       NULL);
             if (RT_FAILURE(rc))
                 return rc;
@@ -5530,9 +5327,9 @@
             {
                 /* A marker for something else than a compressed grain. */
-                rc = vmdkFileReadSync(pImage, pExtent->pFile,
-                                        VMDK_SECTOR2BYTE(uGrainSectorAbs)
-                                      + RT_OFFSETOF(VMDKMARKER, uType),
-                                      &Marker.uType, sizeof(Marker.uType),
-                                      NULL);
+                rc = vdIfIoIntFileReadSync(pImage->pIfIo, pExtent->pFile->pStorage,
+                                             VMDK_SECTOR2BYTE(uGrainSectorAbs)
+                                           + RT_OFFSETOF(VMDKMARKER, uType),
+                                           &Marker.uType, sizeof(Marker.uType),
+                                           NULL);
                 if (RT_FAILURE(rc))
                     return rc;
@@ -5547,8 +5344,8 @@
                          * success case. If this read fails it means the image
                          * is truncated, but this is harmless so ignore. */
-                        vmdkFileReadSync(pImage, pExtent->pFile,
-                                           VMDK_SECTOR2BYTE(uGrainSectorAbs)
-                                         + 511,
-                                         &Marker.uSector, 1, NULL);
+                        vdIfIoIntFileReadSync(pImage->pIfIo, pExtent->pFile->pStorage,
+                                                VMDK_SECTOR2BYTE(uGrainSectorAbs)
+                                              + 511,
+                                              &Marker.uSector, 1, NULL);
                         break;
                     case VMDK_MARKER_GT:
@@ -5767,12 +5564,9 @@
     PFNVDPROGRESS pfnProgress = NULL;
     void *pvUser = NULL;
-    PVDINTERFACE pIfProgress = VDInterfaceGet(pVDIfsOperation,
-                                              VDINTERFACETYPE_PROGRESS);
-    PVDINTERFACEPROGRESS pCbProgress = NULL;
+    PVDINTERFACEPROGRESS pIfProgress = VDIfProgressGet(pVDIfsOperation);
     if (pIfProgress)
     {
-        pCbProgress = VDGetInterfaceProgress(pIfProgress);
-        pfnProgress = pCbProgress->pfnProgress;
-        pvUser = pIfProgress->pvUser;
+        pfnProgress = pIfProgress->pfnProgress;
+        pvUser = pIfProgress->Core.pvUser;
     }
 
@@ -5996,5 +5790,5 @@
         vmdkFileClose(pImage, &pExtent->pFile, false);
         /* Rename the extent file. */
-        rc = vmdkFileMove(pImage, pExtent->pszFullname, apszNewName[i], 0);
+        rc = vdIfIoIntFileMove(pImage->pIfIo, pExtent->pszFullname, apszNewName[i], 0);
         if (RT_FAILURE(rc))
             goto rollback;
@@ -6014,5 +5808,5 @@
     if (!fEmbeddedDesc)
     {
-        rc = vmdkFileMove(pImage, pImage->pszFilename, apszNewName[cExtents], 0);
+        rc = vdIfIoIntFileMove(pImage->pIfIo, pImage->pszFilename, apszNewName[cExtents], 0);
         if (RT_FAILURE(rc))
             goto rollback;
@@ -6047,5 +5841,5 @@
             if (apszOldName[i])
             {
-                rrc = vmdkFileMove(pImage, apszNewName[i], apszOldName[i], 0);
+                rrc = vdIfIoIntFileMove(pImage->pIfIo, apszNewName[i], apszOldName[i], 0);
                 AssertRC(rrc);
             }
@@ -6227,7 +6021,7 @@
                 else
                 {
-                    rc = vmdkFileReadSync(pImage, pExtent->pFile,
-                                          VMDK_SECTOR2BYTE(uSectorExtentAbs),
-                                          pvBuf, cbToRead, NULL);
+                    rc = vdIfIoIntFileReadSync(pImage->pIfIo, pExtent->pFile->pStorage,
+                                               VMDK_SECTOR2BYTE(uSectorExtentAbs),
+                                               pvBuf, cbToRead, NULL);
                 }
             }
@@ -6235,7 +6029,7 @@
         case VMDKETYPE_VMFS:
         case VMDKETYPE_FLAT:
-            rc = vmdkFileReadSync(pImage, pExtent->pFile,
-                                  VMDK_SECTOR2BYTE(uSectorExtentRel),
-                                  pvBuf, cbToRead, NULL);
+            rc = vdIfIoIntFileReadSync(pImage->pIfIo, pExtent->pFile->pStorage,
+                                       VMDK_SECTOR2BYTE(uSectorExtentRel),
+                                       pvBuf, cbToRead, NULL);
             break;
         case VMDKETYPE_ZERO:
@@ -6369,7 +6163,7 @@
                 else
                 {
-                    rc = vmdkFileWriteSync(pImage, pExtent->pFile,
-                                           VMDK_SECTOR2BYTE(uSectorExtentAbs),
-                                           pvBuf, cbToWrite, NULL);
+                    rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pExtent->pFile->pStorage,
+                                                VMDK_SECTOR2BYTE(uSectorExtentAbs),
+                                                pvBuf, cbToWrite, NULL);
                 }
             }
@@ -6379,7 +6173,7 @@
             /* Clip write range to remain in this extent. */
             cbToWrite = RT_MIN(cbToWrite, VMDK_SECTOR2BYTE(pExtent->uSectorOffset + pExtent->cNominalSectors - uSectorExtentRel));
-            rc = vmdkFileWriteSync(pImage, pExtent->pFile,
-                                   VMDK_SECTOR2BYTE(uSectorExtentRel),
-                                   pvBuf, cbToWrite, NULL);
+            rc = vdIfIoIntFileWriteSync(pImage->pIfIo, pExtent->pFile->pStorage,
+                                        VMDK_SECTOR2BYTE(uSectorExtentRel),
+                                        pvBuf, cbToWrite, NULL);
             break;
         case VMDKETYPE_ZERO:
@@ -6455,5 +6249,5 @@
         if (pImage->pFile != NULL)
         {
-            int rc = vmdkFileGetSize(pImage, pImage->pFile, &cbFile);
+            int rc = vdIfIoIntFileGetSize(pImage->pIfIo, pImage->pFile->pStorage, &cbFile);
             if (RT_SUCCESS(rc))
                 cb += cbFile;
@@ -6463,5 +6257,5 @@
             if (pImage->pExtents[i].pFile != NULL)
             {
-                int rc = vmdkFileGetSize(pImage, pImage->pExtents[i].pFile, &cbFile);
+                int rc = vdIfIoIntFileGetSize(pImage->pIfIo, pImage->pExtents[i].pFile->pStorage, &cbFile);
                 if (RT_SUCCESS(rc))
                     cb += cbFile;
@@ -6777,5 +6571,5 @@
                                         VMDK_DDB_IMAGE_UUID, pUuid);
                 if (RT_FAILURE(rc))
-                    return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error storing image UUID in descriptor in '%s'"), pImage->pszFilename);
+                    return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error storing image UUID in descriptor in '%s'"), pImage->pszFilename);
                 rc = VINF_SUCCESS;
             }
@@ -6836,5 +6630,5 @@
                                             VMDK_DDB_MODIFICATION_UUID, pUuid);
                     if (RT_FAILURE(rc))
-                        return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error storing modification UUID in descriptor in '%s'"), pImage->pszFilename);
+                        return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error storing modification UUID in descriptor in '%s'"), pImage->pszFilename);
                 }
                 rc = VINF_SUCCESS;
@@ -6893,5 +6687,5 @@
                                         VMDK_DDB_PARENT_UUID, pUuid);
                 if (RT_FAILURE(rc))
-                    return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error storing parent image UUID in descriptor in '%s'"), pImage->pszFilename);
+                    return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error storing parent image UUID in descriptor in '%s'"), pImage->pszFilename);
                 rc = VINF_SUCCESS;
             }
@@ -6949,5 +6743,5 @@
                                         VMDK_DDB_PARENT_MODIFICATION_UUID, pUuid);
                 if (RT_FAILURE(rc))
-                    return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error storing parent image UUID in descriptor in '%s'"), pImage->pszFilename);
+                    return vdIfError(pImage->pIfError, rc, RT_SRC_POS, N_("VMDK: error storing parent image UUID in descriptor in '%s'"), pImage->pszFilename);
                 rc = VINF_SUCCESS;
             }
@@ -6973,12 +6767,12 @@
     if (pImage)
     {
-        vmdkMessage(pImage, "Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u cbSector=%llu\n",
-                    pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors,
-                    pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors,
-                    VMDK_BYTE2SECTOR(pImage->cbSize));
-        vmdkMessage(pImage, "Header: uuidCreation={%RTuuid}\n", &pImage->ImageUuid);
-        vmdkMessage(pImage, "Header: uuidModification={%RTuuid}\n", &pImage->ModificationUuid);
-        vmdkMessage(pImage, "Header: uuidParent={%RTuuid}\n", &pImage->ParentUuid);
-        vmdkMessage(pImage, "Header: uuidParentModification={%RTuuid}\n", &pImage->ParentModificationUuid);
+        vdIfErrorMessage(pImage->pIfError, "Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u cbSector=%llu\n",
+                         pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors,
+                         pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors,
+                         VMDK_BYTE2SECTOR(pImage->cbSize));
+        vdIfErrorMessage(pImage->pIfError, "Header: uuidCreation={%RTuuid}\n", &pImage->ImageUuid);
+        vdIfErrorMessage(pImage->pIfError, "Header: uuidModification={%RTuuid}\n", &pImage->ModificationUuid);
+        vdIfErrorMessage(pImage->pIfError, "Header: uuidParent={%RTuuid}\n", &pImage->ParentUuid);
+        vdIfErrorMessage(pImage->pIfError, "Header: uuidParentModification={%RTuuid}\n", &pImage->ParentModificationUuid);
     }
 }
@@ -7041,19 +6835,19 @@
             {
                 AssertMsg(!(pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED), ("Async I/O is not supported for stream optimized VMDK's\n"));
-                rc = vmdkFileReadUserAsync(pImage, pExtent->pFile,
-                                           VMDK_SECTOR2BYTE(uSectorExtentAbs),
-                                           pIoCtx, cbRead);
+                rc = vdIfIoIntFileReadUserAsync(pImage->pIfIo, pExtent->pFile->pStorage,
+                                                VMDK_SECTOR2BYTE(uSectorExtentAbs),
+                                                pIoCtx, cbRead);
             }
             break;
         case VMDKETYPE_VMFS:
         case VMDKETYPE_FLAT:
-            rc = vmdkFileReadUserAsync(pImage, pExtent->pFile,
-                                       VMDK_SECTOR2BYTE(uSectorExtentRel),
-                                       pIoCtx, cbRead);
+            rc = vdIfIoIntFileReadUserAsync(pImage->pIfIo, pExtent->pFile->pStorage,
+                                            VMDK_SECTOR2BYTE(uSectorExtentRel),
+                                            pIoCtx, cbRead);
             break;
         case VMDKETYPE_ZERO:
             size_t cbSet;
 
-            cbSet = vmdkFileIoCtxSet(pImage, pIoCtx, 0, cbRead);
+            cbSet = vdIfIoIntIoCtxSet(pImage->pIfIo, pIoCtx, 0, cbRead);
             Assert(cbSet == cbRead);
 
@@ -7166,7 +6960,7 @@
             {
                 Assert(!(pImage->uImageFlags & VD_VMDK_IMAGE_FLAGS_STREAM_OPTIMIZED));
-                rc = vmdkFileWriteUserAsync(pImage, pExtent->pFile,
-                                            VMDK_SECTOR2BYTE(uSectorExtentAbs),
-                                            pIoCtx, cbWrite, NULL, NULL);
+                rc = vdIfIoIntFileWriteUserAsync(pImage->pIfIo, pExtent->pFile->pStorage,
+                                                 VMDK_SECTOR2BYTE(uSectorExtentAbs),
+                                                 pIoCtx, cbWrite, NULL, NULL);
             }
             break;
@@ -7175,7 +6969,7 @@
             /* Clip write range to remain in this extent. */
             cbWrite = RT_MIN(cbWrite, VMDK_SECTOR2BYTE(pExtent->uSectorOffset + pExtent->cNominalSectors - uSectorExtentRel));
-            rc = vmdkFileWriteUserAsync(pImage, pExtent->pFile,
-                                        VMDK_SECTOR2BYTE(uSectorExtentRel),
-                                        pIoCtx, cbWrite, NULL, NULL);
+            rc = vdIfIoIntFileWriteUserAsync(pImage->pIfIo, pExtent->pFile->pStorage,
+                                             VMDK_SECTOR2BYTE(uSectorExtentRel),
+                                             pIoCtx, cbWrite, NULL, NULL);
             break;
         case VMDKETYPE_ZERO:
@@ -7270,5 +7064,6 @@
                 if (   pExtent->pFile != NULL
                     && !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY))
-                    rc = vmdkFileFlushAsync(pImage, pExtent->pFile, pIoCtx);
+                    rc = vdIfIoIntFileFlushAsync(pImage->pIfIo, pExtent->pFile->pStorage,
+                                                 pIoCtx, NULL, NULL);
                 break;
             case VMDKETYPE_ZERO:
