VirtualBox

Changeset 5101 in vbox


Ignore:
Timestamp:
Sep 28, 2007 4:13:06 PM (17 years ago)
Author:
vboxsync
Message:

Introduce a new harddisk object which supports virtual harddisk through plugins

Location:
trunk/src/VBox
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Storage/VBoxHDD-new.cpp

    r4798 r5101  
    3131#include <iprt/asm.h>
    3232#include <iprt/ldr.h>
     33#include <iprt/dir.h>
     34#include <iprt/path.h>
    3335
    3436#include "VBoxHDD-newInternal.h"
     
    501503         * @todo: find out what to do if filenames are case sensitive.
    502504         */
    503         cbPluginName = RTStrAPrintf(&pszPluginName, "VBoxHDD%s", pszBackend);
     505        cbPluginName = RTStrAPrintf(&pszPluginName, "%s%s", VBOX_HDDFORMAT_PLUGIN_PREFIX, pszBackend);
    504506        if (cbPluginName == -1)
    505507        {
     
    577579
    578580/**
     581 * Try to get the backend name which can use this image.
     582 *
     583 * @returns VBox status code.
     584 * @param   pszFilename     Name of the image file for which the backend is queried.
     585 * @param   ppszFormat      Where to store the name of the plugin.
     586 */
     587
     588VBOXDDU_DECL(int) VDGetFormat(const char *pszFilename, char **ppszFormat)
     589{
     590    char pszProgramPath[1024]; /* Far too much I think but to be on the safe side. */
     591    char *pszPluginFilter;
     592    PRTDIR pPluginDir = NULL;
     593    PRTDIRENTRY pPluginDirEntry = NULL;
     594    unsigned cbPluginDirEntry;
     595    int rc = VERR_NOT_SUPPORTED;
     596    bool fPluginFound = false;
     597
     598    if (!ppszFormat)
     599        return VERR_INVALID_PARAMETER;
     600       
     601    memset(pszProgramPath, 0, 1024);
     602    rc = RTPathProgram(pszProgramPath, 1024);
     603    if (VBOX_FAILURE(rc))
     604    {
     605        return rc;
     606    }
     607
     608    /* To get all entries with VBoxHDD as prefix. */
     609    rc = RTStrAPrintf(&pszPluginFilter, "%s/%s*", pszProgramPath, VBOX_HDDFORMAT_PLUGIN_PREFIX);
     610    if (VBOX_FAILURE(rc))
     611    {
     612        RTStrFree(pszProgramPath);
     613        rc = VERR_NO_MEMORY;
     614        return rc;
     615    }
     616
     617    /* The plugins are in the same directory as the program. */
     618    rc = RTDirOpenFiltered(&pPluginDir, pszPluginFilter, RTDIRFILTER_WINNT);
     619    if (VBOX_FAILURE(rc))
     620        goto out;
     621
     622    pPluginDirEntry = (PRTDIRENTRY)RTMemAllocZ(sizeof(RTDIRENTRY));
     623    if (!pPluginDir)
     624    {
     625        rc = VERR_NO_MEMORY;
     626        goto out;
     627    }
     628
     629    while ((rc = RTDirRead(pPluginDir, pPluginDirEntry, &cbPluginDirEntry)) != VERR_NO_MORE_FILES)
     630    {
     631        RTLDRMOD hPlugin = NIL_RTLDRMOD;
     632        PFNVBOXHDDFORMATLOAD pfnHDDFormatLoad = NULL;
     633        PVBOXHDDBACKEND pBackend = NULL;
     634
     635        if (rc == VERR_BUFFER_OVERFLOW)
     636        {
     637            /* allocate new buffer. */
     638            RTMemFree(pPluginDirEntry);
     639            pPluginDirEntry = (PRTDIRENTRY)RTMemAllocZ(cbPluginDirEntry);
     640            /* Retry. */
     641            rc = RTDirRead(pPluginDir, pPluginDirEntry, &cbPluginDirEntry);
     642            if (VBOX_FAILURE(rc))
     643                break;
     644        }
     645        else if (VBOX_FAILURE(rc))
     646                break;
     647
     648        /* We got the new entry. */
     649        if (pPluginDirEntry->enmType != RTDIRENTRYTYPE_FILE)
     650            continue;
     651
     652        rc = RTLdrLoad(pPluginDirEntry->szName, &hPlugin);
     653        if (VBOX_SUCCESS(rc))
     654        {
     655            rc = RTLdrGetSymbol(hPlugin, VBOX_HDDFORMAT_LOAD_NAME, (void**)&pfnHDDFormatLoad);
     656            if (VBOX_FAILURE(rc) || !pfnHDDFormatLoad)
     657            {
     658                Log(("%s: Error resolving the entry point %s, rc = %d, pfnHDDFormat = %p\n", VBOX_HDDFORMAT_LOAD_NAME, rc, pfnHDDFormatLoad));
     659                if (VBOX_SUCCESS(rc))
     660                    rc = VERR_SYMBOL_NOT_FOUND;
     661            }
     662            else
     663            {
     664                /* Get the function table. */
     665                pBackend = (PVBOXHDDBACKEND)RTMemAllocZ(sizeof(VBOXHDDBACKEND));
     666                if (!pBackend)
     667                {
     668                    rc = VERR_NO_MEMORY;
     669                }
     670                else
     671                {
     672                    pBackend->cbSize = sizeof(VBOXHDDBACKEND);
     673                    rc = pfnHDDFormatLoad(pBackend);
     674                    if (VBOX_FAILURE(rc))
     675                    {
     676                        RTMemFree(pBackend);
     677                        pBackend = NULL;
     678                    }
     679
     680                    /* Check if the plugin can handle this file. */
     681                    rc = pBackend->pfnCheckIfValid(pszFilename);
     682                    if (VBOX_FAILURE(rc))
     683                    {
     684                        RTMemFree(pBackend);
     685                        RTLdrClose(hPlugin);
     686                    }
     687                    else
     688                    {
     689                        RTMemFree(pBackend);
     690                        RTLdrClose(hPlugin);
     691                        fPluginFound = true;
     692
     693                        /* Report the format name. */
     694                        char *pszName = pPluginDirEntry->szName + VBOX_HDDFORMAT_PLUGIN_PREFIX_LENGTH; /* Point to the rest after the prefix. */
     695                        char *pszFormat = NULL;
     696                        unsigned cbFormat = 0;
     697                         
     698                        while((*pszName != '.') && (*pszName != '\0'))
     699                        {
     700                            cbFormat++;
     701                            pszName++;
     702                        }
     703
     704                        pszName = pPluginDirEntry->szName + VBOX_HDDFORMAT_PLUGIN_PREFIX_LENGTH;
     705
     706                        /* Copy the name into the new string. */   
     707                        pszFormat = (char *)RTMemAllocZ(cbFormat+1);
     708
     709                        if (!pszFormat)
     710                        {
     711                            rc = VERR_NO_MEMORY;
     712                            break;
     713                        }
     714
     715                        memcpy(pszFormat, pszName, cbFormat);
     716                       
     717                        *ppszFormat = pszFormat;
     718
     719                        break;
     720                    }
     721                }
     722            }
     723        }
     724    }
     725
     726out:
     727    if (pPluginDirEntry)
     728        RTMemFree(pPluginDirEntry);
     729    if (pPluginDir)
     730        RTDirClose(pPluginDir);
     731
     732    RTStrFree(pszPluginFilter);
     733    RTStrFree(pszProgramPath);
     734
     735    if ((fPluginFound == true) && (*ppszFormat != NULL))
     736        rc = VINF_SUCCESS;
     737
     738    return rc;
     739}
     740
     741/**
    579742 * Destroys the VBox HDD container.
    580743 * If container has opened image files they will be closed.
     
    584747VBOXDDU_DECL(void) VDDestroy(PVBOXHDD pDisk)
    585748{
    586     LogFlow(("%s: pDisk=%#p\n", pDisk));
     749    LogFlow(("%s: pDisk=%#p\n", __FUNCTION__, pDisk));
    587750    /* sanity check */
    588751    Assert(pDisk);
  • trunk/src/VBox/Devices/Storage/VmdkHDDCore.cpp

    r4522 r5101  
    34823482    /* cbSize */
    34833483    sizeof(VBOXHDDBACKEND),
     3484    /* pfnCheckIfValid */
     3485    NULL,
    34843486    /* pfnOpen */
    34853487    vmdkOpen,
  • trunk/src/VBox/Main/ConsoleImpl2.cpp

    r5060 r5101  
    727727            STR_CONV();
    728728            rc = CFGMR3InsertString(pCfg,   "Path",             psz);                   RC_CHECK();
     729            STR_FREE();
     730        }
     731        else if (hddType == HardDiskStorageType_CustomHardDisk)
     732        {
     733            ComPtr<ICustomHardDisk> customHardDisk = hardDisk;
     734            AssertBreak (!customHardDisk.isNull(), hrc = E_FAIL);
     735
     736            rc = CFGMR3InsertNode(pLunL0,   "AttachedDriver", &pLunL1);                 RC_CHECK();
     737            rc = CFGMR3InsertString(pLunL1, "Driver",         "VD");                    RC_CHECK();
     738            rc = CFGMR3InsertNode(pLunL1,   "Config", &pCfg);                           RC_CHECK();
     739            hrc = customHardDisk->COMGETTER(Location)(&str);                            H();
     740            STR_CONV();
     741            rc = CFGMR3InsertString(pCfg,   "Path",             psz);                   RC_CHECK();
     742            STR_FREE();
     743            hrc = customHardDisk->COMGETTER(Format)(&str);                              H();
     744            STR_CONV();
     745            rc = CFGMR3InsertString(pCfg,   "Format",           psz);                   RC_CHECK();
    729746            STR_FREE();
    730747        }
  • trunk/src/VBox/Main/HardDiskImpl.cpp

    r5027 r5101  
    10881088    HRESULT firstRC = S_OK;
    10891089    com::ErrorInfoKeeper firstErr (true /* aIsNull */);
     1090
     1091    if (haveFirst == false)
     1092    {
     1093        /* Try if a plugin supports this format. */
     1094        ComObjPtr <HCustomHardDisk> obj;
     1095        obj.createObject();
     1096        rc = obj->init (aVirtualBox, NULL, aLocation,
     1097                        FALSE /* aRegistered */);
     1098        if (SUCCEEDED (rc))
     1099        {
     1100            hardDisk = obj;
     1101            return rc;
     1102        }
     1103    }
    10901104
    10911105    for (size_t i = 0; i < ELEMENTS (storageTypes); ++ i)
     
    42124226}
    42134227
     4228////////////////////////////////////////////////////////////////////////////////
     4229// HCustomHardDisk class
     4230////////////////////////////////////////////////////////////////////////////////
     4231
     4232// constructor / destructor
     4233////////////////////////////////////////////////////////////////////////////////
     4234
     4235HRESULT HCustomHardDisk::FinalConstruct()
     4236{
     4237    HRESULT rc = HardDisk::FinalConstruct();
     4238    if (FAILED (rc))
     4239        return rc;
     4240
     4241    mState = NotCreated;
     4242
     4243    mStateCheckSem = NIL_RTSEMEVENTMULTI;
     4244    mStateCheckWaiters = 0;
     4245
     4246    mSize = 0;
     4247    mActualSize = 0;
     4248    mContainer = NULL;
     4249
     4250    ComAssertRCRet (rc, E_FAIL);
     4251
     4252    return S_OK;
     4253}
     4254
     4255void HCustomHardDisk::FinalRelease()
     4256{
     4257    if (mContainer != NULL)
     4258        VDDestroy (mContainer);
     4259
     4260    HardDisk::FinalRelease();
     4261}
     4262
     4263// public initializer/uninitializer for internal purposes only
     4264////////////////////////////////////////////////////////////////////////////////
     4265
     4266// public methods for internal purposes only
     4267/////////////////////////////////////////////////////////////////////////////
     4268
     4269/**
     4270 *  Initializes the custom hard disk object by reading its properties from
     4271 *  the given configuration node. The created hard disk will be marked as
     4272 *  registered on success.
     4273 *
     4274 *  @param aHDNode      <HardDisk> node
     4275 *  @param aCustomNode  <VirtualDiskImage> node
     4276 */
     4277HRESULT HCustomHardDisk::init (VirtualBox *aVirtualBox, HardDisk *aParent,
     4278                          CFGNODE aHDNode, CFGNODE aCustomNode)
     4279{
     4280    LogFlowThisFunc (("aHDNode=%p, aCustomNode=%p\n", aHDNode, aCustomNode));
     4281
     4282    AssertReturn (aHDNode && aCustomNode, E_FAIL);
     4283
     4284    AutoLock alock (this);
     4285    ComAssertRet (!isReady(), E_UNEXPECTED);
     4286
     4287    mStorageType = HardDiskStorageType_CustomHardDisk;
     4288
     4289    HRESULT rc = S_OK;
     4290    int     vrc = VINF_SUCCESS;
     4291    do
     4292    {
     4293        rc = protectedInit (aVirtualBox, aParent);
     4294        CheckComRCBreakRC (rc);
     4295
     4296        /* set ready to let protectedUninit() be called on failure */
     4297        setReady (true);
     4298
     4299        /* location (required) */
     4300        Bstr location;
     4301        CFGLDRQueryBSTR (aCustomNode, "location", location.asOutParam());
     4302
     4303        /* format (required) */
     4304        Bstr format;
     4305        char *pszFormat;
     4306        CFGLDRQueryBSTR (aCustomNode, "format", format.asOutParam());
     4307        vrc = RTStrUcs2ToUtf8(&pszFormat, format);
     4308
     4309        /* initialize the container */
     4310        vrc = VDCreate (pszFormat, VDError, this, &mContainer);
     4311        ComAssertRCRet (vrc, E_FAIL);
     4312
     4313        RTStrFree(pszFormat);
     4314
     4315        rc = setLocation (location);
     4316        CheckComRCBreakRC (rc);
     4317
     4318        mFormat = format;
     4319
     4320        /* load basic settings and children */
     4321        rc = loadSettings (aHDNode);
     4322        CheckComRCBreakRC (rc);
     4323
     4324        mState = Created;
     4325        mRegistered = TRUE;
     4326
     4327        /* Don't call queryInformation() for registered hard disks to
     4328         * prevent the calling thread (i.e. the VirtualBox server startup
     4329         * thread) from an unexpected freeze. The vital mId property (UUID)
     4330         * is read from the registry file in loadSettings(). To get the rest,
     4331         * the user will have to call COMGETTER(Accessible) manually. */
     4332    }
     4333    while (0);
     4334
     4335    if (FAILED (rc))
     4336        uninit();
     4337
     4338    return rc;
     4339}
     4340
     4341/**
     4342 *  Initializes the custom hard disk object using the given image file name.
     4343 *
     4344 *  @param aVirtualBox  VirtualBox parent.
     4345 *  @param aParent      Currently, must always be @c NULL.
     4346 *  @param aLocation    Location of the virtual disk, or @c NULL to create an
     4347 *                      image-less object.
     4348 *  @param aRegistered  Whether to mark this disk as registered or not
     4349 *                      (ignored when @a aFilePath is @c NULL, assuming @c FALSE)
     4350 */
     4351HRESULT HCustomHardDisk::init (VirtualBox *aVirtualBox, HardDisk *aParent,
     4352                               const BSTR aLocation, BOOL aRegistered /* = FALSE */)
     4353{
     4354    LogFlowThisFunc (("aLocation='%ls', aRegistered=%d\n", aLocation, aRegistered));
     4355
     4356    AssertReturn (aParent == NULL, E_FAIL);
     4357
     4358    AutoLock alock (this);
     4359    ComAssertRet (!isReady(), E_UNEXPECTED);
     4360
     4361    mStorageType = HardDiskStorageType_CustomHardDisk;
     4362
     4363    HRESULT rc = S_OK;
     4364
     4365    do
     4366    {
     4367        rc = protectedInit (aVirtualBox, aParent);
     4368        CheckComRCBreakRC (rc);
     4369
     4370        /* set ready to let protectedUninit() be called on failure */
     4371        setReady (true);
     4372
     4373        rc = setLocation (aLocation);
     4374        CheckComRCBreakRC (rc);
     4375
     4376        /* currently, all custom hard disks are writethrough */
     4377        mType = HardDiskType_WritethroughHardDisk;
     4378
     4379        Assert (mId.isEmpty());
     4380
     4381        if (aLocation && *aLocation)
     4382        {
     4383            int vrc;
     4384            char *pszLocation = NULL;
     4385            char *pszFormat = NULL;
     4386
     4387            mRegistered = aRegistered;
     4388            mState = Created;
     4389
     4390            vrc = RTStrUcs2ToUtf8(&pszLocation, aLocation);
     4391            if (VBOX_FAILURE(vrc))
     4392            {
     4393                rc = E_FAIL;
     4394            }
     4395
     4396            vrc = VDGetFormat(pszLocation, &pszFormat);
     4397            if (VBOX_FAILURE(vrc))
     4398            {
     4399                if (vrc == VERR_NOT_SUPPORTED)
     4400                {
     4401                    /* @todo: show a understandable error string. */
     4402                }
     4403                rc = E_FAIL;
     4404            }
     4405
     4406            mFormat = Bstr(pszFormat);
     4407
     4408            /* Create the corresponding container. */
     4409            vrc = VDCreate (pszFormat, VDError, this, &mContainer);
     4410            ComAssertRCRet (vrc, E_FAIL);
     4411
     4412            /* Call queryInformation() anyway (even if it will block), because
     4413             * it is the only way to get the UUID of the existing VDI and
     4414             * initialize the vital mId property. */
     4415            Bstr errMsg;
     4416            rc = queryInformation (&errMsg);
     4417            if (SUCCEEDED (rc))
     4418            {
     4419                /* We are constructing a new HVirtualDiskImage object. If there
     4420                 * is a fatal accessibility error (we cannot read image UUID),
     4421                 * we have to fail. We do so even on non-fatal errors as well,
     4422                 * because it's not worth to keep going with the inaccessible
     4423                 * image from the very beginning (when nothing else depends on
     4424                 * it yet). */
     4425                if (!errMsg.isNull())
     4426                    rc = setErrorBstr (E_FAIL, errMsg);
     4427            }
     4428        }
     4429        else
     4430        {
     4431            mRegistered = FALSE;
     4432            mState = NotCreated;
     4433            mId.create();
     4434        }
     4435    }
     4436    while (0);
     4437
     4438    if (FAILED (rc))
     4439        uninit();
     4440
     4441    return rc;
     4442}
     4443
     4444/**
     4445 *  Uninitializes the instance and sets the ready flag to FALSE.
     4446 *  Called either from FinalRelease(), by the parent when it gets destroyed,
     4447 *  or by a third party when it decides this object is no more valid.
     4448 */
     4449void HCustomHardDisk::uninit()
     4450{
     4451    LogFlowThisFunc (("\n"));
     4452
     4453    AutoLock alock (this);
     4454    if (!isReady())
     4455        return;
     4456
     4457    HardDisk::protectedUninit (alock);
     4458}
     4459
     4460// IHardDisk properties
     4461////////////////////////////////////////////////////////////////////////////////
     4462
     4463STDMETHODIMP HCustomHardDisk::COMGETTER(Description) (BSTR *aDescription)
     4464{
     4465    if (!aDescription)
     4466        return E_POINTER;
     4467
     4468    AutoLock alock (this);
     4469    CHECK_READY();
     4470
     4471    mDescription.cloneTo (aDescription);
     4472    return S_OK;
     4473}
     4474
     4475STDMETHODIMP HCustomHardDisk::COMSETTER(Description) (INPTR BSTR aDescription)
     4476{
     4477    AutoLock alock (this);
     4478    CHECK_READY();
     4479
     4480    CHECK_BUSY_AND_READERS();
     4481
     4482    return E_NOTIMPL;
     4483}
     4484
     4485STDMETHODIMP HCustomHardDisk::COMGETTER(Size) (ULONG64 *aSize)
     4486{
     4487    if (!aSize)
     4488        return E_POINTER;
     4489
     4490    AutoLock alock (this);
     4491    CHECK_READY();
     4492
     4493    *aSize = mSize;
     4494    return S_OK;
     4495}
     4496
     4497STDMETHODIMP HCustomHardDisk::COMGETTER(ActualSize) (ULONG64 *aActualSize)
     4498{
     4499    if (!aActualSize)
     4500        return E_POINTER;
     4501
     4502    AutoLock alock (this);
     4503    CHECK_READY();
     4504
     4505    *aActualSize = mActualSize;
     4506    return S_OK;
     4507}
     4508
     4509// IVirtualDiskImage properties
     4510////////////////////////////////////////////////////////////////////////////////
     4511
     4512STDMETHODIMP HCustomHardDisk::COMGETTER(Location) (BSTR *aLocation)
     4513{
     4514    if (!aLocation)
     4515        return E_POINTER;
     4516
     4517    AutoLock alock (this);
     4518    CHECK_READY();
     4519
     4520    mLocation.cloneTo (aLocation);
     4521    return S_OK;
     4522}
     4523
     4524STDMETHODIMP HCustomHardDisk::COMSETTER(Location) (INPTR BSTR aLocation)
     4525{
     4526    AutoLock alock (this);
     4527    CHECK_READY();
     4528
     4529    if (mState != NotCreated)
     4530        return setError (E_ACCESSDENIED,
     4531            tr ("Cannot change the file path of the existing hard disk '%ls'"),
     4532            toString().raw());
     4533
     4534    CHECK_BUSY_AND_READERS();
     4535
     4536    /* append the default path if only a name is given */
     4537    Bstr path = aLocation;
     4538    if (aLocation && *aLocation)
     4539    {
     4540        Utf8Str fp = aLocation;
     4541        if (!RTPathHavePath (fp))
     4542        {
     4543            AutoReaderLock propsLock (mVirtualBox->systemProperties());
     4544            path = Utf8StrFmt ("%ls%c%s",
     4545                               mVirtualBox->systemProperties()->defaultVDIFolder().raw(),
     4546                               RTPATH_DELIMITER,
     4547                               fp.raw());
     4548        }
     4549    }
     4550
     4551    return setLocation (path);
     4552}
     4553
     4554STDMETHODIMP HCustomHardDisk::COMGETTER(Created) (BOOL *aCreated)
     4555{
     4556    if (!aCreated)
     4557        return E_POINTER;
     4558
     4559    AutoLock alock (this);
     4560    CHECK_READY();
     4561
     4562    *aCreated = mState >= Created;
     4563    return S_OK;
     4564}
     4565
     4566STDMETHODIMP HCustomHardDisk::COMGETTER(Format) (BSTR *aFormat)
     4567{
     4568    if (!aFormat)
     4569        return E_POINTER;
     4570
     4571    AutoLock alock (this);
     4572    CHECK_READY();
     4573
     4574    mFormat.cloneTo (aFormat);
     4575    return S_OK;
     4576}
     4577
     4578// ICustomHardDisk methods
     4579/////////////////////////////////////////////////////////////////////////////
     4580
     4581STDMETHODIMP HCustomHardDisk::CreateDynamicImage (ULONG64 aSize, IProgress **aProgress)
     4582{
     4583    if (!aProgress)
     4584        return E_POINTER;
     4585
     4586    AutoLock alock (this);
     4587    CHECK_READY();
     4588
     4589    return createImage (aSize, TRUE /* aDynamic */, aProgress);
     4590}
     4591
     4592STDMETHODIMP HCustomHardDisk::CreateFixedImage (ULONG64 aSize, IProgress **aProgress)
     4593{
     4594    if (!aProgress)
     4595        return E_POINTER;
     4596
     4597    AutoLock alock (this);
     4598    CHECK_READY();
     4599
     4600    return createImage (aSize, FALSE /* aDynamic */, aProgress);
     4601}
     4602
     4603STDMETHODIMP HCustomHardDisk::DeleteImage()
     4604{
     4605    AutoLock alock (this);
     4606    CHECK_READY();
     4607    CHECK_BUSY_AND_READERS();
     4608
     4609    return E_NOTIMPL;
     4610
     4611/// @todo later
     4612}
     4613
     4614// public/protected methods for internal purposes only
     4615/////////////////////////////////////////////////////////////////////////////
     4616
     4617/**
     4618 *  Attempts to mark the hard disk as registered.
     4619 *  Only VirtualBox can call this method.
     4620 */
     4621HRESULT HCustomHardDisk::trySetRegistered (BOOL aRegistered)
     4622{
     4623    AutoLock alock (this);
     4624    CHECK_READY();
     4625
     4626    if (aRegistered)
     4627    {
     4628        if (mState == NotCreated)
     4629            return setError (E_FAIL,
     4630                tr ("The storage location '%ls' is not yet created for this hard disk"),
     4631                mLocation.raw());
     4632    }
     4633    else
     4634    {
     4635        ComAssertRet (mState >= Created, E_FAIL);
     4636    }
     4637
     4638    return HardDisk::trySetRegistered (aRegistered);
     4639}
     4640
     4641/**
     4642 *  Checks accessibility of this hard disk image only (w/o parents).
     4643 *
     4644 *  @param aAccessError on output, a null string indicates the hard disk is
     4645 *                      accessible, otherwise contains a message describing
     4646 *                      the reason of inaccessibility.
     4647 */
     4648HRESULT HCustomHardDisk::getAccessible (Bstr &aAccessError)
     4649{
     4650    AutoLock alock (this);
     4651    CHECK_READY();
     4652
     4653    if (mStateCheckSem != NIL_RTSEMEVENTMULTI)
     4654    {
     4655        /* An accessibility check in progress on some other thread,
     4656         * wait for it to finish. */
     4657
     4658        ComAssertRet (mStateCheckWaiters != (ULONG) ~0, E_FAIL);
     4659        ++ mStateCheckWaiters;
     4660        alock.leave();
     4661
     4662        int vrc = RTSemEventMultiWait (mStateCheckSem, RT_INDEFINITE_WAIT);
     4663
     4664        alock.enter();
     4665        AssertReturn (mStateCheckWaiters != 0, E_FAIL);
     4666        -- mStateCheckWaiters;
     4667        if (mStateCheckWaiters == 0)
     4668        {
     4669            RTSemEventMultiDestroy (mStateCheckSem);
     4670            mStateCheckSem = NIL_RTSEMEVENTMULTI;
     4671        }
     4672
     4673        AssertRCReturn (vrc, E_FAIL);
     4674
     4675        /* don't touch aAccessError, it has been already set */
     4676        return S_OK;
     4677    }
     4678
     4679    /* check the basic accessibility */
     4680    HRESULT rc = getBaseAccessible (aAccessError, true /* aCheckBusy */);
     4681    if (FAILED (rc) || !aAccessError.isNull())
     4682        return rc;
     4683
     4684    if (mState >= Created)
     4685    {
     4686        return queryInformation (&aAccessError);
     4687    }
     4688
     4689    aAccessError = Utf8StrFmt ("Hard disk location '%ls' is not yet created",
     4690                               mLocation.raw());
     4691    return S_OK;
     4692}
     4693
     4694/**
     4695 *  Saves hard disk settings to the specified storage node and saves
     4696 *  all children to the specified hard disk node
     4697 *
     4698 *  @param aHDNode      <HardDisk> or <DiffHardDisk> node
     4699 *  @param aStorageNode <VirtualDiskImage> node
     4700 */
     4701HRESULT HCustomHardDisk::saveSettings (CFGNODE aHDNode, CFGNODE aStorageNode)
     4702{
     4703    AssertReturn (aHDNode && aStorageNode, E_FAIL);
     4704
     4705    AutoLock alock (this);
     4706    CHECK_READY();
     4707
     4708    /* location (required) */
     4709    CFGLDRSetBSTR (aStorageNode, "location", mLocation);
     4710
     4711    CFGLDRSetBSTR (aStorageNode, "format", mFormat);
     4712    /* save basic settings and children */
     4713    return HardDisk::saveSettings (aHDNode);
     4714}
     4715
     4716/**
     4717 *  Returns the string representation of this hard disk.
     4718 *  When \a aShort is false, returns the full image file path.
     4719 *  Otherwise, returns the image file name only.
     4720 *
     4721 *  @param aShort       if true, a short representation is returned
     4722 */
     4723Bstr HCustomHardDisk::toString (bool aShort /* = false */)
     4724{
     4725    AutoLock alock (this);
     4726
     4727    if (!aShort)
     4728        return mLocation;
     4729    else
     4730    {
     4731        Utf8Str fname = mLocation;
     4732        return fname.mutableRaw();
     4733    }
     4734}
     4735
     4736/**
     4737 *  Creates a clone of this hard disk by storing hard disk data in the given
     4738 *  VDI file.
     4739 *
     4740 *  If the operation fails, @a aDeleteTarget will be set to @c true unless the
     4741 *  failure happened because the target file already existed.
     4742 *
     4743 *  @param aId              UUID to assign to the created image.
     4744 *  @param aTargetPath      VDI file where the cloned image is to be to stored.
     4745 *  @param aProgress        progress object to run during operation.
     4746 *  @param aDeleteTarget    Whether it is recommended to delete target on
     4747 *                          failure or not.
     4748 */
     4749HRESULT
     4750HCustomHardDisk::cloneToImage (const Guid &aId, const Utf8Str &aTargetPath,
     4751                          Progress *aProgress, bool &aDeleteTarget)
     4752{
     4753    ComAssertMsgFailed (("Not implemented"));
     4754    return E_NOTIMPL;
     4755}
     4756
     4757/**
     4758 *  Creates a new differencing image for this hard disk with the given
     4759 *  VDI file name.
     4760 *
     4761 *  @param aId          UUID to assign to the created image
     4762 *  @param aTargetPath  VDI file where to store the created differencing image
     4763 *  @param aProgress    progress object to run during operation
     4764 *                      (can be NULL)
     4765 */
     4766HRESULT
     4767HCustomHardDisk::createDiffImage (const Guid &aId, const Utf8Str &aTargetPath,
     4768                                  Progress *aProgress)
     4769{
     4770    ComAssertMsgFailed (("Not implemented"));
     4771    return E_NOTIMPL;
     4772}
     4773
     4774// private methods
     4775/////////////////////////////////////////////////////////////////////////////
     4776
     4777/**
     4778 *  Helper to set a new location.
     4779 *
     4780 *  @note
     4781 *      Must be called from under the object's lock!
     4782 */
     4783HRESULT HCustomHardDisk::setLocation (const BSTR aLocation)
     4784{
     4785    if (aLocation && *aLocation)
     4786    {
     4787        mLocation = aLocation;
     4788    }
     4789    else
     4790    {
     4791        mLocation.setNull();
     4792    }
     4793
     4794    return S_OK;
     4795}
     4796
     4797/**
     4798 *  Helper to query information about the custom hard disk.
     4799 *
     4800 *  @param aAccessError not used when NULL, otherwise see #getAccessible()
     4801 *
     4802 *  @note Must be called from under the object's lock, only after
     4803 *        CHECK_BUSY_AND_READERS() succeeds.
     4804 */
     4805HRESULT HCustomHardDisk::queryInformation (Bstr *aAccessError)
     4806{
     4807    AssertReturn (isLockedOnCurrentThread(), E_FAIL);
     4808
     4809    /* create a lock object to completely release it later */
     4810    AutoLock alock (this);
     4811
     4812    AssertReturn (mStateCheckWaiters == 0, E_FAIL);
     4813
     4814    ComAssertRet (mState >= Created, E_FAIL);
     4815
     4816    HRESULT rc = S_OK;
     4817    int vrc = VINF_SUCCESS;
     4818
     4819    /* lazily create a semaphore */
     4820    vrc = RTSemEventMultiCreate (&mStateCheckSem);
     4821    ComAssertRCRet (vrc, E_FAIL);
     4822
     4823    /* Reference the disk to prevent any concurrent modifications
     4824     * after releasing the lock below (to unblock getters before
     4825     * a lengthy operation). */
     4826    addReader();
     4827
     4828    alock.leave();
     4829
     4830    /* VBoxVHDD management interface needs to be optimized: we're opening a
     4831     * file three times in a raw to get three bits of information. */
     4832
     4833    Utf8Str location = mLocation;
     4834    Bstr errMsg;
     4835
     4836    /* reset any previous error report from VDError() */
     4837    mLastVDError.setNull();
     4838
     4839    do
     4840    {
     4841        Guid id, parentId;
     4842
     4843        /// @todo changed from VD_OPEN_FLAGS_READONLY to VD_OPEN_FLAGS_NORMAL,
     4844        /// because otherwise registering a virtual harddisk which so far has no UUID will
     4845        /// yield a null UUID. It cannot be added to a custom harddisk opened readonly,
     4846        /// obviously. This of course changes locking behavior, but for now
     4847        /// this is acceptable. A better solution needs to be found later.
     4848        vrc = VDOpen (mContainer, location, VD_OPEN_FLAGS_NORMAL);
     4849        if (VBOX_FAILURE (vrc))
     4850            break;
     4851
     4852        vrc = VDGetUuid (mContainer, 0, id.ptr());
     4853        if (VBOX_FAILURE (vrc))
     4854            break;
     4855        vrc = VDGetParentUuid (mContainer, 0, parentId.ptr());
     4856        if (VBOX_FAILURE (vrc))
     4857            break;
     4858
     4859        if (!mId.isEmpty())
     4860        {
     4861            /* check that the actual UUID of the image matches the stored UUID */
     4862            if (mId != id)
     4863            {
     4864                errMsg = Utf8StrFmt (
     4865                    tr ("Actual UUID {%Vuuid} of the hard disk image '%s' doesn't "
     4866                        "match UUID {%Vuuid} stored in the registry"),
     4867                        id.ptr(), location.raw(), mId.ptr());
     4868                break;
     4869            }
     4870        }
     4871        else
     4872        {
     4873            /* assgn an UUID read from the image file */
     4874            mId = id;
     4875        }
     4876
     4877        if (mParent)
     4878        {
     4879            /* check parent UUID */
     4880            AutoLock parentLock (mParent);
     4881            if (mParent->id() != parentId)
     4882            {
     4883                errMsg = Utf8StrFmt (
     4884                    tr ("UUID {%Vuuid} of the parent image '%ls' stored in "
     4885                        "the hard disk image file '%s' doesn't match "
     4886                        "UUID {%Vuuid} stored in the registry"),
     4887                    parentId.raw(), mParent->toString().raw(),
     4888                    location.raw(), mParent->id().raw());
     4889                break;
     4890            }
     4891        }
     4892        else if (!parentId.isEmpty())
     4893        {
     4894            errMsg = Utf8StrFmt (
     4895                tr ("Hard disk image '%s' is a differencing image that is linked "
     4896                    "to a hard disk with UUID {%Vuuid} and cannot be used "
     4897                    "directly as a base hard disk"),
     4898                location.raw(), parentId.raw());
     4899            break;
     4900        }
     4901
     4902        /* get actual file size */
     4903        /// @todo is there a direct method in RT?
     4904        {
     4905            RTFILE file = NIL_RTFILE;
     4906            vrc = RTFileOpen (&file, location, RTFILE_O_READ);
     4907            if (VBOX_SUCCESS (vrc))
     4908            {
     4909                uint64_t size = 0;
     4910                vrc = RTFileGetSize (file, &size);
     4911                if (VBOX_SUCCESS (vrc))
     4912                    mActualSize = size;
     4913                RTFileClose (file);
     4914            }
     4915            if (VBOX_FAILURE (vrc))
     4916                break;
     4917        }
     4918
     4919        /* query logical size only for non-differencing images */
     4920        if (!mParent)
     4921        {
     4922            uint64_t size = VDGetSize (mContainer);
     4923            /* convert to MBytes */
     4924            mSize = size / 1024 / 1024;
     4925        }
     4926    }
     4927    while (0);
     4928
     4929    VDCloseAll (mContainer);
     4930
     4931    /* enter the lock again */
     4932    alock.enter();
     4933
     4934    /* remove the reference */
     4935    releaseReader();
     4936
     4937    if (FAILED (rc) || VBOX_FAILURE (vrc) || !errMsg.isNull())
     4938    {
     4939        LogWarningFunc (("'%ls' is not accessible "
     4940                         "(rc=%08X, vrc=%Vrc, errMsg='%ls')\n",
     4941                         mLocation.raw(), rc, vrc, errMsg.raw()));
     4942
     4943        if (aAccessError)
     4944        {
     4945            if (!errMsg.isNull())
     4946                *aAccessError = errMsg;
     4947            else if (!mLastVDError.isNull())
     4948                *aAccessError = mLastVDError;
     4949            else if (VBOX_FAILURE (vrc))
     4950                *aAccessError = Utf8StrFmt (
     4951                    tr ("Could not access hard disk image '%ls' (%Vrc)"),
     4952                        mLocation.raw(), vrc);
     4953        }
     4954
     4955        /* downgrade to not accessible */
     4956        mState = Created;
     4957    }
     4958    else
     4959    {
     4960        if (aAccessError)
     4961            aAccessError->setNull();
     4962
     4963        mState = Accessible;
     4964    }
     4965
     4966    /* inform waiters if there are any */
     4967    if (mStateCheckWaiters > 0)
     4968    {
     4969        RTSemEventMultiSignal (mStateCheckSem);
     4970    }
     4971    else
     4972    {
     4973        /* delete the semaphore ourselves */
     4974        RTSemEventMultiDestroy (mStateCheckSem);
     4975        mStateCheckSem = NIL_RTSEMEVENTMULTI;
     4976    }
     4977
     4978    /* cleanup the last error report from VDError() */
     4979    mLastVDError.setNull();
     4980
     4981    return rc;
     4982}
     4983
     4984/**
     4985 *  Helper to create hard disk images.
     4986 *
     4987 *  @param aSize        size in MB
     4988 *  @param aDynamic     dynamic or fixed image
     4989 *  @param aProgress    address of IProgress pointer to return
     4990 */
     4991HRESULT HCustomHardDisk::createImage (ULONG64 aSize, BOOL aDynamic,
     4992                                      IProgress **aProgress)
     4993{
     4994    ComAssertMsgFailed (("Not implemented"));
     4995    return E_NOTIMPL;
     4996}
     4997
     4998/* static */
     4999DECLCALLBACK(int) HCustomHardDisk::VDITaskThread (RTTHREAD thread, void *pvUser)
     5000{
     5001    AssertMsgFailed (("Not implemented"));
     5002    return VERR_GENERAL_FAILURE;
     5003}
     5004
     5005/* static */
     5006DECLCALLBACK(void) HCustomHardDisk::VDError (void *pvUser, int rc, RT_SRC_POS_DECL,
     5007                                             const char *pszFormat, va_list va)
     5008{
     5009    HCustomHardDisk *that = static_cast <HCustomHardDisk *> (pvUser);
     5010    AssertReturnVoid (that != NULL);
     5011
     5012    /// @todo pass the error message to the operation initiator
     5013    Utf8Str err = Utf8StrFmt (pszFormat, va);
     5014    if (VBOX_FAILURE (rc))
     5015        err = Utf8StrFmt ("%s (%Vrc)", err.raw(), rc);
     5016
     5017    if (that->mLastVDError.isNull())
     5018        that->mLastVDError = err;
     5019    else
     5020        that->mLastVDError = Utf8StrFmt
     5021            ("%s.\n%s", that->mLastVDError.raw(), err.raw());
     5022}
     5023
  • trunk/src/VBox/Main/VirtualBoxImpl.cpp

    r5061 r5101  
    946946            rc = vmdk->init (this, NULL, NULL);
    947947            hardDisk = vmdk;
     948            break;
     949       }
     950       case HardDiskStorageType_CustomHardDisk:
     951       {
     952            ComObjPtr <HCustomHardDisk> custom;
     953            custom.createObject();
     954            rc = custom->init (this, NULL, NULL);
     955            hardDisk = custom;
    948956            break;
    949957       }
     
    35993607                    break;
    36003608                }
     3609                CFGLDRGetChildNode (hdNode, "CustomHardDisk", 0, &storageNode);
     3610                if (storageNode)
     3611                {
     3612                    ComObjPtr <HCustomHardDisk> custom;
     3613                    custom.createObject();
     3614                    rc = custom->init (this, NULL, hdNode, storageNode);
     3615                    break;
     3616                }
    36013617
    36023618                /// @todo (dmik) later
     
    38553871            {
    38563872                CFGLDRAppendChildNode (hdNode, "VMDKImage", &storageNode);
     3873                ComAssertBreak (storageNode, rc = E_FAIL);
     3874                rc = hd->saveSettings (hdNode, storageNode);
     3875                break;
     3876            }
     3877            case HardDiskStorageType_CustomHardDisk:
     3878            {
     3879                CFGLDRAppendChildNode (hdNode, "CustomHardDisk", &storageNode);
    38573880                ComAssertBreak (storageNode, rc = E_FAIL);
    38583881                rc = hd->saveSettings (hdNode, storageNode);
  • trunk/src/VBox/Main/idl/VirtualBox.xidl

    r5060 r5101  
    49284928      </desc>
    49294929    </const>
     4930    <const name="CustomHardDisk" value="3">
     4931      <desc>
     4932        Disk formats supported through plugins (the access type (
     4933        wether regular file in the host OS or something else) is up to
     4934        the plugin, see <link to="ICustomHardDisk"/>)
     4935      </desc>
     4936    </const>
    49304937  </enum>
    49314938
     
    50385045          <i>VMware VMDK Image</i>, a regular file in the file system of the
    50395046          host OS (represented by the <link to="IVMDKImage"/> interface).
     5047        </li>
     5048
     5049        <li>
     5050          <i>Custom HardDisk</i>, a disk accessed via a plugin which is loaded
     5051          when the disk is accessed (represented by the
     5052          <link to="ICustomHardDisk"/> interface).
    50405053        </li>
    50415054
     
    58665879          folder</link> will be used as a path to the image file.
    58675880        </note>
     5881
     5882      </desc>
     5883    </attribute>
     5884
     5885    <attribute name="created" type="boolean" readonly="yes">
     5886      <desc>
     5887
     5888        Whether the virual disk image is created or not. For newly created
     5889        hard disk objects or after a successful invocation of
     5890        <link to="#deleteImage()"/>, this value is <tt>false</tt> until
     5891        <link to="#createFixedImage()"/> or <link to="#createDynamicImage()"/>
     5892        is called.
     5893
     5894      </desc>
     5895    </attribute>
     5896
     5897    <method name="createDynamicImage">
     5898
     5899      <desc>
     5900
     5901        Starts creating a dymically expanding hard disk image in the
     5902        background. The previous image associated with this object, if
     5903        any, must be deleted using <link to="#deleteImage"/>, otherwise
     5904        the operation will fail.
     5905
     5906        <note>
     5907          After the returned progress object reports that the
     5908          operation is complete, this hard disk object can be
     5909          <link to="IVirtualBox::registerHardDisk()">registered</link> within
     5910          this VirtualBox installation.
     5911        </note>
     5912
     5913      </desc>
     5914
     5915      <param name="size" type="unsigned long long" dir="in">
     5916        <desc>Maximum logical size of the hard disk in megabytes.</desc>
     5917      </param>
     5918      <param name="progress" type="IProgress" dir="return">
     5919        <desc>Progress object to track the operation completion.</desc>
     5920      </param>
     5921
     5922    </method>
     5923
     5924    <method name="createFixedImage">
     5925      <desc>
     5926
     5927        Starts creating a fixed-size hard disk image in the background.  The
     5928        previous image, if any, must be deleted using
     5929        <link to="#deleteImage"/>, otherwise the operation will fail.
     5930
     5931        <note>
     5932          After the returned progress object reports that the
     5933          operation is complete, this hard disk object can be
     5934          <link to="IVirtualBox::registerHardDisk()">registered</link> within
     5935          this VirtualBox installation.
     5936        </note>
     5937
     5938      </desc>
     5939
     5940      <param name="size" type="unsigned long long" dir="in">
     5941        <desc>Logical size of the hard disk in megabytes.</desc>
     5942      </param>
     5943      <param name="progress" type="IProgress" dir="return">
     5944        <desc>Progress object to track the operation completion.</desc>
     5945      </param>
     5946
     5947    </method>
     5948
     5949    <method name="deleteImage">
     5950      <desc>
     5951
     5952        Deletes the existing hard disk image. The hard disk must not be
     5953        registered within this VirtualBox installation, otherwise the
     5954        operation will fail.
     5955
     5956        <note>
     5957          After this operation succeeds, it will be impossible to register the
     5958          hard disk until the image file is created again.
     5959        </note>
     5960
     5961        <note>
     5962          This operation is valid only for non-differencing hard disks, after
     5963          they are unregistered using
     5964          <link to="IVirtualBox::unregisterHardDisk()"/>.
     5965        </note>
     5966
     5967      </desc>
     5968    </method>
     5969
     5970  </interface>
     5971
     5972  <!--
     5973  // ICustomHardDisk
     5974  /////////////////////////////////////////////////////////////////////////
     5975  -->
     5976
     5977  <interface
     5978     name="ICustomHardDisk" extends="$unknown"
     5979     uuid="a7b0236d-3ff4-47c0-a4aa-ddc4ddc1141a"
     5980     wsmap="managed"
     5981     >
     5982    <desc>
     5983
     5984      The ICustomHardDisk interface represents <link to="IHardDisk">virtual hard
     5985      disks</link> that are supported through third-parite plugins.
     5986
     5987      Hard disks using custom images can be opened using
     5988      <link to="IVirtualBox::openHardDisk()"/>.
     5989
     5990      Objects that support this interface also support the
     5991      <link to="IHardDisk"/> interface.
     5992
     5993      When a new hard disk object is created from scratch, an image file for it
     5994      is not automatically created. To do it, you need to specify a
     5995      valid <link to="#filePath">file path</link>, and call
     5996      <link to="#createFixedImage()"/> or <link to="#createDynamicImage()"/>.
     5997      When it is done, the hard disk object can be registered by calling
     5998      <link to="IVirtualBox::registerHardDisk()"/> and then
     5999      <link to="IMachine::attachHardDisk()">attached</link> to
     6000      virtual machines.
     6001
     6002      The <link to="IHardDisk::description">description</link>
     6003      of the hard disk is stored in the VirtualBox
     6004      configuration file, so it can be changed (at appropriate
     6005      times) even when
     6006      <link to="IHardDisk::accessible">accessible</link> returns
     6007      <tt>false</tt>.  However, the hard disk must not be
     6008      attached to a running virtual machine.
     6009
     6010    </desc>
     6011
     6012    <attribute name="location" type="wstring">
     6013      <desc>
     6014
     6015        Full location path of the custom image of this hard disk.
     6016
     6017        When assigning a new path, it must be absolute (full path).
     6018        When reading this propery, a full path is always returned.
     6019
     6020        <note>
     6021          This property cannot be changed when <link to="#created"/>
     6022          returns <tt>true</tt>. In this case, the specified file name can be
     6023          absolute (full path) or relative to
     6024          the <link to="IVirtualBox::homeFolder"> VirtualBox home
     6025          directory</link>.  If only a file name without any path is given,
     6026          the <link to="ISystemProperties::defaultVDIFolder"> default VDI
     6027          folder</link> will be used as a path to the image file.
     6028        </note>
     6029
     6030      </desc>
     6031    </attribute>
     6032
     6033    <attribute name="format" type="wstring" readonly="yes">
     6034      <desc>
     6035
     6036      The plugin name of the image file.
    58686037
    58696038      </desc>
  • trunk/src/VBox/Main/include/HardDiskImpl.h

    r4071 r5101  
    538538};
    539539
     540////////////////////////////////////////////////////////////////////////////////
     541
     542class ATL_NO_VTABLE HCustomHardDisk :
     543    public HardDisk,
     544    public VirtualBoxSupportTranslation <HCustomHardDisk>,
     545    public ICustomHardDisk
     546{
     547
     548public:
     549
     550    VIRTUALBOXSUPPORTTRANSLATION_OVERRIDE(HCustomHardDisk)
     551
     552    DECLARE_NOT_AGGREGATABLE(HCustomHardDisk)
     553
     554    DECLARE_PROTECT_FINAL_CONSTRUCT()
     555
     556    BEGIN_COM_MAP(HCustomHardDisk)
     557        COM_INTERFACE_ENTRY(ISupportErrorInfo)
     558        COM_INTERFACE_ENTRY(IHardDisk)
     559        COM_INTERFACE_ENTRY(ICustomHardDisk)
     560    END_COM_MAP()
     561
     562    NS_DECL_ISUPPORTS
     563
     564    HRESULT FinalConstruct();
     565    void FinalRelease();
     566
     567    // public initializer/uninitializer for internal purposes only
     568
     569    HRESULT init (VirtualBox *aVirtualBox, HardDisk *aParent,
     570                  CFGNODE aHDNode, CFGNODE aCustomNode);
     571    HRESULT init (VirtualBox *aVirtualBox, HardDisk *aParent,
     572                  INPTR BSTR aLocation, BOOL aRegistered = FALSE);
     573    void uninit();
     574
     575    // IHardDisk properties
     576    STDMETHOD(COMGETTER(Description)) (BSTR *aDescription);
     577    STDMETHOD(COMSETTER(Description)) (INPTR BSTR aDescription);
     578    STDMETHOD(COMGETTER(Size)) (ULONG64 *aSize);
     579    STDMETHOD(COMGETTER(ActualSize)) (ULONG64 *aActualSize);
     580
     581    // IVirtualDiskImage properties
     582    STDMETHOD(COMGETTER(Location)) (BSTR *aLocation);
     583    STDMETHOD(COMSETTER(Location)) (INPTR BSTR aLocation);
     584    STDMETHOD(COMGETTER(Format))   (BSTR *aFormat);
     585    STDMETHOD(COMGETTER(Created))  (BOOL *aCreated);
     586
     587    // IVirtualDiskImage methods
     588    STDMETHOD(CreateDynamicImage) (ULONG64 aSize, IProgress **aProgress);
     589    STDMETHOD(CreateFixedImage) (ULONG64 aSize, IProgress **aProgress);
     590    STDMETHOD(DeleteImage)();
     591
     592    // public methods for internal purposes only
     593
     594    const Bstr &Location() const { return mLocation; }
     595
     596    HRESULT trySetRegistered (BOOL aRegistered);
     597    HRESULT getAccessible (Bstr &aAccessError);
     598
     599    HRESULT saveSettings (CFGNODE aHDNode, CFGNODE aStorageNode);
     600
     601    Bstr toString (bool aShort = false);
     602
     603    HRESULT cloneToImage (const Guid &aId, const Utf8Str &aTargetPath,
     604                          Progress *aProgress, bool &aDeleteTarget);
     605    HRESULT createDiffImage (const Guid &aId, const Utf8Str &aTargetPath,
     606                             Progress *aProgress);
     607
     608    // for VirtualBoxSupportErrorInfoImpl
     609    static const wchar_t *getComponentName() { return L"CustomHardDisk"; }
     610
     611private:
     612
     613    HRESULT setLocation (const BSTR aLocation);
     614    HRESULT queryInformation (Bstr *aAccessError);
     615    HRESULT createImage (ULONG64 aSize, BOOL aDynamic, IProgress **aProgress);
     616
     617    /** VDI asynchronous operation thread function */
     618    static DECLCALLBACK(int) VDITaskThread (RTTHREAD thread, void *pvUser);
     619
     620    static DECLCALLBACK(void) VDError (void *pvUser, int rc, RT_SRC_POS_DECL,
     621                                       const char *pszFormat, va_list va);
     622
     623    enum State
     624    {
     625        NotCreated,
     626        Created,
     627        /* the following must be greater than Created */
     628        Accessible,
     629    };
     630
     631    State mState;
     632   
     633    RTSEMEVENTMULTI mStateCheckSem;
     634    ULONG mStateCheckWaiters;
     635
     636    Bstr mDescription;
     637
     638    ULONG64 mSize;
     639    ULONG64 mActualSize;
     640
     641    Bstr mLocation;
     642    Bstr mFormat;
     643
     644    PVBOXHDD mContainer;
     645
     646    Utf8Str mLastVDError;
     647
     648    friend class HardDisk;
     649};
     650
    540651
    541652COM_DECL_READONLY_ENUM_AND_COLLECTION (HardDisk)
  • trunk/src/VBox/Main/linux/server.cpp

    r4100 r5101  
    120120NS_DECL_CLASSINFO(HVMDKImage)
    121121NS_IMPL_THREADSAFE_ISUPPORTS2_CI(HVMDKImage, IHardDisk, IVMDKImage)
     122NS_DECL_CLASSINFO(HCustomHardDisk)
     123NS_IMPL_THREADSAFE_ISUPPORTS2_CI(HCustomHardDisk, IHardDisk, ICustomHardDisk)
    122124NS_DECL_CLASSINFO(HardDiskAttachment)
    123125NS_IMPL_THREADSAFE_ISUPPORTS1_CI(HardDiskAttachment, IHardDiskAttachment)
  • trunk/src/VBox/Main/xml/VirtualBox-settings-common.xsd

    r5074 r5101  
    254254        </xsd:complexType>
    255255      </xsd:element>
     256      <xsd:element name="CustomHardDisk">
     257        <xsd:complexType>
     258           <xsd:attribute name="location" type="TLocalFile" use="required"/>
     259           <xsd:attribute name="format" type="xsd:string" use="required"/>
     260        </xsd:complexType>
     261      </xsd:element>
    256262    </xsd:choice>
    257263    <xsd:element name="DiffHardDisk" type="TDiffHardDisk" minOccurs="0" maxOccurs="unbounded"/>
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette