DrvVD.cpp revision 8083a259c13e6e26e56ca2582edbad4a8cfac25a
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * VBox storage devices:
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Media implementation for VBox disk container
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync * Copyright (C) 2006-2008 innotek GmbH
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * available from http://www.virtualbox.org. This file is free software;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * you can redistribute it and/or modify it under the terms of the GNU
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * General Public License (GPL) as published by the Free Software
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/*******************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync* Header files *
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync*******************************************************************************/
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/*******************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync* Defined types, constants and macros *
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync*******************************************************************************/
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** Converts a pointer to VDIDISK::IMedia to a PVBOXDISK. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync ( (PVBOXDISK)((uintptr_t)pInterface - RT_OFFSETOF(VBOXDISK, IMedia)) )
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** Converts a pointer to PDMDRVINS::IBase to a PPDMDRVINS. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync ( (PPDMDRVINS)((uintptr_t)pInterface - RT_OFFSETOF(PDMDRVINS, IBase)) )
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** Converts a pointer to PDMDRVINS::IBase to a PVBOXDISK. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync ( PDMINS2DATA(PDMIBASE_2_DRVINS(pInterface), PVBOXDISK) )
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * VBox disk container media main structure, private part.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsynctypedef struct VBOXDISK
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /** The VBox disk container. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /** The media interface. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /** Pointer to the driver instance. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /** Name of the image format backend. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /** Flag whether suspend has changed image open mode to read only. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/*******************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync* Error reporting callback *
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync*******************************************************************************/
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsyncstatic void drvvdErrorCallback(void *pvUser, int rc, RT_SRC_POS_DECL,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pDrvIns->pDrvHlp->pfnVMSetErrorV(pDrvIns, rc, RT_SRC_POS_ARGS, pszFormat, va);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/*******************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync* Media interface methods *
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync*******************************************************************************/
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** @copydoc PDMIMEDIA::pfnRead */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsyncstatic DECLCALLBACK(int) drvvdRead(PPDMIMEDIA pInterface,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync LogFlow(("%s: off=%#llx pvBuf=%p cbRead=%d\n", __FUNCTION__,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PVBOXDISK pData = PDMIMEDIA_2_VBOXDISK(pInterface);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync Log2(("%s: off=%#llx pvBuf=%p cbRead=%d %.*Vhxd\n", __FUNCTION__,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** @copydoc PDMIMEDIA::pfnWrite */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsyncstatic DECLCALLBACK(int) drvvdWrite(PPDMIMEDIA pInterface,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync LogFlow(("%s: off=%#llx pvBuf=%p cbWrite=%d\n", __FUNCTION__,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PVBOXDISK pData = PDMIMEDIA_2_VBOXDISK(pInterface);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync Log2(("%s: off=%#llx pvBuf=%p cbWrite=%d %.*Vhxd\n", __FUNCTION__,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync int rc = VDWrite(pData->pDisk, off, pvBuf, cbWrite);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** @copydoc PDMIMEDIA::pfnFlush */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsyncstatic DECLCALLBACK(int) drvvdFlush(PPDMIMEDIA pInterface)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PVBOXDISK pData = PDMIMEDIA_2_VBOXDISK(pInterface);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** @copydoc PDMIMEDIA::pfnGetSize */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsyncstatic DECLCALLBACK(uint64_t) drvvdGetSize(PPDMIMEDIA pInterface)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PVBOXDISK pData = PDMIMEDIA_2_VBOXDISK(pInterface);
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync uint64_t cb = VDGetSize(pData->pDisk, VD_LAST_IMAGE);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync LogFlow(("%s: returns %#llx (%llu)\n", __FUNCTION__, cb, cb));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** @copydoc PDMIMEDIA::pfnIsReadOnly */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsyncstatic DECLCALLBACK(bool) drvvdIsReadOnly(PPDMIMEDIA pInterface)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PVBOXDISK pData = PDMIMEDIA_2_VBOXDISK(pInterface);
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync/** @copydoc PDMIMEDIA::pfnBiosGetPCHSGeometry */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsyncstatic DECLCALLBACK(int) drvvdBiosGetPCHSGeometry(PPDMIMEDIA pInterface,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PVBOXDISK pData = PDMIMEDIA_2_VBOXDISK(pInterface);
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync int rc = VDGetPCHSGeometry(pData->pDisk, VD_LAST_IMAGE, pPCHSGeometry);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync Log(("%s: geometry not available.\n", __FUNCTION__));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync LogFlow(("%s: returns %Vrc (CHS=%d/%d/%d)\n", __FUNCTION__,
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync rc, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync/** @copydoc PDMIMEDIA::pfnBiosSetPCHSGeometry */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsyncstatic DECLCALLBACK(int) drvvdBiosSetPCHSGeometry(PPDMIMEDIA pInterface,
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PVBOXDISK pData = PDMIMEDIA_2_VBOXDISK(pInterface);
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync int rc = VDSetPCHSGeometry(pData->pDisk, VD_LAST_IMAGE, pPCHSGeometry);
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync/** @copydoc PDMIMEDIA::pfnBiosGetLCHSGeometry */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsyncstatic DECLCALLBACK(int) drvvdBiosGetLCHSGeometry(PPDMIMEDIA pInterface,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PVBOXDISK pData = PDMIMEDIA_2_VBOXDISK(pInterface);
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync int rc = VDGetLCHSGeometry(pData->pDisk, VD_LAST_IMAGE, pLCHSGeometry);
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync Log(("%s: geometry not available.\n", __FUNCTION__));
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync LogFlow(("%s: returns %Vrc (CHS=%d/%d/%d)\n", __FUNCTION__,
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync rc, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync/** @copydoc PDMIMEDIA::pfnBiosSetLCHSGeometry */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsyncstatic DECLCALLBACK(int) drvvdBiosSetLCHSGeometry(PPDMIMEDIA pInterface,
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PVBOXDISK pData = PDMIMEDIA_2_VBOXDISK(pInterface);
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync int rc = VDSetLCHSGeometry(pData->pDisk, VD_LAST_IMAGE, pLCHSGeometry);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** @copydoc PDMIMEDIA::pfnGetUuid */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsyncstatic DECLCALLBACK(int) drvvdGetUuid(PPDMIMEDIA pInterface, PRTUUID pUuid)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PVBOXDISK pData = PDMIMEDIA_2_VBOXDISK(pInterface);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync LogFlow(("%s: returns %Vrc ({%Vuuid})\n", __FUNCTION__, rc, pUuid));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/*******************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync* Base interface methods *
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync*******************************************************************************/
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** @copydoc PDMIBASE::pfnQueryInterface */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsyncstatic DECLCALLBACK(void *) drvvdQueryInterface(PPDMIBASE pInterface,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PPDMDRVINS pDrvIns = PDMIBASE_2_DRVINS(pInterface);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/*******************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync* Driver methods *
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync*******************************************************************************/
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Construct a VBox disk media driver instance.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * @returns VBox status.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * @param pDrvIns The driver instance data.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * If the registration structure is needed, pDrvIns->pDrvReg points to it.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * @param pCfgHandle Configuration node handle for the driver. Use this to obtain the configuration
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * of the driver instance. It's also found in pDrvIns->pCfgHandle as it's expected
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * to be used frequently in this function.
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsyncstatic DECLCALLBACK(int) drvvdConstruct(PPDMDRVINS pDrvIns,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync char *pszName; /**< The path of the disk image file. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync bool fReadOnly; /**< True if the media is readonly. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync bool fHonorZeroWrites; /**< True if zero blocks should be written. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Init the static parts.
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync pDrvIns->IBase.pfnQueryInterface = drvvdQueryInterface;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* IMedia */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync pData->IMedia.pfnBiosGetPCHSGeometry = drvvdBiosGetPCHSGeometry;
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync pData->IMedia.pfnBiosSetPCHSGeometry = drvvdBiosSetPCHSGeometry;
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync pData->IMedia.pfnBiosGetLCHSGeometry = drvvdBiosGetLCHSGeometry;
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync pData->IMedia.pfnBiosSetLCHSGeometry = drvvdBiosSetLCHSGeometry;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Validate configuration and find all parent images.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * It's sort of up side down from the image dependency tree.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync unsigned iLevel = 0;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* Toplevel configuration contains the format backend name and
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * full image open information. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync "Path\0ReadOnly\0HonorZeroWrites\0");
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* All other image configurations only contain image name. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync rc = PDMDrvHlpVMSetError(pDrvIns, VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync RT_SRC_POS, N_("DrvVD: Configuration error: keys incorrect at level %d"), iLevel);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PCFGMNODE pParent = CFGMR3GetChild(pCurNode, "Parent");
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Open the images.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync rc = CFGMR3QueryString(pCfgHandle, "Format", &pData->szFormat[0],
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* Default disk image format is VMDK. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync strncpy(&pData->szFormat[0], "VMDK", sizeof(pData->szFormat));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pData->szFormat[sizeof(pData->szFormat) - 1] = '\0';
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync rc = VDCreate(pData->szFormat, drvvdErrorCallback, pDrvIns, &pData->pDisk);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* Error message is already set correctly. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync N_("DrvVD: Configuration error: Querying \"Format\" as string failed"));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Read the image configuration.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync rc = CFGMR3QueryStringAlloc(pCurNode, "Path", &pszName);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync N_("DrvVD: Configuration error: Querying \"Path\" as string failed"));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync rc = CFGMR3QueryBool(pCurNode, "ReadOnly", &fReadOnly);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync N_("DrvVD: Configuration error: Querying \"ReadOnly\" as boolean failed"));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync rc = CFGMR3QueryBool(pCfgHandle, "HonorZeroWrites", &fHonorZeroWrites);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync N_("DrvVD: Configuration error: Querying \"HonorZeroWrites\" as boolean failed"));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Open the image.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync Log(("%s: %d - Opened '%s' in %s mode\n", __FUNCTION__,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync VDIsReadOnly(pData->pDisk) ? "read-only" : "read-write"));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync AssertMsgFailed(("Failed to open image '%s' rc=%Vrc\n", pszName, rc));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Destruct a driver instance.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Most VM resources are freed by the VM. This callback is provided so that any non-VM
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * resources can be freed correctly.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * @param pDrvIns The driver instance data.
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsyncstatic DECLCALLBACK(void) drvvdDestruct(PPDMDRVINS pDrvIns)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * When the VM has been suspended we'll change the image mode to read-only
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * so that main and others can read the VDIs. This is important when
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * saving state and so forth.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * @param pDrvIns The driver instance data.
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsyncstatic DECLCALLBACK(void) drvvdSuspend(PPDMDRVINS pDrvIns)
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync int rc = VDGetOpenFlags(pData->pDisk, VD_LAST_IMAGE, &uOpenFlags);
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync rc = VDSetOpenFlags(pData->pDisk, VD_LAST_IMAGE, uOpenFlags);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Before the VM resumes we'll have to undo the read-only mode change
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync * done in drvvdSuspend.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * @param pDrvIns The driver instance data.
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsyncstatic DECLCALLBACK(void) drvvdResume(PPDMDRVINS pDrvIns)
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync int rc = VDGetOpenFlags(pData->pDisk, VD_LAST_IMAGE, &uOpenFlags);
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync rc = VDSetOpenFlags(pData->pDisk, VD_LAST_IMAGE, uOpenFlags);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * VBox disk container media driver registration record.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* u32Version */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* szDriverName */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* pszDescription */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync "Generic VBox disk media driver.",
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* fFlags */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* fClass. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* cMaxInstances */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* cbInstance */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* pfnConstruct */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* pfnDestruct */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* pfnIOCtl */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* pfnPowerOn */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* pfnReset */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* pfnSuspend */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* pfnResume */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* pfnDetach */