VirtualBox

儲存庫 vbox 的更動 17104


忽略:
時間撮記:
2009-2-24 下午11:18:45 (16 年 以前)
作者:
vboxsync
訊息:

VBoxManage: split USB into separate file

位置:
trunk/src/VBox/Frontends/VBoxManage
檔案:
修改 4 筆資料
複製 1 筆資料

圖例:

未更動
新增
刪除
  • trunk/src/VBox/Frontends/VBoxManage/Makefile.kmk

    r17103 r17104  
    5353        VBoxManageDisk.cpp \
    5454        VBoxManageSnapshot.cpp \
     55        VBoxManageUSB.cpp \
    5556        VBoxInternalManage.cpp \
    5657        $(if $(VBOX_WITH_GUEST_PROPS),VBoxManageGuestProp.cpp) \
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManage.cpp

    r17103 r17104  
    6262using namespace com;
    6363
    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 
    7564/** command handler type */
    7665typedef int (*PFNHANDLER)(HandlerArg *a);
    7766
    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 };
    20967#endif /* !VBOX_ONLY_DOCS */
    21068
     
    12401098
    12411099    return SUCCEEDED(rc) ? 0 : 1;
    1242 }
    1243 
    1244 static int handleUSBFilter (HandlerArg *a)
    1245 {
    1246     HRESULT rc = S_OK;
    1247     USBFilterCmd cmd;
    1248 
    1249     /* at least: 0: command, 1: index, 2: -target, 3: <target value> */
    1250     if (a->argc < 4)
    1251         return errorSyntax(USAGE_USBFILTER, "Not enough parameters");
    1252 
    1253     /* which command? */
    1254     cmd.mAction = USBFilterCmd::Invalid;
    1255     if      (strcmp (a->argv [0], "add") == 0)     cmd.mAction = USBFilterCmd::Add;
    1256     else if (strcmp (a->argv [0], "modify") == 0)  cmd.mAction = USBFilterCmd::Modify;
    1257     else if (strcmp (a->argv [0], "remove") == 0)  cmd.mAction = USBFilterCmd::Remove;
    1258 
    1259     if (cmd.mAction == USBFilterCmd::Invalid)
    1260         return errorSyntax(USAGE_USBFILTER, "Invalid parameter '%s'", a->argv[0]);
    1261 
    1262     /* which index? */
    1263     if (VINF_SUCCESS !=  RTStrToUInt32Full (a->argv[1], 10, &cmd.mIndex))
    1264         return errorSyntax(USAGE_USBFILTER, "Invalid index '%s'", a->argv[1]);
    1265 
    1266     switch (cmd.mAction)
    1267     {
    1268         case USBFilterCmd::Add:
    1269         case USBFilterCmd::Modify:
    1270         {
    1271             /* at least: 0: command, 1: index, 2: -target, 3: <target value>, 4: -name, 5: <name value> */
    1272             if (a->argc < 6)
    1273             {
    1274                 if (cmd.mAction == USBFilterCmd::Add)
    1275                     return errorSyntax(USAGE_USBFILTER_ADD, "Not enough parameters");
    1276 
    1277                 return errorSyntax(USAGE_USBFILTER_MODIFY, "Not enough parameters");
    1278             }
    1279 
    1280             // set Active to true by default
    1281             // (assuming that the user sets up all necessary attributes
    1282             // at once and wants the filter to be active immediately)
    1283             if (cmd.mAction == USBFilterCmd::Add)
    1284                 cmd.mFilter.mActive = true;
    1285 
    1286             for (int i = 2; i < a->argc; i++)
    1287             {
    1288                 if  (strcmp(a->argv [i], "-target") == 0)
    1289                 {
    1290                     if (a->argc <= i + 1 || !*a->argv[i+1])
    1291                         return errorArgument("Missing argument to '%s'", a->argv[i]);
    1292                     i++;
    1293                     if (strcmp (a->argv [i], "global") == 0)
    1294                         cmd.mGlobal = true;
    1295                     else
    1296                     {
    1297                         /* assume it's a UUID of a machine */
    1298                         rc = a->virtualBox->GetMachine(Guid(a->argv[i]), cmd.mMachine.asOutParam());
    1299                         if (FAILED(rc) || !cmd.mMachine)
    1300                         {
    1301                             /* must be a name */
    1302                             CHECK_ERROR_RET(a->virtualBox, FindMachine(Bstr(a->argv[i]), cmd.mMachine.asOutParam()), 1);
    1303                         }
    1304                     }
    1305                 }
    1306                 else if (strcmp(a->argv [i], "-name") == 0)
    1307                 {
    1308                     if (a->argc <= i + 1 || !*a->argv[i+1])
    1309                         return errorArgument("Missing argument to '%s'", a->argv[i]);
    1310                     i++;
    1311                     cmd.mFilter.mName = a->argv [i];
    1312                 }
    1313                 else if (strcmp(a->argv [i], "-active") == 0)
    1314                 {
    1315                     if (a->argc <= i + 1)
    1316                         return errorArgument("Missing argument to '%s'", a->argv[i]);
    1317                     i++;
    1318                     if (strcmp (a->argv [i], "yes") == 0)
    1319                         cmd.mFilter.mActive = true;
    1320                     else if (strcmp (a->argv [i], "no") == 0)
    1321                         cmd.mFilter.mActive = false;
    1322                     else
    1323                         return errorArgument("Invalid -active argument '%s'", a->argv[i]);
    1324                 }
    1325                 else if (strcmp(a->argv [i], "-vendorid") == 0)
    1326                 {
    1327                     if (a->argc <= i + 1)
    1328                         return errorArgument("Missing argument to '%s'", a->argv[i]);
    1329                     i++;
    1330                     cmd.mFilter.mVendorId = a->argv [i];
    1331                 }
    1332                 else if (strcmp(a->argv [i], "-productid") == 0)
    1333                 {
    1334                     if (a->argc <= i + 1)
    1335                         return errorArgument("Missing argument to '%s'", a->argv[i]);
    1336                     i++;
    1337                     cmd.mFilter.mProductId = a->argv [i];
    1338                 }
    1339                 else if (strcmp(a->argv [i], "-revision") == 0)
    1340                 {
    1341                     if (a->argc <= i + 1)
    1342                         return errorArgument("Missing argument to '%s'", a->argv[i]);
    1343                     i++;
    1344                     cmd.mFilter.mRevision = a->argv [i];
    1345                 }
    1346                 else if (strcmp(a->argv [i], "-manufacturer") == 0)
    1347                 {
    1348                     if (a->argc <= i + 1)
    1349                         return errorArgument("Missing argument to '%s'", a->argv[i]);
    1350                     i++;
    1351                     cmd.mFilter.mManufacturer = a->argv [i];
    1352                 }
    1353                 else if (strcmp(a->argv [i], "-product") == 0)
    1354                 {
    1355                     if (a->argc <= i + 1)
    1356                         return errorArgument("Missing argument to '%s'", a->argv[i]);
    1357                     i++;
    1358                     cmd.mFilter.mProduct = a->argv [i];
    1359                 }
    1360                 else if (strcmp(a->argv [i], "-remote") == 0)
    1361                 {
    1362                     if (a->argc <= i + 1)
    1363                         return errorArgument("Missing argument to '%s'", a->argv[i]);
    1364                     i++;
    1365                     cmd.mFilter.mRemote = a->argv[i];
    1366                 }
    1367                 else if (strcmp(a->argv [i], "-serialnumber") == 0)
    1368                 {
    1369                     if (a->argc <= i + 1)
    1370                         return errorArgument("Missing argument to '%s'", a->argv[i]);
    1371                     i++;
    1372                     cmd.mFilter.mSerialNumber = a->argv [i];
    1373                 }
    1374                 else if (strcmp(a->argv [i], "-maskedinterfaces") == 0)
    1375                 {
    1376                     if (a->argc <= i + 1)
    1377                         return errorArgument("Missing argument to '%s'", a->argv[i]);
    1378                     i++;
    1379                     uint32_t u32;
    1380                     rc = RTStrToUInt32Full(a->argv[i], 0, &u32);
    1381                     if (RT_FAILURE(rc))
    1382                         return errorArgument("Failed to convert the -maskedinterfaces value '%s' to a number, rc=%Rrc", a->argv[i], rc);
    1383                     cmd.mFilter.mMaskedInterfaces = u32;
    1384                 }
    1385                 else if (strcmp(a->argv [i], "-action") == 0)
    1386                 {
    1387                     if (a->argc <= i + 1)
    1388                         return errorArgument("Missing argument to '%s'", a->argv[i]);
    1389                     i++;
    1390                     if (strcmp (a->argv [i], "ignore") == 0)
    1391                         cmd.mFilter.mAction = USBDeviceFilterAction_Ignore;
    1392                     else if (strcmp (a->argv [i], "hold") == 0)
    1393                         cmd.mFilter.mAction = USBDeviceFilterAction_Hold;
    1394                     else
    1395                         return errorArgument("Invalid USB filter action '%s'", a->argv[i]);
    1396                 }
    1397                 else
    1398                     return errorSyntax(cmd.mAction == USBFilterCmd::Add ? USAGE_USBFILTER_ADD : USAGE_USBFILTER_MODIFY,
    1399                                        "Unknown option '%s'", a->argv[i]);
    1400             }
    1401 
    1402             if (cmd.mAction == USBFilterCmd::Add)
    1403             {
    1404                 // mandatory/forbidden options
    1405                 if (   cmd.mFilter.mName.isEmpty()
    1406                     ||
    1407                        (   cmd.mGlobal
    1408                         && cmd.mFilter.mAction == USBDeviceFilterAction_Null
    1409                        )
    1410                     || (   !cmd.mGlobal
    1411                         && !cmd.mMachine)
    1412                     || (   cmd.mGlobal
    1413                         && cmd.mFilter.mRemote)
    1414                    )
    1415                 {
    1416                     return errorSyntax(USAGE_USBFILTER_ADD, "Mandatory options not supplied");
    1417                 }
    1418             }
    1419             break;
    1420         }
    1421 
    1422         case USBFilterCmd::Remove:
    1423         {
    1424             /* at least: 0: command, 1: index, 2: -target, 3: <target value> */
    1425             if (a->argc < 4)
    1426                 return errorSyntax(USAGE_USBFILTER_REMOVE, "Not enough parameters");
    1427 
    1428             for (int i = 2; i < a->argc; i++)
    1429             {
    1430                 if  (strcmp(a->argv [i], "-target") == 0)
    1431                 {
    1432                     if (a->argc <= i + 1 || !*a->argv[i+1])
    1433                         return errorArgument("Missing argument to '%s'", a->argv[i]);
    1434                     i++;
    1435                     if (strcmp (a->argv [i], "global") == 0)
    1436                         cmd.mGlobal = true;
    1437                     else
    1438                     {
    1439                         /* assume it's a UUID of a machine */
    1440                         rc = a->virtualBox->GetMachine(Guid(a->argv[i]), cmd.mMachine.asOutParam());
    1441                         if (FAILED(rc) || !cmd.mMachine)
    1442                         {
    1443                             /* must be a name */
    1444                             CHECK_ERROR_RET(a->virtualBox, FindMachine(Bstr(a->argv[i]), cmd.mMachine.asOutParam()), 1);
    1445                         }
    1446                     }
    1447                 }
    1448             }
    1449 
    1450             // mandatory options
    1451             if (!cmd.mGlobal && !cmd.mMachine)
    1452                 return errorSyntax(USAGE_USBFILTER_REMOVE, "Mandatory options not supplied");
    1453 
    1454             break;
    1455         }
    1456 
    1457         default: break;
    1458     }
    1459 
    1460     USBFilterCmd::USBFilter &f = cmd.mFilter;
    1461 
    1462     ComPtr <IHost> host;
    1463     ComPtr <IUSBController> ctl;
    1464     if (cmd.mGlobal)
    1465         CHECK_ERROR_RET (a->virtualBox, COMGETTER(Host) (host.asOutParam()), 1);
    1466     else
    1467     {
    1468         Guid uuid;
    1469         cmd.mMachine->COMGETTER(Id)(uuid.asOutParam());
    1470         /* open a session for the VM */
    1471         CHECK_ERROR_RET (a->virtualBox, OpenSession(a->session, uuid), 1);
    1472         /* get the mutable session machine */
    1473         a->session->COMGETTER(Machine)(cmd.mMachine.asOutParam());
    1474         /* and get the USB controller */
    1475         CHECK_ERROR_RET (cmd.mMachine, COMGETTER(USBController) (ctl.asOutParam()), 1);
    1476     }
    1477 
    1478     switch (cmd.mAction)
    1479     {
    1480         case USBFilterCmd::Add:
    1481         {
    1482             if (cmd.mGlobal)
    1483             {
    1484                 ComPtr <IHostUSBDeviceFilter> flt;
    1485                 CHECK_ERROR_BREAK (host, CreateUSBDeviceFilter (f.mName, flt.asOutParam()));
    1486 
    1487                 if (!f.mActive.isNull())
    1488                     CHECK_ERROR_BREAK (flt, COMSETTER(Active) (f.mActive));
    1489                 if (!f.mVendorId.isNull())
    1490                     CHECK_ERROR_BREAK (flt, COMSETTER(VendorId) (f.mVendorId.setNullIfEmpty()));
    1491                 if (!f.mProductId.isNull())
    1492                     CHECK_ERROR_BREAK (flt, COMSETTER(ProductId) (f.mProductId.setNullIfEmpty()));
    1493                 if (!f.mRevision.isNull())
    1494                     CHECK_ERROR_BREAK (flt, COMSETTER(Revision) (f.mRevision.setNullIfEmpty()));
    1495                 if (!f.mManufacturer.isNull())
    1496                     CHECK_ERROR_BREAK (flt, COMSETTER(Manufacturer) (f.mManufacturer.setNullIfEmpty()));
    1497                 if (!f.mSerialNumber.isNull())
    1498                     CHECK_ERROR_BREAK (flt, COMSETTER(SerialNumber) (f.mSerialNumber.setNullIfEmpty()));
    1499                 if (!f.mMaskedInterfaces.isNull())
    1500                     CHECK_ERROR_BREAK (flt, COMSETTER(MaskedInterfaces) (f.mMaskedInterfaces));
    1501 
    1502                 if (f.mAction != USBDeviceFilterAction_Null)
    1503                     CHECK_ERROR_BREAK (flt, COMSETTER(Action) (f.mAction));
    1504 
    1505                 CHECK_ERROR_BREAK (host, InsertUSBDeviceFilter (cmd.mIndex, flt));
    1506             }
    1507             else
    1508             {
    1509                 ComPtr <IUSBDeviceFilter> flt;
    1510                 CHECK_ERROR_BREAK (ctl, CreateDeviceFilter (f.mName, flt.asOutParam()));
    1511 
    1512                 if (!f.mActive.isNull())
    1513                     CHECK_ERROR_BREAK (flt, COMSETTER(Active) (f.mActive));
    1514                 if (!f.mVendorId.isNull())
    1515                     CHECK_ERROR_BREAK (flt, COMSETTER(VendorId) (f.mVendorId.setNullIfEmpty()));
    1516                 if (!f.mProductId.isNull())
    1517                     CHECK_ERROR_BREAK (flt, COMSETTER(ProductId) (f.mProductId.setNullIfEmpty()));
    1518                 if (!f.mRevision.isNull())
    1519                     CHECK_ERROR_BREAK (flt, COMSETTER(Revision) (f.mRevision.setNullIfEmpty()));
    1520                 if (!f.mManufacturer.isNull())
    1521                     CHECK_ERROR_BREAK (flt, COMSETTER(Manufacturer) (f.mManufacturer.setNullIfEmpty()));
    1522                 if (!f.mRemote.isNull())
    1523                     CHECK_ERROR_BREAK (flt, COMSETTER(Remote) (f.mRemote.setNullIfEmpty()));
    1524                 if (!f.mSerialNumber.isNull())
    1525                     CHECK_ERROR_BREAK (flt, COMSETTER(SerialNumber) (f.mSerialNumber.setNullIfEmpty()));
    1526                 if (!f.mMaskedInterfaces.isNull())
    1527                     CHECK_ERROR_BREAK (flt, COMSETTER(MaskedInterfaces) (f.mMaskedInterfaces));
    1528 
    1529                 CHECK_ERROR_BREAK (ctl, InsertDeviceFilter (cmd.mIndex, flt));
    1530             }
    1531             break;
    1532         }
    1533         case USBFilterCmd::Modify:
    1534         {
    1535             if (cmd.mGlobal)
    1536             {
    1537                 ComPtr <IHostUSBDeviceFilterCollection> coll;
    1538                 CHECK_ERROR_BREAK (host, COMGETTER(USBDeviceFilters) (coll.asOutParam()));
    1539                 ComPtr <IHostUSBDeviceFilter> flt;
    1540                 CHECK_ERROR_BREAK (coll, GetItemAt (cmd.mIndex, flt.asOutParam()));
    1541 
    1542                 if (!f.mName.isNull())
    1543                     CHECK_ERROR_BREAK (flt, COMSETTER(Name) (f.mName.setNullIfEmpty()));
    1544                 if (!f.mActive.isNull())
    1545                     CHECK_ERROR_BREAK (flt, COMSETTER(Active) (f.mActive));
    1546                 if (!f.mVendorId.isNull())
    1547                     CHECK_ERROR_BREAK (flt, COMSETTER(VendorId) (f.mVendorId.setNullIfEmpty()));
    1548                 if (!f.mProductId.isNull())
    1549                     CHECK_ERROR_BREAK (flt, COMSETTER(ProductId) (f.mProductId.setNullIfEmpty()));
    1550                 if (!f.mRevision.isNull())
    1551                     CHECK_ERROR_BREAK (flt, COMSETTER(Revision) (f.mRevision.setNullIfEmpty()));
    1552                 if (!f.mManufacturer.isNull())
    1553                     CHECK_ERROR_BREAK (flt, COMSETTER(Manufacturer) (f.mManufacturer.setNullIfEmpty()));
    1554                 if (!f.mSerialNumber.isNull())
    1555                     CHECK_ERROR_BREAK (flt, COMSETTER(SerialNumber) (f.mSerialNumber.setNullIfEmpty()));
    1556                 if (!f.mMaskedInterfaces.isNull())
    1557                     CHECK_ERROR_BREAK (flt, COMSETTER(MaskedInterfaces) (f.mMaskedInterfaces));
    1558 
    1559                 if (f.mAction != USBDeviceFilterAction_Null)
    1560                     CHECK_ERROR_BREAK (flt, COMSETTER(Action) (f.mAction));
    1561             }
    1562             else
    1563             {
    1564                 ComPtr <IUSBDeviceFilterCollection> coll;
    1565                 CHECK_ERROR_BREAK (ctl, COMGETTER(DeviceFilters) (coll.asOutParam()));
    1566 
    1567                 ComPtr <IUSBDeviceFilter> flt;
    1568                 CHECK_ERROR_BREAK (coll, GetItemAt (cmd.mIndex, flt.asOutParam()));
    1569 
    1570                 if (!f.mName.isNull())
    1571                     CHECK_ERROR_BREAK (flt, COMSETTER(Name) (f.mName.setNullIfEmpty()));
    1572                 if (!f.mActive.isNull())
    1573                     CHECK_ERROR_BREAK (flt, COMSETTER(Active) (f.mActive));
    1574                 if (!f.mVendorId.isNull())
    1575                     CHECK_ERROR_BREAK (flt, COMSETTER(VendorId) (f.mVendorId.setNullIfEmpty()));
    1576                 if (!f.mProductId.isNull())
    1577                     CHECK_ERROR_BREAK (flt, COMSETTER(ProductId) (f.mProductId.setNullIfEmpty()));
    1578                 if (!f.mRevision.isNull())
    1579                     CHECK_ERROR_BREAK (flt, COMSETTER(Revision) (f.mRevision.setNullIfEmpty()));
    1580                 if (!f.mManufacturer.isNull())
    1581                     CHECK_ERROR_BREAK (flt, COMSETTER(Manufacturer) (f.mManufacturer.setNullIfEmpty()));
    1582                 if (!f.mRemote.isNull())
    1583                     CHECK_ERROR_BREAK (flt, COMSETTER(Remote) (f.mRemote.setNullIfEmpty()));
    1584                 if (!f.mSerialNumber.isNull())
    1585                     CHECK_ERROR_BREAK (flt, COMSETTER(SerialNumber) (f.mSerialNumber.setNullIfEmpty()));
    1586                 if (!f.mMaskedInterfaces.isNull())
    1587                     CHECK_ERROR_BREAK (flt, COMSETTER(MaskedInterfaces) (f.mMaskedInterfaces));
    1588             }
    1589             break;
    1590         }
    1591         case USBFilterCmd::Remove:
    1592         {
    1593             if (cmd.mGlobal)
    1594             {
    1595                 ComPtr <IHostUSBDeviceFilter> flt;
    1596                 CHECK_ERROR_BREAK (host, RemoveUSBDeviceFilter (cmd.mIndex, flt.asOutParam()));
    1597             }
    1598             else
    1599             {
    1600                 ComPtr <IUSBDeviceFilter> flt;
    1601                 CHECK_ERROR_BREAK (ctl, RemoveDeviceFilter (cmd.mIndex, flt.asOutParam()));
    1602             }
    1603             break;
    1604         }
    1605         default:
    1606             break;
    1607     }
    1608 
    1609     if (cmd.mMachine)
    1610     {
    1611         /* commit and close the session */
    1612         CHECK_ERROR(cmd.mMachine, SaveSettings());
    1613         a->session->Close();
    1614     }
    1615 
    1616     return SUCCEEDED (rc) ? 0 : 1;
    16171100}
    16181101
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManage.h

    r17103 r17104  
    186186
    187187/* VBoxManageUSB.cpp */
    188 /* VBoxManageTODO.cpp */
     188int handleUSBFilter(HandlerArg *a);
    189189
    190190#endif /* !VBOX_ONLY_DOCS */
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManageSnapshot.cpp

    r17102 r17104  
    2020 */
    2121
    22 #ifndef VBOX_ONLY_DOCS
    23 
    2422/*******************************************************************************
    2523*   Header Files                                                               *
     
    285283}
    286284
    287 #endif /* !VBOX_ONLY_DOCS */
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManageUSB.cpp

    r17103 r17104  
    2020 */
    2121
    22 
    23 /*******************************************************************************
    24 *   Header Files                                                               *
    25 *******************************************************************************/
    26 #ifndef VBOX_ONLY_DOCS
    2722#include <VBox/com/com.h>
    2823#include <VBox/com/string.h>
     
    3530#include <VBox/com/VirtualBox.h>
    3631
    37 #include <vector>
    38 #include <list>
    39 #endif /* !VBOX_ONLY_DOCS */
     32#include "VBoxManage.h"
    4033
    4134#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>
    51 #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>
    58 
    59 #include "VBoxManage.h"
    60 
    61 #ifndef VBOX_ONLY_DOCS
    62 using namespace com;
    6335
    6436/* missing XPCOM <-> COM wrappers */
     
    7345#endif
    7446
    75 /** command handler type */
    76 typedef int (*PFNHANDLER)(HandlerArg *a);
     47using namespace com;
    7748
    7849/**
     
    207178    USBFilter mFilter;
    208179};
    209 #endif /* !VBOX_ONLY_DOCS */
    210 
    211 // funcs
    212 ///////////////////////////////////////////////////////////////////////////////
    213 
    214 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 #ifndef VBOX_ONLY_DOCS
    230 
    231 static int handleRegisterVM(HandlerArg *a)
    232 {
    233     HRESULT rc;
    234 
    235     if (a->argc != 1)
    236         return errorSyntax(USAGE_REGISTERVM, "Incorrect number of parameters");
    237 
    238     ComPtr<IMachine> machine;
    239     CHECK_ERROR(a->virtualBox, OpenMachine(Bstr(a->argv[0]), machine.asOutParam()));
    240     if (SUCCEEDED(rc))
    241     {
    242         ASSERT(machine);
    243         CHECK_ERROR(a->virtualBox, RegisterMachine(machine));
    244     }
    245     return SUCCEEDED(rc) ? 0 : 1;
    246 }
    247 
    248 static int handleUnregisterVM(HandlerArg *a)
    249 {
    250     HRESULT rc;
    251 
    252     if ((a->argc != 1) && (a->argc != 2))
    253         return errorSyntax(USAGE_UNREGISTERVM, "Incorrect number of parameters");
    254 
    255     ComPtr<IMachine> machine;
    256     /* assume it's a UUID */
    257     rc = a->virtualBox->GetMachine(Guid(a->argv[0]), machine.asOutParam());
    258     if (FAILED(rc) || !machine)
    259     {
    260         /* must be a name */
    261         CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]), machine.asOutParam()));
    262     }
    263     if (machine)
    264     {
    265         Guid uuid;
    266         machine->COMGETTER(Id)(uuid.asOutParam());
    267         machine = NULL;
    268         CHECK_ERROR(a->virtualBox, UnregisterMachine(uuid, machine.asOutParam()));
    269         if (SUCCEEDED(rc) && machine)
    270         {
    271             /* are we supposed to delete the config file? */
    272             if ((a->argc == 2) && (strcmp(a->argv[1], "-delete") == 0))
    273             {
    274                 CHECK_ERROR(machine, DeleteSettings());
    275             }
    276         }
    277     }
    278     return SUCCEEDED(rc) ? 0 : 1;
    279 }
    280 
    281 static int handleCreateVM(HandlerArg *a)
    282 {
    283     HRESULT rc;
    284     Bstr baseFolder;
    285     Bstr settingsFile;
    286     Bstr name;
    287     Bstr osTypeId;
    288     RTUUID id;
    289     bool fRegister = false;
    290 
    291     RTUuidClear(&id);
    292     for (int i = 0; i < a->argc; i++)
    293     {
    294         if (strcmp(a->argv[i], "-basefolder") == 0)
    295         {
    296             if (a->argc <= i + 1)
    297                 return errorArgument("Missing argument to '%s'", a->argv[i]);
    298             i++;
    299             baseFolder = a->argv[i];
    300         }
    301         else if (strcmp(a->argv[i], "-settingsfile") == 0)
    302         {
    303             if (a->argc <= i + 1)
    304                 return errorArgument("Missing argument to '%s'", a->argv[i]);
    305             i++;
    306             settingsFile = a->argv[i];
    307         }
    308         else if (strcmp(a->argv[i], "-name") == 0)
    309         {
    310             if (a->argc <= i + 1)
    311                 return errorArgument("Missing argument to '%s'", a->argv[i]);
    312             i++;
    313             name = a->argv[i];
    314         }
    315         else if (strcmp(a->argv[i], "-ostype") == 0)
    316         {
    317             if (a->argc <= i + 1)
    318                 return errorArgument("Missing argument to '%s'", a->argv[i]);
    319             i++;
    320             osTypeId = a->argv[i];
    321         }
    322         else if (strcmp(a->argv[i], "-uuid") == 0)
    323         {
    324             if (a->argc <= i + 1)
    325                 return errorArgument("Missing argument to '%s'", a->argv[i]);
    326             i++;
    327             if (RT_FAILURE(RTUuidFromStr(&id, a->argv[i])))
    328                 return errorArgument("Invalid UUID format %s\n", a->argv[i]);
    329         }
    330         else if (strcmp(a->argv[i], "-register") == 0)
    331         {
    332             fRegister = true;
    333         }
    334         else
    335             return errorSyntax(USAGE_CREATEVM, "Invalid parameter '%s'", Utf8Str(a->argv[i]).raw());
    336     }
    337     if (!name)
    338         return errorSyntax(USAGE_CREATEVM, "Parameter -name is required");
    339 
    340     if (!!baseFolder && !!settingsFile)
    341         return errorSyntax(USAGE_CREATEVM, "Either -basefolder or -settingsfile must be specified");
    342 
    343     do
    344     {
    345         ComPtr<IMachine> machine;
    346 
    347         if (!settingsFile)
    348             CHECK_ERROR_BREAK(a->virtualBox,
    349                 CreateMachine(name, osTypeId, baseFolder, Guid(id), machine.asOutParam()));
    350         else
    351             CHECK_ERROR_BREAK(a->virtualBox,
    352                 CreateLegacyMachine(name, osTypeId, settingsFile, Guid(id), machine.asOutParam()));
    353 
    354         CHECK_ERROR_BREAK(machine, SaveSettings());
    355         if (fRegister)
    356         {
    357             CHECK_ERROR_BREAK(a->virtualBox, RegisterMachine(machine));
    358         }
    359         Guid uuid;
    360         CHECK_ERROR_BREAK(machine, COMGETTER(Id)(uuid.asOutParam()));
    361         CHECK_ERROR_BREAK(machine, COMGETTER(SettingsFilePath)(settingsFile.asOutParam()));
    362         RTPrintf("Virtual machine '%ls' is created%s.\n"
    363                  "UUID: %s\n"
    364                  "Settings file: '%ls'\n",
    365                  name.raw(), fRegister ? " and registered" : "",
    366                  uuid.toString().raw(), settingsFile.raw());
    367     }
    368     while (0);
    369 
    370     return SUCCEEDED(rc) ? 0 : 1;
    371 }
    372 
    373 /**
    374  * Parses a number.
    375  *
    376  * @returns Valid number on success.
    377  * @returns 0 if invalid number. All necesary bitching has been done.
    378  * @param   psz     Pointer to the nic number.
    379  */
    380 unsigned parseNum(const char *psz, unsigned cMaxNum, const char *name)
    381 {
    382     uint32_t u32;
    383     char *pszNext;
    384     int rc = RTStrToUInt32Ex(psz, &pszNext, 10, &u32);
    385     if (    RT_SUCCESS(rc)
    386         &&  *pszNext == '\0'
    387         &&  u32 >= 1
    388         &&  u32 <= cMaxNum)
    389         return (unsigned)u32;
    390     errorArgument("Invalid %s number '%s'", name, psz);
    391     return 0;
    392 }
    393 
    394 
    395 /** @todo refine this after HDD changes; MSC 8.0/64 has trouble with handleModifyVM.  */
    396 #if defined(_MSC_VER)
    397 # pragma optimize("", on)
    398 #endif
    399 
    400 static int handleStartVM(HandlerArg *a)
    401 {
    402     HRESULT rc;
    403 
    404     if (a->argc < 1)
    405         return errorSyntax(USAGE_STARTVM, "Not enough parameters");
    406 
    407     ComPtr<IMachine> machine;
    408     /* assume it's a UUID */
    409     rc = a->virtualBox->GetMachine(Guid(a->argv[0]), machine.asOutParam());
    410     if (FAILED(rc) || !machine)
    411     {
    412         /* must be a name */
    413         CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]), machine.asOutParam()));
    414     }
    415     if (machine)
    416     {
    417         Guid uuid;
    418         machine->COMGETTER(Id)(uuid.asOutParam());
    419 
    420         /* default to GUI session type */
    421         Bstr sessionType = "gui";
    422         /* has a session type been specified? */
    423         if ((a->argc > 2) && (strcmp(a->argv[1], "-type") == 0))
    424         {
    425             if (strcmp(a->argv[2], "gui") == 0)
    426             {
    427                 sessionType = "gui";
    428             }
    429             else if (strcmp(a->argv[2], "vrdp") == 0)
    430             {
    431                 sessionType = "vrdp";
    432             }
    433             else if (strcmp(a->argv[2], "capture") == 0)
    434             {
    435                 sessionType = "capture";
    436             }
    437             else
    438                 return errorArgument("Invalid session type argument '%s'", a->argv[2]);
    439         }
    440 
    441         Bstr env;
    442 #ifdef RT_OS_LINUX
    443         /* make sure the VM process will start on the same display as VBoxManage */
    444         {
    445             const char *display = RTEnvGet ("DISPLAY");
    446             if (display)
    447                 env = Utf8StrFmt ("DISPLAY=%s", display);
    448         }
    449 #endif
    450         ComPtr<IProgress> progress;
    451         CHECK_ERROR_RET(a->virtualBox, OpenRemoteSession(a->session, uuid, sessionType,
    452                                                          env, progress.asOutParam()), rc);
    453         RTPrintf("Waiting for the remote session to open...\n");
    454         CHECK_ERROR_RET(progress, WaitForCompletion (-1), 1);
    455 
    456         BOOL completed;
    457         CHECK_ERROR_RET(progress, COMGETTER(Completed)(&completed), rc);
    458         ASSERT(completed);
    459 
    460         HRESULT resultCode;
    461         CHECK_ERROR_RET(progress, COMGETTER(ResultCode)(&resultCode), rc);
    462         if (FAILED(resultCode))
    463         {
    464             ComPtr <IVirtualBoxErrorInfo> errorInfo;
    465             CHECK_ERROR_RET(progress, COMGETTER(ErrorInfo)(errorInfo.asOutParam()), 1);
    466             ErrorInfo info (errorInfo);
    467             GluePrintErrorInfo(info);
    468         }
    469         else
    470         {
    471             RTPrintf("Remote session has been successfully opened.\n");
    472         }
    473     }
    474 
    475     /* it's important to always close sessions */
    476     a->session->Close();
    477 
    478     return SUCCEEDED(rc) ? 0 : 1;
    479 }
    480 
    481 static int handleControlVM(HandlerArg *a)
    482 {
    483     HRESULT rc;
    484 
    485     if (a->argc < 2)
    486         return errorSyntax(USAGE_CONTROLVM, "Not enough parameters");
    487 
    488     /* try to find the given machine */
    489     ComPtr <IMachine> machine;
    490     Guid uuid (a->argv[0]);
    491     if (!uuid.isEmpty())
    492     {
    493         CHECK_ERROR (a->virtualBox, GetMachine (uuid, machine.asOutParam()));
    494     }
    495     else
    496     {
    497         CHECK_ERROR (a->virtualBox, FindMachine (Bstr(a->argv[0]), machine.asOutParam()));
    498         if (SUCCEEDED (rc))
    499             machine->COMGETTER(Id) (uuid.asOutParam());
    500     }
    501     if (FAILED (rc))
    502         return 1;
    503 
    504     /* open a session for the VM */
    505     CHECK_ERROR_RET (a->virtualBox, OpenExistingSession (a->session, uuid), 1);
    506 
    507     do
    508     {
    509         /* get the associated console */
    510         ComPtr<IConsole> console;
    511         CHECK_ERROR_BREAK (a->session, COMGETTER(Console)(console.asOutParam()));
    512         /* ... and session machine */
    513         ComPtr<IMachine> sessionMachine;
    514         CHECK_ERROR_BREAK (a->session, COMGETTER(Machine)(sessionMachine.asOutParam()));
    515 
    516         /* which command? */
    517         if (strcmp(a->argv[1], "pause") == 0)
    518         {
    519             CHECK_ERROR_BREAK (console, Pause());
    520         }
    521         else if (strcmp(a->argv[1], "resume") == 0)
    522         {
    523             CHECK_ERROR_BREAK (console, Resume());
    524         }
    525         else if (strcmp(a->argv[1], "reset") == 0)
    526         {
    527             CHECK_ERROR_BREAK (console, Reset());
    528         }
    529         else if (strcmp(a->argv[1], "poweroff") == 0)
    530         {
    531             CHECK_ERROR_BREAK (console, PowerDown());
    532         }
    533         else if (strcmp(a->argv[1], "savestate") == 0)
    534         {
    535             ComPtr<IProgress> progress;
    536             CHECK_ERROR_BREAK (console, SaveState(progress.asOutParam()));
    537 
    538             showProgress(progress);
    539 
    540             progress->COMGETTER(ResultCode)(&rc);
    541             if (FAILED(rc))
    542             {
    543                 com::ProgressErrorInfo info(progress);
    544                 if (info.isBasicAvailable())
    545                 {
    546                     RTPrintf("Error: failed to save machine state. Error message: %lS\n", info.getText().raw());
    547                 }
    548                 else
    549                 {
    550                     RTPrintf("Error: failed to save machine state. No error message available!\n");
    551                 }
    552             }
    553         }
    554         else if (strcmp(a->argv[1], "acpipowerbutton") == 0)
    555         {
    556             CHECK_ERROR_BREAK (console, PowerButton());
    557         }
    558         else if (strcmp(a->argv[1], "acpisleepbutton") == 0)
    559         {
    560             CHECK_ERROR_BREAK (console, SleepButton());
    561         }
    562         else if (strcmp(a->argv[1], "injectnmi") == 0)
    563         {
    564             /* get the machine debugger. */
    565             ComPtr <IMachineDebugger> debugger;
    566             CHECK_ERROR_BREAK(console, COMGETTER(Debugger)(debugger.asOutParam()));
    567             CHECK_ERROR_BREAK(debugger, InjectNMI());
    568         }
    569         else if (strcmp(a->argv[1], "keyboardputscancode") == 0)
    570         {
    571             ComPtr<IKeyboard> keyboard;
    572             CHECK_ERROR_BREAK(console, COMGETTER(Keyboard)(keyboard.asOutParam()));
    573 
    574             if (a->argc <= 1 + 1)
    575             {
    576                 errorArgument("Missing argument to '%s'. Expected IBM PC AT set 2 keyboard scancode(s) as hex byte(s).", a->argv[1]);
    577                 rc = E_FAIL;
    578                 break;
    579             }
    580 
    581             /* Arbitrary restrict the length of a sequence of scancodes to 1024. */
    582             LONG alScancodes[1024];
    583             int cScancodes = 0;
    584 
    585             /* Process the command line. */
    586             int i;
    587             for (i = 1 + 1; i < a->argc && cScancodes < (int)RT_ELEMENTS(alScancodes); i++, cScancodes++)
    588             {
    589                 if (   RT_C_IS_XDIGIT (a->argv[i][0])
    590                     && RT_C_IS_XDIGIT (a->argv[i][1])
    591                     && a->argv[i][2] == 0)
    592                 {
    593                     uint8_t u8Scancode;
    594                     int rc = RTStrToUInt8Ex(a->argv[i], NULL, 16, &u8Scancode);
    595                     if (RT_FAILURE (rc))
    596                     {
    597                         RTPrintf("Error: converting '%s' returned %Rrc!\n", a->argv[i], rc);
    598                         rc = E_FAIL;
    599                         break;
    600                     }
    601 
    602                     alScancodes[cScancodes] = u8Scancode;
    603                 }
    604                 else
    605                 {
    606                     RTPrintf("Error: '%s' is not a hex byte!\n", a->argv[i]);
    607                     rc = E_FAIL;
    608                     break;
    609                 }
    610             }
    611 
    612             if (FAILED(rc))
    613                 break;
    614 
    615             if (   cScancodes == RT_ELEMENTS(alScancodes)
    616                 && i < a->argc)
    617             {
    618                 RTPrintf("Error: too many scancodes, maximum %d allowed!\n", RT_ELEMENTS(alScancodes));
    619                 rc = E_FAIL;
    620                 break;
    621             }
    622 
    623             /* Send scancodes to the VM.
    624              * Note: 'PutScancodes' did not work here. Only the first scancode was transmitted.
    625              */
    626             for (i = 0; i < cScancodes; i++)
    627             {
    628                 CHECK_ERROR_BREAK(keyboard, PutScancode(alScancodes[i]));
    629                 RTPrintf("Scancode[%d]: 0x%02X\n", i, alScancodes[i]);
    630             }
    631         }
    632         else if (strncmp(a->argv[1], "setlinkstate", 12) == 0)
    633         {
    634             /* Get the number of network adapters */
    635             ULONG NetworkAdapterCount = 0;
    636             ComPtr <ISystemProperties> info;
    637             CHECK_ERROR_BREAK (a->virtualBox, COMGETTER(SystemProperties) (info.asOutParam()));
    638             CHECK_ERROR_BREAK (info, COMGETTER(NetworkAdapterCount) (&NetworkAdapterCount));
    639 
    640             unsigned n = parseNum(&a->argv[1][12], NetworkAdapterCount, "NIC");
    641             if (!n)
    642             {
    643                 rc = E_FAIL;
    644                 break;
    645             }
    646             if (a->argc <= 1 + 1)
    647             {
    648                 errorArgument("Missing argument to '%s'", a->argv[1]);
    649                 rc = E_FAIL;
    650                 break;
    651             }
    652             /* get the corresponding network adapter */
    653             ComPtr<INetworkAdapter> adapter;
    654             CHECK_ERROR_BREAK (sessionMachine, GetNetworkAdapter(n - 1, adapter.asOutParam()));
    655             if (adapter)
    656             {
    657                 if (strcmp(a->argv[2], "on") == 0)
    658                 {
    659                     CHECK_ERROR_BREAK (adapter, COMSETTER(CableConnected)(TRUE));
    660                 }
    661                 else if (strcmp(a->argv[2], "off") == 0)
    662                 {
    663                     CHECK_ERROR_BREAK (adapter, COMSETTER(CableConnected)(FALSE));
    664                 }
    665                 else
    666                 {
    667                     errorArgument("Invalid link state '%s'", Utf8Str(a->argv[2]).raw());
    668                     rc = E_FAIL;
    669                     break;
    670                 }
    671             }
    672         }
    673 #ifdef VBOX_WITH_VRDP
    674         else if (strcmp(a->argv[1], "vrdp") == 0)
    675         {
    676             if (a->argc <= 1 + 1)
    677             {
    678                 errorArgument("Missing argument to '%s'", a->argv[1]);
    679                 rc = E_FAIL;
    680                 break;
    681             }
    682             /* get the corresponding VRDP server */
    683             ComPtr<IVRDPServer> vrdpServer;
    684             sessionMachine->COMGETTER(VRDPServer)(vrdpServer.asOutParam());
    685             ASSERT(vrdpServer);
    686             if (vrdpServer)
    687             {
    688                 if (strcmp(a->argv[2], "on") == 0)
    689                 {
    690                     CHECK_ERROR_BREAK (vrdpServer, COMSETTER(Enabled)(TRUE));
    691                 }
    692                 else if (strcmp(a->argv[2], "off") == 0)
    693                 {
    694                     CHECK_ERROR_BREAK (vrdpServer, COMSETTER(Enabled)(FALSE));
    695                 }
    696                 else
    697                 {
    698                     errorArgument("Invalid vrdp server state '%s'", Utf8Str(a->argv[2]).raw());
    699                     rc = E_FAIL;
    700                     break;
    701                 }
    702             }
    703         }
    704 #endif /* VBOX_WITH_VRDP */
    705         else if (strcmp (a->argv[1], "usbattach") == 0 ||
    706                  strcmp (a->argv[1], "usbdetach") == 0)
    707         {
    708             if (a->argc < 3)
    709             {
    710                 errorSyntax(USAGE_CONTROLVM, "Not enough parameters");
    711                 rc = E_FAIL;
    712                 break;
    713             }
    714 
    715             bool attach = strcmp (a->argv[1], "usbattach") == 0;
    716 
    717             Guid usbId = a->argv [2];
    718             if (usbId.isEmpty())
    719             {
    720                 // assume address
    721                 if (attach)
    722                 {
    723                     ComPtr <IHost> host;
    724                     CHECK_ERROR_BREAK (a->virtualBox, COMGETTER(Host) (host.asOutParam()));
    725                     ComPtr <IHostUSBDeviceCollection> coll;
    726                     CHECK_ERROR_BREAK (host, COMGETTER(USBDevices) (coll.asOutParam()));
    727                     ComPtr <IHostUSBDevice> dev;
    728                     CHECK_ERROR_BREAK (coll, FindByAddress (Bstr (a->argv [2]), dev.asOutParam()));
    729                     CHECK_ERROR_BREAK (dev, COMGETTER(Id) (usbId.asOutParam()));
    730                 }
    731                 else
    732                 {
    733                     ComPtr <IUSBDeviceCollection> coll;
    734                     CHECK_ERROR_BREAK (console, COMGETTER(USBDevices)(coll.asOutParam()));
    735                     ComPtr <IUSBDevice> dev;
    736                     CHECK_ERROR_BREAK (coll, FindByAddress (Bstr (a->argv [2]), dev.asOutParam()));
    737                     CHECK_ERROR_BREAK (dev, COMGETTER(Id) (usbId.asOutParam()));
    738                 }
    739             }
    740 
    741             if (attach)
    742                 CHECK_ERROR_BREAK (console, AttachUSBDevice (usbId));
    743             else
    744             {
    745                 ComPtr <IUSBDevice> dev;
    746                 CHECK_ERROR_BREAK (console, DetachUSBDevice (usbId, dev.asOutParam()));
    747             }
    748         }
    749         else if (strcmp(a->argv[1], "setvideomodehint") == 0)
    750         {
    751             if (a->argc != 5 && a->argc != 6)
    752             {
    753                 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
    754                 rc = E_FAIL;
    755                 break;
    756             }
    757             uint32_t xres = RTStrToUInt32(a->argv[2]);
    758             uint32_t yres = RTStrToUInt32(a->argv[3]);
    759             uint32_t bpp  = RTStrToUInt32(a->argv[4]);
    760             uint32_t displayIdx = 0;
    761             if (a->argc == 6)
    762                 displayIdx = RTStrToUInt32(a->argv[5]);
    763 
    764             ComPtr<IDisplay> display;
    765             CHECK_ERROR_BREAK(console, COMGETTER(Display)(display.asOutParam()));
    766             CHECK_ERROR_BREAK(display, SetVideoModeHint(xres, yres, bpp, displayIdx));
    767         }
    768         else if (strcmp(a->argv[1], "setcredentials") == 0)
    769         {
    770             bool fAllowLocalLogon = true;
    771             if (a->argc == 7)
    772             {
    773                 if (strcmp(a->argv[5], "-allowlocallogon") != 0)
    774                 {
    775                     errorArgument("Invalid parameter '%s'", a->argv[5]);
    776                     rc = E_FAIL;
    777                     break;
    778                 }
    779                 if (strcmp(a->argv[6], "no") == 0)
    780                     fAllowLocalLogon = false;
    781             }
    782             else if (a->argc != 5)
    783             {
    784                 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
    785                 rc = E_FAIL;
    786                 break;
    787             }
    788 
    789             ComPtr<IGuest> guest;
    790             CHECK_ERROR_BREAK(console, COMGETTER(Guest)(guest.asOutParam()));
    791             CHECK_ERROR_BREAK(guest, SetCredentials(Bstr(a->argv[2]), Bstr(a->argv[3]), Bstr(a->argv[4]), fAllowLocalLogon));
    792         }
    793         else if (strcmp(a->argv[1], "dvdattach") == 0)
    794         {
    795             if (a->argc != 3)
    796             {
    797                 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
    798                 rc = E_FAIL;
    799                 break;
    800             }
    801             ComPtr<IDVDDrive> dvdDrive;
    802             sessionMachine->COMGETTER(DVDDrive)(dvdDrive.asOutParam());
    803             ASSERT(dvdDrive);
    804 
    805             /* unmount? */
    806             if (strcmp(a->argv[2], "none") == 0)
    807             {
    808                 CHECK_ERROR(dvdDrive, Unmount());
    809             }
    810             /* host drive? */
    811             else if (strncmp(a->argv[2], "host:", 5) == 0)
    812             {
    813                 ComPtr<IHost> host;
    814                 CHECK_ERROR(a->virtualBox, COMGETTER(Host)(host.asOutParam()));
    815                 ComPtr<IHostDVDDriveCollection> hostDVDs;
    816                 CHECK_ERROR(host, COMGETTER(DVDDrives)(hostDVDs.asOutParam()));
    817                 ComPtr<IHostDVDDrive> hostDVDDrive;
    818                 rc = hostDVDs->FindByName(Bstr(a->argv[2] + 5), hostDVDDrive.asOutParam());
    819                 if (!hostDVDDrive)
    820                 {
    821                     errorArgument("Invalid host DVD drive name");
    822                     rc = E_FAIL;
    823                     break;
    824                 }
    825                 CHECK_ERROR(dvdDrive, CaptureHostDrive(hostDVDDrive));
    826             }
    827             else
    828             {
    829                 /* first assume it's a UUID */
    830                 Guid uuid(a->argv[2]);
    831                 ComPtr<IDVDImage> dvdImage;
    832                 rc = a->virtualBox->GetDVDImage(uuid, dvdImage.asOutParam());
    833                 if (FAILED(rc) || !dvdImage)
    834                 {
    835                     /* must be a filename, check if it's in the collection */
    836                     rc = a->virtualBox->FindDVDImage(Bstr(a->argv[2]), dvdImage.asOutParam());
    837                     /* not registered, do that on the fly */
    838                     if (!dvdImage)
    839                     {
    840                         Guid emptyUUID;
    841                         CHECK_ERROR(a->virtualBox, OpenDVDImage(Bstr(a->argv[2]), emptyUUID, dvdImage.asOutParam()));
    842                     }
    843                 }
    844                 if (!dvdImage)
    845                 {
    846                     rc = E_FAIL;
    847                     break;
    848                 }
    849                 dvdImage->COMGETTER(Id)(uuid.asOutParam());
    850                 CHECK_ERROR(dvdDrive, MountImage(uuid));
    851             }
    852         }
    853         else if (strcmp(a->argv[1], "floppyattach") == 0)
    854         {
    855             if (a->argc != 3)
    856             {
    857                 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
    858                 rc = E_FAIL;
    859                 break;
    860             }
    861 
    862             ComPtr<IFloppyDrive> floppyDrive;
    863             sessionMachine->COMGETTER(FloppyDrive)(floppyDrive.asOutParam());
    864             ASSERT(floppyDrive);
    865 
    866             /* unmount? */
    867             if (strcmp(a->argv[2], "none") == 0)
    868             {
    869                 CHECK_ERROR(floppyDrive, Unmount());
    870             }
    871             /* host drive? */
    872             else if (strncmp(a->argv[2], "host:", 5) == 0)
    873             {
    874                 ComPtr<IHost> host;
    875                 CHECK_ERROR(a->virtualBox, COMGETTER(Host)(host.asOutParam()));
    876                 ComPtr<IHostFloppyDriveCollection> hostFloppies;
    877                 CHECK_ERROR(host, COMGETTER(FloppyDrives)(hostFloppies.asOutParam()));
    878                 ComPtr<IHostFloppyDrive> hostFloppyDrive;
    879                 rc = hostFloppies->FindByName(Bstr(a->argv[2] + 5), hostFloppyDrive.asOutParam());
    880                 if (!hostFloppyDrive)
    881                 {
    882                     errorArgument("Invalid host floppy drive name");
    883                     rc = E_FAIL;
    884                     break;
    885                 }
    886                 CHECK_ERROR(floppyDrive, CaptureHostDrive(hostFloppyDrive));
    887             }
    888             else
    889             {
    890                 /* first assume it's a UUID */
    891                 Guid uuid(a->argv[2]);
    892                 ComPtr<IFloppyImage> floppyImage;
    893                 rc = a->virtualBox->GetFloppyImage(uuid, floppyImage.asOutParam());
    894                 if (FAILED(rc) || !floppyImage)
    895                 {
    896                     /* must be a filename, check if it's in the collection */
    897                     rc = a->virtualBox->FindFloppyImage(Bstr(a->argv[2]), floppyImage.asOutParam());
    898                     /* not registered, do that on the fly */
    899                     if (!floppyImage)
    900                     {
    901                         Guid emptyUUID;
    902                         CHECK_ERROR(a->virtualBox, OpenFloppyImage(Bstr(a->argv[2]), emptyUUID, floppyImage.asOutParam()));
    903                     }
    904                 }
    905                 if (!floppyImage)
    906                 {
    907                     rc = E_FAIL;
    908                     break;
    909                 }
    910                 floppyImage->COMGETTER(Id)(uuid.asOutParam());
    911                 CHECK_ERROR(floppyDrive, MountImage(uuid));
    912             }
    913         }
    914 #ifdef VBOX_WITH_MEM_BALLOONING
    915         else if (strncmp(a->argv[1], "-guestmemoryballoon", 19) == 0)
    916         {
    917             if (a->argc != 3)
    918             {
    919                 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
    920                 rc = E_FAIL;
    921                 break;
    922             }
    923             uint32_t uVal;
    924             int vrc;
    925             vrc = RTStrToUInt32Ex(a->argv[2], NULL, 0, &uVal);
    926             if (vrc != VINF_SUCCESS)
    927             {
    928                 errorArgument("Error parsing guest memory balloon size '%s'", a->argv[2]);
    929                 rc = E_FAIL;
    930                 break;
    931             }
    932 
    933             /* guest is running; update IGuest */
    934             ComPtr <IGuest> guest;
    935 
    936             rc = console->COMGETTER(Guest)(guest.asOutParam());
    937             if (SUCCEEDED(rc))
    938                 CHECK_ERROR(guest, COMSETTER(MemoryBalloonSize)(uVal));
    939         }
    940 #endif
    941         else if (strncmp(a->argv[1], "-gueststatisticsinterval", 24) == 0)
    942         {
    943             if (a->argc != 3)
    944             {
    945                 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
    946                 rc = E_FAIL;
    947                 break;
    948             }
    949             uint32_t uVal;
    950             int vrc;
    951             vrc = RTStrToUInt32Ex(a->argv[2], NULL, 0, &uVal);
    952             if (vrc != VINF_SUCCESS)
    953             {
    954                 errorArgument("Error parsing guest statistics interval '%s'", a->argv[2]);
    955                 rc = E_FAIL;
    956                 break;
    957             }
    958 
    959             /* guest is running; update IGuest */
    960             ComPtr <IGuest> guest;
    961 
    962             rc = console->COMGETTER(Guest)(guest.asOutParam());
    963             if (SUCCEEDED(rc))
    964                 CHECK_ERROR(guest, COMSETTER(StatisticsUpdateInterval)(uVal));
    965         }
    966         else
    967         {
    968             errorSyntax(USAGE_CONTROLVM, "Invalid parameter '%s'", Utf8Str(a->argv[1]).raw());
    969             rc = E_FAIL;
    970         }
    971     }
    972     while (0);
    973 
    974     a->session->Close();
    975 
    976     return SUCCEEDED (rc) ? 0 : 1;
    977 }
    978 
    979 static int handleDiscardState(HandlerArg *a)
    980 {
    981     HRESULT rc;
    982 
    983     if (a->argc != 1)
    984         return errorSyntax(USAGE_DISCARDSTATE, "Incorrect number of parameters");
    985 
    986     ComPtr<IMachine> machine;
    987     /* assume it's a UUID */
    988     rc = a->virtualBox->GetMachine(Guid(a->argv[0]), machine.asOutParam());
    989     if (FAILED(rc) || !machine)
    990     {
    991         /* must be a name */
    992         CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]), machine.asOutParam()));
    993     }
    994     if (machine)
    995     {
    996         do
    997         {
    998             /* we have to open a session for this task */
    999             Guid guid;
    1000             machine->COMGETTER(Id)(guid.asOutParam());
    1001             CHECK_ERROR_BREAK(a->virtualBox, OpenSession(a->session, guid));
    1002             do
    1003             {
    1004                 ComPtr<IConsole> console;
    1005                 CHECK_ERROR_BREAK(a->session, COMGETTER(Console)(console.asOutParam()));
    1006                 CHECK_ERROR_BREAK(console, DiscardSavedState());
    1007             }
    1008             while (0);
    1009             CHECK_ERROR_BREAK(a->session, Close());
    1010         }
    1011         while (0);
    1012     }
    1013 
    1014     return SUCCEEDED(rc) ? 0 : 1;
    1015 }
    1016 
    1017 static int handleAdoptdState(HandlerArg *a)
    1018 {
    1019     HRESULT rc;
    1020 
    1021     if (a->argc != 2)
    1022         return errorSyntax(USAGE_ADOPTSTATE, "Incorrect number of parameters");
    1023 
    1024     ComPtr<IMachine> machine;
    1025     /* assume it's a UUID */
    1026     rc = a->virtualBox->GetMachine(Guid(a->argv[0]), machine.asOutParam());
    1027     if (FAILED(rc) || !machine)
    1028     {
    1029         /* must be a name */
    1030         CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]), machine.asOutParam()));
    1031     }
    1032     if (machine)
    1033     {
    1034         do
    1035         {
    1036             /* we have to open a session for this task */
    1037             Guid guid;
    1038             machine->COMGETTER(Id)(guid.asOutParam());
    1039             CHECK_ERROR_BREAK(a->virtualBox, OpenSession(a->session, guid));
    1040             do
    1041             {
    1042                 ComPtr<IConsole> console;
    1043                 CHECK_ERROR_BREAK(a->session, COMGETTER(Console)(console.asOutParam()));
    1044                 CHECK_ERROR_BREAK(console, AdoptSavedState (Bstr (a->argv[1])));
    1045             }
    1046             while (0);
    1047             CHECK_ERROR_BREAK(a->session, Close());
    1048         }
    1049         while (0);
    1050     }
    1051 
    1052     return SUCCEEDED(rc) ? 0 : 1;
    1053 }
    1054 
    1055 static int handleGetExtraData(HandlerArg *a)
    1056 {
    1057     HRESULT rc = S_OK;
    1058 
    1059     if (a->argc != 2)
    1060         return errorSyntax(USAGE_GETEXTRADATA, "Incorrect number of parameters");
    1061 
    1062     /* global data? */
    1063     if (strcmp(a->argv[0], "global") == 0)
    1064     {
    1065         /* enumeration? */
    1066         if (strcmp(a->argv[1], "enumerate") == 0)
    1067         {
    1068             Bstr extraDataKey;
    1069 
    1070             do
    1071             {
    1072                 Bstr nextExtraDataKey;
    1073                 Bstr nextExtraDataValue;
    1074                 HRESULT rcEnum = a->virtualBox->GetNextExtraDataKey(extraDataKey, nextExtraDataKey.asOutParam(),
    1075                                                                     nextExtraDataValue.asOutParam());
    1076                 extraDataKey = nextExtraDataKey;
    1077 
    1078                 if (SUCCEEDED(rcEnum) && extraDataKey)
    1079                     RTPrintf("Key: %lS, Value: %lS\n", nextExtraDataKey.raw(), nextExtraDataValue.raw());
    1080             } while (extraDataKey);
    1081         }
    1082         else
    1083         {
    1084             Bstr value;
    1085             CHECK_ERROR(a->virtualBox, GetExtraData(Bstr(a->argv[1]), value.asOutParam()));
    1086             if (value)
    1087                 RTPrintf("Value: %lS\n", value.raw());
    1088             else
    1089                 RTPrintf("No value set!\n");
    1090         }
    1091     }
    1092     else
    1093     {
    1094         ComPtr<IMachine> machine;
    1095         /* assume it's a UUID */
    1096         rc = a->virtualBox->GetMachine(Guid(a->argv[0]), machine.asOutParam());
    1097         if (FAILED(rc) || !machine)
    1098         {
    1099             /* must be a name */
    1100             CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]), machine.asOutParam()));
    1101         }
    1102         if (machine)
    1103         {
    1104             /* enumeration? */
    1105             if (strcmp(a->argv[1], "enumerate") == 0)
    1106             {
    1107                 Bstr extraDataKey;
    1108 
    1109                 do
    1110                 {
    1111                     Bstr nextExtraDataKey;
    1112                     Bstr nextExtraDataValue;
    1113                     HRESULT rcEnum = machine->GetNextExtraDataKey(extraDataKey, nextExtraDataKey.asOutParam(),
    1114                                                                   nextExtraDataValue.asOutParam());
    1115                     extraDataKey = nextExtraDataKey;
    1116 
    1117                     if (SUCCEEDED(rcEnum) && extraDataKey)
    1118                     {
    1119                         RTPrintf("Key: %lS, Value: %lS\n", nextExtraDataKey.raw(), nextExtraDataValue.raw());
    1120                     }
    1121                 } while (extraDataKey);
    1122             }
    1123             else
    1124             {
    1125                 Bstr value;
    1126                 CHECK_ERROR(machine, GetExtraData(Bstr(a->argv[1]), value.asOutParam()));
    1127                 if (value)
    1128                     RTPrintf("Value: %lS\n", value.raw());
    1129                 else
    1130                     RTPrintf("No value set!\n");
    1131             }
    1132         }
    1133     }
    1134     return SUCCEEDED(rc) ? 0 : 1;
    1135 }
    1136 
    1137 static int handleSetExtraData(HandlerArg *a)
    1138 {
    1139     HRESULT rc = S_OK;
    1140 
    1141     if (a->argc < 2)
    1142         return errorSyntax(USAGE_SETEXTRADATA, "Not enough parameters");
    1143 
    1144     /* global data? */
    1145     if (strcmp(a->argv[0], "global") == 0)
    1146     {
    1147         if (a->argc < 3)
    1148             CHECK_ERROR(a->virtualBox, SetExtraData(Bstr(a->argv[1]), NULL));
    1149         else if (a->argc == 3)
    1150             CHECK_ERROR(a->virtualBox, SetExtraData(Bstr(a->argv[1]), Bstr(a->argv[2])));
    1151         else
    1152             return errorSyntax(USAGE_SETEXTRADATA, "Too many parameters");
    1153     }
    1154     else
    1155     {
    1156         ComPtr<IMachine> machine;
    1157         /* assume it's a UUID */
    1158         rc = a->virtualBox->GetMachine(Guid(a->argv[0]), machine.asOutParam());
    1159         if (FAILED(rc) || !machine)
    1160         {
    1161             /* must be a name */
    1162             CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]), machine.asOutParam()));
    1163         }
    1164         if (machine)
    1165         {
    1166             if (a->argc < 3)
    1167                 CHECK_ERROR(machine, SetExtraData(Bstr(a->argv[1]), NULL));
    1168             else if (a->argc == 3)
    1169                 CHECK_ERROR(machine, SetExtraData(Bstr(a->argv[1]), Bstr(a->argv[2])));
    1170             else
    1171                 return errorSyntax(USAGE_SETEXTRADATA, "Too many parameters");
    1172         }
    1173     }
    1174     return SUCCEEDED(rc) ? 0 : 1;
    1175 }
    1176 
    1177 static int handleSetProperty(HandlerArg *a)
    1178 {
    1179     HRESULT rc;
    1180 
    1181     /* there must be two arguments: property name and value */
    1182     if (a->argc != 2)
    1183         return errorSyntax(USAGE_SETPROPERTY, "Incorrect number of parameters");
    1184 
    1185     ComPtr<ISystemProperties> systemProperties;
    1186     a->virtualBox->COMGETTER(SystemProperties)(systemProperties.asOutParam());
    1187 
    1188     if (strcmp(a->argv[0], "hdfolder") == 0)
    1189     {
    1190         /* reset to default? */
    1191         if (strcmp(a->argv[1], "default") == 0)
    1192             CHECK_ERROR(systemProperties, COMSETTER(DefaultHardDiskFolder)(NULL));
    1193         else
    1194             CHECK_ERROR(systemProperties, COMSETTER(DefaultHardDiskFolder)(Bstr(a->argv[1])));
    1195     }
    1196     else if (strcmp(a->argv[0], "machinefolder") == 0)
    1197     {
    1198         /* reset to default? */
    1199         if (strcmp(a->argv[1], "default") == 0)
    1200             CHECK_ERROR(systemProperties, COMSETTER(DefaultMachineFolder)(NULL));
    1201         else
    1202             CHECK_ERROR(systemProperties, COMSETTER(DefaultMachineFolder)(Bstr(a->argv[1])));
    1203     }
    1204     else if (strcmp(a->argv[0], "vrdpauthlibrary") == 0)
    1205     {
    1206         /* reset to default? */
    1207         if (strcmp(a->argv[1], "default") == 0)
    1208             CHECK_ERROR(systemProperties, COMSETTER(RemoteDisplayAuthLibrary)(NULL));
    1209         else
    1210             CHECK_ERROR(systemProperties, COMSETTER(RemoteDisplayAuthLibrary)(Bstr(a->argv[1])));
    1211     }
    1212     else if (strcmp(a->argv[0], "websrvauthlibrary") == 0)
    1213     {
    1214         /* reset to default? */
    1215         if (strcmp(a->argv[1], "default") == 0)
    1216             CHECK_ERROR(systemProperties, COMSETTER(WebServiceAuthLibrary)(NULL));
    1217         else
    1218             CHECK_ERROR(systemProperties, COMSETTER(WebServiceAuthLibrary)(Bstr(a->argv[1])));
    1219     }
    1220     else if (strcmp(a->argv[0], "hwvirtexenabled") == 0)
    1221     {
    1222         if (strcmp(a->argv[1], "yes") == 0)
    1223             CHECK_ERROR(systemProperties, COMSETTER(HWVirtExEnabled)(TRUE));
    1224         else if (strcmp(a->argv[1], "no") == 0)
    1225             CHECK_ERROR(systemProperties, COMSETTER(HWVirtExEnabled)(FALSE));
    1226         else
    1227             return errorArgument("Invalid value '%s' for hardware virtualization extension flag", a->argv[1]);
    1228     }
    1229     else if (strcmp(a->argv[0], "loghistorycount") == 0)
    1230     {
    1231         uint32_t uVal;
    1232         int vrc;
    1233         vrc = RTStrToUInt32Ex(a->argv[1], NULL, 0, &uVal);
    1234         if (vrc != VINF_SUCCESS)
    1235             return errorArgument("Error parsing Log history count '%s'", a->argv[1]);
    1236         CHECK_ERROR(systemProperties, COMSETTER(LogHistoryCount)(uVal));
    1237     }
    1238     else
    1239         return errorSyntax(USAGE_SETPROPERTY, "Invalid parameter '%s'", a->argv[0]);
    1240 
    1241     return SUCCEEDED(rc) ? 0 : 1;
    1242 }
    1243 
    1244 static int handleUSBFilter (HandlerArg *a)
     180
     181int handleUSBFilter (HandlerArg *a)
    1245182{
    1246183    HRESULT rc = S_OK;
     
    1617554}
    1618555
    1619 static int handleSharedFolder (HandlerArg *a)
    1620 {
    1621     HRESULT rc;
    1622 
    1623     /* we need at least a command and target */
    1624     if (a->argc < 2)
    1625         return errorSyntax(USAGE_SHAREDFOLDER, "Not enough parameters");
    1626 
    1627     ComPtr<IMachine> machine;
    1628     /* assume it's a UUID */
    1629     rc = a->virtualBox->GetMachine(Guid(a->argv[1]), machine.asOutParam());
    1630     if (FAILED(rc) || !machine)
    1631     {
    1632         /* must be a name */
    1633         CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[1]), machine.asOutParam()));
    1634     }
    1635     if (!machine)
    1636         return 1;
    1637     Guid uuid;
    1638     machine->COMGETTER(Id)(uuid.asOutParam());
    1639 
    1640     if (strcmp(a->argv[0], "add") == 0)
    1641     {
    1642         /* we need at least four more parameters */
    1643         if (a->argc < 5)
    1644             return errorSyntax(USAGE_SHAREDFOLDER_ADD, "Not enough parameters");
    1645 
    1646         char *name = NULL;
    1647         char *hostpath = NULL;
    1648         bool fTransient = false;
    1649         bool fWritable = true;
    1650 
    1651         for (int i = 2; i < a->argc; i++)
    1652         {
    1653             if (strcmp(a->argv[i], "-name") == 0)
    1654             {
    1655                 if (a->argc <= i + 1 || !*a->argv[i+1])
    1656                     return errorArgument("Missing argument to '%s'", a->argv[i]);
    1657                 i++;
    1658                 name = a->argv[i];
    1659             }
    1660             else if (strcmp(a->argv[i], "-hostpath") == 0)
    1661             {
    1662                 if (a->argc <= i + 1 || !*a->argv[i+1])
    1663                     return errorArgument("Missing argument to '%s'", a->argv[i]);
    1664                 i++;
    1665                 hostpath = a->argv[i];
    1666             }
    1667             else if (strcmp(a->argv[i], "-readonly") == 0)
    1668             {
    1669                 fWritable = false;
    1670             }
    1671             else if (strcmp(a->argv[i], "-transient") == 0)
    1672             {
    1673                 fTransient = true;
    1674             }
    1675             else
    1676                 return errorSyntax(USAGE_SHAREDFOLDER_ADD, "Invalid parameter '%s'", Utf8Str(a->argv[i]).raw());
    1677         }
    1678 
    1679         if (NULL != strstr(name, " "))
    1680             return errorSyntax(USAGE_SHAREDFOLDER_ADD, "No spaces allowed in parameter '-name'!");
    1681 
    1682         /* required arguments */
    1683         if (!name || !hostpath)
    1684         {
    1685             return errorSyntax(USAGE_SHAREDFOLDER_ADD, "Parameters -name and -hostpath are required");
    1686         }
    1687 
    1688         if (fTransient)
    1689         {
    1690             ComPtr <IConsole> console;
    1691 
    1692             /* open an existing session for the VM */
    1693             CHECK_ERROR_RET(a->virtualBox, OpenExistingSession (a->session, uuid), 1);
    1694             /* get the session machine */
    1695             CHECK_ERROR_RET(a->session, COMGETTER(Machine)(machine.asOutParam()), 1);
    1696             /* get the session console */
    1697             CHECK_ERROR_RET(a->session, COMGETTER(Console)(console.asOutParam()), 1);
    1698 
    1699             CHECK_ERROR(console, CreateSharedFolder(Bstr(name), Bstr(hostpath), fWritable));
    1700 
    1701             if (console)
    1702                 a->session->Close();
    1703         }
    1704         else
    1705         {
    1706             /* open a session for the VM */
    1707             CHECK_ERROR_RET (a->virtualBox, OpenSession(a->session, uuid), 1);
    1708 
    1709             /* get the mutable session machine */
    1710             a->session->COMGETTER(Machine)(machine.asOutParam());
    1711 
    1712             CHECK_ERROR(machine, CreateSharedFolder(Bstr(name), Bstr(hostpath), fWritable));
    1713 
    1714             if (SUCCEEDED(rc))
    1715                 CHECK_ERROR(machine, SaveSettings());
    1716 
    1717             a->session->Close();
    1718         }
    1719     }
    1720     else if (strcmp(a->argv[0], "remove") == 0)
    1721     {
    1722         /* we need at least two more parameters */
    1723         if (a->argc < 3)
    1724             return errorSyntax(USAGE_SHAREDFOLDER_REMOVE, "Not enough parameters");
    1725 
    1726         char *name = NULL;
    1727         bool fTransient = false;
    1728 
    1729         for (int i = 2; i < a->argc; i++)
    1730         {
    1731             if (strcmp(a->argv[i], "-name") == 0)
    1732             {
    1733                 if (a->argc <= i + 1 || !*a->argv[i+1])
    1734                     return errorArgument("Missing argument to '%s'", a->argv[i]);
    1735                 i++;
    1736                 name = a->argv[i];
    1737             }
    1738             else if (strcmp(a->argv[i], "-transient") == 0)
    1739             {
    1740                 fTransient = true;
    1741             }
    1742             else
    1743                 return errorSyntax(USAGE_SHAREDFOLDER_REMOVE, "Invalid parameter '%s'", Utf8Str(a->argv[i]).raw());
    1744         }
    1745 
    1746         /* required arguments */
    1747         if (!name)
    1748             return errorSyntax(USAGE_SHAREDFOLDER_REMOVE, "Parameter -name is required");
    1749 
    1750         if (fTransient)
    1751         {
    1752             ComPtr <IConsole> console;
    1753 
    1754             /* open an existing session for the VM */
    1755             CHECK_ERROR_RET(a->virtualBox, OpenExistingSession (a->session, uuid), 1);
    1756             /* get the session machine */
    1757             CHECK_ERROR_RET(a->session, COMGETTER(Machine)(machine.asOutParam()), 1);
    1758             /* get the session console */
    1759             CHECK_ERROR_RET(a->session, COMGETTER(Console)(console.asOutParam()), 1);
    1760 
    1761             CHECK_ERROR(console, RemoveSharedFolder(Bstr(name)));
    1762 
    1763             if (console)
    1764                 a->session->Close();
    1765         }
    1766         else
    1767         {
    1768             /* open a session for the VM */
    1769             CHECK_ERROR_RET (a->virtualBox, OpenSession(a->session, uuid), 1);
    1770 
    1771             /* get the mutable session machine */
    1772             a->session->COMGETTER(Machine)(machine.asOutParam());
    1773 
    1774             CHECK_ERROR(machine, RemoveSharedFolder(Bstr(name)));
    1775 
    1776             /* commit and close the session */
    1777             CHECK_ERROR(machine, SaveSettings());
    1778             a->session->Close();
    1779         }
    1780     }
    1781     else
    1782         return errorSyntax(USAGE_SETPROPERTY, "Invalid parameter '%s'", Utf8Str(a->argv[0]).raw());
    1783 
    1784     return 0;
    1785 }
    1786 
    1787 static int handleVMStatistics(HandlerArg *a)
    1788 {
    1789     HRESULT rc;
    1790 
    1791     /* at least one option: the UUID or name of the VM */
    1792     if (a->argc < 1)
    1793         return errorSyntax(USAGE_VM_STATISTICS, "Incorrect number of parameters");
    1794 
    1795     /* try to find the given machine */
    1796     ComPtr <IMachine> machine;
    1797     Guid uuid (a->argv[0]);
    1798     if (!uuid.isEmpty())
    1799         CHECK_ERROR(a->virtualBox, GetMachine(uuid, machine.asOutParam()));
    1800     else
    1801     {
    1802         CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]), machine.asOutParam()));
    1803         if (SUCCEEDED (rc))
    1804             machine->COMGETTER(Id)(uuid.asOutParam());
    1805     }
    1806     if (FAILED(rc))
    1807         return 1;
    1808 
    1809     /* parse arguments. */
    1810     bool fReset = false;
    1811     bool fWithDescriptions = false;
    1812     const char *pszPattern = NULL; /* all */
    1813     for (int i = 1; i < a->argc; i++)
    1814     {
    1815         if (!strcmp(a->argv[i], "-pattern"))
    1816         {
    1817             if (pszPattern)
    1818                 return errorSyntax(USAGE_VM_STATISTICS, "Multiple -patterns options is not permitted");
    1819             if (i + 1 >= a->argc)
    1820                 return errorArgument("Missing argument to '%s'", a->argv[i]);
    1821             pszPattern = a->argv[++i];
    1822         }
    1823         else if (!strcmp(a->argv[i], "-descriptions"))
    1824             fWithDescriptions = true;
    1825         /* add: -file <filename> and -formatted */
    1826         else if (!strcmp(a->argv[i], "-reset"))
    1827             fReset = true;
    1828         else
    1829             return errorSyntax(USAGE_VM_STATISTICS, "Unknown option '%s'", a->argv[i]);
    1830     }
    1831     if (fReset && fWithDescriptions)
    1832         return errorSyntax(USAGE_VM_STATISTICS, "The -reset and -descriptions options does not mix");
    1833 
    1834 
    1835     /* open an existing session for the VM. */
    1836     CHECK_ERROR(a->virtualBox, OpenExistingSession(a->session, uuid));
    1837     if (SUCCEEDED(rc))
    1838     {
    1839         /* get the session console. */
    1840         ComPtr <IConsole> console;
    1841         CHECK_ERROR(a->session, COMGETTER(Console)(console.asOutParam()));
    1842         if (SUCCEEDED(rc))
    1843         {
    1844             /* get the machine debugger. */
    1845             ComPtr <IMachineDebugger> debugger;
    1846             CHECK_ERROR(console, COMGETTER(Debugger)(debugger.asOutParam()));
    1847             if (SUCCEEDED(rc))
    1848             {
    1849                 if (fReset)
    1850                     CHECK_ERROR(debugger, ResetStats(Bstr(pszPattern)));
    1851                 else
    1852                 {
    1853                     Bstr stats;
    1854                     CHECK_ERROR(debugger, GetStats(Bstr(pszPattern), fWithDescriptions, stats.asOutParam()));
    1855                     if (SUCCEEDED(rc))
    1856                     {
    1857                         /* if (fFormatted)
    1858                          { big mess }
    1859                          else
    1860                          */
    1861                         RTPrintf("%ls\n", stats.raw());
    1862                     }
    1863                 }
    1864             }
    1865             a->session->Close();
    1866         }
    1867     }
    1868 
    1869     return SUCCEEDED(rc) ? 0 : 1;
    1870 }
    1871 #endif /* !VBOX_ONLY_DOCS */
    1872 
    1873 enum ConvertSettings
    1874 {
    1875     ConvertSettings_No      = 0,
    1876     ConvertSettings_Yes     = 1,
    1877     ConvertSettings_Backup  = 2,
    1878     ConvertSettings_Ignore  = 3,
    1879 };
    1880 
    1881 #ifndef VBOX_ONLY_DOCS
    1882 /**
    1883  * Checks if any of the settings files were auto-converted and informs the
    1884  * user if so.
    1885  *
    1886  * @return @false if the program should terminate and @true otherwise.
    1887  */
    1888 static bool checkForAutoConvertedSettings (ComPtr<IVirtualBox> virtualBox,
    1889                                            ComPtr<ISession> session,
    1890                                            ConvertSettings fConvertSettings)
    1891 {
    1892     /* return early if nothing to do */
    1893     if (fConvertSettings == ConvertSettings_Ignore)
    1894         return true;
    1895 
    1896     HRESULT rc;
    1897 
    1898     do
    1899     {
    1900         Bstr formatVersion;
    1901         CHECK_ERROR_BREAK(virtualBox, COMGETTER(SettingsFormatVersion) (formatVersion.asOutParam()));
    1902 
    1903         bool isGlobalConverted = false;
    1904         std::list <ComPtr <IMachine> > cvtMachines;
    1905         std::list <Utf8Str> fileList;
    1906         Bstr version;
    1907         Bstr filePath;
    1908 
    1909         com::SafeIfaceArray <IMachine> machines;
    1910         CHECK_ERROR_BREAK(virtualBox, COMGETTER(Machines2) (ComSafeArrayAsOutParam (machines)));
    1911 
    1912         for (size_t i = 0; i < machines.size(); ++ i)
    1913         {
    1914             BOOL accessible;
    1915             CHECK_ERROR_BREAK(machines[i], COMGETTER(Accessible) (&accessible));
    1916             if (!accessible)
    1917                 continue;
    1918 
    1919             CHECK_ERROR_BREAK(machines[i], COMGETTER(SettingsFileVersion) (version.asOutParam()));
    1920 
    1921             if (version != formatVersion)
    1922             {
    1923                 cvtMachines.push_back (machines [i]);
    1924                 Bstr filePath;
    1925                 CHECK_ERROR_BREAK(machines[i], COMGETTER(SettingsFilePath) (filePath.asOutParam()));
    1926                 fileList.push_back (Utf8StrFmt ("%ls  (%ls)", filePath.raw(),
    1927                                                 version.raw()));
    1928             }
    1929         }
    1930 
    1931         if (FAILED(rc))
    1932             break;
    1933 
    1934         CHECK_ERROR_BREAK(virtualBox, COMGETTER(SettingsFileVersion) (version.asOutParam()));
    1935         if (version != formatVersion)
    1936         {
    1937             isGlobalConverted = true;
    1938             CHECK_ERROR_BREAK(virtualBox, COMGETTER(SettingsFilePath) (filePath.asOutParam()));
    1939             fileList.push_back (Utf8StrFmt ("%ls  (%ls)", filePath.raw(),
    1940                                             version.raw()));
    1941         }
    1942 
    1943         if (fileList.size() > 0)
    1944         {
    1945             switch (fConvertSettings)
    1946             {
    1947                 case ConvertSettings_No:
    1948                 {
    1949                     RTPrintf (
    1950 "WARNING! The following VirtualBox settings files have been automatically\n"
    1951 "converted to the new settings file format version '%ls':\n"
    1952 "\n",
    1953                               formatVersion.raw());
    1954 
    1955                     for (std::list <Utf8Str>::const_iterator f = fileList.begin();
    1956                          f != fileList.end(); ++ f)
    1957                         RTPrintf ("  %S\n", (*f).raw());
    1958                     RTPrintf (
    1959 "\n"
    1960 "The current command was aborted to prevent overwriting the above settings\n"
    1961 "files with the results of the auto-conversion without your permission.\n"
    1962 "Please put one of the following command line switches to the beginning of\n"
    1963 "the VBoxManage command line and repeat the command:\n"
    1964 "\n"
    1965 "  -convertSettings       - to save all auto-converted files (it will not\n"
    1966 "                           be possible to use these settings files with an\n"
    1967 "                           older version of VirtualBox in the future);\n"
    1968 "  -convertSettingsBackup - to create backup copies of the settings files in\n"
    1969 "                           the old format before saving them in the new format;\n"
    1970 "  -convertSettingsIgnore - to not save the auto-converted settings files.\n"
    1971 "\n"
    1972 "Note that if you use -convertSettingsIgnore, the auto-converted settings files\n"
    1973 "will be implicitly saved in the new format anyway once you change a setting or\n"
    1974 "start a virtual machine, but NO backup copies will be created in this case.\n");
    1975                     return false;
    1976                 }
    1977                 case ConvertSettings_Yes:
    1978                 case ConvertSettings_Backup:
    1979                 {
    1980                     break;
    1981                 }
    1982                 default:
    1983                     AssertFailedReturn (false);
    1984             }
    1985 
    1986             for (std::list <ComPtr <IMachine> >::const_iterator m = cvtMachines.begin();
    1987                  m != cvtMachines.end(); ++ m)
    1988             {
    1989                 Guid id;
    1990                 CHECK_ERROR_BREAK((*m), COMGETTER(Id) (id.asOutParam()));
    1991 
    1992                 /* open a session for the VM */
    1993                 CHECK_ERROR_BREAK (virtualBox, OpenSession (session, id));
    1994 
    1995                 ComPtr <IMachine> sm;
    1996                 CHECK_ERROR_BREAK(session, COMGETTER(Machine) (sm.asOutParam()));
    1997 
    1998                 Bstr bakFileName;
    1999                 if (fConvertSettings == ConvertSettings_Backup)
    2000                     CHECK_ERROR (sm, SaveSettingsWithBackup (bakFileName.asOutParam()));
    2001                 else
    2002                     CHECK_ERROR (sm, SaveSettings());
    2003 
    2004                 session->Close();
    2005 
    2006                 if (FAILED(rc))
    2007                     break;
    2008             }
    2009 
    2010             if (FAILED(rc))
    2011                 break;
    2012 
    2013             if (isGlobalConverted)
    2014             {
    2015                 Bstr bakFileName;
    2016                 if (fConvertSettings == ConvertSettings_Backup)
    2017                     CHECK_ERROR (virtualBox, SaveSettingsWithBackup (bakFileName.asOutParam()));
    2018                 else
    2019                     CHECK_ERROR (virtualBox, SaveSettings());
    2020             }
    2021 
    2022             if (FAILED(rc))
    2023                 break;
    2024         }
    2025     }
    2026     while (0);
    2027 
    2028     return SUCCEEDED (rc);
    2029 }
    2030 #endif /* !VBOX_ONLY_DOCS */
    2031 
    2032 // main
    2033 ///////////////////////////////////////////////////////////////////////////////
    2034 
    2035 int main(int argc, char *argv[])
    2036 {
    2037     /*
    2038      * Before we do anything, init the runtime without loading
    2039      * the support driver.
    2040      */
    2041     RTR3Init();
    2042 
    2043     bool fShowLogo = true;
    2044     int  iCmd      = 1;
    2045     int  iCmdArg;
    2046 
    2047     ConvertSettings fConvertSettings = ConvertSettings_No;
    2048 
    2049     /* global options */
    2050     for (int i = 1; i < argc || argc <= iCmd; i++)
    2051     {
    2052         if (    argc <= iCmd
    2053             ||  (strcmp(argv[i], "help")   == 0)
    2054             ||  (strcmp(argv[i], "-?")     == 0)
    2055             ||  (strcmp(argv[i], "-h")     == 0)
    2056             ||  (strcmp(argv[i], "-help")  == 0)
    2057             ||  (strcmp(argv[i], "--help") == 0))
    2058         {
    2059             showLogo();
    2060             printUsage(USAGE_ALL);
    2061             return 0;
    2062         }
    2063         else if (   strcmp(argv[i], "-v") == 0
    2064                  || strcmp(argv[i], "-version") == 0
    2065                  || strcmp(argv[i], "-Version") == 0
    2066                  || strcmp(argv[i], "--version") == 0)
    2067         {
    2068             /* Print version number, and do nothing else. */
    2069             RTPrintf("%sr%d\n", VBOX_VERSION_STRING, VBoxSVNRev ());
    2070             return 0;
    2071         }
    2072         else if (strcmp(argv[i], "-dumpopts") == 0)
    2073         {
    2074             /* Special option to dump really all commands,
    2075              * even the ones not understood on this platform. */
    2076             printUsage(USAGE_DUMPOPTS);
    2077             return 0;
    2078         }
    2079         else if (strcmp(argv[i], "-nologo") == 0)
    2080         {
    2081             /* suppress the logo */
    2082             fShowLogo = false;
    2083             iCmd++;
    2084         }
    2085         else if (strcmp(argv[i], "-convertSettings") == 0)
    2086         {
    2087             fConvertSettings = ConvertSettings_Yes;
    2088             iCmd++;
    2089         }
    2090         else if (strcmp(argv[i], "-convertSettingsBackup") == 0)
    2091         {
    2092             fConvertSettings = ConvertSettings_Backup;
    2093             iCmd++;
    2094         }
    2095         else if (strcmp(argv[i], "-convertSettingsIgnore") == 0)
    2096         {
    2097             fConvertSettings = ConvertSettings_Ignore;
    2098             iCmd++;
    2099         }
    2100         else
    2101         {
    2102             break;
    2103         }
    2104     }
    2105 
    2106     iCmdArg = iCmd + 1;
    2107 
    2108     if (fShowLogo)
    2109         showLogo();
    2110 
    2111 
    2112 #ifdef VBOX_ONLY_DOCS
    2113     int rc = 0;
    2114 #else /* !VBOX_ONLY_DOCS */
    2115     HRESULT rc = 0;
    2116 
    2117     rc = com::Initialize();
    2118     if (FAILED(rc))
    2119     {
    2120         RTPrintf("ERROR: failed to initialize COM!\n");
    2121         return rc;
    2122     }
    2123 
    2124     /*
    2125      * The input is in the host OS'es codepage (NT guarantees ACP).
    2126      * For VBox we use UTF-8 and convert to UCS-2 when calling (XP)COM APIs.
    2127      * For simplicity, just convert the argv[] array here.
    2128      */
    2129     for (int i = iCmdArg; i < argc; i++)
    2130     {
    2131         char *converted;
    2132         RTStrCurrentCPToUtf8(&converted, argv[i]);
    2133         argv[i] = converted;
    2134     }
    2135 
    2136     do
    2137     {
    2138     // scopes all the stuff till shutdown
    2139     ////////////////////////////////////////////////////////////////////////////
    2140 
    2141     /* convertfromraw: does not need a VirtualBox instantiation. */
    2142     if (argc >= iCmdArg && (   !strcmp(argv[iCmd], "convertfromraw")
    2143                             || !strcmp(argv[iCmd], "convertdd")))
    2144     {
    2145         rc = handleConvertFromRaw(argc - iCmdArg, argv + iCmdArg);
    2146         break;
    2147     }
    2148 
    2149     ComPtr<IVirtualBox> virtualBox;
    2150     ComPtr<ISession> session;
    2151 
    2152     rc = virtualBox.createLocalObject(CLSID_VirtualBox);
    2153     if (FAILED(rc))
    2154         RTPrintf("ERROR: failed to create the VirtualBox object!\n");
    2155     else
    2156     {
    2157         rc = session.createInprocObject(CLSID_Session);
    2158         if (FAILED(rc))
    2159             RTPrintf("ERROR: failed to create a session object!\n");
    2160     }
    2161 
    2162     if (FAILED(rc))
    2163     {
    2164         com::ErrorInfo info;
    2165         if (!info.isFullAvailable() && !info.isBasicAvailable())
    2166         {
    2167             com::GluePrintRCMessage(rc);
    2168             RTPrintf("Most likely, the VirtualBox COM server is not running or failed to start.\n");
    2169         }
    2170         else
    2171             GluePrintErrorInfo(info);
    2172         break;
    2173     }
    2174 
    2175     /* create the event queue
    2176      * (here it is necessary only to process remaining XPCOM/IPC events
    2177      * after the session is closed) */
    2178 
    2179 #ifdef USE_XPCOM_QUEUE
    2180     nsCOMPtr<nsIEventQueue> eventQ;
    2181     NS_GetMainEventQ(getter_AddRefs(eventQ));
    2182 #endif
    2183 
    2184     if (!checkForAutoConvertedSettings (virtualBox, session, fConvertSettings))
    2185         break;
    2186 
    2187 #ifdef USE_XPCOM_QUEUE
    2188     HandlerArg handlerArg = { 0, NULL, eventQ, virtualBox, session };
    2189 #else
    2190     HandlerArg handlerArg = { 0, NULL, virtualBox, session };
    2191 #endif
    2192 
    2193     /*
    2194      * All registered command handlers
    2195      */
    2196     struct
    2197     {
    2198         const char *command;
    2199         PFNHANDLER handler;
    2200     } commandHandlers[] =
    2201     {
    2202         { "internalcommands", handleInternalCommands },
    2203         { "list",             handleList },
    2204         { "showvminfo",       handleShowVMInfo },
    2205         { "registervm",       handleRegisterVM },
    2206         { "unregistervm",     handleUnregisterVM },
    2207         { "createhd",         handleCreateHardDisk },
    2208         { "createvdi",        handleCreateHardDisk }, /* backward compatiblity */
    2209         { "modifyhd",         handleModifyHardDisk },
    2210         { "modifyvdi",        handleModifyHardDisk }, /* backward compatiblity */
    2211         { "clonehd",          handleCloneHardDisk },
    2212         { "clonevdi",         handleCloneHardDisk }, /* backward compatiblity */
    2213         { "addiscsidisk",     handleAddiSCSIDisk },
    2214         { "createvm",         handleCreateVM },
    2215         { "modifyvm",         handleModifyVM },
    2216         { "startvm",          handleStartVM },
    2217         { "controlvm",        handleControlVM },
    2218         { "discardstate",     handleDiscardState },
    2219         { "adoptstate",       handleAdoptdState },
    2220         { "snapshot",         handleSnapshot },
    2221         { "openmedium",       handleOpenMedium },
    2222         { "registerimage",    handleOpenMedium }, /* backward compatiblity */
    2223         { "closemedium",      handleCloseMedium },
    2224         { "unregisterimage",  handleCloseMedium }, /* backward compatiblity */
    2225         { "showhdinfo",       handleShowHardDiskInfo },
    2226         { "showvdiinfo",      handleShowHardDiskInfo }, /* backward compatiblity */
    2227         { "getextradata",     handleGetExtraData },
    2228         { "setextradata",     handleSetExtraData },
    2229         { "setproperty",      handleSetProperty },
    2230         { "usbfilter",        handleUSBFilter },
    2231         { "sharedfolder",     handleSharedFolder },
    2232         { "vmstatistics",     handleVMStatistics },
    2233 #ifdef VBOX_WITH_GUEST_PROPS
    2234         { "guestproperty",    handleGuestProperty },
    2235 #endif /* VBOX_WITH_GUEST_PROPS defined */
    2236         { "metrics",          handleMetrics },
    2237         { "import",           handleImportAppliance },
    2238         { "export",           handleExportAppliance },
    2239         { NULL,               NULL }
    2240     };
    2241 
    2242     int commandIndex;
    2243     for (commandIndex = 0; commandHandlers[commandIndex].command != NULL; commandIndex++)
    2244     {
    2245         if (strcmp(commandHandlers[commandIndex].command, argv[iCmd]) == 0)
    2246         {
    2247             handlerArg.argc = argc - iCmdArg;
    2248             handlerArg.argv = &argv[iCmdArg];
    2249 
    2250             rc = commandHandlers[commandIndex].handler(&handlerArg);
    2251             break;
    2252         }
    2253     }
    2254     if (!commandHandlers[commandIndex].command)
    2255     {
    2256         rc = errorSyntax(USAGE_ALL, "Invalid command '%s'", Utf8Str(argv[iCmd]).raw());
    2257     }
    2258 
    2259     /* Although all handlers should always close the session if they open it,
    2260      * we do it here just in case if some of the handlers contains a bug --
    2261      * leaving the direct session not closed will turn the machine state to
    2262      * Aborted which may have unwanted side effects like killing the saved
    2263      * state file (if the machine was in the Saved state before). */
    2264     session->Close();
    2265 
    2266 #ifdef USE_XPCOM_QUEUE
    2267     eventQ->ProcessPendingEvents();
    2268 #endif
    2269 
    2270     // end "all-stuff" scope
    2271     ////////////////////////////////////////////////////////////////////////////
    2272     }
    2273     while (0);
    2274 
    2275     com::Shutdown();
    2276 #endif /* !VBOX_ONLY_DOCS */
    2277 
    2278     /*
    2279      * Free converted argument vector
    2280      */
    2281     for (int i = iCmdArg; i < argc; i++)
    2282         RTStrFree(argv[i]);
    2283 
    2284     return rc != 0;
    2285 }
注意: 瀏覽 TracChangeset 來幫助您使用更動檢視器

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