VirtualBox

Changeset 17102 in vbox


Ignore:
Timestamp:
Feb 24, 2009 10:42:29 PM (16 years ago)
Author:
vboxsync
Message:

VBoxManage: split snapshot into separate file

Location:
trunk/src/VBox/Frontends/VBoxManage
Files:
3 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VBoxManage/Makefile.kmk

    r16485 r17102  
    5050        VBoxManageList.cpp \
    5151        VBoxManageDisk.cpp \
     52        VBoxManageSnapshot.cpp \
    5253        VBoxInternalManage.cpp \
    5354        $(if $(VBOX_WITH_GUEST_PROPS),VBoxManageGuestProp.cpp) \
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManage.cpp

    r17090 r17102  
    15831583}
    15841584
    1585 static int handleSnapshot(HandlerArg *a)
    1586 {
    1587     HRESULT rc;
    1588 
    1589     /* we need at least a VM and a command */
    1590     if (a->argc < 2)
    1591         return errorSyntax(USAGE_SNAPSHOT, "Not enough parameters");
    1592 
    1593     /* the first argument must be the VM */
    1594     ComPtr<IMachine> machine;
    1595     /* assume it's a UUID */
    1596     rc = a->virtualBox->GetMachine(Guid(a->argv[0]), machine.asOutParam());
    1597     if (FAILED(rc) || !machine)
    1598     {
    1599         /* must be a name */
    1600         CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]), machine.asOutParam()));
    1601     }
    1602     if (!machine)
    1603         return 1;
    1604     Guid guid;
    1605     machine->COMGETTER(Id)(guid.asOutParam());
    1606 
    1607     do
    1608     {
    1609         /* we have to open a session for this task. First try an existing session */
    1610         rc = a->virtualBox->OpenExistingSession(a->session, guid);
    1611         if (FAILED(rc))
    1612             CHECK_ERROR_BREAK(a->virtualBox, OpenSession(a->session, guid));
    1613         ComPtr<IConsole> console;
    1614         CHECK_ERROR_BREAK(a->session, COMGETTER(Console)(console.asOutParam()));
    1615 
    1616         /* switch based on the command */
    1617         if (strcmp(a->argv[1], "take") == 0)
    1618         {
    1619             /* there must be a name */
    1620             if (a->argc < 3)
    1621             {
    1622                 errorSyntax(USAGE_SNAPSHOT, "Missing snapshot name");
    1623                 rc = E_FAIL;
    1624                 break;
    1625             }
    1626             Bstr name(a->argv[2]);
    1627             if ((a->argc > 3) && ((a->argc != 5) || (strcmp(a->argv[3], "-desc") != 0)))
    1628             {
    1629                 errorSyntax(USAGE_SNAPSHOT, "Incorrect description format");
    1630                 rc = E_FAIL;
    1631                 break;
    1632             }
    1633             Bstr desc;
    1634             if (a->argc == 5)
    1635                 desc = a->argv[4];
    1636             ComPtr<IProgress> progress;
    1637             CHECK_ERROR_BREAK(console, TakeSnapshot(name, desc, progress.asOutParam()));
    1638 
    1639             showProgress(progress);
    1640             progress->COMGETTER(ResultCode)(&rc);
    1641             if (FAILED(rc))
    1642             {
    1643                 com::ProgressErrorInfo info(progress);
    1644                 if (info.isBasicAvailable())
    1645                     RTPrintf("Error: failed to take snapshot. Error message: %lS\n", info.getText().raw());
    1646                 else
    1647                     RTPrintf("Error: failed to take snapshot. No error message available!\n");
    1648             }
    1649         }
    1650         else if (strcmp(a->argv[1], "discard") == 0)
    1651         {
    1652             /* exactly one parameter: snapshot name */
    1653             if (a->argc != 3)
    1654             {
    1655                 errorSyntax(USAGE_SNAPSHOT, "Expecting snapshot name only");
    1656                 rc = E_FAIL;
    1657                 break;
    1658             }
    1659 
    1660             ComPtr<ISnapshot> snapshot;
    1661 
    1662             /* assume it's a UUID */
    1663             Guid guid(a->argv[2]);
    1664             if (!guid.isEmpty())
    1665             {
    1666                 CHECK_ERROR_BREAK(machine, GetSnapshot(guid, snapshot.asOutParam()));
    1667             }
    1668             else
    1669             {
    1670                 /* then it must be a name */
    1671                 CHECK_ERROR_BREAK(machine, FindSnapshot(Bstr(a->argv[2]), snapshot.asOutParam()));
    1672             }
    1673 
    1674             snapshot->COMGETTER(Id)(guid.asOutParam());
    1675 
    1676             ComPtr<IProgress> progress;
    1677             CHECK_ERROR_BREAK(console, DiscardSnapshot(guid, progress.asOutParam()));
    1678 
    1679             showProgress(progress);
    1680             progress->COMGETTER(ResultCode)(&rc);
    1681             if (FAILED(rc))
    1682             {
    1683                 com::ProgressErrorInfo info(progress);
    1684                 if (info.isBasicAvailable())
    1685                     RTPrintf("Error: failed to discard snapshot. Error message: %lS\n", info.getText().raw());
    1686                 else
    1687                     RTPrintf("Error: failed to discard snapshot. No error message available!\n");
    1688             }
    1689         }
    1690         else if (strcmp(a->argv[1], "discardcurrent") == 0)
    1691         {
    1692             if (   (a->argc != 3)
    1693                 || (   (strcmp(a->argv[2], "-state") != 0)
    1694                     && (strcmp(a->argv[2], "-all") != 0)))
    1695             {
    1696                 errorSyntax(USAGE_SNAPSHOT, "Invalid parameter '%s'", Utf8Str(a->argv[2]).raw());
    1697                 rc = E_FAIL;
    1698                 break;
    1699             }
    1700             bool fAll = false;
    1701             if (strcmp(a->argv[2], "-all") == 0)
    1702                 fAll = true;
    1703 
    1704             ComPtr<IProgress> progress;
    1705 
    1706             if (fAll)
    1707             {
    1708                 CHECK_ERROR_BREAK(console, DiscardCurrentSnapshotAndState(progress.asOutParam()));
    1709             }
    1710             else
    1711             {
    1712                 CHECK_ERROR_BREAK(console, DiscardCurrentState(progress.asOutParam()));
    1713             }
    1714 
    1715             showProgress(progress);
    1716             progress->COMGETTER(ResultCode)(&rc);
    1717             if (FAILED(rc))
    1718             {
    1719                 com::ProgressErrorInfo info(progress);
    1720                 if (info.isBasicAvailable())
    1721                     RTPrintf("Error: failed to discard. Error message: %lS\n", info.getText().raw());
    1722                 else
    1723                     RTPrintf("Error: failed to discard. No error message available!\n");
    1724             }
    1725 
    1726         }
    1727         else if (strcmp(a->argv[1], "edit") == 0)
    1728         {
    1729             if (a->argc < 3)
    1730             {
    1731                 errorSyntax(USAGE_SNAPSHOT, "Missing snapshot name");
    1732                 rc = E_FAIL;
    1733                 break;
    1734             }
    1735 
    1736             ComPtr<ISnapshot> snapshot;
    1737 
    1738             if (strcmp(a->argv[2], "-current") == 0)
    1739             {
    1740                 CHECK_ERROR_BREAK(machine, COMGETTER(CurrentSnapshot)(snapshot.asOutParam()));
    1741             }
    1742             else
    1743             {
    1744                 /* assume it's a UUID */
    1745                 Guid guid(a->argv[2]);
    1746                 if (!guid.isEmpty())
    1747                 {
    1748                     CHECK_ERROR_BREAK(machine, GetSnapshot(guid, snapshot.asOutParam()));
    1749                 }
    1750                 else
    1751                 {
    1752                     /* then it must be a name */
    1753                     CHECK_ERROR_BREAK(machine, FindSnapshot(Bstr(a->argv[2]), snapshot.asOutParam()));
    1754                 }
    1755             }
    1756 
    1757             /* parse options */
    1758             for (int i = 3; i < a->argc; i++)
    1759             {
    1760                 if (strcmp(a->argv[i], "-newname") == 0)
    1761                 {
    1762                     if (a->argc <= i + 1)
    1763                     {
    1764                         errorArgument("Missing argument to '%s'", a->argv[i]);
    1765                         rc = E_FAIL;
    1766                         break;
    1767                     }
    1768                     i++;
    1769                     snapshot->COMSETTER(Name)(Bstr(a->argv[i]));
    1770                 }
    1771                 else if (strcmp(a->argv[i], "-newdesc") == 0)
    1772                 {
    1773                     if (a->argc <= i + 1)
    1774                     {
    1775                         errorArgument("Missing argument to '%s'", a->argv[i]);
    1776                         rc = E_FAIL;
    1777                         break;
    1778                     }
    1779                     i++;
    1780                     snapshot->COMSETTER(Description)(Bstr(a->argv[i]));
    1781                 }
    1782                 else
    1783                 {
    1784                     errorSyntax(USAGE_SNAPSHOT, "Invalid parameter '%s'", Utf8Str(a->argv[i]).raw());
    1785                     rc = E_FAIL;
    1786                     break;
    1787                 }
    1788             }
    1789 
    1790         }
    1791         else if (strcmp(a->argv[1], "showvminfo") == 0)
    1792         {
    1793             /* exactly one parameter: snapshot name */
    1794             if (a->argc != 3)
    1795             {
    1796                 errorSyntax(USAGE_SNAPSHOT, "Expecting snapshot name only");
    1797                 rc = E_FAIL;
    1798                 break;
    1799             }
    1800 
    1801             ComPtr<ISnapshot> snapshot;
    1802 
    1803             /* assume it's a UUID */
    1804             Guid guid(a->argv[2]);
    1805             if (!guid.isEmpty())
    1806             {
    1807                 CHECK_ERROR_BREAK(machine, GetSnapshot(guid, snapshot.asOutParam()));
    1808             }
    1809             else
    1810             {
    1811                 /* then it must be a name */
    1812                 CHECK_ERROR_BREAK(machine, FindSnapshot(Bstr(a->argv[2]), snapshot.asOutParam()));
    1813             }
    1814 
    1815             /* get the machine of the given snapshot */
    1816             ComPtr<IMachine> machine;
    1817             snapshot->COMGETTER(Machine)(machine.asOutParam());
    1818             showVMInfo(a->virtualBox, machine, VMINFO_NONE, console);
    1819         }
    1820         else
    1821         {
    1822             errorSyntax(USAGE_SNAPSHOT, "Invalid parameter '%s'", Utf8Str(a->argv[1]).raw());
    1823             rc = E_FAIL;
    1824         }
    1825     } while (0);
    1826 
    1827     a->session->Close();
    1828 
    1829     return SUCCEEDED(rc) ? 0 : 1;
    1830 }
    1831 
    18321585static int handleGetExtraData(HandlerArg *a)
    18331586{
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManage.h

    r17079 r17102  
    176176int handleExportAppliance(HandlerArg *a);
    177177
     178// VBoxManageSnapshot.cpp
     179int handleSnapshot(HandlerArg *a);
     180
    178181/* VBoxManageUSB.cpp */
    179182/* VBoxManageTODO.cpp */
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManageSnapshot.cpp

    r17101 r17102  
    11/* $Id$ */
    22/** @file
    3  * VBoxManage - VirtualBox's command-line interface.
     3 * VBoxManage - The 'snapshot' command.
    44 */
    55
     
    2020 */
    2121
     22#ifndef VBOX_ONLY_DOCS
    2223
    2324/*******************************************************************************
    2425*   Header Files                                                               *
    2526*******************************************************************************/
    26 #ifndef VBOX_ONLY_DOCS
    2727#include <VBox/com/com.h>
    2828#include <VBox/com/string.h>
    29 #include <VBox/com/Guid.h>
    30 #include <VBox/com/array.h>
    3129#include <VBox/com/ErrorInfo.h>
    3230#include <VBox/com/errorprint2.h>
    33 #include <VBox/com/EventQueue.h>
    3431
    3532#include <VBox/com/VirtualBox.h>
    3633
    37 #include <vector>
    38 #include <list>
    39 #endif /* !VBOX_ONLY_DOCS */
    40 
    41 #include <iprt/asm.h>
    42 #include <iprt/cidr.h>
    43 #include <iprt/ctype.h>
    44 #include <iprt/dir.h>
    45 #include <iprt/env.h>
    46 #include <VBox/err.h>
    47 #include <iprt/file.h>
    48 #include <iprt/initterm.h>
    49 #include <iprt/param.h>
    50 #include <iprt/path.h>
    5134#include <iprt/stream.h>
    52 #include <iprt/string.h>
    53 #include <iprt/stdarg.h>
    54 #include <iprt/thread.h>
    55 #include <iprt/uuid.h>
    56 #include <VBox/version.h>
    57 #include <VBox/log.h>
     35#include <iprt/getopt.h>
    5836
    5937#include "VBoxManage.h"
    60 
    61 #ifndef VBOX_ONLY_DOCS
    6238using namespace com;
    6339
    64 /* missing XPCOM <-> COM wrappers */
    65 #ifndef STDMETHOD_
    66 # define STDMETHOD_(ret, meth) NS_IMETHOD_(ret) meth
    67 #endif
    68 #ifndef NS_GET_IID
    69 # define NS_GET_IID(I) IID_##I
    70 #endif
    71 #ifndef RT_OS_WINDOWS
    72 #define IUnknown nsISupports
    73 #endif
    74 
    75 /** command handler type */
    76 typedef int (*PFNHANDLER)(HandlerArg *a);
    77 
    78 /**
    79  * Quick IUSBDevice implementation for detaching / attaching
    80  * devices to the USB Controller.
    81  */
    82 class MyUSBDevice : public IUSBDevice
    83 {
    84 public:
    85     // public initializer/uninitializer for internal purposes only
    86     MyUSBDevice(uint16_t a_u16VendorId, uint16_t a_u16ProductId, uint16_t a_bcdRevision, uint64_t a_u64SerialHash, const char *a_pszComment)
    87         :  m_usVendorId(a_u16VendorId), m_usProductId(a_u16ProductId),
    88            m_bcdRevision(a_bcdRevision), m_u64SerialHash(a_u64SerialHash),
    89            m_bstrComment(a_pszComment),
    90            m_cRefs(0)
    91     {
    92     }
    93 
    94     STDMETHOD_(ULONG, AddRef)(void)
    95     {
    96         return ASMAtomicIncU32(&m_cRefs);
    97     }
    98     STDMETHOD_(ULONG, Release)(void)
    99     {
    100         ULONG cRefs = ASMAtomicDecU32(&m_cRefs);
    101         if (!cRefs)
    102             delete this;
    103         return cRefs;
    104     }
    105     STDMETHOD(QueryInterface)(const IID &iid, void **ppvObject)
    106     {
    107         Guid guid(iid);
    108         if (guid == Guid(NS_GET_IID(IUnknown)))
    109             *ppvObject = (IUnknown *)this;
    110         else if (guid == Guid(NS_GET_IID(IUSBDevice)))
    111             *ppvObject = (IUSBDevice *)this;
    112         else
    113             return E_NOINTERFACE;
    114         AddRef();
    115         return S_OK;
    116     }
    117 
    118     STDMETHOD(COMGETTER(Id))(OUT_GUID a_pId)                    { return E_NOTIMPL; }
    119     STDMETHOD(COMGETTER(VendorId))(USHORT *a_pusVendorId)       { *a_pusVendorId    = m_usVendorId;     return S_OK; }
    120     STDMETHOD(COMGETTER(ProductId))(USHORT *a_pusProductId)     { *a_pusProductId   = m_usProductId;    return S_OK; }
    121     STDMETHOD(COMGETTER(Revision))(USHORT *a_pusRevision)       { *a_pusRevision    = m_bcdRevision;    return S_OK; }
    122     STDMETHOD(COMGETTER(SerialHash))(ULONG64 *a_pullSerialHash) { *a_pullSerialHash = m_u64SerialHash;  return S_OK; }
    123     STDMETHOD(COMGETTER(Manufacturer))(BSTR *a_pManufacturer)   { return E_NOTIMPL; }
    124     STDMETHOD(COMGETTER(Product))(BSTR *a_pProduct)             { return E_NOTIMPL; }
    125     STDMETHOD(COMGETTER(SerialNumber))(BSTR *a_pSerialNumber)   { return E_NOTIMPL; }
    126     STDMETHOD(COMGETTER(Address))(BSTR *a_pAddress)             { return E_NOTIMPL; }
    127 
    128 private:
    129     /** The vendor id of this USB device. */
    130     USHORT m_usVendorId;
    131     /** The product id of this USB device. */
    132     USHORT m_usProductId;
    133     /** The product revision number of this USB device.
    134      * (high byte = integer; low byte = decimal) */
    135     USHORT m_bcdRevision;
    136     /** The USB serial hash of the device. */
    137     uint64_t m_u64SerialHash;
    138     /** The user comment string. */
    139     Bstr     m_bstrComment;
    140     /** Reference counter. */
    141     uint32_t volatile m_cRefs;
    142 };
    143 
    144 
    145 // types
    146 ///////////////////////////////////////////////////////////////////////////////
    147 
    148 template <typename T>
    149 class Nullable
    150 {
    151 public:
    152 
    153     Nullable() : mIsNull (true) {}
    154     Nullable (const T &aValue, bool aIsNull = false)
    155         : mIsNull (aIsNull), mValue (aValue) {}
    156 
    157     bool isNull() const { return mIsNull; };
    158     void setNull (bool aIsNull = true) { mIsNull = aIsNull; }
    159 
    160     operator const T&() const { return mValue; }
    161 
    162     Nullable &operator= (const T &aValue)
    163     {
    164         mValue = aValue;
    165         mIsNull = false;
    166         return *this;
    167     }
    168 
    169 private:
    170 
    171     bool mIsNull;
    172     T mValue;
    173 };
    174 
    175 /** helper structure to encapsulate USB filter manipulation commands */
    176 struct USBFilterCmd
    177 {
    178     struct USBFilter
    179     {
    180         USBFilter ()
    181             : mAction (USBDeviceFilterAction_Null)
    182             {}
    183 
    184         Bstr mName;
    185         Nullable <bool> mActive;
    186         Bstr mVendorId;
    187         Bstr mProductId;
    188         Bstr mRevision;
    189         Bstr mManufacturer;
    190         Bstr mProduct;
    191         Bstr mRemote;
    192         Bstr mSerialNumber;
    193         Nullable <ULONG> mMaskedInterfaces;
    194         USBDeviceFilterAction_T mAction;
    195     };
    196 
    197     enum Action { Invalid, Add, Modify, Remove };
    198 
    199     USBFilterCmd() : mAction (Invalid), mIndex (0), mGlobal (false) {}
    200 
    201     Action mAction;
    202     uint32_t mIndex;
    203     /** flag whether the command target is a global filter */
    204     bool mGlobal;
    205     /** machine this command is targeted at (null for global filters) */
    206     ComPtr<IMachine> mMachine;
    207     USBFilter mFilter;
    208 };
    209 #endif /* !VBOX_ONLY_DOCS */
    210 
    211 // funcs
    212 ///////////////////////////////////////////////////////////////////////////////
    213 
    214 static void showLogo(void)
    215 {
    216     static bool fShown; /* show only once */
    217 
    218     if (!fShown)
    219     {
    220         RTPrintf("VirtualBox Command Line Management Interface Version "
    221                  VBOX_VERSION_STRING  "\n"
    222                  "(C) 2005-2009 Sun Microsystems, Inc.\n"
    223                  "All rights reserved.\n"
    224                  "\n");
    225         fShown = true;
    226     }
    227 }
    228 
    229 static void printUsage(USAGECATEGORY u64Cmd)
    230 {
    231 #ifdef RT_OS_LINUX
    232     bool fLinux = true;
    233 #else
    234     bool fLinux = false;
    235 #endif
    236 #ifdef RT_OS_WINDOWS
    237     bool fWin = true;
    238 #else
    239     bool fWin = false;
    240 #endif
    241 #ifdef RT_OS_SOLARIS
    242     bool fSolaris = true;
    243 #else
    244     bool fSolaris = false;
    245 #endif
    246 #ifdef RT_OS_DARWIN
    247     bool fDarwin = true;
    248 #else
    249     bool fDarwin = false;
    250 #endif
    251 #ifdef VBOX_WITH_VRDP
    252     bool fVRDP = true;
    253 #else
    254     bool fVRDP = false;
    255 #endif
    256 
    257     if (u64Cmd == USAGE_DUMPOPTS)
    258     {
    259         fLinux = true;
    260         fWin = true;
    261         fSolaris = true;
    262         fDarwin = true;
    263         fVRDP = true;
    264         u64Cmd = USAGE_ALL;
    265     }
    266 
    267     RTPrintf("Usage:\n"
    268              "\n");
    269 
    270     if (u64Cmd == USAGE_ALL)
    271     {
    272         RTPrintf("VBoxManage [-v|-version]    print version number and exit\n"
    273                  "VBoxManage -nologo ...      suppress the logo\n"
    274                  "\n");
    275     }
    276 
    277     if (u64Cmd & USAGE_LIST)
    278     {
    279         RTPrintf("VBoxManage list [--long|-l] vms|runningvms|ostypes|hostdvds|hostfloppies|\n"
    280                  "                            hostifs|hostinfo|hddbackends|hdds|dvds|floppies|\n"
    281                  "                            usbhost|usbfilters|systemproperties\n"
    282                  "\n");
    283     }
    284 
    285     if (u64Cmd & USAGE_SHOWVMINFO)
    286     {
    287         RTPrintf("VBoxManage showvminfo       <uuid>|<name> [-details] [-statistics]\n"
    288                  "                            [-machinereadable]\n"
    289                  "\n");
    290     }
    291 
    292     if (u64Cmd & USAGE_REGISTERVM)
    293     {
    294         RTPrintf("VBoxManage registervm       <filename>\n"
    295                  "\n");
    296     }
    297 
    298     if (u64Cmd & USAGE_UNREGISTERVM)
    299     {
    300         RTPrintf("VBoxManage unregistervm     <uuid>|<name> [-delete]\n"
    301                  "\n");
    302     }
    303 
    304     if (u64Cmd & USAGE_CREATEVM)
    305     {
    306         RTPrintf("VBoxManage createvm         -name <name>\n"
    307                  "                            [-ostype <ostype>]\n"
    308                  "                            [-register]\n"
    309                  "                            [-basefolder <path> | -settingsfile <path>]\n"
    310                  "                            [-uuid <uuid>]\n"
    311                  "\n");
    312     }
    313 
    314     if (u64Cmd & USAGE_IMPORTAPPLIANCE)
    315     {
    316         RTPrintf("VBoxManage import           <ovf>\n"
    317                  "\n"); // @todo
    318     }
    319 
    320     if (u64Cmd & USAGE_EXPORTAPPLIANCE)
    321     {
    322         RTPrintf("VBoxManage export           <machines> [--output|-o] <ovf>\n"
    323                  "\n");
    324     }
    325 
    326     if (u64Cmd & USAGE_MODIFYVM)
    327     {
    328         RTPrintf("VBoxManage modifyvm         <uuid|name>\n"
    329                  "                            [-name <name>]\n"
    330                  "                            [-ostype <ostype>]\n"
    331                  "                            [-memory <memorysize in MB>]\n"
    332                  "                            [-vram <vramsize in MB>]\n"
    333                  "                            [-acpi on|off]\n"
    334                  "                            [-ioapic on|off]\n"
    335                  "                            [-pae on|off]\n"
    336                  "                            [-hwvirtex on|off|default]\n"
    337                  "                            [-nestedpaging on|off]\n"
    338                  "                            [-vtxvpid on|off]\n"
    339                  "                            [-monitorcount <number>]\n"
    340                  "                            [-accelerate3d <on|off>]\n"
    341                  "                            [-bioslogofadein on|off]\n"
    342                  "                            [-bioslogofadeout on|off]\n"
    343                  "                            [-bioslogodisplaytime <msec>]\n"
    344                  "                            [-bioslogoimagepath <imagepath>]\n"
    345                  "                            [-biosbootmenu disabled|menuonly|messageandmenu]\n"
    346                  "                            [-biossystemtimeoffset <msec>]\n"
    347                  "                            [-biospxedebug on|off]\n"
    348                  "                            [-boot<1-4> none|floppy|dvd|disk|net>]\n"
    349                  "                            [-hd<a|b|d> none|<uuid>|<filename>]\n"
    350                  "                            [-idecontroller PIIX3|PIIX4]\n"
    351 #ifdef VBOX_WITH_AHCI
    352                  "                            [-sata on|off]\n"
    353                  "                            [-sataportcount <1-30>]\n"
    354                  "                            [-sataport<1-30> none|<uuid>|<filename>]\n"
    355                  "                            [-sataideemulation<1-4> <1-30>]\n"
    356 #endif
    357                  "                            [-dvd none|<uuid>|<filename>|host:<drive>]\n"
    358                  "                            [-dvdpassthrough on|off]\n"
    359                  "                            [-floppy disabled|empty|<uuid>|\n"
    360                  "                                     <filename>|host:<drive>]\n"
    361 #if defined(RT_OS_LINUX) || defined(RT_OS_DARWIN)
    362                  "                            [-nic<1-N> none|null|nat|hostif|intnet|hostonly]\n"
    363 #else /* !RT_OS_LINUX && !RT_OS_DARWIN */
    364                  "                            [-nic<1-N> none|null|nat|hostif|intnet]\n"
    365 #endif /* !RT_OS_LINUX && !RT_OS_DARWIN  */
    366                  "                            [-nictype<1-N> Am79C970A|Am79C973"
    367 #ifdef VBOX_WITH_E1000
    368                                                                               "|82540EM|82543GC"
    369 #endif
    370                  "]\n"
    371                  "                            [-cableconnected<1-N> on|off]\n"
    372                  "                            [-nictrace<1-N> on|off]\n"
    373                  "                            [-nictracefile<1-N> <filename>]\n"
    374                  "                            [-nicspeed<1-N> <kbps>]\n"
    375                  "                            [-hostifdev<1-N> none|<devicename>]\n"
    376                  "                            [-intnet<1-N> <network name>]\n"
    377                  "                            [-natnet<1-N> <network>|default]\n"
    378                  "                            [-macaddress<1-N> auto|<mac>]\n"
    379                  "                            [-uart<1-N> off|<I/O base> <IRQ>]\n"
    380                  "                            [-uartmode<1-N> disconnected|\n"
    381                  "                                            server <pipe>|\n"
    382                  "                                            client <pipe>|\n"
    383                  "                                            <devicename>]\n"
    384 #ifdef VBOX_WITH_MEM_BALLOONING
    385                  "                            [-guestmemoryballoon <balloonsize in MB>]\n"
    386 #endif
    387                  "                            [-gueststatisticsinterval <seconds>]\n"
    388                  );
    389         RTPrintf("                            [-audio none|null");
    390         if (fWin)
    391         {
    392 #ifdef VBOX_WITH_WINMM
    393             RTPrintf(                        "|winmm|dsound");
    394 #else
    395             RTPrintf(                        "|dsound");
    396 #endif
    397         }
    398         if (fSolaris)
    399         {
    400             RTPrintf(                        "|solaudio");
    401         }
    402         if (fLinux)
    403         {
    404             RTPrintf(                        "|oss"
    405 #ifdef VBOX_WITH_ALSA
    406                                              "|alsa"
    407 #endif
    408 #ifdef VBOX_WITH_PULSE
    409                                              "|pulse"
    410 #endif
    411                                              );
    412         }
    413         if (fDarwin)
    414         {
    415             RTPrintf(                        "|coreaudio");
    416         }
    417         RTPrintf(                            "]\n");
    418         RTPrintf("                            [-audiocontroller ac97|sb16]\n"
    419                  "                            [-clipboard disabled|hosttoguest|guesttohost|\n"
    420                  "                                        bidirectional]\n");
    421         if (fVRDP)
    422         {
    423             RTPrintf("                            [-vrdp on|off]\n"
    424                      "                            [-vrdpport default|<port>]\n"
    425                      "                            [-vrdpaddress <host>]\n"
    426                      "                            [-vrdpauthtype null|external|guest]\n"
    427                      "                            [-vrdpmulticon on|off]\n"
    428                      "                            [-vrdpreusecon on|off]\n");
    429         }
    430         RTPrintf("                            [-usb on|off]\n"
    431                  "                            [-usbehci on|off]\n"
    432                  "                            [-snapshotfolder default|<path>]\n");
    433         RTPrintf("\n");
    434     }
    435 
    436     if (u64Cmd & USAGE_STARTVM)
    437     {
    438         RTPrintf("VBoxManage startvm          <uuid>|<name>\n");
    439         if (fVRDP)
    440             RTPrintf("                            [-type gui|vrdp]\n");
    441         RTPrintf("\n");
    442     }
    443 
    444     if (u64Cmd & USAGE_CONTROLVM)
    445     {
    446         RTPrintf("VBoxManage controlvm        <uuid>|<name>\n"
    447                  "                            pause|resume|reset|poweroff|savestate|\n"
    448                  "                            acpipowerbutton|acpisleepbutton|\n"
    449                  "                            keyboardputscancode <hex> [<hex> ...]|\n"
    450                  "                            injectnmi|\n"
    451                  "                            setlinkstate<1-4> on|off |\n"
    452                  "                            usbattach <uuid>|<address> |\n"
    453                  "                            usbdetach <uuid>|<address> |\n"
    454                  "                            dvdattach none|<uuid>|<filename>|host:<drive> |\n"
    455                  "                            floppyattach none|<uuid>|<filename>|host:<drive> |\n");
    456         if (fVRDP)
    457         {
    458             RTPrintf("                            vrdp on|off] |\n");
    459         }
    460         RTPrintf("                            setvideomodehint <xres> <yres> <bpp> [display]|\n"
    461                  "                            setcredentials <username> <password> <domain>\n"
    462                  "                                           [-allowlocallogon <yes|no>]\n"
    463                  "\n");
    464     }
    465 
    466     if (u64Cmd & USAGE_DISCARDSTATE)
    467     {
    468         RTPrintf("VBoxManage discardstate     <uuid>|<name>\n"
    469                  "\n");
    470     }
    471 
    472     if (u64Cmd & USAGE_ADOPTSTATE)
    473     {
    474         RTPrintf("VBoxManage adoptstate       <uuid>|<name> <state_file>\n"
    475                  "\n");
    476     }
    477 
    478     if (u64Cmd & USAGE_SNAPSHOT)
    479     {
    480         RTPrintf("VBoxManage snapshot         <uuid>|<name>\n"
    481                  "                            take <name> [-desc <desc>] |\n"
    482                  "                            discard <uuid>|<name> |\n"
    483                  "                            discardcurrent -state|-all |\n"
    484                  "                            edit <uuid>|<name>|-current\n"
    485                  "                                 [-newname <name>]\n"
    486                  "                                 [-newdesc <desc>] |\n"
    487                  "                            showvminfo <uuid>|<name>\n"
    488                  "\n");
    489     }
    490 
    491     if (u64Cmd & USAGE_REGISTERIMAGE)
    492     {
    493         RTPrintf("VBoxManage openmedium       disk|dvd|floppy <filename>\n"
    494                  "                            [-type normal|immutable|writethrough] (disk only)\n"
    495                  "\n");
    496     }
    497 
    498     if (u64Cmd & USAGE_UNREGISTERIMAGE)
    499     {
    500         RTPrintf("VBoxManage closemedium      disk|dvd|floppy <uuid>|<filename>\n"
    501                  "\n");
    502     }
    503 
    504     if (u64Cmd & USAGE_SHOWHDINFO)
    505     {
    506         RTPrintf("VBoxManage showhdinfo       <uuid>|<filename>\n"
    507                  "\n");
    508     }
    509 
    510     if (u64Cmd & USAGE_CREATEHD)
    511     {
    512         /// @todo NEWMEDIA add -format to specify the hard disk backend
    513         RTPrintf("VBoxManage createhd         -filename <filename>\n"
    514                  "                            -size <megabytes>\n"
    515                  "                            [-format VDI|VMDK|VHD]\n"
    516                  "                            [-static]\n"
    517                  "                            [-comment <comment>]\n"
    518                  "                            [-register]\n"
    519                  "                            [-type normal|writethrough] (default: normal)\n"
    520                  "\n");
    521     }
    522 
    523     if (u64Cmd & USAGE_MODIFYHD)
    524     {
    525         RTPrintf("VBoxManage modifyhd         <uuid>|<filename>\n"
    526                  "                            settype normal|writethrough|immutable |\n"
    527                  "                            compact\n"
    528                  "\n");
    529     }
    530 
    531     if (u64Cmd & USAGE_CLONEHD)
    532     {
    533         RTPrintf("VBoxManage clonehd          <uuid>|<filename> <outputfile>\n"
    534                  "                            [-format VDI|VMDK|VHD|RAW|<other>]\n"
    535                  "                            [-remember]\n"
    536                  "\n");
    537     }
    538 
    539     if (u64Cmd & USAGE_CONVERTFROMRAW)
    540     {
    541         RTPrintf("VBoxManage convertfromraw   [-static] [-format VDI|VMDK|VHD]\n"
    542                  "                            <filename> <outputfile>\n"
    543                  "VBoxManage convertfromraw   [-static] [-format VDI|VMDK|VHD]\n"
    544                  "                            stdin <outputfile> <bytes>\n"
    545                  "\n");
    546     }
    547 
    548     if (u64Cmd & USAGE_ADDISCSIDISK)
    549     {
    550         RTPrintf("VBoxManage addiscsidisk     -server <name>|<ip>\n"
    551                  "                            -target <target>\n"
    552                  "                            [-port <port>]\n"
    553                  "                            [-lun <lun>]\n"
    554                  "                            [-encodedlun <lun>]\n"
    555                  "                            [-username <username>]\n"
    556                  "                            [-password <password>]\n"
    557                  "                            [-comment <comment>]\n"
    558                  "                            [-intnet]\n"
    559                  "\n");
    560     }
    561 
    562     if (u64Cmd & USAGE_GETEXTRADATA)
    563     {
    564         RTPrintf("VBoxManage getextradata     global|<uuid>|<name>\n"
    565                  "                            <key>|enumerate\n"
    566                  "\n");
    567     }
    568 
    569     if (u64Cmd & USAGE_SETEXTRADATA)
    570     {
    571         RTPrintf("VBoxManage setextradata     global|<uuid>|<name>\n"
    572                  "                            <key>\n"
    573                  "                            [<value>] (no value deletes key)\n"
    574                  "\n");
    575     }
    576 
    577     if (u64Cmd & USAGE_SETPROPERTY)
    578     {
    579         RTPrintf("VBoxManage setproperty      hdfolder default|<folder> |\n"
    580                  "                            machinefolder default|<folder> |\n"
    581                  "                            vrdpauthlibrary default|<library> |\n"
    582                  "                            websrvauthlibrary default|null|<library> |\n"
    583                  "                            hwvirtexenabled yes|no\n"
    584                  "                            loghistorycount <value>\n"
    585                  "\n");
    586     }
    587 
    588     if (u64Cmd & USAGE_USBFILTER_ADD)
    589     {
    590         RTPrintf("VBoxManage usbfilter        add <index,0-N>\n"
    591                  "                            -target <uuid>|<name>|global\n"
    592                  "                            -name <string>\n"
    593                  "                            -action ignore|hold (global filters only)\n"
    594                  "                            [-active yes|no] (yes)\n"
    595                  "                            [-vendorid <XXXX>] (null)\n"
    596                  "                            [-productid <XXXX>] (null)\n"
    597                  "                            [-revision <IIFF>] (null)\n"
    598                  "                            [-manufacturer <string>] (null)\n"
    599                  "                            [-product <string>] (null)\n"
    600                  "                            [-remote yes|no] (null, VM filters only)\n"
    601                  "                            [-serialnumber <string>] (null)\n"
    602                  "                            [-maskedinterfaces <XXXXXXXX>]\n"
    603                  "\n");
    604     }
    605 
    606     if (u64Cmd & USAGE_USBFILTER_MODIFY)
    607     {
    608         RTPrintf("VBoxManage usbfilter        modify <index,0-N>\n"
    609                  "                            -target <uuid>|<name>|global\n"
    610                  "                            [-name <string>]\n"
    611                  "                            [-action ignore|hold] (global filters only)\n"
    612                  "                            [-active yes|no]\n"
    613                  "                            [-vendorid <XXXX>|\"\"]\n"
    614                  "                            [-productid <XXXX>|\"\"]\n"
    615                  "                            [-revision <IIFF>|\"\"]\n"
    616                  "                            [-manufacturer <string>|\"\"]\n"
    617                  "                            [-product <string>|\"\"]\n"
    618                  "                            [-remote yes|no] (null, VM filters only)\n"
    619                  "                            [-serialnumber <string>|\"\"]\n"
    620                  "                            [-maskedinterfaces <XXXXXXXX>]\n"
    621                  "\n");
    622     }
    623 
    624     if (u64Cmd & USAGE_USBFILTER_REMOVE)
    625     {
    626         RTPrintf("VBoxManage usbfilter        remove <index,0-N>\n"
    627                  "                            -target <uuid>|<name>|global\n"
    628                  "\n");
    629     }
    630 
    631     if (u64Cmd & USAGE_SHAREDFOLDER_ADD)
    632     {
    633         RTPrintf("VBoxManage sharedfolder     add <vmname>|<uuid>\n"
    634                  "                            -name <name> -hostpath <hostpath>\n"
    635                  "                            [-transient] [-readonly]\n"
    636                  "\n");
    637     }
    638 
    639     if (u64Cmd & USAGE_SHAREDFOLDER_REMOVE)
    640     {
    641         RTPrintf("VBoxManage sharedfolder     remove <vmname>|<uuid>\n"
    642                  "                            -name <name> [-transient]\n"
    643                  "\n");
    644     }
    645 
    646     if (u64Cmd & USAGE_VM_STATISTICS)
    647     {
    648         RTPrintf("VBoxManage vmstatistics     <vmname>|<uuid> [-reset]\n"
    649                  "                            [-pattern <pattern>] [-descriptions]\n"
    650                  "\n");
    651     }
    652 
    653 #ifdef VBOX_WITH_GUEST_PROPS
    654     if (u64Cmd & USAGE_GUESTPROPERTY)
    655         usageGuestProperty();
    656 #endif /* VBOX_WITH_GUEST_PROPS defined */
    657 
    658     if (u64Cmd & USAGE_METRICS)
    659     {
    660         RTPrintf("VBoxManage metrics          list [*|host|<vmname> [<metric_list>]] (comma-separated)\n\n"
    661                  "VBoxManage metrics          setup\n"
    662                  "                            [-period <seconds>]\n"
    663                  "                            [-samples <count>]\n"
    664                  "                            [-list]\n"
    665                  "                            [*|host|<vmname> [<metric_list>]]\n\n"
    666                  "VBoxManage metrics          query [*|host|<vmname> [<metric_list>]]\n\n"
    667                  "VBoxManage metrics          collect\n"
    668                  "                            [-period <seconds>]\n"
    669                  "                            [-samples <count>]\n"
    670                  "                            [-list]\n"
    671                  "                            [-detach]\n"
    672                  "                            [*|host|<vmname> [<metric_list>]]\n"
    673                  "\n");
    674     }
    675 
    676 }
    677 
    678 /**
    679  * Print a usage synopsis and the syntax error message.
    680  */
    681 int errorSyntax(USAGECATEGORY u64Cmd, const char *pszFormat, ...)
    682 {
    683     va_list args;
    684     showLogo(); // show logo even if suppressed
    685 #ifndef VBOX_ONLY_DOCS
    686     if (g_fInternalMode)
    687         printUsageInternal(u64Cmd);
    688     else
    689         printUsage(u64Cmd);
    690 #endif /* !VBOX_ONLY_DOCS */
    691     va_start(args, pszFormat);
    692     RTPrintf("\n"
    693              "Syntax error: %N\n", pszFormat, &args);
    694     va_end(args);
    695     return 1;
    696 }
    697 
    698 /**
    699  * Print an error message without the syntax stuff.
    700  */
    701 int errorArgument(const char *pszFormat, ...)
    702 {
    703     va_list args;
    704     va_start(args, pszFormat);
    705     RTPrintf("error: %N\n", pszFormat, &args);
    706     va_end(args);
    707     return 1;
    708 }
    709 
    710 #ifndef VBOX_ONLY_DOCS
    711 /**
    712  * Print out progress on the console
    713  */
    714 void showProgress(ComPtr<IProgress> progress)
    715 {
    716     BOOL fCompleted;
    717     LONG currentPercent;
    718     LONG lastPercent = 0;
    719 
    720     RTPrintf("0%%...");
    721     RTStrmFlush(g_pStdOut);
    722     while (SUCCEEDED(progress->COMGETTER(Completed(&fCompleted))))
    723     {
    724         progress->COMGETTER(Percent(&currentPercent));
    725 
    726         /* did we cross a 10% mark? */
    727         if (((currentPercent / 10) > (lastPercent / 10)))
    728         {
    729             /* make sure to also print out missed steps */
    730             for (LONG curVal = (lastPercent / 10) * 10 + 10; curVal <= (currentPercent / 10) * 10; curVal += 10)
    731             {
    732                 if (curVal < 100)
    733                 {
    734                     RTPrintf("%ld%%...", curVal);
    735                     RTStrmFlush(g_pStdOut);
    736                 }
    737             }
    738             lastPercent = (currentPercent / 10) * 10;
    739         }
    740         if (fCompleted)
    741             break;
    742 
    743         /* make sure the loop is not too tight */
    744         progress->WaitForCompletion(100);
    745     }
    746 
    747     /* complete the line. */
    748     HRESULT rc;
    749     if (SUCCEEDED(progress->COMGETTER(ResultCode)(&rc)))
    750     {
    751         if (SUCCEEDED(rc))
    752             RTPrintf("100%%\n");
    753         else
    754             RTPrintf("FAILED\n");
    755     }
    756     else
    757         RTPrintf("\n");
    758     RTStrmFlush(g_pStdOut);
    759 }
    760 
    761 static int handleRegisterVM(HandlerArg *a)
    762 {
    763     HRESULT rc;
    764 
    765     if (a->argc != 1)
    766         return errorSyntax(USAGE_REGISTERVM, "Incorrect number of parameters");
    767 
    768     ComPtr<IMachine> machine;
    769     CHECK_ERROR(a->virtualBox, OpenMachine(Bstr(a->argv[0]), machine.asOutParam()));
    770     if (SUCCEEDED(rc))
    771     {
    772         ASSERT(machine);
    773         CHECK_ERROR(a->virtualBox, RegisterMachine(machine));
    774     }
    775     return SUCCEEDED(rc) ? 0 : 1;
    776 }
    777 
    778 static int handleUnregisterVM(HandlerArg *a)
    779 {
    780     HRESULT rc;
    781 
    782     if ((a->argc != 1) && (a->argc != 2))
    783         return errorSyntax(USAGE_UNREGISTERVM, "Incorrect number of parameters");
    784 
    785     ComPtr<IMachine> machine;
    786     /* assume it's a UUID */
    787     rc = a->virtualBox->GetMachine(Guid(a->argv[0]), machine.asOutParam());
    788     if (FAILED(rc) || !machine)
    789     {
    790         /* must be a name */
    791         CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]), machine.asOutParam()));
    792     }
    793     if (machine)
    794     {
    795         Guid uuid;
    796         machine->COMGETTER(Id)(uuid.asOutParam());
    797         machine = NULL;
    798         CHECK_ERROR(a->virtualBox, UnregisterMachine(uuid, machine.asOutParam()));
    799         if (SUCCEEDED(rc) && machine)
    800         {
    801             /* are we supposed to delete the config file? */
    802             if ((a->argc == 2) && (strcmp(a->argv[1], "-delete") == 0))
    803             {
    804                 CHECK_ERROR(machine, DeleteSettings());
    805             }
    806         }
    807     }
    808     return SUCCEEDED(rc) ? 0 : 1;
    809 }
    810 
    811 static int handleCreateVM(HandlerArg *a)
    812 {
    813     HRESULT rc;
    814     Bstr baseFolder;
    815     Bstr settingsFile;
    816     Bstr name;
    817     Bstr osTypeId;
    818     RTUUID id;
    819     bool fRegister = false;
    820 
    821     RTUuidClear(&id);
    822     for (int i = 0; i < a->argc; i++)
    823     {
    824         if (strcmp(a->argv[i], "-basefolder") == 0)
    825         {
    826             if (a->argc <= i + 1)
    827                 return errorArgument("Missing argument to '%s'", a->argv[i]);
    828             i++;
    829             baseFolder = a->argv[i];
    830         }
    831         else if (strcmp(a->argv[i], "-settingsfile") == 0)
    832         {
    833             if (a->argc <= i + 1)
    834                 return errorArgument("Missing argument to '%s'", a->argv[i]);
    835             i++;
    836             settingsFile = a->argv[i];
    837         }
    838         else if (strcmp(a->argv[i], "-name") == 0)
    839         {
    840             if (a->argc <= i + 1)
    841                 return errorArgument("Missing argument to '%s'", a->argv[i]);
    842             i++;
    843             name = a->argv[i];
    844         }
    845         else if (strcmp(a->argv[i], "-ostype") == 0)
    846         {
    847             if (a->argc <= i + 1)
    848                 return errorArgument("Missing argument to '%s'", a->argv[i]);
    849             i++;
    850             osTypeId = a->argv[i];
    851         }
    852         else if (strcmp(a->argv[i], "-uuid") == 0)
    853         {
    854             if (a->argc <= i + 1)
    855                 return errorArgument("Missing argument to '%s'", a->argv[i]);
    856             i++;
    857             if (RT_FAILURE(RTUuidFromStr(&id, a->argv[i])))
    858                 return errorArgument("Invalid UUID format %s\n", a->argv[i]);
    859         }
    860         else if (strcmp(a->argv[i], "-register") == 0)
    861         {
    862             fRegister = true;
    863         }
    864         else
    865             return errorSyntax(USAGE_CREATEVM, "Invalid parameter '%s'", Utf8Str(a->argv[i]).raw());
    866     }
    867     if (!name)
    868         return errorSyntax(USAGE_CREATEVM, "Parameter -name is required");
    869 
    870     if (!!baseFolder && !!settingsFile)
    871         return errorSyntax(USAGE_CREATEVM, "Either -basefolder or -settingsfile must be specified");
    872 
    873     do
    874     {
    875         ComPtr<IMachine> machine;
    876 
    877         if (!settingsFile)
    878             CHECK_ERROR_BREAK(a->virtualBox,
    879                 CreateMachine(name, osTypeId, baseFolder, Guid(id), machine.asOutParam()));
    880         else
    881             CHECK_ERROR_BREAK(a->virtualBox,
    882                 CreateLegacyMachine(name, osTypeId, settingsFile, Guid(id), machine.asOutParam()));
    883 
    884         CHECK_ERROR_BREAK(machine, SaveSettings());
    885         if (fRegister)
    886         {
    887             CHECK_ERROR_BREAK(a->virtualBox, RegisterMachine(machine));
    888         }
    889         Guid uuid;
    890         CHECK_ERROR_BREAK(machine, COMGETTER(Id)(uuid.asOutParam()));
    891         CHECK_ERROR_BREAK(machine, COMGETTER(SettingsFilePath)(settingsFile.asOutParam()));
    892         RTPrintf("Virtual machine '%ls' is created%s.\n"
    893                  "UUID: %s\n"
    894                  "Settings file: '%ls'\n",
    895                  name.raw(), fRegister ? " and registered" : "",
    896                  uuid.toString().raw(), settingsFile.raw());
    897     }
    898     while (0);
    899 
    900     return SUCCEEDED(rc) ? 0 : 1;
    901 }
    902 
    903 /**
    904  * Parses a number.
    905  *
    906  * @returns Valid number on success.
    907  * @returns 0 if invalid number. All necesary bitching has been done.
    908  * @param   psz     Pointer to the nic number.
    909  */
    910 unsigned parseNum(const char *psz, unsigned cMaxNum, const char *name)
    911 {
    912     uint32_t u32;
    913     char *pszNext;
    914     int rc = RTStrToUInt32Ex(psz, &pszNext, 10, &u32);
    915     if (    RT_SUCCESS(rc)
    916         &&  *pszNext == '\0'
    917         &&  u32 >= 1
    918         &&  u32 <= cMaxNum)
    919         return (unsigned)u32;
    920     errorArgument("Invalid %s number '%s'", name, psz);
    921     return 0;
    922 }
    923 
    924 
    925 /** @todo refine this after HDD changes; MSC 8.0/64 has trouble with handleModifyVM.  */
    926 #if defined(_MSC_VER)
    927 # pragma optimize("", on)
    928 #endif
    929 
    930 static int handleStartVM(HandlerArg *a)
    931 {
    932     HRESULT rc;
    933 
    934     if (a->argc < 1)
    935         return errorSyntax(USAGE_STARTVM, "Not enough parameters");
    936 
    937     ComPtr<IMachine> machine;
    938     /* assume it's a UUID */
    939     rc = a->virtualBox->GetMachine(Guid(a->argv[0]), machine.asOutParam());
    940     if (FAILED(rc) || !machine)
    941     {
    942         /* must be a name */
    943         CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]), machine.asOutParam()));
    944     }
    945     if (machine)
    946     {
    947         Guid uuid;
    948         machine->COMGETTER(Id)(uuid.asOutParam());
    949 
    950         /* default to GUI session type */
    951         Bstr sessionType = "gui";
    952         /* has a session type been specified? */
    953         if ((a->argc > 2) && (strcmp(a->argv[1], "-type") == 0))
    954         {
    955             if (strcmp(a->argv[2], "gui") == 0)
    956             {
    957                 sessionType = "gui";
    958             }
    959             else if (strcmp(a->argv[2], "vrdp") == 0)
    960             {
    961                 sessionType = "vrdp";
    962             }
    963             else if (strcmp(a->argv[2], "capture") == 0)
    964             {
    965                 sessionType = "capture";
    966             }
    967             else
    968                 return errorArgument("Invalid session type argument '%s'", a->argv[2]);
    969         }
    970 
    971         Bstr env;
    972 #ifdef RT_OS_LINUX
    973         /* make sure the VM process will start on the same display as VBoxManage */
    974         {
    975             const char *display = RTEnvGet ("DISPLAY");
    976             if (display)
    977                 env = Utf8StrFmt ("DISPLAY=%s", display);
    978         }
    979 #endif
    980         ComPtr<IProgress> progress;
    981         CHECK_ERROR_RET(a->virtualBox, OpenRemoteSession(a->session, uuid, sessionType,
    982                                                          env, progress.asOutParam()), rc);
    983         RTPrintf("Waiting for the remote session to open...\n");
    984         CHECK_ERROR_RET(progress, WaitForCompletion (-1), 1);
    985 
    986         BOOL completed;
    987         CHECK_ERROR_RET(progress, COMGETTER(Completed)(&completed), rc);
    988         ASSERT(completed);
    989 
    990         HRESULT resultCode;
    991         CHECK_ERROR_RET(progress, COMGETTER(ResultCode)(&resultCode), rc);
    992         if (FAILED(resultCode))
    993         {
    994             ComPtr <IVirtualBoxErrorInfo> errorInfo;
    995             CHECK_ERROR_RET(progress, COMGETTER(ErrorInfo)(errorInfo.asOutParam()), 1);
    996             ErrorInfo info (errorInfo);
    997             GluePrintErrorInfo(info);
    998         }
    999         else
    1000         {
    1001             RTPrintf("Remote session has been successfully opened.\n");
    1002         }
    1003     }
    1004 
    1005     /* it's important to always close sessions */
    1006     a->session->Close();
    1007 
    1008     return SUCCEEDED(rc) ? 0 : 1;
    1009 }
    1010 
    1011 static int handleControlVM(HandlerArg *a)
    1012 {
    1013     HRESULT rc;
    1014 
    1015     if (a->argc < 2)
    1016         return errorSyntax(USAGE_CONTROLVM, "Not enough parameters");
    1017 
    1018     /* try to find the given machine */
    1019     ComPtr <IMachine> machine;
    1020     Guid uuid (a->argv[0]);
    1021     if (!uuid.isEmpty())
    1022     {
    1023         CHECK_ERROR (a->virtualBox, GetMachine (uuid, machine.asOutParam()));
    1024     }
    1025     else
    1026     {
    1027         CHECK_ERROR (a->virtualBox, FindMachine (Bstr(a->argv[0]), machine.asOutParam()));
    1028         if (SUCCEEDED (rc))
    1029             machine->COMGETTER(Id) (uuid.asOutParam());
    1030     }
    1031     if (FAILED (rc))
    1032         return 1;
    1033 
    1034     /* open a session for the VM */
    1035     CHECK_ERROR_RET (a->virtualBox, OpenExistingSession (a->session, uuid), 1);
    1036 
    1037     do
    1038     {
    1039         /* get the associated console */
    1040         ComPtr<IConsole> console;
    1041         CHECK_ERROR_BREAK (a->session, COMGETTER(Console)(console.asOutParam()));
    1042         /* ... and session machine */
    1043         ComPtr<IMachine> sessionMachine;
    1044         CHECK_ERROR_BREAK (a->session, COMGETTER(Machine)(sessionMachine.asOutParam()));
    1045 
    1046         /* which command? */
    1047         if (strcmp(a->argv[1], "pause") == 0)
    1048         {
    1049             CHECK_ERROR_BREAK (console, Pause());
    1050         }
    1051         else if (strcmp(a->argv[1], "resume") == 0)
    1052         {
    1053             CHECK_ERROR_BREAK (console, Resume());
    1054         }
    1055         else if (strcmp(a->argv[1], "reset") == 0)
    1056         {
    1057             CHECK_ERROR_BREAK (console, Reset());
    1058         }
    1059         else if (strcmp(a->argv[1], "poweroff") == 0)
    1060         {
    1061             CHECK_ERROR_BREAK (console, PowerDown());
    1062         }
    1063         else if (strcmp(a->argv[1], "savestate") == 0)
    1064         {
    1065             ComPtr<IProgress> progress;
    1066             CHECK_ERROR_BREAK (console, SaveState(progress.asOutParam()));
    1067 
    1068             showProgress(progress);
    1069 
    1070             progress->COMGETTER(ResultCode)(&rc);
    1071             if (FAILED(rc))
    1072             {
    1073                 com::ProgressErrorInfo info(progress);
    1074                 if (info.isBasicAvailable())
    1075                 {
    1076                     RTPrintf("Error: failed to save machine state. Error message: %lS\n", info.getText().raw());
    1077                 }
    1078                 else
    1079                 {
    1080                     RTPrintf("Error: failed to save machine state. No error message available!\n");
    1081                 }
    1082             }
    1083         }
    1084         else if (strcmp(a->argv[1], "acpipowerbutton") == 0)
    1085         {
    1086             CHECK_ERROR_BREAK (console, PowerButton());
    1087         }
    1088         else if (strcmp(a->argv[1], "acpisleepbutton") == 0)
    1089         {
    1090             CHECK_ERROR_BREAK (console, SleepButton());
    1091         }
    1092         else if (strcmp(a->argv[1], "injectnmi") == 0)
    1093         {
    1094             /* get the machine debugger. */
    1095             ComPtr <IMachineDebugger> debugger;
    1096             CHECK_ERROR_BREAK(console, COMGETTER(Debugger)(debugger.asOutParam()));
    1097             CHECK_ERROR_BREAK(debugger, InjectNMI());
    1098         }
    1099         else if (strcmp(a->argv[1], "keyboardputscancode") == 0)
    1100         {
    1101             ComPtr<IKeyboard> keyboard;
    1102             CHECK_ERROR_BREAK(console, COMGETTER(Keyboard)(keyboard.asOutParam()));
    1103 
    1104             if (a->argc <= 1 + 1)
    1105             {
    1106                 errorArgument("Missing argument to '%s'. Expected IBM PC AT set 2 keyboard scancode(s) as hex byte(s).", a->argv[1]);
    1107                 rc = E_FAIL;
    1108                 break;
    1109             }
    1110 
    1111             /* Arbitrary restrict the length of a sequence of scancodes to 1024. */
    1112             LONG alScancodes[1024];
    1113             int cScancodes = 0;
    1114 
    1115             /* Process the command line. */
    1116             int i;
    1117             for (i = 1 + 1; i < a->argc && cScancodes < (int)RT_ELEMENTS(alScancodes); i++, cScancodes++)
    1118             {
    1119                 if (   RT_C_IS_XDIGIT (a->argv[i][0])
    1120                     && RT_C_IS_XDIGIT (a->argv[i][1])
    1121                     && a->argv[i][2] == 0)
    1122                 {
    1123                     uint8_t u8Scancode;
    1124                     int rc = RTStrToUInt8Ex(a->argv[i], NULL, 16, &u8Scancode);
    1125                     if (RT_FAILURE (rc))
    1126                     {
    1127                         RTPrintf("Error: converting '%s' returned %Rrc!\n", a->argv[i], rc);
    1128                         rc = E_FAIL;
    1129                         break;
    1130                     }
    1131 
    1132                     alScancodes[cScancodes] = u8Scancode;
    1133                 }
    1134                 else
    1135                 {
    1136                     RTPrintf("Error: '%s' is not a hex byte!\n", a->argv[i]);
    1137                     rc = E_FAIL;
    1138                     break;
    1139                 }
    1140             }
    1141 
    1142             if (FAILED(rc))
    1143                 break;
    1144 
    1145             if (   cScancodes == RT_ELEMENTS(alScancodes)
    1146                 && i < a->argc)
    1147             {
    1148                 RTPrintf("Error: too many scancodes, maximum %d allowed!\n", RT_ELEMENTS(alScancodes));
    1149                 rc = E_FAIL;
    1150                 break;
    1151             }
    1152 
    1153             /* Send scancodes to the VM.
    1154              * Note: 'PutScancodes' did not work here. Only the first scancode was transmitted.
    1155              */
    1156             for (i = 0; i < cScancodes; i++)
    1157             {
    1158                 CHECK_ERROR_BREAK(keyboard, PutScancode(alScancodes[i]));
    1159                 RTPrintf("Scancode[%d]: 0x%02X\n", i, alScancodes[i]);
    1160             }
    1161         }
    1162         else if (strncmp(a->argv[1], "setlinkstate", 12) == 0)
    1163         {
    1164             /* Get the number of network adapters */
    1165             ULONG NetworkAdapterCount = 0;
    1166             ComPtr <ISystemProperties> info;
    1167             CHECK_ERROR_BREAK (a->virtualBox, COMGETTER(SystemProperties) (info.asOutParam()));
    1168             CHECK_ERROR_BREAK (info, COMGETTER(NetworkAdapterCount) (&NetworkAdapterCount));
    1169 
    1170             unsigned n = parseNum(&a->argv[1][12], NetworkAdapterCount, "NIC");
    1171             if (!n)
    1172             {
    1173                 rc = E_FAIL;
    1174                 break;
    1175             }
    1176             if (a->argc <= 1 + 1)
    1177             {
    1178                 errorArgument("Missing argument to '%s'", a->argv[1]);
    1179                 rc = E_FAIL;
    1180                 break;
    1181             }
    1182             /* get the corresponding network adapter */
    1183             ComPtr<INetworkAdapter> adapter;
    1184             CHECK_ERROR_BREAK (sessionMachine, GetNetworkAdapter(n - 1, adapter.asOutParam()));
    1185             if (adapter)
    1186             {
    1187                 if (strcmp(a->argv[2], "on") == 0)
    1188                 {
    1189                     CHECK_ERROR_BREAK (adapter, COMSETTER(CableConnected)(TRUE));
    1190                 }
    1191                 else if (strcmp(a->argv[2], "off") == 0)
    1192                 {
    1193                     CHECK_ERROR_BREAK (adapter, COMSETTER(CableConnected)(FALSE));
    1194                 }
    1195                 else
    1196                 {
    1197                     errorArgument("Invalid link state '%s'", Utf8Str(a->argv[2]).raw());
    1198                     rc = E_FAIL;
    1199                     break;
    1200                 }
    1201             }
    1202         }
    1203 #ifdef VBOX_WITH_VRDP
    1204         else if (strcmp(a->argv[1], "vrdp") == 0)
    1205         {
    1206             if (a->argc <= 1 + 1)
    1207             {
    1208                 errorArgument("Missing argument to '%s'", a->argv[1]);
    1209                 rc = E_FAIL;
    1210                 break;
    1211             }
    1212             /* get the corresponding VRDP server */
    1213             ComPtr<IVRDPServer> vrdpServer;
    1214             sessionMachine->COMGETTER(VRDPServer)(vrdpServer.asOutParam());
    1215             ASSERT(vrdpServer);
    1216             if (vrdpServer)
    1217             {
    1218                 if (strcmp(a->argv[2], "on") == 0)
    1219                 {
    1220                     CHECK_ERROR_BREAK (vrdpServer, COMSETTER(Enabled)(TRUE));
    1221                 }
    1222                 else if (strcmp(a->argv[2], "off") == 0)
    1223                 {
    1224                     CHECK_ERROR_BREAK (vrdpServer, COMSETTER(Enabled)(FALSE));
    1225                 }
    1226                 else
    1227                 {
    1228                     errorArgument("Invalid vrdp server state '%s'", Utf8Str(a->argv[2]).raw());
    1229                     rc = E_FAIL;
    1230                     break;
    1231                 }
    1232             }
    1233         }
    1234 #endif /* VBOX_WITH_VRDP */
    1235         else if (strcmp (a->argv[1], "usbattach") == 0 ||
    1236                  strcmp (a->argv[1], "usbdetach") == 0)
    1237         {
    1238             if (a->argc < 3)
    1239             {
    1240                 errorSyntax(USAGE_CONTROLVM, "Not enough parameters");
    1241                 rc = E_FAIL;
    1242                 break;
    1243             }
    1244 
    1245             bool attach = strcmp (a->argv[1], "usbattach") == 0;
    1246 
    1247             Guid usbId = a->argv [2];
    1248             if (usbId.isEmpty())
    1249             {
    1250                 // assume address
    1251                 if (attach)
    1252                 {
    1253                     ComPtr <IHost> host;
    1254                     CHECK_ERROR_BREAK (a->virtualBox, COMGETTER(Host) (host.asOutParam()));
    1255                     ComPtr <IHostUSBDeviceCollection> coll;
    1256                     CHECK_ERROR_BREAK (host, COMGETTER(USBDevices) (coll.asOutParam()));
    1257                     ComPtr <IHostUSBDevice> dev;
    1258                     CHECK_ERROR_BREAK (coll, FindByAddress (Bstr (a->argv [2]), dev.asOutParam()));
    1259                     CHECK_ERROR_BREAK (dev, COMGETTER(Id) (usbId.asOutParam()));
    1260                 }
    1261                 else
    1262                 {
    1263                     ComPtr <IUSBDeviceCollection> coll;
    1264                     CHECK_ERROR_BREAK (console, COMGETTER(USBDevices)(coll.asOutParam()));
    1265                     ComPtr <IUSBDevice> dev;
    1266                     CHECK_ERROR_BREAK (coll, FindByAddress (Bstr (a->argv [2]), dev.asOutParam()));
    1267                     CHECK_ERROR_BREAK (dev, COMGETTER(Id) (usbId.asOutParam()));
    1268                 }
    1269             }
    1270 
    1271             if (attach)
    1272                 CHECK_ERROR_BREAK (console, AttachUSBDevice (usbId));
    1273             else
    1274             {
    1275                 ComPtr <IUSBDevice> dev;
    1276                 CHECK_ERROR_BREAK (console, DetachUSBDevice (usbId, dev.asOutParam()));
    1277             }
    1278         }
    1279         else if (strcmp(a->argv[1], "setvideomodehint") == 0)
    1280         {
    1281             if (a->argc != 5 && a->argc != 6)
    1282             {
    1283                 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
    1284                 rc = E_FAIL;
    1285                 break;
    1286             }
    1287             uint32_t xres = RTStrToUInt32(a->argv[2]);
    1288             uint32_t yres = RTStrToUInt32(a->argv[3]);
    1289             uint32_t bpp  = RTStrToUInt32(a->argv[4]);
    1290             uint32_t displayIdx = 0;
    1291             if (a->argc == 6)
    1292                 displayIdx = RTStrToUInt32(a->argv[5]);
    1293 
    1294             ComPtr<IDisplay> display;
    1295             CHECK_ERROR_BREAK(console, COMGETTER(Display)(display.asOutParam()));
    1296             CHECK_ERROR_BREAK(display, SetVideoModeHint(xres, yres, bpp, displayIdx));
    1297         }
    1298         else if (strcmp(a->argv[1], "setcredentials") == 0)
    1299         {
    1300             bool fAllowLocalLogon = true;
    1301             if (a->argc == 7)
    1302             {
    1303                 if (strcmp(a->argv[5], "-allowlocallogon") != 0)
    1304                 {
    1305                     errorArgument("Invalid parameter '%s'", a->argv[5]);
    1306                     rc = E_FAIL;
    1307                     break;
    1308                 }
    1309                 if (strcmp(a->argv[6], "no") == 0)
    1310                     fAllowLocalLogon = false;
    1311             }
    1312             else if (a->argc != 5)
    1313             {
    1314                 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
    1315                 rc = E_FAIL;
    1316                 break;
    1317             }
    1318 
    1319             ComPtr<IGuest> guest;
    1320             CHECK_ERROR_BREAK(console, COMGETTER(Guest)(guest.asOutParam()));
    1321             CHECK_ERROR_BREAK(guest, SetCredentials(Bstr(a->argv[2]), Bstr(a->argv[3]), Bstr(a->argv[4]), fAllowLocalLogon));
    1322         }
    1323         else if (strcmp(a->argv[1], "dvdattach") == 0)
    1324         {
    1325             if (a->argc != 3)
    1326             {
    1327                 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
    1328                 rc = E_FAIL;
    1329                 break;
    1330             }
    1331             ComPtr<IDVDDrive> dvdDrive;
    1332             sessionMachine->COMGETTER(DVDDrive)(dvdDrive.asOutParam());
    1333             ASSERT(dvdDrive);
    1334 
    1335             /* unmount? */
    1336             if (strcmp(a->argv[2], "none") == 0)
    1337             {
    1338                 CHECK_ERROR(dvdDrive, Unmount());
    1339             }
    1340             /* host drive? */
    1341             else if (strncmp(a->argv[2], "host:", 5) == 0)
    1342             {
    1343                 ComPtr<IHost> host;
    1344                 CHECK_ERROR(a->virtualBox, COMGETTER(Host)(host.asOutParam()));
    1345                 ComPtr<IHostDVDDriveCollection> hostDVDs;
    1346                 CHECK_ERROR(host, COMGETTER(DVDDrives)(hostDVDs.asOutParam()));
    1347                 ComPtr<IHostDVDDrive> hostDVDDrive;
    1348                 rc = hostDVDs->FindByName(Bstr(a->argv[2] + 5), hostDVDDrive.asOutParam());
    1349                 if (!hostDVDDrive)
    1350                 {
    1351                     errorArgument("Invalid host DVD drive name");
    1352                     rc = E_FAIL;
    1353                     break;
    1354                 }
    1355                 CHECK_ERROR(dvdDrive, CaptureHostDrive(hostDVDDrive));
    1356             }
    1357             else
    1358             {
    1359                 /* first assume it's a UUID */
    1360                 Guid uuid(a->argv[2]);
    1361                 ComPtr<IDVDImage> dvdImage;
    1362                 rc = a->virtualBox->GetDVDImage(uuid, dvdImage.asOutParam());
    1363                 if (FAILED(rc) || !dvdImage)
    1364                 {
    1365                     /* must be a filename, check if it's in the collection */
    1366                     rc = a->virtualBox->FindDVDImage(Bstr(a->argv[2]), dvdImage.asOutParam());
    1367                     /* not registered, do that on the fly */
    1368                     if (!dvdImage)
    1369                     {
    1370                         Guid emptyUUID;
    1371                         CHECK_ERROR(a->virtualBox, OpenDVDImage(Bstr(a->argv[2]), emptyUUID, dvdImage.asOutParam()));
    1372                     }
    1373                 }
    1374                 if (!dvdImage)
    1375                 {
    1376                     rc = E_FAIL;
    1377                     break;
    1378                 }
    1379                 dvdImage->COMGETTER(Id)(uuid.asOutParam());
    1380                 CHECK_ERROR(dvdDrive, MountImage(uuid));
    1381             }
    1382         }
    1383         else if (strcmp(a->argv[1], "floppyattach") == 0)
    1384         {
    1385             if (a->argc != 3)
    1386             {
    1387                 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
    1388                 rc = E_FAIL;
    1389                 break;
    1390             }
    1391 
    1392             ComPtr<IFloppyDrive> floppyDrive;
    1393             sessionMachine->COMGETTER(FloppyDrive)(floppyDrive.asOutParam());
    1394             ASSERT(floppyDrive);
    1395 
    1396             /* unmount? */
    1397             if (strcmp(a->argv[2], "none") == 0)
    1398             {
    1399                 CHECK_ERROR(floppyDrive, Unmount());
    1400             }
    1401             /* host drive? */
    1402             else if (strncmp(a->argv[2], "host:", 5) == 0)
    1403             {
    1404                 ComPtr<IHost> host;
    1405                 CHECK_ERROR(a->virtualBox, COMGETTER(Host)(host.asOutParam()));
    1406                 ComPtr<IHostFloppyDriveCollection> hostFloppies;
    1407                 CHECK_ERROR(host, COMGETTER(FloppyDrives)(hostFloppies.asOutParam()));
    1408                 ComPtr<IHostFloppyDrive> hostFloppyDrive;
    1409                 rc = hostFloppies->FindByName(Bstr(a->argv[2] + 5), hostFloppyDrive.asOutParam());
    1410                 if (!hostFloppyDrive)
    1411                 {
    1412                     errorArgument("Invalid host floppy drive name");
    1413                     rc = E_FAIL;
    1414                     break;
    1415                 }
    1416                 CHECK_ERROR(floppyDrive, CaptureHostDrive(hostFloppyDrive));
    1417             }
    1418             else
    1419             {
    1420                 /* first assume it's a UUID */
    1421                 Guid uuid(a->argv[2]);
    1422                 ComPtr<IFloppyImage> floppyImage;
    1423                 rc = a->virtualBox->GetFloppyImage(uuid, floppyImage.asOutParam());
    1424                 if (FAILED(rc) || !floppyImage)
    1425                 {
    1426                     /* must be a filename, check if it's in the collection */
    1427                     rc = a->virtualBox->FindFloppyImage(Bstr(a->argv[2]), floppyImage.asOutParam());
    1428                     /* not registered, do that on the fly */
    1429                     if (!floppyImage)
    1430                     {
    1431                         Guid emptyUUID;
    1432                         CHECK_ERROR(a->virtualBox, OpenFloppyImage(Bstr(a->argv[2]), emptyUUID, floppyImage.asOutParam()));
    1433                     }
    1434                 }
    1435                 if (!floppyImage)
    1436                 {
    1437                     rc = E_FAIL;
    1438                     break;
    1439                 }
    1440                 floppyImage->COMGETTER(Id)(uuid.asOutParam());
    1441                 CHECK_ERROR(floppyDrive, MountImage(uuid));
    1442             }
    1443         }
    1444 #ifdef VBOX_WITH_MEM_BALLOONING
    1445         else if (strncmp(a->argv[1], "-guestmemoryballoon", 19) == 0)
    1446         {
    1447             if (a->argc != 3)
    1448             {
    1449                 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
    1450                 rc = E_FAIL;
    1451                 break;
    1452             }
    1453             uint32_t uVal;
    1454             int vrc;
    1455             vrc = RTStrToUInt32Ex(a->argv[2], NULL, 0, &uVal);
    1456             if (vrc != VINF_SUCCESS)
    1457             {
    1458                 errorArgument("Error parsing guest memory balloon size '%s'", a->argv[2]);
    1459                 rc = E_FAIL;
    1460                 break;
    1461             }
    1462 
    1463             /* guest is running; update IGuest */
    1464             ComPtr <IGuest> guest;
    1465 
    1466             rc = console->COMGETTER(Guest)(guest.asOutParam());
    1467             if (SUCCEEDED(rc))
    1468                 CHECK_ERROR(guest, COMSETTER(MemoryBalloonSize)(uVal));
    1469         }
    1470 #endif
    1471         else if (strncmp(a->argv[1], "-gueststatisticsinterval", 24) == 0)
    1472         {
    1473             if (a->argc != 3)
    1474             {
    1475                 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
    1476                 rc = E_FAIL;
    1477                 break;
    1478             }
    1479             uint32_t uVal;
    1480             int vrc;
    1481             vrc = RTStrToUInt32Ex(a->argv[2], NULL, 0, &uVal);
    1482             if (vrc != VINF_SUCCESS)
    1483             {
    1484                 errorArgument("Error parsing guest statistics interval '%s'", a->argv[2]);
    1485                 rc = E_FAIL;
    1486                 break;
    1487             }
    1488 
    1489             /* guest is running; update IGuest */
    1490             ComPtr <IGuest> guest;
    1491 
    1492             rc = console->COMGETTER(Guest)(guest.asOutParam());
    1493             if (SUCCEEDED(rc))
    1494                 CHECK_ERROR(guest, COMSETTER(StatisticsUpdateInterval)(uVal));
    1495         }
    1496         else
    1497         {
    1498             errorSyntax(USAGE_CONTROLVM, "Invalid parameter '%s'", Utf8Str(a->argv[1]).raw());
    1499             rc = E_FAIL;
    1500         }
    1501     }
    1502     while (0);
    1503 
    1504     a->session->Close();
    1505 
    1506     return SUCCEEDED (rc) ? 0 : 1;
    1507 }
    1508 
    1509 static int handleDiscardState(HandlerArg *a)
    1510 {
    1511     HRESULT rc;
    1512 
    1513     if (a->argc != 1)
    1514         return errorSyntax(USAGE_DISCARDSTATE, "Incorrect number of parameters");
    1515 
    1516     ComPtr<IMachine> machine;
    1517     /* assume it's a UUID */
    1518     rc = a->virtualBox->GetMachine(Guid(a->argv[0]), machine.asOutParam());
    1519     if (FAILED(rc) || !machine)
    1520     {
    1521         /* must be a name */
    1522         CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]), machine.asOutParam()));
    1523     }
    1524     if (machine)
    1525     {
    1526         do
    1527         {
    1528             /* we have to open a session for this task */
    1529             Guid guid;
    1530             machine->COMGETTER(Id)(guid.asOutParam());
    1531             CHECK_ERROR_BREAK(a->virtualBox, OpenSession(a->session, guid));
    1532             do
    1533             {
    1534                 ComPtr<IConsole> console;
    1535                 CHECK_ERROR_BREAK(a->session, COMGETTER(Console)(console.asOutParam()));
    1536                 CHECK_ERROR_BREAK(console, DiscardSavedState());
    1537             }
    1538             while (0);
    1539             CHECK_ERROR_BREAK(a->session, Close());
    1540         }
    1541         while (0);
    1542     }
    1543 
    1544     return SUCCEEDED(rc) ? 0 : 1;
    1545 }
    1546 
    1547 static int handleAdoptdState(HandlerArg *a)
    1548 {
    1549     HRESULT rc;
    1550 
    1551     if (a->argc != 2)
    1552         return errorSyntax(USAGE_ADOPTSTATE, "Incorrect number of parameters");
    1553 
    1554     ComPtr<IMachine> machine;
    1555     /* assume it's a UUID */
    1556     rc = a->virtualBox->GetMachine(Guid(a->argv[0]), machine.asOutParam());
    1557     if (FAILED(rc) || !machine)
    1558     {
    1559         /* must be a name */
    1560         CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]), machine.asOutParam()));
    1561     }
    1562     if (machine)
    1563     {
    1564         do
    1565         {
    1566             /* we have to open a session for this task */
    1567             Guid guid;
    1568             machine->COMGETTER(Id)(guid.asOutParam());
    1569             CHECK_ERROR_BREAK(a->virtualBox, OpenSession(a->session, guid));
    1570             do
    1571             {
    1572                 ComPtr<IConsole> console;
    1573                 CHECK_ERROR_BREAK(a->session, COMGETTER(Console)(console.asOutParam()));
    1574                 CHECK_ERROR_BREAK(console, AdoptSavedState (Bstr (a->argv[1])));
    1575             }
    1576             while (0);
    1577             CHECK_ERROR_BREAK(a->session, Close());
    1578         }
    1579         while (0);
    1580     }
    1581 
    1582     return SUCCEEDED(rc) ? 0 : 1;
    1583 }
    1584 
    1585 static int handleSnapshot(HandlerArg *a)
     40int handleSnapshot(HandlerArg *a)
    158641{
    158742    HRESULT rc;
     
    1830285}
    1831286
    1832 static int handleGetExtraData(HandlerArg *a)
    1833 {
    1834     HRESULT rc = S_OK;
    1835 
    1836     if (a->argc != 2)
    1837         return errorSyntax(USAGE_GETEXTRADATA, "Incorrect number of parameters");
    1838 
    1839     /* global data? */
    1840     if (strcmp(a->argv[0], "global") == 0)
    1841     {
    1842         /* enumeration? */
    1843         if (strcmp(a->argv[1], "enumerate") == 0)
    1844         {
    1845             Bstr extraDataKey;
    1846 
    1847             do
    1848             {
    1849                 Bstr nextExtraDataKey;
    1850                 Bstr nextExtraDataValue;
    1851                 HRESULT rcEnum = a->virtualBox->GetNextExtraDataKey(extraDataKey, nextExtraDataKey.asOutParam(),
    1852                                                                     nextExtraDataValue.asOutParam());
    1853                 extraDataKey = nextExtraDataKey;
    1854 
    1855                 if (SUCCEEDED(rcEnum) && extraDataKey)
    1856                     RTPrintf("Key: %lS, Value: %lS\n", nextExtraDataKey.raw(), nextExtraDataValue.raw());
    1857             } while (extraDataKey);
    1858         }
    1859         else
    1860         {
    1861             Bstr value;
    1862             CHECK_ERROR(a->virtualBox, GetExtraData(Bstr(a->argv[1]), value.asOutParam()));
    1863             if (value)
    1864                 RTPrintf("Value: %lS\n", value.raw());
    1865             else
    1866                 RTPrintf("No value set!\n");
    1867         }
    1868     }
    1869     else
    1870     {
    1871         ComPtr<IMachine> machine;
    1872         /* assume it's a UUID */
    1873         rc = a->virtualBox->GetMachine(Guid(a->argv[0]), machine.asOutParam());
    1874         if (FAILED(rc) || !machine)
    1875         {
    1876             /* must be a name */
    1877             CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]), machine.asOutParam()));
    1878         }
    1879         if (machine)
    1880         {
    1881             /* enumeration? */
    1882             if (strcmp(a->argv[1], "enumerate") == 0)
    1883             {
    1884                 Bstr extraDataKey;
    1885 
    1886                 do
    1887                 {
    1888                     Bstr nextExtraDataKey;
    1889                     Bstr nextExtraDataValue;
    1890                     HRESULT rcEnum = machine->GetNextExtraDataKey(extraDataKey, nextExtraDataKey.asOutParam(),
    1891                                                                   nextExtraDataValue.asOutParam());
    1892                     extraDataKey = nextExtraDataKey;
    1893 
    1894                     if (SUCCEEDED(rcEnum) && extraDataKey)
    1895                     {
    1896                         RTPrintf("Key: %lS, Value: %lS\n", nextExtraDataKey.raw(), nextExtraDataValue.raw());
    1897                     }
    1898                 } while (extraDataKey);
    1899             }
    1900             else
    1901             {
    1902                 Bstr value;
    1903                 CHECK_ERROR(machine, GetExtraData(Bstr(a->argv[1]), value.asOutParam()));
    1904                 if (value)
    1905                     RTPrintf("Value: %lS\n", value.raw());
    1906                 else
    1907                     RTPrintf("No value set!\n");
    1908             }
    1909         }
    1910     }
    1911     return SUCCEEDED(rc) ? 0 : 1;
    1912 }
    1913 
    1914 static int handleSetExtraData(HandlerArg *a)
    1915 {
    1916     HRESULT rc = S_OK;
    1917 
    1918     if (a->argc < 2)
    1919         return errorSyntax(USAGE_SETEXTRADATA, "Not enough parameters");
    1920 
    1921     /* global data? */
    1922     if (strcmp(a->argv[0], "global") == 0)
    1923     {
    1924         if (a->argc < 3)
    1925             CHECK_ERROR(a->virtualBox, SetExtraData(Bstr(a->argv[1]), NULL));
    1926         else if (a->argc == 3)
    1927             CHECK_ERROR(a->virtualBox, SetExtraData(Bstr(a->argv[1]), Bstr(a->argv[2])));
    1928         else
    1929             return errorSyntax(USAGE_SETEXTRADATA, "Too many parameters");
    1930     }
    1931     else
    1932     {
    1933         ComPtr<IMachine> machine;
    1934         /* assume it's a UUID */
    1935         rc = a->virtualBox->GetMachine(Guid(a->argv[0]), machine.asOutParam());
    1936         if (FAILED(rc) || !machine)
    1937         {
    1938             /* must be a name */
    1939             CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]), machine.asOutParam()));
    1940         }
    1941         if (machine)
    1942         {
    1943             if (a->argc < 3)
    1944                 CHECK_ERROR(machine, SetExtraData(Bstr(a->argv[1]), NULL));
    1945             else if (a->argc == 3)
    1946                 CHECK_ERROR(machine, SetExtraData(Bstr(a->argv[1]), Bstr(a->argv[2])));
    1947             else
    1948                 return errorSyntax(USAGE_SETEXTRADATA, "Too many parameters");
    1949         }
    1950     }
    1951     return SUCCEEDED(rc) ? 0 : 1;
    1952 }
    1953 
    1954 static int handleSetProperty(HandlerArg *a)
    1955 {
    1956     HRESULT rc;
    1957 
    1958     /* there must be two arguments: property name and value */
    1959     if (a->argc != 2)
    1960         return errorSyntax(USAGE_SETPROPERTY, "Incorrect number of parameters");
    1961 
    1962     ComPtr<ISystemProperties> systemProperties;
    1963     a->virtualBox->COMGETTER(SystemProperties)(systemProperties.asOutParam());
    1964 
    1965     if (strcmp(a->argv[0], "hdfolder") == 0)
    1966     {
    1967         /* reset to default? */
    1968         if (strcmp(a->argv[1], "default") == 0)
    1969             CHECK_ERROR(systemProperties, COMSETTER(DefaultHardDiskFolder)(NULL));
    1970         else
    1971             CHECK_ERROR(systemProperties, COMSETTER(DefaultHardDiskFolder)(Bstr(a->argv[1])));
    1972     }
    1973     else if (strcmp(a->argv[0], "machinefolder") == 0)
    1974     {
    1975         /* reset to default? */
    1976         if (strcmp(a->argv[1], "default") == 0)
    1977             CHECK_ERROR(systemProperties, COMSETTER(DefaultMachineFolder)(NULL));
    1978         else
    1979             CHECK_ERROR(systemProperties, COMSETTER(DefaultMachineFolder)(Bstr(a->argv[1])));
    1980     }
    1981     else if (strcmp(a->argv[0], "vrdpauthlibrary") == 0)
    1982     {
    1983         /* reset to default? */
    1984         if (strcmp(a->argv[1], "default") == 0)
    1985             CHECK_ERROR(systemProperties, COMSETTER(RemoteDisplayAuthLibrary)(NULL));
    1986         else
    1987             CHECK_ERROR(systemProperties, COMSETTER(RemoteDisplayAuthLibrary)(Bstr(a->argv[1])));
    1988     }
    1989     else if (strcmp(a->argv[0], "websrvauthlibrary") == 0)
    1990     {
    1991         /* reset to default? */
    1992         if (strcmp(a->argv[1], "default") == 0)
    1993             CHECK_ERROR(systemProperties, COMSETTER(WebServiceAuthLibrary)(NULL));
    1994         else
    1995             CHECK_ERROR(systemProperties, COMSETTER(WebServiceAuthLibrary)(Bstr(a->argv[1])));
    1996     }
    1997     else if (strcmp(a->argv[0], "hwvirtexenabled") == 0)
    1998     {
    1999         if (strcmp(a->argv[1], "yes") == 0)
    2000             CHECK_ERROR(systemProperties, COMSETTER(HWVirtExEnabled)(TRUE));
    2001         else if (strcmp(a->argv[1], "no") == 0)
    2002             CHECK_ERROR(systemProperties, COMSETTER(HWVirtExEnabled)(FALSE));
    2003         else
    2004             return errorArgument("Invalid value '%s' for hardware virtualization extension flag", a->argv[1]);
    2005     }
    2006     else if (strcmp(a->argv[0], "loghistorycount") == 0)
    2007     {
    2008         uint32_t uVal;
    2009         int vrc;
    2010         vrc = RTStrToUInt32Ex(a->argv[1], NULL, 0, &uVal);
    2011         if (vrc != VINF_SUCCESS)
    2012             return errorArgument("Error parsing Log history count '%s'", a->argv[1]);
    2013         CHECK_ERROR(systemProperties, COMSETTER(LogHistoryCount)(uVal));
    2014     }
    2015     else
    2016         return errorSyntax(USAGE_SETPROPERTY, "Invalid parameter '%s'", a->argv[0]);
    2017 
    2018     return SUCCEEDED(rc) ? 0 : 1;
    2019 }
    2020 
    2021 static int handleUSBFilter (HandlerArg *a)
    2022 {
    2023     HRESULT rc = S_OK;
    2024     USBFilterCmd cmd;
    2025 
    2026     /* at least: 0: command, 1: index, 2: -target, 3: <target value> */
    2027     if (a->argc < 4)
    2028         return errorSyntax(USAGE_USBFILTER, "Not enough parameters");
    2029 
    2030     /* which command? */
    2031     cmd.mAction = USBFilterCmd::Invalid;
    2032     if      (strcmp (a->argv [0], "add") == 0)     cmd.mAction = USBFilterCmd::Add;
    2033     else if (strcmp (a->argv [0], "modify") == 0)  cmd.mAction = USBFilterCmd::Modify;
    2034     else if (strcmp (a->argv [0], "remove") == 0)  cmd.mAction = USBFilterCmd::Remove;
    2035 
    2036     if (cmd.mAction == USBFilterCmd::Invalid)
    2037         return errorSyntax(USAGE_USBFILTER, "Invalid parameter '%s'", a->argv[0]);
    2038 
    2039     /* which index? */
    2040     if (VINF_SUCCESS !=  RTStrToUInt32Full (a->argv[1], 10, &cmd.mIndex))
    2041         return errorSyntax(USAGE_USBFILTER, "Invalid index '%s'", a->argv[1]);
    2042 
    2043     switch (cmd.mAction)
    2044     {
    2045         case USBFilterCmd::Add:
    2046         case USBFilterCmd::Modify:
    2047         {
    2048             /* at least: 0: command, 1: index, 2: -target, 3: <target value>, 4: -name, 5: <name value> */
    2049             if (a->argc < 6)
    2050             {
    2051                 if (cmd.mAction == USBFilterCmd::Add)
    2052                     return errorSyntax(USAGE_USBFILTER_ADD, "Not enough parameters");
    2053 
    2054                 return errorSyntax(USAGE_USBFILTER_MODIFY, "Not enough parameters");
    2055             }
    2056 
    2057             // set Active to true by default
    2058             // (assuming that the user sets up all necessary attributes
    2059             // at once and wants the filter to be active immediately)
    2060             if (cmd.mAction == USBFilterCmd::Add)
    2061                 cmd.mFilter.mActive = true;
    2062 
    2063             for (int i = 2; i < a->argc; i++)
    2064             {
    2065                 if  (strcmp(a->argv [i], "-target") == 0)
    2066                 {
    2067                     if (a->argc <= i + 1 || !*a->argv[i+1])
    2068                         return errorArgument("Missing argument to '%s'", a->argv[i]);
    2069                     i++;
    2070                     if (strcmp (a->argv [i], "global") == 0)
    2071                         cmd.mGlobal = true;
    2072                     else
    2073                     {
    2074                         /* assume it's a UUID of a machine */
    2075                         rc = a->virtualBox->GetMachine(Guid(a->argv[i]), cmd.mMachine.asOutParam());
    2076                         if (FAILED(rc) || !cmd.mMachine)
    2077                         {
    2078                             /* must be a name */
    2079                             CHECK_ERROR_RET(a->virtualBox, FindMachine(Bstr(a->argv[i]), cmd.mMachine.asOutParam()), 1);
    2080                         }
    2081                     }
    2082                 }
    2083                 else if (strcmp(a->argv [i], "-name") == 0)
    2084                 {
    2085                     if (a->argc <= i + 1 || !*a->argv[i+1])
    2086                         return errorArgument("Missing argument to '%s'", a->argv[i]);
    2087                     i++;
    2088                     cmd.mFilter.mName = a->argv [i];
    2089                 }
    2090                 else if (strcmp(a->argv [i], "-active") == 0)
    2091                 {
    2092                     if (a->argc <= i + 1)
    2093                         return errorArgument("Missing argument to '%s'", a->argv[i]);
    2094                     i++;
    2095                     if (strcmp (a->argv [i], "yes") == 0)
    2096                         cmd.mFilter.mActive = true;
    2097                     else if (strcmp (a->argv [i], "no") == 0)
    2098                         cmd.mFilter.mActive = false;
    2099                     else
    2100                         return errorArgument("Invalid -active argument '%s'", a->argv[i]);
    2101                 }
    2102                 else if (strcmp(a->argv [i], "-vendorid") == 0)
    2103                 {
    2104                     if (a->argc <= i + 1)
    2105                         return errorArgument("Missing argument to '%s'", a->argv[i]);
    2106                     i++;
    2107                     cmd.mFilter.mVendorId = a->argv [i];
    2108                 }
    2109                 else if (strcmp(a->argv [i], "-productid") == 0)
    2110                 {
    2111                     if (a->argc <= i + 1)
    2112                         return errorArgument("Missing argument to '%s'", a->argv[i]);
    2113                     i++;
    2114                     cmd.mFilter.mProductId = a->argv [i];
    2115                 }
    2116                 else if (strcmp(a->argv [i], "-revision") == 0)
    2117                 {
    2118                     if (a->argc <= i + 1)
    2119                         return errorArgument("Missing argument to '%s'", a->argv[i]);
    2120                     i++;
    2121                     cmd.mFilter.mRevision = a->argv [i];
    2122                 }
    2123                 else if (strcmp(a->argv [i], "-manufacturer") == 0)
    2124                 {
    2125                     if (a->argc <= i + 1)
    2126                         return errorArgument("Missing argument to '%s'", a->argv[i]);
    2127                     i++;
    2128                     cmd.mFilter.mManufacturer = a->argv [i];
    2129                 }
    2130                 else if (strcmp(a->argv [i], "-product") == 0)
    2131                 {
    2132                     if (a->argc <= i + 1)
    2133                         return errorArgument("Missing argument to '%s'", a->argv[i]);
    2134                     i++;
    2135                     cmd.mFilter.mProduct = a->argv [i];
    2136                 }
    2137                 else if (strcmp(a->argv [i], "-remote") == 0)
    2138                 {
    2139                     if (a->argc <= i + 1)
    2140                         return errorArgument("Missing argument to '%s'", a->argv[i]);
    2141                     i++;
    2142                     cmd.mFilter.mRemote = a->argv[i];
    2143                 }
    2144                 else if (strcmp(a->argv [i], "-serialnumber") == 0)
    2145                 {
    2146                     if (a->argc <= i + 1)
    2147                         return errorArgument("Missing argument to '%s'", a->argv[i]);
    2148                     i++;
    2149                     cmd.mFilter.mSerialNumber = a->argv [i];
    2150                 }
    2151                 else if (strcmp(a->argv [i], "-maskedinterfaces") == 0)
    2152                 {
    2153                     if (a->argc <= i + 1)
    2154                         return errorArgument("Missing argument to '%s'", a->argv[i]);
    2155                     i++;
    2156                     uint32_t u32;
    2157                     rc = RTStrToUInt32Full(a->argv[i], 0, &u32);
    2158                     if (RT_FAILURE(rc))
    2159                         return errorArgument("Failed to convert the -maskedinterfaces value '%s' to a number, rc=%Rrc", a->argv[i], rc);
    2160                     cmd.mFilter.mMaskedInterfaces = u32;
    2161                 }
    2162                 else if (strcmp(a->argv [i], "-action") == 0)
    2163                 {
    2164                     if (a->argc <= i + 1)
    2165                         return errorArgument("Missing argument to '%s'", a->argv[i]);
    2166                     i++;
    2167                     if (strcmp (a->argv [i], "ignore") == 0)
    2168                         cmd.mFilter.mAction = USBDeviceFilterAction_Ignore;
    2169                     else if (strcmp (a->argv [i], "hold") == 0)
    2170                         cmd.mFilter.mAction = USBDeviceFilterAction_Hold;
    2171                     else
    2172                         return errorArgument("Invalid USB filter action '%s'", a->argv[i]);
    2173                 }
    2174                 else
    2175                     return errorSyntax(cmd.mAction == USBFilterCmd::Add ? USAGE_USBFILTER_ADD : USAGE_USBFILTER_MODIFY,
    2176                                        "Unknown option '%s'", a->argv[i]);
    2177             }
    2178 
    2179             if (cmd.mAction == USBFilterCmd::Add)
    2180             {
    2181                 // mandatory/forbidden options
    2182                 if (   cmd.mFilter.mName.isEmpty()
    2183                     ||
    2184                        (   cmd.mGlobal
    2185                         && cmd.mFilter.mAction == USBDeviceFilterAction_Null
    2186                        )
    2187                     || (   !cmd.mGlobal
    2188                         && !cmd.mMachine)
    2189                     || (   cmd.mGlobal
    2190                         && cmd.mFilter.mRemote)
    2191                    )
    2192                 {
    2193                     return errorSyntax(USAGE_USBFILTER_ADD, "Mandatory options not supplied");
    2194                 }
    2195             }
    2196             break;
    2197         }
    2198 
    2199         case USBFilterCmd::Remove:
    2200         {
    2201             /* at least: 0: command, 1: index, 2: -target, 3: <target value> */
    2202             if (a->argc < 4)
    2203                 return errorSyntax(USAGE_USBFILTER_REMOVE, "Not enough parameters");
    2204 
    2205             for (int i = 2; i < a->argc; i++)
    2206             {
    2207                 if  (strcmp(a->argv [i], "-target") == 0)
    2208                 {
    2209                     if (a->argc <= i + 1 || !*a->argv[i+1])
    2210                         return errorArgument("Missing argument to '%s'", a->argv[i]);
    2211                     i++;
    2212                     if (strcmp (a->argv [i], "global") == 0)
    2213                         cmd.mGlobal = true;
    2214                     else
    2215                     {
    2216                         /* assume it's a UUID of a machine */
    2217                         rc = a->virtualBox->GetMachine(Guid(a->argv[i]), cmd.mMachine.asOutParam());
    2218                         if (FAILED(rc) || !cmd.mMachine)
    2219                         {
    2220                             /* must be a name */
    2221                             CHECK_ERROR_RET(a->virtualBox, FindMachine(Bstr(a->argv[i]), cmd.mMachine.asOutParam()), 1);
    2222                         }
    2223                     }
    2224                 }
    2225             }
    2226 
    2227             // mandatory options
    2228             if (!cmd.mGlobal && !cmd.mMachine)
    2229                 return errorSyntax(USAGE_USBFILTER_REMOVE, "Mandatory options not supplied");
    2230 
    2231             break;
    2232         }
    2233 
    2234         default: break;
    2235     }
    2236 
    2237     USBFilterCmd::USBFilter &f = cmd.mFilter;
    2238 
    2239     ComPtr <IHost> host;
    2240     ComPtr <IUSBController> ctl;
    2241     if (cmd.mGlobal)
    2242         CHECK_ERROR_RET (a->virtualBox, COMGETTER(Host) (host.asOutParam()), 1);
    2243     else
    2244     {
    2245         Guid uuid;
    2246         cmd.mMachine->COMGETTER(Id)(uuid.asOutParam());
    2247         /* open a session for the VM */
    2248         CHECK_ERROR_RET (a->virtualBox, OpenSession(a->session, uuid), 1);
    2249         /* get the mutable session machine */
    2250         a->session->COMGETTER(Machine)(cmd.mMachine.asOutParam());
    2251         /* and get the USB controller */
    2252         CHECK_ERROR_RET (cmd.mMachine, COMGETTER(USBController) (ctl.asOutParam()), 1);
    2253     }
    2254 
    2255     switch (cmd.mAction)
    2256     {
    2257         case USBFilterCmd::Add:
    2258         {
    2259             if (cmd.mGlobal)
    2260             {
    2261                 ComPtr <IHostUSBDeviceFilter> flt;
    2262                 CHECK_ERROR_BREAK (host, CreateUSBDeviceFilter (f.mName, flt.asOutParam()));
    2263 
    2264                 if (!f.mActive.isNull())
    2265                     CHECK_ERROR_BREAK (flt, COMSETTER(Active) (f.mActive));
    2266                 if (!f.mVendorId.isNull())
    2267                     CHECK_ERROR_BREAK (flt, COMSETTER(VendorId) (f.mVendorId.setNullIfEmpty()));
    2268                 if (!f.mProductId.isNull())
    2269                     CHECK_ERROR_BREAK (flt, COMSETTER(ProductId) (f.mProductId.setNullIfEmpty()));
    2270                 if (!f.mRevision.isNull())
    2271                     CHECK_ERROR_BREAK (flt, COMSETTER(Revision) (f.mRevision.setNullIfEmpty()));
    2272                 if (!f.mManufacturer.isNull())
    2273                     CHECK_ERROR_BREAK (flt, COMSETTER(Manufacturer) (f.mManufacturer.setNullIfEmpty()));
    2274                 if (!f.mSerialNumber.isNull())
    2275                     CHECK_ERROR_BREAK (flt, COMSETTER(SerialNumber) (f.mSerialNumber.setNullIfEmpty()));
    2276                 if (!f.mMaskedInterfaces.isNull())
    2277                     CHECK_ERROR_BREAK (flt, COMSETTER(MaskedInterfaces) (f.mMaskedInterfaces));
    2278 
    2279                 if (f.mAction != USBDeviceFilterAction_Null)
    2280                     CHECK_ERROR_BREAK (flt, COMSETTER(Action) (f.mAction));
    2281 
    2282                 CHECK_ERROR_BREAK (host, InsertUSBDeviceFilter (cmd.mIndex, flt));
    2283             }
    2284             else
    2285             {
    2286                 ComPtr <IUSBDeviceFilter> flt;
    2287                 CHECK_ERROR_BREAK (ctl, CreateDeviceFilter (f.mName, flt.asOutParam()));
    2288 
    2289                 if (!f.mActive.isNull())
    2290                     CHECK_ERROR_BREAK (flt, COMSETTER(Active) (f.mActive));
    2291                 if (!f.mVendorId.isNull())
    2292                     CHECK_ERROR_BREAK (flt, COMSETTER(VendorId) (f.mVendorId.setNullIfEmpty()));
    2293                 if (!f.mProductId.isNull())
    2294                     CHECK_ERROR_BREAK (flt, COMSETTER(ProductId) (f.mProductId.setNullIfEmpty()));
    2295                 if (!f.mRevision.isNull())
    2296                     CHECK_ERROR_BREAK (flt, COMSETTER(Revision) (f.mRevision.setNullIfEmpty()));
    2297                 if (!f.mManufacturer.isNull())
    2298                     CHECK_ERROR_BREAK (flt, COMSETTER(Manufacturer) (f.mManufacturer.setNullIfEmpty()));
    2299                 if (!f.mRemote.isNull())
    2300                     CHECK_ERROR_BREAK (flt, COMSETTER(Remote) (f.mRemote.setNullIfEmpty()));
    2301                 if (!f.mSerialNumber.isNull())
    2302                     CHECK_ERROR_BREAK (flt, COMSETTER(SerialNumber) (f.mSerialNumber.setNullIfEmpty()));
    2303                 if (!f.mMaskedInterfaces.isNull())
    2304                     CHECK_ERROR_BREAK (flt, COMSETTER(MaskedInterfaces) (f.mMaskedInterfaces));
    2305 
    2306                 CHECK_ERROR_BREAK (ctl, InsertDeviceFilter (cmd.mIndex, flt));
    2307             }
    2308             break;
    2309         }
    2310         case USBFilterCmd::Modify:
    2311         {
    2312             if (cmd.mGlobal)
    2313             {
    2314                 ComPtr <IHostUSBDeviceFilterCollection> coll;
    2315                 CHECK_ERROR_BREAK (host, COMGETTER(USBDeviceFilters) (coll.asOutParam()));
    2316                 ComPtr <IHostUSBDeviceFilter> flt;
    2317                 CHECK_ERROR_BREAK (coll, GetItemAt (cmd.mIndex, flt.asOutParam()));
    2318 
    2319                 if (!f.mName.isNull())
    2320                     CHECK_ERROR_BREAK (flt, COMSETTER(Name) (f.mName.setNullIfEmpty()));
    2321                 if (!f.mActive.isNull())
    2322                     CHECK_ERROR_BREAK (flt, COMSETTER(Active) (f.mActive));
    2323                 if (!f.mVendorId.isNull())
    2324                     CHECK_ERROR_BREAK (flt, COMSETTER(VendorId) (f.mVendorId.setNullIfEmpty()));
    2325                 if (!f.mProductId.isNull())
    2326                     CHECK_ERROR_BREAK (flt, COMSETTER(ProductId) (f.mProductId.setNullIfEmpty()));
    2327                 if (!f.mRevision.isNull())
    2328                     CHECK_ERROR_BREAK (flt, COMSETTER(Revision) (f.mRevision.setNullIfEmpty()));
    2329                 if (!f.mManufacturer.isNull())
    2330                     CHECK_ERROR_BREAK (flt, COMSETTER(Manufacturer) (f.mManufacturer.setNullIfEmpty()));
    2331                 if (!f.mSerialNumber.isNull())
    2332                     CHECK_ERROR_BREAK (flt, COMSETTER(SerialNumber) (f.mSerialNumber.setNullIfEmpty()));
    2333                 if (!f.mMaskedInterfaces.isNull())
    2334                     CHECK_ERROR_BREAK (flt, COMSETTER(MaskedInterfaces) (f.mMaskedInterfaces));
    2335 
    2336                 if (f.mAction != USBDeviceFilterAction_Null)
    2337                     CHECK_ERROR_BREAK (flt, COMSETTER(Action) (f.mAction));
    2338             }
    2339             else
    2340             {
    2341                 ComPtr <IUSBDeviceFilterCollection> coll;
    2342                 CHECK_ERROR_BREAK (ctl, COMGETTER(DeviceFilters) (coll.asOutParam()));
    2343 
    2344                 ComPtr <IUSBDeviceFilter> flt;
    2345                 CHECK_ERROR_BREAK (coll, GetItemAt (cmd.mIndex, flt.asOutParam()));
    2346 
    2347                 if (!f.mName.isNull())
    2348                     CHECK_ERROR_BREAK (flt, COMSETTER(Name) (f.mName.setNullIfEmpty()));
    2349                 if (!f.mActive.isNull())
    2350                     CHECK_ERROR_BREAK (flt, COMSETTER(Active) (f.mActive));
    2351                 if (!f.mVendorId.isNull())
    2352                     CHECK_ERROR_BREAK (flt, COMSETTER(VendorId) (f.mVendorId.setNullIfEmpty()));
    2353                 if (!f.mProductId.isNull())
    2354                     CHECK_ERROR_BREAK (flt, COMSETTER(ProductId) (f.mProductId.setNullIfEmpty()));
    2355                 if (!f.mRevision.isNull())
    2356                     CHECK_ERROR_BREAK (flt, COMSETTER(Revision) (f.mRevision.setNullIfEmpty()));
    2357                 if (!f.mManufacturer.isNull())
    2358                     CHECK_ERROR_BREAK (flt, COMSETTER(Manufacturer) (f.mManufacturer.setNullIfEmpty()));
    2359                 if (!f.mRemote.isNull())
    2360                     CHECK_ERROR_BREAK (flt, COMSETTER(Remote) (f.mRemote.setNullIfEmpty()));
    2361                 if (!f.mSerialNumber.isNull())
    2362                     CHECK_ERROR_BREAK (flt, COMSETTER(SerialNumber) (f.mSerialNumber.setNullIfEmpty()));
    2363                 if (!f.mMaskedInterfaces.isNull())
    2364                     CHECK_ERROR_BREAK (flt, COMSETTER(MaskedInterfaces) (f.mMaskedInterfaces));
    2365             }
    2366             break;
    2367         }
    2368         case USBFilterCmd::Remove:
    2369         {
    2370             if (cmd.mGlobal)
    2371             {
    2372                 ComPtr <IHostUSBDeviceFilter> flt;
    2373                 CHECK_ERROR_BREAK (host, RemoveUSBDeviceFilter (cmd.mIndex, flt.asOutParam()));
    2374             }
    2375             else
    2376             {
    2377                 ComPtr <IUSBDeviceFilter> flt;
    2378                 CHECK_ERROR_BREAK (ctl, RemoveDeviceFilter (cmd.mIndex, flt.asOutParam()));
    2379             }
    2380             break;
    2381         }
    2382         default:
    2383             break;
    2384     }
    2385 
    2386     if (cmd.mMachine)
    2387     {
    2388         /* commit and close the session */
    2389         CHECK_ERROR(cmd.mMachine, SaveSettings());
    2390         a->session->Close();
    2391     }
    2392 
    2393     return SUCCEEDED (rc) ? 0 : 1;
    2394 }
    2395 
    2396 static int handleSharedFolder (HandlerArg *a)
    2397 {
    2398     HRESULT rc;
    2399 
    2400     /* we need at least a command and target */
    2401     if (a->argc < 2)
    2402         return errorSyntax(USAGE_SHAREDFOLDER, "Not enough parameters");
    2403 
    2404     ComPtr<IMachine> machine;
    2405     /* assume it's a UUID */
    2406     rc = a->virtualBox->GetMachine(Guid(a->argv[1]), machine.asOutParam());
    2407     if (FAILED(rc) || !machine)
    2408     {
    2409         /* must be a name */
    2410         CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[1]), machine.asOutParam()));
    2411     }
    2412     if (!machine)
    2413         return 1;
    2414     Guid uuid;
    2415     machine->COMGETTER(Id)(uuid.asOutParam());
    2416 
    2417     if (strcmp(a->argv[0], "add") == 0)
    2418     {
    2419         /* we need at least four more parameters */
    2420         if (a->argc < 5)
    2421             return errorSyntax(USAGE_SHAREDFOLDER_ADD, "Not enough parameters");
    2422 
    2423         char *name = NULL;
    2424         char *hostpath = NULL;
    2425         bool fTransient = false;
    2426         bool fWritable = true;
    2427 
    2428         for (int i = 2; i < a->argc; i++)
    2429         {
    2430             if (strcmp(a->argv[i], "-name") == 0)
    2431             {
    2432                 if (a->argc <= i + 1 || !*a->argv[i+1])
    2433                     return errorArgument("Missing argument to '%s'", a->argv[i]);
    2434                 i++;
    2435                 name = a->argv[i];
    2436             }
    2437             else if (strcmp(a->argv[i], "-hostpath") == 0)
    2438             {
    2439                 if (a->argc <= i + 1 || !*a->argv[i+1])
    2440                     return errorArgument("Missing argument to '%s'", a->argv[i]);
    2441                 i++;
    2442                 hostpath = a->argv[i];
    2443             }
    2444             else if (strcmp(a->argv[i], "-readonly") == 0)
    2445             {
    2446                 fWritable = false;
    2447             }
    2448             else if (strcmp(a->argv[i], "-transient") == 0)
    2449             {
    2450                 fTransient = true;
    2451             }
    2452             else
    2453                 return errorSyntax(USAGE_SHAREDFOLDER_ADD, "Invalid parameter '%s'", Utf8Str(a->argv[i]).raw());
    2454         }
    2455 
    2456         if (NULL != strstr(name, " "))
    2457             return errorSyntax(USAGE_SHAREDFOLDER_ADD, "No spaces allowed in parameter '-name'!");
    2458 
    2459         /* required arguments */
    2460         if (!name || !hostpath)
    2461         {
    2462             return errorSyntax(USAGE_SHAREDFOLDER_ADD, "Parameters -name and -hostpath are required");
    2463         }
    2464 
    2465         if (fTransient)
    2466         {
    2467             ComPtr <IConsole> console;
    2468 
    2469             /* open an existing session for the VM */
    2470             CHECK_ERROR_RET(a->virtualBox, OpenExistingSession (a->session, uuid), 1);
    2471             /* get the session machine */
    2472             CHECK_ERROR_RET(a->session, COMGETTER(Machine)(machine.asOutParam()), 1);
    2473             /* get the session console */
    2474             CHECK_ERROR_RET(a->session, COMGETTER(Console)(console.asOutParam()), 1);
    2475 
    2476             CHECK_ERROR(console, CreateSharedFolder(Bstr(name), Bstr(hostpath), fWritable));
    2477 
    2478             if (console)
    2479                 a->session->Close();
    2480         }
    2481         else
    2482         {
    2483             /* open a session for the VM */
    2484             CHECK_ERROR_RET (a->virtualBox, OpenSession(a->session, uuid), 1);
    2485 
    2486             /* get the mutable session machine */
    2487             a->session->COMGETTER(Machine)(machine.asOutParam());
    2488 
    2489             CHECK_ERROR(machine, CreateSharedFolder(Bstr(name), Bstr(hostpath), fWritable));
    2490 
    2491             if (SUCCEEDED(rc))
    2492                 CHECK_ERROR(machine, SaveSettings());
    2493 
    2494             a->session->Close();
    2495         }
    2496     }
    2497     else if (strcmp(a->argv[0], "remove") == 0)
    2498     {
    2499         /* we need at least two more parameters */
    2500         if (a->argc < 3)
    2501             return errorSyntax(USAGE_SHAREDFOLDER_REMOVE, "Not enough parameters");
    2502 
    2503         char *name = NULL;
    2504         bool fTransient = false;
    2505 
    2506         for (int i = 2; i < a->argc; i++)
    2507         {
    2508             if (strcmp(a->argv[i], "-name") == 0)
    2509             {
    2510                 if (a->argc <= i + 1 || !*a->argv[i+1])
    2511                     return errorArgument("Missing argument to '%s'", a->argv[i]);
    2512                 i++;
    2513                 name = a->argv[i];
    2514             }
    2515             else if (strcmp(a->argv[i], "-transient") == 0)
    2516             {
    2517                 fTransient = true;
    2518             }
    2519             else
    2520                 return errorSyntax(USAGE_SHAREDFOLDER_REMOVE, "Invalid parameter '%s'", Utf8Str(a->argv[i]).raw());
    2521         }
    2522 
    2523         /* required arguments */
    2524         if (!name)
    2525             return errorSyntax(USAGE_SHAREDFOLDER_REMOVE, "Parameter -name is required");
    2526 
    2527         if (fTransient)
    2528         {
    2529             ComPtr <IConsole> console;
    2530 
    2531             /* open an existing session for the VM */
    2532             CHECK_ERROR_RET(a->virtualBox, OpenExistingSession (a->session, uuid), 1);
    2533             /* get the session machine */
    2534             CHECK_ERROR_RET(a->session, COMGETTER(Machine)(machine.asOutParam()), 1);
    2535             /* get the session console */
    2536             CHECK_ERROR_RET(a->session, COMGETTER(Console)(console.asOutParam()), 1);
    2537 
    2538             CHECK_ERROR(console, RemoveSharedFolder(Bstr(name)));
    2539 
    2540             if (console)
    2541                 a->session->Close();
    2542         }
    2543         else
    2544         {
    2545             /* open a session for the VM */
    2546             CHECK_ERROR_RET (a->virtualBox, OpenSession(a->session, uuid), 1);
    2547 
    2548             /* get the mutable session machine */
    2549             a->session->COMGETTER(Machine)(machine.asOutParam());
    2550 
    2551             CHECK_ERROR(machine, RemoveSharedFolder(Bstr(name)));
    2552 
    2553             /* commit and close the session */
    2554             CHECK_ERROR(machine, SaveSettings());
    2555             a->session->Close();
    2556         }
    2557     }
    2558     else
    2559         return errorSyntax(USAGE_SETPROPERTY, "Invalid parameter '%s'", Utf8Str(a->argv[0]).raw());
    2560 
    2561     return 0;
    2562 }
    2563 
    2564 static int handleVMStatistics(HandlerArg *a)
    2565 {
    2566     HRESULT rc;
    2567 
    2568     /* at least one option: the UUID or name of the VM */
    2569     if (a->argc < 1)
    2570         return errorSyntax(USAGE_VM_STATISTICS, "Incorrect number of parameters");
    2571 
    2572     /* try to find the given machine */
    2573     ComPtr <IMachine> machine;
    2574     Guid uuid (a->argv[0]);
    2575     if (!uuid.isEmpty())
    2576         CHECK_ERROR(a->virtualBox, GetMachine(uuid, machine.asOutParam()));
    2577     else
    2578     {
    2579         CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]), machine.asOutParam()));
    2580         if (SUCCEEDED (rc))
    2581             machine->COMGETTER(Id)(uuid.asOutParam());
    2582     }
    2583     if (FAILED(rc))
    2584         return 1;
    2585 
    2586     /* parse arguments. */
    2587     bool fReset = false;
    2588     bool fWithDescriptions = false;
    2589     const char *pszPattern = NULL; /* all */
    2590     for (int i = 1; i < a->argc; i++)
    2591     {
    2592         if (!strcmp(a->argv[i], "-pattern"))
    2593         {
    2594             if (pszPattern)
    2595                 return errorSyntax(USAGE_VM_STATISTICS, "Multiple -patterns options is not permitted");
    2596             if (i + 1 >= a->argc)
    2597                 return errorArgument("Missing argument to '%s'", a->argv[i]);
    2598             pszPattern = a->argv[++i];
    2599         }
    2600         else if (!strcmp(a->argv[i], "-descriptions"))
    2601             fWithDescriptions = true;
    2602         /* add: -file <filename> and -formatted */
    2603         else if (!strcmp(a->argv[i], "-reset"))
    2604             fReset = true;
    2605         else
    2606             return errorSyntax(USAGE_VM_STATISTICS, "Unknown option '%s'", a->argv[i]);
    2607     }
    2608     if (fReset && fWithDescriptions)
    2609         return errorSyntax(USAGE_VM_STATISTICS, "The -reset and -descriptions options does not mix");
    2610 
    2611 
    2612     /* open an existing session for the VM. */
    2613     CHECK_ERROR(a->virtualBox, OpenExistingSession(a->session, uuid));
    2614     if (SUCCEEDED(rc))
    2615     {
    2616         /* get the session console. */
    2617         ComPtr <IConsole> console;
    2618         CHECK_ERROR(a->session, COMGETTER(Console)(console.asOutParam()));
    2619         if (SUCCEEDED(rc))
    2620         {
    2621             /* get the machine debugger. */
    2622             ComPtr <IMachineDebugger> debugger;
    2623             CHECK_ERROR(console, COMGETTER(Debugger)(debugger.asOutParam()));
    2624             if (SUCCEEDED(rc))
    2625             {
    2626                 if (fReset)
    2627                     CHECK_ERROR(debugger, ResetStats(Bstr(pszPattern)));
    2628                 else
    2629                 {
    2630                     Bstr stats;
    2631                     CHECK_ERROR(debugger, GetStats(Bstr(pszPattern), fWithDescriptions, stats.asOutParam()));
    2632                     if (SUCCEEDED(rc))
    2633                     {
    2634                         /* if (fFormatted)
    2635                          { big mess }
    2636                          else
    2637                          */
    2638                         RTPrintf("%ls\n", stats.raw());
    2639                     }
    2640                 }
    2641             }
    2642             a->session->Close();
    2643         }
    2644     }
    2645 
    2646     return SUCCEEDED(rc) ? 0 : 1;
    2647 }
    2648287#endif /* !VBOX_ONLY_DOCS */
    2649 
    2650 enum ConvertSettings
    2651 {
    2652     ConvertSettings_No      = 0,
    2653     ConvertSettings_Yes     = 1,
    2654     ConvertSettings_Backup  = 2,
    2655     ConvertSettings_Ignore  = 3,
    2656 };
    2657 
    2658 #ifndef VBOX_ONLY_DOCS
    2659 /**
    2660  * Checks if any of the settings files were auto-converted and informs the
    2661  * user if so.
    2662  *
    2663  * @return @false if the program should terminate and @true otherwise.
    2664  */
    2665 static bool checkForAutoConvertedSettings (ComPtr<IVirtualBox> virtualBox,
    2666                                            ComPtr<ISession> session,
    2667                                            ConvertSettings fConvertSettings)
    2668 {
    2669     /* return early if nothing to do */
    2670     if (fConvertSettings == ConvertSettings_Ignore)
    2671         return true;
    2672 
    2673     HRESULT rc;
    2674 
    2675     do
    2676     {
    2677         Bstr formatVersion;
    2678         CHECK_ERROR_BREAK(virtualBox, COMGETTER(SettingsFormatVersion) (formatVersion.asOutParam()));
    2679 
    2680         bool isGlobalConverted = false;
    2681         std::list <ComPtr <IMachine> > cvtMachines;
    2682         std::list <Utf8Str> fileList;
    2683         Bstr version;
    2684         Bstr filePath;
    2685 
    2686         com::SafeIfaceArray <IMachine> machines;
    2687         CHECK_ERROR_BREAK(virtualBox, COMGETTER(Machines2) (ComSafeArrayAsOutParam (machines)));
    2688 
    2689         for (size_t i = 0; i < machines.size(); ++ i)
    2690         {
    2691             BOOL accessible;
    2692             CHECK_ERROR_BREAK(machines[i], COMGETTER(Accessible) (&accessible));
    2693             if (!accessible)
    2694                 continue;
    2695 
    2696             CHECK_ERROR_BREAK(machines[i], COMGETTER(SettingsFileVersion) (version.asOutParam()));
    2697 
    2698             if (version != formatVersion)
    2699             {
    2700                 cvtMachines.push_back (machines [i]);
    2701                 Bstr filePath;
    2702                 CHECK_ERROR_BREAK(machines[i], COMGETTER(SettingsFilePath) (filePath.asOutParam()));
    2703                 fileList.push_back (Utf8StrFmt ("%ls  (%ls)", filePath.raw(),
    2704                                                 version.raw()));
    2705             }
    2706         }
    2707 
    2708         if (FAILED(rc))
    2709             break;
    2710 
    2711         CHECK_ERROR_BREAK(virtualBox, COMGETTER(SettingsFileVersion) (version.asOutParam()));
    2712         if (version != formatVersion)
    2713         {
    2714             isGlobalConverted = true;
    2715             CHECK_ERROR_BREAK(virtualBox, COMGETTER(SettingsFilePath) (filePath.asOutParam()));
    2716             fileList.push_back (Utf8StrFmt ("%ls  (%ls)", filePath.raw(),
    2717                                             version.raw()));
    2718         }
    2719 
    2720         if (fileList.size() > 0)
    2721         {
    2722             switch (fConvertSettings)
    2723             {
    2724                 case ConvertSettings_No:
    2725                 {
    2726                     RTPrintf (
    2727 "WARNING! The following VirtualBox settings files have been automatically\n"
    2728 "converted to the new settings file format version '%ls':\n"
    2729 "\n",
    2730                               formatVersion.raw());
    2731 
    2732                     for (std::list <Utf8Str>::const_iterator f = fileList.begin();
    2733                          f != fileList.end(); ++ f)
    2734                         RTPrintf ("  %S\n", (*f).raw());
    2735                     RTPrintf (
    2736 "\n"
    2737 "The current command was aborted to prevent overwriting the above settings\n"
    2738 "files with the results of the auto-conversion without your permission.\n"
    2739 "Please put one of the following command line switches to the beginning of\n"
    2740 "the VBoxManage command line and repeat the command:\n"
    2741 "\n"
    2742 "  -convertSettings       - to save all auto-converted files (it will not\n"
    2743 "                           be possible to use these settings files with an\n"
    2744 "                           older version of VirtualBox in the future);\n"
    2745 "  -convertSettingsBackup - to create backup copies of the settings files in\n"
    2746 "                           the old format before saving them in the new format;\n"
    2747 "  -convertSettingsIgnore - to not save the auto-converted settings files.\n"
    2748 "\n"
    2749 "Note that if you use -convertSettingsIgnore, the auto-converted settings files\n"
    2750 "will be implicitly saved in the new format anyway once you change a setting or\n"
    2751 "start a virtual machine, but NO backup copies will be created in this case.\n");
    2752                     return false;
    2753                 }
    2754                 case ConvertSettings_Yes:
    2755                 case ConvertSettings_Backup:
    2756                 {
    2757                     break;
    2758                 }
    2759                 default:
    2760                     AssertFailedReturn (false);
    2761             }
    2762 
    2763             for (std::list <ComPtr <IMachine> >::const_iterator m = cvtMachines.begin();
    2764                  m != cvtMachines.end(); ++ m)
    2765             {
    2766                 Guid id;
    2767                 CHECK_ERROR_BREAK((*m), COMGETTER(Id) (id.asOutParam()));
    2768 
    2769                 /* open a session for the VM */
    2770                 CHECK_ERROR_BREAK (virtualBox, OpenSession (session, id));
    2771 
    2772                 ComPtr <IMachine> sm;
    2773                 CHECK_ERROR_BREAK(session, COMGETTER(Machine) (sm.asOutParam()));
    2774 
    2775                 Bstr bakFileName;
    2776                 if (fConvertSettings == ConvertSettings_Backup)
    2777                     CHECK_ERROR (sm, SaveSettingsWithBackup (bakFileName.asOutParam()));
    2778                 else
    2779                     CHECK_ERROR (sm, SaveSettings());
    2780 
    2781                 session->Close();
    2782 
    2783                 if (FAILED(rc))
    2784                     break;
    2785             }
    2786 
    2787             if (FAILED(rc))
    2788                 break;
    2789 
    2790             if (isGlobalConverted)
    2791             {
    2792                 Bstr bakFileName;
    2793                 if (fConvertSettings == ConvertSettings_Backup)
    2794                     CHECK_ERROR (virtualBox, SaveSettingsWithBackup (bakFileName.asOutParam()));
    2795                 else
    2796                     CHECK_ERROR (virtualBox, SaveSettings());
    2797             }
    2798 
    2799             if (FAILED(rc))
    2800                 break;
    2801         }
    2802     }
    2803     while (0);
    2804 
    2805     return SUCCEEDED (rc);
    2806 }
    2807 #endif /* !VBOX_ONLY_DOCS */
    2808 
    2809 // main
    2810 ///////////////////////////////////////////////////////////////////////////////
    2811 
    2812 int main(int argc, char *argv[])
    2813 {
    2814     /*
    2815      * Before we do anything, init the runtime without loading
    2816      * the support driver.
    2817      */
    2818     RTR3Init();
    2819 
    2820     bool fShowLogo = true;
    2821     int  iCmd      = 1;
    2822     int  iCmdArg;
    2823 
    2824     ConvertSettings fConvertSettings = ConvertSettings_No;
    2825 
    2826     /* global options */
    2827     for (int i = 1; i < argc || argc <= iCmd; i++)
    2828     {
    2829         if (    argc <= iCmd
    2830             ||  (strcmp(argv[i], "help")   == 0)
    2831             ||  (strcmp(argv[i], "-?")     == 0)
    2832             ||  (strcmp(argv[i], "-h")     == 0)
    2833             ||  (strcmp(argv[i], "-help")  == 0)
    2834             ||  (strcmp(argv[i], "--help") == 0))
    2835         {
    2836             showLogo();
    2837             printUsage(USAGE_ALL);
    2838             return 0;
    2839         }
    2840         else if (   strcmp(argv[i], "-v") == 0
    2841                  || strcmp(argv[i], "-version") == 0
    2842                  || strcmp(argv[i], "-Version") == 0
    2843                  || strcmp(argv[i], "--version") == 0)
    2844         {
    2845             /* Print version number, and do nothing else. */
    2846             RTPrintf("%sr%d\n", VBOX_VERSION_STRING, VBoxSVNRev ());
    2847             return 0;
    2848         }
    2849         else if (strcmp(argv[i], "-dumpopts") == 0)
    2850         {
    2851             /* Special option to dump really all commands,
    2852              * even the ones not understood on this platform. */
    2853             printUsage(USAGE_DUMPOPTS);
    2854             return 0;
    2855         }
    2856         else if (strcmp(argv[i], "-nologo") == 0)
    2857         {
    2858             /* suppress the logo */
    2859             fShowLogo = false;
    2860             iCmd++;
    2861         }
    2862         else if (strcmp(argv[i], "-convertSettings") == 0)
    2863         {
    2864             fConvertSettings = ConvertSettings_Yes;
    2865             iCmd++;
    2866         }
    2867         else if (strcmp(argv[i], "-convertSettingsBackup") == 0)
    2868         {
    2869             fConvertSettings = ConvertSettings_Backup;
    2870             iCmd++;
    2871         }
    2872         else if (strcmp(argv[i], "-convertSettingsIgnore") == 0)
    2873         {
    2874             fConvertSettings = ConvertSettings_Ignore;
    2875             iCmd++;
    2876         }
    2877         else
    2878         {
    2879             break;
    2880         }
    2881     }
    2882 
    2883     iCmdArg = iCmd + 1;
    2884 
    2885     if (fShowLogo)
    2886         showLogo();
    2887 
    2888 
    2889 #ifdef VBOX_ONLY_DOCS
    2890     int rc = 0;
    2891 #else /* !VBOX_ONLY_DOCS */
    2892     HRESULT rc = 0;
    2893 
    2894     rc = com::Initialize();
    2895     if (FAILED(rc))
    2896     {
    2897         RTPrintf("ERROR: failed to initialize COM!\n");
    2898         return rc;
    2899     }
    2900 
    2901     /*
    2902      * The input is in the host OS'es codepage (NT guarantees ACP).
    2903      * For VBox we use UTF-8 and convert to UCS-2 when calling (XP)COM APIs.
    2904      * For simplicity, just convert the argv[] array here.
    2905      */
    2906     for (int i = iCmdArg; i < argc; i++)
    2907     {
    2908         char *converted;
    2909         RTStrCurrentCPToUtf8(&converted, argv[i]);
    2910         argv[i] = converted;
    2911     }
    2912 
    2913     do
    2914     {
    2915     // scopes all the stuff till shutdown
    2916     ////////////////////////////////////////////////////////////////////////////
    2917 
    2918     /* convertfromraw: does not need a VirtualBox instantiation. */
    2919     if (argc >= iCmdArg && (   !strcmp(argv[iCmd], "convertfromraw")
    2920                             || !strcmp(argv[iCmd], "convertdd")))
    2921     {
    2922         rc = handleConvertFromRaw(argc - iCmdArg, argv + iCmdArg);
    2923         break;
    2924     }
    2925 
    2926     ComPtr<IVirtualBox> virtualBox;
    2927     ComPtr<ISession> session;
    2928 
    2929     rc = virtualBox.createLocalObject(CLSID_VirtualBox);
    2930     if (FAILED(rc))
    2931         RTPrintf("ERROR: failed to create the VirtualBox object!\n");
    2932     else
    2933     {
    2934         rc = session.createInprocObject(CLSID_Session);
    2935         if (FAILED(rc))
    2936             RTPrintf("ERROR: failed to create a session object!\n");
    2937     }
    2938 
    2939     if (FAILED(rc))
    2940     {
    2941         com::ErrorInfo info;
    2942         if (!info.isFullAvailable() && !info.isBasicAvailable())
    2943         {
    2944             com::GluePrintRCMessage(rc);
    2945             RTPrintf("Most likely, the VirtualBox COM server is not running or failed to start.\n");
    2946         }
    2947         else
    2948             GluePrintErrorInfo(info);
    2949         break;
    2950     }
    2951 
    2952     /* create the event queue
    2953      * (here it is necessary only to process remaining XPCOM/IPC events
    2954      * after the session is closed) */
    2955 
    2956 #ifdef USE_XPCOM_QUEUE
    2957     nsCOMPtr<nsIEventQueue> eventQ;
    2958     NS_GetMainEventQ(getter_AddRefs(eventQ));
    2959 #endif
    2960 
    2961     if (!checkForAutoConvertedSettings (virtualBox, session, fConvertSettings))
    2962         break;
    2963 
    2964 #ifdef USE_XPCOM_QUEUE
    2965     HandlerArg handlerArg = { 0, NULL, eventQ, virtualBox, session };
    2966 #else
    2967     HandlerArg handlerArg = { 0, NULL, virtualBox, session };
    2968 #endif
    2969 
    2970     /*
    2971      * All registered command handlers
    2972      */
    2973     struct
    2974     {
    2975         const char *command;
    2976         PFNHANDLER handler;
    2977     } commandHandlers[] =
    2978     {
    2979         { "internalcommands", handleInternalCommands },
    2980         { "list",             handleList },
    2981         { "showvminfo",       handleShowVMInfo },
    2982         { "registervm",       handleRegisterVM },
    2983         { "unregistervm",     handleUnregisterVM },
    2984         { "createhd",         handleCreateHardDisk },
    2985         { "createvdi",        handleCreateHardDisk }, /* backward compatiblity */
    2986         { "modifyhd",         handleModifyHardDisk },
    2987         { "modifyvdi",        handleModifyHardDisk }, /* backward compatiblity */
    2988         { "clonehd",          handleCloneHardDisk },
    2989         { "clonevdi",         handleCloneHardDisk }, /* backward compatiblity */
    2990         { "addiscsidisk",     handleAddiSCSIDisk },
    2991         { "createvm",         handleCreateVM },
    2992         { "modifyvm",         handleModifyVM },
    2993         { "startvm",          handleStartVM },
    2994         { "controlvm",        handleControlVM },
    2995         { "discardstate",     handleDiscardState },
    2996         { "adoptstate",       handleAdoptdState },
    2997         { "snapshot",         handleSnapshot },
    2998         { "openmedium",       handleOpenMedium },
    2999         { "registerimage",    handleOpenMedium }, /* backward compatiblity */
    3000         { "closemedium",      handleCloseMedium },
    3001         { "unregisterimage",  handleCloseMedium }, /* backward compatiblity */
    3002         { "showhdinfo",       handleShowHardDiskInfo },
    3003         { "showvdiinfo",      handleShowHardDiskInfo }, /* backward compatiblity */
    3004         { "getextradata",     handleGetExtraData },
    3005         { "setextradata",     handleSetExtraData },
    3006         { "setproperty",      handleSetProperty },
    3007         { "usbfilter",        handleUSBFilter },
    3008         { "sharedfolder",     handleSharedFolder },
    3009         { "vmstatistics",     handleVMStatistics },
    3010 #ifdef VBOX_WITH_GUEST_PROPS
    3011         { "guestproperty",    handleGuestProperty },
    3012 #endif /* VBOX_WITH_GUEST_PROPS defined */
    3013         { "metrics",          handleMetrics },
    3014         { "import",           handleImportAppliance },
    3015         { "export",           handleExportAppliance },
    3016         { NULL,               NULL }
    3017     };
    3018 
    3019     int commandIndex;
    3020     for (commandIndex = 0; commandHandlers[commandIndex].command != NULL; commandIndex++)
    3021     {
    3022         if (strcmp(commandHandlers[commandIndex].command, argv[iCmd]) == 0)
    3023         {
    3024             handlerArg.argc = argc - iCmdArg;
    3025             handlerArg.argv = &argv[iCmdArg];
    3026 
    3027             rc = commandHandlers[commandIndex].handler(&handlerArg);
    3028             break;
    3029         }
    3030     }
    3031     if (!commandHandlers[commandIndex].command)
    3032     {
    3033         rc = errorSyntax(USAGE_ALL, "Invalid command '%s'", Utf8Str(argv[iCmd]).raw());
    3034     }
    3035 
    3036     /* Although all handlers should always close the session if they open it,
    3037      * we do it here just in case if some of the handlers contains a bug --
    3038      * leaving the direct session not closed will turn the machine state to
    3039      * Aborted which may have unwanted side effects like killing the saved
    3040      * state file (if the machine was in the Saved state before). */
    3041     session->Close();
    3042 
    3043 #ifdef USE_XPCOM_QUEUE
    3044     eventQ->ProcessPendingEvents();
    3045 #endif
    3046 
    3047     // end "all-stuff" scope
    3048     ////////////////////////////////////////////////////////////////////////////
    3049     }
    3050     while (0);
    3051 
    3052     com::Shutdown();
    3053 #endif /* !VBOX_ONLY_DOCS */
    3054 
    3055     /*
    3056      * Free converted argument vector
    3057      */
    3058     for (int i = iCmdArg; i < argc; i++)
    3059         RTStrFree(argv[i]);
    3060 
    3061     return rc != 0;
    3062 }
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