VDIHDDCore.cpp revision c7551981eb6d97331da479f68f14a9c56247e4f7
326d1845a5ad33574cb834270779589136854527vboxsync * Virtual Disk Image (VDI), Core Code.
326d1845a5ad33574cb834270779589136854527vboxsync * Copyright (C) 2006-2010 Sun Microsystems, Inc.
326d1845a5ad33574cb834270779589136854527vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
326d1845a5ad33574cb834270779589136854527vboxsync * available from http://www.virtualbox.org. This file is free software;
326d1845a5ad33574cb834270779589136854527vboxsync * you can redistribute it and/or modify it under the terms of the GNU
326d1845a5ad33574cb834270779589136854527vboxsync * General Public License (GPL) as published by the Free Software
326d1845a5ad33574cb834270779589136854527vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
326d1845a5ad33574cb834270779589136854527vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
326d1845a5ad33574cb834270779589136854527vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
326d1845a5ad33574cb834270779589136854527vboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
326d1845a5ad33574cb834270779589136854527vboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
326d1845a5ad33574cb834270779589136854527vboxsync * additional information or have any questions.
326d1845a5ad33574cb834270779589136854527vboxsync/*******************************************************************************
326d1845a5ad33574cb834270779589136854527vboxsync* Header Files *
326d1845a5ad33574cb834270779589136854527vboxsync*******************************************************************************/
326d1845a5ad33574cb834270779589136854527vboxsync#define VBOX_VDICORE_VD /* Signal that the header is included from here. */
326d1845a5ad33574cb834270779589136854527vboxsync/*******************************************************************************
326d1845a5ad33574cb834270779589136854527vboxsync* Static Variables *
326d1845a5ad33574cb834270779589136854527vboxsync*******************************************************************************/
326d1845a5ad33574cb834270779589136854527vboxsync/** NULL-terminated array of supported file extensions. */
326d1845a5ad33574cb834270779589136854527vboxsyncstatic const char *const s_apszVdiFileExtensions[] =
326d1845a5ad33574cb834270779589136854527vboxsync/*******************************************************************************
326d1845a5ad33574cb834270779589136854527vboxsync* Internal Functions *
326d1845a5ad33574cb834270779589136854527vboxsync*******************************************************************************/
326d1845a5ad33574cb834270779589136854527vboxsyncstatic void vdiInitPreHeader(PVDIPREHEADER pPreHdr);
326d1845a5ad33574cb834270779589136854527vboxsyncstatic int vdiValidatePreHeader(PVDIPREHEADER pPreHdr);
326d1845a5ad33574cb834270779589136854527vboxsyncstatic void vdiInitHeader(PVDIHEADER pHeader, uint32_t uImageFlags,
326d1845a5ad33574cb834270779589136854527vboxsyncstatic void vdiSetupImageDesc(PVDIIMAGEDESC pImage);
326d1845a5ad33574cb834270779589136854527vboxsyncstatic int vdiUpdateBlockInfo(PVDIIMAGEDESC pImage, unsigned uBlock);
326d1845a5ad33574cb834270779589136854527vboxsyncstatic void vdiFreeImage(PVDIIMAGEDESC pImage, bool fDelete);
326d1845a5ad33574cb834270779589136854527vboxsync * Internal: signal an error to the frontend.
326d1845a5ad33574cb834270779589136854527vboxsyncDECLINLINE(int) vdiError(PVDIIMAGEDESC pImage, int rc, RT_SRC_POS_DECL,
326d1845a5ad33574cb834270779589136854527vboxsync const char *pszFormat, ...)
326d1845a5ad33574cb834270779589136854527vboxsync if (pImage->pInterfaceError && pImage->pInterfaceErrorCallbacks)
326d1845a5ad33574cb834270779589136854527vboxsync pImage->pInterfaceErrorCallbacks->pfnError(pImage->pInterfaceError->pvUser,
326d1845a5ad33574cb834270779589136854527vboxsyncstatic int vdiFileOpen(PVDIIMAGEDESC pImage, bool fReadonly, bool fCreate)
326d1845a5ad33574cb834270779589136854527vboxsync AssertMsg(!(fReadonly && fCreate), ("Image can't be opened readonly whilebeing created\n"));
326d1845a5ad33574cb834270779589136854527vboxsync uint32_t fOpen = fReadonly ? RTFILE_O_READ | RTFILE_O_DENY_NONE
326d1845a5ad33574cb834270779589136854527vboxsync rc = RTFileOpen(&pImage->File, pImage->pszFilename, fOpen);
326d1845a5ad33574cb834270779589136854527vboxsync unsigned uOpenFlags = fReadonly ? VD_INTERFACEASYNCIO_OPEN_FLAGS_READONLY : 0;
326d1845a5ad33574cb834270779589136854527vboxsync uOpenFlags |= VD_INTERFACEASYNCIO_OPEN_FLAGS_CREATE;
326d1845a5ad33574cb834270779589136854527vboxsync rc = pImage->pInterfaceIOCallbacks->pfnOpen(pImage->pInterfaceIO->pvUser,
326d1845a5ad33574cb834270779589136854527vboxsync rc = pImage->pInterfaceIOCallbacks->pfnClose(pImage->pInterfaceIO->pvUser,
326d1845a5ad33574cb834270779589136854527vboxsync rc = pImage->pInterfaceIOCallbacks->pfnFlushSync(pImage->pInterfaceIO->pvUser,
326d1845a5ad33574cb834270779589136854527vboxsyncstatic int vdiFileGetSize(PVDIIMAGEDESC pImage, uint64_t *pcbSize)
326d1845a5ad33574cb834270779589136854527vboxsync rc = pImage->pInterfaceIOCallbacks->pfnGetSize(pImage->pInterfaceIO->pvUser,
326d1845a5ad33574cb834270779589136854527vboxsyncstatic int vdiFileSetSize(PVDIIMAGEDESC pImage, uint64_t cbSize)
326d1845a5ad33574cb834270779589136854527vboxsync rc = pImage->pInterfaceIOCallbacks->pfnSetSize(pImage->pInterfaceIO->pvUser,
326d1845a5ad33574cb834270779589136854527vboxsyncstatic int vdiFileWriteSync(PVDIIMAGEDESC pImage, uint64_t off, const void *pcvBuf, size_t cbWrite, size_t *pcbWritten)
326d1845a5ad33574cb834270779589136854527vboxsync rc = RTFileWriteAt(pImage->File, off, pcvBuf, cbWrite, pcbWritten);
326d1845a5ad33574cb834270779589136854527vboxsync rc = pImage->pInterfaceIOCallbacks->pfnWriteSync(pImage->pInterfaceIO->pvUser,
326d1845a5ad33574cb834270779589136854527vboxsyncstatic int vdiFileReadSync(PVDIIMAGEDESC pImage, uint64_t off, void *pvBuf, size_t cbRead, size_t *pcbRead)
326d1845a5ad33574cb834270779589136854527vboxsync rc = RTFileReadAt(pImage->File, off, pvBuf, cbRead, pcbRead);
326d1845a5ad33574cb834270779589136854527vboxsync rc = pImage->pInterfaceIOCallbacks->pfnReadSync(pImage->pInterfaceIO->pvUser,
326d1845a5ad33574cb834270779589136854527vboxsync * internal: return power of 2 or 0 if num error.
326d1845a5ad33574cb834270779589136854527vboxsync unsigned uPower2 = 0;
326d1845a5ad33574cb834270779589136854527vboxsync * Internal: Init VDI preheader.
326d1845a5ad33574cb834270779589136854527vboxsync memset(pPreHdr->szFileInfo, 0, sizeof(pPreHdr->szFileInfo));
326d1845a5ad33574cb834270779589136854527vboxsync strncat(pPreHdr->szFileInfo, VDI_IMAGE_FILE_INFO, sizeof(pPreHdr->szFileInfo));
db073d0e5fab95903c54296592a82cb35d565520vboxsync * Internal: check VDI preheader.
db073d0e5fab95903c54296592a82cb35d565520vboxsyncstatic int vdiValidatePreHeader(PVDIPREHEADER pPreHdr)
db073d0e5fab95903c54296592a82cb35d565520vboxsync if ( VDI_GET_VERSION_MAJOR(pPreHdr->u32Version) != VDI_IMAGE_VERSION_MAJOR
db073d0e5fab95903c54296592a82cb35d565520vboxsync && pPreHdr->u32Version != 0x00000002) /* old version. */
db073d0e5fab95903c54296592a82cb35d565520vboxsync * Internal: translate VD image flags to VDI image type enum.
db073d0e5fab95903c54296592a82cb35d565520vboxsyncstatic VDIIMAGETYPE vdiTranslateImageFlags2VDI(unsigned uImageFlags)
db073d0e5fab95903c54296592a82cb35d565520vboxsync * Internal: translate VDI image type enum to VD image type enum.
db073d0e5fab95903c54296592a82cb35d565520vboxsyncstatic unsigned vdiTranslateVDI2ImageFlags(VDIIMAGETYPE enmType)
326d1845a5ad33574cb834270779589136854527vboxsync AssertMsgFailed(("invalid VDIIMAGETYPE enmType=%d\n", (int)enmType));
326d1845a5ad33574cb834270779589136854527vboxsync * Internal: Init VDI header. Always use latest header version.
326d1845a5ad33574cb834270779589136854527vboxsync * @param pHeader Assumes it was initially initialized to all zeros.
326d1845a5ad33574cb834270779589136854527vboxsyncstatic void vdiInitHeader(PVDIHEADER pHeader, uint32_t uImageFlags,
326d1845a5ad33574cb834270779589136854527vboxsync pHeader->u.v1.u32Type = (uint32_t)vdiTranslateImageFlags2VDI(uImageFlags);
326d1845a5ad33574cb834270779589136854527vboxsync pHeader->u.v1.fFlags = (uImageFlags & VD_VDI_IMAGE_FLAGS_ZERO_EXPAND) ? 1 : 0;
326d1845a5ad33574cb834270779589136854527vboxsync Assert(!memcmp(pHeader->u.v1.szComment, achZero, VDI_IMAGE_COMMENT_SIZE));
326d1845a5ad33574cb834270779589136854527vboxsync AssertMsg(strlen(pszComment) < sizeof(pHeader->u.v1.szComment),
326d1845a5ad33574cb834270779589136854527vboxsync ("HDD Comment is too long, cb=%d\n", strlen(pszComment)));
326d1845a5ad33574cb834270779589136854527vboxsync strncat(pHeader->u.v1.szComment, pszComment, sizeof(pHeader->u.v1.szComment));
326d1845a5ad33574cb834270779589136854527vboxsync /* Mark the legacy geometry not-calculated. */
326d1845a5ad33574cb834270779589136854527vboxsync pHeader->u.v1.LegacyGeometry.cbSector = VDI_GEOMETRY_SECTOR_SIZE;
326d1845a5ad33574cb834270779589136854527vboxsync pHeader->u.v1.u32Dummy = 0; /* used to be the translation value */
326d1845a5ad33574cb834270779589136854527vboxsync pHeader->u.v1.cBlocks = (uint32_t)(cbDisk / cbBlock);
326d1845a5ad33574cb834270779589136854527vboxsync /* Init offsets. */
326d1845a5ad33574cb834270779589136854527vboxsync pHeader->u.v1.offBlocks = RT_ALIGN_32(sizeof(VDIPREHEADER) + sizeof(VDIHEADER1), VDI_GEOMETRY_SECTOR_SIZE);
326d1845a5ad33574cb834270779589136854527vboxsync pHeader->u.v1.offData = RT_ALIGN_32(pHeader->u.v1.offBlocks + (pHeader->u.v1.cBlocks * sizeof(VDIIMAGEBLOCKPOINTER)), VDI_GEOMETRY_SECTOR_SIZE);
326d1845a5ad33574cb834270779589136854527vboxsync /* Init uuids. */
326d1845a5ad33574cb834270779589136854527vboxsync /* Mark LCHS geometry not-calculated. */
326d1845a5ad33574cb834270779589136854527vboxsync pHeader->u.v1plus.LCHSGeometry.cbSector = VDI_GEOMETRY_SECTOR_SIZE;
326d1845a5ad33574cb834270779589136854527vboxsync * Internal: Check VDI header.
326d1845a5ad33574cb834270779589136854527vboxsync /* Check version-dependend header parameters. */
326d1845a5ad33574cb834270779589136854527vboxsync /* Old header version. */
326d1845a5ad33574cb834270779589136854527vboxsync /* Current header version. */
326d1845a5ad33574cb834270779589136854527vboxsync if (getImageBlocksOffset(pHeader) < (sizeof(VDIPREHEADER) + sizeof(VDIHEADER1)))
326d1845a5ad33574cb834270779589136854527vboxsync getImageBlocksOffset(pHeader), sizeof(VDIPREHEADER) + sizeof(VDIHEADER1)));
if (getImageDataOffset(pHeader) < (getImageBlocksOffset(pHeader) + getImageBlocks(pHeader) * sizeof(VDIIMAGEBLOCKPOINTER)))
getImageDataOffset(pHeader), getImageBlocksOffset(pHeader) + getImageBlocks(pHeader) * sizeof(VDIIMAGEBLOCKPOINTER)));
return VERR_VD_VDI_INVALID_HEADER;
return VERR_VD_VDI_UNSUPPORTED_VERSION;
bool fFailed = false;
fFailed = true;
fFailed = true;
fFailed = true;
fFailed = true;
fFailed = true;
fFailed = true;
fFailed = true;
fFailed = true;
fFailed = true;
int rc;
rc = vdiError(pImage, VERR_VD_VDI_COMMENT_TOO_LONG, RT_SRC_POS, N_("VDI: comment is too long for '%s'"), pImage->pszFilename);
goto out;
#ifdef VBOX_WITH_NEW_IO_CODE
pImage->paBlocks = (PVDIIMAGEBLOCKPOINTER)RTMemAlloc(sizeof(VDIIMAGEBLOCKPOINTER) * getImageBlocks(&pImage->Header));
goto out;
goto out;
rc = vdiError(pImage, VERR_DISK_FULL, RT_SRC_POS, N_("VDI: disk would overflow creating image '%s'"), pImage->pszFilename);
goto out;
rc = vdiError(pImage, rc, RT_SRC_POS, N_("VDI: setting image size failed for '%s'"), pImage->pszFilename);
goto out;
rc = vdiError(pImage, rc, RT_SRC_POS, N_("VDI: writing pre-header failed for '%s'"), pImage->pszFilename);
goto out;
rc = vdiFileWriteSync(pImage, sizeof(pImage->PreHeader), &pImage->Header.u.v1plus, sizeof(pImage->Header.u.v1plus), NULL);
rc = vdiError(pImage, rc, RT_SRC_POS, N_("VDI: writing header failed for '%s'"), pImage->pszFilename);
goto out;
NULL);
rc = vdiError(pImage, rc, RT_SRC_POS, N_("VDI: writing block pointers failed for '%s'"), pImage->pszFilename);
goto out;
if (!pvBuf)
goto out;
uOff = 0;
rc = vdiError(pImage, rc, RT_SRC_POS, N_("VDI: writing block failed for '%s'"), pImage->pszFilename);
goto out;
if (pfnProgress)
goto out;
out:
return rc;
int rc;
return VERR_NOT_SUPPORTED;
#ifdef VBOX_WITH_NEW_IO_CODE
goto out;
NULL);
rc = vdiError(pImage, rc, RT_SRC_POS, N_("VDI: error reading pre-header in '%s'"), pImage->pszFilename);
goto out;
goto out;
NULL);
rc = vdiError(pImage, rc, RT_SRC_POS, N_("VDI: error reading v0 header in '%s'"), pImage->pszFilename);
goto out;
NULL);
rc = vdiError(pImage, rc, RT_SRC_POS, N_("VDI: error reading v1 header in '%s'"), pImage->pszFilename);
goto out;
rc = vdiFileReadSync(pImage, sizeof(pImage->PreHeader), &pImage->Header.u.v1plus, sizeof(pImage->Header.u.v1plus), NULL);
rc = vdiError(pImage, rc, RT_SRC_POS, N_("VDI: error reading v1.1+ header in '%s'"), pImage->pszFilename);
goto out;
rc = vdiError(pImage, VERR_VD_VDI_UNSUPPORTED_VERSION, RT_SRC_POS, N_("VDI: unsupported major version %u in '%s'"), GET_MAJOR_HEADER_VERSION(&pImage->Header), pImage->pszFilename);
goto out;
rc = vdiError(pImage, VERR_VD_VDI_INVALID_HEADER, RT_SRC_POS, N_("VDI: invalid header in '%s'"), pImage->pszFilename);
goto out;
pImage->paBlocks = (PVDIIMAGEBLOCKPOINTER)RTMemAlloc(sizeof(VDIIMAGEBLOCKPOINTER) * getImageBlocks(&pImage->Header));
goto out;
NULL);
out:
return rc;
int rc;
rc = vdiFileWriteSync(pImage, sizeof(VDIPREHEADER), &pImage->Header.u.v0, sizeof(pImage->Header.u.v0), NULL);
rc = vdiFileWriteSync(pImage, sizeof(VDIPREHEADER), &pImage->Header.u.v1, sizeof(pImage->Header.u.v1), NULL);
rc = vdiFileWriteSync(pImage, sizeof(VDIPREHEADER), &pImage->Header.u.v1plus, sizeof(pImage->Header.u.v1plus), NULL);
return rc;
sizeof(VDIIMAGEBLOCKPOINTER),
NULL);
return rc;
|| !*pszFilename)
goto out;
if (!pImage)
goto out;
#ifndef VBOX_WITH_NEW_IO_CODE
out:
return rc;
void **ppBackendData)
LogFlowFunc(("pszFilename=\"%s\" uOpenFlags=%#x pVDIfsDisk=%#p pVDIfsImage=%#p ppBackendData=%#p\n", pszFilename, uOpenFlags, pVDIfsDisk, pVDIfsImage, ppBackendData));
int rc;
goto out;
|| !*pszFilename)
goto out;
if (!pImage)
goto out;
#ifndef VBOX_WITH_NEW_IO_CODE
out:
return rc;
void **ppBackendData)
LogFlowFunc(("pszFilename=\"%s\" cbSize=%llu uImageFlags=%#x pszComment=\"%s\" pPCHSGeometry=%#p pLCHSGeometry=%#p Uuid=%RTuuid uOpenFlags=%#x uPercentStart=%u uPercentSpan=%u pVDIfsDisk=%#p pVDIfsImage=%#p pVDIfsOperation=%#p ppBackendData=%#p", pszFilename, cbSize, uImageFlags, pszComment, pPCHSGeometry, pLCHSGeometry, pUuid, uOpenFlags, uPercentStart, uPercentSpan, pVDIfsDisk, pVDIfsImage, pVDIfsOperation, ppBackendData));
int rc;
if (pIfProgress)
if (pCbProgress)
goto out;
if ( !cbSize
goto out;
|| !*pszFilename
goto out;
if (!pImage)
goto out;
#ifndef VBOX_WITH_NEW_IO_CODE
goto out;
out:
return rc;
if ( !pImage
|| !pszFilename
|| !*pszFilename)
goto out;
goto out;
goto out;
out:
return rc;
if (pImage)
return rc;
LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToRead=%zu pcbActuallyRead=%#p\n", pBackendData, uOffset, pvBuf, cbToRead, pcbActuallyRead));
unsigned uBlock;
unsigned offRead;
int rc;
|| !cbToRead)
goto out;
if (pcbActuallyRead)
out:
return rc;
LogFlowFunc(("pBackendData=%#p uOffset=%llu pvBuf=%#p cbToWrite=%zu pcbWriteProcess=%#p pcbPreRead=%#p pcbPostRead=%#p\n", pBackendData, uOffset, pvBuf, cbToWrite, pcbWriteProcess, pcbPreRead, pcbPostRead));
unsigned uBlock;
unsigned offWrite;
goto out;
goto out;
goto out;
goto out;
*pcbPreRead = 0;
*pcbPostRead = 0;
if (pcbWriteProcess)
out:
return rc;
return rc;
unsigned uVersion;
if (pImage)
uVersion = 0;
return uVersion;
if (pImage)
cbSize = 0;
return cbSize;
if (pImage)
return cb;
int rc;
if (pImage)
LogFlowFunc(("returns %Rrc (PCHS=%u/%u/%u)\n", rc, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
return rc;
LogFlowFunc(("pBackendData=%#p pPCHSGeometry=%#p PCHS=%u/%u/%u\n", pBackendData, pPCHSGeometry, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
int rc;
if (pImage)
goto out;
out:
return rc;
int rc;
if (pImage)
if (!pGeometry)
LogFlowFunc(("returns %Rrc (LCHS=%u/%u/%u)\n", rc, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
return rc;
LogFlowFunc(("pBackendData=%#p pLCHSGeometry=%#p LCHS=%u/%u/%u\n", pBackendData, pLCHSGeometry, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
int rc;
if (pImage)
goto out;
if (pGeometry)
out:
return rc;
unsigned uImageFlags;
if (pImage)
uImageFlags = 0;
return uImageFlags;
unsigned uOpenFlags;
if (pImage)
uOpenFlags = 0;
return uOpenFlags;
int rc;
const char *pszFilename;
goto out;
out:
return rc;
LogFlowFunc(("pBackendData=%#p pszComment=%#p cbComment=%zu\n", pBackendData, pszComment, cbComment));
if (pImage)
return rc;
int rc;
goto out;
if (pImage)
goto out;
out:
return rc;
int rc;
if (pImage)
return rc;
if (pImage)
return rc;
int rc;
if (pImage)
return rc;
if (pImage)
return rc;
int rc;
if (pImage)
return rc;
if (pImage)
return rc;
int rc;
if (pImage)
return rc;
if (pImage)
return rc;
#ifndef VBOX_WITH_NEW_IO_CODE
pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Dumping VDI image \"%s\" mode=%s uOpenFlags=%X File=%08X\n",
pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Dumping VDI image \"%s\" mode=%s uOpenFlags=%X File=%#p\n",
pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Header: Version=%08X Type=%X Flags=%X Size=%llu\n",
pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Header: cbBlock=%u cbBlockExtra=%u cBlocks=%u cBlocksAllocated=%u\n",
pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Header: offBlocks=%u offData=%u\n",
if (pg)
pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Header: Geometry: C/H/S=%u/%u/%u cbSector=%u\n",
pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Header: uuidCreation={%RTuuid}\n", getImageCreationUUID(&pImage->Header));
pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Header: uuidModification={%RTuuid}\n", getImageModificationUUID(&pImage->Header));
pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Header: uuidParent={%RTuuid}\n", getImageParentUUID(&pImage->Header));
pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Header: uuidParentModification={%RTuuid}\n", getImageParentModificationUUID(&pImage->Header));
pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Image: fFlags=%08X offStartBlocks=%u offStartData=%u\n",
pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "Image: uBlockMask=%08X cbTotalBlockData=%u uShiftOffset2Index=%u offStartBlockData=%u\n",
cBadBlocks++;
pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "!! WARNING: %u blocks actually allocated (cBlocksAllocated=%u) !!\n",
if (cBadBlocks)
pImage->pInterfaceErrorCallbacks->pfnMessage(pImage->pInterfaceError->pvUser, "!! WARNING: %u bad blocks found !!\n",
return rc;
return rc;
return rc;
return rc;
return rc;
return rc;
return rc;
return rc;
if (pIfParentState)
if (pCbParentState)
if (pIfProgress)
if (pCbProgress)
unsigned cBlocks;
unsigned cBlocksToMove = 0;
if (pfnParentRead)
unsigned cBlocksAllocated = (unsigned)((cbFile - pImage->offStartData - pImage->offStartBlockData) >> pImage->uShiftOffset2Index);
if (cBlocksAllocated == 0)
for (unsigned i = 0; i < cBlocksAllocated; i++)
for (unsigned i = 0; i < cBlocks; i++)
for (unsigned i = 0; i < cBlocks; i++)
else if (pfnParentRead)
unsigned cBlocksMoved = 0;
for (unsigned i = 0; i < cBlocksAllocated; i++)
if (uBlockUsedPos == i)
cBlocksMoved++;
if (paBlocks2)
if (pvTmp)
if (pvBuf)
return rc;
sizeof(VBOXHDDBACKEND),
NULL,