third_party/virtualbox/src/VBox/Main/src-server/MachineImpl.cpp
/**
 * Main implementation for Machine::DetachDevice. This also gets called
 * from Machine::prepareUnregister() so it has been taken out for simplicity.
 *
 * @param pAttach   Medium attachment to detach.
 * @param writeLock Machine write lock which the caller must have locked once.
 *                  This may be released temporarily in here.
 * @param pSnapshot If NULL, then the detachment is for the current machine.
 *                  Otherwise this is for a SnapshotMachine, and this must be
 *                  its snapshot.
 * @return
 */
Main implementation for Machine::DetachDevice. This also gets called
from Machine::prepareUnregister() so it has been taken out for simplicity.

@param pAttach   Medium attachment to detach.
@param writeLock Machine write lock which the caller must have locked once.
This may be released temporarily in here.
@param pSnapshot If NULL, then the detachment is for the current machine.
Otherwise this is for a SnapshotMachine, and this must be
its snapshot.
@return
Main implementation for Machine :: DetachDevice . This also gets called from Machine :: prepareUnregister () so it has been taken out for simplicity . @param pAttach Medium attachment to detach . @param writeLock Machine write lock which the caller must have locked once . This may be released temporarily in here . @param pSnapshot If NULL then the detachment is for the current machine . Otherwise this is for a SnapshotMachine and this must be its snapshot . @return
HRESULT Machine::i_detachDevice(MediumAttachment *pAttach,
                                AutoWriteLock &writeLock,
                                Snapshot *pSnapshot)
{
    ComObjPtr<Medium> oldmedium = pAttach->i_getMedium();
    DeviceType_T mediumType = pAttach->i_getType();
    LogFlowThisFunc(("Entering, medium of attachment is %s\n", oldmedium ? oldmedium->i_getLocationFull().c_str() : "NULL"));
    if (pAttach->i_isImplicit())
    {
        Assert(mMediumAttachments.isBackedUp());
        MachineState_T oldState = mData->mMachineState;
        i_setMachineState(MachineState_SettingUp);
        writeLock.release();
        HRESULT rc = oldmedium->i_deleteStorage(NULL ,
                                                true );
        writeLock.acquire();
        i_setMachineState(oldState);
        if (FAILED(rc)) return rc;
    }
    i_setModified(IsModified_Storage);
    mMediumAttachments.backup();
    mMediumAttachments->remove(pAttach);
    if (!oldmedium.isNull())
    {
        if (pSnapshot)
            oldmedium->i_removeBackReference(mData->mUuid, pSnapshot->i_getId());
        else if (mediumType != DeviceType_HardDisk)
            oldmedium->i_removeBackReference(mData->mUuid);
    }
    return S_OK;
}
HRESULT Machine :: i_detachDevice ( MediumAttachment * pAttach , AutoWriteLock & writeLock , Snapshot * pSnapshot ) { ComObjPtr < Medium > oldmedium = pAttach -> i_getMedium ( ) ; DeviceType_T mediumType = pAttach -> i_getType ( ) ; LogFlowThisFunc ( ( " \n " , oldmedium ? oldmedium -> i_getLocationFull ( ) . c_str ( ) : " " ) ) ; if ( pAttach -> i_isImplicit ( ) ) { Assert ( mMediumAttachments . isBackedUp ( ) ) ; MachineState_T oldState = mData -> mMachineState ; i_setMachineState ( MachineState_SettingUp ) ; writeLock . release ( ) ; HRESULT rc = oldmedium -> i_deleteStorage ( NULL , true ) ; writeLock . acquire ( ) ; i_setMachineState ( oldState ) ; if ( FAILED ( rc ) ) return rc ; } i_setModified ( IsModified_Storage ) ; mMediumAttachments . backup ( ) ; mMediumAttachments -> remove ( pAttach ) ; if ( ! oldmedium . isNull ( ) ) { if ( pSnapshot ) oldmedium -> i_removeBackReference ( mData -> mUuid , pSnapshot -> i_getId ( ) ) ; else if ( mediumType != DeviceType_HardDisk ) oldmedium -> i_removeBackReference ( mData -> mUuid ) ; } return S_OK ; }
Main implementation for Machine::DetachDevice.
Main implementation for Machine :: DetachDevice .
/* attempt to implicitly delete the implicitly created diff */ /// @todo move the implicit flag from MediumAttachment to Medium /// and forbid any hard disk operation when it is implicit. Or maybe /// a special media state for it to make it even more simple. /* will release the lock before the potentially lengthy operation, so
         * protect with the special state */ /*aProgress*/ /*aWait*/ // if this is from a snapshot, do not defer detachment to i_commitMedia() // else if non-hard disk media, do not defer detachment to i_commitMedia() either