Changeset 17104 in vbox for trunk/src/VBox/Frontends/VBoxManage
- Timestamp:
- Feb 24, 2009 11:18:45 PM (16 years ago)
- Location:
- trunk/src/VBox/Frontends/VBoxManage
- Files:
-
- 4 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VBoxManage/Makefile.kmk
r17103 r17104 53 53 VBoxManageDisk.cpp \ 54 54 VBoxManageSnapshot.cpp \ 55 VBoxManageUSB.cpp \ 55 56 VBoxInternalManage.cpp \ 56 57 $(if $(VBOX_WITH_GUEST_PROPS),VBoxManageGuestProp.cpp) \ -
trunk/src/VBox/Frontends/VBoxManage/VBoxManage.cpp
r17103 r17104 62 62 using namespace com; 63 63 64 /* missing XPCOM <-> COM wrappers */65 #ifndef STDMETHOD_66 # define STDMETHOD_(ret, meth) NS_IMETHOD_(ret) meth67 #endif68 #ifndef NS_GET_IID69 # define NS_GET_IID(I) IID_##I70 #endif71 #ifndef RT_OS_WINDOWS72 #define IUnknown nsISupports73 #endif74 75 64 /** command handler type */ 76 65 typedef int (*PFNHANDLER)(HandlerArg *a); 77 66 78 /**79 * Quick IUSBDevice implementation for detaching / attaching80 * devices to the USB Controller.81 */82 class MyUSBDevice : public IUSBDevice83 {84 public:85 // public initializer/uninitializer for internal purposes only86 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 else113 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 // types146 ///////////////////////////////////////////////////////////////////////////////147 148 template <typename T>149 class Nullable150 {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 USBFilterCmd177 {178 struct USBFilter179 {180 USBFilter ()181 : mAction (USBDeviceFilterAction_Null)182 {}183 184 Bstr mName;185 Nullable <bool> mActive;186 Bstr mVendorId;187 Bstr mProductId;188 Bstr mRevision;189 Bstr mManufacturer;190 Bstr mProduct;191 Bstr mRemote;192 Bstr mSerialNumber;193 Nullable <ULONG> mMaskedInterfaces;194 USBDeviceFilterAction_T mAction;195 };196 197 enum Action { Invalid, Add, Modify, Remove };198 199 USBFilterCmd() : mAction (Invalid), mIndex (0), mGlobal (false) {}200 201 Action mAction;202 uint32_t mIndex;203 /** flag whether the command target is a global filter */204 bool mGlobal;205 /** machine this command is targeted at (null for global filters) */206 ComPtr<IMachine> mMachine;207 USBFilter mFilter;208 };209 67 #endif /* !VBOX_ONLY_DOCS */ 210 68 … … 1240 1098 1241 1099 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 default1281 // (assuming that the user sets up all necessary attributes1282 // 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 else1296 {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 else1323 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 else1395 return errorArgument("Invalid USB filter action '%s'", a->argv[i]);1396 }1397 else1398 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 options1405 if ( cmd.mFilter.mName.isEmpty()1406 ||1407 ( cmd.mGlobal1408 && cmd.mFilter.mAction == USBDeviceFilterAction_Null1409 )1410 || ( !cmd.mGlobal1411 && !cmd.mMachine)1412 || ( cmd.mGlobal1413 && 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 else1438 {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 options1451 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 else1467 {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 else1508 {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 else1563 {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 else1599 {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;1617 1100 } 1618 1101 -
trunk/src/VBox/Frontends/VBoxManage/VBoxManage.h
r17103 r17104 186 186 187 187 /* VBoxManageUSB.cpp */ 188 /* VBoxManageTODO.cpp */ 188 int handleUSBFilter(HandlerArg *a); 189 189 190 190 #endif /* !VBOX_ONLY_DOCS */ -
trunk/src/VBox/Frontends/VBoxManage/VBoxManageSnapshot.cpp
r17102 r17104 20 20 */ 21 21 22 #ifndef VBOX_ONLY_DOCS23 24 22 /******************************************************************************* 25 23 * Header Files * … … 285 283 } 286 284 287 #endif /* !VBOX_ONLY_DOCS */ -
trunk/src/VBox/Frontends/VBoxManage/VBoxManageUSB.cpp
r17103 r17104 20 20 */ 21 21 22 23 /*******************************************************************************24 * Header Files *25 *******************************************************************************/26 #ifndef VBOX_ONLY_DOCS27 22 #include <VBox/com/com.h> 28 23 #include <VBox/com/string.h> … … 35 30 #include <VBox/com/VirtualBox.h> 36 31 37 #include <vector> 38 #include <list> 39 #endif /* !VBOX_ONLY_DOCS */ 32 #include "VBoxManage.h" 40 33 41 34 #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_DOCS62 using namespace com;63 35 64 36 /* missing XPCOM <-> COM wrappers */ … … 73 45 #endif 74 46 75 /** command handler type */ 76 typedef int (*PFNHANDLER)(HandlerArg *a); 47 using namespace com; 77 48 78 49 /** … … 207 178 USBFilter mFilter; 208 179 }; 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 181 int handleUSBFilter (HandlerArg *a) 1245 182 { 1246 183 HRESULT rc = S_OK; … … 1617 554 } 1618 555 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 else1676 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 else1705 {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 else1743 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 else1767 {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 else1782 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 else1801 {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 else1829 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 else1852 {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 else1860 */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 ConvertSettings1874 {1875 ConvertSettings_No = 0,1876 ConvertSettings_Yes = 1,1877 ConvertSettings_Backup = 2,1878 ConvertSettings_Ignore = 3,1879 };1880 1881 #ifndef VBOX_ONLY_DOCS1882 /**1883 * Checks if any of the settings files were auto-converted and informs the1884 * 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 do1899 {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 else2002 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 else2019 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 // main2033 ///////////////////////////////////////////////////////////////////////////////2034 2035 int main(int argc, char *argv[])2036 {2037 /*2038 * Before we do anything, init the runtime without loading2039 * 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 <= iCmd2053 || (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") == 02064 || strcmp(argv[i], "-version") == 02065 || strcmp(argv[i], "-Version") == 02066 || 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 else2101 {2102 break;2103 }2104 }2105 2106 iCmdArg = iCmd + 1;2107 2108 if (fShowLogo)2109 showLogo();2110 2111 2112 #ifdef VBOX_ONLY_DOCS2113 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 do2137 {2138 // scopes all the stuff till shutdown2139 ////////////////////////////////////////////////////////////////////////////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 else2156 {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 else2171 GluePrintErrorInfo(info);2172 break;2173 }2174 2175 /* create the event queue2176 * (here it is necessary only to process remaining XPCOM/IPC events2177 * after the session is closed) */2178 2179 #ifdef USE_XPCOM_QUEUE2180 nsCOMPtr<nsIEventQueue> eventQ;2181 NS_GetMainEventQ(getter_AddRefs(eventQ));2182 #endif2183 2184 if (!checkForAutoConvertedSettings (virtualBox, session, fConvertSettings))2185 break;2186 2187 #ifdef USE_XPCOM_QUEUE2188 HandlerArg handlerArg = { 0, NULL, eventQ, virtualBox, session };2189 #else2190 HandlerArg handlerArg = { 0, NULL, virtualBox, session };2191 #endif2192 2193 /*2194 * All registered command handlers2195 */2196 struct2197 {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_PROPS2234 { "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 to2262 * Aborted which may have unwanted side effects like killing the saved2263 * state file (if the machine was in the Saved state before). */2264 session->Close();2265 2266 #ifdef USE_XPCOM_QUEUE2267 eventQ->ProcessPendingEvents();2268 #endif2269 2270 // end "all-stuff" scope2271 ////////////////////////////////////////////////////////////////////////////2272 }2273 while (0);2274 2275 com::Shutdown();2276 #endif /* !VBOX_ONLY_DOCS */2277 2278 /*2279 * Free converted argument vector2280 */2281 for (int i = iCmdArg; i < argc; i++)2282 RTStrFree(argv[i]);2283 2284 return rc != 0;2285 }
Note:
See TracChangeset
for help on using the changeset viewer.