VirtualBox

Changeset 55214 in vbox


Ignore:
Timestamp:
Apr 13, 2015 3:53:01 PM (9 years ago)
Author:
vboxsync
Message:

Main/Console+Machine+Session+Snapshot: move the save state and snapshot related methods from IConsole to IMachine, with lots of unavoidable code restructuring and cleanup. Also define two new machine states (so that the "Saving" one is specifically for saving state now) which requires more changes everywhere
Frontends: necessary adjustments
doc/SDK: document the changes

Location:
trunk
Files:
33 edited

Legend:

Unmodified
Added
Removed
  • trunk/doc/manual/en_US/SDKRef.xml

    r55142 r55214  
    38563856
    38573857      <itemizedlist>
     3858        <listitem>
     3859          <para>The methods for saving state, adopting a saved state file,
     3860          discarding saved state, taking a snapshot, restoring
     3861          a snapshot and deleting a snapshot have been moved from
     3862          <computeroutput>IConsole</computeroutput> to
     3863          <computeroutput>IMachine</computeroutput>. This straightens out the
     3864          logical placement of methods and was necessary to resolve a
     3865          long-standing issue, preventing 32 bit API clients from invokingi
     3866          those operations in the case where no VM is running.
     3867          Method
     3868          <xref linkend="IMachine__saveState"
     3869          xreflabel="IMachine::saveState()" /> replaces
     3870          <computeroutput>IConsole::saveState()</computeroutput>,
     3871          <xref linkend="IMachine__adoptSavedState"
     3872          xreflabel="IMachine::adoptSavedState()" /> replaces
     3873          <computeroutput>IConsole::adoptSavedState()</computeroutput>,
     3874          <xref linkend="IMachine__discardSavedState"
     3875          xreflabel="IMachine::discardSavedState()" /> replaces
     3876          <computeroutput>IConsole::discardSavedState()</computeroutput>,
     3877          <xref linkend="IMachine__takeSnapshot"
     3878          xreflabel="IMachine::takeSnapshot()" /> replaces
     3879          <computeroutput>IConsole::takeSnapshot()</computeroutput>,
     3880          <xref linkend="IMachine__deleteSnapshot"
     3881          xreflabel="IMachine::deleteSnapshot()" /> replaces
     3882          <computeroutput>IConsole::deleteSnapshot()</computeroutput>,
     3883          <xref linkend="IMachine__deleteSnapshotAndAllChildren"
     3884          xreflabel="IMachine::deleteSnapshotAndAllChildren()" /> replaces
     3885          <computeroutput>IConsole::deleteSnapshotAndAllChildren()</computeroutput>,
     3886          <xref linkend="IMachine__deleteSnapshotRange"
     3887          xreflabel="IMachine::deleteSnapshotRange()" /> replaces
     3888          <computeroutput>IConsole::deleteSnapshotRange()</computeroutput> and
     3889          <xref linkend="IMachine__restoreSnapshot"
     3890          xreflabel="IMachine::restoreSnapshot()" /> replaces
     3891          <computeroutput>IConsole::restoreSnapshot()</computeroutput>.
     3892          Small adjustments to the parameter lists have been made to reduce
     3893          the number of API calls when taking online snapshots etc.</para>
     3894        </listitem>
     3895
     3896        <listitem>
     3897          <para>Two new machine states have been introduced to allow proper
     3898          distinction between saving state and taking a snapshot.
     3899          <xref linkend="MachineState__Saving" xreflabel="MachineState_Saving" />
     3900          now is used exclusively while the VM's state is being saved, without
     3901          any overlaps with snapshot functionality. The new state
     3902          <xref linkend="MachineState__Snapshotting" xreflabel="MachineState_Snapshotting" />
     3903          is used when an offline snapshot is taken and likewise the new state
     3904          <xref linkend="MachineState__OnlineSnapshotting" xreflabel="MachineState_OnlineSnapshotting" />
     3905          is used when an online snapshot is taken.</para>
     3906        </listitem>
     3907
    38583908        <listitem>
    38593909          <para>The method <xref linkend="IVirtualBox__createMedium"
  • trunk/src/VBox/Frontends/VBoxAutostart/VBoxAutostartStop.cpp

    r43967 r55214  
    5151{
    5252    HRESULT rc = S_OK;
     53    ComPtr<IMachine> machine;
    5354    ComPtr<IProgress> progress;
    5455
     
    8384        }
    8485
    85         CHECK_ERROR(console, SaveState(progress.asOutParam()));
     86        CHECK_ERROR(console, COMGETTER(Machine)(machine.asOutParam()));
     87        CHECK_ERROR(machine, SaveState(progress.asOutParam()));
    8688        if (FAILED(rc))
    8789        {
  • trunk/src/VBox/Frontends/VBoxAutostart/VBoxAutostartUtils.cpp

    r43967 r55214  
    4848        case MachineState_Saved:
    4949            return "saved";
     50        case MachineState_Teleported:
     51            return "teleported";
    5052        case MachineState_Aborted:
    5153            return "aborted";
    52         case MachineState_Teleported:
    53             return "teleported";
    5454        case MachineState_Running:
    5555            return "running";
     
    5858        case MachineState_Stuck:
    5959            return fShort ? "gurumeditation"       : "guru meditation";
     60        case MachineState_Teleporting:
     61            return "teleporting";
    6062        case MachineState_LiveSnapshotting:
    6163            return fShort ? "livesnapshotting"     : "live snapshotting";
    62         case MachineState_Teleporting:
    63             return "teleporting";
    6464        case MachineState_Starting:
    6565            return "starting";
     
    7474        case MachineState_TeleportingIn:
    7575            return fShort ? "teleportingin"        : "teleporting (incoming)";
     76        case MachineState_DeletingSnapshotOnline:
     77            return fShort ? "deletingsnapshotlive" : "deleting snapshot live";
     78        case MachineState_DeletingSnapshotPaused:
     79            return fShort ? "deletingsnapshotlivepaused" : "deleting snapshot live paused";
     80        case MachineState_OnlineSnapshotting:
     81            return fShort ? "onlinesnapshotting"   : "online snapshotting";
    7682        case MachineState_RestoringSnapshot:
    7783            return fShort ? "restoringsnapshot"    : "restoring snapshot";
    7884        case MachineState_DeletingSnapshot:
    7985            return fShort ? "deletingsnapshot"     : "deleting snapshot";
    80         case MachineState_DeletingSnapshotOnline:
    81             return fShort ? "deletingsnapshotlive" : "deleting snapshot live";
    82         case MachineState_DeletingSnapshotPaused:
    83             return fShort ? "deletingsnapshotlivepaused" : "deleting snapshot live paused";
    8486        case MachineState_SettingUp:
    8587            return fShort ? "settingup"           : "setting up";
     88        case MachineState_Snapshotting:
     89            return "snapshotting";
    8690        default:
    8791            break;
  • trunk/src/VBox/Frontends/VBoxBalloonCtrl/VBoxModAPIMonitor.cpp

    r43738 r55214  
    1 
    21/* $Id$ */
    32/** @file
     
    65
    76/*
    8  * Copyright (C) 2012 Oracle Corporation
     7 * Copyright (C) 2012-2015 Oracle Corporation
    98 *
    109 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    214213                ComPtr<IConsole> console;
    215214                CHECK_ERROR_BREAK(g_pSession, COMGETTER(Console)(console.asOutParam()));
     215                /* Get the associated session machine. */
     216                ComPtr<IMachine> sessionMachine;
     217                CHECK_ERROR_BREAK(g_pSession, COMGETTER(Machine)(sessionMachine.asOutParam()));
    216218
    217219                ComPtr<IProgress> progress;
     
    269271                        }
    270272
    271                         CHECK_ERROR(console, SaveState(progress.asOutParam()));
     273                        CHECK_ERROR(sessionMachine, SaveState(progress.asOutParam()));
    272274                        if (SUCCEEDED(rc))
    273275                        {
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManageControlVM.cpp

    r55180 r55214  
    262262
    263263            ComPtr<IProgress> progress;
    264             CHECK_ERROR(console, SaveState(progress.asOutParam()));
     264            CHECK_ERROR(sessionMachine, SaveState(progress.asOutParam()));
    265265            if (FAILED(rc))
    266266            {
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManageInfo.cpp

    r55180 r55214  
    139139        case MachineState_Saved:
    140140            return "saved";
     141        case MachineState_Teleported:
     142            return "teleported";
    141143        case MachineState_Aborted:
    142144            return "aborted";
    143         case MachineState_Teleported:
    144             return "teleported";
    145145        case MachineState_Running:
    146146            return "running";
     
    149149        case MachineState_Stuck:
    150150            return fShort ? "gurumeditation"       : "guru meditation";
     151        case MachineState_Teleporting:
     152            return "teleporting";
    151153        case MachineState_LiveSnapshotting:
    152154            return fShort ? "livesnapshotting"     : "live snapshotting";
    153         case MachineState_Teleporting:
    154             return "teleporting";
    155155        case MachineState_Starting:
    156156            return "starting";
     
    165165        case MachineState_TeleportingIn:
    166166            return fShort ? "teleportingin"        : "teleporting (incoming)";
     167        case MachineState_FaultTolerantSyncing:
     168            return fShort ? "faulttolerantsyncing" : "fault tolerant syncing";
     169        case MachineState_DeletingSnapshotOnline:
     170            return fShort ? "deletingsnapshotlive" : "deleting snapshot live";
     171        case MachineState_DeletingSnapshotPaused:
     172            return fShort ? "deletingsnapshotlivepaused" : "deleting snapshot live paused";
     173        case MachineState_OnlineSnapshotting:
     174            return fShort ? "onlinesnapshotting"   : "online snapshotting";
    167175        case MachineState_RestoringSnapshot:
    168176            return fShort ? "restoringsnapshot"    : "restoring snapshot";
    169177        case MachineState_DeletingSnapshot:
    170178            return fShort ? "deletingsnapshot"     : "deleting snapshot";
    171         case MachineState_DeletingSnapshotOnline:
    172             return fShort ? "deletingsnapshotlive" : "deleting snapshot live";
    173         case MachineState_DeletingSnapshotPaused:
    174             return fShort ? "deletingsnapshotlivepaused" : "deleting snapshot live paused";
    175179        case MachineState_SettingUp:
    176             return fShort ? "settingup"           : "setting up";
     180            return fShort ? "settingup"            : "setting up";
     181        case MachineState_Snapshotting:
     182            return fShort ? "snapshotting"         : "offline snapshotting";
    177183        default:
    178184            break;
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManageMisc.cpp

    r54791 r55214  
    650650            do
    651651            {
    652                 ComPtr<IConsole> console;
    653                 CHECK_ERROR_BREAK(a->session, COMGETTER(Console)(console.asOutParam()));
     652                ComPtr<IMachine> console;
     653                CHECK_ERROR_BREAK(a->session, COMGETTER(Machine)(machine.asOutParam()));
    654654                CHECK_ERROR_BREAK(console, DiscardSavedState(true /* fDeleteFile */));
    655655            } while (0);
     
    687687            do
    688688            {
    689                 ComPtr<IConsole> console;
    690                 CHECK_ERROR_BREAK(a->session, COMGETTER(Console)(console.asOutParam()));
    691                 CHECK_ERROR_BREAK(console, AdoptSavedState(Bstr(szStateFileAbs).raw()));
     689                ComPtr<IMachine> machine;
     690                CHECK_ERROR_BREAK(a->session, COMGETTER(Machine)(machine.asOutParam()));
     691                CHECK_ERROR_BREAK(machine, AdoptSavedState(Bstr(szStateFileAbs).raw()));
    692692            } while (0);
    693693            CHECK_ERROR_BREAK(a->session, UnlockMachine());
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManageSnapshot.cpp

    r53624 r55214  
    281281        return 1;
    282282
     283    /* we have to open a session for this task (new or shared) */
     284    CHECK_ERROR_RET(pMachine, LockMachine(a->session, LockType_Shared), 1);
    283285    do
    284286    {
    285         /* we have to open a session for this task (new or shared) */
    286         rc = pMachine->LockMachine(a->session, LockType_Shared);
    287         ComPtr<IConsole> pConsole;
    288         CHECK_ERROR_BREAK(a->session, COMGETTER(Console)(pConsole.asOutParam()));
     287        /* replace the (read-only) IMachine object by a writable one */
     288        CHECK_ERROR_BREAK(a->session, COMGETTER(Machine)(pMachine.asOutParam()));
    289289
    290290        /* switch based on the command */
     
    346346                break;
    347347
    348             if (fPause)
    349             {
    350                 MachineState_T machineState;
    351                 CHECK_ERROR_BREAK(pConsole, COMGETTER(State)(&machineState));
    352                 if (machineState == MachineState_Running)
    353                     CHECK_ERROR_BREAK(pConsole, Pause());
    354                 else
    355                     fPause = false;
    356             }
    357 
    358348            ComPtr<IProgress> progress;
    359             CHECK_ERROR_BREAK(pConsole, TakeSnapshot(name.raw(), desc.raw(),
     349            CHECK_ERROR_BREAK(pMachine, TakeSnapshot(name.raw(), desc.raw(),
     350                                                     fPause,
    360351                                                     progress.asOutParam()));
    361352
    362353            rc = showProgress(progress);
    363354            CHECK_PROGRESS_ERROR(progress, ("Failed to take snapshot"));
    364 
    365             if (fPause)
    366             {
    367                 MachineState_T machineState;
    368                 CHECK_ERROR_BREAK(pConsole, COMGETTER(State)(&machineState));
    369                 if (machineState == MachineState_Paused)
    370                 {
    371                     if (SUCCEEDED(rc))
    372                         CHECK_ERROR_BREAK(pConsole, Resume());
    373                     else
    374                         pConsole->Resume();
    375                 }
    376             }
    377355        }
    378356        else if (    (fDelete = !strcmp(a->argv[1], "delete"))
     
    417395            if (fDelete)
    418396            {
    419                 CHECK_ERROR_BREAK(pConsole, DeleteSnapshot(bstrSnapGuid.raw(),
     397                CHECK_ERROR_BREAK(pMachine, DeleteSnapshot(bstrSnapGuid.raw(),
    420398                                                           pProgress.asOutParam()));
    421399            }
     
    424402                // restore or restore current
    425403                RTPrintf("Restoring snapshot %ls\n", bstrSnapGuid.raw());
    426                 CHECK_ERROR_BREAK(pConsole, RestoreSnapshot(pSnapshot, pProgress.asOutParam()));
     404                CHECK_ERROR_BREAK(pMachine, RestoreSnapshot(pSnapshot, pProgress.asOutParam()));
    427405            }
    428406
  • trunk/src/VBox/Frontends/VBoxSDL/VBoxSDL.cpp

    r55133 r55214  
    18381838        if (machineState == MachineState_Saved)
    18391839        {
    1840             CHECK_ERROR(gpConsole, DiscardSavedState(true /* fDeleteFile */));
     1840            CHECK_ERROR(gpMachine, DiscardSavedState(true /* fDeleteFile */));
    18411841        }
    18421842        /*
     
    18551855                goto leave;
    18561856
    1857             CHECK_ERROR(gpConsole, RestoreSnapshot(pCurrentSnapshot, gpProgress.asOutParam()));
     1857            CHECK_ERROR(gpMachine, RestoreSnapshot(pCurrentSnapshot, gpProgress.asOutParam()));
    18581858            rc = gpProgress->WaitForCompletion(-1);
    18591859        }
     
    42004200    UpdateTitlebar(TITLEBAR_SAVE);
    42014201    gpProgress = NULL;
    4202     HRESULT rc = gpConsole->SaveState(gpProgress.asOutParam());
     4202    HRESULT rc = gpMachine->SaveState(gpProgress.asOutParam());
    42034203    if (FAILED(rc))
    42044204    {
     
    49504950            gpProgress = NULL;
    49514951            HRESULT rc;
    4952             CHECK_ERROR(gpConsole, TakeSnapshot(Bstr(pszSnapshotName).raw(),
     4952            CHECK_ERROR(gpMachine, TakeSnapshot(Bstr(pszSnapshotName).raw(),
    49534953                                                Bstr("Taken by VBoxSDL").raw(),
     4954                                                TRUE,
    49544955                                                gpProgress.asOutParam()));
    49554956            if (FAILED(rc))
  • trunk/src/VBox/Frontends/VBoxShell/vboxshell.py

    r54434 r55214  
    250250    print "removing machine ", mach.name, "with UUID", uuid
    251251    cmdClosedVm(ctx, mach, detachVmDevice, ["ALL"])
    252     mach = mach.unregister(ctx['global'].constants.CleanupMode_Full)
     252    disks = mach.unregister(ctx['global'].constants.CleanupMode_Full)
    253253    if mach:
    254         mach.deleteSettings()
     254        progress = mach.deleteConfig(disks)
     255        if progressBar(ctx, progress, 100) and int(progress.resultCode) == 0:
     256            print "Success!"
     257        else:
     258            reportError(ctx, progress)
    255259    # update cache
    256260    getMachines(ctx, True)
     
    718722           'ginfo':           lambda: ginfo(ctx, console, args),
    719723           'guestlambda':     lambda: args[0](ctx, mach, console, args[1:]),
    720            'save':            lambda: progressBar(ctx, console.saveState()),
     724           'save':            lambda: progressBar(ctx, session.machine.saveState()),
    721725           'screenshot':      lambda: takeScreenshot(ctx, console, args),
    722726           'teleport':        lambda: teleport(ctx, session, console, args),
     
    26312635        else:
    26322636            desc = ""
    2633         cmdAnyVm(ctx, mach, lambda ctx, mach, console, args: progressBar(ctx, console.takeSnapshot(name, desc)))
     2637        cmdAnyVm(ctx, mach, lambda ctx, mach, console, args: progressBar(ctx, mach.takeSnapshot(name, desc, true)))
    26342638        return 0
    26352639
     
    26402644        name = args[3]
    26412645        snap = mach.findSnapshot(name)
    2642         cmdAnyVm(ctx, mach, lambda ctx, mach, console, args: progressBar(ctx, console.restoreSnapshot(snap)))
     2646        cmdAnyVm(ctx, mach, lambda ctx, mach, console, args: progressBar(ctx, mach.restoreSnapshot(snap)))
    26432647        return 0
    26442648
     
    26482652            return 0
    26492653        snap = mach.currentSnapshot()
    2650         cmdAnyVm(ctx, mach, lambda ctx, mach, console, args: progressBar(ctx, console.restoreSnapshot(snap)))
     2654        cmdAnyVm(ctx, mach, lambda ctx, mach, console, args: progressBar(ctx, mach.restoreSnapshot(snap)))
    26512655        return 0
    26522656
     
    26572661        name = args[3]
    26582662        snap = mach.findSnapshot(name)
    2659         cmdAnyVm(ctx, mach, lambda ctx, mach, console, args: progressBar(ctx, console.deleteSnapshot(snap.id)))
     2663        cmdAnyVm(ctx, mach, lambda ctx, mach, console, args: progressBar(ctx, mach.deleteSnapshot(snap.id)))
    26602664        return 0
    26612665
  • trunk/src/VBox/Frontends/VirtualBox/src/converter/UIConverterBackendCOM.cpp

    r55140 r55214  
    55
    66/*
    7  * Copyright (C) 2012-2014 Oracle Corporation
     7 * Copyright (C) 2012-2015 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    7373        case KMachineState_Stuck:                  return QColor(Qt::darkMagenta);
    7474        case KMachineState_Teleporting:            return QColor(Qt::blue);
     75        case KMachineState_Snapshotting:           return QColor(Qt::green);
     76        case KMachineState_OnlineSnapshotting:     return QColor(Qt::green);
    7577        case KMachineState_LiveSnapshotting:       return QColor(Qt::green);
    7678        case KMachineState_Starting:               return QColor(Qt::green);
     
    108110        case KMachineState_Stuck:                  return UIIconPool::iconSet(":/state_stuck_16px.png");
    109111        case KMachineState_Teleporting:            return UIIconPool::iconSet(":/state_running_16px.png");
     112        case KMachineState_Snapshotting:           return UIIconPool::iconSet(":/state_saving_16px.png");
     113        case KMachineState_OnlineSnapshotting:     return UIIconPool::iconSet(":/state_running_16px.png");
    110114        case KMachineState_LiveSnapshotting:       return UIIconPool::iconSet(":/state_running_16px.png");
    111115        case KMachineState_Starting:               return UIIconPool::iconSet(":/state_running_16px.png");
     
    143147        case KMachineState_Stuck:                  return QApplication::translate("VBoxGlobal", "Guru Meditation", "MachineState");
    144148        case KMachineState_Teleporting:            return QApplication::translate("VBoxGlobal", "Teleporting", "MachineState");
     149        case KMachineState_Snapshotting:           return QApplication::translate("VBoxGlobal", "Taking Snapshot", "MachineState");
     150        case KMachineState_OnlineSnapshotting:     return QApplication::translate("VBoxGlobal", "Taking Online Snapshot", "MachineState");
    145151        case KMachineState_LiveSnapshotting:       return QApplication::translate("VBoxGlobal", "Taking Live Snapshot", "MachineState");
    146152        case KMachineState_Starting:               return QApplication::translate("VBoxGlobal", "Starting", "MachineState");
  • trunk/src/VBox/Frontends/VirtualBox/src/globals/UIMessageCenter.cpp

    r55115 r55214  
    55
    66/*
    7  * Copyright (C) 2006-2013 Oracle Corporation
     7 * Copyright (C) 2006-2014 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    766766}
    767767
    768 void UIMessageCenter::cannotDiscardSavedState(const CConsole &console) const
     768void UIMessageCenter::cannotDiscardSavedState(const CMachine &machine) const
    769769{
    770770    error(0, MessageType_Error,
    771771          tr("Failed to discard the saved state of the virtual machine <b>%1</b>.")
    772              .arg(CConsole(console).GetMachine().GetName()),
    773           formatErrorInfo(console));
    774 }
    775 
    776 void UIMessageCenter::cannotSaveMachineState(const CConsole &console)
     772             .arg(machine.GetName()),
     773          formatErrorInfo(machine));
     774}
     775
     776void UIMessageCenter::cannotSaveMachineState(const CMachine &machine)
    777777{
    778778    error(0, MessageType_Error,
    779779          tr("Failed to save the state of the virtual machine <b>%1</b>.")
    780              .arg(CConsole(console).GetMachine().GetName()),
    781           formatErrorInfo(console));
     780             .arg(machine.GetName()),
     781          formatErrorInfo(machine));
    782782}
    783783
     
    866866}
    867867
    868 void UIMessageCenter::cannotTakeSnapshot(const CConsole &console, const QString &strMachineName, QWidget *pParent /* = 0*/) const
     868void UIMessageCenter::cannotTakeSnapshot(const CMachine &machine, const QString &strMachineName, QWidget *pParent /* = 0*/) const
    869869{
    870870    error(pParent, MessageType_Error,
    871871          tr("Failed to create a snapshot of the virtual machine <b>%1</b>.")
    872872             .arg(strMachineName),
    873           formatErrorInfo(console));
     873          formatErrorInfo(machine));
    874874}
    875875
     
    882882}
    883883
    884 bool UIMessageCenter::cannotRestoreSnapshot(const CConsole &console, const QString &strSnapshotName, const QString &strMachineName) const
     884bool UIMessageCenter::cannotRestoreSnapshot(const CMachine &machine, const QString &strSnapshotName, const QString &strMachineName) const
    885885{
    886886    error(0, MessageType_Error,
    887887          tr("Failed to restore the snapshot <b>%1</b> of the virtual machine <b>%2</b>.")
    888888             .arg(strSnapshotName, strMachineName),
    889           formatErrorInfo(console));
     889          formatErrorInfo(machine));
    890890    return false;
    891891}
     
    900900}
    901901
    902 void UIMessageCenter::cannotRemoveSnapshot(const CConsole &console, const QString &strSnapshotName, const QString &strMachineName) const
     902void UIMessageCenter::cannotRemoveSnapshot(const CMachine &machine, const QString &strSnapshotName, const QString &strMachineName) const
    903903{
    904904    error(0, MessageType_Error,
    905905          tr("Failed to delete the snapshot <b>%1</b> of the virtual machine <b>%2</b>.")
    906906             .arg(strSnapshotName, strMachineName),
    907           formatErrorInfo(console));
     907          formatErrorInfo(machine));
    908908}
    909909
  • trunk/src/VBox/Frontends/VirtualBox/src/globals/UIMessageCenter.h

    r54937 r55214  
    44
    55/*
    6  * Copyright (C) 2006-2013 Oracle Corporation
     6 * Copyright (C) 2006-2014 Oracle Corporation
    77 *
    88 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    191191    void cannotPauseMachine(const CConsole &console) const;
    192192    void cannotResumeMachine(const CConsole &console) const;
    193     void cannotDiscardSavedState(const CConsole &console) const;
    194     void cannotSaveMachineState(const CConsole &console);
     193    void cannotDiscardSavedState(const CMachine &machine) const;
     194    void cannotSaveMachineState(const CMachine &machine);
    195195    void cannotSaveMachineState(const CProgress &progress, const QString &strMachineName);
    196196    void cannotACPIShutdownMachine(const CConsole &console) const;
     
    203203    bool warnAboutSnapshotRemovalFreeSpace(const QString &strSnapshotName, const QString &strTargetImageName,
    204204                                           const QString &strTargetImageMaxSize, const QString &strTargetFileSystemFree) const;
    205     void cannotTakeSnapshot(const CConsole &console, const QString &strMachineName, QWidget *pParent = 0) const;
     205    void cannotTakeSnapshot(const CMachine &machine, const QString &strMachineName, QWidget *pParent = 0) const;
    206206    void cannotTakeSnapshot(const CProgress &progress, const QString &strMachineName, QWidget *pParent = 0) const;
    207     bool cannotRestoreSnapshot(const CConsole &console, const QString &strSnapshotName, const QString &strMachineName) const;
     207    bool cannotRestoreSnapshot(const CMachine &machine, const QString &strSnapshotName, const QString &strMachineName) const;
    208208    bool cannotRestoreSnapshot(const CProgress &progress, const QString &strSnapshotName, const QString &strMachineName) const;
    209     void cannotRemoveSnapshot(const CConsole &console, const QString &strSnapshotName, const QString &strMachineName) const;
     209    void cannotRemoveSnapshot(const CMachine &machine, const QString &strSnapshotName, const QString &strMachineName) const;
    210210    void cannotRemoveSnapshot(const CProgress &progress, const QString &strSnapshotName, const QString &strMachineName) const;
    211211
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachine.cpp

    r53046 r55214  
    6262        CSnapshot snapshot = machine.GetCurrentSnapshot();
    6363
    64         /* Open corresponding console: */
    65         CConsole console  = session.GetConsole();
    6664        /* Prepare restore-snapshot progress: */
    67         CProgress progress = console.RestoreSnapshot(snapshot);
    68         if (!console.isOk())
    69             return msgCenter().cannotRestoreSnapshot(console, snapshot.GetName(), machine.GetName());
     65        CProgress progress = machine.RestoreSnapshot(snapshot);
     66        if (!machine.isOk())
     67            return msgCenter().cannotRestoreSnapshot(machine, snapshot.GetName(), machine.GetName());
    7068
    7169        /* Show the snapshot-discarding progress: */
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineLogic.cpp

    r55170 r55214  
    13911391        return;
    13921392
    1393     /* Remember the paused state: */
    1394     bool fWasPaused = uisession()->isPaused();
    1395     if (!fWasPaused)
    1396     {
    1397         /* Suspend the VM and ignore the close event if failed to do so.
    1398          * pause() will show the error message to the user. */
    1399         if (!uisession()->pause())
    1400             return;
    1401     }
    1402 
    14031393    /* Create take-snapshot dialog: */
    14041394    QWidget *pDlgParent = windowManager().realParentWindow(activeMachineWindow());
     
    14331423    {
    14341424        /* Prepare the take-snapshot progress: */
    1435         CProgress progress = console().TakeSnapshot(strSnapshotName, strSnapshotDescription);
    1436         if (console().isOk())
     1425        CProgress progress = machine().TakeSnapshot(strSnapshotName, strSnapshotDescription, true);
     1426        if (machine().isOk())
    14371427        {
    14381428            /* Show the take-snapshot progress: */
     
    14421432        }
    14431433        else
    1444             msgCenter().cannotTakeSnapshot(console(), machineName());
    1445     }
    1446 
    1447     /* Restore the running state if needed: */
    1448     if (!fWasPaused)
    1449     {
    1450         /* Make sure machine-state-change callback is processed: */
    1451         QApplication::sendPostedEvents(uisession(), UIConsoleEventType_StateChange);
    1452         /* Unpause VM: */
    1453         uisession()->unpause();
     1434            msgCenter().cannotTakeSnapshot(machine(), machineName());
    14541435    }
    14551436}
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UISession.cpp

    r55155 r55214  
    55
    66/*
    7  * Copyright (C) 2006-2013 Oracle Corporation
     7 * Copyright (C) 2006-2014 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    300300{
    301301    /* Prepare the saving progress: */
    302     CProgress progress = console().SaveState();
    303     if (console().isOk())
     302    CProgress progress = machine().SaveState();
     303    if (machine().isOk())
    304304    {
    305305        /* Show the saving progress: */
     
    315315    {
    316316        /* Failed in console: */
    317         msgCenter().cannotSaveMachineState(console());
     317        msgCenter().cannotSaveMachineState(machine());
    318318        return false;
    319319    }
     
    408408        do
    409409        {
    410             /* Acquire console for this session: */
    411             CConsole cons = sess.GetConsole();
    412             if (cons.isNull())
     410            /* Acquire machine for this session: */
     411            CMachine machine = sess.GetMachine();
     412            if (machine.isNull())
    413413            {
    414                 /* Unable to acquire console: */
     414                /* Unable to acquire machine: */
    415415                break;
    416416            }
    417417
    418418            /* Prepare the snapshot-discard progress: */
    419             const CSnapshot snap = mach.GetCurrentSnapshot();
    420             CProgress prog = cons.RestoreSnapshot(snap);
    421             if (!cons.isOk() || prog.isNull())
     419            const CSnapshot snap = machine.GetCurrentSnapshot();
     420            CProgress prog = machine.RestoreSnapshot(snap);
     421            if (!machine.isOk() || prog.isNull())
    422422            {
    423423                /* Unable to restore snapshot: */
    424                 msgCenter().cannotRestoreSnapshot(cons, snap.GetName(), machineName());
     424                msgCenter().cannotRestoreSnapshot(machine, snap.GetName(), machineName());
    425425                break;
    426426            }
    427427
    428428            /* Show the snapshot-discard progress: */
    429             msgCenter().showModalProgressDialog(prog, mach.GetName(), ":/progress_snapshot_discard_90px.png");
     429            msgCenter().showModalProgressDialog(prog, machine.GetName(), ":/progress_snapshot_discard_90px.png");
    430430            if (prog.GetResultCode() != 0)
    431431            {
    432432                /* Unable to restore snapshot: */
    433                 msgCenter().cannotRestoreSnapshot(prog, snap.GetName(), mach.GetName());
     433                msgCenter().cannotRestoreSnapshot(prog, snap.GetName(), machine.GetName());
    434434                break;
    435435            }
  • trunk/src/VBox/Frontends/VirtualBox/src/selector/UISelectorWindow.cpp

    r55170 r55214  
    55
    66/*
    7  * Copyright (C) 2006-2013 Oracle Corporation
     7 * Copyright (C) 2006-2015 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    498498            return;
    499499
    500         /* Get session console: */
    501         CConsole console = session.GetConsole();
    502         console.DiscardSavedState(true);
    503         if (!console.isOk())
    504             msgCenter().cannotDiscardSavedState(console);
     500        /* Get session machine: */
     501        CMachine machine = session.GetMachine();
     502        machine.DiscardSavedState(true);
     503        if (!machine.isOk())
     504            msgCenter().cannotDiscardSavedState(machine);
    505505
    506506        /* Unlock machine finally: */
     
    623623        /* Get session console: */
    624624        CConsole console = session.GetConsole();
     625        /* Get session machine: */
     626        CMachine machine = session.GetMachine();
    625627        /* Pause VM first: */
    626628        console.Pause();
     
    628630        {
    629631            /* Prepare machine state saving: */
    630             CProgress progress = console.SaveState();
    631             if (console.isOk())
     632            CProgress progress = machine.SaveState();
     633            if (machine.isOk())
    632634            {
    633635                /* Show machine state saving progress: */
    634                 CMachine machine = session.GetMachine();
    635636                msgCenter().showModalProgressDialog(progress, machine.GetName(), ":/progress_state_save_90px.png");
    636637                if (!progress.isOk() || progress.GetResultCode() != 0)
     
    638639            }
    639640            else
    640                 msgCenter().cannotSaveMachineState(console);
     641                msgCenter().cannotSaveMachineState(machine);
    641642        }
    642643        else
  • trunk/src/VBox/Frontends/VirtualBox/src/selector/VBoxSnapshotsWgt.cpp

    r54774 r55214  
    55
    66/*
    7  * Copyright (C) 2006-2013 Oracle Corporation
     7 * Copyright (C) 2006-2014 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    641641
    642642    /* Restore chosen snapshot: */
    643     CConsole console = session.GetConsole();
    644     CProgress progress = console.RestoreSnapshot(snapshot);
    645     if (console.isOk())
     643    CMachine machine = session.GetMachine();
     644    CProgress progress = machine.RestoreSnapshot(snapshot);
     645    if (machine.isOk())
    646646    {
    647647        msgCenter().showModalProgressDialog(progress, mMachine.GetName(), ":/progress_snapshot_restore_90px.png");
     
    650650    }
    651651    else
    652         msgCenter().cannotRestoreSnapshot(console, snapshot.GetName(), mMachine.GetName());
     652        msgCenter().cannotRestoreSnapshot(machine, snapshot.GetName(), mMachine.GetName());
    653653
    654654    /* Unlock machine finally: */
     
    688688        return;
    689689
    690     CConsole console = session.GetConsole();
    691     CProgress progress = console.DeleteSnapshot (snapId);
    692     if (console.isOk())
     690    /* Remove chosen snapshot: */
     691    CMachine machine = session.GetMachine();
     692    CProgress progress = machine.DeleteSnapshot(snapId);
     693    if (machine.isOk())
    693694    {
    694695        /* Show the progress dialog */
     
    699700    }
    700701    else
    701         msgCenter().cannotRemoveSnapshot(console,  snapshot.GetName(), mMachine.GetName());
     702        msgCenter().cannotRemoveSnapshot(machine,  snapshot.GetName(), mMachine.GetName());
    702703
    703704    session.UnlockMachine();
     
    829830    if (fIsValid)
    830831    {
    831         /* Get corresponding console object also: */
    832         CConsole console = session.GetConsole();
    833         /* Remember runtime state: */
    834         bool fAtRuntime = mMachine.GetState() == KMachineState_Running;
    835         /* Remember paused state: */
    836         bool fWasPaused = mMachine.GetState() == KMachineState_Paused ||
    837                           mMachine.GetState() == KMachineState_TeleportingPausedVM;
    838 
    839         /* Pause VM if necessary: */
    840         if (fIsValid && fAtRuntime && !fWasPaused)
    841         {
    842             /* Pausing VM: */
    843             console.Pause();
    844             if (!console.isOk())
     832        /* Get corresponding machine object also: */
     833        CMachine machine = session.GetMachine();
     834
     835        /* Create take-snapshot dialog: */
     836        QWidget *pDlgParent = windowManager().realParentWindow(this);
     837        QPointer<VBoxTakeSnapshotDlg> pDlg = new VBoxTakeSnapshotDlg(pDlgParent, mMachine);
     838        windowManager().registerNewParent(pDlg, pDlgParent);
     839
     840        /* Assign corresponding icon: */
     841        pDlg->mLbIcon->setPixmap(vboxGlobal().vmGuestOSTypeIcon(mMachine.GetOSTypeId()));
     842
     843        /* Search for the max available snapshot index: */
     844        int iMaxSnapShotIndex = 0;
     845        QString snapShotName = tr("Snapshot %1");
     846        QRegExp regExp(QString("^") + snapShotName.arg("([0-9]+)") + QString("$"));
     847        QTreeWidgetItemIterator iterator(mTreeWidget);
     848        while (*iterator)
     849        {
     850            QString snapShot = static_cast<SnapshotWgtItem*>(*iterator)->text(0);
     851            int pos = regExp.indexIn(snapShot);
     852            if (pos != -1)
     853                iMaxSnapShotIndex = regExp.cap(1).toInt() > iMaxSnapShotIndex ? regExp.cap(1).toInt() : iMaxSnapShotIndex;
     854            ++iterator;
     855        }
     856        pDlg->mLeName->setText(snapShotName.arg(iMaxSnapShotIndex + 1));
     857
     858        /* Exec the dialog: */
     859        bool fDialogAccepted = pDlg->exec() == QDialog::Accepted;
     860
     861        /* Is the dialog still valid? */
     862        if (pDlg)
     863        {
     864            /* Acquire variables: */
     865            QString strSnapshotName = pDlg->mLeName->text().trimmed();
     866            QString strSnapshotDescription = pDlg->mTeDescription->toPlainText();
     867
     868            /* Destroy dialog early: */
     869            delete pDlg;
     870
     871            /* Was the dialog accepted? */
     872            if (fDialogAccepted)
    845873            {
    846                 msgCenter().cannotPauseMachine(console);
    847                 fIsValid = false;
    848             }
    849         }
    850 
    851         if (fIsValid)
    852         {
    853             /* Create take-snapshot dialog: */
    854             QWidget *pDlgParent = windowManager().realParentWindow(this);
    855             QPointer<VBoxTakeSnapshotDlg> pDlg = new VBoxTakeSnapshotDlg(pDlgParent, mMachine);
    856             windowManager().registerNewParent(pDlg, pDlgParent);
    857 
    858             /* Assign corresponding icon: */
    859             pDlg->mLbIcon->setPixmap(vboxGlobal().vmGuestOSTypeIcon(mMachine.GetOSTypeId()));
    860 
    861             /* Search for the max available snapshot index: */
    862             int iMaxSnapShotIndex = 0;
    863             QString snapShotName = tr("Snapshot %1");
    864             QRegExp regExp(QString("^") + snapShotName.arg("([0-9]+)") + QString("$"));
    865             QTreeWidgetItemIterator iterator(mTreeWidget);
    866             while (*iterator)
    867             {
    868                 QString snapShot = static_cast<SnapshotWgtItem*>(*iterator)->text(0);
    869                 int pos = regExp.indexIn(snapShot);
    870                 if (pos != -1)
    871                     iMaxSnapShotIndex = regExp.cap(1).toInt() > iMaxSnapShotIndex ? regExp.cap(1).toInt() : iMaxSnapShotIndex;
    872                 ++iterator;
    873             }
    874             pDlg->mLeName->setText(snapShotName.arg(iMaxSnapShotIndex + 1));
    875 
    876             /* Exec the dialog: */
    877             bool fDialogAccepted = pDlg->exec() == QDialog::Accepted;
    878 
    879             /* Is the dialog still valid? */
    880             if (pDlg)
    881             {
    882                 /* Acquire variables: */
    883                 QString strSnapshotName = pDlg->mLeName->text().trimmed();
    884                 QString strSnapshotDescription = pDlg->mTeDescription->toPlainText();
    885 
    886                 /* Destroy dialog early: */
    887                 delete pDlg;
    888 
    889                 /* Was the dialog accepted? */
    890                 if (fDialogAccepted)
     874                /* Prepare the take-snapshot progress: */
     875                CProgress progress = machine.TakeSnapshot(strSnapshotName, strSnapshotDescription, true);
     876                if (machine.isOk())
    891877                {
    892                     /* Prepare the take-snapshot progress: */
    893                     CProgress progress = console.TakeSnapshot(strSnapshotName, strSnapshotDescription);
    894                     if (console.isOk())
     878                    /* Show the take-snapshot progress: */
     879                    msgCenter().showModalProgressDialog(progress, mMachine.GetName(), ":/progress_snapshot_create_90px.png");
     880                    if (!progress.isOk() || progress.GetResultCode() != 0)
    895881                    {
    896                         /* Show the take-snapshot progress: */
    897                         msgCenter().showModalProgressDialog(progress, mMachine.GetName(), ":/progress_snapshot_create_90px.png");
    898                         if (!progress.isOk() || progress.GetResultCode() != 0)
    899                         {
    900                             msgCenter().cannotTakeSnapshot(progress, mMachine.GetName());
    901                             fIsValid = false;
    902                         }
    903                     }
    904                     else
    905                     {
    906                         msgCenter().cannotTakeSnapshot(console, mMachine.GetName());
     882                        msgCenter().cannotTakeSnapshot(progress, mMachine.GetName());
    907883                        fIsValid = false;
    908884                    }
    909885                }
    910886                else
     887                {
     888                    msgCenter().cannotTakeSnapshot(machine, mMachine.GetName());
    911889                    fIsValid = false;
     890                }
    912891            }
    913892            else
    914893                fIsValid = false;
    915894        }
    916 
    917         /* Resume VM if necessary: */
    918         if (fIsValid && fAtRuntime && !fWasPaused)
    919         {
    920             /* Resuming VM: */
    921             console.Resume();
    922             if (!console.isOk())
    923             {
    924                 msgCenter().cannotResumeMachine(console);
    925                 fIsValid = false;
    926             }
    927         }
     895        else
     896            fIsValid = false;
    928897
    929898        /* Unlock machine finally: */
  • trunk/src/VBox/Frontends/VirtualBox/src/wizards/clonevm/UIWizardCloneVM.cpp

    r52730 r55214  
    55
    66/*
    7  * Copyright (C) 2011-2013 Oracle Corporation
     7 * Copyright (C) 2011-2014 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    7979            return false;
    8080
    81         /* Prepare console: */
    82         CConsole console = session.GetConsole();
     81        /* Prepare machine: */
     82        CMachine machine = session.GetMachine();
    8383
    8484        /* Take the snapshot: */
    8585        QString strSnapshotName = tr("Linked Base for %1 and %2").arg(m_machine.GetName()).arg(strName);
    86         CProgress progress = console.TakeSnapshot(strSnapshotName, "");
    87 
    88         if (console.isOk())
     86        CProgress progress = machine.TakeSnapshot(strSnapshotName, "", true);
     87
     88        if (machine.isOk())
    8989        {
    9090            /* Show the "Taking Snapshot" progress dialog: */
     
    9999        else
    100100        {
    101             msgCenter().cannotTakeSnapshot(console, m_machine.GetName(), this);
     101            msgCenter().cannotTakeSnapshot(machine, m_machine.GetName(), this);
    102102            return false;
    103103        }
  • trunk/src/VBox/Main/idl/VirtualBox.xidl

    r55182 r55214  
    587587  <enum
    588588    name="MachineState"
    589     uuid="ec6c6a9e-113d-4ff4-b44f-0b69f21c97fe"
     589    uuid="87f085c3-ca67-4e45-9225-6057f32e9e8e"
    590590    >
    591591    <desc>
     
    597597      Below is the basic virtual machine state diagram. It shows how the state
    598598      changes during virtual machine execution. The text in square braces shows
    599       a method of the IConsole interface that performs the given state
     599      a method of the IConsole or IMachine interface that performs the given state
    600600      transition.
    601601
     
    611611    |     |     +-----------------------------------------+-|-------------------+ +
    612612    |     |     |                                           |                     |
    613     |     |     +-- Saving &lt;--------[takeSnapshot()]&lt;-------+---------------------+
     613    |     |     +- OnlineSnapshotting &lt;--[takeSnapshot()]&lt;--+---------------------+
    614614    |     |                                                 |                     |
    615615    |     +-------- Saving &lt;--------[saveState()]&lt;----------+---------------------+
     
    683683    |                                                                       |
    684684    +-&gt; PoweredOff --+                                                      |
    685     |                +--&gt;[takeSnapshot()] -------------------&gt; Saving ------+
     685    |                +--&gt;[takeSnapshot()] ------------------&gt; Snapshotting -+
    686686    +-&gt; Aborted -----+
    687687
     
    694694    +---(Saved if restored from an online snapshot, PoweredOff otherwise)---+
    695695      </pre>
    696 
    697       Note that the Saving state is present in both the offline state group and
    698       online state group. Currently, the only way to determine what group is
    699       assumed in a particular case is to remember the previous machine state: if
    700       it was Running or Paused, then Saving is an online state, otherwise it is
    701       an offline state. This inconsistency may be removed in one of the future
    702       versions of VirtualBox by adding a new state.
    703696
    704697      <note internal="yes">
     
    792785        some of the runtime configuration options are inaccessible. Also, if
    793786        paused while in this state it will transition to
    794         @c Saving and it will not be resume the
     787        @c OnlineSnapshotting and it will not be resume the
    795788        execution until the snapshot operation has completed.
    796789      </desc>
     
    810803    <const name="Saving"                    value="12">
    811804      <desc>
    812         Machine is saving its execution state to a file, or an online
    813         snapshot of the machine is being taken.
     805        Machine is saving its execution state to a file.
    814806      </desc>
    815807    </const>
     
    824816        The machine is being teleported to another host or process, but it is
    825817        not running. This is the paused variant of the
    826         @c state.
     818        @c Teleporting state.
    827819      </desc>
    828820    </const>
     
    849841      </desc>
    850842    </const>
    851     <const name="RestoringSnapshot"         value="19">
     843    <const name="OnlineSnapshotting"        value="19">
     844      <desc>
     845        Like @c LiveSnapshotting, but the machine was paused when the
     846        merging of differencing media was started.
     847      </desc>
     848    </const>
     849    <const name="RestoringSnapshot"         value="20">
    852850      <desc>
    853851        A machine snapshot is being restored; this typically does not take long.
    854852      </desc>
    855853    </const>
    856     <const name="DeletingSnapshot"          value="20">
     854    <const name="DeletingSnapshot"          value="21">
    857855      <desc>
    858856        A machine snapshot is being deleted; this can take a long time since this
     
    861859      </desc>
    862860    </const>
    863     <const name="SettingUp"                 value="21">
     861    <const name="SettingUp"                 value="22">
    864862      <desc>
    865863        Lengthy setup operation is in progress.
    866864      </desc>
    867865    </const>
     866    <const name="Snapshotting"              value="23">
     867      <desc>
     868        Taking an (offline) snapshot.
     869      </desc>
     870    </const>
    868871
    869872    <const name="FirstOnline" value="5" wsmap="suppress"> <!-- Running -->
     
    872875      </desc>
    873876    </const>
    874     <const name="LastOnline" value="18" wsmap="suppress"> <!-- DeletingSnapshotPaused -->
     877    <const name="LastOnline" value="19" wsmap="suppress"> <!-- OnlineSnapshotting -->
    875878      <desc>
    876879        Pseudo-state: last online state (for use in relational expressions).
     
    883886      </desc>
    884887    </const>
    885     <const name="LastTransient" value="21" wsmap="suppress"> <!-- SettingUp -->
     888    <const name="LastTransient" value="23" wsmap="suppress"> <!-- Snapshotting -->
    886889      <desc>
    887890        Pseudo-state: last transient state (for use in relational expressions).
     
    10741077  <enum
    10751078    name="LockType"
    1076     uuid="168a6a8e-12fd-4878-a1f9-38a750a56089"
     1079    uuid="678aaf14-2815-4c3e-b20a-e86ed0216498"
    10771080    >
    10781081    <desc>
    10791082      Used with <link to="IMachine::lockMachine" />.
    10801083    </desc>
     1084    <const name="Null" value="0">
     1085      <desc>Placeholder value, do not use when obtaining a lock.</desc>
     1086    </const>
     1087    <const name="Shared" value="1">
     1088      <desc>Request only a shared lock for remote-controlling the machine.
     1089        Such a lock allows changing certain VM settings which can be safely
     1090        modified for a running VM.</desc>
     1091    </const>
    10811092    <const name="Write" value="2">
    10821093      <desc>Lock the machine for writing. This requests an exclusive lock, i.e.
     
    10851096        which implicitly holds the equivalent of a shared lock during the
    10861097        entire VM runtime.</desc>
    1087     </const>
    1088     <const name="Shared" value="1">
    1089       <desc>Request only a shared lock for remote-controlling the machine.
    1090         Such a lock allows changing certain VM settings which can be safely
    1091         modified for a running VM.</desc>
    10921098    </const>
    10931099    <const name="VM" value="3">
     
    35863592  <interface
    35873593    name="IInternalMachineControl" extends="$unknown"
    3588     uuid="1470ff16-d7fa-448e-9c38-0352a36053bf"
     3594    uuid="f0b3bf6e-c609-4d5e-9fd7-77537a52c31b"
    35893595    internal="yes"
    35903596    wsmap="suppress"
    35913597    >
    3592     <method name="setRemoveSavedStateFile">
    3593       <desc>
    3594         Updates the flag whether the saved state file is removed on a
    3595         machine state change from Saved to PoweredOff.
    3596       </desc>
    3597       <param name="remove" type="boolean" dir="in"/>
    3598     </method>
    35993598
    36003599    <method name="updateState">
     
    37583757    </method>
    37593758
    3760     <method name="beginSavingState">
    3761       <desc>
    3762         Called by the VM process to inform the server it wants to
    3763         save the current state and stop the VM execution.
    3764       </desc>
    3765       <param name="progress" type="IProgress" dir="out">
    3766         <desc>
    3767           Progress object created by VBoxSVC to wait until
    3768           the state is saved.
    3769         </desc>
    3770       </param>
    3771       <param name="stateFilePath" type="wstring" dir="out">
    3772         <desc>
    3773           File path the VM process must save the execution state to.
    3774         </desc>
    3775       </param>
    3776     </method>
    3777 
    3778     <method name="endSavingState">
    3779       <desc>
    3780         Called by the VM process to inform the server that saving
    3781         the state previously requested by #beginSavingState is either
    3782         successfully finished or there was a failure.
    3783 
    3784         <result name="VBOX_E_FILE_ERROR">
    3785           Settings file not accessible.
    3786         </result>
    3787         <result name="VBOX_E_XML_ERROR">
    3788           Could not parse the settings file.
    3789         </result>
    3790 
    3791       </desc>
    3792 
    3793       <param name="result" type="long" dir="in">
    3794         <desc>@c S_OK to indicate success.
    3795         </desc>
    3796       </param>
    3797       <param name="errMsg" type="wstring" dir="in">
    3798         <desc>@c human readable error message in case of failure.
    3799         </desc>
    3800       </param>
    3801     </method>
    3802 
    3803     <method name="adoptSavedState">
    3804       <desc>
    3805         Gets called by <link to="IConsole::adoptSavedState"/>.
    3806         <result name="VBOX_E_FILE_ERROR">
    3807           Invalid saved state file path.
    3808         </result>
    3809       </desc>
    3810       <param name="savedStateFile" type="wstring" dir="in">
    3811         <desc>Path to the saved state file to adopt.</desc>
    3812       </param>
    3813     </method>
    3814 
    3815     <method name="beginTakingSnapshot">
    3816       <desc>
    3817         Called from the VM process to request from the server to perform the
    3818         server-side actions of creating a snapshot (creating differencing images
    3819         and the snapshot object).
    3820 
    3821         <result name="VBOX_E_FILE_ERROR">
    3822           Settings file not accessible.
    3823         </result>
    3824         <result name="VBOX_E_XML_ERROR">
    3825           Could not parse the settings file.
    3826         </result>
    3827       </desc>
    3828       <param name="initiator" type="IConsole" dir="in">
    3829         <desc>The console object that initiated this call.</desc>
    3830       </param>
    3831       <param name="name" type="wstring" dir="in">
    3832         <desc>Snapshot name.</desc>
    3833       </param>
    3834       <param name="description" type="wstring" dir="in">
    3835         <desc>Snapshot description.</desc>
    3836       </param>
    3837       <param name="consoleProgress" type="IProgress" dir="in">
    3838         <desc>
    3839           Progress object created by the VM process tracking the
    3840           snapshot's progress. This has the following sub-operations:
    3841           <ul>
    3842             <li>setting up (weight 1);</li>
    3843             <li>one for each medium attachment that needs a differencing image (weight 1 each);</li>
    3844             <li>another one to copy the VM state (if offline with saved state, weight is VM memory size in MB);</li>
    3845             <li>another one to save the VM state (if online, weight is VM memory size in MB);</li>
    3846             <li>finishing up (weight 1)</li>
    3847           </ul>
    3848         </desc>
    3849       </param>
    3850       <param name="fTakingSnapshotOnline" type="boolean" dir="in">
    3851         <desc>
    3852           Whether this is an online snapshot (i.e. the machine is running).
    3853         </desc>
    3854       </param>
    3855       <param name="stateFilePath" type="wstring" dir="out">
    3856         <desc>
    3857           File path the VM process must save the execution state to.
    3858         </desc>
    3859       </param>
    3860     </method>
    3861 
    3862     <method name="endTakingSnapshot">
    3863       <desc>
    3864         Called by the VM process to inform the server that the snapshot
    3865         previously requested by #beginTakingSnapshot is either
    3866         successfully taken or there was a failure.
    3867       </desc>
    3868 
    3869       <param name="success" type="boolean" dir="in">
    3870         <desc>@c true to indicate success and @c false otherwise</desc>
    3871       </param>
    3872     </method>
    3873 
    3874     <method name="deleteSnapshot">
    3875       <desc>
    3876         Gets called by <link to="IConsole::deleteSnapshot"/>,
    3877         <link to="IConsole::deleteSnapshotAndAllChildren"/> and
    3878         <link to="IConsole::deleteSnapshotRange"/>.
    3879         <result name="VBOX_E_INVALID_OBJECT_STATE">
    3880           Snapshot has more than one child snapshot. Only possible if the
    3881           delete operation does not delete all children or the range does
    3882           not meet the linearity condition.
    3883         </result>
    3884       </desc>
    3885       <param name="initiator" type="IConsole" dir="in">
    3886         <desc>The console object that initiated this call.</desc>
    3887       </param>
    3888       <param name="startId" type="uuid" mod="string" dir="in">
    3889         <desc>UUID of the first snapshot to delete.</desc>
    3890       </param>
    3891       <param name="endId" type="uuid" mod="string" dir="in">
    3892         <desc>UUID of the last snapshot to delete.</desc>
    3893       </param>
    3894       <param name="deleteAllChildren" type="boolean" dir="in">
    3895         <desc>Whether all children should be deleted.</desc>
    3896       </param>
    3897       <param name="machineState" type="MachineState" dir="out">
    3898         <desc>New machine state after this operation is started.</desc>
    3899       </param>
    3900       <param name="progress" type="IProgress" dir="return">
    3901         <desc>Progress object to track the operation completion.</desc>
    3902       </param>
    3903     </method>
    3904 
    39053759    <method name="finishOnlineMergeMedium">
    39063760      <desc>
     
    39083762        All necessary state information is available at the called object.
    39093763      </desc>
    3910     </method>
    3911 
    3912     <method name="restoreSnapshot">
    3913       <desc>
    3914         Gets called by <link to="IConsole::restoreSnapshot"/>.
    3915       </desc>
    3916       <param name="initiator" type="IConsole" dir="in">
    3917         <desc>The console object that initiated this call.</desc>
    3918       </param>
    3919       <param name="snapshot" type="ISnapshot" dir="in">
    3920         <desc>The snapshot to restore the VM state from.</desc>
    3921       </param>
    3922       <param name="machineState" type="MachineState" dir="out">
    3923         <desc>New machine state after this operation is started.</desc>
    3924       </param>
    3925       <param name="progress" type="IProgress" dir="return">
    3926         <desc>Progress object to track the operation completion.</desc>
    3927       </param>
    39283764    </method>
    39293765
     
    43414177  <interface
    43424178    name="IMachine" extends="$unknown"
    4343     uuid="2280b3f8-0c33-4641-8bd5-ccecd1071b49"
     4179    uuid="bfe5287a-5fbc-4ceb-9f0e-7fb317e78681"
    43444180    wsmap="managed"
    43454181    wrap-hint-server-addinterfaces="IInternalMachineControl"
     
    48884724        Current snapshot of this machine. This is @c null if the machine
    48894725        currently has no snapshots. If it is not @c null, then it was
    4890         set by one of <link to="IConsole::takeSnapshot" />,
    4891         <link to="IConsole::deleteSnapshot" />
    4892         or <link to="IConsole::restoreSnapshot" />, depending on which
    4893         was called last. See <link to="ISnapshot"/> for details.
     4726        set by one of <link to="#takeSnapshot" />, <link to="#deleteSnapshot" />
     4727        or <link to="#restoreSnapshot" />, depending on which was called last.
     4728       See <link to="ISnapshot"/> for details.
    48944729      </desc>
    48954730    </attribute>
     
    49114746
    49124747        <ul>
    4913           <li><link to="IConsole::restoreSnapshot"/>
     4748          <li><link to="#restoreSnapshot"/>
    49144749          </li>
    4915           <li><link to="IConsole::takeSnapshot"/> (issued on a
    4916             "powered off" or "saved" machine, for which
    4917             <link to="#settingsModified"/> returns @c false)
     4750          <li><link to="#takeSnapshot"/> (issued on a "powered off" or "saved"
     4751            machine, for which <link to="#settingsModified"/> returns @c false)
    49184752          </li>
    49194753        </ul>
     
    74327266    </method>
    74337267
    7434   </interface>
    7435 
    7436   <interface
    7437     name="IEmulatedUSB" extends="$unknown"
    7438     uuid="38cc4dfd-8bb2-4d40-aebe-699eead8c2dd"
    7439     wsmap="managed"
    7440     >
    7441     <desc>
    7442       Manages emulated USB devices.
    7443     </desc>
    7444 
    7445     <method name="webcamAttach">
    7446       <desc>
    7447         Attaches the emulated USB webcam to the VM, which will use a host video capture device.
    7448       </desc>
    7449       <param name="path" type="wstring" dir="in">
    7450         <desc>The host path of the capture device to use.</desc>
    7451       </param>
    7452       <param name="settings" type="wstring" dir="in">
    7453         <desc>Optional settings.</desc>
    7454       </param>
    7455     </method>
    7456 
    7457     <method name="webcamDetach">
    7458       <desc>
    7459         Detaches the emulated USB webcam from the VM
    7460       </desc>
    7461       <param name="path" type="wstring" dir="in">
    7462         <desc>The host path of the capture device to detach.</desc>
    7463       </param>
    7464     </method>
    7465 
    7466     <attribute name="webcams" type="wstring" safearray="yes" readonly="yes">
    7467       <desc>Lists attached virtual webcams.</desc>
    7468     </attribute>
    7469   </interface>
    7470 
    7471   <!--
    7472   // IConsole
    7473   /////////////////////////////////////////////////////////////////////////
    7474   -->
    7475 
    7476   <interface
    7477     name="IVRDEServerInfo" extends="$unknown"
    7478     uuid="714434a1-58c3-4aab-9049-7652c5df113b"
    7479     wsmap="struct"
    7480     >
    7481     <desc>
    7482       Contains information about the remote desktop (VRDE) server capabilities and status.
    7483       This is used in the <link to="IConsole::VRDEServerInfo" /> attribute.
    7484     </desc>
    7485 
    7486     <attribute name="active" type="boolean" readonly="yes">
    7487       <desc>
    7488         Whether the remote desktop connection is active.
    7489       </desc>
    7490     </attribute>
    7491 
    7492     <attribute name="port" type="long" readonly="yes">
    7493       <desc>
    7494         VRDE server port number. If this property is equal to <tt>0</tt>, then
    7495         the VRDE server failed to start, usually because there are no free IP
    7496         ports to bind to. If this property is equal to <tt>-1</tt>, then the VRDE
    7497         server has not yet been started.
    7498       </desc>
    7499     </attribute>
    7500 
    7501     <attribute name="numberOfClients" type="unsigned long" readonly="yes">
    7502       <desc>
    7503         How many times a client connected.
    7504       </desc>
    7505     </attribute>
    7506 
    7507     <attribute name="beginTime" type="long long" readonly="yes">
    7508       <desc>
    7509         When the last connection was established, in milliseconds since 1970-01-01 UTC.
    7510       </desc>
    7511     </attribute>
    7512 
    7513     <attribute name="endTime" type="long long" readonly="yes">
    7514       <desc>
    7515         When the last connection was terminated or the current time, if
    7516         connection is still active, in milliseconds since 1970-01-01 UTC.
    7517       </desc>
    7518     </attribute>
    7519 
    7520     <attribute name="bytesSent" type="long long" readonly="yes">
    7521       <desc>
    7522         How many bytes were sent in last or current, if still active, connection.
    7523       </desc>
    7524     </attribute>
    7525 
    7526     <attribute name="bytesSentTotal" type="long long" readonly="yes">
    7527       <desc>
    7528         How many bytes were sent in all connections.
    7529       </desc>
    7530     </attribute>
    7531 
    7532     <attribute name="bytesReceived" type="long long" readonly="yes">
    7533       <desc>
    7534         How many bytes were received in last or current, if still active, connection.
    7535       </desc>
    7536     </attribute>
    7537 
    7538     <attribute name="bytesReceivedTotal" type="long long" readonly="yes">
    7539       <desc>
    7540         How many bytes were received in all connections.
    7541       </desc>
    7542     </attribute>
    7543 
    7544     <attribute name="user" type="wstring" readonly="yes">
    7545       <desc>
    7546         Login user name supplied by the client.
    7547       </desc>
    7548     </attribute>
    7549 
    7550     <attribute name="domain" type="wstring" readonly="yes">
    7551       <desc>
    7552         Login domain name supplied by the client.
    7553       </desc>
    7554     </attribute>
    7555 
    7556     <attribute name="clientName" type="wstring" readonly="yes">
    7557       <desc>
    7558         The client name supplied by the client.
    7559       </desc>
    7560     </attribute>
    7561 
    7562     <attribute name="clientIP" type="wstring" readonly="yes">
    7563       <desc>
    7564         The IP address of the client.
    7565       </desc>
    7566     </attribute>
    7567 
    7568     <attribute name="clientVersion" type="unsigned long" readonly="yes">
    7569       <desc>
    7570         The client software version number.
    7571       </desc>
    7572     </attribute>
    7573 
    7574     <attribute name="encryptionStyle" type="unsigned long" readonly="yes">
    7575       <desc>
    7576         Public key exchange method used when connection was established.
    7577         Values: 0 - RDP4 public key exchange scheme.
    7578         1 - X509 certificates were sent to client.
    7579       </desc>
    7580     </attribute>
    7581 
    7582   </interface>
    7583 
    7584   <interface
    7585     name="IConsole" extends="$unknown"
    7586     uuid="080505f4-bca9-45aa-ab95-030036b665e6"
    7587     wsmap="managed"
    7588     >
    7589     <desc>
    7590       The IConsole interface represents an interface to control virtual
    7591       machine execution.
    7592 
    7593       A console object gets created when a machine has been locked for a
    7594       particular session (client process) using <link to="IMachine::lockMachine" />
    7595       or <link to="IMachine::launchVMProcess"/>. The console object can
    7596       then be found in the session's <link to="ISession::console" /> attribute.
    7597 
    7598       Methods of the IConsole interface allow the caller to query the current
    7599       virtual machine execution state, pause the machine or power it down, save
    7600       the machine state or take a snapshot, attach and detach removable media
    7601       and so on.
    7602 
    7603       <see><link to="ISession"/></see>
    7604     </desc>
    7605 
    7606     <attribute name="machine" type="IMachine" readonly="yes">
    7607       <desc>
    7608         Machine object for this console session.
    7609         <note>
    7610           This is a convenience property, it has the same value as
    7611           <link to="ISession::machine"/> of the corresponding session
    7612           object.
    7613         </note>
    7614       </desc>
    7615     </attribute>
    7616 
    7617     <attribute name="state" type="MachineState" readonly="yes">
    7618       <desc>
    7619         Current execution state of the machine.
    7620         <note>
    7621           This property always returns the same value as the corresponding
    7622           property of the IMachine object for this console session.
    7623           For the process that owns (executes) the VM, this is the
    7624           preferable way of querying the VM state, because no IPC
    7625           calls are made.
    7626         </note>
    7627       </desc>
    7628     </attribute>
    7629 
    7630     <attribute name="guest" type="IGuest" readonly="yes">
    7631       <desc>Guest object.</desc>
    7632     </attribute>
    7633 
    7634     <attribute name="keyboard" type="IKeyboard" readonly="yes">
    7635       <desc>
    7636         Virtual keyboard object.
    7637         <note>
    7638           If the machine is not running, any attempt to use
    7639           the returned object will result in an error.
    7640         </note>
    7641       </desc>
    7642     </attribute>
    7643 
    7644     <attribute name="mouse" type="IMouse" readonly="yes">
    7645       <desc>
    7646         Virtual mouse object.
    7647         <note>
    7648           If the machine is not running, any attempt to use
    7649           the returned object will result in an error.
    7650         </note>
    7651       </desc>
    7652     </attribute>
    7653 
    7654     <attribute name="display" type="IDisplay" readonly="yes">
    7655       <desc>Virtual display object.
    7656         <note>
    7657           If the machine is not running, any attempt to use
    7658           the returned object will result in an error.
    7659         </note>
    7660       </desc>
    7661     </attribute>
    7662 
    7663     <attribute name="debugger" type="IMachineDebugger" readonly="yes">
    7664       <desc>Debugging interface.</desc>
    7665     </attribute>
    7666 
    7667     <attribute name="USBDevices" type="IUSBDevice" readonly="yes" safearray="yes">
    7668       <desc>
    7669         Collection of USB devices currently attached to the virtual
    7670         USB controller.
    7671         <note>
    7672           The collection is empty if the machine is not running.
    7673         </note>
    7674       </desc>
    7675     </attribute>
    7676 
    7677     <attribute name="remoteUSBDevices" type="IHostUSBDevice" readonly="yes" safearray="yes">
    7678       <desc>
    7679         List of USB devices currently attached to the remote VRDE client.
    7680         Once a new device is physically attached to the remote host computer,
    7681         it appears in this list and remains there until detached.
    7682       </desc>
    7683     </attribute>
    7684 
    7685     <attribute name="sharedFolders" type="ISharedFolder" readonly="yes" safearray="yes">
    7686       <desc>
    7687         Collection of shared folders for the current session. These folders
    7688         are called transient shared folders because they are available to the
    7689         guest OS running inside the associated virtual machine only for the
    7690         duration of the session (as opposed to
    7691         <link to="IMachine::sharedFolders"/> which represent permanent shared
    7692         folders). When the session is closed (e.g. the machine is powered down),
    7693         these folders are automatically discarded.
    7694 
    7695         New shared folders are added to the collection using
    7696         <link to="#createSharedFolder"/>. Existing shared folders can be
    7697         removed using <link to="#removeSharedFolder"/>.
    7698       </desc>
    7699     </attribute>
    7700 
    7701     <attribute name="VRDEServerInfo" type="IVRDEServerInfo" readonly="yes">
    7702       <desc>
    7703         Interface that provides information on Remote Desktop Extension (VRDE) connection.
    7704       </desc>
    7705     </attribute>
    7706 
    7707     <attribute name="eventSource" type="IEventSource" readonly="yes">
    7708       <desc>
    7709         Event source for console events.
    7710       </desc>
    7711     </attribute>
    7712 
    7713     <attribute name="attachedPCIDevices" type="IPCIDeviceAttachment" readonly="yes" safearray="yes">
    7714       <desc>Array of PCI devices attached to this machine.</desc>
    7715     </attribute>
    7716 
    7717     <attribute name="useHostClipboard" type="boolean">
    7718       <desc>
    7719         Whether the guest clipboard should be connected to the host one or
    7720         whether it should only be allowed access to the VRDE clipboard. This
    7721         setting may not affect existing guest clipboard connections which
    7722         are already connected to the host clipboard.
    7723       </desc>
    7724     </attribute>
    7725 
    7726     <attribute name="emulatedUSB" type="IEmulatedUSB" readonly="yes">
    7727       <desc>
    7728         Interface that manages emulated USB devices.
    7729       </desc>
    7730     </attribute>
    7731 
    7732     <method name="powerUp">
    7733       <desc>
    7734         Starts the virtual machine execution using the current machine
    7735         state (that is, its current execution state, current settings and
    7736         current storage devices).
    7737 
    7738         <note>
    7739           This method is only useful for front-ends that want to actually
    7740           execute virtual machines in their own process (like the VirtualBox
    7741           or VBoxSDL front-ends). Unless you are intending to write such a
    7742           front-end, do not call this method. If you simply want to
    7743           start virtual machine execution using one of the existing front-ends
    7744           (for example the VirtualBox GUI or headless server), use
    7745           <link to="IMachine::launchVMProcess"/> instead; these
    7746           front-ends will power up the machine automatically for you.
    7747         </note>
    7748 
    7749         If the machine is powered off or aborted, the execution will
    7750         start from the beginning (as if the real hardware were just
    7751         powered on).
    7752 
    7753         If the machine is in the <link to="MachineState_Saved"/> state,
    7754         it will continue its execution the point where the state has
    7755         been saved.
    7756 
    7757         If the machine <link to="IMachine::teleporterEnabled"/> property is
    7758         enabled on the machine being powered up, the machine will wait for an
    7759         incoming teleportation in the <link to="MachineState_TeleportingIn"/>
    7760         state. The returned progress object will have at least three
    7761         operations where the last three are defined as: (1) powering up and
    7762         starting TCP server, (2) waiting for incoming teleportations, and
    7763         (3) perform teleportation. These operations will be reflected as the
    7764         last three operations of the progress objected returned by
    7765         <link to="IMachine::launchVMProcess"/> as well.
    7766 
    7767         <see><link to="#saveState"/></see>
    7768 
    7769         <result name="VBOX_E_INVALID_VM_STATE">
    7770           Virtual machine already running.
    7771         </result>
    7772         <result name="VBOX_E_HOST_ERROR">
    7773           Host interface does not exist or name not set.
    7774         </result>
    7775         <result name="VBOX_E_FILE_ERROR">
    7776           Invalid saved state file.
    7777         </result>
    7778       </desc>
    7779       <param name="progress" type="IProgress" dir="return">
    7780         <desc>Progress object to track the operation completion.</desc>
    7781       </param>
    7782     </method>
    7783 
    7784     <method name="powerUpPaused">
    7785       <desc>
    7786         Identical to powerUp except that the VM will enter the
    7787         <link to="MachineState_Paused"/> state, instead of
    7788         <link to="MachineState_Running"/>.
    7789 
    7790         <see><link to="#powerUp"/></see>
    7791         <result name="VBOX_E_INVALID_VM_STATE">
    7792           Virtual machine already running.
    7793         </result>
    7794         <result name="VBOX_E_HOST_ERROR">
    7795           Host interface does not exist or name not set.
    7796         </result>
    7797         <result name="VBOX_E_FILE_ERROR">
    7798           Invalid saved state file.
    7799         </result>
    7800       </desc>
    7801       <param name="progress" type="IProgress" dir="return">
    7802         <desc>Progress object to track the operation completion.</desc>
    7803       </param>
    7804     </method>
    7805 
    7806     <method name="powerDown">
    7807       <desc>
    7808         Initiates the power down procedure to stop the virtual machine
    7809         execution.
    7810 
    7811         The completion of the power down procedure is tracked using the returned
    7812         IProgress object. After the operation is complete, the machine will go
    7813         to the PoweredOff state.
    7814         <result name="VBOX_E_INVALID_VM_STATE">
    7815           Virtual machine must be Running, Paused or Stuck to be powered down.
    7816         </result>
    7817       </desc>
    7818       <param name="progress" type="IProgress" dir="return">
    7819         <desc>Progress object to track the operation completion.</desc>
    7820       </param>
    7821     </method>
    7822 
    7823     <method name="reset">
    7824       <desc>Resets the virtual machine.
    7825         <result name="VBOX_E_INVALID_VM_STATE">
    7826           Virtual machine not in Running state.
    7827         </result>
    7828         <result name="VBOX_E_VM_ERROR">
    7829           Virtual machine error in reset operation.
    7830         </result>
    7831       </desc>
    7832     </method>
    7833 
    7834     <method name="pause">
    7835       <desc>Pauses the virtual machine execution.
    7836         <result name="VBOX_E_INVALID_VM_STATE">
    7837           Virtual machine not in Running state.
    7838         </result>
    7839         <result name="VBOX_E_VM_ERROR">
    7840           Virtual machine error in suspend operation.
    7841         </result>
    7842       </desc>
    7843     </method>
    7844 
    7845     <method name="resume">
    7846       <desc>Resumes the virtual machine execution.
    7847         <result name="VBOX_E_INVALID_VM_STATE">
    7848           Virtual machine not in Paused state.
    7849         </result>
    7850         <result name="VBOX_E_VM_ERROR">
    7851           Virtual machine error in resume operation.
    7852         </result>
    7853       </desc>
    7854     </method>
    7855 
    7856     <method name="powerButton">
    7857       <desc>Sends the ACPI power button event to the guest.
    7858         <result name="VBOX_E_INVALID_VM_STATE">
    7859           Virtual machine not in Running state.
    7860         </result>
    7861         <result name="VBOX_E_PDM_ERROR">
    7862           Controlled power off failed.
    7863         </result>
    7864       </desc>
    7865     </method>
    7866 
    7867     <method name="sleepButton">
    7868       <desc>Sends the ACPI sleep button event to the guest.
    7869         <result name="VBOX_E_INVALID_VM_STATE">
    7870           Virtual machine not in Running state.
    7871         </result>
    7872         <result name="VBOX_E_PDM_ERROR">
    7873           Sending sleep button event failed.
    7874         </result>
    7875       </desc>
    7876     </method>
    7877 
    7878     <method name="getPowerButtonHandled">
    7879       <desc>Checks if the last power button event was handled by guest.
    7880         <result name="VBOX_E_PDM_ERROR">
    7881           Checking if the event was handled by the guest OS failed.
    7882         </result>
    7883       </desc>
    7884       <param name="handled" type="boolean" dir="return"/>
    7885     </method>
    7886 
    7887     <method name="getGuestEnteredACPIMode">
    7888       <desc>Checks if the guest entered the ACPI mode G0 (working) or
    7889         G1 (sleeping). If this method returns @c false, the guest will
    7890         most likely not respond to external ACPI events.
    7891         <result name="VBOX_E_INVALID_VM_STATE">
    7892           Virtual machine not in Running state.
    7893         </result>
    7894       </desc>
    7895       <param name="entered" type="boolean" dir="return"/>
    7896     </method>
    7897 
    78987268    <method name="saveState">
    78997269      <desc>
     
    79147284        <note>
    79157285          On success, this method implicitly calls
    7916           <link to="IMachine::saveSettings"/> to save all current machine
     7286          <link to="#saveSettings"/> to save all current machine
    79177287          settings (including runtime changes to the DVD medium, etc.).
    79187288          Together with the impossibility to change any VM settings when it is
     
    79517321        The specified saved state file path may be absolute or relative to the
    79527322        folder the VM normally saves the state to (usually,
    7953         <link to="IMachine::snapshotFolder"/>).
     7323        <link to="#snapshotFolder"/>).
    79547324
    79557325        <note>
     
    79857355        re-inserted into a machine using <link to="#adoptSavedState" />.
    79867356        The location of the file can be found in the
    7987         <link to="IMachine::stateFilePath" /> attribute.
     7357        <link to="#stateFilePath" /> attribute.
    79887358        <result name="VBOX_E_INVALID_VM_STATE">
    79897359          Virtual machine not in state Saved.
     
    79927362      <param name="fRemoveFile" type="boolean" dir="in" >
    79937363        <desc>Whether to also remove the saved state file.</desc>
    7994       </param>
    7995     </method>
    7996 
    7997     <method name="getDeviceActivity">
    7998       <desc>
    7999         Gets the current activity type of given devices or device groups.
    8000         <result name="E_INVALIDARG">
    8001           Invalid device type.
    8002         </result>
    8003       </desc>
    8004       <param name="type" type="DeviceType" safearray="yes" dir="in"/>
    8005       <param name="activity" type="DeviceActivity" safearray="yes" dir="return"/>
    8006     </method>
    8007 
    8008     <method name="attachUSBDevice">
    8009       <desc>
    8010         Attaches a host USB device with the given UUID to the
    8011         USB controller of the virtual machine.
    8012 
    8013         The device needs to be in one of the following states:
    8014         <link to="USBDeviceState_Busy"/>,
    8015         <link to="USBDeviceState_Available"/> or
    8016         <link to="USBDeviceState_Held"/>,
    8017         otherwise an error is immediately returned.
    8018 
    8019         When the device state is
    8020         <link to="USBDeviceState_Busy">Busy</link>, an error may also
    8021         be returned if the host computer refuses to release it for some reason.
    8022 
    8023         <see><link to="IUSBDeviceFilters::deviceFilters"/>,
    8024           <link to="USBDeviceState"/></see>
    8025         <result name="VBOX_E_INVALID_VM_STATE">
    8026           Virtual machine state neither Running nor Paused.
    8027         </result>
    8028         <result name="VBOX_E_PDM_ERROR">
    8029           Virtual machine does not have a USB controller.
    8030         </result>
    8031       </desc>
    8032       <param name="id" type="uuid" mod="string" dir="in">
    8033         <desc>UUID of the host USB device to attach.</desc>
    8034       </param>
    8035       <param name="captureFilename" type="wstring" dir="in">
    8036         <desc>Filename to capture the USB traffic to.</desc>
    8037       </param>
    8038     </method>
    8039 
    8040     <method name="detachUSBDevice">
    8041       <desc>
    8042         Detaches an USB device with the given UUID from the USB controller
    8043         of the virtual machine.
    8044 
    8045         After this method succeeds, the VirtualBox server re-initiates
    8046         all USB filters as if the device were just physically attached
    8047         to the host, but filters of this machine are ignored to avoid
    8048         a possible automatic re-attachment.
    8049 
    8050         <see><link to="IUSBDeviceFilters::deviceFilters"/>,
    8051           <link to="USBDeviceState"/></see>
    8052 
    8053         <result name="VBOX_E_PDM_ERROR">
    8054           Virtual machine does not have a USB controller.
    8055         </result>
    8056         <result name="E_INVALIDARG">
    8057           USB device not attached to this virtual machine.
    8058         </result>
    8059       </desc>
    8060       <param name="id" type="uuid" mod="string" dir="in">
    8061         <desc>UUID of the USB device to detach.</desc>
    8062       </param>
    8063       <param name="device" type="IUSBDevice" dir="return">
    8064         <desc>Detached USB device.</desc>
    8065       </param>
    8066     </method>
    8067 
    8068     <method name="findUSBDeviceByAddress">
    8069       <desc>
    8070         Searches for a USB device with the given host address.
    8071 
    8072         <result name="VBOX_E_OBJECT_NOT_FOUND">
    8073           Given @c name does not correspond to any USB device.
    8074         </result>
    8075 
    8076         <see><link to="IUSBDevice::address"/></see>
    8077       </desc>
    8078       <param name="name" type="wstring" dir="in">
    8079         <desc>
    8080           Address of the USB device (as assigned by the host) to
    8081           search for.
    8082         </desc>
    8083       </param>
    8084       <param name="device" type="IUSBDevice" dir="return">
    8085         <desc>Found USB device object.</desc>
    8086       </param>
    8087     </method>
    8088 
    8089     <method name="findUSBDeviceById">
    8090       <desc>
    8091         Searches for a USB device with the given UUID.
    8092 
    8093         <result name="VBOX_E_OBJECT_NOT_FOUND">
    8094           Given @c id does not correspond to any USB device.
    8095         </result>
    8096 
    8097         <see><link to="IUSBDevice::id"/></see>
    8098       </desc>
    8099       <param name="id" type="uuid" mod="string" dir="in">
    8100         <desc>UUID of the USB device to search for.</desc>
    8101       </param>
    8102       <param name="device" type="IUSBDevice" dir="return">
    8103         <desc>Found USB device object.</desc>
    8104       </param>
    8105     </method>
    8106 
    8107     <method name="createSharedFolder">
    8108       <desc>
    8109         Creates a transient new shared folder by associating the given logical
    8110         name with the given host path, adds it to the collection of shared
    8111         folders and starts sharing it. Refer to the description of
    8112         <link to="ISharedFolder"/> to read more about logical names.
    8113 
    8114         <result name="VBOX_E_INVALID_VM_STATE">
    8115           Virtual machine in Saved state or currently changing state.
    8116         </result>
    8117         <result name="VBOX_E_FILE_ERROR">
    8118           Shared folder already exists or not accessible.
    8119         </result>
    8120       </desc>
    8121       <param name="name" type="wstring" dir="in">
    8122         <desc>Unique logical name of the shared folder.</desc>
    8123       </param>
    8124       <param name="hostPath" type="wstring" dir="in">
    8125         <desc>Full path to the shared folder in the host file system.</desc>
    8126       </param>
    8127       <param name="writable" type="boolean" dir="in">
    8128         <desc>Whether the share is writable or readonly</desc>
    8129       </param>
    8130       <param name="automount" type="boolean" dir="in">
    8131         <desc>Whether the share gets automatically mounted by the guest
    8132           or not.</desc>
    8133       </param>
    8134     </method>
    8135 
    8136     <method name="removeSharedFolder">
    8137       <desc>
    8138         Removes a transient shared folder with the given name previously
    8139         created by <link to="#createSharedFolder"/> from the collection of
    8140         shared folders and stops sharing it.
    8141         <result name="VBOX_E_INVALID_VM_STATE">
    8142           Virtual machine in Saved state or currently changing state.
    8143         </result>
    8144         <result name="VBOX_E_FILE_ERROR">
    8145           Shared folder does not exists.
    8146         </result>
    8147       </desc>
    8148       <param name="name" type="wstring" dir="in">
    8149         <desc>Logical name of the shared folder to remove.</desc>
    81507364      </param>
    81517365    </method>
     
    81657379
    81667380        The taken snapshot is always based on the
    8167         <link to="IMachine::currentSnapshot">current snapshot</link>
     7381        <link to="#currentSnapshot">current snapshot</link>
    81687382        of the associated virtual machine and becomes a new current snapshot.
    81697383
    81707384        <note>
    8171           This method implicitly calls <link to="IMachine::saveSettings"/> to
     7385          This method implicitly calls <link to="#saveSettings"/> to
    81727386          save all current machine settings before taking an offline snapshot.
    81737387        </note>
     
    81827396      <param name="description" type="wstring" dir="in">
    81837397        <desc>Optional description of the snapshot.</desc>
     7398      </param>
     7399      <param name="pause" type="boolean" dir="in">
     7400        <desc>Whether the VM should be paused while taking the snapshot. Only
     7401          relevant when the VM is running, and distinguishes between online
     7402          (@c true) and live (@c false) snapshots. When the VM is not running
     7403          the result is always an offline snapshot.</desc>
    81847404      </param>
    81857405      <param name="progress" type="IProgress" dir="return">
     
    82107430        If the deleted snapshot is the first or current snapshot, then the
    82117431        respective IMachine attributes will be adjusted. Deleting the current
    8212         snapshot will also implicitly call <link to="IMachine::saveSettings"/>
     7432        snapshot will also implicitly call <link to="#saveSettings"/>
    82137433        to make all current machine settings permanent.
    82147434
     
    82337453        </ul>
    82347454
    8235         The virtual machine's <link to="IMachine::state">state</link> is
     7455        The virtual machine's <link to="#state">state</link> is
    82367456        changed to "DeletingSnapshot", "DeletingSnapshotOnline" or
    82377457        "DeletingSnapshotPaused" while this operation is in progress.
     
    83667586      <param name="progress" type="IProgress" dir="return">
    83677587        <desc>Progress object to track the operation completion.</desc>
     7588      </param>
     7589    </method>
     7590
     7591  </interface>
     7592
     7593  <interface
     7594    name="IEmulatedUSB" extends="$unknown"
     7595    uuid="38cc4dfd-8bb2-4d40-aebe-699eead8c2dd"
     7596    wsmap="managed"
     7597    >
     7598    <desc>
     7599      Manages emulated USB devices.
     7600    </desc>
     7601
     7602    <method name="webcamAttach">
     7603      <desc>
     7604        Attaches the emulated USB webcam to the VM, which will use a host video capture device.
     7605      </desc>
     7606      <param name="path" type="wstring" dir="in">
     7607        <desc>The host path of the capture device to use.</desc>
     7608      </param>
     7609      <param name="settings" type="wstring" dir="in">
     7610        <desc>Optional settings.</desc>
     7611      </param>
     7612    </method>
     7613
     7614    <method name="webcamDetach">
     7615      <desc>
     7616        Detaches the emulated USB webcam from the VM
     7617      </desc>
     7618      <param name="path" type="wstring" dir="in">
     7619        <desc>The host path of the capture device to detach.</desc>
     7620      </param>
     7621    </method>
     7622
     7623    <attribute name="webcams" type="wstring" safearray="yes" readonly="yes">
     7624      <desc>Lists attached virtual webcams.</desc>
     7625    </attribute>
     7626  </interface>
     7627
     7628  <!--
     7629  // IConsole
     7630  /////////////////////////////////////////////////////////////////////////
     7631  -->
     7632
     7633  <interface
     7634    name="IVRDEServerInfo" extends="$unknown"
     7635    uuid="714434a1-58c3-4aab-9049-7652c5df113b"
     7636    wsmap="struct"
     7637    >
     7638    <desc>
     7639      Contains information about the remote desktop (VRDE) server capabilities and status.
     7640      This is used in the <link to="IConsole::VRDEServerInfo" /> attribute.
     7641    </desc>
     7642
     7643    <attribute name="active" type="boolean" readonly="yes">
     7644      <desc>
     7645        Whether the remote desktop connection is active.
     7646      </desc>
     7647    </attribute>
     7648
     7649    <attribute name="port" type="long" readonly="yes">
     7650      <desc>
     7651        VRDE server port number. If this property is equal to <tt>0</tt>, then
     7652        the VRDE server failed to start, usually because there are no free IP
     7653        ports to bind to. If this property is equal to <tt>-1</tt>, then the VRDE
     7654        server has not yet been started.
     7655      </desc>
     7656    </attribute>
     7657
     7658    <attribute name="numberOfClients" type="unsigned long" readonly="yes">
     7659      <desc>
     7660        How many times a client connected.
     7661      </desc>
     7662    </attribute>
     7663
     7664    <attribute name="beginTime" type="long long" readonly="yes">
     7665      <desc>
     7666        When the last connection was established, in milliseconds since 1970-01-01 UTC.
     7667      </desc>
     7668    </attribute>
     7669
     7670    <attribute name="endTime" type="long long" readonly="yes">
     7671      <desc>
     7672        When the last connection was terminated or the current time, if
     7673        connection is still active, in milliseconds since 1970-01-01 UTC.
     7674      </desc>
     7675    </attribute>
     7676
     7677    <attribute name="bytesSent" type="long long" readonly="yes">
     7678      <desc>
     7679        How many bytes were sent in last or current, if still active, connection.
     7680      </desc>
     7681    </attribute>
     7682
     7683    <attribute name="bytesSentTotal" type="long long" readonly="yes">
     7684      <desc>
     7685        How many bytes were sent in all connections.
     7686      </desc>
     7687    </attribute>
     7688
     7689    <attribute name="bytesReceived" type="long long" readonly="yes">
     7690      <desc>
     7691        How many bytes were received in last or current, if still active, connection.
     7692      </desc>
     7693    </attribute>
     7694
     7695    <attribute name="bytesReceivedTotal" type="long long" readonly="yes">
     7696      <desc>
     7697        How many bytes were received in all connections.
     7698      </desc>
     7699    </attribute>
     7700
     7701    <attribute name="user" type="wstring" readonly="yes">
     7702      <desc>
     7703        Login user name supplied by the client.
     7704      </desc>
     7705    </attribute>
     7706
     7707    <attribute name="domain" type="wstring" readonly="yes">
     7708      <desc>
     7709        Login domain name supplied by the client.
     7710      </desc>
     7711    </attribute>
     7712
     7713    <attribute name="clientName" type="wstring" readonly="yes">
     7714      <desc>
     7715        The client name supplied by the client.
     7716      </desc>
     7717    </attribute>
     7718
     7719    <attribute name="clientIP" type="wstring" readonly="yes">
     7720      <desc>
     7721        The IP address of the client.
     7722      </desc>
     7723    </attribute>
     7724
     7725    <attribute name="clientVersion" type="unsigned long" readonly="yes">
     7726      <desc>
     7727        The client software version number.
     7728      </desc>
     7729    </attribute>
     7730
     7731    <attribute name="encryptionStyle" type="unsigned long" readonly="yes">
     7732      <desc>
     7733        Public key exchange method used when connection was established.
     7734        Values: 0 - RDP4 public key exchange scheme.
     7735        1 - X509 certificates were sent to client.
     7736      </desc>
     7737    </attribute>
     7738
     7739  </interface>
     7740
     7741  <interface
     7742    name="IConsole" extends="$unknown"
     7743    uuid="650b5f05-8258-4ee9-b518-89c515ca5dd9"
     7744    wsmap="managed"
     7745    >
     7746    <desc>
     7747      The IConsole interface represents an interface to control virtual
     7748      machine execution.
     7749
     7750      A console object gets created when a machine has been locked for a
     7751      particular session (client process) using <link to="IMachine::lockMachine" />
     7752      or <link to="IMachine::launchVMProcess"/>. The console object can
     7753      then be found in the session's <link to="ISession::console" /> attribute.
     7754
     7755      Methods of the IConsole interface allow the caller to query the current
     7756      virtual machine execution state, pause the machine or power it down, save
     7757      the machine state or take a snapshot, attach and detach removable media
     7758      and so on.
     7759
     7760      <see><link to="ISession"/></see>
     7761    </desc>
     7762
     7763    <attribute name="machine" type="IMachine" readonly="yes">
     7764      <desc>
     7765        Machine object for this console session.
     7766        <note>
     7767          This is a convenience property, it has the same value as
     7768          <link to="ISession::machine"/> of the corresponding session
     7769          object.
     7770        </note>
     7771      </desc>
     7772    </attribute>
     7773
     7774    <attribute name="state" type="MachineState" readonly="yes">
     7775      <desc>
     7776        Current execution state of the machine.
     7777        <note>
     7778          This property always returns the same value as the corresponding
     7779          property of the IMachine object for this console session.
     7780          For the process that owns (executes) the VM, this is the
     7781          preferable way of querying the VM state, because no IPC
     7782          calls are made.
     7783        </note>
     7784      </desc>
     7785    </attribute>
     7786
     7787    <attribute name="guest" type="IGuest" readonly="yes">
     7788      <desc>Guest object.</desc>
     7789    </attribute>
     7790
     7791    <attribute name="keyboard" type="IKeyboard" readonly="yes">
     7792      <desc>
     7793        Virtual keyboard object.
     7794        <note>
     7795          If the machine is not running, any attempt to use
     7796          the returned object will result in an error.
     7797        </note>
     7798      </desc>
     7799    </attribute>
     7800
     7801    <attribute name="mouse" type="IMouse" readonly="yes">
     7802      <desc>
     7803        Virtual mouse object.
     7804        <note>
     7805          If the machine is not running, any attempt to use
     7806          the returned object will result in an error.
     7807        </note>
     7808      </desc>
     7809    </attribute>
     7810
     7811    <attribute name="display" type="IDisplay" readonly="yes">
     7812      <desc>Virtual display object.
     7813        <note>
     7814          If the machine is not running, any attempt to use
     7815          the returned object will result in an error.
     7816        </note>
     7817      </desc>
     7818    </attribute>
     7819
     7820    <attribute name="debugger" type="IMachineDebugger" readonly="yes">
     7821      <desc>Debugging interface.</desc>
     7822    </attribute>
     7823
     7824    <attribute name="USBDevices" type="IUSBDevice" readonly="yes" safearray="yes">
     7825      <desc>
     7826        Collection of USB devices currently attached to the virtual
     7827        USB controller.
     7828        <note>
     7829          The collection is empty if the machine is not running.
     7830        </note>
     7831      </desc>
     7832    </attribute>
     7833
     7834    <attribute name="remoteUSBDevices" type="IHostUSBDevice" readonly="yes" safearray="yes">
     7835      <desc>
     7836        List of USB devices currently attached to the remote VRDE client.
     7837        Once a new device is physically attached to the remote host computer,
     7838        it appears in this list and remains there until detached.
     7839      </desc>
     7840    </attribute>
     7841
     7842    <attribute name="sharedFolders" type="ISharedFolder" readonly="yes" safearray="yes">
     7843      <desc>
     7844        Collection of shared folders for the current session. These folders
     7845        are called transient shared folders because they are available to the
     7846        guest OS running inside the associated virtual machine only for the
     7847        duration of the session (as opposed to
     7848        <link to="IMachine::sharedFolders"/> which represent permanent shared
     7849        folders). When the session is closed (e.g. the machine is powered down),
     7850        these folders are automatically discarded.
     7851
     7852        New shared folders are added to the collection using
     7853        <link to="#createSharedFolder"/>. Existing shared folders can be
     7854        removed using <link to="#removeSharedFolder"/>.
     7855      </desc>
     7856    </attribute>
     7857
     7858    <attribute name="VRDEServerInfo" type="IVRDEServerInfo" readonly="yes">
     7859      <desc>
     7860        Interface that provides information on Remote Desktop Extension (VRDE) connection.
     7861      </desc>
     7862    </attribute>
     7863
     7864    <attribute name="eventSource" type="IEventSource" readonly="yes">
     7865      <desc>
     7866        Event source for console events.
     7867      </desc>
     7868    </attribute>
     7869
     7870    <attribute name="attachedPCIDevices" type="IPCIDeviceAttachment" readonly="yes" safearray="yes">
     7871      <desc>Array of PCI devices attached to this machine.</desc>
     7872    </attribute>
     7873
     7874    <attribute name="useHostClipboard" type="boolean">
     7875      <desc>
     7876        Whether the guest clipboard should be connected to the host one or
     7877        whether it should only be allowed access to the VRDE clipboard. This
     7878        setting may not affect existing guest clipboard connections which
     7879        are already connected to the host clipboard.
     7880      </desc>
     7881    </attribute>
     7882
     7883    <attribute name="emulatedUSB" type="IEmulatedUSB" readonly="yes">
     7884      <desc>
     7885        Interface that manages emulated USB devices.
     7886      </desc>
     7887    </attribute>
     7888
     7889    <method name="powerUp">
     7890      <desc>
     7891        Starts the virtual machine execution using the current machine
     7892        state (that is, its current execution state, current settings and
     7893        current storage devices).
     7894
     7895        <note>
     7896          This method is only useful for front-ends that want to actually
     7897          execute virtual machines in their own process (like the VirtualBox
     7898          or VBoxSDL front-ends). Unless you are intending to write such a
     7899          front-end, do not call this method. If you simply want to
     7900          start virtual machine execution using one of the existing front-ends
     7901          (for example the VirtualBox GUI or headless server), use
     7902          <link to="IMachine::launchVMProcess"/> instead; these
     7903          front-ends will power up the machine automatically for you.
     7904        </note>
     7905
     7906        If the machine is powered off or aborted, the execution will
     7907        start from the beginning (as if the real hardware were just
     7908        powered on).
     7909
     7910        If the machine is in the <link to="MachineState_Saved"/> state,
     7911        it will continue its execution the point where the state has
     7912        been saved.
     7913
     7914        If the machine <link to="IMachine::teleporterEnabled"/> property is
     7915        enabled on the machine being powered up, the machine will wait for an
     7916        incoming teleportation in the <link to="MachineState_TeleportingIn"/>
     7917        state. The returned progress object will have at least three
     7918        operations where the last three are defined as: (1) powering up and
     7919        starting TCP server, (2) waiting for incoming teleportations, and
     7920        (3) perform teleportation. These operations will be reflected as the
     7921        last three operations of the progress objected returned by
     7922        <link to="IMachine::launchVMProcess"/> as well.
     7923
     7924        <see><link to="IMachine::saveState"/></see>
     7925
     7926        <result name="VBOX_E_INVALID_VM_STATE">
     7927          Virtual machine already running.
     7928        </result>
     7929        <result name="VBOX_E_HOST_ERROR">
     7930          Host interface does not exist or name not set.
     7931        </result>
     7932        <result name="VBOX_E_FILE_ERROR">
     7933          Invalid saved state file.
     7934        </result>
     7935      </desc>
     7936      <param name="progress" type="IProgress" dir="return">
     7937        <desc>Progress object to track the operation completion.</desc>
     7938      </param>
     7939    </method>
     7940
     7941    <method name="powerUpPaused">
     7942      <desc>
     7943        Identical to powerUp except that the VM will enter the
     7944        <link to="MachineState_Paused"/> state, instead of
     7945        <link to="MachineState_Running"/>.
     7946
     7947        <see><link to="#powerUp"/></see>
     7948        <result name="VBOX_E_INVALID_VM_STATE">
     7949          Virtual machine already running.
     7950        </result>
     7951        <result name="VBOX_E_HOST_ERROR">
     7952          Host interface does not exist or name not set.
     7953        </result>
     7954        <result name="VBOX_E_FILE_ERROR">
     7955          Invalid saved state file.
     7956        </result>
     7957      </desc>
     7958      <param name="progress" type="IProgress" dir="return">
     7959        <desc>Progress object to track the operation completion.</desc>
     7960      </param>
     7961    </method>
     7962
     7963    <method name="powerDown">
     7964      <desc>
     7965        Initiates the power down procedure to stop the virtual machine
     7966        execution.
     7967
     7968        The completion of the power down procedure is tracked using the returned
     7969        IProgress object. After the operation is complete, the machine will go
     7970        to the PoweredOff state.
     7971        <result name="VBOX_E_INVALID_VM_STATE">
     7972          Virtual machine must be Running, Paused or Stuck to be powered down.
     7973        </result>
     7974      </desc>
     7975      <param name="progress" type="IProgress" dir="return">
     7976        <desc>Progress object to track the operation completion.</desc>
     7977      </param>
     7978    </method>
     7979
     7980    <method name="reset">
     7981      <desc>Resets the virtual machine.
     7982        <result name="VBOX_E_INVALID_VM_STATE">
     7983          Virtual machine not in Running state.
     7984        </result>
     7985        <result name="VBOX_E_VM_ERROR">
     7986          Virtual machine error in reset operation.
     7987        </result>
     7988      </desc>
     7989    </method>
     7990
     7991    <method name="pause">
     7992      <desc>Pauses the virtual machine execution.
     7993        <result name="VBOX_E_INVALID_VM_STATE">
     7994          Virtual machine not in Running state.
     7995        </result>
     7996        <result name="VBOX_E_VM_ERROR">
     7997          Virtual machine error in suspend operation.
     7998        </result>
     7999      </desc>
     8000    </method>
     8001
     8002    <method name="resume">
     8003      <desc>Resumes the virtual machine execution.
     8004        <result name="VBOX_E_INVALID_VM_STATE">
     8005          Virtual machine not in Paused state.
     8006        </result>
     8007        <result name="VBOX_E_VM_ERROR">
     8008          Virtual machine error in resume operation.
     8009        </result>
     8010      </desc>
     8011    </method>
     8012
     8013    <method name="powerButton">
     8014      <desc>Sends the ACPI power button event to the guest.
     8015        <result name="VBOX_E_INVALID_VM_STATE">
     8016          Virtual machine not in Running state.
     8017        </result>
     8018        <result name="VBOX_E_PDM_ERROR">
     8019          Controlled power off failed.
     8020        </result>
     8021      </desc>
     8022    </method>
     8023
     8024    <method name="sleepButton">
     8025      <desc>Sends the ACPI sleep button event to the guest.
     8026        <result name="VBOX_E_INVALID_VM_STATE">
     8027          Virtual machine not in Running state.
     8028        </result>
     8029        <result name="VBOX_E_PDM_ERROR">
     8030          Sending sleep button event failed.
     8031        </result>
     8032      </desc>
     8033    </method>
     8034
     8035    <method name="getPowerButtonHandled">
     8036      <desc>Checks if the last power button event was handled by guest.
     8037        <result name="VBOX_E_PDM_ERROR">
     8038          Checking if the event was handled by the guest OS failed.
     8039        </result>
     8040      </desc>
     8041      <param name="handled" type="boolean" dir="return"/>
     8042    </method>
     8043
     8044    <method name="getGuestEnteredACPIMode">
     8045      <desc>Checks if the guest entered the ACPI mode G0 (working) or
     8046        G1 (sleeping). If this method returns @c false, the guest will
     8047        most likely not respond to external ACPI events.
     8048        <result name="VBOX_E_INVALID_VM_STATE">
     8049          Virtual machine not in Running state.
     8050        </result>
     8051      </desc>
     8052      <param name="entered" type="boolean" dir="return"/>
     8053    </method>
     8054
     8055    <method name="getDeviceActivity">
     8056      <desc>
     8057        Gets the current activity type of given devices or device groups.
     8058        <result name="E_INVALIDARG">
     8059          Invalid device type.
     8060        </result>
     8061      </desc>
     8062      <param name="type" type="DeviceType" safearray="yes" dir="in"/>
     8063      <param name="activity" type="DeviceActivity" safearray="yes" dir="return"/>
     8064    </method>
     8065
     8066    <method name="attachUSBDevice">
     8067      <desc>
     8068        Attaches a host USB device with the given UUID to the
     8069        USB controller of the virtual machine.
     8070
     8071        The device needs to be in one of the following states:
     8072        <link to="USBDeviceState_Busy"/>,
     8073        <link to="USBDeviceState_Available"/> or
     8074        <link to="USBDeviceState_Held"/>,
     8075        otherwise an error is immediately returned.
     8076
     8077        When the device state is
     8078        <link to="USBDeviceState_Busy">Busy</link>, an error may also
     8079        be returned if the host computer refuses to release it for some reason.
     8080
     8081        <see><link to="IUSBDeviceFilters::deviceFilters"/>,
     8082          <link to="USBDeviceState"/></see>
     8083        <result name="VBOX_E_INVALID_VM_STATE">
     8084          Virtual machine state neither Running nor Paused.
     8085        </result>
     8086        <result name="VBOX_E_PDM_ERROR">
     8087          Virtual machine does not have a USB controller.
     8088        </result>
     8089      </desc>
     8090      <param name="id" type="uuid" mod="string" dir="in">
     8091        <desc>UUID of the host USB device to attach.</desc>
     8092      </param>
     8093      <param name="captureFilename" type="wstring" dir="in">
     8094        <desc>Filename to capture the USB traffic to.</desc>
     8095      </param>
     8096    </method>
     8097
     8098    <method name="detachUSBDevice">
     8099      <desc>
     8100        Detaches an USB device with the given UUID from the USB controller
     8101        of the virtual machine.
     8102
     8103        After this method succeeds, the VirtualBox server re-initiates
     8104        all USB filters as if the device were just physically attached
     8105        to the host, but filters of this machine are ignored to avoid
     8106        a possible automatic re-attachment.
     8107
     8108        <see><link to="IUSBDeviceFilters::deviceFilters"/>,
     8109          <link to="USBDeviceState"/></see>
     8110
     8111        <result name="VBOX_E_PDM_ERROR">
     8112          Virtual machine does not have a USB controller.
     8113        </result>
     8114        <result name="E_INVALIDARG">
     8115          USB device not attached to this virtual machine.
     8116        </result>
     8117      </desc>
     8118      <param name="id" type="uuid" mod="string" dir="in">
     8119        <desc>UUID of the USB device to detach.</desc>
     8120      </param>
     8121      <param name="device" type="IUSBDevice" dir="return">
     8122        <desc>Detached USB device.</desc>
     8123      </param>
     8124    </method>
     8125
     8126    <method name="findUSBDeviceByAddress">
     8127      <desc>
     8128        Searches for a USB device with the given host address.
     8129
     8130        <result name="VBOX_E_OBJECT_NOT_FOUND">
     8131          Given @c name does not correspond to any USB device.
     8132        </result>
     8133
     8134        <see><link to="IUSBDevice::address"/></see>
     8135      </desc>
     8136      <param name="name" type="wstring" dir="in">
     8137        <desc>
     8138          Address of the USB device (as assigned by the host) to
     8139          search for.
     8140        </desc>
     8141      </param>
     8142      <param name="device" type="IUSBDevice" dir="return">
     8143        <desc>Found USB device object.</desc>
     8144      </param>
     8145    </method>
     8146
     8147    <method name="findUSBDeviceById">
     8148      <desc>
     8149        Searches for a USB device with the given UUID.
     8150
     8151        <result name="VBOX_E_OBJECT_NOT_FOUND">
     8152          Given @c id does not correspond to any USB device.
     8153        </result>
     8154
     8155        <see><link to="IUSBDevice::id"/></see>
     8156      </desc>
     8157      <param name="id" type="uuid" mod="string" dir="in">
     8158        <desc>UUID of the USB device to search for.</desc>
     8159      </param>
     8160      <param name="device" type="IUSBDevice" dir="return">
     8161        <desc>Found USB device object.</desc>
     8162      </param>
     8163    </method>
     8164
     8165    <method name="createSharedFolder">
     8166      <desc>
     8167        Creates a transient new shared folder by associating the given logical
     8168        name with the given host path, adds it to the collection of shared
     8169        folders and starts sharing it. Refer to the description of
     8170        <link to="ISharedFolder"/> to read more about logical names.
     8171
     8172        <result name="VBOX_E_INVALID_VM_STATE">
     8173          Virtual machine in Saved state or currently changing state.
     8174        </result>
     8175        <result name="VBOX_E_FILE_ERROR">
     8176          Shared folder already exists or not accessible.
     8177        </result>
     8178      </desc>
     8179      <param name="name" type="wstring" dir="in">
     8180        <desc>Unique logical name of the shared folder.</desc>
     8181      </param>
     8182      <param name="hostPath" type="wstring" dir="in">
     8183        <desc>Full path to the shared folder in the host file system.</desc>
     8184      </param>
     8185      <param name="writable" type="boolean" dir="in">
     8186        <desc>Whether the share is writable or readonly</desc>
     8187      </param>
     8188      <param name="automount" type="boolean" dir="in">
     8189        <desc>Whether the share gets automatically mounted by the guest
     8190          or not.</desc>
     8191      </param>
     8192    </method>
     8193
     8194    <method name="removeSharedFolder">
     8195      <desc>
     8196        Removes a transient shared folder with the given name previously
     8197        created by <link to="#createSharedFolder"/> from the collection of
     8198        shared folders and stops sharing it.
     8199        <result name="VBOX_E_INVALID_VM_STATE">
     8200          Virtual machine in Saved state or currently changing state.
     8201        </result>
     8202        <result name="VBOX_E_FILE_ERROR">
     8203          Shared folder does not exists.
     8204        </result>
     8205      </desc>
     8206      <param name="name" type="wstring" dir="in">
     8207        <desc>Logical name of the shared folder to remove.</desc>
    83688208      </param>
    83698209    </method>
     
    1298612826
    1298712827      The ISnapshot interface has no methods, only attributes; snapshots
    12988       are controlled through methods of the <link to="IConsole" /> interface
     12828      are controlled through methods of the <link to="IMachine" /> interface
    1298912829      which also manage the media associated with the snapshot.
    1299012830      The following operations exist:
    1299112831
    1299212832      <ul>
    12993           <li><link to="IConsole::takeSnapshot"/> creates a new snapshot
     12833          <li><link to="IMachine::takeSnapshot"/> creates a new snapshot
    1299412834              by creating new, empty differencing images for the machine's
    1299512835              media and saving the VM settings and (if the VM is running)
     
    1819218032      <desc>Host is running low on battery (power management event).</desc>
    1819318033    </const>
     18034    <const name="Snapshot"          value="4">
     18035      <desc>A snapshot of the VM is being taken.</desc>
     18036    </const>
    1819418037  </enum>
    1819518038
    1819618039  <interface
    1819718040    name="IInternalSessionControl" extends="$unknown"
    18198     uuid="fdb5fa71-eddb-4e06-9844-277d22270fe0"
     18041    uuid="747e397e-69c8-45a0-88d9-f7f070960718"
    1819918042    internal="yes"
    1820018043    wsmap="suppress"
    1820118044    >
    18202     <method name="getPID">
     18045    <attribute name="PID" type="unsigned long" readonly="yes">
    1820318046      <desc>PID of the process that has created this Session object.
    1820418047      </desc>
    18205       <param name="pid" type="unsigned long" dir="return"/>
    18206     </method>
    18207 
    18208     <method name="getRemoteConsole">
     18048    </attribute>
     18049
     18050    <attribute name="remoteConsole" type="IConsole" readonly="yes">
    1820918051      <desc>
    1821018052        Returns the console object suitable for remote control.
     
    1821818060
    1821918061      </desc>
    18220       <param name="console" type="IConsole" dir="return"/>
    18221     </method>
     18062    </attribute>
     18063
     18064    <attribute name="nominalState" type="MachineState" readonly="yes">
     18065      <desc>Returns suitable machine state for the VM execution state. Useful
     18066        for choosing a sensible machine state after a complex operation which
     18067        failed or otherwise resulted in an unclear situation.
     18068      </desc>
     18069    </attribute>
    1822218070
    1822318071<if target="midl">
     
    1868818536    </method>
    1868918537
     18538    <method name="reconfigureMediumAttachments">
     18539      <desc>
     18540        Reconfigure all specified medium attachments in one go, making sure
     18541        the current state corresponds to the specified medium.
     18542
     18543        <result name="VBOX_E_INVALID_VM_STATE">
     18544          Machine session is not open.
     18545        </result>
     18546        <result name="VBOX_E_INVALID_OBJECT_STATE">
     18547          Session type is not direct.
     18548        </result>
     18549      </desc>
     18550      <param name="attachments" type="IMediumAttachment" dir="in" safearray="yes">
     18551        <desc>Array containing the medium attachments which need to be
     18552          reconfigured.</desc>
     18553      </param>
     18554    </method>
     18555
    1869018556    <method name="enableVMMStatistics">
    1869118557      <desc>
     
    1875118617        might behave slightly differently than a normal VM save state.
    1875218618
     18619        This call is fully synchronous, and the caller is expected to have set
     18620        the machine state appropriately (and has to set the follow-up machine
     18621        state if this call failed).
     18622
    1875318623        <result name="VBOX_E_INVALID_VM_STATE">
    18754           Virtual machine state neither Running nor Paused.
     18624          Virtual machine state is not one of the expected values.
    1875518625        </result>
    1875618626        <result name="VBOX_E_FILE_ERROR">
    1875718627          Failed to create directory for saved state file.
    1875818628        </result>
    18759         <see><link to="IConsole::saveState"/></see>
     18629        <see><link to="IMachine::saveState"/></see>
    1876018630      </desc>
    1876118631
     
    1876318633        <desc>Specify the best matching reason code please.</desc>
    1876418634      </param>
    18765       <param name="progress" type="IProgress" dir="return">
     18635      <param name="progress" type="IProgress" dir="in">
    1876618636        <desc>Progress object to track the operation completion.</desc>
    1876718637      </param>
     18638      <param name="stateFilePath" type="wstring" dir="in">
     18639        <desc>File path the VM process must save the execution state to.</desc>
     18640      </param>
     18641      <param name="pauseVM" type="boolean" dir="in">
     18642        <desc>The VM should be paused before saving state. It is automatically
     18643        unpaused on error in the "vanilla save state" case.</desc>
     18644      </param>
     18645      <param name="leftPaused" type="boolean" dir="return">
     18646        <desc>Returns if the VM was left in paused state, which is necessary
     18647        in many situations (snapshots, teleportation).</desc>
     18648      </param>
     18649    </method>
     18650
     18651    <method name="cancelSaveStateWithReason">
     18652      <desc>
     18653        Internal method for cancelling a VM save state.
     18654        <see><link to="IInternalSessionControl::saveStateWithReason"/></see>
     18655      </desc>
    1876818656    </method>
    1876918657
  • trunk/src/VBox/Main/include/ConsoleImpl.h

    r55184 r55214  
    155155
    156156    HRESULT i_updateMachineState(MachineState_T aMachineState);
     157    HRESULT i_getNominalState(MachineState_T &aNominalState);
    157158
    158159    // events from IInternalSessionControl
     
    188189                                ULONG aSourceIdx, ULONG aTargetIdx,
    189190                                IProgress *aProgress);
     191    HRESULT i_reconfigureMediumAttachments(const std::vector<ComPtr<IMediumAttachment> > &aAttachments);
    190192    int i_hgcmLoadService(const char *pszServiceLibrary, const char *pszServiceName);
    191193    VMMDev *i_getVMMDev() { return m_pVMMDev; }
     
    230232
    231233    HRESULT i_pause(Reason_T aReason);
    232     HRESULT i_resume(Reason_T aReason);
    233     HRESULT i_saveState(Reason_T aReason, IProgress **aProgress);
     234    HRESULT i_resume(Reason_T aReason, AutoWriteLock &alock);
     235    HRESULT i_saveState(Reason_T aReason, const ComPtr<IProgress> &aProgress, const Utf8Str &aStateFilePath, bool fPauseVM, bool &fLeftPaused);
     236    HRESULT i_cancelSaveState();
    234237
    235238    // callback callers (partly; for some events console callbacks are notified
     
    318321    HRESULT getPowerButtonHandled(BOOL *aHandled);
    319322    HRESULT getGuestEnteredACPIMode(BOOL *aEntered);
    320     HRESULT saveState(ComPtr<IProgress> &aProgress);
    321     HRESULT adoptSavedState(const com::Utf8Str &aSavedStateFile);
    322     HRESULT discardSavedState(BOOL aFRemoveFile);
    323323    HRESULT getDeviceActivity(const std::vector<DeviceType_T> &aType,
    324324                              std::vector<DeviceActivity_T> &aActivity);
     
    335335                               BOOL aAutomount);
    336336    HRESULT removeSharedFolder(const com::Utf8Str &aName);
    337     HRESULT takeSnapshot(const com::Utf8Str &aName,
    338                          const com::Utf8Str &aDescription,
    339                          ComPtr<IProgress> &aProgress);
    340     HRESULT deleteSnapshot(const com::Guid &aId,
    341                            ComPtr<IProgress> &aProgress);
    342     HRESULT deleteSnapshotAndAllChildren(const com::Guid &aId,
    343                                          ComPtr<IProgress> &aProgress);
    344     HRESULT deleteSnapshotRange(const com::Guid &aStartId,
    345                                 const com::Guid &aEndId,
    346                                 ComPtr<IProgress> &aProgress);
    347     HRESULT restoreSnapshot(const ComPtr<ISnapshot> &aSnapshot,
    348                             ComPtr<IProgress> &aProgress);
    349337    HRESULT teleport(const com::Utf8Str &aHostname,
    350338                     ULONG aTcpport,
     
    751739    HRESULT i_doStorageDeviceDetach(IMediumAttachment *aMediumAttachment, PUVM pUVM, bool fSilent);
    752740
    753     static DECLCALLBACK(int)    i_fntTakeSnapshotWorker(RTTHREAD Thread, void *pvUser);
    754 
    755741    static DECLCALLBACK(int)    i_stateProgressCallback(PUVM pUVM, unsigned uPercent, void *pvUser);
    756742
     
    766752
    767753    static DECLCALLBACK(int)    i_powerUpThread(RTTHREAD Thread, void *pvUser);
    768     static DECLCALLBACK(int)    i_saveStateThread(RTTHREAD Thread, void *pvUser);
    769754    static DECLCALLBACK(int)    i_powerDownThread(RTTHREAD Thread, void *pvUser);
    770755
     
    997982     * teleportation operation, will cancel the teleportation / live snapshot
    998983     * operation before starting. */
    999     ComObjPtr<Progress> mptrCancelableProgress;
     984    ComPtr<IProgress> mptrCancelableProgress;
    1000985
    1001986    ComPtr<IEventListener> mVmListener;
  • trunk/src/VBox/Main/include/Global.h

    r49074 r55214  
    9797     * dedicated process) or not. Note that some online states are also
    9898     * transitional states (see #IsTransitional()).
    99      *
    100      * @remarks Saving may actually be an offline state according to the
    101      *          documentation (offline snapshot).
    10299     */
    103100    static bool IsOnline(MachineState_T aState)
    104101    {
    105 #if 0
    106102        return aState >= MachineState_FirstOnline &&
    107103               aState <= MachineState_LastOnline;
    108 #else
    109         switch (aState)
    110         {
    111             case MachineState_Running:
    112             case MachineState_Paused:
    113             case MachineState_Teleporting:
    114             case MachineState_LiveSnapshotting:
    115             case MachineState_Stuck:
    116             case MachineState_Starting:
    117             case MachineState_Stopping:
    118             case MachineState_Saving:
    119             case MachineState_Restoring:
    120             case MachineState_TeleportingPausedVM:
    121             case MachineState_TeleportingIn:
    122                 return true;
    123             default:
    124                 return false;
    125         }
    126 #endif
    127104    }
    128105
     
    136113    static bool IsTransient(MachineState_T aState)
    137114    {
    138 #if 0
    139115        return aState >= MachineState_FirstTransient &&
    140116               aState <= MachineState_LastTransient;
    141 #else
    142         switch (aState)
    143         {
    144             case MachineState_Teleporting:
    145             case MachineState_LiveSnapshotting:
    146             case MachineState_Starting:
    147             case MachineState_Stopping:
    148             case MachineState_Saving:
    149             case MachineState_Restoring:
    150             case MachineState_TeleportingPausedVM:
    151             case MachineState_TeleportingIn:
    152             case MachineState_RestoringSnapshot:
    153             case MachineState_DeletingSnapshot:
    154             case MachineState_SettingUp:
    155                 return true;
    156             default:
    157                 return false;
    158         }
    159 #endif
    160117    }
    161118
  • trunk/src/VBox/Main/include/MachineImpl.h

    r55168 r55214  
    125125        struct Session
    126126        {
     127            /** Type of lock which created this session */
     128            LockType_T mLockType;
     129
    127130            /** Control of the direct session opened by lockMachine() */
    128131            ComPtr<IInternalSessionControl> mDirectControl;
     
    597600    }
    598601
    599 
     602    static HRESULT i_setErrorStatic(HRESULT aResultCode, const char *pcszMsg, ...);
    600603
    601604protected:
     
    712715    bool i_isControllerHotplugCapable(StorageControllerType_T enmCtrlType);
    713716
    714     struct DeleteTask;
    715     static DECLCALLBACK(int) deleteThread(RTTHREAD Thread, void *pvUser);
    716     HRESULT i_deleteTaskWorker(DeleteTask &task);
    717717    Utf8Str i_getExtraData(const Utf8Str &strKey);
    718718
     
    778778
    779779    uint64_t                        uRegistryNeedsSaving;
     780
     781    /**
     782     * Abstract base class for all Machine or SessionMachine related
     783     * asynchronous tasks. This is necessary since RTThreadCreate cannot call
     784     * a (non-static) method as its thread function, so instead we have it call
     785     * the static Machine::taskHandler, which then calls the handler() method
     786     * in here (implemented by the subclasses).
     787     */
     788    struct Task
     789    {
     790        Task(Machine *m, Progress *p, const Utf8Str &t)
     791            : m_pMachine(m),
     792              m_machineCaller(m),
     793              m_pProgress(p),
     794              m_strTaskName(t),
     795              m_machineStateBackup(m->mData->mMachineState) // save the current machine state
     796        {}
     797
     798        HRESULT createThread()
     799        {
     800            int vrc = RTThreadCreate(NULL,
     801                                     taskHandler,
     802                                     (void *)this,
     803                                     0,
     804                                     RTTHREADTYPE_MAIN_WORKER,
     805                                     0,
     806                                     m_strTaskName.c_str());
     807            if (RT_FAILURE(vrc))
     808            {
     809                HRESULT rc = Machine::i_setErrorStatic(E_FAIL, Machine::tr("Could not create thread \"%s\" (%Rrc)"), m_strTaskName.c_str(), vrc);
     810                delete this;
     811                return rc;
     812            }
     813            return S_OK;
     814        }
     815
     816        void modifyBackedUpState(MachineState_T s)
     817        {
     818            *const_cast<MachineState_T *>(&m_machineStateBackup) = s;
     819        }
     820
     821        virtual void handler() = 0;
     822
     823        ComObjPtr<Machine>       m_pMachine;
     824        AutoCaller                      m_machineCaller;
     825        ComObjPtr<Progress>             m_pProgress;
     826        Utf8Str                         m_strTaskName;
     827        const MachineState_T            m_machineStateBackup;
     828    };
     829
     830    struct DeleteConfigTask;
     831    void i_deleteConfigHandler(DeleteConfigTask &task);
     832
     833    static DECLCALLBACK(int) taskHandler(RTTHREAD thread, void *pvUser);
    780834
    781835    friend class SessionMachine;
     
    11311185                    const std::vector<CloneOptions_T> &aOptions,
    11321186                    ComPtr<IProgress> &aProgress);
     1187    HRESULT saveState(ComPtr<IProgress> &aProgress);
     1188    HRESULT adoptSavedState(const com::Utf8Str &aSavedStateFile);
     1189    HRESULT discardSavedState(BOOL aFRemoveFile);
     1190    HRESULT takeSnapshot(const com::Utf8Str &aName,
     1191                         const com::Utf8Str &aDescription,
     1192                         BOOL aPause,
     1193                         ComPtr<IProgress> &aProgress);
     1194    HRESULT deleteSnapshot(const com::Guid &aId,
     1195                           ComPtr<IProgress> &aProgress);
     1196    HRESULT deleteSnapshotAndAllChildren(const com::Guid &aId,
     1197                                         ComPtr<IProgress> &aProgress);
     1198    HRESULT deleteSnapshotRange(const com::Guid &aStartId,
     1199                                const com::Guid &aEndId,
     1200                                ComPtr<IProgress> &aProgress);
     1201    HRESULT restoreSnapshot(const ComPtr<ISnapshot> &aSnapshot,
     1202                            ComPtr<IProgress> &aProgress);
    11331203
    11341204    // wrapped IInternalMachineControl properties
    11351205
    11361206    // wrapped IInternalMachineControl methods
    1137     HRESULT setRemoveSavedStateFile(BOOL aRemove);
    11381207    HRESULT updateState(MachineState_T aState);
    11391208    HRESULT beginPowerUp(const ComPtr<IProgress> &aProgress);
     
    11451214                                BOOL *aMatched,
    11461215                                ULONG *aMaskedInterfaces);
    1147     HRESULT captureUSBDevice(const com::Guid &aId, const com::Utf8Str &aCaptureFilename);
     1216    HRESULT captureUSBDevice(const com::Guid &aId,
     1217                             const com::Utf8Str &aCaptureFilename);
    11481218    HRESULT detachUSBDevice(const com::Guid &aId,
    11491219                            BOOL aDone);
     
    11521222    HRESULT onSessionEnd(const ComPtr<ISession> &aSession,
    11531223                         ComPtr<IProgress> &aProgress);
    1154     HRESULT beginSavingState(ComPtr<IProgress> &aProgress,
    1155                              com::Utf8Str &aStateFilePath);
    1156     HRESULT endSavingState(LONG aResult,
    1157                            const com::Utf8Str &aErrMsg);
    1158     HRESULT adoptSavedState(const com::Utf8Str &aSavedStateFile);
    1159     HRESULT beginTakingSnapshot(const ComPtr<IConsole> &aInitiator,
    1160                                 const com::Utf8Str &aName,
    1161                                 const com::Utf8Str &aDescription,
    1162                                 const ComPtr<IProgress> &aConsoleProgress,
    1163                                 BOOL aFTakingSnapshotOnline,
    1164                                 com::Utf8Str &aStateFilePath);
    1165     HRESULT endTakingSnapshot(BOOL aSuccess);
    1166     HRESULT deleteSnapshot(const ComPtr<IConsole> &aInitiator,
    1167                            const com::Guid &aStartId,
    1168                            const com::Guid &aEndId,
    1169                            BOOL aDeleteAllChildren,
    1170                            MachineState_T *aMachineState,
    1171                            ComPtr<IProgress> &aProgress);
    11721224    HRESULT finishOnlineMergeMedium();
    1173     HRESULT restoreSnapshot(const ComPtr<IConsole> &aInitiator,
    1174                             const ComPtr<ISnapshot> &aSnapshot,
    1175                             MachineState_T *aMachineState,
    1176                             ComPtr<IProgress> &aProgress);
    11771225    HRESULT pullGuestProperties(std::vector<com::Utf8Str> &aNames,
    11781226                                std::vector<com::Utf8Str> &aValues,
     
    12031251                               ULONG aVmNetRx,
    12041252                               ULONG aVmNetTx);
    1205 
    1206 
    1207 
    1208 
    12091253};
    12101254
     
    13021346    HRESULT i_unlockMedia();
    13031347
     1348    HRESULT i_saveStateWithReason(Reason_T aReason, ComPtr<IProgress> &aProgress);
     1349
    13041350private:
    13051351
     
    13241370    HRESULT onSessionEnd(const ComPtr<ISession> &aSession,
    13251371                         ComPtr<IProgress> &aProgress);
    1326     HRESULT beginSavingState(ComPtr<IProgress> &aProgress,
    1327                              com::Utf8Str &aStateFilePath);
    1328     HRESULT endSavingState(LONG aResult,
    1329                            const com::Utf8Str &aErrMsg);
    1330     HRESULT adoptSavedState(const com::Utf8Str &aSavedStateFile);
    1331     HRESULT beginTakingSnapshot(const ComPtr<IConsole> &aInitiator,
    1332                                 const com::Utf8Str &aName,
    1333                                 const com::Utf8Str &aDescription,
    1334                                 const ComPtr<IProgress> &aConsoleProgress,
    1335                                 BOOL aFTakingSnapshotOnline,
    1336                                 com::Utf8Str &aStateFilePath);
    1337     HRESULT endTakingSnapshot(BOOL aSuccess);
    1338     HRESULT deleteSnapshot(const ComPtr<IConsole> &aInitiator,
    1339                            const com::Guid &aStartId,
    1340                            const com::Guid &aEndId,
    1341                            BOOL aDeleteAllChildren,
    1342                            MachineState_T *aMachineState,
    1343                            ComPtr<IProgress> &aProgress);
    13441372    HRESULT finishOnlineMergeMedium();
    1345     HRESULT restoreSnapshot(const ComPtr<IConsole> &aInitiator,
    1346                             const ComPtr<ISnapshot> &aSnapshot,
    1347                             MachineState_T *aMachineState,
    1348                             ComPtr<IProgress> &aProgress);
    13491373    HRESULT pullGuestProperties(std::vector<com::Utf8Str> &aNames,
    13501374                                std::vector<com::Utf8Str> &aValues,
     
    13801404    {
    13811405        ConsoleTaskData()
    1382             : mLastState(MachineState_Null), mDeleteSnapshotInfo(NULL)
     1406            : mLastState(MachineState_Null),
     1407              mDeleteSnapshotInfo(NULL)
    13831408        { }
    13841409
     
    13861411        ComObjPtr<Progress> mProgress;
    13871412
    1388         // used when taking snapshot
    1389         ComObjPtr<Snapshot> mSnapshot;
    1390 
    1391         // used when deleting online snapshot
     1413        // used when deleting online snaphshot
    13921414        void *mDeleteSnapshotInfo;
    1393 
    1394         // used when saving state (either as part of a snapshot or separate)
    1395         Utf8Str strStateFilePath;
    13961415    };
    13971416
     1417    struct SaveStateTask;
    13981418    struct SnapshotTask;
     1419    struct TakeSnapshotTask;
    13991420    struct DeleteSnapshotTask;
    14001421    struct RestoreSnapshotTask;
    14011422
     1423    friend struct TakeSnapshotTask;
    14021424    friend struct DeleteSnapshotTask;
    14031425    friend struct RestoreSnapshotTask;
    14041426
    1405     HRESULT i_endSavingState(HRESULT aRC, const Utf8Str &aErrMsg);
     1427    void i_saveStateHandler(SaveStateTask &aTask);
     1428
     1429    // Override some functionality for SessionMachine, this is where the
     1430    // real action happens (the Machine methods are just dummies).
     1431    HRESULT saveState(ComPtr<IProgress> &aProgress);
     1432    HRESULT adoptSavedState(const com::Utf8Str &aSavedStateFile);
     1433    HRESULT discardSavedState(BOOL aFRemoveFile);
     1434    HRESULT takeSnapshot(const com::Utf8Str &aName,
     1435                         const com::Utf8Str &aDescription,
     1436                         BOOL aPause,
     1437                         ComPtr<IProgress> &aProgress);
     1438    HRESULT deleteSnapshot(const com::Guid &aId,
     1439                           ComPtr<IProgress> &aProgress);
     1440    HRESULT deleteSnapshotAndAllChildren(const com::Guid &aId,
     1441                                         ComPtr<IProgress> &aProgress);
     1442    HRESULT deleteSnapshotRange(const com::Guid &aStartId,
     1443                                const com::Guid &aEndId,
     1444                                ComPtr<IProgress> &aProgress);
     1445    HRESULT restoreSnapshot(const ComPtr<ISnapshot> &aSnapshot,
     1446                            ComPtr<IProgress> &aProgress);
     1447
    14061448    void i_releaseSavedStateFile(const Utf8Str &strSavedStateFile, Snapshot *pSnapshotToIgnore);
    14071449
     1450    void i_takeSnapshotHandler(TakeSnapshotTask &aTask);
     1451    static void i_takeSnapshotProgressCancelCallback(void *pvUser);
     1452    HRESULT i_finishTakingSnapshot(TakeSnapshotTask &aTask, AutoWriteLock &alock, bool aSuccess);
     1453    HRESULT i_deleteSnapshot(const com::Guid &aStartId,
     1454                             const com::Guid &aEndId,
     1455                             BOOL aDeleteAllChildren,
     1456                             ComPtr<IProgress> &aProgress);
    14081457    void i_deleteSnapshotHandler(DeleteSnapshotTask &aTask);
    14091458    void i_restoreSnapshotHandler(RestoreSnapshotTask &aTask);
     
    14511500
    14521501    int miNATNetworksStarted;
    1453 
    1454     static DECLCALLBACK(int) taskHandler(RTTHREAD thread, void *pvUser);
    14551502};
    14561503
  • trunk/src/VBox/Main/include/SessionImpl.h

    r53062 r55214  
    5353private:
    5454
    55     // Wrapped Isession properties
     55    // Wrapped ISession properties
    5656    HRESULT getState(SessionState_T *aState);
    5757    HRESULT getType(SessionType_T *aType);
     
    5959    HRESULT getConsole(ComPtr<IConsole> &aConsole);
    6060
    61     // Wrapped Isession methods
     61    // Wrapped ISession methods
    6262    HRESULT unlockMachine();
     63
     64    // Wrapped IInternalSessionControl properties
    6365    HRESULT getPID(ULONG *aPid);
    64     HRESULT getRemoteConsole(ComPtr<IConsole> &aConsole);
     66    HRESULT getRemoteConsole(ComPtr<IConsole> &aRemoteConsole);
     67    HRESULT getNominalState(MachineState_T *aNominalState);
     68
     69    // Wrapped IInternalSessionControl methods
    6570#ifndef VBOX_WITH_GENERIC_SESSION_WATCHER
    6671    HRESULT assignMachine(const ComPtr<IMachine> &aMachine,
     
    121126                              ULONG aTargetIdx,
    122127                              const ComPtr<IProgress> &aProgress);
     128    HRESULT reconfigureMediumAttachments(const std::vector<ComPtr<IMediumAttachment> > &aAttachments);
    123129    HRESULT enableVMMStatistics(BOOL aEnable);
    124130    HRESULT pauseWithReason(Reason_T aReason);
    125131    HRESULT resumeWithReason(Reason_T aReason);
    126132    HRESULT saveStateWithReason(Reason_T aReason,
    127                                 ComPtr<IProgress> &aProgress);
    128     HRESULT unlockMachine(bool aFinalRelease, bool aFromServer);
     133                                const ComPtr<IProgress> &aProgress,
     134                                const Utf8Str &aStateFilePath,
     135                                BOOL aPauseVM,
     136                                BOOL *aLeftPaused);
     137    HRESULT cancelSaveStateWithReason();
     138
     139
     140    HRESULT i_unlockMachine(bool aFinalRelease, bool aFromServer);
    129141
    130142    SessionState_T mState;
  • trunk/src/VBox/Main/src-all/Global.cpp

    r54017 r55214  
    77
    88/*
    9  * Copyright (C) 2008-2013 Oracle Corporation
     9 * Copyright (C) 2008-2015 Oracle Corporation
    1010 *
    1111 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    448448        case MachineState_DeletingSnapshotOnline: return "DeletingSnapshotOnline";
    449449        case MachineState_DeletingSnapshotPaused: return "DeletingSnapshotPaused";
     450        case MachineState_OnlineSnapshotting:   return "OnlineSnapshotting";
    450451        case MachineState_RestoringSnapshot:    return "RestoringSnapshot";
    451452        case MachineState_DeletingSnapshot:     return "DeletingSnapshot";
    452453        case MachineState_SettingUp:            return "SettingUp";
     454        case MachineState_Snapshotting:         return "Snapshotting";
    453455        default:
    454456        {
     
    513515        case Reason_HostResume:       return "host resume";
    514516        case Reason_HostBatteryLow:   return "host battery low";
     517        case Reason_Snapshot:         return "snapshot";
    515518        default:
    516519        {
  • trunk/src/VBox/Main/src-client/ConsoleImpl.cpp

    r55185 r55214  
    164164          mProgress(aProgress),
    165165          mServerProgress(aServerProgress),
    166           mpUVM(NULL),
    167166          mRC(E_FAIL),
    168167          mpSafeVMPtr(NULL)
     
    175174        {
    176175            mpSafeVMPtr = new Console::SafeVMPtr(aConsole);
    177             if (mpSafeVMPtr->isOk())
    178                 mpUVM = mpSafeVMPtr->rawUVM();
    179             else
     176            if (!mpSafeVMPtr->isOk())
    180177                mRC = mpSafeVMPtr->rc();
    181178        }
     
    205202    Utf8Str                     mErrorMsg;
    206203    const ComPtr<IProgress>     mServerProgress;
    207     PUVM                        mpUVM;
    208204
    209205private:
     
    212208};
    213209
    214 struct VMTakeSnapshotTask : public VMTask
    215 {
    216     VMTakeSnapshotTask(Console *aConsole,
    217                        Progress *aProgress,
    218                        IN_BSTR aName,
    219                        IN_BSTR aDescription)
    220         : VMTask(aConsole, aProgress, NULL /* aServerProgress */,
    221                  false /* aUsesVMPtr */),
    222           bstrName(aName),
    223           bstrDescription(aDescription),
    224           lastMachineState(MachineState_Null)
    225     {}
    226 
    227     Bstr                    bstrName,
    228                             bstrDescription;
    229     Bstr                    bstrSavedStateFile;         // received from BeginTakeSnapshot()
    230     MachineState_T          lastMachineState;
    231     bool                    fTakingSnapshotOnline;
    232     ULONG                   ulMemSize;
    233 };
    234210
    235211struct VMPowerUpTask : public VMTask
     
    264240                 true /* aUsesVMPtr */)
    265241    {}
    266 };
    267 
    268 struct VMSaveTask : public VMTask
    269 {
    270     VMSaveTask(Console *aConsole,
    271                const ComPtr<IProgress> &aServerProgress,
    272                const Utf8Str &aSavedStateFile,
    273                MachineState_T aMachineStateBefore,
    274                Reason_T aReason)
    275         : VMTask(aConsole, NULL /* aProgress */, aServerProgress,
    276                  true /* aUsesVMPtr */),
    277           mSavedStateFile(aSavedStateFile),
    278           mMachineStateBefore(aMachineStateBefore),
    279           mReason(aReason)
    280     {}
    281 
    282     Utf8Str mSavedStateFile;
    283     /* The local machine state we had before. Required if something fails */
    284     MachineState_T mMachineStateBefore;
    285     /* The reason for saving state */
    286     Reason_T mReason;
    287242};
    288243
     
    597552            meAttachmentType[slot] = NetworkAttachmentType_Null;
    598553
    599         // VirtualBox 4.0: We no longer initialize the VMMDev instance here,
    600         // which starts the HGCM thread. Instead, this is now done in the
    601         // power-up thread when a VM is actually being powered up to avoid
    602         // having HGCM threads all over the place every time a session is
    603         // opened, even if that session will not run a VM.
    604         //     unconst(m_pVMMDev) = new VMMDev(this);
    605         //     AssertReturn(mVMMDev, E_FAIL);
    606 
    607554#ifdef VBOX_WITH_PDM_AUDIO_DRIVER
    608555        unconst(mAudioVRDE) = new AudioVRDE(this);
     
    21062053HRESULT Console::powerUp(ComPtr<IProgress> &aProgress)
    21072054{
    2108     ComObjPtr<IProgress> pProgress;
    2109     i_powerUp(pProgress.asOutParam(), false /* aPaused */);
    2110     pProgress.queryInterfaceTo(aProgress.asOutParam());
     2055    i_powerUp(aProgress.asOutParam(), false /* aPaused */);
    21112056    return S_OK;
    21122057}
     
    21142059HRESULT Console::powerUpPaused(ComPtr<IProgress> &aProgress)
    21152060{
    2116     ComObjPtr<IProgress> pProgress;
    2117     i_powerUp(pProgress.asOutParam(), true /* aPaused */);
    2118     pProgress.queryInterfaceTo(aProgress.asOutParam());
     2061    i_powerUp(aProgress.asOutParam(), true /* aPaused */);
    21192062    return S_OK;
    21202063}
     
    21332076        case MachineState_Stuck:
    21342077            break;
     2078
     2079        /* Try cancel the save state. */
     2080        case MachineState_Saving:
     2081            if (!mptrCancelableProgress.isNull())
     2082            {
     2083                HRESULT hrc = mptrCancelableProgress->Cancel();
     2084                if (SUCCEEDED(hrc))
     2085                    break;
     2086            }
     2087            return setError(VBOX_E_INVALID_VM_STATE, tr("Cannot power down at this point during a save state"));
    21352088
    21362089        /* Try cancel the teleportation. */
     
    21452098            return setError(VBOX_E_INVALID_VM_STATE, tr("Cannot power down at this point in a teleportation"));
    21462099
     2100        /* Try cancel the online snapshot. */
     2101        case MachineState_OnlineSnapshotting:
     2102            if (!mptrCancelableProgress.isNull())
     2103            {
     2104                HRESULT hrc = mptrCancelableProgress->Cancel();
     2105                if (SUCCEEDED(hrc))
     2106                    break;
     2107            }
     2108            return setError(VBOX_E_INVALID_VM_STATE, tr("Cannot power down at this point in an online snapshot"));
     2109
    21472110        /* Try cancel the live snapshot. */
    21482111        case MachineState_LiveSnapshotting:
     
    25392502    LogFlowThisFuncEnter();
    25402503
    2541     HRESULT rc = i_resume(Reason_Unspecified);
     2504    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     2505
     2506    if (mMachineState != MachineState_Paused)
     2507        return setError(VBOX_E_INVALID_VM_STATE,
     2508                        tr("Cannot resume the machine as it is not paused (machine state: %s)"),
     2509                        Global::stringifyMachineState(mMachineState));
     2510
     2511    HRESULT rc = i_resume(Reason_Unspecified, alock);
    25422512
    25432513    LogFlowThisFunc(("rc=%Rhrc\n", rc));
     
    27202690    LogFlowThisFunc(("rc=%Rhrc\n", rc));
    27212691    LogFlowThisFuncLeave();
    2722     return rc;
    2723 }
    2724 
    2725 HRESULT Console::saveState(ComPtr<IProgress> &aProgress)
    2726 {
    2727     LogFlowThisFuncEnter();
    2728     ComObjPtr<IProgress> pProgress;
    2729 
    2730     HRESULT rc = i_saveState(Reason_Unspecified, pProgress.asOutParam());
    2731     pProgress.queryInterfaceTo(aProgress.asOutParam());
    2732 
    2733     LogFlowThisFunc(("rc=%Rhrc\n", rc));
    2734     LogFlowThisFuncLeave();
    2735     return rc;
    2736 }
    2737 
    2738 HRESULT Console::adoptSavedState(const com::Utf8Str &aSavedStateFile)
    2739 {
    2740     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    2741 
    2742     if (   mMachineState != MachineState_PoweredOff
    2743         && mMachineState != MachineState_Teleported
    2744         && mMachineState != MachineState_Aborted
    2745        )
    2746         return setError(VBOX_E_INVALID_VM_STATE,
    2747             tr("Cannot adopt the saved machine state as the machine is not in Powered Off, Teleported or Aborted state (machine state: %s)"),
    2748             Global::stringifyMachineState(mMachineState));
    2749 
    2750     return mControl->AdoptSavedState(Bstr(aSavedStateFile.c_str()).raw());
    2751 }
    2752 
    2753 HRESULT Console::discardSavedState(BOOL aFRemoveFile)
    2754 {
    2755     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    2756 
    2757     if (mMachineState != MachineState_Saved)
    2758         return setError(VBOX_E_INVALID_VM_STATE,
    2759             tr("Cannot delete the machine state as the machine is not in the saved state (machine state: %s)"),
    2760             Global::stringifyMachineState(mMachineState));
    2761 
    2762     HRESULT rc = mControl->SetRemoveSavedStateFile(aFRemoveFile);
    2763     if (FAILED(rc)) return rc;
    2764 
    2765     /*
    2766      * Saved -> PoweredOff transition will be detected in the SessionMachine
    2767      * and properly handled.
    2768      */
    2769     rc = i_setMachineState(MachineState_PoweredOff);
    2770 
    27712692    return rc;
    27722693}
     
    31553076
    31563077    return rc;
    3157 }
    3158 
    3159 HRESULT Console::takeSnapshot(const com::Utf8Str &aName,
    3160                               const com::Utf8Str &aDescription,
    3161                               ComPtr<IProgress> &aProgress)
    3162 {
    3163     LogFlowThisFuncEnter();
    3164 
    3165     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    3166     LogFlowThisFunc(("aName='%s' mMachineState=%d\n", aName.c_str(), mMachineState));
    3167 
    3168     if (Global::IsTransient(mMachineState))
    3169         return setError(VBOX_E_INVALID_VM_STATE,
    3170                         tr("Cannot take a snapshot of the machine while it is changing the state (machine state: %s)"),
    3171                         Global::stringifyMachineState(mMachineState));
    3172 
    3173     HRESULT rc = S_OK;
    3174 
    3175     /* prepare the progress object:
    3176        a) count the no. of hard disk attachments to get a matching no. of progress sub-operations */
    3177     ULONG cOperations = 2;              // always at least setting up + finishing up
    3178     ULONG ulTotalOperationsWeight = 2;  // one each for setting up + finishing up
    3179     SafeIfaceArray<IMediumAttachment> aMediumAttachments;
    3180     rc = mMachine->COMGETTER(MediumAttachments)(ComSafeArrayAsOutParam(aMediumAttachments));
    3181     if (FAILED(rc))
    3182         return setError(rc, tr("Cannot get medium attachments of the machine"));
    3183 
    3184     ULONG ulMemSize;
    3185     rc = mMachine->COMGETTER(MemorySize)(&ulMemSize);
    3186     if (FAILED(rc))
    3187         return rc;
    3188 
    3189     for (size_t i = 0;
    3190          i < aMediumAttachments.size();
    3191          ++i)
    3192     {
    3193         DeviceType_T type;
    3194         rc = aMediumAttachments[i]->COMGETTER(Type)(&type);
    3195         if (FAILED(rc))
    3196             return rc;
    3197 
    3198         if (type == DeviceType_HardDisk)
    3199         {
    3200             ++cOperations;
    3201 
    3202             // assume that creating a diff image takes as long as saving a 1MB state
    3203             // (note, the same value must be used in SessionMachine::BeginTakingSnapshot() on the server!)
    3204             ulTotalOperationsWeight += 1;
    3205         }
    3206     }
    3207 
    3208     // b) one extra sub-operations for online snapshots OR offline snapshots that have a saved state (needs to be copied)
    3209     bool const fTakingSnapshotOnline = Global::IsOnline(mMachineState);
    3210 
    3211     LogFlowFunc(("fTakingSnapshotOnline = %d, mMachineState = %d\n", fTakingSnapshotOnline, mMachineState));
    3212 
    3213     if (fTakingSnapshotOnline)
    3214     {
    3215         ++cOperations;
    3216         ulTotalOperationsWeight += ulMemSize;
    3217     }
    3218 
    3219     // finally, create the progress object
    3220     ComObjPtr<Progress> pProgress;
    3221     pProgress.createObject();
    3222     rc = pProgress->init(static_cast<IConsole *>(this),
    3223                          Bstr(tr("Taking a snapshot of the virtual machine")).raw(),
    3224                             (mMachineState >= MachineState_FirstOnline)
    3225                          && (mMachineState <= MachineState_LastOnline) /* aCancelable */,
    3226                          cOperations,
    3227                          ulTotalOperationsWeight,
    3228                          Bstr(tr("Setting up snapshot operation")).raw(),      // first sub-op description
    3229                          1);        // ulFirstOperationWeight
    3230 
    3231     if (FAILED(rc))
    3232         return rc;
    3233 
    3234     VMTakeSnapshotTask *pTask;
    3235     if (!(pTask = new VMTakeSnapshotTask(this, pProgress, Bstr(aName).raw(), Bstr(aDescription).raw())))
    3236         return E_OUTOFMEMORY;
    3237 
    3238     Assert(pTask->mProgress);
    3239 
    3240     try
    3241     {
    3242         mptrCancelableProgress = pProgress;
    3243 
    3244         /*
    3245          * If we fail here it means a PowerDown() call happened on another
    3246          * thread while we were doing Pause() (which releases the Console lock).
    3247          * We assign PowerDown() a higher precedence than TakeSnapshot(),
    3248          * therefore just return the error to the caller.
    3249          */
    3250         rc = pTask->rc();
    3251         if (FAILED(rc)) throw rc;
    3252 
    3253         pTask->ulMemSize = ulMemSize;
    3254 
    3255         /* memorize the current machine state */
    3256         pTask->lastMachineState = mMachineState;
    3257         pTask->fTakingSnapshotOnline = fTakingSnapshotOnline;
    3258 
    3259         int vrc = RTThreadCreate(NULL,
    3260                                  Console::i_fntTakeSnapshotWorker,
    3261                                  (void *)pTask,
    3262                                  0,
    3263                                  RTTHREADTYPE_MAIN_WORKER,
    3264                                  0,
    3265                                  "TakeSnap");
    3266         if (FAILED(vrc))
    3267             throw setError(E_FAIL,
    3268                            tr("Could not create VMTakeSnap thread (%Rrc)"),
    3269                            vrc);
    3270 
    3271         pTask->mProgress.queryInterfaceTo(aProgress.asOutParam());
    3272     }
    3273     catch (HRESULT erc)
    3274     {
    3275         delete pTask;
    3276         rc = erc;
    3277         mptrCancelableProgress.setNull();
    3278     }
    3279 
    3280     LogFlowThisFunc(("rc=%Rhrc\n", rc));
    3281     LogFlowThisFuncLeave();
    3282     return rc;
    3283 }
    3284 
    3285 HRESULT Console::deleteSnapshot(const com::Guid &aId, ComPtr<IProgress> &aProgress)
    3286 {
    3287     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    3288 
    3289     if (Global::IsTransient(mMachineState))
    3290         return setError(VBOX_E_INVALID_VM_STATE,
    3291                         tr("Cannot delete a snapshot of the machine while it is changing the state (machine state: %s)"),
    3292                         Global::stringifyMachineState(mMachineState));
    3293     ComObjPtr<IProgress> iProgress;
    3294     MachineState_T machineState = MachineState_Null;
    3295     HRESULT rc = mControl->DeleteSnapshot((IConsole *)this, Bstr(aId.toString()).raw(), Bstr(aId.toString()).raw(),
    3296                                           FALSE /* fDeleteAllChildren */, &machineState, iProgress.asOutParam());
    3297     if (FAILED(rc)) return rc;
    3298     iProgress.queryInterfaceTo(aProgress.asOutParam());
    3299 
    3300     i_setMachineStateLocally(machineState);
    3301     return S_OK;
    3302 }
    3303 
    3304 HRESULT Console::deleteSnapshotAndAllChildren(const com::Guid &aId, ComPtr<IProgress> &aProgress)
    3305 
    3306 {
    3307     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    3308 
    3309     if (Global::IsTransient(mMachineState))
    3310         return setError(VBOX_E_INVALID_VM_STATE,
    3311                         tr("Cannot delete a snapshot of the machine while it is changing the state (machine state: %s)"),
    3312                         Global::stringifyMachineState(mMachineState));
    3313 
    3314     ComObjPtr<IProgress> iProgress;
    3315     MachineState_T machineState = MachineState_Null;
    3316     HRESULT rc = mControl->DeleteSnapshot((IConsole *)this, Bstr(aId.toString()).raw(), Bstr(aId.toString()).raw(),
    3317                                           TRUE /* fDeleteAllChildren */, &machineState, iProgress.asOutParam());
    3318     if (FAILED(rc)) return rc;
    3319     iProgress.queryInterfaceTo(aProgress.asOutParam());
    3320 
    3321     i_setMachineStateLocally(machineState);
    3322     return S_OK;
    3323 }
    3324 
    3325 HRESULT Console::deleteSnapshotRange(const com::Guid &aStartId, const com::Guid &aEndId, ComPtr<IProgress> &aProgress)
    3326 {
    3327     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    3328 
    3329     if (Global::IsTransient(mMachineState))
    3330         return setError(VBOX_E_INVALID_VM_STATE,
    3331                         tr("Cannot delete a snapshot of the machine while it is changing the state (machine state: %s)"),
    3332                         Global::stringifyMachineState(mMachineState));
    3333 
    3334     ComObjPtr<IProgress> iProgress;
    3335     MachineState_T machineState = MachineState_Null;
    3336     HRESULT rc = mControl->DeleteSnapshot((IConsole *)this, Bstr(aStartId.toString()).raw(), Bstr(aEndId.toString()).raw(),
    3337                                           FALSE /* fDeleteAllChildren */, &machineState, iProgress.asOutParam());
    3338     if (FAILED(rc)) return rc;
    3339     iProgress.queryInterfaceTo(aProgress.asOutParam());
    3340 
    3341     i_setMachineStateLocally(machineState);
    3342     return S_OK;
    3343 }
    3344 
    3345 HRESULT Console::restoreSnapshot(const ComPtr<ISnapshot> &aSnapshot, ComPtr<IProgress> &aProgress)
    3346 {
    3347     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    3348 
    3349     if (Global::IsOnlineOrTransient(mMachineState))
    3350         return setError(VBOX_E_INVALID_VM_STATE,
    3351                         tr("Cannot delete the current state of the running machine (machine state: %s)"),
    3352                         Global::stringifyMachineState(mMachineState));
    3353 
    3354     ISnapshot* iSnapshot = aSnapshot;
    3355     ComObjPtr<IProgress> iProgress;
    3356     MachineState_T machineState = MachineState_Null;
    3357     HRESULT rc = mControl->RestoreSnapshot((IConsole*)this, iSnapshot, &machineState, iProgress.asOutParam());
    3358     if (FAILED(rc)) return rc;
    3359     iProgress.queryInterfaceTo(aProgress.asOutParam());
    3360 
    3361     i_setMachineStateLocally(machineState);
    3362     return S_OK;
    33633078}
    33643079
     
    36453360                                    getStaticComponentName(),
    36463361                                    Utf8StrFmt("Invalid state '%s' for changing medium",
    3647                                         VMR3GetStateName(enmVMState)),
     3362                                               VMR3GetStateName(enmVMState)),
    36483363                                    false /*aWarning*/,
    36493364                                    true /*aLogIt*/);
     
    62195934
    62205935    /* We will need to release the lock before doing the actual merge */
    6221     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     5936    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    62225937
    62235938    /* paranoia - we don't want merges to happen while teleporting etc. */
     
    62956010    AssertComRCReturnRC(rc);
    62966011
     6012    Assert(mMachineState == MachineState_DeletingSnapshotOnline);
     6013
     6014    /* Pause the VM, as it might have pending IO on this drive */
     6015    bool fResume = false;
     6016    rc = i_suspendBeforeConfigChange(ptrVM.rawUVM(), &alock, &fResume);
     6017    if (FAILED(rc))
     6018        return rc;
     6019
    62976020    alock.release();
    6298 
    6299     /* Pause the VM, as it might have pending IO on this drive */
    6300     VMSTATE enmVMState = VMR3GetStateU(ptrVM.rawUVM());
    6301     if (mMachineState == MachineState_DeletingSnapshotOnline)
    6302     {
    6303         LogFlowFunc(("Suspending the VM...\n"));
    6304         /* disable the callback to prevent Console-level state change */
    6305         mVMStateChangeCallbackDisabled = true;
    6306         int vrc2 = VMR3Suspend(ptrVM.rawUVM(), VMSUSPENDREASON_RECONFIG);
    6307         mVMStateChangeCallbackDisabled = false;
    6308         AssertRCReturn(vrc2, E_FAIL);
    6309     }
    6310 
    63116021    vrc = VMR3ReqCallWaitU(ptrVM.rawUVM(), VMCPUID_ANY,
    63126022                           (PFNRT)i_reconfigureMediumAttachment, 13,
     
    63166026    /* error handling is after resuming the VM */
    63176027
    6318     if (mMachineState == MachineState_DeletingSnapshotOnline)
    6319     {
    6320         LogFlowFunc(("Resuming the VM...\n"));
    6321         /* disable the callback to prevent Console-level state change */
    6322         mVMStateChangeCallbackDisabled = true;
    6323         int vrc2 = VMR3Resume(ptrVM.rawUVM(), VMRESUMEREASON_RECONFIG);
    6324         mVMStateChangeCallbackDisabled = false;
    6325         if (RT_FAILURE(vrc2))
    6326         {
    6327             /* too bad, we failed. try to sync the console state with the VMM state */
    6328             AssertLogRelRC(vrc2);
    6329             i_vmstateChangeCallback(ptrVM.rawUVM(), VMSTATE_SUSPENDED, enmVMState, this);
    6330         }
    6331     }
     6028    if (fResume)
     6029        i_resumeAfterConfigChange(ptrVM.rawUVM());
    63326030
    63336031    if (RT_FAILURE(vrc))
     
    63566054        return setError(E_FAIL, tr("Failed to perform an online medium merge (%Rrc)"), vrc);
    63576055
     6056    alock.acquire();
    63586057    /* Pause the VM, as it might have pending IO on this drive */
    6359     enmVMState = VMR3GetStateU(ptrVM.rawUVM());
    6360     if (mMachineState == MachineState_DeletingSnapshotOnline)
    6361     {
    6362         LogFlowFunc(("Suspending the VM...\n"));
    6363         /* disable the callback to prevent Console-level state change */
    6364         mVMStateChangeCallbackDisabled = true;
    6365         int vrc2 = VMR3Suspend(ptrVM.rawUVM(), VMSUSPENDREASON_RECONFIG);
    6366         mVMStateChangeCallbackDisabled = false;
    6367         AssertRCReturn(vrc2, E_FAIL);
    6368     }
     6058    rc = i_suspendBeforeConfigChange(ptrVM.rawUVM(), &alock, &fResume);
     6059    if (FAILED(rc))
     6060        return rc;
     6061    alock.release();
    63696062
    63706063    /* Update medium chain and state now, so that the VM can continue. */
     
    63786071    /* error handling is after resuming the VM */
    63796072
    6380     if (mMachineState == MachineState_DeletingSnapshotOnline)
    6381     {
    6382         LogFlowFunc(("Resuming the VM...\n"));
    6383         /* disable the callback to prevent Console-level state change */
    6384         mVMStateChangeCallbackDisabled = true;
    6385         int vrc2 = VMR3Resume(ptrVM.rawUVM(), VMRESUMEREASON_RECONFIG);
    6386         mVMStateChangeCallbackDisabled = false;
    6387         AssertRC(vrc2);
    6388         if (RT_FAILURE(vrc2))
    6389         {
    6390             /* too bad, we failed. try to sync the console state with the VMM state */
    6391             i_vmstateChangeCallback(ptrVM.rawUVM(), VMSTATE_SUSPENDED, enmVMState, this);
    6392         }
    6393     }
     6073    if (fResume)
     6074        i_resumeAfterConfigChange(ptrVM.rawUVM());
    63946075
    63956076    if (RT_FAILURE(vrc))
     
    63976078    if (FAILED(rc))
    63986079        return rc;
     6080
     6081    return rc;
     6082}
     6083
     6084HRESULT Console::i_reconfigureMediumAttachments(const std::vector<ComPtr<IMediumAttachment> > &aAttachments)
     6085{
     6086    HRESULT rc = S_OK;
     6087
     6088    AutoCaller autoCaller(this);
     6089    if (FAILED(autoCaller.rc())) return autoCaller.rc();
     6090
     6091    /* get the VM handle. */
     6092    SafeVMPtr ptrVM(this);
     6093    if (!ptrVM.isOk())
     6094        return ptrVM.rc();
     6095
     6096    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     6097
     6098    for (size_t i = 0; i < aAttachments.size(); ++i)
     6099    {
     6100        ComPtr<IStorageController> pStorageController;
     6101        Bstr controllerName;
     6102        ULONG lInstance;
     6103        StorageControllerType_T enmController;
     6104        StorageBus_T enmBus;
     6105        BOOL fUseHostIOCache;
     6106
     6107        /*
     6108         * We could pass the objects, but then EMT would have to do lots of
     6109         * IPC (to VBoxSVC) which takes a significant amount of time.
     6110         * Better query needed values here and pass them.
     6111         */
     6112        rc = aAttachments[i]->COMGETTER(Controller)(controllerName.asOutParam());
     6113        if (FAILED(rc))
     6114            throw rc;
     6115
     6116        rc = mMachine->GetStorageControllerByName(controllerName.raw(),
     6117                                                  pStorageController.asOutParam());
     6118        if (FAILED(rc))
     6119            throw rc;
     6120
     6121        rc = pStorageController->COMGETTER(ControllerType)(&enmController);
     6122        if (FAILED(rc))
     6123            throw rc;
     6124        rc = pStorageController->COMGETTER(Instance)(&lInstance);
     6125        if (FAILED(rc))
     6126            throw rc;
     6127        rc = pStorageController->COMGETTER(Bus)(&enmBus);
     6128        if (FAILED(rc))
     6129            throw rc;
     6130        rc = pStorageController->COMGETTER(UseHostIOCache)(&fUseHostIOCache);
     6131        if (FAILED(rc))
     6132            throw rc;
     6133
     6134        const char *pcszDevice = i_convertControllerTypeToDev(enmController);
     6135
     6136        BOOL fBuiltinIOCache;
     6137        rc = mMachine->COMGETTER(IOCacheEnabled)(&fBuiltinIOCache);
     6138        if (FAILED(rc))
     6139            throw rc;
     6140
     6141        alock.release();
     6142
     6143        int vrc = VMR3ReqCallWaitU(ptrVM.rawUVM(), VMCPUID_ANY,
     6144                                   (PFNRT)i_reconfigureMediumAttachment, 13,
     6145                                   this, ptrVM.rawUVM(), pcszDevice, lInstance, enmBus, fUseHostIOCache,
     6146                                   fBuiltinIOCache, false /* fSetupMerge */, 0 /* uMergeSource */,
     6147                                   0 /* uMergeTarget */, aAttachments[i], mMachineState, &rc);
     6148        if (RT_FAILURE(vrc))
     6149            throw setError(E_FAIL, tr("%Rrc"), vrc);
     6150        if (FAILED(rc))
     6151            throw rc;
     6152
     6153        alock.acquire();
     6154    }
    63996155
    64006156    return rc;
     
    64506206        case MachineState_Paused:
    64516207        case MachineState_TeleportingPausedVM:
    6452         case MachineState_Saving:
     6208        case MachineState_OnlineSnapshotting:
    64536209
    64546210        /* Remove any keys which are supposed to be removed on a suspend. */
     
    65026258 * a specific reason.
    65036259 */
    6504 HRESULT Console::i_resume(Reason_T aReason)
     6260HRESULT Console::i_resume(Reason_T aReason, AutoWriteLock &alock)
    65056261{
    65066262    LogFlowThisFuncEnter();
     
    65086264    AutoCaller autoCaller(this);
    65096265    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    6510 
    6511     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    6512 
    6513     if (mMachineState != MachineState_Paused)
    6514         return setError(VBOX_E_INVALID_VM_STATE,
    6515                         tr("Cannot resume the machine as it is not paused (machine state: %s)"),
    6516                         Global::stringifyMachineState(mMachineState));
    65176266
    65186267    /* get the VM handle. */
     
    65446293        if (aReason == Reason_HostResume)
    65456294            enmReason = VMRESUMEREASON_HOST_RESUME;
     6295        else if (aReason == Reason_Snapshot)
     6296            enmReason = VMRESUMEREASON_STATE_SAVED;
     6297
     6298        // for snapshots: no state change callback, VBoxSVC does everything
     6299        if (aReason == Reason_Snapshot)
     6300            mVMStateChangeCallbackDisabled = true;
    65466301        vrc = VMR3Resume(ptrVM.rawUVM(), enmReason);
     6302        if (aReason == Reason_Snapshot)
     6303            mVMStateChangeCallbackDisabled = false;
    65476304    }
    65486305
     
    65586315
    65596316/**
    6560  * Worker for Console::SaveState and internal entry point for saving state of
    6561  * a VM for a specific reason.
    6562  */
    6563 HRESULT Console::i_saveState(Reason_T aReason, IProgress **aProgress)
     6317 * Internal entry point for saving state of a VM for a specific reason. This
     6318 * method is completely synchronous.
     6319 *
     6320 * The machine state is already set appropriately. It is only changed when
     6321 * saving state actually paused the VM (happens with live snapshots and
     6322 * teleportation), and in this case reflects the now paused variant.
     6323 *
     6324 * @note Locks this object for writing.
     6325 */
     6326HRESULT Console::i_saveState(Reason_T aReason, const ComPtr<IProgress> &aProgress, const Utf8Str &aStateFilePath, bool aPauseVM, bool &aLeftPaused)
    65646327{
    65656328    LogFlowThisFuncEnter();
    6566 
    6567     CheckComArgOutPointerValid(aProgress);
     6329    aLeftPaused = false;
     6330
     6331    AssertReturn(!aProgress.isNull(), E_INVALIDARG);
     6332    AssertReturn(!aStateFilePath.isEmpty(), E_INVALIDARG);
    65686333
    65696334    AutoCaller autoCaller(this);
     
    65736338
    65746339    LogFlowThisFunc(("mMachineState=%d\n", mMachineState));
    6575     if (   mMachineState != MachineState_Running
    6576         && mMachineState != MachineState_Paused)
     6340    if (   mMachineState != MachineState_Saving
     6341        && mMachineState != MachineState_LiveSnapshotting
     6342        && mMachineState != MachineState_OnlineSnapshotting
     6343        && mMachineState != MachineState_Teleporting
     6344        && mMachineState != MachineState_TeleportingPausedVM)
    65776345    {
    65786346        return setError(VBOX_E_INVALID_VM_STATE,
     
    65806348            Global::stringifyMachineState(mMachineState));
    65816349    }
     6350    bool fContinueAfterwards = mMachineState != MachineState_Saving;
    65826351
    65836352    Bstr strDisableSaveState;
     
    65906359        LogRel(("Saving state of VM, reason \"%s\"\n", Global::stringifyReason(aReason)));
    65916360
    6592     /* memorize the current machine state */
    6593     MachineState_T lastMachineState = mMachineState;
    6594 
    6595     if (mMachineState == MachineState_Running)
    6596     {
    6597         /* get the VM handle. */
    6598         SafeVMPtr ptrVM(this);
    6599         if (!ptrVM.isOk())
    6600             return ptrVM.rc();
    6601 
     6361    /* ensure the directory for the saved state file exists */
     6362    {
     6363        Utf8Str dir = aStateFilePath;
     6364        dir.stripFilename();
     6365        if (!RTDirExists(dir.c_str()))
     6366        {
     6367            int vrc = RTDirCreateFullPath(dir.c_str(), 0700);
     6368            if (RT_FAILURE(vrc))
     6369                return setError(VBOX_E_FILE_ERROR,
     6370                                tr("Could not create a directory '%s' to save the state to (%Rrc)"),
     6371                                dir.c_str(), vrc);
     6372        }
     6373    }
     6374
     6375    /* Get the VM handle early, we need it in several places. */
     6376    SafeVMPtr ptrVM(this);
     6377    if (!ptrVM.isOk())
     6378        return ptrVM.rc();
     6379
     6380    bool fPaused = false;
     6381    if (aPauseVM)
     6382    {
    66026383        /* release the lock before a VMR3* call (EMT might wait for it, @bugref{7648})! */
    66036384        alock.release();
     
    66106391        alock.acquire();
    66116392
    6612         HRESULT hrc = S_OK;
    66136393        if (RT_FAILURE(vrc))
    6614             hrc = setError(VBOX_E_VM_ERROR, tr("Could not suspend the machine execution (%Rrc)"), vrc);
    6615         if (FAILED(hrc))
    6616             return hrc;
    6617     }
    6618 
    6619     HRESULT rc = S_OK;
    6620     bool fBeganSavingState = false;
    6621     bool fTaskCreationFailed = false;
    6622 
    6623     do
    6624     {
    6625         ComPtr<IProgress> pProgress;
    6626         Bstr stateFilePath;
    6627 
     6394            return setError(VBOX_E_VM_ERROR, tr("Could not suspend the machine execution (%Rrc)"), vrc);
     6395        fPaused = true;
     6396    }
     6397
     6398    LogFlowFunc(("Saving the state to '%s'...\n", aStateFilePath.c_str()));
     6399
     6400    mptrCancelableProgress = aProgress;
     6401    alock.release();
     6402    int vrc = VMR3Save(ptrVM.rawUVM(),
     6403                       aStateFilePath.c_str(),
     6404                       fContinueAfterwards,
     6405                       Console::i_stateProgressCallback,
     6406                       static_cast<IProgress *>(aProgress),
     6407                       &aLeftPaused);
     6408    alock.acquire();
     6409    mptrCancelableProgress.setNull();
     6410    if (RT_FAILURE(vrc))
     6411    {
     6412        if (fPaused)
     6413        {
     6414            alock.release();
     6415            VMR3Resume(ptrVM.rawUVM(), VMRESUMEREASON_STATE_RESTORED);
     6416            alock.acquire();
     6417        }
     6418        return setError(E_FAIL, tr("Failed to save the machine state to '%s' (%Rrc)"),
     6419                        aStateFilePath.c_str(), vrc);
     6420    }
     6421    Assert(fContinueAfterwards || !aLeftPaused);
     6422
     6423    if (!fContinueAfterwards)
     6424    {
    66286425        /*
    6629          * request a saved state file path from the server
    6630          * (this will set the machine state to Saving on the server to block
    6631          * others from accessing this machine)
     6426         * The machine has been successfully saved, so power it down
     6427         * (vmstateChangeCallback() will set state to Saved on success).
     6428         * Note: we release the VM caller, otherwise it will deadlock.
    66326429         */
    6633         rc = mControl->BeginSavingState(pProgress.asOutParam(),
    6634                                         stateFilePath.asOutParam());
    6635         if (FAILED(rc))
    6636             break;
    6637 
    6638         fBeganSavingState = true;
    6639 
    6640         /* sync the state with the server */
    6641         i_setMachineStateLocally(MachineState_Saving);
    6642 
    6643         /* ensure the directory for the saved state file exists */
    6644         {
    6645             Utf8Str dir = stateFilePath;
    6646             dir.stripFilename();
    6647             if (!RTDirExists(dir.c_str()))
    6648             {
    6649                 int vrc = RTDirCreateFullPath(dir.c_str(), 0700);
    6650                 if (RT_FAILURE(vrc))
    6651                 {
    6652                     rc = setError(VBOX_E_FILE_ERROR,
    6653                         tr("Could not create a directory '%s' to save the state to (%Rrc)"),
    6654                         dir.c_str(), vrc);
    6655                     break;
    6656                 }
    6657             }
    6658         }
    6659 
    6660         /* Create a task object early to ensure mpUVM protection is successful. */
    6661         std::auto_ptr<VMSaveTask> task(new VMSaveTask(this, pProgress,
    6662                                                       stateFilePath,
    6663                                                       lastMachineState,
    6664                                                       aReason));
    6665         rc = task->rc();
    6666         /*
    6667          * If we fail here it means a PowerDown() call happened on another
    6668          * thread while we were doing Pause() (which releases the Console lock).
    6669          * We assign PowerDown() a higher precedence than SaveState(),
    6670          * therefore just return the error to the caller.
    6671          */
    6672         if (FAILED(rc))
    6673         {
    6674             fTaskCreationFailed = true;
    6675             break;
    6676         }
    6677 
    6678         /* create a thread to wait until the VM state is saved */
    6679         int vrc = RTThreadCreate(NULL, Console::i_saveStateThread, (void *)task.get(),
    6680                                  0, RTTHREADTYPE_MAIN_WORKER, 0, "VMSave");
    6681         if (RT_FAILURE(vrc))
    6682         {
    6683             rc = setError(E_FAIL, "Could not create VMSave thread (%Rrc)", vrc);
    6684             break;
    6685         }
    6686 
    6687         /* task is now owned by saveStateThread(), so release it */
    6688         task.release();
    6689 
    6690         /* return the progress to the caller */
    6691         pProgress.queryInterfaceTo(aProgress);
    6692     } while (0);
    6693 
    6694     if (FAILED(rc) && !fTaskCreationFailed)
    6695     {
    6696         /* preserve existing error info */
    6697         ErrorInfoKeeper eik;
    6698 
    6699         if (fBeganSavingState)
    6700         {
    6701             /*
    6702              * cancel the requested save state procedure.
    6703              * This will reset the machine state to the state it had right
    6704              * before calling mControl->BeginSavingState().
    6705              */
    6706             mControl->EndSavingState(eik.getResultCode(), eik.getText().raw());
    6707         }
    6708 
    6709         if (lastMachineState == MachineState_Running)
    6710         {
    6711             /* restore the paused state if appropriate */
    6712             i_setMachineStateLocally(MachineState_Paused);
    6713             /* restore the running state if appropriate */
    6714             SafeVMPtr ptrVM(this);
    6715             if (ptrVM.isOk())
    6716             {
    6717                 alock.release();
    6718                 VMR3Resume(ptrVM.rawUVM(), VMRESUMEREASON_STATE_RESTORED);
    6719                 alock.acquire();
    6720             }
    6721         }
    6722         else
    6723             i_setMachineStateLocally(lastMachineState);
    6724     }
    6725 
    6726     LogFlowThisFunc(("rc=%Rhrc\n", rc));
    6727     LogFlowThisFuncLeave();
    6728     return rc;
     6430        ptrVM.release();
     6431        alock.release();
     6432        autoCaller.release();
     6433        HRESULT rc = i_powerDown();
     6434        AssertComRC(rc);
     6435        autoCaller.add();
     6436        alock.acquire();
     6437    }
     6438    else
     6439    {
     6440        if (fPaused)
     6441            aLeftPaused = true;
     6442    }
     6443
     6444    LogFlowFuncLeave();
     6445    return S_OK;
     6446}
     6447
     6448/**
     6449 * Internal entry point for cancelling a VM save state.
     6450 *
     6451 * @note Locks this object for writing.
     6452 */
     6453HRESULT Console::i_cancelSaveState()
     6454{
     6455    LogFlowThisFuncEnter();
     6456
     6457    AutoCaller autoCaller(this);
     6458    if (FAILED(autoCaller.rc())) return autoCaller.rc();
     6459
     6460    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     6461
     6462    /* Get the VM handle. */
     6463    SafeVMPtr ptrVM(this);
     6464    if (!ptrVM.isOk())
     6465        return ptrVM.rc();
     6466
     6467    SSMR3Cancel(ptrVM.rawUVM());
     6468
     6469    LogFlowFuncLeave();
     6470    return S_OK;
    67296471}
    67306472
     
    67456487
    67466488    AssertReturn(   mMachineState == MachineState_Saving
     6489                 || mMachineState == MachineState_OnlineSnapshotting
    67476490                 || mMachineState == MachineState_LiveSnapshotting
    6748                  || mMachineState == MachineState_RestoringSnapshot
    6749                  || mMachineState == MachineState_DeletingSnapshot
    67506491                 || mMachineState == MachineState_DeletingSnapshotOnline
    67516492                 || mMachineState == MachineState_DeletingSnapshotPaused
     6493                 || aMachineState == MachineState_Saving
     6494                 || aMachineState == MachineState_OnlineSnapshotting
     6495                 || aMachineState == MachineState_LiveSnapshotting
     6496                 || aMachineState == MachineState_DeletingSnapshotOnline
     6497                 || aMachineState == MachineState_DeletingSnapshotPaused
    67526498                 , E_FAIL);
    67536499
    67546500    return i_setMachineStateLocally(aMachineState);
     6501}
     6502
     6503/**
     6504 * Gets called by Session::COMGETTER(NominalState)()
     6505 * (IInternalSessionControl::getNominalState()).
     6506 *
     6507 * @note Locks this object for reading.
     6508 */
     6509HRESULT Console::i_getNominalState(MachineState_T &aNominalState)
     6510{
     6511    LogFlowThisFuncEnter();
     6512
     6513    AutoCaller autoCaller(this);
     6514    AssertComRCReturnRC(autoCaller.rc());
     6515
     6516    /* Get the VM handle. */
     6517    SafeVMPtr ptrVM(this);
     6518    if (!ptrVM.isOk())
     6519        return ptrVM.rc();
     6520
     6521    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     6522
     6523    MachineState_T enmMachineState = MachineState_Null;
     6524    VMSTATE enmVMState = VMR3GetStateU(ptrVM.rawUVM());
     6525    switch (enmVMState)
     6526    {
     6527        case VMSTATE_CREATING:
     6528        case VMSTATE_CREATED:
     6529        case VMSTATE_POWERING_ON:
     6530            enmMachineState = MachineState_Starting;
     6531            break;
     6532        case VMSTATE_LOADING:
     6533            enmMachineState = MachineState_Restoring;
     6534            break;
     6535        case VMSTATE_RESUMING:
     6536        case VMSTATE_SUSPENDING:
     6537        case VMSTATE_SUSPENDING_LS:
     6538        case VMSTATE_SUSPENDING_EXT_LS:
     6539        case VMSTATE_SUSPENDED:
     6540        case VMSTATE_SUSPENDED_LS:
     6541        case VMSTATE_SUSPENDED_EXT_LS:
     6542            enmMachineState = MachineState_Paused;
     6543            break;
     6544        case VMSTATE_RUNNING:
     6545        case VMSTATE_RUNNING_LS:
     6546        case VMSTATE_RUNNING_FT:
     6547        case VMSTATE_RESETTING:
     6548        case VMSTATE_RESETTING_LS:
     6549        case VMSTATE_DEBUGGING:
     6550        case VMSTATE_DEBUGGING_LS:
     6551            enmMachineState = MachineState_Running;
     6552            break;
     6553        case VMSTATE_SAVING:
     6554            enmMachineState = MachineState_Saving;
     6555            break;
     6556        case VMSTATE_POWERING_OFF:
     6557        case VMSTATE_POWERING_OFF_LS:
     6558        case VMSTATE_DESTROYING:
     6559            enmMachineState = MachineState_Stopping;
     6560            break;
     6561        case VMSTATE_OFF:
     6562        case VMSTATE_OFF_LS:
     6563        case VMSTATE_FATAL_ERROR:
     6564        case VMSTATE_FATAL_ERROR_LS:
     6565        case VMSTATE_LOAD_FAILURE:
     6566        case VMSTATE_TERMINATED:
     6567            enmMachineState = MachineState_PoweredOff;
     6568            break;
     6569        case VMSTATE_GURU_MEDITATION:
     6570        case VMSTATE_GURU_MEDITATION_LS:
     6571            enmMachineState = MachineState_Stuck;
     6572            break;
     6573        default:
     6574            AssertMsgFailed(("%s\n", VMR3GetStateName(enmVMState)));
     6575            enmMachineState = MachineState_PoweredOff;
     6576    }
     6577    aNominalState = enmMachineState;
     6578
     6579    LogFlowFuncLeave();
     6580    return S_OK;
    67556581}
    67566582
     
    71606986    try
    71616987    {
    7162 
    71636988        if (Global::IsOnlineOrTransient(mMachineState))
    71646989            throw setError(VBOX_E_INVALID_VM_STATE,
     
    72737098        }
    72747099
    7275         /* Setup task object and thread to carry out the operaton
    7276          * Asycnhronously */
     7100        /* Setup task object and thread to carry out the operation
     7101         * asynchronously */
    72777102        std::auto_ptr<VMPowerUpTask> task(new VMPowerUpTask(this, pPowerupProgress));
    72787103        ComAssertComRCRetRC(task->rc());
     
    78927717 */
    78937718HRESULT Console::i_setMachineState(MachineState_T aMachineState,
    7894                                  bool aUpdateServer /* = true */)
     7719                                   bool aUpdateServer /* = true */)
    78957720{
    78967721    AutoCaller autoCaller(this);
     
    79057730        LogThisFunc(("machineState=%s -> %s aUpdateServer=%RTbool\n",
    79067731                     Global::stringifyMachineState(mMachineState), Global::stringifyMachineState(aMachineState), aUpdateServer));
     7732        LogRel(("Console: machine state changed to %s\n", Global::stringifyMachineState(aMachineState)));
    79077733        mMachineState = aMachineState;
    79087734
     
    85158341
    85168342                case MachineState_LiveSnapshotting:
    8517                     that->i_setMachineState(MachineState_Saving);
     8343                    that->i_setMachineState(MachineState_OnlineSnapshotting);
    85188344                    break;
    85198345
     
    85248350                case MachineState_TeleportingIn:
    85258351                case MachineState_FaultTolerantSyncing:
     8352                case MachineState_OnlineSnapshotting:
    85268353                    /* The worker thread handles the transition. */
    85278354                    break;
    85288355
    8529                 default:
    8530                     AssertMsgFailed(("%s\n", Global::stringifyMachineState(that->mMachineState)));
    85318356                case MachineState_Running:
    85328357                    that->i_setMachineState(MachineState_Paused);
     
    85368361                    /* Nothing to do. */
    85378362                    break;
     8363
     8364                default:
     8365                    AssertMsgFailed(("%s\n", Global::stringifyMachineState(that->mMachineState)));
    85388366            }
    85398367            break;
     
    85538381
    85548382                case MachineState_LiveSnapshotting:
    8555                     that->i_setMachineState(MachineState_Saving);
     8383                    that->i_setMachineState(MachineState_OnlineSnapshotting);
    85568384                    break;
    85578385
     
    96139441        // Create the VMM device object, which starts the HGCM thread; do this only
    96149442        // once for the console, for the pathological case that the same console
    9615         // object is used to power up a VM twice. VirtualBox 4.0: we now do that
    9616         // here instead of the Console constructor (see Console::init())
     9443        // object is used to power up a VM twice.
    96179444        if (!pConsole->m_pVMMDev)
    96189445        {
     
    101029929
    101039930/**
    10104  * Progress cancelation callback employed by Console::fntTakeSnapshotWorker.
    10105  */
    10106 static void takesnapshotProgressCancelCallback(void *pvUser)
    10107 {
    10108     PUVM pUVM = (PUVM)pvUser;
    10109     SSMR3Cancel(pUVM);
    10110 }
    10111 
    10112 /**
    10113  * Worker thread created by Console::TakeSnapshot.
    10114  * @param Thread The current thread (ignored).
    10115  * @param pvUser The task.
    10116  * @return VINF_SUCCESS (ignored).
    10117  */
    10118 /*static*/
    10119 DECLCALLBACK(int) Console::i_fntTakeSnapshotWorker(RTTHREAD Thread, void *pvUser)
    10120 {
    10121     VMTakeSnapshotTask *pTask = (VMTakeSnapshotTask*)pvUser;
    10122 
    10123     // taking a snapshot consists of the following:
    10124 
    10125     // 1) creating a diff image for each virtual hard disk, into which write operations go after
    10126     //    the snapshot has been created (done in VBoxSVC, in SessionMachine::BeginTakingSnapshot)
    10127     // 2) creating a Snapshot object with the state of the machine (hardware + storage,
    10128     //    done in VBoxSVC, also in SessionMachine::BeginTakingSnapshot)
    10129     // 3) saving the state of the virtual machine (here, in the VM process, if the machine is online)
    10130 
    10131     Console    *that                 = pTask->mConsole;
    10132     bool        fBeganTakingSnapshot = false;
    10133     bool        fSuspenededBySave    = false;
    10134 
    10135     AutoCaller autoCaller(that);
    10136     if (FAILED(autoCaller.rc()))
    10137     {
    10138         that->mptrCancelableProgress.setNull();
    10139         return autoCaller.rc();
    10140     }
    10141 
    10142     AutoWriteLock alock(that COMMA_LOCKVAL_SRC_POS);
    10143 
    10144     HRESULT rc = S_OK;
    10145 
    10146     try
    10147     {
    10148         /* STEP 1 + 2:
    10149          * request creating the diff images on the server and create the snapshot object
    10150          * (this will set the machine state to Saving on the server to block
    10151          * others from accessing this machine)
    10152          */
    10153         rc = that->mControl->BeginTakingSnapshot(that,
    10154                                                  pTask->bstrName.raw(),
    10155                                                  pTask->bstrDescription.raw(),
    10156                                                  pTask->mProgress,
    10157                                                  pTask->fTakingSnapshotOnline,
    10158                                                  pTask->bstrSavedStateFile.asOutParam());
    10159         if (FAILED(rc))
    10160             throw rc;
    10161 
    10162         fBeganTakingSnapshot = true;
    10163 
    10164         /* Check sanity: for offline snapshots there must not be a saved state
    10165          * file name. All other combinations are valid (even though online
    10166          * snapshots without saved state file seems inconsistent - there are
    10167          * some exotic use cases, which need to be explicitly enabled, see the
    10168          * code of SessionMachine::BeginTakingSnapshot. */
    10169         if (   !pTask->fTakingSnapshotOnline
    10170             && !pTask->bstrSavedStateFile.isEmpty())
    10171             throw i_setErrorStatic(E_FAIL, "Invalid state of saved state file");
    10172 
    10173         /* sync the state with the server */
    10174         if (pTask->lastMachineState == MachineState_Running)
    10175             that->i_setMachineStateLocally(MachineState_LiveSnapshotting);
    10176         else
    10177             that->i_setMachineStateLocally(MachineState_Saving);
    10178 
    10179         // STEP 3: save the VM state (if online)
    10180         if (pTask->fTakingSnapshotOnline)
    10181         {
    10182             int vrc;
    10183             SafeVMPtr ptrVM(that);
    10184             if (!ptrVM.isOk())
    10185                 throw ptrVM.rc();
    10186 
    10187             pTask->mProgress->SetNextOperation(Bstr(tr("Saving the machine state")).raw(),
    10188                                                pTask->ulMemSize);       // operation weight, same as computed
    10189                                                                         // when setting up progress object
    10190             if (!pTask->bstrSavedStateFile.isEmpty())
    10191             {
    10192                 Utf8Str strSavedStateFile(pTask->bstrSavedStateFile);
    10193 
    10194                 pTask->mProgress->i_setCancelCallback(takesnapshotProgressCancelCallback, ptrVM.rawUVM());
    10195 
    10196                 alock.release();
    10197                 LogFlowFunc(("VMR3Save...\n"));
    10198                 vrc = VMR3Save(ptrVM.rawUVM(),
    10199                                strSavedStateFile.c_str(),
    10200                                true /*fContinueAfterwards*/,
    10201                                Console::i_stateProgressCallback,
    10202                                static_cast<IProgress *>(pTask->mProgress),
    10203                                &fSuspenededBySave);
    10204                 alock.acquire();
    10205                 if (RT_FAILURE(vrc))
    10206                     throw i_setErrorStatic(E_FAIL,
    10207                                          tr("Failed to save the machine state to '%s' (%Rrc)"),
    10208                                          strSavedStateFile.c_str(), vrc);
    10209 
    10210                 pTask->mProgress->i_setCancelCallback(NULL, NULL);
    10211             }
    10212             else
    10213                 LogRel(("Console: skipped saving state as part of online snapshot\n"));
    10214 
    10215             if (!pTask->mProgress->i_notifyPointOfNoReturn())
    10216                 throw i_setErrorStatic(E_FAIL, tr("Canceled"));
    10217             that->mptrCancelableProgress.setNull();
    10218 
    10219             // STEP 4: reattach hard disks
    10220             LogFlowFunc(("Reattaching new differencing hard disks...\n"));
    10221 
    10222             pTask->mProgress->SetNextOperation(Bstr(tr("Reconfiguring medium attachments")).raw(),
    10223                                                1);       // operation weight, same as computed when setting up progress object
    10224 
    10225             com::SafeIfaceArray<IMediumAttachment> atts;
    10226             rc = that->mMachine->COMGETTER(MediumAttachments)(ComSafeArrayAsOutParam(atts));
    10227             if (FAILED(rc))
    10228                 throw rc;
    10229 
    10230             for (size_t i = 0;
    10231                 i < atts.size();
    10232                 ++i)
    10233             {
    10234                 ComPtr<IStorageController> pStorageController;
    10235                 Bstr controllerName;
    10236                 ULONG lInstance;
    10237                 StorageControllerType_T enmController;
    10238                 StorageBus_T enmBus;
    10239                 BOOL fUseHostIOCache;
    10240 
    10241                 /*
    10242                 * We can't pass a storage controller object directly
    10243                 * (g++ complains about not being able to pass non POD types through '...')
    10244                 * so we have to query needed values here and pass them.
    10245                 */
    10246                 rc = atts[i]->COMGETTER(Controller)(controllerName.asOutParam());
    10247                 if (FAILED(rc))
    10248                     throw rc;
    10249 
    10250                 rc = that->mMachine->GetStorageControllerByName(controllerName.raw(),
    10251                                                                 pStorageController.asOutParam());
    10252                 if (FAILED(rc))
    10253                     throw rc;
    10254 
    10255                 rc = pStorageController->COMGETTER(ControllerType)(&enmController);
    10256                 if (FAILED(rc))
    10257                     throw rc;
    10258                 rc = pStorageController->COMGETTER(Instance)(&lInstance);
    10259                 if (FAILED(rc))
    10260                     throw rc;
    10261                 rc = pStorageController->COMGETTER(Bus)(&enmBus);
    10262                 if (FAILED(rc))
    10263                     throw rc;
    10264                 rc = pStorageController->COMGETTER(UseHostIOCache)(&fUseHostIOCache);
    10265                 if (FAILED(rc))
    10266                     throw rc;
    10267 
    10268                 const char *pcszDevice = Console::i_convertControllerTypeToDev(enmController);
    10269 
    10270                 BOOL fBuiltinIOCache;
    10271                 rc = that->mMachine->COMGETTER(IOCacheEnabled)(&fBuiltinIOCache);
    10272                 if (FAILED(rc))
    10273                     throw rc;
    10274 
    10275                 alock.release();
    10276                 vrc = VMR3ReqCallWaitU(ptrVM.rawUVM(), VMCPUID_ANY,
    10277                                        (PFNRT)i_reconfigureMediumAttachment, 13,
    10278                                        that, ptrVM.rawUVM(), pcszDevice, lInstance, enmBus, fUseHostIOCache,
    10279                                        fBuiltinIOCache, false /* fSetupMerge */, 0 /* uMergeSource */,
    10280                                        0 /* uMergeTarget */, atts[i], that->mMachineState, &rc);
    10281                 alock.acquire();
    10282                 if (RT_FAILURE(vrc))
    10283                     throw i_setErrorStatic(E_FAIL, Console::tr("%Rrc"), vrc);
    10284                 if (FAILED(rc))
    10285                     throw rc;
    10286             }
    10287         }
    10288 
    10289         /*
    10290          * finalize the requested snapshot object.
    10291          * This will reset the machine state to the state it had right
    10292          * before calling mControl->BeginTakingSnapshot().
    10293          */
    10294         rc = that->mControl->EndTakingSnapshot(TRUE /*aSuccess*/);
    10295         // do not throw rc here because we can't call EndTakingSnapshot() twice
    10296         LogFlowFunc(("EndTakingSnapshot -> %Rhrc [mMachineState=%s]\n", rc, Global::stringifyMachineState(that->mMachineState)));
    10297     }
    10298     catch (HRESULT rcThrown)
    10299     {
    10300         /* preserve existing error info */
    10301         ErrorInfoKeeper eik;
    10302 
    10303         if (fBeganTakingSnapshot)
    10304             that->mControl->EndTakingSnapshot(FALSE /*aSuccess*/);
    10305 
    10306         rc = rcThrown;
    10307         LogFunc(("Caught %Rhrc [mMachineState=%s]\n", rc, Global::stringifyMachineState(that->mMachineState)));
    10308     }
    10309     Assert(alock.isWriteLockOnCurrentThread());
    10310 
    10311     if (FAILED(rc)) /* Must come before calling setMachineState. */
    10312         pTask->mProgress->i_notifyComplete(rc);
    10313 
    10314     /*
    10315      * Fix up the machine state.
    10316      *
    10317      * For live snapshots we do all the work, for the two other variations we
    10318      * just update the local copy.
    10319      */
    10320     MachineState_T enmMachineState;
    10321     that->mMachine->COMGETTER(State)(&enmMachineState);
    10322     if (   that->mMachineState == MachineState_LiveSnapshotting
    10323         || that->mMachineState == MachineState_Saving)
    10324     {
    10325 
    10326         if (!pTask->fTakingSnapshotOnline)
    10327             that->i_setMachineStateLocally(pTask->lastMachineState);
    10328         else if (SUCCEEDED(rc))
    10329         {
    10330             Assert(   pTask->lastMachineState == MachineState_Running
    10331                    || pTask->lastMachineState == MachineState_Paused);
    10332             Assert(that->mMachineState == MachineState_Saving);
    10333             if (pTask->lastMachineState == MachineState_Running)
    10334             {
    10335                 LogFlowFunc(("VMR3Resume...\n"));
    10336                 SafeVMPtr ptrVM(that);
    10337                 alock.release();
    10338                 int vrc = VMR3Resume(ptrVM.rawUVM(), VMRESUMEREASON_STATE_SAVED);
    10339                 alock.acquire();
    10340                 if (RT_FAILURE(vrc))
    10341                 {
    10342                     rc = i_setErrorStatic(VBOX_E_VM_ERROR, tr("Could not resume the machine execution (%Rrc)"), vrc);
    10343                     pTask->mProgress->i_notifyComplete(rc);
    10344                     if (that->mMachineState == MachineState_Saving)
    10345                         that->i_setMachineStateLocally(MachineState_Paused);
    10346                 }
    10347             }
    10348             else
    10349                 that->i_setMachineStateLocally(MachineState_Paused);
    10350         }
    10351         else
    10352         {
    10353             /** @todo this could probably be made more generic and reused elsewhere. */
    10354             /* paranoid cleanup on for a failed online snapshot. */
    10355             VMSTATE enmVMState = VMR3GetStateU(that->mpUVM);
    10356             switch (enmVMState)
    10357             {
    10358                 case VMSTATE_RUNNING:
    10359                 case VMSTATE_RUNNING_LS:
    10360                 case VMSTATE_DEBUGGING:
    10361                 case VMSTATE_DEBUGGING_LS:
    10362                 case VMSTATE_POWERING_OFF:
    10363                 case VMSTATE_POWERING_OFF_LS:
    10364                 case VMSTATE_RESETTING:
    10365                 case VMSTATE_RESETTING_LS:
    10366                     Assert(!fSuspenededBySave);
    10367                     that->i_setMachineState(MachineState_Running);
    10368                     break;
    10369 
    10370                 case VMSTATE_GURU_MEDITATION:
    10371                 case VMSTATE_GURU_MEDITATION_LS:
    10372                     that->i_setMachineState(MachineState_Stuck);
    10373                     break;
    10374 
    10375                 case VMSTATE_FATAL_ERROR:
    10376                 case VMSTATE_FATAL_ERROR_LS:
    10377                     if (pTask->lastMachineState == MachineState_Paused)
    10378                         that->i_setMachineStateLocally(pTask->lastMachineState);
    10379                     else
    10380                         that->i_setMachineState(MachineState_Paused);
    10381                     break;
    10382 
    10383                 default:
    10384                     AssertMsgFailed(("%s\n", VMR3GetStateName(enmVMState)));
    10385                 case VMSTATE_SUSPENDED:
    10386                 case VMSTATE_SUSPENDED_LS:
    10387                 case VMSTATE_SUSPENDING:
    10388                 case VMSTATE_SUSPENDING_LS:
    10389                 case VMSTATE_SUSPENDING_EXT_LS:
    10390                     if (fSuspenededBySave)
    10391                     {
    10392                         Assert(pTask->lastMachineState == MachineState_Running);
    10393                         LogFlowFunc(("VMR3Resume (on failure)...\n"));
    10394                         SafeVMPtr ptrVM(that);
    10395                         alock.release();
    10396                         int vrc = VMR3Resume(ptrVM.rawUVM(), VMRESUMEREASON_STATE_SAVED); AssertLogRelRC(vrc);
    10397                         alock.acquire();
    10398                         if (RT_FAILURE(vrc))
    10399                             that->i_setMachineState(MachineState_Paused);
    10400                     }
    10401                     else if (pTask->lastMachineState == MachineState_Paused)
    10402                         that->i_setMachineStateLocally(pTask->lastMachineState);
    10403                     else
    10404                         that->i_setMachineState(MachineState_Paused);
    10405                     break;
    10406             }
    10407 
    10408         }
    10409     }
    10410     /*else: somebody else has change the state... Leave it. */
    10411 
    10412     /* check the remote state to see that we got it right. */
    10413     that->mMachine->COMGETTER(State)(&enmMachineState);
    10414     AssertLogRelMsg(that->mMachineState == enmMachineState,
    10415                     ("mMachineState=%s enmMachineState=%s\n", Global::stringifyMachineState(that->mMachineState),
    10416                      Global::stringifyMachineState(enmMachineState) ));
    10417 
    10418 
    10419     if (SUCCEEDED(rc)) /* The failure cases are handled above. */
    10420         pTask->mProgress->i_notifyComplete(rc);
    10421 
    10422     delete pTask;
    10423 
    10424     LogFlowFuncLeave();
    10425     return VINF_SUCCESS;
    10426 }
    10427 
    10428 /**
    10429  * Thread for executing the saved state operation.
    10430  *
    10431  * @param   Thread      The thread handle.
    10432  * @param   pvUser      Pointer to a VMSaveTask structure.
    10433  * @return  VINF_SUCCESS (ignored).
    10434  *
    10435  * @note Locks the Console object for writing.
    10436  */
    10437 /*static*/
    10438 DECLCALLBACK(int) Console::i_saveStateThread(RTTHREAD Thread, void *pvUser)
    10439 {
    10440     LogFlowFuncEnter();
    10441 
    10442     std::auto_ptr<VMSaveTask> task(static_cast<VMSaveTask*>(pvUser));
    10443     AssertReturn(task.get(), VERR_INVALID_PARAMETER);
    10444 
    10445     Assert(task->mSavedStateFile.length());
    10446     Assert(task->mProgress.isNull());
    10447     Assert(!task->mServerProgress.isNull());
    10448 
    10449     const ComObjPtr<Console> &that = task->mConsole;
    10450     Utf8Str errMsg;
    10451     HRESULT rc = S_OK;
    10452 
    10453     LogFlowFunc(("Saving the state to '%s'...\n", task->mSavedStateFile.c_str()));
    10454 
    10455     bool fSuspenededBySave;
    10456     int vrc = VMR3Save(task->mpUVM,
    10457                        task->mSavedStateFile.c_str(),
    10458                        false, /*fContinueAfterwards*/
    10459                        Console::i_stateProgressCallback,
    10460                        static_cast<IProgress *>(task->mServerProgress),
    10461                        &fSuspenededBySave);
    10462     if (RT_FAILURE(vrc))
    10463     {
    10464         errMsg = Utf8StrFmt(Console::tr("Failed to save the machine state to '%s' (%Rrc)"),
    10465                             task->mSavedStateFile.c_str(), vrc);
    10466         rc = E_FAIL;
    10467     }
    10468     Assert(!fSuspenededBySave);
    10469 
    10470     /* lock the console once we're going to access it */
    10471     AutoWriteLock thatLock(that COMMA_LOCKVAL_SRC_POS);
    10472 
    10473     /* synchronize the state with the server */
    10474     if (SUCCEEDED(rc))
    10475     {
    10476         /*
    10477          * The machine has been successfully saved, so power it down
    10478          * (vmstateChangeCallback() will set state to Saved on success).
    10479          * Note: we release the task's VM caller, otherwise it will
    10480          * deadlock.
    10481          */
    10482         task->releaseVMCaller();
    10483         thatLock.release();
    10484         rc = that->i_powerDown();
    10485         thatLock.acquire();
    10486     }
    10487 
    10488     /*
    10489      * If we failed, reset the local machine state.
    10490      */
    10491     if (FAILED(rc))
    10492         that->i_setMachineStateLocally(task->mMachineStateBefore);
    10493 
    10494     /*
    10495      * Finalize the requested save state procedure. In case of failure it will
    10496      * reset the machine state to the state it had right before calling
    10497      * mControl->BeginSavingState(). This must be the last thing because it
    10498      * will set the progress to completed, and that means that the frontend
    10499      * can immediately uninit the associated console object.
    10500      */
    10501     that->mControl->EndSavingState(rc, Bstr(errMsg).raw());
    10502 
    10503     LogFlowFuncLeave();
    10504     return VINF_SUCCESS;
    10505 }
    10506 
    10507 /**
    105089931 * Thread for powering down the Console.
    105099932 *
     
    105609983    /*
    105619984     * For now, just call SaveState.  We should probably try notify the GUI so
    10562      * it can pop up a progress object and stuff.
     9985     * it can pop up a progress object and stuff. The progress object created
     9986     * by the call isn't returned to anyone and thus gets updated without
     9987     * anyone noticing it.
    105639988     */
    10564     HRESULT hrc = pConsole->SaveState(NULL);
     9989    ComPtr<IProgress> pProgress;
     9990    HRESULT hrc = pConsole->mMachine->SaveState(pProgress.asOutParam());
    105659991    return SUCCEEDED(hrc) ? VINF_SUCCESS : Global::vboxStatusCodeFromCOM(hrc);
    105669992}
  • trunk/src/VBox/Main/src-client/ConsoleImplTeleporter.cpp

    r51612 r55214  
    55
    66/*
    7  * Copyright (C) 2010-2014 Oracle Corporation
     7 * Copyright (C) 2010-2015 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    997997        {
    998998            ptrProgress.queryInterfaceTo(aProgress.asOutParam());
    999             mptrCancelableProgress = ptrProgress;
     999            mptrCancelableProgress = aProgress;
    10001000        }
    10011001        else
  • trunk/src/VBox/Main/src-client/SessionImpl.cpp

    r53062 r55214  
    123123               mState == SessionState_Spawning);
    124124
    125         HRESULT rc = unlockMachine(true /* aFinalRelease */, false /* aFromServer */);
     125        HRESULT rc = i_unlockMachine(true /* aFinalRelease */, false /* aFromServer */);
    126126        AssertComRC(rc);
    127127    }
     
    167167    if (FAILED(rc))
    168168    {
    169         /** @todo VBox 3.3: replace E_FAIL with rc here. */
    170169#ifndef VBOX_COM_INPROC_API_CLIENT
    171170        if (mConsole)
    172             setError(E_FAIL, tr("Failed to query the session machine (%Rhrc)"), rc);
     171            setError(rc, tr("Failed to query the session machine"));
    173172        else
    174173#endif
    175174        if (FAILED_DEAD_INTERFACE(rc))
    176             setError(E_FAIL, tr("Peer process crashed"));
     175            setError(rc, tr("Peer process crashed"));
    177176        else
    178             setError(E_FAIL, tr("Failed to query the remote session machine (%Rhrc)"), rc);
     177            setError(rc, tr("Failed to query the remote session machine"));
    179178    }
    180179
     
    198197    if (FAILED(rc))
    199198    {
    200         /** @todo VBox 3.3: replace E_FAIL with rc here. */
    201199#ifndef VBOX_COM_INPROC_API_CLIENT
    202200        if (mConsole)
    203             setError(E_FAIL, tr("Failed to query the console (%Rhrc)"), rc);
     201            setError(rc, tr("Failed to query the console"));
    204202        else
    205203#endif
    206204        if (FAILED_DEAD_INTERFACE(rc))
    207             setError(E_FAIL, tr("Peer process crashed"));
     205            setError(rc, tr("Peer process crashed"));
    208206        else
    209             setError(E_FAIL, tr("Failed to query the remote console (%Rhrc)"), rc);
     207            setError(rc, tr("Failed to query the remote console"));
    210208    }
    211209
     
    224222    CHECK_OPEN();
    225223
    226     return unlockMachine(false /* aFinalRelease */, false /* aFromServer */);
     224    return i_unlockMachine(false /* aFinalRelease */, false /* aFromServer */);
    227225}
    228226
     
    265263    return VBOX_E_INVALID_OBJECT_STATE;
    266264#endif /* VBOX_COM_INPROC_API_CLIENT */
     265}
     266
     267HRESULT Session::getNominalState(MachineState_T *aNominalState)
     268{
     269    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     270    AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
     271    AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
     272#ifndef VBOX_COM_INPROC_API_CLIENT
     273    AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
     274
     275    return mConsole->i_getNominalState(*aNominalState);
     276#else
     277    AssertFailed();
     278    return E_NOTIMPL;
     279#endif
    267280}
    268281
     
    300313    AssertReturn(!!mControl, E_FAIL);
    301314
    302 #ifndef VBOX_COM_INPROC_API_CLIENT
    303     HRESULT rc = mConsole.createObject();
    304     AssertComRCReturn(rc, rc);
    305 
    306     rc = mConsole->init(aMachine, mControl, aLockType);
    307     AssertComRCReturn(rc, rc);
    308 #else
    309315    HRESULT rc = S_OK;
     316#ifndef VBOX_COM_INPROC_API_CLIENT
     317    if (aLockType == LockType_VM)
     318    {
     319        /* This is what is special about VM processes: they have a Console
     320         * object which is the root of all VM related activity. */
     321        rc = mConsole.createObject();
     322        AssertComRCReturn(rc, rc);
     323
     324        rc = mConsole->init(aMachine, mControl, aLockType);
     325        AssertComRCReturn(rc, rc);
     326    }
     327    else
     328        mRemoteMachine = aMachine;
     329#else
    310330    mRemoteMachine = aMachine;
    311331#endif
     
    369389
    370390{
    371     AssertReturn(aMachine && aConsole, E_INVALIDARG);
     391    AssertReturn(aMachine, E_INVALIDARG);
    372392
    373393    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     
    496516
    497517        /* close ourselves */
    498         rc = unlockMachine(false /* aFinalRelease */, true /* aFromServer */);
     518        rc = i_unlockMachine(false /* aFinalRelease */, true /* aFromServer */);
    499519    }
    500520    else if (getObjectState().getState() == ObjectState::InUninit)
     
    721741#ifndef VBOX_COM_INPROC_API_CLIENT
    722742    AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
     743    AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
    723744
    724745    return mConsole->i_onDnDModeChange(aDndMode);
     
    911932}
    912933
    913 HRESULT Session::enableVMMStatistics(BOOL aEnable)
    914 {
    915     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    916     AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
    917     AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
    918 #ifndef VBOX_COM_INPROC_API_CLIENT
    919     AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
    920 
    921     mConsole->i_enableVMMStatistics(aEnable);
    922 
    923     return S_OK;
     934HRESULT Session::reconfigureMediumAttachments(const std::vector<ComPtr<IMediumAttachment> > &aAttachments)
     935{
     936    if (mState != SessionState_Locked)
     937        return setError(VBOX_E_INVALID_VM_STATE,
     938                        tr("Machine is not locked by session (session state: %s)."),
     939                        Global::stringifySessionState(mState));
     940#ifndef VBOX_COM_INPROC_API_CLIENT
     941    AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
     942    AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
     943
     944    return mConsole->i_reconfigureMediumAttachments(aAttachments);
    924945#else
    925946    AssertFailed();
     
    928949}
    929950
    930 HRESULT Session::pauseWithReason(Reason_T aReason)
    931 {
    932     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    933     AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
    934     AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
    935 #ifndef VBOX_COM_INPROC_API_CLIENT
    936     AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
    937 
    938     return mConsole->i_pause(aReason);
     951HRESULT Session::enableVMMStatistics(BOOL aEnable)
     952{
     953    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     954    AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
     955    AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
     956#ifndef VBOX_COM_INPROC_API_CLIENT
     957    AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
     958
     959    mConsole->i_enableVMMStatistics(aEnable);
     960
     961    return S_OK;
    939962#else
    940963    AssertFailed();
     
    943966}
    944967
    945 HRESULT Session::resumeWithReason(Reason_T aReason)
    946 {
    947     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    948     AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
    949     AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
    950 #ifndef VBOX_COM_INPROC_API_CLIENT
    951     AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
    952 
    953     return mConsole->i_resume(aReason);
     968HRESULT Session::pauseWithReason(Reason_T aReason)
     969{
     970    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     971    AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
     972    AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
     973#ifndef VBOX_COM_INPROC_API_CLIENT
     974    AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
     975
     976    return mConsole->i_pause(aReason);
    954977#else
    955978    AssertFailed();
     
    958981}
    959982
    960 HRESULT Session::saveStateWithReason(Reason_T aReason, ComPtr<IProgress> &aProgress)
    961 {
    962     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    963     AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
    964     AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
    965 #ifndef VBOX_COM_INPROC_API_CLIENT
    966     AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
    967 
    968     return mConsole->i_saveState(aReason, aProgress.asOutParam());
     983HRESULT Session::resumeWithReason(Reason_T aReason)
     984{
     985    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     986    AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
     987    AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
     988#ifndef VBOX_COM_INPROC_API_CLIENT
     989    AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
     990
     991    AutoWriteLock dummyLock(mConsole COMMA_LOCKVAL_SRC_POS);
     992    return mConsole->i_resume(aReason, dummyLock);
     993#else
     994    AssertFailed();
     995    return E_NOTIMPL;
     996#endif
     997}
     998
     999HRESULT Session::saveStateWithReason(Reason_T aReason, const ComPtr<IProgress> &aProgress, const Utf8Str &aStateFilePath, BOOL aPauseVM, BOOL *aLeftPaused)
     1000{
     1001    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     1002    AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
     1003    AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
     1004#ifndef VBOX_COM_INPROC_API_CLIENT
     1005    AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
     1006
     1007    bool fLeftPaused = false;
     1008    HRESULT rc = mConsole->i_saveState(aReason, aProgress, aStateFilePath, !!aPauseVM, fLeftPaused);
     1009    if (aLeftPaused)
     1010        *aLeftPaused = fLeftPaused;
     1011    return rc;
     1012#else
     1013    AssertFailed();
     1014    return E_NOTIMPL;
     1015#endif
     1016}
     1017
     1018HRESULT Session::cancelSaveStateWithReason()
     1019{
     1020    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     1021    AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE);
     1022    AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE);
     1023#ifndef VBOX_COM_INPROC_API_CLIENT
     1024    AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE);
     1025
     1026    return mConsole->i_cancelSaveState();
    9691027#else
    9701028    AssertFailed();
     
    9851043 *  @note Locks this object for writing.
    9861044 */
    987 HRESULT Session::unlockMachine(bool aFinalRelease, bool aFromServer)
     1045HRESULT Session::i_unlockMachine(bool aFinalRelease, bool aFromServer)
    9881046{
    9891047    LogFlowThisFuncEnter();
  • trunk/src/VBox/Main/src-server/HostPower.cpp

    r51498 r55214  
    55
    66/*
    7  * Copyright (C) 2006-2014 Oracle Corporation
     7 * Copyright (C) 2006-2015 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    139139
    140140            /* save running VMs */
    141             SessionMachinesList::const_iterator it2 = machines.begin();
    142             for (VirtualBox::InternalControlList::const_iterator it = controls.begin();
    143                  it != controls.end() && it2 != machines.end();
    144                  ++it, ++it2)
     141            for (SessionMachinesList::const_iterator it = machines.begin();
     142                 it != machines.end();
     143                 ++it)
    145144            {
    146                 ComPtr<SessionMachine> pMachine = *it2;
     145                ComPtr<SessionMachine> pMachine = *it;
    147146                rc = pMachine->GetExtraData(Bstr("VBoxInternal2/SavestateOnBatteryLow").raw(),
    148147                                            value.asOutParam());
     
    160159                if (fGlobal + fPerVM >= 0)
    161160                {
    162                     ComPtr<IInternalSessionControl> pControl = *it;
    163161                    ComPtr<IProgress> progress;
    164162
    165                     /* note that SaveStateWithReason() will simply return a failure
    166                      * if the VM is in an inappropriate state */
    167                     rc = pControl->SaveStateWithReason(Reason_HostBatteryLow, progress.asOutParam());
     163                    /* SessionMachine::i_saveStateWithReason() will return
     164                     * a failure if the VM is in an inappropriate state */
     165                    rc = pMachine->i_saveStateWithReason(Reason_HostBatteryLow, progress);
    168166                    if (FAILED(rc))
    169167                    {
  • trunk/src/VBox/Main/src-server/MachineImpl.cpp

    r55168 r55214  
    131131
    132132    mSession.mPID              = NIL_RTPROCESS;
     133    mSession.mLockType         = LockType_Null;
    133134    mSession.mState            = SessionState_Unlocked;
    134135}
     
    26942695
    26952696    *aState = mData->mMachineState;
     2697    Assert(mData->mMachineState != MachineState_Null);
    26962698
    26972699    return S_OK;
     
    32483250
    32493251        // copy pointers to W (the write-locking session) before leaving lock (these must not be NULL)
     3252        ComAssertRet(mData->mSession.mLockType == LockType_Write || mData->mSession.mLockType == LockType_VM, E_FAIL);
    32503253        ComPtr<IInternalSessionControl> pSessionW = mData->mSession.mDirectControl;
    32513254        ComAssertRet(!pSessionW.isNull(), E_FAIL);
     
    32633266        // get the console of the session holding the write lock (this is a remote call)
    32643267        ComPtr<IConsole> pConsoleW;
    3265         LogFlowThisFunc(("Calling GetRemoteConsole()...\n"));
    3266         rc = pSessionW->GetRemoteConsole(pConsoleW.asOutParam());
    3267         LogFlowThisFunc(("GetRemoteConsole() returned %08X\n", rc));
    3268         if (FAILED(rc))
    3269             // the failure may occur w/o any error info (from RPC), so provide one
    3270             return setError(VBOX_E_VM_ERROR,
    3271                             tr("Failed to get a console object from the direct session (%Rhrc)"), rc);
    3272 
    3273         ComAssertRet(!pConsoleW.isNull(), E_FAIL);
     3268        if (mData->mSession.mLockType == LockType_VM)
     3269        {
     3270            LogFlowThisFunc(("Calling GetRemoteConsole()...\n"));
     3271            rc = pSessionW->COMGETTER(RemoteConsole)(pConsoleW.asOutParam());
     3272            LogFlowThisFunc(("GetRemoteConsole() returned %08X\n", rc));
     3273            if (FAILED(rc))
     3274                // the failure may occur w/o any error info (from RPC), so provide one
     3275                return setError(VBOX_E_VM_ERROR,
     3276                                tr("Failed to get a console object from the direct session (%Rhrc)"), rc);
     3277            ComAssertRet(!pConsoleW.isNull(), E_FAIL);
     3278        }
    32743279
    32753280        // share the session machine and W's console with the caller's session
     
    33153320        RTPROCESS pid = NIL_RTPROCESS;
    33163321        AssertCompile(sizeof(ULONG) == sizeof(RTPROCESS));
    3317         pSessionControl->GetPID((ULONG*)&pid);
     3322        pSessionControl->COMGETTER(PID)((ULONG*)&pid);
    33183323        Assert(pid != NIL_RTPROCESS);
    33193324
     
    34323437                /* get the console from the direct session */
    34333438                ComPtr<IConsole> console;
    3434                 rc = pSessionControl->GetRemoteConsole(console.asOutParam());
     3439                rc = pSessionControl->COMGETTER(RemoteConsole)(console.asOutParam());
    34353440                ComAssertComRC(rc);
    34363441
     
    35053510        if (SUCCEEDED(rc))
    35063511        {
     3512            mData->mSession.mLockType = aLockType;
    35073513            /* memorize the direct session control and cache IUnknown for it */
    35083514            mData->mSession.mDirectControl = pSessionControl;
     
    35253531        if (FAILED(rc))
    35263532            sessionMachine->uninit();
    3527 
    35283533    }
    35293534
     
    51725177}
    51735178
    5174 struct Machine::DeleteTask
    5175 {
    5176     ComObjPtr<Machine>          pMachine;
    5177     RTCList<ComPtr<IMedium> >   llMediums;
    5178     StringsList                 llFilesToDelete;
    5179     ComObjPtr<Progress>         pProgress;
     5179/**
     5180 * Task record for deleting a machine config.
     5181 */
     5182struct Machine::DeleteConfigTask
     5183    : public Machine::Task
     5184{
     5185    DeleteConfigTask(Machine *m,
     5186                     Progress *p,
     5187                     const Utf8Str &t,
     5188                     const RTCList<ComPtr<IMedium> > &llMediums,
     5189                     const StringsList &llFilesToDelete)
     5190        : Task(m, p, t),
     5191          m_llMediums(llMediums),
     5192          m_llFilesToDelete(llFilesToDelete)
     5193    {}
     5194
     5195    void handler()
     5196    {
     5197        m_pMachine->i_deleteConfigHandler(*this);
     5198    }
     5199
     5200    RTCList<ComPtr<IMedium> >   m_llMediums;
     5201    StringsList                 m_llFilesToDelete;
    51805202};
    51815203
    5182 HRESULT Machine::deleteConfig(const std::vector<ComPtr<IMedium> > &aMedia, ComPtr<IProgress> &aProgress)
    5183 {
    5184     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    5185 
    5186     HRESULT rc = i_checkStateDependency(MutableStateDep);
    5187     if (FAILED(rc)) return rc;
    5188 
    5189     if (mData->mRegistered)
    5190         return setError(VBOX_E_INVALID_VM_STATE,
    5191                         tr("Cannot delete settings of a registered machine"));
    5192 
    5193     DeleteTask *pTask = new DeleteTask;
    5194     pTask->pMachine = this;
    5195 
    5196     // collect files to delete
    5197     pTask->llFilesToDelete = mData->llFilesToDelete;            // saved states pushed here by Unregister()
    5198 
    5199     for (size_t i = 0; i < aMedia.size(); ++i)
    5200     {
    5201         IMedium *pIMedium(aMedia[i]);
    5202         ComObjPtr<Medium> pMedium = static_cast<Medium*>(pIMedium);
    5203         if (pMedium.isNull())
    5204             return setError(E_INVALIDARG, "The given medium pointer with index %d is invalid", i);
    5205         SafeArray<BSTR> ids;
    5206         rc = pMedium->COMGETTER(MachineIds)(ComSafeArrayAsOutParam(ids));
    5207         if (FAILED(rc)) return rc;
    5208         /* At this point the medium should not have any back references
    5209          * anymore. If it has it is attached to another VM and *must* not
    5210          * deleted. */
    5211         if (ids.size() < 1)
    5212             pTask->llMediums.append(pMedium);
    5213     }
    5214     if (mData->pMachineConfigFile->fileExists())
    5215         pTask->llFilesToDelete.push_back(mData->m_strConfigFileFull);
    5216 
    5217     pTask->pProgress.createObject();
    5218     pTask->pProgress->init(i_getVirtualBox(),
    5219                            static_cast<IMachine*>(this) /* aInitiator */,
    5220                            Bstr(tr("Deleting files")).raw(),
    5221                            true /* fCancellable */,
    5222                            (ULONG)(pTask->llFilesToDelete.size() + pTask->llMediums.size() + 1),   // cOperations
    5223                            BstrFmt(tr("Deleting '%s'"), pTask->llFilesToDelete.front().c_str()).raw());
    5224 
    5225     int vrc = RTThreadCreate(NULL,
    5226                              Machine::deleteThread,
    5227                              (void*)pTask,
    5228                              0,
    5229                              RTTHREADTYPE_MAIN_WORKER,
    5230                              0,
    5231                              "MachineDelete");
    5232 
    5233     pTask->pProgress.queryInterfaceTo(aProgress.asOutParam());
    5234 
    5235     if (RT_FAILURE(vrc))
    5236     {
    5237         delete pTask;
    5238         return setError(E_FAIL, "Could not create MachineDelete thread (%Rrc)", vrc);
    5239     }
    5240 
    5241     LogFlowFuncLeave();
    5242 
    5243     return S_OK;
    5244 }
    5245 
    52465204/**
    5247  * Static task wrapper passed to RTThreadCreate() in Machine::Delete() which then
    5248  * calls Machine::deleteTaskWorker() on the actual machine object.
    5249  * @param Thread
    5250  * @param pvUser
    5251  * @return
    5252  */
    5253 /*static*/
    5254 DECLCALLBACK(int) Machine::deleteThread(RTTHREAD Thread, void *pvUser)
    5255 {
    5256     LogFlowFuncEnter();
    5257 
    5258     DeleteTask *pTask = (DeleteTask*)pvUser;
    5259     Assert(pTask);
    5260     Assert(pTask->pMachine);
    5261     Assert(pTask->pProgress);
    5262 
    5263     HRESULT rc = pTask->pMachine->i_deleteTaskWorker(*pTask);
    5264     pTask->pProgress->i_notifyComplete(rc);
    5265 
    5266     delete pTask;
    5267 
    5268     LogFlowFuncLeave();
    5269 
    5270     NOREF(Thread);
    5271 
    5272     return VINF_SUCCESS;
    5273 }
    5274 
    5275 /**
    5276  * Task thread implementation for Machine::Delete(), called from Machine::deleteThread().
     5205 * Task thread implementation for SessionMachine::DeleteConfig(), called from
     5206 * SessionMachine::taskHandler().
     5207 *
     5208 * @note Locks this object for writing.
     5209 *
    52775210 * @param task
    52785211 * @return
    52795212 */
    5280 HRESULT Machine::i_deleteTaskWorker(DeleteTask &task)
    5281 {
     5213void Machine::i_deleteConfigHandler(DeleteConfigTask &task)
     5214{
     5215    LogFlowThisFuncEnter();
     5216
    52825217    AutoCaller autoCaller(this);
    5283     if (FAILED(autoCaller.rc())) return autoCaller.rc();
     5218    LogFlowThisFunc(("state=%d\n", getObjectState().getState()));
     5219    if (FAILED(autoCaller.rc()))
     5220    {
     5221        /* we might have been uninitialized because the session was accidentally
     5222         * closed by the client, so don't assert */
     5223        HRESULT rc = setError(E_FAIL,
     5224                              tr("The session has been accidentally closed"));
     5225        task.m_pProgress->i_notifyComplete(rc);
     5226        LogFlowThisFuncLeave();
     5227        return;
     5228    }
    52845229
    52855230    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     
    53035248        i_setMachineState(MachineState_SettingUp);
    53045249        alock.release();
    5305         for (size_t i = 0; i < task.llMediums.size(); ++i)
    5306         {
    5307             ComObjPtr<Medium> pMedium = (Medium*)(IMedium*)task.llMediums.at(i);
     5250        for (size_t i = 0; i < task.m_llMediums.size(); ++i)
     5251        {
     5252            ComObjPtr<Medium> pMedium = (Medium*)(IMedium*)(task.m_llMediums.at(i));
    53085253            {
    53095254                AutoCaller mac(pMedium);
    53105255                if (FAILED(mac.rc())) throw mac.rc();
    53115256                Utf8Str strLocation = pMedium->i_getLocationFull();
    5312                 rc = task.pProgress->SetNextOperation(BstrFmt(tr("Deleting '%s'"), strLocation.c_str()).raw(), 1);
     5257                rc = task.m_pProgress->SetNextOperation(BstrFmt(tr("Deleting '%s'"), strLocation.c_str()).raw(), 1);
    53135258                if (FAILED(rc)) throw rc;
    53145259                LogFunc(("Deleting file %s\n", strLocation.c_str()));
     
    53195264                rc = pMedium->DeleteStorage(pProgress2.asOutParam());
    53205265                if (FAILED(rc)) throw rc;
    5321                 rc = task.pProgress->WaitForAsyncProgressCompletion(pProgress2);
     5266                rc = task.m_pProgress->WaitForAsyncProgressCompletion(pProgress2);
    53225267                if (FAILED(rc)) throw rc;
    53235268                /* Check the result of the asynchronous process. */
     
    53475292        // medium storage files from the IMedium list passed in, and the
    53485293        // machine XML file)
    5349         StringsList::const_iterator it = task.llFilesToDelete.begin();
    5350         while (it != task.llFilesToDelete.end())
     5294        StringsList::const_iterator it = task.m_llFilesToDelete.begin();
     5295        while (it != task.m_llFilesToDelete.end())
    53515296        {
    53525297            const Utf8Str &strFile = *it;
     
    53585303
    53595304            ++it;
    5360             if (it == task.llFilesToDelete.end())
     5305            if (it == task.m_llFilesToDelete.end())
    53615306            {
    5362                 rc = task.pProgress->SetNextOperation(Bstr(tr("Cleaning up machine directory")).raw(), 1);
     5307                rc = task.m_pProgress->SetNextOperation(Bstr(tr("Cleaning up machine directory")).raw(), 1);
    53635308                if (FAILED(rc)) throw rc;
    53645309                break;
    53655310            }
    53665311
    5367             rc = task.pProgress->SetNextOperation(BstrFmt(tr("Deleting '%s'"), it->c_str()).raw(), 1);
     5312            rc = task.m_pProgress->SetNextOperation(BstrFmt(tr("Deleting '%s'"), it->c_str()).raw(), 1);
    53685313            if (FAILED(rc)) throw rc;
    53695314        }
     
    54385383    catch (HRESULT aRC) { rc = aRC; }
    54395384
    5440     return rc;
     5385    task.m_pProgress->i_notifyComplete(rc);
     5386
     5387    LogFlowThisFuncLeave();
     5388}
     5389
     5390HRESULT Machine::deleteConfig(const std::vector<ComPtr<IMedium> > &aMedia, ComPtr<IProgress> &aProgress)
     5391{
     5392    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     5393
     5394    HRESULT rc = i_checkStateDependency(MutableStateDep);
     5395    if (FAILED(rc)) return rc;
     5396
     5397    if (mData->mRegistered)
     5398        return setError(VBOX_E_INVALID_VM_STATE,
     5399                        tr("Cannot delete settings of a registered machine"));
     5400
     5401    // collect files to delete
     5402    StringsList llFilesToDelete(mData->llFilesToDelete);    // saved states pushed here by Unregister()
     5403    if (mData->pMachineConfigFile->fileExists())
     5404        llFilesToDelete.push_back(mData->m_strConfigFileFull);
     5405
     5406    RTCList<ComPtr<IMedium> > llMediums;
     5407    for (size_t i = 0; i < aMedia.size(); ++i)
     5408    {
     5409        IMedium *pIMedium(aMedia[i]);
     5410        ComObjPtr<Medium> pMedium = static_cast<Medium*>(pIMedium);
     5411        if (pMedium.isNull())
     5412            return setError(E_INVALIDARG, "The given medium pointer with index %d is invalid", i);
     5413        SafeArray<BSTR> ids;
     5414        rc = pMedium->COMGETTER(MachineIds)(ComSafeArrayAsOutParam(ids));
     5415        if (FAILED(rc)) return rc;
     5416        /* At this point the medium should not have any back references
     5417         * anymore. If it has it is attached to another VM and *must* not
     5418         * deleted. */
     5419        if (ids.size() < 1)
     5420            llMediums.append(pMedium);
     5421    }
     5422
     5423    ComObjPtr<Progress> pProgress;
     5424    pProgress.createObject();
     5425    rc = pProgress->init(i_getVirtualBox(),
     5426                         static_cast<IMachine*>(this) /* aInitiator */,
     5427                         Bstr(tr("Deleting files")).raw(),
     5428                         true /* fCancellable */,
     5429                         (ULONG)(llFilesToDelete.size() + llMediums.size() + 1),   // cOperations
     5430                         BstrFmt(tr("Deleting '%s'"), llFilesToDelete.front().c_str()).raw());
     5431    if (FAILED(rc))
     5432        return rc;
     5433
     5434    /* create and start the task on a separate thread (note that it will not
     5435     * start working until we release alock) */
     5436    DeleteConfigTask *pTask = new DeleteConfigTask(this, pProgress, "DeleteVM", llMediums, llFilesToDelete);
     5437    rc = pTask->createThread();
     5438    if (FAILED(rc))
     5439        return rc;
     5440
     5441    pProgress.queryInterfaceTo(aProgress.asOutParam());
     5442
     5443    LogFlowFuncLeave();
     5444
     5445    return S_OK;
    54415446}
    54425447
     
    55345539                            Global::stringifySessionState(mData->mSession.mState));
    55355540
    5536         directControl = mData->mSession.mDirectControl;
     5541        if (mData->mSession.mLockType == LockType_VM)
     5542            directControl = mData->mSession.mDirectControl;
    55375543    }
    55385544
     
    55565562                            Global::stringifySessionState(mData->mSession.mState));
    55575563
    5558         directControl = mData->mSession.mDirectControl;
     5564        if (mData->mSession.mLockType == LockType_VM)
     5565            directControl = mData->mSession.mDirectControl;
    55595566    }
    55605567
     
    56095616
    56105617    ComPtr<IInternalSessionControl> directControl;
    5611     directControl = mData->mSession.mDirectControl;
    5612 
    5613     /* fail if we were called after #OnSessionEnd() is called.  This is a
    5614      * silly race condition. */
    5615 
    5616     /** @todo This code is bothering API clients (like python script clients) with
    5617      *        the AccessGuestProperty call, creating unncessary IPC.  Need to
    5618      *        have a way of figuring out which kind of direct session it is... */
     5618    {
     5619        AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     5620        if (mData->mSession.mLockType == LockType_VM)
     5621            directControl = mData->mSession.mDirectControl;
     5622    }
     5623
     5624    /* ignore calls made after #OnSessionEnd() is called */
    56195625    if (!directControl)
    56205626        rc = E_ACCESSDENIED;
     
    57695775    try
    57705776    {
    5771         ComPtr<IInternalSessionControl> directControl = mData->mSession.mDirectControl;
     5777        ComPtr<IInternalSessionControl> directControl;
     5778        {
     5779            AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     5780            if (mData->mSession.mLockType == LockType_VM)
     5781                directControl = mData->mSession.mDirectControl;
     5782        }
    57725783
    57735784        BSTR dummy = NULL; /* will not be changed (setter) */
     
    58965907    HRESULT rc;
    58975908    ComPtr<IInternalSessionControl> directControl;
    5898     directControl = mData->mSession.mDirectControl;
    5899 
     5909    {
     5910        AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     5911        if (mData->mSession.mLockType == LockType_VM)
     5912            directControl = mData->mSession.mDirectControl;
     5913    }
    59005914
    59015915    com::SafeArray<BSTR> bNames;
     
    70867100    return rc;
    70877101
     7102}
     7103
     7104HRESULT Machine::saveState(ComPtr<IProgress> &aProgress)
     7105{
     7106    NOREF(aProgress);
     7107    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     7108
     7109    // This check should always fail.
     7110    HRESULT rc = i_checkStateDependency(MutableStateDep);
     7111    if (FAILED(rc)) return rc;
     7112
     7113    AssertFailedReturn(E_NOTIMPL);
     7114}
     7115
     7116HRESULT Machine::adoptSavedState(const com::Utf8Str &aSavedStateFile)
     7117{
     7118    NOREF(aSavedStateFile);
     7119    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     7120
     7121    // This check should always fail.
     7122    HRESULT rc = i_checkStateDependency(MutableStateDep);
     7123    if (FAILED(rc)) return rc;
     7124
     7125    AssertFailedReturn(E_NOTIMPL);
     7126}
     7127
     7128HRESULT Machine::discardSavedState(BOOL aFRemoveFile)
     7129{
     7130    NOREF(aFRemoveFile);
     7131    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     7132
     7133    // This check should always fail.
     7134    HRESULT rc = i_checkStateDependency(MutableStateDep);
     7135    if (FAILED(rc)) return rc;
     7136
     7137    AssertFailedReturn(E_NOTIMPL);
    70887138}
    70897139
     
    77187768    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    77197769
    7720     if (    mData->mSession.mState == SessionState_Locked
     7770    if (    (   mData->mSession.mState == SessionState_Locked
     7771             && mData->mSession.mLockType == LockType_VM)
    77217772         || (aAllowClosing && mData->mSession.mState == SessionState_Unlocking)
    77227773       )
     
    84198470    LogFlowThisFuncEnter();
    84208471    LogFlowThisFunc(("aMachineState=%s\n", Global::stringifyMachineState(aMachineState) ));
     8472    Assert(aMachineState != MachineState_Null);
    84218473
    84228474    AutoCaller autoCaller(this);
     
    1058110633
    1058210634    /* must be in a protective state because we release the lock below */
    10583     AssertReturn(   mData->mMachineState == MachineState_Saving
     10635    AssertReturn(   mData->mMachineState == MachineState_Snapshotting
     10636                 || mData->mMachineState == MachineState_OnlineSnapshotting
    1058410637                 || mData->mMachineState == MachineState_LiveSnapshotting
    1058510638                 || mData->mMachineState == MachineState_RestoringSnapshot
     
    1067010723                /* copy the attachment as is */
    1067110724
    10672                 /** @todo the progress object created in Console::TakeSnaphot
     10725                /** @todo the progress object created in SessionMachine::TakeSnaphot
    1067310726                 * only expects operations for hard disks. Later other
    1067410727                 * device types need to show up in the progress as well. */
     
    1083210885    /* will release the lock before the potentially lengthy operation,
    1083310886     * so protect with the special state (unless already protected) */
    10834     if (   oldState != MachineState_Saving
     10887    if (   oldState != MachineState_Snapshotting
     10888        && oldState != MachineState_OnlineSnapshotting
    1083510889        && oldState != MachineState_LiveSnapshotting
    1083610890        && oldState != MachineState_RestoringSnapshot
     
    1096911023                mrc = rc;
    1097011024            }
     11025            // Clear the list of deleted implicit attachments now, while not
     11026            // holding the lock, as it will ultimately trigger Medium::uninit()
     11027            // calls which assume that the media tree lock isn't held.
     11028            implicitAtts.clear();
    1097111029
    1097211030            alock.acquire();
     
    1249012548    }
    1249112549
    12492     Assert(    mConsoleTaskData.strStateFilePath.isEmpty()
    12493             || !mConsoleTaskData.mSnapshot);
    12494     if (!mConsoleTaskData.strStateFilePath.isEmpty())
    12495     {
    12496         LogWarningThisFunc(("canceling failed save state request!\n"));
    12497         endSavingState(E_FAIL, tr("Machine terminated with pending save state!"));
    12498     }
    12499     else if (!mConsoleTaskData.mSnapshot.isNull())
    12500     {
    12501         LogWarningThisFunc(("canceling untaken snapshot!\n"));
    12502 
    12503         /* delete all differencing hard disks created (this will also attach
    12504          * their parents back by rolling back mMediaData) */
    12505         i_rollbackMedia();
    12506 
    12507         // delete the saved state file (it might have been already created)
    12508         // AFTER killing the snapshot so that releaseSavedStateFile() won't
    12509         // think it's still in use
    12510         Utf8Str strStateFile = mConsoleTaskData.mSnapshot->i_getStateFilePath();
    12511         mConsoleTaskData.mSnapshot->uninit();
    12512         i_releaseSavedStateFile(strStateFile, NULL /* pSnapshotToIgnore */ );
    12513     }
    12514 
    1251512550    mData->mSession.mPID = NIL_RTPROCESS;
    1251612551
     
    1261312648
    1261412649    /* reset the rest of session data */
     12650    mData->mSession.mLockType = LockType_Null;
    1261512651    mData->mSession.mMachine.setNull();
    1261612652    mData->mSession.mState = SessionState_Unlocked;
     
    1269812734}
    1269912735
     12736////////////////////////////////////////////////////////////////////////////////
     12737//
     12738// SessionMachine task records
     12739//
     12740////////////////////////////////////////////////////////////////////////////////
     12741
     12742/**
     12743 * Task record for saving the machine state.
     12744 */
     12745struct SessionMachine::SaveStateTask
     12746    : public Machine::Task
     12747{
     12748    SaveStateTask(SessionMachine *m,
     12749                  Progress *p,
     12750                  const Utf8Str &t,
     12751                  Reason_T enmReason,
     12752                  const Utf8Str &strStateFilePath)
     12753        : Task(m, p, t),
     12754          m_enmReason(enmReason),
     12755          m_strStateFilePath(strStateFilePath)
     12756    {}
     12757
     12758    void handler()
     12759    {
     12760        ((SessionMachine *)(Machine *)m_pMachine)->i_saveStateHandler(*this);
     12761    }
     12762
     12763    Reason_T m_enmReason;
     12764    Utf8Str m_strStateFilePath;
     12765};
     12766
     12767/**
     12768 * Task thread implementation for SessionMachine::SaveState(), called from
     12769 * SessionMachine::taskHandler().
     12770 *
     12771 * @note Locks this object for writing.
     12772 *
     12773 * @param task
     12774 * @return
     12775 */
     12776void SessionMachine::i_saveStateHandler(SaveStateTask &task)
     12777{
     12778    LogFlowThisFuncEnter();
     12779
     12780    AutoCaller autoCaller(this);
     12781    LogFlowThisFunc(("state=%d\n", getObjectState().getState()));
     12782    if (FAILED(autoCaller.rc()))
     12783    {
     12784        /* we might have been uninitialized because the session was accidentally
     12785         * closed by the client, so don't assert */
     12786        HRESULT rc = setError(E_FAIL,
     12787                              tr("The session has been accidentally closed"));
     12788        task.m_pProgress->i_notifyComplete(rc);
     12789        LogFlowThisFuncLeave();
     12790        return;
     12791    }
     12792
     12793    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     12794
     12795    HRESULT rc = S_OK;
     12796
     12797    try
     12798    {
     12799        ComPtr<IInternalSessionControl> directControl;
     12800        if (mData->mSession.mLockType == LockType_VM)
     12801            directControl = mData->mSession.mDirectControl;
     12802        if (directControl.isNull())
     12803            throw setError(VBOX_E_INVALID_VM_STATE,
     12804                           tr("Trying to save state without a running VM"));
     12805        alock.release();
     12806        BOOL fSuspendedBySave;
     12807        rc = directControl->SaveStateWithReason(task.m_enmReason, task.m_pProgress, Bstr(task.m_strStateFilePath).raw(), task.m_machineStateBackup != MachineState_Paused, &fSuspendedBySave);
     12808        Assert(!fSuspendedBySave);
     12809        alock.acquire();
     12810
     12811        AssertStmt(   (SUCCEEDED(rc) && mData->mMachineState == MachineState_Saved)
     12812                   || (FAILED(rc) && mData->mMachineState == MachineState_Saving),
     12813                   throw E_FAIL);
     12814
     12815        if (SUCCEEDED(rc))
     12816        {
     12817            mSSData->strStateFilePath = task.m_strStateFilePath;
     12818
     12819            /* save all VM settings */
     12820            rc = i_saveSettings(NULL);
     12821                    // no need to check whether VirtualBox.xml needs saving also since
     12822                    // we can't have a name change pending at this point
     12823        }
     12824        else
     12825        {
     12826            // On failure, set the state to the state we had at the beginning.
     12827            i_setMachineState(task.m_machineStateBackup);
     12828            i_updateMachineStateOnClient();
     12829
     12830            // Delete the saved state file (might have been already created).
     12831            // No need to check whether this is shared with a snapshot here
     12832            // because we certainly created a fresh saved state file here.
     12833            RTFileDelete(task.m_strStateFilePath.c_str());
     12834        }
     12835    }
     12836    catch (HRESULT aRC) { rc = aRC; }
     12837
     12838    task.m_pProgress->i_notifyComplete(rc);
     12839
     12840    LogFlowThisFuncLeave();
     12841}
     12842
    1270012843/**
    1270112844 *  @note Locks this object for writing.
    1270212845 */
    12703 HRESULT SessionMachine::setRemoveSavedStateFile(BOOL aRemove)
     12846HRESULT SessionMachine::saveState(ComPtr<IProgress> &aProgress)
     12847{
     12848    return i_saveStateWithReason(Reason_Unspecified, aProgress);
     12849}
     12850
     12851HRESULT SessionMachine::i_saveStateWithReason(Reason_T aReason, ComPtr<IProgress> &aProgress)
    1270412852{
    1270512853    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    1270612854
    12707     mRemoveSavedState = RT_BOOL(aRemove);
    12708 
    12709     return S_OK;
    12710 }
     12855    HRESULT rc = i_checkStateDependency(MutableOrRunningStateDep);
     12856    if (FAILED(rc)) return rc;
     12857
     12858    if (   mData->mMachineState != MachineState_Running
     12859        && mData->mMachineState != MachineState_Paused
     12860       )
     12861        return setError(VBOX_E_INVALID_VM_STATE,
     12862            tr("Cannot save the execution state as the machine is not running or paused (machine state: %s)"),
     12863            Global::stringifyMachineState(mData->mMachineState));
     12864
     12865    ComObjPtr<Progress> pProgress;
     12866    pProgress.createObject();
     12867    rc = pProgress->init(i_getVirtualBox(),
     12868                         static_cast<IMachine *>(this) /* aInitiator */,
     12869                         Bstr(tr("Saving the execution state of the virtual machine")).raw(),
     12870                         FALSE /* aCancelable */);
     12871    if (FAILED(rc))
     12872        return rc;
     12873
     12874    Utf8Str strStateFilePath;
     12875    i_composeSavedStateFilename(strStateFilePath);
     12876
     12877    /* create and start the task on a separate thread (note that it will not
     12878     * start working until we release alock) */
     12879    SaveStateTask *pTask = new SaveStateTask(this, pProgress, "SaveState", aReason, strStateFilePath);
     12880    rc = pTask->createThread();
     12881    if (FAILED(rc))
     12882        return rc;
     12883
     12884    /* set the state to Saving (expected by Session::SaveStateWithReason()) */
     12885    i_setMachineState(MachineState_Saving);
     12886    i_updateMachineStateOnClient();
     12887
     12888    pProgress.queryInterfaceTo(aProgress.asOutParam());
     12889
     12890    return S_OK;
     12891}
     12892
     12893/**
     12894 *  @note Locks this object for writing.
     12895 */
     12896HRESULT SessionMachine::adoptSavedState(const com::Utf8Str &aSavedStateFile)
     12897{
     12898    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     12899
     12900    HRESULT rc = i_checkStateDependency(MutableStateDep);
     12901    if (FAILED(rc)) return rc;
     12902
     12903    if (   mData->mMachineState != MachineState_PoweredOff
     12904        && mData->mMachineState != MachineState_Teleported
     12905        && mData->mMachineState != MachineState_Aborted
     12906       )
     12907        return setError(VBOX_E_INVALID_VM_STATE,
     12908            tr("Cannot adopt the saved machine state as the machine is not in Powered Off, Teleported or Aborted state (machine state: %s)"),
     12909            Global::stringifyMachineState(mData->mMachineState));
     12910
     12911    com::Utf8Str stateFilePathFull;
     12912    int vrc = i_calculateFullPath(aSavedStateFile, stateFilePathFull);
     12913    if (RT_FAILURE(vrc))
     12914        return setError(VBOX_E_FILE_ERROR,
     12915                        tr("Invalid saved state file path '%s' (%Rrc)"),
     12916                        aSavedStateFile.c_str(),
     12917                        vrc);
     12918
     12919    mSSData->strStateFilePath = stateFilePathFull;
     12920
     12921    /* The below i_setMachineState() will detect the state transition and will
     12922     * update the settings file */
     12923
     12924    return i_setMachineState(MachineState_Saved);
     12925}
     12926
     12927/**
     12928 *  @note Locks this object for writing.
     12929 */
     12930HRESULT SessionMachine::discardSavedState(BOOL aFRemoveFile)
     12931{
     12932    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     12933
     12934    HRESULT rc = i_checkStateDependency(MutableStateDep);
     12935    if (FAILED(rc)) return rc;
     12936
     12937    if (mData->mMachineState != MachineState_Saved)
     12938        return setError(VBOX_E_INVALID_VM_STATE,
     12939            tr("Cannot delete the machine state as the machine is not in the saved state (machine state: %s)"),
     12940            Global::stringifyMachineState(mData->mMachineState));
     12941
     12942    mRemoveSavedState = RT_BOOL(aFRemoveFile);
     12943
     12944    /*
     12945     * Saved -> PoweredOff transition will be detected in the SessionMachine
     12946     * and properly handled.
     12947     */
     12948    rc = i_setMachineState(MachineState_PoweredOff);
     12949    return rc;
     12950}
     12951
    1271112952
    1271212953/**
     
    1308713328}
    1308813329
    13089 /**
    13090  *  @note Locks this object for writing.
    13091  */
    13092 HRESULT SessionMachine::beginSavingState(ComPtr<IProgress> &aProgress,
    13093                                          com::Utf8Str &aStateFilePath)
    13094 {
    13095     LogFlowThisFuncEnter();
    13096 
    13097     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    13098 
    13099     AssertReturn(    mData->mMachineState == MachineState_Paused
    13100                   && mConsoleTaskData.mLastState == MachineState_Null
    13101                   && mConsoleTaskData.strStateFilePath.isEmpty(),
    13102                  E_FAIL);
    13103 
    13104     /* create a progress object to track operation completion */
    13105     ComObjPtr<Progress> pProgress;
    13106     pProgress.createObject();
    13107     pProgress->init(i_getVirtualBox(),
    13108                     static_cast<IMachine *>(this) /* aInitiator */,
    13109                     Bstr(tr("Saving the execution state of the virtual machine")).raw(),
    13110                     FALSE /* aCancelable */);
    13111 
    13112     /* stateFilePath is null when the machine is not running */
    13113     if (mData->mMachineState == MachineState_Paused)
    13114         i_composeSavedStateFilename(aStateFilePath);
    13115 
    13116     /* fill in the console task data */
    13117     mConsoleTaskData.mLastState = mData->mMachineState;
    13118     mConsoleTaskData.strStateFilePath = aStateFilePath;
    13119     mConsoleTaskData.mProgress = pProgress;
    13120 
    13121     /* set the state to Saving (this is expected by Console::SaveState()) */
    13122     i_setMachineState(MachineState_Saving);
    13123 
    13124     pProgress.queryInterfaceTo(aProgress.asOutParam());
    13125 
    13126     return S_OK;
    13127 }
    13128 
    13129 /**
    13130  *  @note Locks mParent + this object for writing.
    13131  */
    13132 HRESULT SessionMachine::endSavingState(LONG aResult,
    13133                                        const com::Utf8Str &aErrMsg)
    13134 {
    13135     LogFlowThisFunc(("\n"));
    13136 
    13137     /* endSavingState() need mParent lock */
    13138     AutoMultiWriteLock2 alock(mParent, this COMMA_LOCKVAL_SRC_POS);
    13139 
    13140     AssertReturn(    (   (SUCCEEDED(aResult) && mData->mMachineState == MachineState_Saved)
    13141                       || (FAILED(aResult) && mData->mMachineState == MachineState_Saving))
    13142                   && mConsoleTaskData.mLastState != MachineState_Null
    13143                   && !mConsoleTaskData.strStateFilePath.isEmpty(),
    13144                  E_FAIL);
    13145 
    13146     /*
    13147      * On failure, set the state to the state we had when BeginSavingState()
    13148      * was called (this is expected by Console::SaveState() and the associated
    13149      * task). On success the VM process already changed the state to
    13150      * MachineState_Saved, so no need to do anything.
    13151      */
    13152     if (FAILED(aResult))
    13153         i_setMachineState(mConsoleTaskData.mLastState);
    13154 
    13155     return i_endSavingState(aResult, aErrMsg);
    13156 }
    13157 
    13158 /**
    13159  *  @note Locks this object for writing.
    13160  */
    13161 HRESULT SessionMachine::adoptSavedState(const com::Utf8Str &aSavedStateFile)
    13162 {
    13163     LogFlowThisFunc(("\n"));
    13164 
    13165     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    13166 
    13167     AssertReturn(   mData->mMachineState == MachineState_PoweredOff
    13168                  || mData->mMachineState == MachineState_Teleported
    13169                  || mData->mMachineState == MachineState_Aborted
    13170                  , E_FAIL); /** @todo setError. */
    13171 
    13172     com::Utf8Str stateFilePathFull;
    13173     int vrc = i_calculateFullPath(aSavedStateFile, stateFilePathFull);
    13174     if (RT_FAILURE(vrc))
    13175         return setError(VBOX_E_FILE_ERROR,
    13176                         tr("Invalid saved state file path '%s' (%Rrc)"),
    13177                         aSavedStateFile.c_str(),
    13178                         vrc);
    13179 
    13180     mSSData->strStateFilePath = stateFilePathFull;
    13181 
    13182     /* The below i_setMachineState() will detect the state transition and will
    13183      * update the settings file */
    13184 
    13185     return i_setMachineState(MachineState_Saved);
    13186 }
    13187 
    1318813330HRESULT SessionMachine::pullGuestProperties(std::vector<com::Utf8Str> &aNames,
    1318913331                                            std::vector<com::Utf8Str> &aValues,
     
    1326313405            case MachineState_Teleporting:
    1326413406            case MachineState_TeleportingPausedVM:
     13407            case MachineState_OnlineSnapshotting:
    1326513408            case MachineState_LiveSnapshotting:
    1326613409            case MachineState_DeletingSnapshotOnline:
     
    1353613679    {
    1353713680        AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    13538         directControl = mData->mSession.mDirectControl;
     13681        if (mData->mSession.mLockType == LockType_VM)
     13682            directControl = mData->mSession.mDirectControl;
    1353913683    }
    1354013684
     
    1356113705    {
    1356213706        AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    13563         directControl = mData->mSession.mDirectControl;
     13707        if (mData->mSession.mLockType == LockType_VM)
     13708            directControl = mData->mSession.mDirectControl;
    1356413709    }
    1356513710
     
    1358913734    {
    1359013735        AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    13591         directControl = mData->mSession.mDirectControl;
     13736        if (mData->mSession.mLockType == LockType_VM)
     13737            directControl = mData->mSession.mDirectControl;
    1359213738    }
    1359313739
     
    1361213758    {
    1361313759        AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    13614         directControl = mData->mSession.mDirectControl;
     13760        if (mData->mSession.mLockType == LockType_VM)
     13761            directControl = mData->mSession.mDirectControl;
    1361513762    }
    1361613763
     
    1363513782    {
    1363613783        AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    13637         directControl = mData->mSession.mDirectControl;
     13784        if (mData->mSession.mLockType == LockType_VM)
     13785            directControl = mData->mSession.mDirectControl;
    1363813786    }
    1363913787
     
    1365813806    {
    1365913807        AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    13660         directControl = mData->mSession.mDirectControl;
     13808        if (mData->mSession.mLockType == LockType_VM)
     13809            directControl = mData->mSession.mDirectControl;
    1366113810    }
    1366213811
     
    1368113830    {
    1368213831        AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    13683         directControl = mData->mSession.mDirectControl;
     13832        if (mData->mSession.mLockType == LockType_VM)
     13833            directControl = mData->mSession.mDirectControl;
    1368413834    }
    1368513835
     
    1370113851    {
    1370213852        AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    13703         directControl = mData->mSession.mDirectControl;
     13853        if (mData->mSession.mLockType == LockType_VM)
     13854            directControl = mData->mSession.mDirectControl;
    1370413855    }
    1370513856
     
    1372413875    {
    1372513876        AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    13726         directControl = mData->mSession.mDirectControl;
     13877        if (mData->mSession.mLockType == LockType_VM)
     13878            directControl = mData->mSession.mDirectControl;
    1372713879    }
    1372813880
     
    1374713899    {
    1374813900        AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    13749         directControl = mData->mSession.mDirectControl;
     13901        if (mData->mSession.mLockType == LockType_VM)
     13902            directControl = mData->mSession.mDirectControl;
    1375013903    }
    1375113904
     
    1377013923    {
    1377113924        AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    13772         directControl = mData->mSession.mDirectControl;
     13925        if (mData->mSession.mLockType == LockType_VM)
     13926            directControl = mData->mSession.mDirectControl;
    1377313927    }
    1377413928
     
    1379313947    {
    1379413948        AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    13795         directControl = mData->mSession.mDirectControl;
     13949        if (mData->mSession.mLockType == LockType_VM)
     13950            directControl = mData->mSession.mDirectControl;
    1379613951    }
    1379713952
     
    1381613971    {
    1381713972        AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    13818         directControl = mData->mSession.mDirectControl;
     13973        if (mData->mSession.mLockType == LockType_VM)
     13974            directControl = mData->mSession.mDirectControl;
    1381913975    }
    1382013976
     
    1383913995    {
    1384013996        AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    13841         directControl = mData->mSession.mDirectControl;
     13997        if (mData->mSession.mLockType == LockType_VM)
     13998            directControl = mData->mSession.mDirectControl;
    1384213999    }
    1384314000
     
    1386214019    {
    1386314020        AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    13864         directControl = mData->mSession.mDirectControl;
     14021        if (mData->mSession.mLockType == LockType_VM)
     14022            directControl = mData->mSession.mDirectControl;
    1386514023    }
    1386614024
     
    1388514043    {
    1388614044        AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    13887         directControl = mData->mSession.mDirectControl;
     14045        if (mData->mSession.mLockType == LockType_VM)
     14046            directControl = mData->mSession.mDirectControl;
    1388814047    }
    1388914048
     
    1395114110    {
    1395214111        AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    13953         directControl = mData->mSession.mDirectControl;
     14112        if (mData->mSession.mLockType == LockType_VM)
     14113            directControl = mData->mSession.mDirectControl;
    1395414114    }
    1395514115
     
    1398314143    {
    1398414144        AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    13985         directControl = mData->mSession.mDirectControl;
     14145        if (mData->mSession.mLockType == LockType_VM)
     14146            directControl = mData->mSession.mDirectControl;
    1398614147    }
    1398714148
     
    1400014161// protected methods
    1400114162/////////////////////////////////////////////////////////////////////////////
    14002 
    14003 /**
    14004  *  Helper method to finalize saving the state.
    14005  *
    14006  *  @note Must be called from under this object's lock.
    14007  *
    14008  *  @param aRc      S_OK if the snapshot has been taken successfully
    14009  *  @param aErrMsg  human readable error message for failure
    14010  *
    14011  *  @note Locks mParent + this objects for writing.
    14012  */
    14013 HRESULT SessionMachine::i_endSavingState(HRESULT aRc, const Utf8Str &aErrMsg)
    14014 {
    14015     LogFlowThisFuncEnter();
    14016 
    14017     AutoCaller autoCaller(this);
    14018     AssertComRCReturn(autoCaller.rc(), autoCaller.rc());
    14019 
    14020     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    14021 
    14022     HRESULT rc = S_OK;
    14023 
    14024     if (SUCCEEDED(aRc))
    14025     {
    14026         mSSData->strStateFilePath = mConsoleTaskData.strStateFilePath;
    14027 
    14028         /* save all VM settings */
    14029         rc = i_saveSettings(NULL);
    14030                 // no need to check whether VirtualBox.xml needs saving also since
    14031                 // we can't have a name change pending at this point
    14032     }
    14033     else
    14034     {
    14035         // delete the saved state file (it might have been already created);
    14036         // we need not check whether this is shared with a snapshot here because
    14037         // we certainly created this saved state file here anew
    14038         RTFileDelete(mConsoleTaskData.strStateFilePath.c_str());
    14039     }
    14040 
    14041     /* notify the progress object about operation completion */
    14042     Assert(mConsoleTaskData.mProgress);
    14043     if (SUCCEEDED(aRc))
    14044         mConsoleTaskData.mProgress->i_notifyComplete(S_OK);
    14045     else
    14046     {
    14047         if (aErrMsg.length())
    14048             mConsoleTaskData.mProgress->i_notifyComplete(aRc,
    14049                                                          COM_IIDOF(ISession),
    14050                                                          getComponentName(),
    14051                                                          aErrMsg.c_str());
    14052         else
    14053             mConsoleTaskData.mProgress->i_notifyComplete(aRc);
    14054     }
    14055 
    14056     /* clear out the temporary saved state data */
    14057     mConsoleTaskData.mLastState = MachineState_Null;
    14058     mConsoleTaskData.strStateFilePath.setNull();
    14059     mConsoleTaskData.mProgress.setNull();
    14060 
    14061     LogFlowThisFuncLeave();
    14062     return rc;
    14063 }
    1406414163
    1406514164/**
     
    1425914358                 || oldMachineState == MachineState_Paused
    1426014359                 || oldMachineState == MachineState_Teleporting
     14360                 || oldMachineState == MachineState_OnlineSnapshotting
    1426114361                 || oldMachineState == MachineState_LiveSnapshotting
    1426214362                 || oldMachineState == MachineState_Stuck
     
    1427314373                 || aMachineState == MachineState_Aborted
    1427414374                )
    14275              /* ignore PoweredOff->Saving->PoweredOff transition when taking a
    14276               * snapshot */
    14277              && (   mConsoleTaskData.mSnapshot.isNull()
    14278                  || mConsoleTaskData.mLastState >= MachineState_Running /** @todo Live Migration: clean up (lazy bird) */
    14279                 )
    1428014375            )
    1428114376    {
     
    1431014405    {
    1431114406        /*
    14312          *  delete the saved state after Console::ForgetSavedState() is called
     14407         *  delete the saved state after SessionMachine::ForgetSavedState() is called
    1431314408         *  or if the VM process (owning a direct VM session) crashed while the
    1431414409         *  VM was Saved
     
    1445614551        AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    1445714552        AssertReturn(!!mData, E_FAIL);
    14458         directControl = mData->mSession.mDirectControl;
     14553        if (mData->mSession.mLockType == LockType_VM)
     14554            directControl = mData->mSession.mDirectControl;
    1445914555
    1446014556        /* directControl may be already set to NULL here in #OnSessionEnd()
     
    1446914565        if (mData->mSession.mState == SessionState_Unlocking)
    1447014566            return S_OK;
    14471 
    14472         AssertReturn(!directControl.isNull(), E_FAIL);
    14473     }
     14567    }
     14568
     14569    /* ignore notifications sent after #OnSessionEnd() is called */
     14570    if (!directControl)
     14571        return S_OK;
    1447414572
    1447514573    return directControl->UpdateMachineState(mData->mMachineState);
    1447614574}
    1447714575
    14478 HRESULT Machine::setRemoveSavedStateFile(BOOL aRemove)
    14479 {
    14480     NOREF(aRemove);
    14481     ReturnComNotImplemented();
    14482 }
     14576
     14577/**
     14578 * Static Machine method that can get passed to RTThreadCreate to
     14579 * have a thread started for a Task. See Machine::Task.
     14580 */
     14581/* static */ DECLCALLBACK(int) Machine::taskHandler(RTTHREAD /* thread */, void *pvUser)
     14582{
     14583    AssertReturn(pvUser, VERR_INVALID_POINTER);
     14584
     14585    Task *pTask = static_cast<Task *>(pvUser);
     14586    pTask->handler();
     14587    /** @todo r=klaus it would be safer to update the progress object here,
     14588     * as it avoids possible races due to scoping issues/tricks in the handler */
     14589    // it's our responsibility to delete the task
     14590    delete pTask;
     14591
     14592    return 0;
     14593}
     14594
     14595/*static*/
     14596HRESULT Machine::i_setErrorStatic(HRESULT aResultCode, const char *pcszMsg, ...)
     14597{
     14598    va_list args;
     14599    va_start(args, pcszMsg);
     14600    HRESULT rc = setErrorInternal(aResultCode,
     14601                                  getStaticClassIID(),
     14602                                  getStaticComponentName(),
     14603                                  Utf8Str(pcszMsg, args),
     14604                                  false /* aWarning */,
     14605                                  true /* aLogIt */);
     14606    va_end(args);
     14607    return rc;
     14608}
     14609
    1448314610
    1448414611HRESULT Machine::updateState(MachineState_T aState)
     
    1455814685}
    1455914686
    14560 HRESULT Machine::beginSavingState(ComPtr<IProgress> &aProgress,
    14561                                   com::Utf8Str &aStateFilePath)
    14562 {
    14563     NOREF(aProgress);
    14564     NOREF(aStateFilePath);
    14565     ReturnComNotImplemented();
    14566 }
    14567 
    14568 HRESULT Machine::endSavingState(LONG aResult,
    14569                                 const com::Utf8Str &aErrMsg)
    14570 {
    14571     NOREF(aResult);
    14572     NOREF(aErrMsg);
    14573     ReturnComNotImplemented();
    14574 }
    14575 
    14576 HRESULT Machine::adoptSavedState(const com::Utf8Str &aSavedStateFile)
    14577 {
    14578     NOREF(aSavedStateFile);
    14579     ReturnComNotImplemented();
    14580 }
    14581 
    14582 HRESULT Machine::beginTakingSnapshot(const ComPtr<IConsole> &aInitiator,
    14583                                      const com::Utf8Str &aName,
    14584                                      const com::Utf8Str &aDescription,
    14585                                      const ComPtr<IProgress> &aConsoleProgress,
    14586                                      BOOL aFTakingSnapshotOnline,
    14587                                      com::Utf8Str &aStateFilePath)
    14588 {
    14589     NOREF(aInitiator);
    14590     NOREF(aName);
    14591     NOREF(aDescription);
    14592     NOREF(aConsoleProgress);
    14593     NOREF(aFTakingSnapshotOnline);
    14594     NOREF(aStateFilePath);
    14595     ReturnComNotImplemented();
    14596 }
    14597 
    14598 HRESULT Machine::endTakingSnapshot(BOOL aSuccess)
    14599 {
    14600     NOREF(aSuccess);
    14601     ReturnComNotImplemented();
    14602 }
    14603 
    14604 HRESULT Machine::deleteSnapshot(const ComPtr<IConsole> &aInitiator,
    14605                                 const com::Guid &aStartId,
    14606                                 const com::Guid &aEndId,
    14607                                 BOOL aDeleteAllChildren,
    14608                                 MachineState_T *aMachineState,
    14609                                 ComPtr<IProgress> &aProgress)
    14610 {
    14611     NOREF(aInitiator);
    14612     NOREF(aStartId);
    14613     NOREF(aEndId);
    14614     NOREF(aDeleteAllChildren);
    14615     NOREF(aMachineState);
    14616     NOREF(aProgress);
    14617     ReturnComNotImplemented();
    14618 }
    14619 
    1462014687HRESULT Machine::finishOnlineMergeMedium()
    1462114688{
    14622     ReturnComNotImplemented();
    14623 }
    14624 
    14625 HRESULT Machine::restoreSnapshot(const ComPtr<IConsole> &aInitiator,
    14626                                  const ComPtr<ISnapshot> &aSnapshot,
    14627                                  MachineState_T *aMachineState,
    14628                                  ComPtr<IProgress> &aProgress)
    14629 {
    14630     NOREF(aInitiator);
    14631     NOREF(aSnapshot);
    14632     NOREF(aMachineState);
    14633     NOREF(aProgress);
    1463414689    ReturnComNotImplemented();
    1463514690}
  • trunk/src/VBox/Main/src-server/Performance.cpp

    r51498 r55214  
    55
    66/*
    7  * Copyright (C) 2008-2014 Oracle Corporation
     7 * Copyright (C) 2008-2015 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    311311
    312312        /* get the associated console; this is a remote call (!) */
    313         ret = directControl->GetRemoteConsole(mConsole.asOutParam());
     313        ret = directControl->COMGETTER(RemoteConsole)(mConsole.asOutParam());
    314314        if (ret != S_OK)
    315315            return ret;
  • trunk/src/VBox/Main/src-server/SnapshotImpl.cpp

    r54948 r55214  
    412412}
    413413
    414 HRESULT Snapshot::getChildrenCount(ULONG* count)
     414HRESULT Snapshot::getChildrenCount(ULONG *count)
    415415{
    416416    *count = i_getChildrenCount();
     
    13051305
    13061306/**
    1307  * Abstract base class for SessionMachine::RestoreSnapshotTask and
    1308  * SessionMachine::DeleteSnapshotTask. This is necessary since
    1309  * RTThreadCreate cannot call a method as its thread function, so
    1310  * instead we have it call the static SessionMachine::taskHandler,
    1311  * which can then call the handler() method in here (implemented
    1312  * by the children).
     1307 * Still abstract base class for SessionMachine::TakeSnapshotTask,
     1308 * SessionMachine::RestoreSnapshotTask and SessionMachine::DeleteSnapshotTask.
    13131309 */
    13141310struct SessionMachine::SnapshotTask
     1311    : public SessionMachine::Task
    13151312{
    13161313    SnapshotTask(SessionMachine *m,
    13171314                 Progress *p,
     1315                 const Utf8Str &t,
    13181316                 Snapshot *s)
    1319         : pMachine(m),
    1320           pProgress(p),
    1321           machineStateBackup(m->mData->mMachineState), // save the current machine state
    1322           pSnapshot(s)
     1317        : Task(m, p, t),
     1318          m_pSnapshot(s)
    13231319    {}
    13241320
    1325     void modifyBackedUpState(MachineState_T s)
    1326     {
    1327         *const_cast<MachineState_T*>(&machineStateBackup) = s;
    1328     }
    1329 
    1330     virtual void handler() = 0;
    1331 
    1332     ComObjPtr<SessionMachine>       pMachine;
    1333     ComObjPtr<Progress>             pProgress;
    1334     const MachineState_T            machineStateBackup;
    1335     ComObjPtr<Snapshot>             pSnapshot;
     1321    ComObjPtr<Snapshot> m_pSnapshot;
    13361322};
    13371323
    1338 /** Restore snapshot state task */
     1324/** Take snapshot task */
     1325struct SessionMachine::TakeSnapshotTask
     1326    : public SessionMachine::SnapshotTask
     1327{
     1328    TakeSnapshotTask(SessionMachine *m,
     1329                     Progress *p,
     1330                     const Utf8Str &t,
     1331                     Snapshot *s,
     1332                     const Utf8Str &strName,
     1333                     const Utf8Str &strDescription,
     1334                     bool fPause,
     1335                     uint32_t uMemSize,
     1336                     bool fTakingSnapshotOnline)
     1337        : SnapshotTask(m, p, t, s),
     1338          m_strName(strName),
     1339          m_strDescription(strDescription),
     1340          m_fPause(fPause),
     1341          m_uMemSize(uMemSize),
     1342          m_fTakingSnapshotOnline(fTakingSnapshotOnline)
     1343    {
     1344        if (fTakingSnapshotOnline)
     1345            m_pDirectControl = m->mData->mSession.mDirectControl;
     1346    }
     1347
     1348    void handler()
     1349    {
     1350        ((SessionMachine *)(Machine *)m_pMachine)->i_takeSnapshotHandler(*this);
     1351    }
     1352
     1353    Utf8Str m_strName;
     1354    Utf8Str m_strDescription;
     1355    Utf8Str m_strStateFilePath;
     1356    ComPtr<IInternalSessionControl> m_pDirectControl;
     1357    bool m_fPause;
     1358    uint32_t m_uMemSize;
     1359    bool m_fTakingSnapshotOnline;
     1360};
     1361
     1362/** Restore snapshot task */
    13391363struct SessionMachine::RestoreSnapshotTask
    13401364    : public SessionMachine::SnapshotTask
     
    13421366    RestoreSnapshotTask(SessionMachine *m,
    13431367                        Progress *p,
     1368                        const Utf8Str &t,
    13441369                        Snapshot *s)
    1345         : SnapshotTask(m, p, s)
     1370        : SnapshotTask(m, p, t, s)
    13461371    {}
    13471372
    13481373    void handler()
    13491374    {
    1350         pMachine->i_restoreSnapshotHandler(*this);
     1375        ((SessionMachine *)(Machine *)m_pMachine)->i_restoreSnapshotHandler(*this);
    13511376    }
    13521377};
     
    13581383    DeleteSnapshotTask(SessionMachine *m,
    13591384                       Progress *p,
     1385                       const Utf8Str &t,
    13601386                       bool fDeleteOnline,
    13611387                       Snapshot *s)
    1362         : SnapshotTask(m, p, s),
     1388        : SnapshotTask(m, p, t, s),
    13631389          m_fDeleteOnline(fDeleteOnline)
    13641390    {}
     
    13661392    void handler()
    13671393    {
    1368         pMachine->i_deleteSnapshotHandler(*this);
     1394        ((SessionMachine *)(Machine *)m_pMachine)->i_deleteSnapshotHandler(*this);
    13691395    }
    13701396
     
    13721398};
    13731399
    1374 /**
    1375  * Static SessionMachine method that can get passed to RTThreadCreate to
    1376  * have a thread started for a SnapshotTask. See SnapshotTask above.
    1377  *
    1378  * This calls either RestoreSnapshotTask::handler() or DeleteSnapshotTask::handler().
    1379  */
    1380 
    1381 /* static */ DECLCALLBACK(int) SessionMachine::taskHandler(RTTHREAD /* thread */, void *pvUser)
    1382 {
    1383     AssertReturn(pvUser, VERR_INVALID_POINTER);
    1384 
    1385     SnapshotTask *task = static_cast<SnapshotTask*>(pvUser);
    1386     task->handler();
    1387 
    1388     // it's our responsibility to delete the task
    1389     delete task;
    1390 
    1391     return 0;
    1392 }
    13931400
    13941401////////////////////////////////////////////////////////////////////////////////
    13951402//
    1396 // TakeSnapshot methods (SessionMachine and related tasks)
     1403// TakeSnapshot methods (Machine and related tasks)
    13971404//
    13981405////////////////////////////////////////////////////////////////////////////////
    13991406
    1400 /**
    1401  * Implementation for IInternalMachineControl::beginTakingSnapshot().
    1402  *
    1403  * Gets called indirectly from Console::TakeSnapshot, which creates a
    1404  * progress object in the client and then starts a thread
    1405  * (Console::fntTakeSnapshotWorker) which then calls this.
    1406  *
    1407  * In other words, the asynchronous work for taking snapshots takes place
    1408  * on the _client_ (in the Console). This is different from restoring
    1409  * or deleting snapshots, which start threads on the server.
    1410  *
    1411  * This does the server-side work of taking a snapshot: it creates differencing
    1412  * images for all hard disks attached to the machine and then creates a
    1413  * Snapshot object with a corresponding SnapshotMachine to save the VM settings.
    1414  *
    1415  * The client's fntTakeSnapshotWorker() blocks while this takes place.
    1416  * After this returns successfully, fntTakeSnapshotWorker() will begin
    1417  * saving the machine state to the snapshot object and reconfigure the
    1418  * hard disks.
    1419  *
    1420  * When the console is done, it calls SessionMachine::EndTakingSnapshot().
    1421  *
    1422  * @note Locks mParent + this object for writing.
    1423  *
    1424  * @param aInitiator in: The console on which Console::TakeSnapshot was called.
    1425  * @param aName  in: The name for the new snapshot.
    1426  * @param aDescription  in: A description for the new snapshot.
    1427  * @param aConsoleProgress  in: The console's (client's) progress object.
    1428  * @param fTakingSnapshotOnline  in: True if an online snapshot is being taken (i.e. machine is running).
    1429  * @param aStateFilePath out: name of file in snapshots folder to which the console should write the VM state.
     1407HRESULT Machine::takeSnapshot(const com::Utf8Str &aName,
     1408                              const com::Utf8Str &aDescription,
     1409                              BOOL fPause,
     1410                              ComPtr<IProgress> &aProgress)
     1411{
     1412    NOREF(aName);
     1413    NOREF(aDescription);
     1414    NOREF(fPause);
     1415    NOREF(aProgress);
     1416    ReturnComNotImplemented();
     1417}
     1418
     1419HRESULT SessionMachine::takeSnapshot(const com::Utf8Str &aName,
     1420                                     const com::Utf8Str &aDescription,
     1421                                     BOOL fPause,
     1422                                     ComPtr<IProgress> &aProgress)
     1423{
     1424    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     1425    LogFlowThisFunc(("aName='%s' mMachineState=%d\n", aName.c_str(), mData->mMachineState));
     1426
     1427    if (Global::IsTransient(mData->mMachineState))
     1428        return setError(VBOX_E_INVALID_VM_STATE,
     1429                        tr("Cannot take a snapshot of the machine while it is changing the state (machine state: %s)"),
     1430                        Global::stringifyMachineState(mData->mMachineState));
     1431
     1432    HRESULT rc = S_OK;
     1433
     1434    // prepare the progress object:
     1435    // a) count the no. of hard disk attachments to get a matching no. of progress sub-operations
     1436    ULONG cOperations = 2;              // always at least setting up + finishing up
     1437    ULONG ulTotalOperationsWeight = 2;  // one each for setting up + finishing up
     1438
     1439    for (MediaData::AttachmentList::iterator it = mMediaData->mAttachments.begin();
     1440         it != mMediaData->mAttachments.end();
     1441         ++it)
     1442    {
     1443        const ComObjPtr<MediumAttachment> pAtt(*it);
     1444        AutoReadLock attlock(pAtt COMMA_LOCKVAL_SRC_POS);
     1445        AutoCaller attCaller(pAtt);
     1446        if (pAtt->i_getType() == DeviceType_HardDisk)
     1447        {
     1448            ++cOperations;
     1449
     1450            // assume that creating a diff image takes as long as saving a 1MB state
     1451            ulTotalOperationsWeight += 1;
     1452        }
     1453    }
     1454
     1455    // b) one extra sub-operations for online snapshots OR offline snapshots that have a saved state (needs to be copied)
     1456    const bool fTakingSnapshotOnline = Global::IsOnline(mData->mMachineState);
     1457    LogFlowThisFunc(("fTakingSnapshotOnline = %d\n", fTakingSnapshotOnline));
     1458    if (fTakingSnapshotOnline)
     1459    {
     1460        ++cOperations;
     1461        ulTotalOperationsWeight += mHWData->mMemorySize;
     1462    }
     1463
     1464    // finally, create the progress object
     1465    ComObjPtr<Progress> pProgress;
     1466    pProgress.createObject();
     1467    rc = pProgress->init(mParent,
     1468                         static_cast<IMachine *>(this),
     1469                         Bstr(tr("Taking a snapshot of the virtual machine")).raw(),
     1470                         fTakingSnapshotOnline /* aCancelable */,
     1471                         cOperations,
     1472                         ulTotalOperationsWeight,
     1473                         Bstr(tr("Setting up snapshot operation")).raw(),      // first sub-op description
     1474                         1);        // ulFirstOperationWeight
     1475    if (FAILED(rc))
     1476        return rc;
     1477
     1478    /* create and start the task on a separate thread (note that it will not
     1479     * start working until we release alock) */
     1480    TakeSnapshotTask *pTask = new TakeSnapshotTask(this,
     1481                                                   pProgress,
     1482                                                   "TakeSnap",
     1483                                                   NULL /* pSnapshot */,
     1484                                                   aName,
     1485                                                   aDescription,
     1486                                                   !!fPause,
     1487                                                   mHWData->mMemorySize,
     1488                                                   fTakingSnapshotOnline);
     1489    rc = pTask->createThread();
     1490    if (FAILED(rc))
     1491        return rc;
     1492
     1493    /* set the proper machine state (note: after creating a Task instance) */
     1494    if (fTakingSnapshotOnline)
     1495    {
     1496        if (pTask->m_machineStateBackup != MachineState_Paused && !fPause)
     1497            i_setMachineState(MachineState_LiveSnapshotting);
     1498        else
     1499            i_setMachineState(MachineState_OnlineSnapshotting);
     1500        i_updateMachineStateOnClient();
     1501    }
     1502    else
     1503        i_setMachineState(MachineState_Snapshotting);
     1504
     1505    pTask->m_pProgress.queryInterfaceTo(aProgress.asOutParam());
     1506
     1507    return rc;
     1508}
     1509
     1510/**
     1511 * Task thread implementation for SessionMachine::TakeSnapshot(), called from
     1512 * SessionMachine::taskHandler().
     1513 *
     1514 * @note Locks this object for writing.
     1515 *
     1516 * @param task
    14301517 * @return
    14311518 */
    1432 HRESULT SessionMachine::beginTakingSnapshot(const ComPtr<IConsole> &aInitiator,
    1433                                             const com::Utf8Str &aName,
    1434                                             const com::Utf8Str &aDescription,
    1435                                             const ComPtr<IProgress> &aConsoleProgress,
    1436                                             BOOL  aFTakingSnapshotOnline,
    1437                                             com::Utf8Str &aStateFilePath)
    1438 {
    1439     NOREF(aInitiator);
     1519void SessionMachine::i_takeSnapshotHandler(TakeSnapshotTask &task)
     1520{
    14401521    LogFlowThisFuncEnter();
    14411522
    1442     LogFlowThisFunc(("aName='%s' aFTakingSnapshotOnline=%RTbool\n", aName.c_str(), aFTakingSnapshotOnline));
     1523    // Taking a snapshot consists of the following:
     1524    // 1) creating a Snapshot object with the current state of the machine
     1525    //    (hardware + storage)
     1526    // 2) creating a diff image for each virtual hard disk, into which write
     1527    //    operations go after the snapshot has been created
     1528    // 3) if the machine is online: saving the state of the virtual machine
     1529    //    (in the VM process)
     1530    // 4) reattach the hard disks
     1531    // 5) update the various snapshot/machine objects, save settings
     1532
     1533    HRESULT rc = S_OK;
     1534    AutoCaller autoCaller(this);
     1535    LogFlowThisFunc(("state=%d\n", getObjectState().getState()));
     1536    if (FAILED(autoCaller.rc()))
     1537    {
     1538        /* we might have been uninitialized because the session was accidentally
     1539         * closed by the client, so don't assert */
     1540        rc = setError(E_FAIL,
     1541                      tr("The session has been accidentally closed"));
     1542        task.m_pProgress->i_notifyComplete(rc);
     1543        LogFlowThisFuncLeave();
     1544        return;
     1545    }
    14431546
    14441547    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    14451548
    1446     AssertReturn(    !Global::IsOnlineOrTransient(mData->mMachineState)
    1447                   || mData->mMachineState == MachineState_Running
    1448                   || mData->mMachineState == MachineState_Paused, E_FAIL);
    1449     AssertReturn(mConsoleTaskData.mLastState == MachineState_Null, E_FAIL);
    1450     AssertReturn(mConsoleTaskData.mSnapshot.isNull(), E_FAIL);
    1451 
    1452     if (   mData->mCurrentSnapshot
    1453         && mData->mCurrentSnapshot->i_getDepth() >= SETTINGS_SNAPSHOT_DEPTH_MAX)
    1454     {
    1455 
    1456         return setError(VBOX_E_INVALID_OBJECT_STATE,
    1457                         tr("Cannot take another snapshot for machine '%s', because it exceeds the maximum snapshot depth limit. Please delete some earlier snapshot which you no longer need"),
    1458                         mUserData->s.strName.c_str());
    1459     }
    1460 
    1461     if (    !aFTakingSnapshotOnline
    1462          && mData->mMachineState != MachineState_Saved
    1463        )
    1464     {
    1465         /* save all current settings to ensure current changes are committed and
    1466          * hard disks are fixed up */
    1467         HRESULT rc = i_saveSettings(NULL);
     1549    bool fBeganTakingSnapshot = false;
     1550    BOOL fSuspendedBySave     = FALSE;
     1551
     1552    try
     1553    {
     1554        // @todo: at this point we have to be in the right state!!!!
     1555        AssertStmt(   !Global::IsOnlineOrTransient(mData->mMachineState)
     1556                   || mData->mMachineState == MachineState_Snapshotting
     1557                   || mData->mMachineState == MachineState_OnlineSnapshotting
     1558                   || mData->mMachineState == MachineState_LiveSnapshotting, throw E_FAIL);
     1559        AssertStmt(task.m_machineStateBackup != mData->mMachineState, throw E_FAIL);
     1560        AssertStmt(task.m_pSnapshot.isNull(), throw E_FAIL);
     1561
     1562        if (   mData->mCurrentSnapshot
     1563            && mData->mCurrentSnapshot->i_getDepth() >= SETTINGS_SNAPSHOT_DEPTH_MAX)
     1564        {
     1565            throw setError(VBOX_E_INVALID_OBJECT_STATE,
     1566                           tr("Cannot take another snapshot for machine '%s', because it exceeds the maximum snapshot depth limit. Please delete some earlier snapshot which you no longer need"),
     1567                           mUserData->s.strName.c_str());
     1568        }
     1569
     1570        if (    !task.m_fTakingSnapshotOnline
     1571             && mData->mMachineState != MachineState_Saved)
     1572        {
     1573            /* save settings to ensure current changes are committed and
     1574             * hard disks are fixed up */
     1575            rc = i_saveSettings(NULL);
    14681576                // no need to check for whether VirtualBox.xml needs changing since
    14691577                // we can't have a machine XML rename pending at this point
    1470         if (FAILED(rc)) return rc;
    1471     }
    1472 
    1473     /* create an ID for the snapshot */
    1474     Guid snapshotId;
    1475     snapshotId.create();
    1476 
    1477     /* stateFilePath is null when the machine is not online nor saved */
    1478     if (aFTakingSnapshotOnline)
    1479     {
    1480         Bstr value;
    1481         HRESULT rc = GetExtraData(Bstr("VBoxInternal2/ForceTakeSnapshotWithoutState").raw(),
    1482                                   value.asOutParam());
    1483         if (FAILED(rc) || value != "1")
    1484             // creating a new online snapshot: we need a fresh saved state file
    1485             i_composeSavedStateFilename(aStateFilePath);
    1486     }
    1487     else if (mData->mMachineState == MachineState_Saved)
    1488         // taking an online snapshot from machine in "saved" state: then use existing state file
    1489         aStateFilePath = mSSData->strStateFilePath;
    1490 
    1491     if (aStateFilePath.isNotEmpty())
    1492     {
    1493         // ensure the directory for the saved state file exists
    1494         HRESULT rc = VirtualBox::i_ensureFilePathExists(aStateFilePath, true /* fCreate */);
    1495         if (FAILED(rc)) return rc;
    1496     }
    1497 
    1498     /* create a snapshot machine object */
    1499     ComObjPtr<SnapshotMachine> snapshotMachine;
    1500     snapshotMachine.createObject();
    1501     HRESULT rc = snapshotMachine->init(this, snapshotId.ref(), aStateFilePath);
    1502     AssertComRCReturn(rc, rc);
    1503 
    1504     /* create a snapshot object */
    1505     RTTIMESPEC time;
    1506     ComObjPtr<Snapshot> pSnapshot;
    1507     pSnapshot.createObject();
    1508     rc = pSnapshot->init(mParent,
    1509                          snapshotId,
    1510                          aName,
    1511                          aDescription,
    1512                          *RTTimeNow(&time),
    1513                          snapshotMachine,
    1514                          mData->mCurrentSnapshot);
    1515     AssertComRCReturnRC(rc);
    1516 
    1517     /* fill in the snapshot data */
    1518     mConsoleTaskData.mLastState = mData->mMachineState;
    1519     mConsoleTaskData.mSnapshot = pSnapshot;
    1520 
    1521     /// @todo in the long run the progress object should be moved to
    1522     // VBoxSVC to avoid trouble with monitoring the progress object state
    1523     // when the process where it lives is terminating shortly after the
    1524     // operation completed.
    1525 
    1526     try
    1527     {
     1578            if (FAILED(rc))
     1579                throw rc;
     1580        }
     1581
     1582        /* task.m_strStateFilePath is "" when the machine is offline or saved */
     1583        if (task.m_fTakingSnapshotOnline)
     1584        {
     1585            Bstr value;
     1586            HRESULT rc = GetExtraData(Bstr("VBoxInternal2/ForceTakeSnapshotWithoutState").raw(),
     1587                                      value.asOutParam());
     1588            if (FAILED(rc) || value != "1")
     1589                // creating a new online snapshot: we need a fresh saved state file
     1590                i_composeSavedStateFilename(task.m_strStateFilePath);
     1591        }
     1592        else if (mData->mMachineState == MachineState_Saved)
     1593            // taking an offline snapshot from machine in "saved" state: use existing state file
     1594            task.m_strStateFilePath = mSSData->strStateFilePath;
     1595
     1596        if (task.m_strStateFilePath.isNotEmpty())
     1597        {
     1598            // ensure the directory for the saved state file exists
     1599            rc = VirtualBox::i_ensureFilePathExists(task.m_strStateFilePath, true /* fCreate */);
     1600            if (FAILED(rc))
     1601                throw rc;
     1602        }
     1603
     1604        /* STEP 1: create the snapshot object */
     1605
     1606        /* create an ID for the snapshot */
     1607        Guid snapshotId;
     1608        snapshotId.create();
     1609
     1610        /* create a snapshot machine object */
     1611        ComObjPtr<SnapshotMachine> pSnapshotMachine;
     1612        pSnapshotMachine.createObject();
     1613        rc = pSnapshotMachine->init(this, snapshotId.ref(), task.m_strStateFilePath);
     1614        AssertComRCThrowRC(rc);
     1615
     1616        /* create a snapshot object */
     1617        RTTIMESPEC time;
     1618        RTTimeNow(&time);
     1619        task.m_pSnapshot.createObject();
     1620        rc = task.m_pSnapshot->init(mParent,
     1621                                    snapshotId,
     1622                                    task.m_strName,
     1623                                    task.m_strDescription,
     1624                                    time,
     1625                                    pSnapshotMachine,
     1626                                    mData->mCurrentSnapshot);
     1627        AssertComRCThrowRC(rc);
     1628
     1629        /* STEP 2: create the diff images */
    15281630        LogFlowThisFunc(("Creating differencing hard disks (online=%d)...\n",
    1529                          aFTakingSnapshotOnline));
    1530 
    1531         // backup the media data so we can recover if things goes wrong along the day;
    1532         // the matching commit() is in fixupMedia() during endSnapshot()
     1631                         task.m_fTakingSnapshotOnline));
     1632
     1633        // Backup the media data so we can recover if something goes wrong.
     1634        // The matching commit() is in fixupMedia() during SessionMachine::i_finishTakingSnapshot()
    15331635        i_setModified(IsModified_Storage);
    15341636        mMediaData.backup();
    15351637
    1536         /* Console::fntTakeSnapshotWorker and friends expects this. */
    1537         if (mConsoleTaskData.mLastState == MachineState_Running)
    1538             i_setMachineState(MachineState_LiveSnapshotting);
    1539         else
    1540             i_setMachineState(MachineState_Saving); /** @todo Confusing! Saving is used for both online and offline snapshots. */
    1541 
    15421638        alock.release();
    15431639        /* create new differencing hard disks and attach them to this machine */
    1544         rc = i_createImplicitDiffs(aConsoleProgress,
    1545                                    1,            // operation weight; must be the same as in Console::TakeSnapshot()
    1546                                    !!aFTakingSnapshotOnline);
     1640        rc = i_createImplicitDiffs(task.m_pProgress,
     1641                                   1,            // operation weight; must be the same as in Machine::TakeSnapshot()
     1642                                   task.m_fTakingSnapshotOnline);
    15471643        if (FAILED(rc))
    15481644            throw rc;
     1645        alock.acquire();
    15491646
    15501647        // MUST NOT save the settings or the media registry here, because
    15511648        // this causes trouble with rolling back settings if the user cancels
    15521649        // taking the snapshot after the diff images have been created.
    1553     }
    1554     catch (HRESULT hrc)
    1555     {
    1556         LogThisFunc(("Caught %Rhrc [%s]\n", hrc, Global::stringifyMachineState(mData->mMachineState) ));
    1557         if (    mConsoleTaskData.mLastState != mData->mMachineState
    1558              && (   mConsoleTaskData.mLastState == MachineState_Running
    1559                   ? mData->mMachineState == MachineState_LiveSnapshotting
    1560                   : mData->mMachineState == MachineState_Saving)
    1561            )
    1562                i_setMachineState(mConsoleTaskData.mLastState);
    1563 
    1564         pSnapshot->uninit();
    1565         pSnapshot.setNull();
    1566         mConsoleTaskData.mLastState = MachineState_Null;
    1567         mConsoleTaskData.mSnapshot.setNull();
    1568 
    1569         rc = hrc;
    1570 
    1571         // @todo r=dj what with the implicit diff that we created above? this is never cleaned up
    1572     }
    1573 
    1574     if (!(aFTakingSnapshotOnline && SUCCEEDED(rc)))
    1575         aStateFilePath = "";
    1576 
    1577     LogFlowThisFunc(("LEAVE - %Rhrc [%s]\n", rc, Global::stringifyMachineState(mData->mMachineState) ));
    1578     return rc;
    1579 }
    1580 
    1581 /**
    1582  * Implementation for IInternalMachineControl::endTakingSnapshot().
    1583  *
     1650
     1651        fBeganTakingSnapshot = true;
     1652
     1653        /* Check sanity: for offline snapshots there must not be a saved state
     1654         * file name. All other combinations are valid (though online snapshots
     1655         * without saved state file seems inconsistent - there are exotic use
     1656         * cases, which need to be explicitly enabled, see the code above. */
     1657        if (   !task.m_fTakingSnapshotOnline
     1658            && !task.m_strStateFilePath.isEmpty())
     1659            throw setError(E_FAIL, "Invalid state of saved state file");
     1660
     1661        // STEP 3: save the VM state (if online)
     1662        if (task.m_fTakingSnapshotOnline)
     1663        {
     1664            task.m_pProgress->SetNextOperation(Bstr(tr("Saving the machine state")).raw(),
     1665                                               mHWData->mMemorySize);   // operation weight, same as computed
     1666                                                                        // when setting up progress object
     1667
     1668            if (task.m_strStateFilePath.isNotEmpty())
     1669            {
     1670                alock.release();
     1671                task.m_pProgress->i_setCancelCallback(i_takeSnapshotProgressCancelCallback, &task);
     1672                rc = task.m_pDirectControl->SaveStateWithReason(Reason_Snapshot,
     1673                                                                task.m_pProgress,
     1674                                                                Bstr(task.m_strStateFilePath).raw(),
     1675                                                                task.m_fPause,
     1676                                                                &fSuspendedBySave);
     1677                task.m_pProgress->i_setCancelCallback(NULL, NULL);
     1678                alock.acquire();
     1679                if (FAILED(rc))
     1680                    throw rc;
     1681            }
     1682            else
     1683                LogRel(("Machine: skipped saving state as part of online snapshot\n"));
     1684
     1685            if (!task.m_pProgress->i_notifyPointOfNoReturn())
     1686                throw setError(E_FAIL, tr("Canceled"));
     1687
     1688            // STEP 4: reattach hard disks
     1689            LogFlowThisFunc(("Reattaching new differencing hard disks...\n"));
     1690
     1691            task.m_pProgress->SetNextOperation(Bstr(tr("Reconfiguring medium attachments")).raw(),
     1692                                               1);       // operation weight, same as computed when setting up progress object
     1693
     1694            com::SafeIfaceArray<IMediumAttachment> atts;
     1695            rc = COMGETTER(MediumAttachments)(ComSafeArrayAsOutParam(atts));
     1696            if (FAILED(rc))
     1697                throw rc;
     1698
     1699            alock.release();
     1700            rc = task.m_pDirectControl->ReconfigureMediumAttachments(ComSafeArrayAsInParam(atts));
     1701            alock.acquire();
     1702            if (FAILED(rc))
     1703                throw rc;
     1704        }
     1705
     1706        /*
     1707         * Finalize the requested snapshot object. This will reset the
     1708         * machine state to the state it had at the beginning.
     1709         */
     1710        rc = i_finishTakingSnapshot(task, alock, true /*aSuccess*/);
     1711        // do not throw rc here because we can't call i_finishTakingSnapshot() twice
     1712        LogFlowThisFunc(("i_finishTakingSnapshot -> %Rhrc [mMachineState=%s]\n", rc, Global::stringifyMachineState(mData->mMachineState)));
     1713    }
     1714    catch (HRESULT rcThrown)
     1715    {
     1716        rc = rcThrown;
     1717        LogThisFunc(("Caught %Rhrc [mMachineState=%s]\n", rc, Global::stringifyMachineState(mData->mMachineState)));
     1718
     1719        // @todo r=klaus check that the implicit diffs created above are cleaned up im the relevant error cases
     1720
     1721        /* preserve existing error info */
     1722        ErrorInfoKeeper eik;
     1723
     1724        if (fBeganTakingSnapshot)
     1725            i_finishTakingSnapshot(task, alock, false /*aSuccess*/);
     1726
     1727        // have to postpone this to the end as i_finishTakingSnapshot() needs
     1728        // it for various cleanup steps
     1729        task.m_pSnapshot->uninit();
     1730        task.m_pSnapshot.setNull();
     1731    }
     1732    Assert(alock.isWriteLockOnCurrentThread());
     1733
     1734    {
     1735        // Keep all error information over the cleanup steps
     1736        ErrorInfoKeeper eik;
     1737
     1738        /*
     1739         * Fix up the machine state.
     1740         *
     1741         * For offline snapshots we just update the local copy, for the other
     1742         * variants do the entire work. This ensures that the state is in sync
     1743         * with the VM process (in particular the VM execution state).
     1744         */
     1745        bool fNeedClientMachineStateUpdate = false;
     1746        if (   mData->mMachineState == MachineState_LiveSnapshotting
     1747            || mData->mMachineState == MachineState_OnlineSnapshotting
     1748            || mData->mMachineState == MachineState_Snapshotting)
     1749        {
     1750            if (!task.m_fTakingSnapshotOnline)
     1751                i_setMachineState(task.m_machineStateBackup);
     1752            else
     1753            {
     1754                MachineState_T enmMachineState = MachineState_Null;
     1755                HRESULT rc2 = task.m_pDirectControl->COMGETTER(NominalState)(&enmMachineState);
     1756                if (FAILED(rc2) || enmMachineState == MachineState_Null)
     1757                {
     1758                    AssertMsgFailed(("state=%s\n", Global::stringifyMachineState(enmMachineState)));
     1759                    // pure nonsense, try to continue somehow
     1760                    enmMachineState = MachineState_Aborted;
     1761                }
     1762                if (enmMachineState == MachineState_Paused)
     1763                {
     1764                    if (fSuspendedBySave)
     1765                    {
     1766                        alock.release();
     1767                        rc2 = task.m_pDirectControl->ResumeWithReason(Reason_Snapshot);
     1768                        alock.acquire();
     1769                        if (SUCCEEDED(rc2))
     1770                            enmMachineState = task.m_machineStateBackup;
     1771                    }
     1772                    else
     1773                        enmMachineState = task.m_machineStateBackup;
     1774                }
     1775                if (enmMachineState != mData->mMachineState)
     1776                {
     1777                    fNeedClientMachineStateUpdate = true;
     1778                    i_setMachineState(enmMachineState);
     1779                }
     1780            }
     1781        }
     1782
     1783        /* check the remote state to see that we got it right. */
     1784        MachineState_T enmMachineState = MachineState_Null;
     1785        if (!task.m_pDirectControl.isNull())
     1786        {
     1787            ComPtr<IConsole> pConsole;
     1788            task.m_pDirectControl->COMGETTER(RemoteConsole)(pConsole.asOutParam());
     1789            if (!pConsole.isNull())
     1790                pConsole->COMGETTER(State)(&enmMachineState);
     1791        }
     1792        LogFlowThisFunc(("local mMachineState=%s remote mMachineState=%s\n",
     1793                         Global::stringifyMachineState(mData->mMachineState),
     1794                         Global::stringifyMachineState(enmMachineState)));
     1795
     1796        if (fNeedClientMachineStateUpdate)
     1797            i_updateMachineStateOnClient();
     1798    }
     1799
     1800    task.m_pProgress->i_notifyComplete(rc);
     1801
     1802    LogFlowThisFuncLeave();
     1803}
     1804
     1805
     1806/**
     1807 * Progress cancelation callback employed by SessionMachine::i_takeSnapshotHandler.
     1808 */
     1809/*static*/
     1810void SessionMachine::i_takeSnapshotProgressCancelCallback(void *pvUser)
     1811{
     1812    TakeSnapshotTask *pTask = (TakeSnapshotTask *)pvUser;
     1813    AssertPtrReturnVoid(pTask);
     1814    AssertReturnVoid(!pTask->m_pDirectControl.isNull());
     1815    pTask->m_pDirectControl->CancelSaveStateWithReason();
     1816}
     1817
     1818
     1819/**
    15841820 * Called by the Console when it's done saving the VM state into the snapshot
    15851821 * (if online) and reconfiguring the hard disks. See BeginTakingSnapshot() above.
     
    15931829 * @return
    15941830 */
    1595 HRESULT SessionMachine::endTakingSnapshot(BOOL aSuccess)
     1831HRESULT SessionMachine::i_finishTakingSnapshot(TakeSnapshotTask &task, AutoWriteLock &alock, bool aSuccess)
    15961832{
    15971833    LogFlowThisFunc(("\n"));
    15981834
    1599     AutoWriteLock machineLock(this COMMA_LOCKVAL_SRC_POS);
     1835    Assert(alock.isWriteLockOnCurrentThread());
    16001836
    16011837    AssertReturn(   !aSuccess
    1602                  || (    (    mData->mMachineState == MachineState_Saving
    1603                            || mData->mMachineState == MachineState_LiveSnapshotting)
    1604                       && mConsoleTaskData.mLastState != MachineState_Null
    1605                       && !mConsoleTaskData.mSnapshot.isNull()
    1606                     )
    1607                  , E_FAIL);
    1608 
    1609     /*
    1610      * Restore the state we had when BeginTakingSnapshot() was called,
    1611      * Console::fntTakeSnapshotWorker restores its local copy when we return.
    1612      * If the state was Running, then let Console::fntTakeSnapshotWorker do it
    1613      * all to avoid races.
    1614      */
    1615     if (    mData->mMachineState != mConsoleTaskData.mLastState
    1616          && mConsoleTaskData.mLastState != MachineState_Running
    1617        )
    1618            i_setMachineState(mConsoleTaskData.mLastState);
     1838                 || mData->mMachineState == MachineState_Snapshotting
     1839                 || mData->mMachineState == MachineState_OnlineSnapshotting
     1840                 || mData->mMachineState == MachineState_LiveSnapshotting, E_FAIL);
    16191841
    16201842    ComObjPtr<Snapshot> pOldFirstSnap = mData->mFirstSnapshot;
    16211843    ComObjPtr<Snapshot> pOldCurrentSnap = mData->mCurrentSnapshot;
    16221844
    1623     bool fOnline = Global::IsOnline(mConsoleTaskData.mLastState);
     1845    bool fOnline = Global::IsOnline(task.m_machineStateBackup);
    16241846
    16251847    HRESULT rc = S_OK;
     
    16281850    {
    16291851        // new snapshot becomes the current one
    1630         mData->mCurrentSnapshot = mConsoleTaskData.mSnapshot;
     1852        mData->mCurrentSnapshot = task.m_pSnapshot;
    16311853
    16321854        /* memorize the first snapshot if necessary */
     
    16511873        /* inform callbacks */
    16521874        mParent->i_onSnapshotTaken(mData->mUuid,
    1653                                    mConsoleTaskData.mSnapshot->i_getId());
    1654         machineLock.release();
     1875                                   task.m_pSnapshot->i_getId());
     1876        alock.release();
    16551877    }
    16561878    else
     
    16581880        /* delete all differencing hard disks created (this will also attach
    16591881         * their parents back by rolling back mMediaData) */
    1660         machineLock.release();
     1882        alock.release();
    16611883
    16621884        i_rollbackMedia();
     
    16701892            // snapshot means that a new saved state file was created, which we must
    16711893            // clean up now
    1672             RTFileDelete(mConsoleTaskData.mSnapshot->i_getStateFilePath().c_str());
    1673             machineLock.acquire();
    1674 
    1675 
    1676         mConsoleTaskData.mSnapshot->uninit();
    1677         machineLock.release();
     1894            RTFileDelete(task.m_pSnapshot->i_getStateFilePath().c_str());
     1895
     1896        alock.acquire();
     1897
     1898        task.m_pSnapshot->uninit();
     1899        alock.release();
    16781900
    16791901    }
    16801902
    16811903    /* clear out the snapshot data */
    1682     mConsoleTaskData.mLastState = MachineState_Null;
    1683     mConsoleTaskData.mSnapshot.setNull();
    1684 
    1685     /* machineLock has been released already */
    1686 
     1904    task.m_pSnapshot.setNull();
     1905
     1906    /* alock has been released already */
    16871907    mParent->i_saveModifiedRegistries();
     1908
     1909    alock.acquire();
    16881910
    16891911    return rc;
     
    16921914////////////////////////////////////////////////////////////////////////////////
    16931915//
    1694 // RestoreSnapshot methods (SessionMachine and related tasks)
     1916// RestoreSnapshot methods (Machine and related tasks)
    16951917//
    16961918////////////////////////////////////////////////////////////////////////////////
    16971919
    1698 /**
    1699  * Implementation for IInternalMachineControl::restoreSnapshot().
    1700  *
    1701  * Gets called from Console::RestoreSnapshot(), and that's basically the
    1702  * only thing Console does. Restoring a snapshot happens entirely on the
    1703  * server side since the machine cannot be running.
    1704  *
    1705  * This creates a new thread that does the work and returns a progress
    1706  * object to the client which is then returned to the caller of
    1707  * Console::RestoreSnapshot().
    1708  *
     1920HRESULT Machine::restoreSnapshot(const ComPtr<ISnapshot> &aSnapshot,
     1921                                 ComPtr<IProgress> &aProgress)
     1922{
     1923    NOREF(aSnapshot);
     1924    NOREF(aProgress);
     1925    ReturnComNotImplemented();
     1926}
     1927
     1928/**
     1929 * Restoring a snapshot happens entirely on the server side, the machine cannot be running.
     1930 *
     1931 * This creates a new thread that does the work and returns a progress object to the client.
    17091932 * Actual work then takes place in RestoreSnapshotTask::handler().
    17101933 *
    17111934 * @note Locks this + children objects for writing!
    17121935 *
    1713  * @param aInitiator in: rhe console on which Console::RestoreSnapshot was called.
    17141936 * @param aSnapshot in: the snapshot to restore.
    1715  * @param aMachineState in: client-side machine state.
    17161937 * @param aProgress out: progress object to monitor restore thread.
    17171938 * @return
    17181939 */
    1719 HRESULT SessionMachine::restoreSnapshot(const ComPtr<IConsole> &aInitiator,
    1720                                         const ComPtr<ISnapshot> &aSnapshot,
    1721                                         MachineState_T *aMachineState,
     1940HRESULT SessionMachine::restoreSnapshot(const ComPtr<ISnapshot> &aSnapshot,
    17221941                                        ComPtr<IProgress> &aProgress)
    17231942{
     
    17271946
    17281947    // machine must not be running
    1729     ComAssertRet(!Global::IsOnlineOrTransient(mData->mMachineState),
    1730                  E_FAIL);
     1948    if (Global::IsOnlineOrTransient(mData->mMachineState))
     1949        return setError(VBOX_E_INVALID_VM_STATE,
     1950                        tr("Cannot delete the current state of the running machine (machine state: %s)"),
     1951                        Global::stringifyMachineState(mData->mMachineState));
    17311952
    17321953    ISnapshot* iSnapshot = aSnapshot;
    17331954    ComObjPtr<Snapshot> pSnapshot(static_cast<Snapshot*>(iSnapshot));
    17341955    ComObjPtr<SnapshotMachine> pSnapMachine = pSnapshot->i_getSnapshotMachine();
     1956
     1957    HRESULT rc = S_OK;
    17351958
    17361959    // create a progress object. The number of operations is:
     
    17581981    ComObjPtr<Progress> pProgress;
    17591982    pProgress.createObject();
    1760     pProgress->init(mParent, aInitiator,
     1983    pProgress->init(mParent, static_cast<IMachine*>(this),
    17611984                    BstrFmt(tr("Restoring snapshot '%s'"), pSnapshot->i_getName().c_str()).raw(),
    17621985                    FALSE /* aCancelable */,
     
    17681991    /* create and start the task on a separate thread (note that it will not
    17691992     * start working until we release alock) */
    1770     RestoreSnapshotTask *task = new RestoreSnapshotTask(this,
    1771                                                         pProgress,
    1772                                                         pSnapshot);
    1773     int vrc = RTThreadCreate(NULL,
    1774                              taskHandler,
    1775                              (void*)task,
    1776                              0,
    1777                              RTTHREADTYPE_MAIN_WORKER,
    1778                              0,
    1779                              "RestoreSnap");
    1780     if (RT_FAILURE(vrc))
    1781     {
    1782         delete task;
    1783         ComAssertRCRet(vrc, E_FAIL);
    1784     }
     1993    RestoreSnapshotTask *pTask = new RestoreSnapshotTask(this,
     1994                                                         pProgress,
     1995                                                         "RestoreSnap",
     1996                                                         pSnapshot);
     1997    rc = pTask->createThread();
     1998    if (FAILED(rc))
     1999        return rc;
    17852000
    17862001    /* set the proper machine state (note: after creating a Task instance) */
     
    17892004    /* return the progress to the caller */
    17902005    pProgress.queryInterfaceTo(aProgress.asOutParam());
    1791 
    1792     /* return the new state to the caller */
    1793     *aMachineState = mData->mMachineState;
    17942006
    17952007    LogFlowThisFuncLeave();
     
    18082020 * @note Locks mParent + this object for writing.
    18092021 *
    1810  * @param aTask Task data.
    1811  */
    1812 void SessionMachine::i_restoreSnapshotHandler(RestoreSnapshotTask &aTask)
     2022 * @param pTask Task data.
     2023 */
     2024void SessionMachine::i_restoreSnapshotHandler(RestoreSnapshotTask &task)
    18132025{
    18142026    LogFlowThisFuncEnter();
     
    18212033        /* we might have been uninitialized because the session was accidentally
    18222034         * closed by the client, so don't assert */
    1823         aTask.pProgress->i_notifyComplete(E_FAIL,
    1824                                           COM_IIDOF(IMachine),
    1825                                           getComponentName(),
    1826                                           tr("The session has been accidentally closed"));
     2035        task.m_pProgress->i_notifyComplete(E_FAIL,
     2036                                           COM_IIDOF(IMachine),
     2037                                           getComponentName(),
     2038                                           tr("The session has been accidentally closed"));
    18272039
    18282040        LogFlowThisFuncLeave();
     
    18462058        /* Delete the saved state file if the machine was Saved prior to this
    18472059         * operation */
    1848         if (aTask.machineStateBackup == MachineState_Saved)
     2060        if (task.m_machineStateBackup == MachineState_Saved)
    18492061        {
    18502062            Assert(!mSSData->strStateFilePath.isEmpty());
     
    18562068            i_releaseSavedStateFile(strStateFile, NULL /* pSnapshotToIgnore */ );
    18572069
    1858             aTask.modifyBackedUpState(MachineState_PoweredOff);
     2070            task.modifyBackedUpState(MachineState_PoweredOff);
    18592071
    18602072            rc = i_saveStateSettings(SaveSTS_StateFilePath);
     
    18672079
    18682080        {
    1869             AutoReadLock snapshotLock(aTask.pSnapshot COMMA_LOCKVAL_SRC_POS);
     2081            AutoReadLock snapshotLock(task.m_pSnapshot COMMA_LOCKVAL_SRC_POS);
    18702082
    18712083            /* remember the timestamp of the snapshot we're restoring from */
    1872             snapshotTimeStamp = aTask.pSnapshot->i_getTimeStamp();
    1873 
    1874             ComPtr<SnapshotMachine> pSnapshotMachine(aTask.pSnapshot->i_getSnapshotMachine());
     2084            snapshotTimeStamp = task.m_pSnapshot->i_getTimeStamp();
     2085
     2086            ComPtr<SnapshotMachine> pSnapshotMachine(task.m_pSnapshot->i_getSnapshotMachine());
    18752087
    18762088            /* copy all hardware data from the snapshot */
     
    18972109            alock.release();
    18982110
    1899             rc = i_createImplicitDiffs(aTask.pProgress,
     2111            rc = i_createImplicitDiffs(task.m_pProgress,
    19002112                                       1,
    19012113                                       false /* aOnline */);
     
    19072119
    19082120            /* Note: on success, current (old) hard disks will be
    1909              * deassociated/deleted on #commit() called from #saveSettings() at
     2121             * deassociated/deleted on #commit() called from #i_saveSettings() at
    19102122             * the end. On failure, newly created implicit diffs will be
    19112123             * deleted by #rollback() at the end. */
     
    19142126            Assert(mSSData->strStateFilePath.isEmpty());
    19152127
    1916             const Utf8Str &strSnapshotStateFile = aTask.pSnapshot->i_getStateFilePath();
     2128            const Utf8Str &strSnapshotStateFile = task.m_pSnapshot->i_getStateFilePath();
    19172129
    19182130            if (strSnapshotStateFile.isNotEmpty())
     
    19202132                mSSData->strStateFilePath = strSnapshotStateFile;
    19212133
    1922             LogFlowThisFunc(("Setting new current snapshot {%RTuuid}\n", aTask.pSnapshot->i_getId().raw()));
     2134            LogFlowThisFunc(("Setting new current snapshot {%RTuuid}\n", task.m_pSnapshot->i_getId().raw()));
    19232135            /* make the snapshot we restored from the current snapshot */
    1924             mData->mCurrentSnapshot = aTask.pSnapshot;
     2136            mData->mCurrentSnapshot = task.m_pSnapshot;
    19252137        }
    19262138
     
    19692181
    19702182        // detach the current-state diffs that we detected above and build a list of
    1971         // image files to delete _after_ saveSettings()
     2183        // image files to delete _after_ i_saveSettings()
    19722184
    19732185        MediaList llDiffsToDelete;
     
    19852197
    19862198            // Normally we "detach" the medium by removing the attachment object
    1987             // from the current machine data; saveSettings() below would then
     2199            // from the current machine data; i_saveSettings() below would then
    19882200            // compare the current machine data with the one in the backup
    19892201            // and actually call Medium::removeBackReference(). But that works only half
     
    19912203            // remove from machine data
    19922204            mMediaData->mAttachments.remove(pAttach);
    1993             // Remove it from the backup or else saveSettings will try to detach
     2205            // Remove it from the backup or else i_saveSettings will try to detach
    19942206            // it again and assert. The paranoia check avoids crashes (see
    19952207            // assert above) if this code is buggy and saves settings in the
     
    20092221        if (FAILED(rc))
    20102222            throw rc;
    2011         // unconditionally add the parent registry. We do similar in SessionMachine::EndTakingSnapshot
    2012         // (mParent->saveSettings())
    20132223
    20142224        // release the locks before updating registry and deleting image files
    20152225        alock.release();
    20162226
     2227        // unconditionally add the parent registry.
    20172228        mParent->i_markRegistryModified(mParent->i_getGlobalRegistryId());
    20182229
     
    20282239            HRESULT rc2 = pMedium->i_deleteStorage(NULL /* aProgress */,
    20292240                                                   true /* aWait */);
    2030             // ignore errors here because we cannot roll back after saveSettings() above
     2241            // ignore errors here because we cannot roll back after i_saveSettings() above
    20312242            if (SUCCEEDED(rc2))
    20322243                pMedium->uninit();
     
    20492260        {
    20502261            /* restore the machine state */
    2051             i_setMachineState(aTask.machineStateBackup);
     2262            i_setMachineState(task.m_machineStateBackup);
    20522263            i_updateMachineStateOnClient();
    20532264        }
     
    20572268
    20582269    /* set the result (this will try to fetch current error info on failure) */
    2059     aTask.pProgress->i_notifyComplete(rc);
     2270    task.m_pProgress->i_notifyComplete(rc);
    20602271
    20612272    if (SUCCEEDED(rc))
     
    20732284////////////////////////////////////////////////////////////////////////////////
    20742285
    2075 /**
    2076  * Implementation for IInternalMachineControl::deleteSnapshot().
    2077  *
    2078  * Gets called from Console::DeleteSnapshot(), and that's basically the
    2079  * only thing Console does initially. Deleting a snapshot happens entirely on
    2080  * the server side if the machine is not running, and if it is running then
    2081  * the individual merges are done via internal session callbacks.
     2286HRESULT Machine::deleteSnapshot(const com::Guid &aId, ComPtr<IProgress> &aProgress)
     2287{
     2288    NOREF(aId);
     2289    NOREF(aProgress);
     2290    ReturnComNotImplemented();
     2291}
     2292
     2293HRESULT SessionMachine::deleteSnapshot(const com::Guid &aId, ComPtr<IProgress> &aProgress)
     2294{
     2295    return i_deleteSnapshot(aId, aId,
     2296                            FALSE /* fDeleteAllChildren */,
     2297                            aProgress);
     2298}
     2299
     2300HRESULT Machine::deleteSnapshotAndAllChildren(const com::Guid &aId, ComPtr<IProgress> &aProgress)
     2301{
     2302    NOREF(aId);
     2303    NOREF(aProgress);
     2304    ReturnComNotImplemented();
     2305}
     2306
     2307HRESULT SessionMachine::deleteSnapshotAndAllChildren(const com::Guid &aId, ComPtr<IProgress> &aProgress)
     2308{
     2309    return i_deleteSnapshot(aId, aId,
     2310                            TRUE /* fDeleteAllChildren */,
     2311                            aProgress);
     2312}
     2313
     2314HRESULT Machine::deleteSnapshotRange(const com::Guid &aStartId, const com::Guid &aEndId, ComPtr<IProgress> &aProgress)
     2315{
     2316    NOREF(aStartId);
     2317    NOREF(aEndId);
     2318    NOREF(aProgress);
     2319    ReturnComNotImplemented();
     2320}
     2321
     2322HRESULT SessionMachine::deleteSnapshotRange(const com::Guid &aStartId, const com::Guid &aEndId, ComPtr<IProgress> &aProgress)
     2323{
     2324    return i_deleteSnapshot(aStartId, aEndId,
     2325                            FALSE /* fDeleteAllChildren */,
     2326                            aProgress);
     2327}
     2328
     2329
     2330/**
     2331 * Implementation for SessionMachine::i_deleteSnapshot().
     2332 *
     2333 * Gets called from SessionMachine::DeleteSnapshot(). Deleting a snapshot
     2334 * happens entirely on the server side if the machine is not running, and
     2335 * if it is running then the merges are done via internal session callbacks.
    20822336 *
    20832337 * This creates a new thread that does the work and returns a progress
    2084  * object to the client which is then returned to the caller of
    2085  * Console::DeleteSnapshot().
    2086  *
    2087  * Actual work then takes place in DeleteSnapshotTask::handler().
     2338 * object to the client.
     2339 *
     2340 * Actual work then takes place in SessionMachine::i_deleteSnapshotHandler().
    20882341 *
    20892342 * @note Locks mParent + this + children objects for writing!
    20902343 */
    2091 HRESULT SessionMachine::deleteSnapshot(const ComPtr<IConsole> &aInitiator,
    2092                                        const com::Guid &aStartId,
    2093                                        const com::Guid &aEndId,
    2094                                        BOOL aDeleteAllChildren,
    2095                                        MachineState_T *aMachineState,
    2096                                        ComPtr<IProgress> &aProgress)
     2344HRESULT SessionMachine::i_deleteSnapshot(const com::Guid &aStartId,
     2345                                         const com::Guid &aEndId,
     2346                                         BOOL aDeleteAllChildren,
     2347                                         ComPtr<IProgress> &aProgress)
    20972348{
    20982349    LogFlowThisFuncEnter();
    20992350
    2100     AssertReturn(aInitiator && !aStartId.isZero() && !aEndId.isZero() && aStartId.isValid() && aEndId.isValid(), E_INVALIDARG);
     2351    AssertReturn(!aStartId.isZero() && !aEndId.isZero() && aStartId.isValid() && aEndId.isValid(), E_INVALIDARG);
    21012352
    21022353
     
    21062357
    21072358    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     2359
     2360    if (Global::IsTransient(mData->mMachineState))
     2361        return setError(VBOX_E_INVALID_VM_STATE,
     2362                        tr("Cannot delete a snapshot of the machine while it is changing the state (machine state: %s)"),
     2363                        Global::stringifyMachineState(mData->mMachineState));
    21082364
    21092365    // be very picky about machine states
     
    22002456    ComObjPtr<Progress> pProgress;
    22012457    pProgress.createObject();
    2202     pProgress->init(mParent, aInitiator,
     2458    pProgress->init(mParent, static_cast<IMachine*>(this),
    22032459                    BstrFmt(tr("Deleting snapshot '%s'"), pSnapshot->i_getName().c_str()).raw(),
    22042460                    FALSE /* aCancelable */,
     
    22122468
    22132469    /* create and start the task on a separate thread */
    2214     DeleteSnapshotTask *task = new DeleteSnapshotTask(this, pProgress,
    2215                                                       fDeleteOnline, pSnapshot);
    2216     int vrc = RTThreadCreate(NULL,
    2217                              taskHandler,
    2218                              (void*)task,
    2219                              0,
    2220                              RTTHREADTYPE_MAIN_WORKER,
    2221                              0,
    2222                              "DeleteSnapshot");
    2223     if (RT_FAILURE(vrc))
    2224     {
    2225         delete task;
    2226         return E_FAIL;
    2227     }
     2470    DeleteSnapshotTask *pTask = new DeleteSnapshotTask(this, pProgress,
     2471                                                       "DeleteSnap",
     2472                                                       fDeleteOnline,
     2473                                                       pSnapshot);
     2474    rc = pTask->createThread();
     2475    if (FAILED(rc))
     2476        return rc;
    22282477
    22292478    // the task might start running but will block on acquiring the machine's write lock
     
    22362485    else
    22372486        i_setMachineState(MachineState_DeletingSnapshot);
     2487    i_updateMachineStateOnClient();
    22382488
    22392489    /* return the progress to the caller */
    22402490    pProgress.queryInterfaceTo(aProgress.asOutParam());
    2241 
    2242     /* return the new state to the caller */
    2243     *aMachineState = mData->mMachineState;
    22442491
    22452492    LogFlowThisFuncLeave();
     
    23412588 * @note Locks the machine + the snapshot + the media tree for writing!
    23422589 *
    2343  * @param aTask Task data.
    2344  */
    2345 
    2346 void SessionMachine::i_deleteSnapshotHandler(DeleteSnapshotTask &aTask)
     2590 * @param pTask Task data.
     2591 */
     2592void SessionMachine::i_deleteSnapshotHandler(DeleteSnapshotTask &task)
    23472593{
    23482594    LogFlowThisFuncEnter();
    23492595
     2596    HRESULT rc = S_OK;
    23502597    AutoCaller autoCaller(this);
    2351 
    23522598    LogFlowThisFunc(("state=%d\n", getObjectState().getState()));
    2353     if (!autoCaller.isOk())
     2599    if (FAILED(autoCaller.rc()))
    23542600    {
    23552601        /* we might have been uninitialized because the session was accidentally
    23562602         * closed by the client, so don't assert */
    2357         aTask.pProgress->i_notifyComplete(E_FAIL,
    2358                                           COM_IIDOF(IMachine),
    2359                                           getComponentName(),
    2360                                           tr("The session has been accidentally closed"));
     2603        rc = setError(E_FAIL,
     2604                      tr("The session has been accidentally closed"));
     2605        task.m_pProgress->i_notifyComplete(rc);
    23612606        LogFlowThisFuncLeave();
    23622607        return;
    23632608    }
    23642609
    2365     HRESULT rc = S_OK;
    23662610    MediumDeleteRecList toDelete;
    23672611    Guid snapshotId;
     
    23712615        /* Locking order:  */
    23722616        AutoMultiWriteLock2 multiLock(this->lockHandle(),                   // machine
    2373                                       aTask.pSnapshot->lockHandle()         // snapshot
     2617                                      task.m_pSnapshot->lockHandle()        // snapshot
    23742618                                      COMMA_LOCKVAL_SRC_POS);
    23752619        // once we have this lock, we know that SessionMachine::DeleteSnapshot()
     
    23792623                               COMMA_LOCKVAL_SRC_POS);
    23802624
    2381         ComObjPtr<SnapshotMachine> pSnapMachine = aTask.pSnapshot->i_getSnapshotMachine();
     2625        ComObjPtr<SnapshotMachine> pSnapMachine = task.m_pSnapshot->i_getSnapshotMachine();
    23822626        // no need to lock the snapshot machine since it is const by definition
    23832627        Guid machineId = pSnapMachine->i_getId();
    23842628
    23852629        // save the snapshot ID (for callbacks)
    2386         snapshotId = aTask.pSnapshot->i_getId();
     2630        snapshotId = task.m_pSnapshot->i_getId();
    23872631
    23882632        // first pass:
     
    24282672            MediumLockList *pChildrenToReparent = NULL;
    24292673            bool fNeedsOnlineMerge = false;
    2430             bool fOnlineMergePossible = aTask.m_fDeleteOnline;
     2674            bool fOnlineMergePossible = task.m_fDeleteOnline;
    24312675            MediumLockList *pMediumLockList = NULL;
    24322676            MediumLockList *pVMMALockList = NULL;
     
    26662910            AutoWriteLock machineLock(this COMMA_LOCKVAL_SRC_POS);
    26672911
    2668             Utf8Str stateFilePath = aTask.pSnapshot->i_getStateFilePath();
     2912            Utf8Str stateFilePath = task.m_pSnapshot->i_getStateFilePath();
    26692913            if (!stateFilePath.isEmpty())
    26702914            {
    2671                 aTask.pProgress->SetNextOperation(Bstr(tr("Deleting the execution state")).raw(),
    2672                                                   1);        // weight
    2673 
    2674                 i_releaseSavedStateFile(stateFilePath, aTask.pSnapshot /* pSnapshotToIgnore */);
     2915                task.m_pProgress->SetNextOperation(Bstr(tr("Deleting the execution state")).raw(),
     2916                                                   1);        // weight
     2917
     2918                i_releaseSavedStateFile(stateFilePath, task.m_pSnapshot /* pSnapshotToIgnore */);
    26752919
    26762920                // machine will need saving now
     
    26972941            }
    26982942
    2699             aTask.pProgress->SetNextOperation(BstrFmt(tr("Merging differencing image '%s'"),
    2700                                               pMedium->i_getName().c_str()).raw(),
    2701                                               ulWeight);
     2943            task.m_pProgress->SetNextOperation(BstrFmt(tr("Merging differencing image '%s'"),
     2944                                               pMedium->i_getName().c_str()).raw(),
     2945                                               ulWeight);
    27022946
    27032947            bool fNeedSourceUninit = false;
     
    27222966                    /* No need to hold the lock any longer. */
    27232967                    mLock.release();
    2724                     rc = pMedium->i_deleteStorage(&aTask.pProgress,
     2968                    rc = pMedium->i_deleteStorage(&task.m_pProgress,
    27252969                                                  true /* aWait */);
    27262970                    if (FAILED(rc))
     
    27402984                    // This callback will arrive while onlineMergeMedium is
    27412985                    // still executing, and there can't be two tasks.
     2986                    /// @todo r=klaus this hack needs to go, and the logic needs to be "unconvoluted", putting SessionMachine in charge of coordinating the reconfig/resume.
    27422987                    mConsoleTaskData.mDeleteSnapshotInfo = (void *)&(*it);
    27432988                    // online medium merge, in the direction decided earlier
     
    27492994                                             it->mpChildrenToReparent,
    27502995                                             it->mpMediumLockList,
    2751                                              aTask.pProgress,
     2996                                             task.m_pProgress,
    27522997                                             &fNeedsSave);
    27532998                    mConsoleTaskData.mDeleteSnapshotInfo = NULL;
     
    27613006                                                 it->mpChildrenToReparent,
    27623007                                                 it->mpMediumLockList,
    2763                                                  &aTask.pProgress,
     3008                                                 &task.m_pProgress,
    27643009                                                 true /* aWait */);
    27653010                }
     
    28263071                ComObjPtr<Machine> pMachine = this;
    28273072                Guid childSnapshotId;
    2828                 ComObjPtr<Snapshot> pChildSnapshot = aTask.pSnapshot->i_getFirstChild();
     3073                ComObjPtr<Snapshot> pChildSnapshot = task.m_pSnapshot->i_getFirstChild();
    28293074                if (pChildSnapshot)
    28303075                {
     
    28713116            AutoWriteLock machineLock(this COMMA_LOCKVAL_SRC_POS);
    28723117
    2873             aTask.pSnapshot->i_beginSnapshotDelete();
    2874             aTask.pSnapshot->uninit();
     3118            task.m_pSnapshot->i_beginSnapshotDelete();
     3119            task.m_pSnapshot->uninit();
    28753120
    28763121            machineLock.release();
     
    29123157        // restore the machine state that was saved when the
    29133158        // task was started
    2914         i_setMachineState(aTask.machineStateBackup);
     3159        i_setMachineState(task.m_machineStateBackup);
    29153160        i_updateMachineStateOnClient();
    29163161
     
    29193164
    29203165    // report the result (this will try to fetch current error info on failure)
    2921     aTask.pProgress->i_notifyComplete(rc);
     3166    task.m_pProgress->i_notifyComplete(rc);
    29223167
    29233168    if (SUCCEEDED(rc))
     
    30613306            aSource = aHD;
    30623307            aTarget = pChild;
    3063             LogFlowFunc(("Forward merging selected\n"));
     3308            LogFlowThisFunc(("Forward merging selected\n"));
    30643309        }
    30653310        else
     
    30673312            aSource = pChild;
    30683313            aTarget = aHD;
    3069             LogFlowFunc(("Backward merging selected\n"));
     3314            LogFlowThisFunc(("Backward merging selected\n"));
    30703315        }
    30713316    }
     
    35803825            AssertComRC(rc);
    35813826
     3827            treeLock.release();
    35823828            pMedium->uninit();
     3829            treeLock.acquire();
    35833830        }
    35843831
  • trunk/src/VBox/ValidationKit/testdriver/vboxwrappers.py

    r55084 r55214  
    21902190
    21912191        Returns True on success.
    2192         Returns False on IConsole::restoreSnapshot() failure.
     2192        Returns False on IMachine::restoreSnapshot() failure.
    21932193        Returns None if the progress object returns failure.
    21942194        """
    21952195        try:
    2196             oProgress = self.o.console.restoreSnapshot(oSnapshot);
    2197         except:
    2198             reporter.logXcpt('IConsole::restoreSnapshot failed on %s' % (self.sName));
     2196            if self.fpApiVer >= 5.0:
     2197                oProgress = self.o.machine.restoreSnapshot(oSnapshot);
     2198            else:
     2199                oProgress = self.o.console.restoreSnapshot(oSnapshot);
     2200        except:
     2201            reporter.logXcpt('IMachine::restoreSnapshot failed on %s' % (self.sName));
    21992202            if fFudgeOnFailure:
    22002203                self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge
     
    22162219
    22172220        Returns True on success.
    2218         Returns False on IConsole::deleteSnapshot() failure.
    2219         """
    2220         try:
    2221             oProgressCom = self.o.console.deleteSnapshot(oSnapshot);
     2221        Returns False on IMachine::deleteSnapshot() failure.
     2222        """
     2223        try:
     2224            if self.fpApiVer >= 5.0:
     2225                oProgressCom = self.o.machine.deleteSnapshot(oSnapshot);
     2226            else:
     2227                oProgressCom = self.o.console.deleteSnapshot(oSnapshot);
    22222228            oProgress = ProgressWrapper(oProgressCom, self.oVBoxMgr, self.oTstDrv, 'Delete Snapshot %s' % (oSnapshot));
    22232229            oProgress.wait(cMsTimeout);
    22242230            oProgress.logResult();
    22252231        except:
    2226             reporter.logXcpt('IConsole::deleteSnapshot failed on %s' % (self.sName));
     2232            reporter.logXcpt('IMachine::deleteSnapshot failed on %s' % (self.sName));
    22272233            if fFudgeOnFailure:
    22282234                self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge
     
    22372243
    22382244        Returns True on success.
    2239         Returns False on IConsole::takeSnapshot() or VM state change failure.
     2245        Returns False on IMachine::takeSnapshot() or VM state change failure.
    22402246        """
    22412247        try:
     
    22432249               and self.oVM.state is vboxcon.MachineState_Running:
    22442250                self.o.console.pause();
    2245 
    2246             oProgressCom = self.o.console.takeSnapshot(sName, sDescription);
     2251            if self.fpApiVer >= 5.0:
     2252                oProgressCom = self.o.machine.takeSnapshot(sName, sDescription);
     2253            else
     2254                oProgressCom = self.o.console.takeSnapshot(sName, sDescription);
    22472255            oProgress = ProgressWrapper(oProgressCom, self.oVBoxMgr, self.oTstDrv, 'Take Snapshot %s' % (sName));
    22482256            oProgress.wait(cMsTimeout);
    22492257            oProgress.logResult();
    22502258        except:
    2251             reporter.logXcpt('IConsole::takeSnapshot failed on %s' % (self.sName));
     2259            reporter.logXcpt('IMachine::takeSnapshot failed on %s' % (self.sName));
    22522260            if fFudgeOnFailure:
    22532261                self.oTstDrv.waitOnDirectSessionClose(self.oVM, 5000); # fudge
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