- Timestamp:
- Nov 26, 2008 2:30:34 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
r14612 r14646 44 44 VBoxManage.cpp \ 45 45 VBoxManageInfo.cpp \ 46 VBoxManageMetrics.cpp \ 46 47 VBoxManageList.cpp \ 47 48 VBoxInternalManage.cpp \ -
trunk/src/VBox/Frontends/VBoxManage/VBoxManage.cpp
r14621 r14646 5288 5288 return SUCCEEDED(rc) ? 0 : 1; 5289 5289 } 5290 5291 static char *toBaseMetricNames(const char *metricList)5292 {5293 char *newList = (char*)RTMemAlloc(strlen(metricList) + 1);5294 int cSlashes = 0;5295 bool fSkip = false;5296 const char *src = metricList;5297 char c, *dst = newList;5298 while ((c = *src++))5299 if (c == ':')5300 fSkip = true;5301 else if (c == '/' && ++cSlashes == 2)5302 fSkip = true;5303 else if (c == ',')5304 {5305 fSkip = false;5306 cSlashes = 0;5307 *dst++ = c;5308 }5309 else5310 if (!fSkip)5311 *dst++ = c;5312 *dst = 0;5313 return newList;5314 }5315 5316 static int parseFilterParameters(int argc, char *argv[],5317 ComPtr<IVirtualBox> aVirtualBox,5318 ComSafeArrayOut(BSTR, outMetrics),5319 ComSafeArrayOut(BSTR, outBaseMetrics),5320 ComSafeArrayOut(IUnknown *, outObjects))5321 {5322 HRESULT rc = S_OK;5323 com::SafeArray<BSTR> retMetrics(1);5324 com::SafeArray<BSTR> retBaseMetrics(1);5325 com::SafeIfaceArray <IUnknown> retObjects;5326 5327 Bstr metricNames, baseNames;5328 5329 /* Metric list */5330 if (argc > 1)5331 {5332 metricNames = argv[1];5333 char *tmp = toBaseMetricNames(argv[1]);5334 if (!tmp)5335 return VERR_NO_MEMORY;5336 baseNames = tmp;5337 RTMemFree(tmp);5338 }5339 else5340 {5341 metricNames = L"*";5342 baseNames = L"*";5343 }5344 metricNames.cloneTo(&retMetrics[0]);5345 baseNames.cloneTo(&retBaseMetrics[0]);5346 5347 /* Object name */5348 if (argc > 0 && strcmp(argv[0], "*"))5349 {5350 if (!strcmp(argv[0], "host"))5351 {5352 ComPtr<IHost> host;5353 CHECK_ERROR(aVirtualBox, COMGETTER(Host)(host.asOutParam()));5354 retObjects.reset(1);5355 host.queryInterfaceTo(&retObjects[0]);5356 }5357 else5358 {5359 ComPtr <IMachine> machine;5360 rc = aVirtualBox->FindMachine(Bstr(argv[0]), machine.asOutParam());5361 if (SUCCEEDED (rc))5362 {5363 retObjects.reset(1);5364 machine.queryInterfaceTo(&retObjects[0]);5365 }5366 else5367 {5368 errorArgument("Invalid machine name: '%s'", argv[0]);5369 return rc;5370 }5371 }5372 5373 }5374 5375 retMetrics.detachTo(ComSafeArrayOutArg(outMetrics));5376 retBaseMetrics.detachTo(ComSafeArrayOutArg(outBaseMetrics));5377 retObjects.detachTo(ComSafeArrayOutArg(outObjects));5378 5379 return rc;5380 }5381 5382 static Bstr getObjectName(ComPtr<IVirtualBox> aVirtualBox,5383 ComPtr<IUnknown> aObject)5384 {5385 HRESULT rc;5386 5387 ComPtr<IHost> host = aObject;5388 if (!host.isNull())5389 return Bstr("host");5390 5391 ComPtr<IMachine> machine = aObject;5392 if (!machine.isNull())5393 {5394 Bstr name;5395 CHECK_ERROR(machine, COMGETTER(Name)(name.asOutParam()));5396 if (SUCCEEDED(rc))5397 return name;5398 }5399 return Bstr("unknown");5400 }5401 5402 static void listAffectedMetrics(ComPtr<IVirtualBox> aVirtualBox,5403 ComSafeArrayIn(IPerformanceMetric*, aMetrics))5404 {5405 HRESULT rc;5406 com::SafeIfaceArray<IPerformanceMetric> metrics(ComSafeArrayInArg(aMetrics));5407 if (metrics.size())5408 {5409 ComPtr<IUnknown> object;5410 Bstr metricName;5411 RTPrintf("The following metrics were modified:\n\n"5412 "Object Metric\n"5413 "---------- --------------------\n");5414 for (size_t i = 0; i < metrics.size(); i++)5415 {5416 CHECK_ERROR(metrics[i], COMGETTER(Object)(object.asOutParam()));5417 CHECK_ERROR(metrics[i], COMGETTER(MetricName)(metricName.asOutParam()));5418 RTPrintf("%-10ls %-20ls\n",5419 getObjectName(aVirtualBox, object).raw(), metricName.raw());5420 }5421 RTPrintf("\n");5422 }5423 else5424 {5425 RTPrintf("No metrics match the specified filter!\n");5426 }5427 }5428 5429 /**5430 * list *5431 */5432 static int handleMetricsList(int argc, char *argv[],5433 ComPtr<IVirtualBox> aVirtualBox,5434 ComPtr<IPerformanceCollector> performanceCollector)5435 {5436 HRESULT rc;5437 com::SafeArray<BSTR> metrics;5438 com::SafeArray<BSTR> baseMetrics;5439 com::SafeIfaceArray<IUnknown> objects;5440 5441 rc = parseFilterParameters(argc - 1, &argv[1], aVirtualBox,5442 ComSafeArrayAsOutParam(metrics),5443 ComSafeArrayAsOutParam(baseMetrics),5444 ComSafeArrayAsOutParam(objects));5445 if (FAILED(rc))5446 return 1;5447 5448 com::SafeIfaceArray<IPerformanceMetric> metricInfo;5449 5450 CHECK_ERROR(performanceCollector,5451 GetMetrics(ComSafeArrayAsInParam(metrics),5452 ComSafeArrayAsInParam(objects),5453 ComSafeArrayAsOutParam(metricInfo)));5454 5455 ComPtr<IUnknown> object;5456 Bstr metricName, unit, description;5457 ULONG period, count;5458 LONG minimum, maximum;5459 RTPrintf(5460 "Object Metric Unit Minimum Maximum Period Count Description\n"5461 "---------- -------------------- ---- ---------- ---------- ---------- ---------- -----------\n");5462 for (size_t i = 0; i < metricInfo.size(); i++)5463 {5464 CHECK_ERROR(metricInfo[i], COMGETTER(Object)(object.asOutParam()));5465 CHECK_ERROR(metricInfo[i], COMGETTER(MetricName)(metricName.asOutParam()));5466 CHECK_ERROR(metricInfo[i], COMGETTER(Period)(&period));5467 CHECK_ERROR(metricInfo[i], COMGETTER(Count)(&count));5468 CHECK_ERROR(metricInfo[i], COMGETTER(MinimumValue)(&minimum));5469 CHECK_ERROR(metricInfo[i], COMGETTER(MaximumValue)(&maximum));5470 CHECK_ERROR(metricInfo[i], COMGETTER(Unit)(unit.asOutParam()));5471 CHECK_ERROR(metricInfo[i], COMGETTER(Description)(description.asOutParam()));5472 RTPrintf("%-10ls %-20ls %-4ls %10d %10d %10u %10u %ls\n",5473 getObjectName(aVirtualBox, object).raw(), metricName.raw(), unit.raw(),5474 minimum, maximum, period, count, description.raw());5475 }5476 5477 return 0;5478 }5479 5480 /**5481 * Metics setup5482 */5483 static int handleMetricsSetup(int argc, char *argv[],5484 ComPtr<IVirtualBox> aVirtualBox,5485 ComPtr<IPerformanceCollector> performanceCollector)5486 {5487 HRESULT rc;5488 com::SafeArray<BSTR> metrics;5489 com::SafeArray<BSTR> baseMetrics;5490 com::SafeIfaceArray<IUnknown> objects;5491 uint32_t period = 1, samples = 1;5492 bool listMatches = false;5493 int i;5494 5495 for (i = 1; i < argc; i++)5496 {5497 if (strcmp(argv[i], "-period") == 0)5498 {5499 if (argc <= i + 1)5500 return errorArgument("Missing argument to '%s'", argv[i]);5501 if ( VINF_SUCCESS != RTStrToUInt32Full(argv[++i], 10, &period)5502 || !period)5503 return errorArgument("Invalid value for 'period' parameter: '%s'", argv[i]);5504 }5505 else if (strcmp(argv[i], "-samples") == 0)5506 {5507 if (argc <= i + 1)5508 return errorArgument("Missing argument to '%s'", argv[i]);5509 if (VINF_SUCCESS != RTStrToUInt32Full(argv[++i], 10, &samples))5510 return errorArgument("Invalid value for 'samples' parameter: '%s'", argv[i]);5511 }5512 else if (strcmp(argv[i], "-list") == 0)5513 listMatches = true;5514 else5515 break; /* The rest of params should define the filter */5516 }5517 5518 rc = parseFilterParameters(argc - i, &argv[i], aVirtualBox,5519 ComSafeArrayAsOutParam(metrics),5520 ComSafeArrayAsOutParam(baseMetrics),5521 ComSafeArrayAsOutParam(objects));5522 if (FAILED(rc))5523 return 1;5524 5525 com::SafeIfaceArray<IPerformanceMetric> affectedMetrics;5526 CHECK_ERROR(performanceCollector,5527 SetupMetrics(ComSafeArrayAsInParam(metrics),5528 ComSafeArrayAsInParam(objects), period, samples,5529 ComSafeArrayAsOutParam(affectedMetrics)));5530 if (listMatches)5531 listAffectedMetrics(aVirtualBox,5532 ComSafeArrayAsInParam(affectedMetrics));5533 5534 return 0;5535 }5536 5537 /**5538 * metrics query5539 */5540 static int handleMetricsQuery(int argc, char *argv[],5541 ComPtr<IVirtualBox> aVirtualBox,5542 ComPtr<IPerformanceCollector> performanceCollector)5543 {5544 HRESULT rc;5545 com::SafeArray<BSTR> metrics;5546 com::SafeArray<BSTR> baseMetrics;5547 com::SafeIfaceArray<IUnknown> objects;5548 5549 rc = parseFilterParameters(argc - 1, &argv[1], aVirtualBox,5550 ComSafeArrayAsOutParam(metrics),5551 ComSafeArrayAsOutParam(baseMetrics),5552 ComSafeArrayAsOutParam(objects));5553 if (FAILED(rc))5554 return 1;5555 5556 com::SafeArray<BSTR> retNames;5557 com::SafeIfaceArray<IUnknown> retObjects;5558 com::SafeArray<BSTR> retUnits;5559 com::SafeArray<ULONG> retScales;5560 com::SafeArray<ULONG> retSequenceNumbers;5561 com::SafeArray<ULONG> retIndices;5562 com::SafeArray<ULONG> retLengths;5563 com::SafeArray<LONG> retData;5564 CHECK_ERROR (performanceCollector, QueryMetricsData(ComSafeArrayAsInParam(metrics),5565 ComSafeArrayAsInParam(objects),5566 ComSafeArrayAsOutParam(retNames),5567 ComSafeArrayAsOutParam(retObjects),5568 ComSafeArrayAsOutParam(retUnits),5569 ComSafeArrayAsOutParam(retScales),5570 ComSafeArrayAsOutParam(retSequenceNumbers),5571 ComSafeArrayAsOutParam(retIndices),5572 ComSafeArrayAsOutParam(retLengths),5573 ComSafeArrayAsOutParam(retData)) );5574 5575 RTPrintf("Object Metric Values\n"5576 "---------- -------------------- --------------------------------------------\n");5577 for (unsigned i = 0; i < retNames.size(); i++)5578 {5579 Bstr metricUnit(retUnits[i]);5580 Bstr metricName(retNames[i]);5581 RTPrintf("%-10ls %-20ls ", getObjectName(aVirtualBox, retObjects[i]).raw(), metricName.raw());5582 const char *separator = "";5583 for (unsigned j = 0; j < retLengths[i]; j++)5584 {5585 if (retScales[i] == 1)5586 RTPrintf("%s%d %ls", separator, retData[retIndices[i] + j], metricUnit.raw());5587 else5588 RTPrintf("%s%d.%02d%ls", separator, retData[retIndices[i] + j] / retScales[i],5589 (retData[retIndices[i] + j] * 100 / retScales[i]) % 100, metricUnit.raw());5590 separator = ", ";5591 }5592 RTPrintf("\n");5593 }5594 5595 return 0;5596 }5597 5598 static void getTimestamp(char *pts, size_t tsSize)5599 {5600 *pts = 0;5601 AssertReturnVoid(tsSize >= 13); /* 3+3+3+3+1 */5602 RTTIMESPEC TimeSpec;5603 RTTIME Time;5604 RTTimeExplode(&Time, RTTimeNow(&TimeSpec));5605 pts += RTStrFormatNumber(pts, Time.u8Hour, 10, 2, 0, RTSTR_F_ZEROPAD);5606 *pts++ = ':';5607 pts += RTStrFormatNumber(pts, Time.u8Minute, 10, 2, 0, RTSTR_F_ZEROPAD);5608 *pts++ = ':';5609 pts += RTStrFormatNumber(pts, Time.u8Second, 10, 2, 0, RTSTR_F_ZEROPAD);5610 *pts++ = '.';5611 pts += RTStrFormatNumber(pts, Time.u32Nanosecond / 1000000, 10, 3, 0, RTSTR_F_ZEROPAD);5612 *pts = 0;5613 }5614 5615 /** Used by the handleMetricsCollect loop. */5616 static bool volatile g_fKeepGoing = true;5617 5618 #ifdef RT_OS_WINDOWS5619 /**5620 * Handler routine for catching Ctrl-C, Ctrl-Break and closing of5621 * the console.5622 *5623 * @returns true if handled, false if not handled.5624 * @param dwCtrlType The type of control signal.5625 *5626 * @remarks This is called on a new thread.5627 */5628 static BOOL WINAPI ctrlHandler(DWORD dwCtrlType)5629 {5630 switch (dwCtrlType)5631 {5632 /* Ctrl-C or Ctrl-Break or Close */5633 case CTRL_C_EVENT:5634 case CTRL_BREAK_EVENT:5635 case CTRL_CLOSE_EVENT:5636 /* Let's shut down gracefully. */5637 ASMAtomicWriteBool(&g_fKeepGoing, false);5638 return TRUE;5639 }5640 /* Don't care about the rest -- let it die a horrible death. */5641 return FALSE;5642 }5643 #endif /* RT_OS_WINDOWS */5644 5645 /**5646 * collect5647 */5648 static int handleMetricsCollect(int argc, char *argv[],5649 ComPtr<IVirtualBox> aVirtualBox,5650 ComPtr<IPerformanceCollector> performanceCollector)5651 {5652 HRESULT rc;5653 com::SafeArray<BSTR> metrics;5654 com::SafeArray<BSTR> baseMetrics;5655 com::SafeIfaceArray<IUnknown> objects;5656 uint32_t period = 1, samples = 1;5657 bool isDetached = false, listMatches = false;5658 int i;5659 for (i = 1; i < argc; i++)5660 {5661 if (strcmp(argv[i], "-period") == 0)5662 {5663 if (argc <= i + 1)5664 return errorArgument("Missing argument to '%s'", argv[i]);5665 if ( VINF_SUCCESS != RTStrToUInt32Full(argv[++i], 10, &period)5666 || !period)5667 return errorArgument("Invalid value for 'period' parameter: '%s'", argv[i]);5668 }5669 else if (strcmp(argv[i], "-samples") == 0)5670 {5671 if (argc <= i + 1)5672 return errorArgument("Missing argument to '%s'", argv[i]);5673 if ( VINF_SUCCESS != RTStrToUInt32Full(argv[++i], 10, &samples)5674 || !samples)5675 return errorArgument("Invalid value for 'samples' parameter: '%s'", argv[i]);5676 }5677 else if (strcmp(argv[i], "-list") == 0)5678 listMatches = true;5679 else if (strcmp(argv[i], "-detach") == 0)5680 isDetached = true;5681 else5682 break; /* The rest of params should define the filter */5683 }5684 5685 rc = parseFilterParameters(argc - i, &argv[i], aVirtualBox,5686 ComSafeArrayAsOutParam(metrics),5687 ComSafeArrayAsOutParam(baseMetrics),5688 ComSafeArrayAsOutParam(objects));5689 if (FAILED(rc))5690 return 1;5691 5692 5693 com::SafeIfaceArray<IPerformanceMetric> affectedMetrics;5694 CHECK_ERROR(performanceCollector,5695 SetupMetrics(ComSafeArrayAsInParam(baseMetrics),5696 ComSafeArrayAsInParam(objects), period, samples,5697 ComSafeArrayAsOutParam(affectedMetrics)));5698 if (listMatches)5699 listAffectedMetrics(aVirtualBox,5700 ComSafeArrayAsInParam(affectedMetrics));5701 if (!affectedMetrics.size())5702 return 1;5703 5704 if (isDetached)5705 {5706 RTPrintf("Warning! The background process holding collected metrics will shutdown\n"5707 "in few seconds, discarding all collected data and parameters.\n");5708 return 0;5709 }5710 5711 #ifdef RT_OS_WINDOWS5712 SetConsoleCtrlHandler(ctrlHandler, true);5713 #endif /* RT_OS_WINDOWS */5714 5715 RTPrintf("Time stamp Object Metric Value\n");5716 5717 while (g_fKeepGoing)5718 {5719 RTPrintf("------------ ---------- -------------------- --------------------\n");5720 RTThreadSleep(period * 1000); // Sleep for 'period' seconds5721 char ts[15];5722 5723 getTimestamp(ts, sizeof(ts));5724 com::SafeArray<BSTR> retNames;5725 com::SafeIfaceArray<IUnknown> retObjects;5726 com::SafeArray<BSTR> retUnits;5727 com::SafeArray<ULONG> retScales;5728 com::SafeArray<ULONG> retSequenceNumbers;5729 com::SafeArray<ULONG> retIndices;5730 com::SafeArray<ULONG> retLengths;5731 com::SafeArray<LONG> retData;5732 CHECK_ERROR (performanceCollector, QueryMetricsData(ComSafeArrayAsInParam(metrics),5733 ComSafeArrayAsInParam(objects),5734 ComSafeArrayAsOutParam(retNames),5735 ComSafeArrayAsOutParam(retObjects),5736 ComSafeArrayAsOutParam(retUnits),5737 ComSafeArrayAsOutParam(retScales),5738 ComSafeArrayAsOutParam(retSequenceNumbers),5739 ComSafeArrayAsOutParam(retIndices),5740 ComSafeArrayAsOutParam(retLengths),5741 ComSafeArrayAsOutParam(retData)) );5742 for (unsigned i = 0; i < retNames.size(); i++)5743 {5744 Bstr metricUnit(retUnits[i]);5745 Bstr metricName(retNames[i]);5746 RTPrintf("%-12s %-10ls %-20ls ", ts, getObjectName(aVirtualBox, retObjects[i]).raw(), metricName.raw());5747 const char *separator = "";5748 for (unsigned j = 0; j < retLengths[i]; j++)5749 {5750 if (retScales[i] == 1)5751 RTPrintf("%s%d %ls", separator, retData[retIndices[i] + j], metricUnit.raw());5752 else5753 RTPrintf("%s%d.%02d%ls", separator, retData[retIndices[i] + j] / retScales[i],5754 (retData[retIndices[i] + j] * 100 / retScales[i]) % 100, metricUnit.raw());5755 separator = ", ";5756 }5757 RTPrintf("\n");5758 }5759 }5760 5761 #ifdef RT_OS_WINDOWS5762 SetConsoleCtrlHandler(ctrlHandler, false);5763 #endif /* RT_OS_WINDOWS */5764 5765 return 0;5766 }5767 5768 static int handleMetrics(int argc, char *argv[],5769 ComPtr<IVirtualBox> aVirtualBox, ComPtr<ISession> aSession)5770 {5771 int rc;5772 5773 /* at least one option: subcommand name */5774 if (argc < 1)5775 return errorSyntax(USAGE_METRICS, "Subcommand missing");5776 5777 ComPtr<IPerformanceCollector> performanceCollector;5778 CHECK_ERROR(aVirtualBox, COMGETTER(PerformanceCollector)(performanceCollector.asOutParam()));5779 5780 if (!strcmp(argv[0], "list"))5781 rc = handleMetricsList(argc, argv, aVirtualBox, performanceCollector);5782 else if (!strcmp(argv[0], "setup"))5783 rc = handleMetricsSetup(argc, argv, aVirtualBox, performanceCollector);5784 else if (!strcmp(argv[0], "query"))5785 rc = handleMetricsQuery(argc, argv, aVirtualBox, performanceCollector);5786 else if (!strcmp(argv[0], "collect"))5787 rc = handleMetricsCollect(argc, argv, aVirtualBox, performanceCollector);5788 else5789 return errorSyntax(USAGE_METRICS, "Invalid subcommand '%s'", argv[0]);5790 5791 return rc;5792 }5793 5290 #endif /* !VBOX_ONLY_DOCS */ 5794 5291 -
trunk/src/VBox/Frontends/VBoxManage/VBoxManage.h
r14612 r14646 141 141 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session); 142 142 143 /* VBoxManageMetrics.cpp */ 144 int handleMetrics(int argc, char *argv[], 145 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session); 146 143 147 /* VBoxManageVD.cpp */ 144 148 /* VBoxManageUSB.cpp */ -
trunk/src/VBox/Frontends/VBoxManage/VBoxManageInfo.cpp
r14613 r14646 2 2 /** @file 3 3 * VBoxManage - VirtualBox's command-line interface. 4 * Information dumping code. 4 5 */ 5 6 6 7 /* 7 * Copyright (C) 2006-200 7Sun Microsystems, Inc.8 * Copyright (C) 2006-2008 Sun Microsystems, Inc. 8 9 * 9 10 * This file is part of VirtualBox Open Source Edition (OSE), as -
trunk/src/VBox/Frontends/VBoxManage/VBoxManageMetrics.cpp
r14562 r14646 2 2 /** @file 3 3 * VBoxManage - VirtualBox's command-line interface. 4 * Metrics handling code. 4 5 */ 5 6 6 7 /* 7 * Copyright (C) 2006-200 7Sun Microsystems, Inc.8 * Copyright (C) 2006-2008 Sun Microsystems, Inc. 8 9 * 9 10 * This file is part of VirtualBox Open Source Edition (OSE), as … … 20 21 */ 21 22 23 #ifndef VBOX_ONLY_DOCS 22 24 23 25 /******************************************************************************* 24 26 * Header Files * 25 27 *******************************************************************************/ 26 #ifndef VBOX_ONLY_DOCS27 28 #include <VBox/com/com.h> 28 29 #include <VBox/com/string.h> … … 39 40 #include <vector> 40 41 #include <list> 41 #endif /* !VBOX_ONLY_DOCS */42 42 43 43 #include <iprt/runtime.h> … … 58 58 59 59 #include "VBoxManage.h" 60 61 #ifndef VBOX_ONLY_DOCS62 60 using namespace com; 63 61 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 /** command handler type */76 typedef DECLCALLBACK(int) FNHANDLER(int argc, char *argv[], ComPtr<IVirtualBox> aVirtualBox, ComPtr<ISession> aSession);77 typedef FNHANDLER *PFNHANDLER;78 79 #ifdef USE_XPCOM_QUEUE80 /** A pointer to the event queue, set by main() before calling any handlers. */81 nsCOMPtr<nsIEventQueue> g_pEventQ;82 #endif83 84 /**85 * Quick IUSBDevice implementation for detaching / attaching86 * devices to the USB Controller.87 */88 class MyUSBDevice : public IUSBDevice89 {90 public:91 // public initializer/uninitializer for internal purposes only92 MyUSBDevice(uint16_t a_u16VendorId, uint16_t a_u16ProductId, uint16_t a_bcdRevision, uint64_t a_u64SerialHash, const char *a_pszComment)93 : m_usVendorId(a_u16VendorId), m_usProductId(a_u16ProductId),94 m_bcdRevision(a_bcdRevision), m_u64SerialHash(a_u64SerialHash),95 m_bstrComment(a_pszComment),96 m_cRefs(0)97 {98 }99 100 STDMETHOD_(ULONG, AddRef)(void)101 {102 return ASMAtomicIncU32(&m_cRefs);103 }104 STDMETHOD_(ULONG, Release)(void)105 {106 ULONG cRefs = ASMAtomicDecU32(&m_cRefs);107 if (!cRefs)108 delete this;109 return cRefs;110 }111 STDMETHOD(QueryInterface)(const IID &iid, void **ppvObject)112 {113 Guid guid(iid);114 if (guid == Guid(NS_GET_IID(IUnknown)))115 *ppvObject = (IUnknown *)this;116 else if (guid == Guid(NS_GET_IID(IUSBDevice)))117 *ppvObject = (IUSBDevice *)this;118 else119 return E_NOINTERFACE;120 AddRef();121 return S_OK;122 }123 124 STDMETHOD(COMGETTER(Id))(GUIDPARAMOUT a_pId) { return E_NOTIMPL; }125 STDMETHOD(COMGETTER(VendorId))(USHORT *a_pusVendorId) { *a_pusVendorId = m_usVendorId; return S_OK; }126 STDMETHOD(COMGETTER(ProductId))(USHORT *a_pusProductId) { *a_pusProductId = m_usProductId; return S_OK; }127 STDMETHOD(COMGETTER(Revision))(USHORT *a_pusRevision) { *a_pusRevision = m_bcdRevision; return S_OK; }128 STDMETHOD(COMGETTER(SerialHash))(ULONG64 *a_pullSerialHash) { *a_pullSerialHash = m_u64SerialHash; return S_OK; }129 STDMETHOD(COMGETTER(Manufacturer))(BSTR *a_pManufacturer) { return E_NOTIMPL; }130 STDMETHOD(COMGETTER(Product))(BSTR *a_pProduct) { return E_NOTIMPL; }131 STDMETHOD(COMGETTER(SerialNumber))(BSTR *a_pSerialNumber) { return E_NOTIMPL; }132 STDMETHOD(COMGETTER(Address))(BSTR *a_pAddress) { return E_NOTIMPL; }133 134 private:135 /** The vendor id of this USB device. */136 USHORT m_usVendorId;137 /** The product id of this USB device. */138 USHORT m_usProductId;139 /** The product revision number of this USB device.140 * (high byte = integer; low byte = decimal) */141 USHORT m_bcdRevision;142 /** The USB serial hash of the device. */143 uint64_t m_u64SerialHash;144 /** The user comment string. */145 Bstr m_bstrComment;146 /** Reference counter. */147 uint32_t volatile m_cRefs;148 };149 150 151 // types152 ///////////////////////////////////////////////////////////////////////////////153 154 template <typename T>155 class Nullable156 {157 public:158 159 Nullable() : mIsNull (true) {}160 Nullable (const T &aValue, bool aIsNull = false)161 : mIsNull (aIsNull), mValue (aValue) {}162 163 bool isNull() const { return mIsNull; };164 void setNull (bool aIsNull = true) { mIsNull = aIsNull; }165 166 operator const T&() const { return mValue; }167 168 Nullable &operator= (const T &aValue)169 {170 mValue = aValue;171 mIsNull = false;172 return *this;173 }174 175 private:176 177 bool mIsNull;178 T mValue;179 };180 181 /** helper structure to encapsulate USB filter manipulation commands */182 struct USBFilterCmd183 {184 struct USBFilter185 {186 USBFilter ()187 : mAction (USBDeviceFilterAction_Null)188 {}189 190 Bstr mName;191 Nullable <bool> mActive;192 Bstr mVendorId;193 Bstr mProductId;194 Bstr mRevision;195 Bstr mManufacturer;196 Bstr mProduct;197 Bstr mRemote;198 Bstr mSerialNumber;199 Nullable <ULONG> mMaskedInterfaces;200 USBDeviceFilterAction_T mAction;201 };202 203 enum Action { Invalid, Add, Modify, Remove };204 205 USBFilterCmd() : mAction (Invalid), mIndex (0), mGlobal (false) {}206 207 Action mAction;208 ULONG mIndex;209 /** flag whether the command target is a global filter */210 bool mGlobal;211 /** machine this command is targeted at (null for global filters) */212 ComPtr<IMachine> mMachine;213 USBFilter mFilter;214 };215 #endif /* !VBOX_ONLY_DOCS */216 62 217 63 // funcs 218 64 /////////////////////////////////////////////////////////////////////////////// 219 65 220 static void showLogo(void)221 {222 static bool fShown; /* show only once */223 224 if (!fShown)225 {226 RTPrintf("VirtualBox Command Line Management Interface Version "227 VBOX_VERSION_STRING "\n"228 "(C) 2005-2008 Sun Microsystems, Inc.\n"229 "All rights reserved.\n"230 "\n");231 fShown = true;232 }233 }234 235 static void printUsage(USAGECATEGORY u64Cmd)236 {237 #ifdef RT_OS_LINUX238 bool fLinux = true;239 #else240 bool fLinux = false;241 #endif242 #ifdef RT_OS_WINDOWS243 bool fWin = true;244 #else245 bool fWin = false;246 #endif247 #ifdef RT_OS_SOLARIS248 bool fSolaris = true;249 #else250 bool fSolaris = false;251 #endif252 #ifdef RT_OS_DARWIN253 bool fDarwin = true;254 #else255 bool fDarwin = false;256 #endif257 #ifdef VBOX_WITH_VRDP258 bool fVRDP = true;259 #else260 bool fVRDP = false;261 #endif262 263 if (u64Cmd == USAGE_DUMPOPTS)264 {265 fLinux = true;266 fWin = true;267 fSolaris = true;268 fDarwin = true;269 fVRDP = true;270 u64Cmd = USAGE_ALL;271 }272 273 RTPrintf("Usage:\n"274 "\n");275 276 if (u64Cmd == USAGE_ALL)277 {278 RTPrintf("VBoxManage [-v|-version] print version number and exit\n"279 "VBoxManage -nologo ... suppress the logo\n"280 "\n"281 "VBoxManage -convertSettings ... allow to auto-convert settings files\n"282 "VBoxManage -convertSettingsBackup ... allow to auto-convert settings files\n"283 " but create backup copies before\n"284 "VBoxManage -convertSettingsIgnore ... allow to auto-convert settings files\n"285 " but don't explicitly save the results\n"286 "\n");287 }288 289 if (u64Cmd & USAGE_LIST)290 {291 RTPrintf("VBoxManage list vms|runningvms|ostypes|hostdvds|hostfloppies|\n"292 " hostifs|hostinfo|hddbackends|hdds|dvds|floppies|\n"293 " usbhost|usbfilters|systemproperties\n"294 "\n");295 }296 297 if (u64Cmd & USAGE_SHOWVMINFO)298 {299 RTPrintf("VBoxManage showvminfo <uuid>|<name>\n"300 " [-details]\n"301 " [-statistics]\n"302 " [-machinereadable]\n"303 "\n");304 }305 306 if (u64Cmd & USAGE_REGISTERVM)307 {308 RTPrintf("VBoxManage registervm <filename>\n"309 "\n");310 }311 312 if (u64Cmd & USAGE_UNREGISTERVM)313 {314 RTPrintf("VBoxManage unregistervm <uuid>|<name>\n"315 " [-delete]\n"316 "\n");317 }318 319 if (u64Cmd & USAGE_CREATEVM)320 {321 RTPrintf("VBoxManage createvm -name <name>\n"322 " [-register]\n"323 " [-basefolder <path> | -settingsfile <path>]\n"324 " [-uuid <uuid>]\n"325 " \n"326 "\n");327 }328 329 if (u64Cmd & USAGE_MODIFYVM)330 {331 RTPrintf("VBoxManage modifyvm <uuid|name>\n"332 " [-name <name>]\n"333 " [-ostype <ostype>]\n"334 " [-memory <memorysize>]\n"335 " [-vram <vramsize>]\n"336 " [-acpi on|off]\n"337 " [-ioapic on|off]\n"338 " [-pae on|off]\n"339 " [-hwvirtex on|off|default]\n"340 " [-nestedpaging on|off]\n"341 " [-vtxvpid on|off]\n"342 " [-monitorcount <number>]\n"343 " [-accelerate3d <on|off>]\n"344 " [-bioslogofadein on|off]\n"345 " [-bioslogofadeout on|off]\n"346 " [-bioslogodisplaytime <msec>]\n"347 " [-bioslogoimagepath <imagepath>]\n"348 " [-biosbootmenu disabled|menuonly|messageandmenu]\n"349 " [-biossystemtimeoffset <msec>]\n"350 " [-biospxedebug on|off]\n"351 " [-boot<1-4> none|floppy|dvd|disk|net>]\n"352 " [-hd<a|b|d> none|<uuid>|<filename>]\n"353 " [-idecontroller PIIX3|PIIX4]\n"354 #ifdef VBOX_WITH_AHCI355 " [-sata on|off]\n"356 " [-sataportcount <1-30>]\n"357 " [-sataport<1-30> none|<uuid>|<filename>]\n"358 " [-sataideemulation<1-4> <1-30>]\n"359 #endif360 " [-dvd none|<uuid>|<filename>|host:<drive>]\n"361 " [-dvdpassthrough on|off]\n"362 " [-floppy disabled|empty|<uuid>|\n"363 " <filename>|host:<drive>]\n"364 " [-nic<1-N> none|null|nat|hostif|intnet]\n"365 " [-nictype<1-N> Am79C970A|Am79C973"366 #ifdef VBOX_WITH_E1000367 "|82540EM|82543GC"368 #endif369 "]\n"370 " [-cableconnected<1-N> on|off]\n"371 " [-nictrace<1-N> on|off]\n"372 " [-nictracefile<1-N> <filename>]\n"373 " [-nicspeed<1-N> <kbps>]\n"374 " [-hostifdev<1-N> none|<devicename>]\n"375 " [-intnet<1-N> <network name>]\n"376 " [-natnet<1-N> <network>|default]\n"377 " [-macaddress<1-N> auto|<mac>]\n"378 " [-uart<1-N> off|<I/O base> <IRQ>]\n"379 " [-uartmode<1-N> disconnected|\n"380 " server <pipe>|\n"381 " client <pipe>|\n"382 " <devicename>]\n"383 #ifdef VBOX_WITH_MEM_BALLOONING384 " [-guestmemoryballoon <balloonsize>]\n"385 #endif386 " [-gueststatisticsinterval <seconds>]\n"387 );388 if (fLinux)389 {390 RTPrintf(" [-tapsetup<1-N> none|<application>]\n"391 " [-tapterminate<1-N> none|<application>]\n");392 }393 RTPrintf(" [-audio none|null");394 if (fWin)395 {396 #ifdef VBOX_WITH_WINMM397 RTPrintf( "|winmm|dsound");398 #else399 RTPrintf( "|dsound");400 #endif401 }402 if (fSolaris)403 {404 RTPrintf( "|solaudio");405 }406 if (fLinux)407 {408 RTPrintf( "|oss"409 #ifdef VBOX_WITH_ALSA410 "|alsa"411 #endif412 #ifdef VBOX_WITH_PULSE413 "|pulse"414 #endif415 );416 }417 if (fDarwin)418 {419 RTPrintf( "|coreaudio");420 }421 RTPrintf( "]\n");422 RTPrintf(" [-audiocontroller ac97|sb16]\n"423 " [-clipboard disabled|hosttoguest|guesttohost|\n"424 " bidirectional]\n");425 if (fVRDP)426 {427 RTPrintf(" [-vrdp on|off]\n"428 " [-vrdpport default|<port>]\n"429 " [-vrdpaddress <host>]\n"430 " [-vrdpauthtype null|external|guest]\n"431 " [-vrdpmulticon on|off]\n"432 " [-vrdpreusecon on|off]\n");433 }434 RTPrintf(" [-usb on|off]\n"435 " [-usbehci on|off]\n"436 " [-snapshotfolder default|<path>]\n");437 RTPrintf("\n");438 }439 440 if (u64Cmd & USAGE_STARTVM)441 {442 RTPrintf("VBoxManage startvm <uuid>|<name>\n");443 if (fVRDP)444 RTPrintf(" [-type gui|vrdp]\n");445 RTPrintf("\n");446 }447 448 if (u64Cmd & USAGE_CONTROLVM)449 {450 RTPrintf("VBoxManage controlvm <uuid>|<name>\n"451 " pause|resume|reset|poweroff|savestate|\n"452 " acpipowerbutton|acpisleepbutton|\n"453 " keyboardputscancode <hex> [<hex> ...]|\n"454 " injectnmi|\n"455 " setlinkstate<1-4> on|off |\n"456 " usbattach <uuid>|<address> |\n"457 " usbdetach <uuid>|<address> |\n"458 " dvdattach none|<uuid>|<filename>|host:<drive> |\n"459 " floppyattach none|<uuid>|<filename>|host:<drive> |\n"460 " setvideomodehint <xres> <yres> <bpp> [display]|\n"461 " setcredentials <username> <password> <domain>\n"462 " [-allowlocallogon <yes|no>]\n"463 "\n");464 }465 466 if (u64Cmd & USAGE_DISCARDSTATE)467 {468 RTPrintf("VBoxManage discardstate <uuid>|<name>\n"469 "\n");470 }471 472 if (u64Cmd & USAGE_ADOPTSTATE)473 {474 RTPrintf("VBoxManage adoptstate <uuid>|<name> <state_file>\n"475 "\n");476 }477 478 if (u64Cmd & USAGE_SNAPSHOT)479 {480 RTPrintf("VBoxManage snapshot <uuid>|<name>\n"481 " take <name> [-desc <desc>] |\n"482 " discard <uuid>|<name> |\n"483 " discardcurrent -state|-all |\n"484 " edit <uuid>|<name>|-current\n"485 " [-newname <name>]\n"486 " [-newdesc <desc>] |\n"487 " showvminfo <uuid>|<name>\n"488 "\n");489 }490 491 if (u64Cmd & USAGE_REGISTERIMAGE)492 {493 RTPrintf("VBoxManage openmedium disk|dvd|floppy <filename>\n"494 " [-type normal|immutable|writethrough] (disk only)\n"495 "\n");496 }497 498 if (u64Cmd & USAGE_UNREGISTERIMAGE)499 {500 RTPrintf("VBoxManage closemedium disk|dvd|floppy <uuid>|<filename>\n"501 "\n");502 }503 504 if (u64Cmd & USAGE_SHOWHDINFO)505 {506 RTPrintf("VBoxManage showhdinfo <uuid>|<filename>\n"507 "\n");508 }509 510 if (u64Cmd & USAGE_CREATEHD)511 {512 /// @todo NEWMEDIA add -format to specify the hard disk backend513 RTPrintf("VBoxManage createhd -filename <filename>\n"514 " -size <megabytes>\n"515 " [-static]\n"516 " [-comment <comment>]\n"517 " [-register]\n"518 " [-type normal|writethrough] (default: normal)\n"519 "\n");520 }521 522 if (u64Cmd & USAGE_MODIFYHD)523 {524 RTPrintf("VBoxManage modifyhd <uuid>|<filename>\n"525 " settype normal|writethrough|immutable |\n"526 " compact\n"527 "\n");528 }529 530 if (u64Cmd & USAGE_CLONEHD)531 {532 RTPrintf("VBoxManage clonehd <uuid>|<filename> <outputfile>\n"533 "\n");534 }535 536 if (u64Cmd & USAGE_CONVERTDD)537 {538 RTPrintf("VBoxManage convertdd [-static] <filename> <outputfile>\n"539 "VBoxManage convertdd [-static] stdin <outputfile> <bytes>\n"540 "\n");541 }542 543 if (u64Cmd & USAGE_ADDISCSIDISK)544 {545 RTPrintf("VBoxManage addiscsidisk -server <name>|<ip>\n"546 " -target <target>\n"547 " [-port <port>]\n"548 " [-lun <lun>]\n"549 " [-encodedlun <lun>]\n"550 " [-username <username>]\n"551 " [-password <password>]\n"552 " [-comment <comment>]\n"553 "\n");554 }555 556 if (u64Cmd & USAGE_CREATEHOSTIF && fWin)557 {558 RTPrintf("VBoxManage createhostif <name>\n"559 "\n");560 }561 562 if (u64Cmd & USAGE_REMOVEHOSTIF && fWin)563 {564 RTPrintf("VBoxManage removehostif <uuid>|<name>\n"565 "\n");566 }567 568 if (u64Cmd & USAGE_GETEXTRADATA)569 {570 RTPrintf("VBoxManage getextradata global|<uuid>|<name>\n"571 " <key>|enumerate\n"572 "\n");573 }574 575 if (u64Cmd & USAGE_SETEXTRADATA)576 {577 RTPrintf("VBoxManage setextradata global|<uuid>|<name>\n"578 " <key>\n"579 " [<value>] (no value deletes key)\n"580 "\n");581 }582 583 if (u64Cmd & USAGE_SETPROPERTY)584 {585 RTPrintf("VBoxManage setproperty hdfolder default|<folder> |\n"586 " machinefolder default|<folder> |\n"587 " vrdpauthlibrary default|<library> |\n"588 " websrvauthlibrary default|null|<library> |\n"589 " hwvirtexenabled yes|no\n"590 " loghistorycount <value>\n"591 "\n");592 }593 594 if (u64Cmd & USAGE_USBFILTER_ADD)595 {596 RTPrintf("VBoxManage usbfilter add <index,0-N>\n"597 " -target <uuid>|<name>|global\n"598 " -name <string>\n"599 " -action ignore|hold (global filters only)\n"600 " [-active yes|no] (yes)\n"601 " [-vendorid <XXXX>] (null)\n"602 " [-productid <XXXX>] (null)\n"603 " [-revision <IIFF>] (null)\n"604 " [-manufacturer <string>] (null)\n"605 " [-product <string>] (null)\n"606 " [-remote yes|no] (null, VM filters only)\n"607 " [-serialnumber <string>] (null)\n"608 " [-maskedinterfaces <XXXXXXXX>]\n"609 "\n");610 }611 612 if (u64Cmd & USAGE_USBFILTER_MODIFY)613 {614 RTPrintf("VBoxManage usbfilter modify <index,0-N>\n"615 " -target <uuid>|<name>|global\n"616 " [-name <string>]\n"617 " [-action ignore|hold] (global filters only)\n"618 " [-active yes|no]\n"619 " [-vendorid <XXXX>|\"\"]\n"620 " [-productid <XXXX>|\"\"]\n"621 " [-revision <IIFF>|\"\"]\n"622 " [-manufacturer <string>|\"\"]\n"623 " [-product <string>|\"\"]\n"624 " [-remote yes|no] (null, VM filters only)\n"625 " [-serialnumber <string>|\"\"]\n"626 " [-maskedinterfaces <XXXXXXXX>]\n"627 "\n");628 }629 630 if (u64Cmd & USAGE_USBFILTER_REMOVE)631 {632 RTPrintf("VBoxManage usbfilter remove <index,0-N>\n"633 " -target <uuid>|<name>|global\n"634 "\n");635 }636 637 if (u64Cmd & USAGE_SHAREDFOLDER_ADD)638 {639 RTPrintf("VBoxManage sharedfolder add <vmname>|<uuid>\n"640 " -name <name> -hostpath <hostpath>\n"641 " [-transient] [-readonly]\n"642 "\n");643 }644 645 if (u64Cmd & USAGE_SHAREDFOLDER_REMOVE)646 {647 RTPrintf("VBoxManage sharedfolder remove <vmname>|<uuid>\n"648 " -name <name> [-transient]\n"649 "\n");650 }651 652 if (u64Cmd & USAGE_VM_STATISTICS)653 {654 RTPrintf("VBoxManage vmstatistics <vmname>|<uuid> [-reset]\n"655 " [-pattern <pattern>] [-descriptions]\n"656 "\n");657 }658 659 #ifdef VBOX_WITH_GUEST_PROPS660 if (u64Cmd & USAGE_GUESTPROPERTY)661 usageGuestProperty();662 #endif /* VBOX_WITH_GUEST_PROPS defined */663 664 if (u64Cmd & USAGE_METRICS)665 {666 RTPrintf("VBoxManage metrics list [*|host|<vmname> [<metric_list>]] (comma-separated)\n\n"667 "VBoxManage metrics setup\n"668 " [-period <seconds>]\n"669 " [-samples <count>]\n"670 " [-list]\n"671 " [*|host|<vmname> [<metric_list>]]\n\n"672 "VBoxManage metrics query [*|host|<vmname> [<metric_list>]]\n\n"673 "VBoxManage metrics collect\n"674 " [-period <seconds>]\n"675 " [-samples <count>]\n"676 " [-list]\n"677 " [-detach]\n"678 " [*|host|<vmname> [<metric_list>]]\n"679 "\n");680 }681 682 }683 684 /**685 * Print a usage synopsis and the syntax error message.686 */687 int errorSyntax(USAGECATEGORY u64Cmd, const char *pszFormat, ...)688 {689 va_list args;690 showLogo(); // show logo even if suppressed691 #ifndef VBOX_ONLY_DOCS692 if (g_fInternalMode)693 printUsageInternal(u64Cmd);694 else695 printUsage(u64Cmd);696 #endif /* !VBOX_ONLY_DOCS */697 va_start(args, pszFormat);698 RTPrintf("\n"699 "Syntax error: %N\n", pszFormat, &args);700 va_end(args);701 return 1;702 }703 704 /**705 * Print an error message without the syntax stuff.706 */707 int errorArgument(const char *pszFormat, ...)708 {709 va_list args;710 va_start(args, pszFormat);711 RTPrintf("error: %N\n", pszFormat, &args);712 va_end(args);713 return 1;714 }715 716 #ifndef VBOX_ONLY_DOCS717 /**718 * Print out progress on the console719 */720 static void showProgress(ComPtr<IProgress> progress)721 {722 BOOL fCompleted;723 LONG currentPercent;724 LONG lastPercent = 0;725 726 RTPrintf("0%%...");727 RTStrmFlush(g_pStdOut);728 while (SUCCEEDED(progress->COMGETTER(Completed(&fCompleted))))729 {730 progress->COMGETTER(Percent(¤tPercent));731 732 /* did we cross a 10% mark? */733 if (((currentPercent / 10) > (lastPercent / 10)))734 {735 /* make sure to also print out missed steps */736 for (LONG curVal = (lastPercent / 10) * 10 + 10; curVal <= (currentPercent / 10) * 10; curVal += 10)737 {738 if (curVal < 100)739 {740 RTPrintf("%ld%%...", curVal);741 RTStrmFlush(g_pStdOut);742 }743 }744 lastPercent = (currentPercent / 10) * 10;745 }746 if (fCompleted)747 break;748 749 /* make sure the loop is not too tight */750 progress->WaitForCompletion(100);751 }752 753 /* complete the line. */754 HRESULT rc;755 if (SUCCEEDED(progress->COMGETTER(ResultCode)(&rc)))756 {757 if (SUCCEEDED(rc))758 RTPrintf("100%%\n");759 else760 RTPrintf("FAILED\n");761 }762 else763 RTPrintf("\n");764 RTStrmFlush(g_pStdOut);765 }766 767 static int handleRegisterVM(int argc, char *argv[],768 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)769 {770 HRESULT rc;771 772 if (argc != 1)773 return errorSyntax(USAGE_REGISTERVM, "Incorrect number of parameters");774 775 ComPtr<IMachine> machine;776 CHECK_ERROR(virtualBox, OpenMachine(Bstr(argv[0]), machine.asOutParam()));777 if (SUCCEEDED(rc))778 {779 ASSERT(machine);780 CHECK_ERROR(virtualBox, RegisterMachine(machine));781 }782 return SUCCEEDED(rc) ? 0 : 1;783 }784 785 static int handleUnregisterVM(int argc, char *argv[],786 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)787 {788 HRESULT rc;789 790 if ((argc != 1) && (argc != 2))791 return errorSyntax(USAGE_UNREGISTERVM, "Incorrect number of parameters");792 793 ComPtr<IMachine> machine;794 /* assume it's a UUID */795 rc = virtualBox->GetMachine(Guid(argv[0]), machine.asOutParam());796 if (FAILED(rc) || !machine)797 {798 /* must be a name */799 CHECK_ERROR(virtualBox, FindMachine(Bstr(argv[0]), machine.asOutParam()));800 }801 if (machine)802 {803 Guid uuid;804 machine->COMGETTER(Id)(uuid.asOutParam());805 machine = NULL;806 CHECK_ERROR(virtualBox, UnregisterMachine(uuid, machine.asOutParam()));807 if (SUCCEEDED(rc) && machine)808 {809 /* are we supposed to delete the config file? */810 if ((argc == 2) && (strcmp(argv[1], "-delete") == 0))811 {812 CHECK_ERROR(machine, DeleteSettings());813 }814 }815 }816 return SUCCEEDED(rc) ? 0 : 1;817 }818 819 static int handleCreateHardDisk(int argc, char *argv[],820 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)821 {822 HRESULT rc;823 Bstr filename;824 uint64_t sizeMB = 0;825 bool fStatic = false;826 Bstr comment;827 bool fRegister = false;828 const char *type = "normal";829 830 /* let's have a closer look at the arguments */831 for (int i = 0; i < argc; i++)832 {833 if (strcmp(argv[i], "-filename") == 0)834 {835 if (argc <= i + 1)836 return errorArgument("Missing argument to '%s'", argv[i]);837 i++;838 filename = argv[i];839 }840 else if (strcmp(argv[i], "-size") == 0)841 {842 if (argc <= i + 1)843 return errorArgument("Missing argument to '%s'", argv[i]);844 i++;845 sizeMB = RTStrToUInt64(argv[i]);846 }847 else if (strcmp(argv[i], "-static") == 0)848 {849 fStatic = true;850 }851 else if (strcmp(argv[i], "-comment") == 0)852 {853 if (argc <= i + 1)854 return errorArgument("Missing argument to '%s'", argv[i]);855 i++;856 comment = argv[i];857 }858 else if (strcmp(argv[i], "-register") == 0)859 {860 fRegister = true;861 }862 else if (strcmp(argv[i], "-type") == 0)863 {864 if (argc <= i + 1)865 return errorArgument("Missing argument to '%s'", argv[i]);866 i++;867 type = argv[i];868 }869 else870 return errorSyntax(USAGE_CREATEHD, "Invalid parameter '%s'", Utf8Str(argv[i]).raw());871 }872 /* check the outcome */873 if (!filename || (sizeMB == 0))874 return errorSyntax(USAGE_CREATEHD, "Parameters -filename and -size are required");875 876 if (strcmp(type, "normal") && strcmp(type, "writethrough"))877 return errorArgument("Invalid hard disk type '%s' specified", Utf8Str(type).raw());878 879 ComPtr<IHardDisk2> hardDisk;880 CHECK_ERROR(virtualBox, CreateHardDisk2(Bstr("VDI"), filename, hardDisk.asOutParam()));881 if (SUCCEEDED(rc) && hardDisk)882 {883 /* we will close the hard disk after the storage has been successfully884 * created unless fRegister is set */885 bool doClose = false;886 887 CHECK_ERROR(hardDisk,COMSETTER(Description)(comment));888 ComPtr<IProgress> progress;889 if (fStatic)890 {891 CHECK_ERROR(hardDisk, CreateFixedStorage(sizeMB, progress.asOutParam()));892 }893 else894 {895 CHECK_ERROR(hardDisk, CreateDynamicStorage(sizeMB, progress.asOutParam()));896 }897 if (SUCCEEDED(rc) && progress)898 {899 if (fStatic)900 showProgress(progress);901 else902 CHECK_ERROR(progress, WaitForCompletion(-1));903 if (SUCCEEDED(rc))904 {905 progress->COMGETTER(ResultCode)(&rc);906 if (FAILED(rc))907 {908 com::ProgressErrorInfo info(progress);909 if (info.isBasicAvailable())910 RTPrintf("Error: failed to create hard disk. Error message: %lS\n", info.getText().raw());911 else912 RTPrintf("Error: failed to create hard disk. No error message available!\n");913 }914 else915 {916 doClose = !fRegister;917 918 Guid uuid;919 CHECK_ERROR(hardDisk, COMGETTER(Id)(uuid.asOutParam()));920 921 if (strcmp(type, "normal") == 0)922 {923 /* nothing required, default */924 }925 else if (strcmp(type, "writethrough") == 0)926 {927 CHECK_ERROR(hardDisk, COMSETTER(Type)(HardDiskType_Writethrough));928 }929 930 RTPrintf("Disk image created. UUID: %s\n", uuid.toString().raw());931 }932 }933 }934 if (doClose)935 {936 CHECK_ERROR(hardDisk, Close());937 }938 }939 return SUCCEEDED(rc) ? 0 : 1;940 }941 942 static DECLCALLBACK(int) hardDiskProgressCallback(PVM pVM, unsigned uPercent, void *pvUser)943 {944 unsigned *pPercent = (unsigned *)pvUser;945 946 if (*pPercent != uPercent)947 {948 *pPercent = uPercent;949 RTPrintf(".");950 if ((uPercent % 10) == 0 && uPercent)951 RTPrintf("%d%%", uPercent);952 RTStrmFlush(g_pStdOut);953 }954 955 return VINF_SUCCESS;956 }957 958 959 static int handleModifyHardDisk(int argc, char *argv[],960 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)961 {962 HRESULT rc;963 964 /* The uuid/filename and a command */965 if (argc < 2)966 return errorSyntax(USAGE_MODIFYHD, "Incorrect number of parameters");967 968 ComPtr<IHardDisk2> hardDisk;969 Bstr filepath;970 971 /* first guess is that it's a UUID */972 Guid uuid(argv[0]);973 rc = virtualBox->GetHardDisk2(uuid, hardDisk.asOutParam());974 /* no? then it must be a filename */975 if (!hardDisk)976 {977 filepath = argv[0];978 CHECK_ERROR(virtualBox, FindHardDisk2(filepath, hardDisk.asOutParam()));979 }980 981 /* let's find out which command */982 if (strcmp(argv[1], "settype") == 0)983 {984 /* hard disk must be registered */985 if (SUCCEEDED(rc) && hardDisk)986 {987 char *type = NULL;988 989 if (argc <= 2)990 return errorArgument("Missing argument to for settype");991 992 type = argv[2];993 994 HardDiskType_T hddType;995 CHECK_ERROR(hardDisk, COMGETTER(Type)(&hddType));996 997 if (strcmp(type, "normal") == 0)998 {999 if (hddType != HardDiskType_Normal)1000 CHECK_ERROR(hardDisk, COMSETTER(Type)(HardDiskType_Normal));1001 }1002 else if (strcmp(type, "writethrough") == 0)1003 {1004 if (hddType != HardDiskType_Writethrough)1005 CHECK_ERROR(hardDisk, COMSETTER(Type)(HardDiskType_Writethrough));1006 1007 }1008 else if (strcmp(type, "immutable") == 0)1009 {1010 if (hddType != HardDiskType_Immutable)1011 CHECK_ERROR(hardDisk, COMSETTER(Type)(HardDiskType_Immutable));1012 }1013 else1014 {1015 return errorArgument("Invalid hard disk type '%s' specified", Utf8Str(type).raw());1016 }1017 }1018 else1019 return errorArgument("Hard disk image not registered");1020 }1021 else if (strcmp(argv[1], "compact") == 0)1022 {1023 /* the hard disk image might not be registered */1024 if (!hardDisk)1025 {1026 virtualBox->OpenHardDisk2(Bstr(argv[0]), hardDisk.asOutParam());1027 if (!hardDisk)1028 return errorArgument("Hard disk image not found");1029 }1030 1031 Bstr format;1032 hardDisk->COMGETTER(Format)(format.asOutParam());1033 if (format != "VDI")1034 return errorArgument("Invalid hard disk type. The command only works on VDI files\n");1035 1036 Bstr fileName;1037 hardDisk->COMGETTER(Location)(fileName.asOutParam());1038 1039 /* make sure the object reference is released */1040 hardDisk = NULL;1041 1042 unsigned uProcent;1043 1044 RTPrintf("Shrinking '%lS': 0%%", fileName.raw());1045 int vrc = VDIShrinkImage(Utf8Str(fileName).raw(), hardDiskProgressCallback, &uProcent);1046 if (RT_FAILURE(vrc))1047 {1048 RTPrintf("Error while shrinking hard disk image: %Rrc\n", vrc);1049 rc = E_FAIL;1050 }1051 }1052 else1053 return errorSyntax(USAGE_MODIFYHD, "Invalid parameter '%s'", Utf8Str(argv[1]).raw());1054 1055 return SUCCEEDED(rc) ? 0 : 1;1056 }1057 1058 static int handleCloneHardDisk(int argc, char *argv[],1059 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)1060 {1061 #if 11062 RTPrintf("Error: Clone hard disk operation is temporarily unavailable!\n");1063 return 1;1064 #else1065 /// @todo NEWMEDIA use IHardDisk2::cloneTo/flattenTo (not yet implemented)1066 HRESULT rc;1067 1068 /* source hard disk and target path */1069 if (argc != 2)1070 return errorSyntax(USAGE_CLONEHD, "Incorrect number of parameters");1071 1072 /* first guess is that it's a UUID */1073 Guid uuid(argv[0]);1074 ComPtr<IHardDisk2> hardDisk;1075 rc = virtualBox->GetHardDisk2(uuid, hardDisk.asOutParam());1076 if (!hardDisk)1077 {1078 /* not successful? Then it must be a filename */1079 CHECK_ERROR(virtualBox, OpenHardDisk2(Bstr(argv[0]), hardDisk.asOutParam()));1080 }1081 if (hardDisk)1082 {1083 ComPtr<IProgress> progress;1084 CHECK_ERROR(hardDisk, CloneToImage(Bstr(argv[1]), hardDisk.asOutParam(), progress.asOutParam()));1085 if (SUCCEEDED(rc))1086 {1087 showProgress(progress);1088 progress->COMGETTER(ResultCode)(&rc);1089 if (FAILED(rc))1090 {1091 com::ProgressErrorInfo info(progress);1092 if (info.isBasicAvailable())1093 {1094 RTPrintf("Error: failed to clone disk image. Error message: %lS\n", info.getText().raw());1095 }1096 else1097 {1098 RTPrintf("Error: failed to clone disk image. No error message available!\n");1099 }1100 }1101 }1102 }1103 return SUCCEEDED(rc) ? 0 : 1;1104 #endif1105 }1106 1107 static int handleConvertDDImage(int argc, char *argv[])1108 {1109 int arg = 0;1110 VDIIMAGETYPE enmImgType = VDI_IMAGE_TYPE_NORMAL;1111 if (argc >= 1 && !strcmp(argv[arg], "-static"))1112 {1113 arg++;1114 enmImgType = VDI_IMAGE_TYPE_FIXED;1115 }1116 1117 #if defined(RT_OS_LINUX) || defined(RT_OS_DARWIN) || defined(RT_OS_SOLARIS)1118 const bool fReadFromStdIn = (argc >= arg + 1) && !strcmp(argv[arg], "stdin");1119 #else1120 const bool fReadFromStdIn = false;1121 #endif1122 1123 if ((!fReadFromStdIn && argc != arg + 2) || (fReadFromStdIn && argc != arg + 3))1124 return errorSyntax(USAGE_CONVERTDD, "Incorrect number of parameters");1125 1126 RTPrintf("Converting VDI: from DD image file=\"%s\" to file=\"%s\"...\n",1127 argv[arg], argv[arg + 1]);1128 1129 /* open raw image file. */1130 RTFILE File;1131 int rc = VINF_SUCCESS;1132 if (fReadFromStdIn)1133 File = 0;1134 else1135 rc = RTFileOpen(&File, argv[arg], RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE);1136 if (RT_FAILURE(rc))1137 {1138 RTPrintf("File=\"%s\" open error: %Rrf\n", argv[arg], rc);1139 return rc;1140 }1141 1142 uint64_t cbFile;1143 /* get image size. */1144 if (fReadFromStdIn)1145 cbFile = RTStrToUInt64(argv[arg + 2]);1146 else1147 rc = RTFileGetSize(File, &cbFile);1148 if (RT_SUCCESS(rc))1149 {1150 RTPrintf("Creating %s image with size %RU64 bytes (%RU64MB)...\n", (enmImgType == VDI_IMAGE_TYPE_FIXED) ? "fixed" : "dynamic", cbFile, (cbFile + _1M - 1) / _1M);1151 char pszComment[256];1152 RTStrPrintf(pszComment, sizeof(pszComment), "Converted image from %s", argv[arg]);1153 rc = VDICreateBaseImage(argv[arg + 1],1154 enmImgType,1155 cbFile,1156 pszComment, NULL, NULL);1157 if (RT_SUCCESS(rc))1158 {1159 PVDIDISK pVdi = VDIDiskCreate();1160 rc = VDIDiskOpenImage(pVdi, argv[arg + 1], VDI_OPEN_FLAGS_NORMAL);1161 if (RT_SUCCESS(rc))1162 {1163 /* alloc work buffer. */1164 size_t cbBuffer = VDIDiskGetBufferSize(pVdi);1165 void *pvBuf = RTMemAlloc(cbBuffer);1166 if (pvBuf)1167 {1168 uint64_t offFile = 0;1169 while (offFile < cbFile)1170 {1171 size_t cbRead = 0;1172 size_t cbToRead = cbFile - offFile >= (uint64_t) cbBuffer ?1173 cbBuffer : (size_t) (cbFile - offFile);1174 rc = RTFileRead(File, pvBuf, cbToRead, &cbRead);1175 if (RT_FAILURE(rc) || !cbRead)1176 break;1177 rc = VDIDiskWrite(pVdi, offFile, pvBuf, cbRead);1178 if (RT_FAILURE(rc))1179 break;1180 offFile += cbRead;1181 }1182 1183 RTMemFree(pvBuf);1184 }1185 else1186 rc = VERR_NO_MEMORY;1187 1188 VDIDiskCloseImage(pVdi);1189 }1190 1191 if (RT_FAILURE(rc))1192 {1193 /* delete image on error */1194 RTPrintf("Failed (%Rrc)!\n", rc);1195 VDIDeleteImage(argv[arg + 1]);1196 }1197 }1198 else1199 RTPrintf("Failed to create output file (%Rrc)!\n", rc);1200 }1201 RTFileClose(File);1202 1203 return rc;1204 }1205 1206 static int handleAddiSCSIDisk(int argc, char *argv[],1207 ComPtr <IVirtualBox> aVirtualBox, ComPtr<ISession> aSession)1208 {1209 #if 11210 RTPrintf("Error: Create iSCSI hard disk operation is temporarily unavailable!\n");1211 return 1;1212 #else1213 HRESULT rc;1214 Bstr server;1215 Bstr target;1216 uint16_t port = UINT16_MAX;1217 uint64_t lun = UINT64_MAX;1218 Bstr username;1219 Bstr password;1220 Bstr comment;1221 1222 /* at least server and target */1223 if (argc < 4)1224 return errorSyntax(USAGE_ADDISCSIDISK, "Not enough parameters");1225 1226 /* let's have a closer look at the arguments */1227 for (int i = 0; i < argc; i++)1228 {1229 if (strcmp(argv[i], "-server") == 0)1230 {1231 if (argc <= i + 1)1232 return errorArgument("Missing argument to '%s'", argv[i]);1233 i++;1234 server = argv[i];1235 }1236 else if (strcmp(argv[i], "-target") == 0)1237 {1238 if (argc <= i + 1)1239 return errorArgument("Missing argument to '%s'", argv[i]);1240 i++;1241 target = argv[i];1242 }1243 else if (strcmp(argv[i], "-port") == 0)1244 {1245 if (argc <= i + 1)1246 return errorArgument("Missing argument to '%s'", argv[i]);1247 i++;1248 port = atoi(argv[i]);1249 }1250 else if (strcmp(argv[i], "-lun") == 0)1251 {1252 /** @todo move the LUN encoding algorithm into IISCSIHardDisk, add decoding */1253 if (argc <= i + 1)1254 return errorArgument("Missing argument to '%s'", argv[i]);1255 i++;1256 char *pszNext;1257 int rc = RTStrToUInt64Ex(argv[i], &pszNext, 0, &lun);1258 if (RT_FAILURE(rc) || *pszNext != '\0' || lun >= 16384)1259 return errorArgument("Invalid LUN number '%s'", argv[i]);1260 if (lun <= 255)1261 {1262 /* Assume bus identifier = 0. */1263 lun = (lun << 48); /* uses peripheral device addressing method */1264 }1265 else1266 {1267 /* Check above already limited the LUN to 14 bits. */1268 lun = (lun << 48) | RT_BIT_64(62); /* uses flat space addressing method */1269 }1270 }1271 else if (strcmp(argv[i], "-encodedlun") == 0)1272 {1273 if (argc <= i + 1)1274 return errorArgument("Missing argument to '%s'", argv[i]);1275 i++;1276 char *pszNext;1277 int rc = RTStrToUInt64Ex(argv[i], &pszNext, 0, &lun);1278 if (RT_FAILURE(rc) || *pszNext != '\0')1279 return errorArgument("Invalid encoded LUN number '%s'", argv[i]);1280 }1281 else if (strcmp(argv[i], "-username") == 0)1282 {1283 if (argc <= i + 1)1284 return errorArgument("Missing argument to '%s'", argv[i]);1285 i++;1286 username = argv[i];1287 }1288 else if (strcmp(argv[i], "-password") == 0)1289 {1290 if (argc <= i + 1)1291 return errorArgument("Missing argument to '%s'", argv[i]);1292 i++;1293 password = argv[i];1294 }1295 else if (strcmp(argv[i], "-comment") == 0)1296 {1297 if (argc <= i + 1)1298 return errorArgument("Missing argument to '%s'", argv[i]);1299 i++;1300 comment = argv[i];1301 }1302 else1303 return errorSyntax(USAGE_ADDISCSIDISK, "Invalid parameter '%s'", Utf8Str(argv[i]).raw());1304 }1305 1306 /* check for required options */1307 if (!server || !target)1308 return errorSyntax(USAGE_ADDISCSIDISK, "Parameters -server and -target are required");1309 1310 ComPtr<IHardDisk> hardDisk;1311 CHECK_ERROR(aVirtualBox, CreateHardDisk(HardDiskStorageType_ISCSIHardDisk, hardDisk.asOutParam()));1312 if (SUCCEEDED(rc) && hardDisk)1313 {1314 CHECK_ERROR(hardDisk, COMSETTER(Description)(comment));1315 ComPtr<IISCSIHardDisk> iSCSIDisk = hardDisk;1316 CHECK_ERROR(iSCSIDisk, COMSETTER(Server)(server));1317 if (port != UINT16_MAX)1318 CHECK_ERROR(iSCSIDisk, COMSETTER(Port)(port));1319 CHECK_ERROR(iSCSIDisk, COMSETTER(Target)(target));1320 if (lun != UINT64_MAX)1321 CHECK_ERROR(iSCSIDisk, COMSETTER(Lun)(lun));1322 CHECK_ERROR(iSCSIDisk, COMSETTER(UserName)(username));1323 CHECK_ERROR(iSCSIDisk, COMSETTER(Password)(password));1324 1325 if (SUCCEEDED(rc))1326 {1327 CHECK_ERROR(aVirtualBox, RegisterHardDisk(hardDisk));1328 }1329 1330 if (SUCCEEDED(rc))1331 {1332 Guid guid;1333 CHECK_ERROR(hardDisk, COMGETTER(Id)(guid.asOutParam()));1334 RTPrintf("iSCSI disk created. UUID: %s\n", guid.toString().raw());1335 }1336 }1337 1338 return SUCCEEDED(rc) ? 0 : 1;1339 #endif1340 }1341 1342 static int handleCreateVM(int argc, char *argv[],1343 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)1344 {1345 HRESULT rc;1346 Bstr baseFolder;1347 Bstr settingsFile;1348 Bstr name;1349 RTUUID id;1350 bool fRegister = false;1351 1352 RTUuidClear(&id);1353 for (int i = 0; i < argc; i++)1354 {1355 if (strcmp(argv[i], "-basefolder") == 0)1356 {1357 if (argc <= i + 1)1358 return errorArgument("Missing argument to '%s'", argv[i]);1359 i++;1360 baseFolder = argv[i];1361 }1362 else if (strcmp(argv[i], "-settingsfile") == 0)1363 {1364 if (argc <= i + 1)1365 return errorArgument("Missing argument to '%s'", argv[i]);1366 i++;1367 settingsFile = argv[i];1368 }1369 else if (strcmp(argv[i], "-name") == 0)1370 {1371 if (argc <= i + 1)1372 return errorArgument("Missing argument to '%s'", argv[i]);1373 i++;1374 name = argv[i];1375 }1376 else if (strcmp(argv[i], "-uuid") == 0)1377 {1378 if (argc <= i + 1)1379 return errorArgument("Missing argument to '%s'", argv[i]);1380 i++;1381 if (RT_FAILURE(RTUuidFromStr(&id, argv[i])))1382 return errorArgument("Invalid UUID format %s\n", argv[i]);1383 }1384 else if (strcmp(argv[i], "-register") == 0)1385 {1386 fRegister = true;1387 }1388 else1389 return errorSyntax(USAGE_CREATEVM, "Invalid parameter '%s'", Utf8Str(argv[i]).raw());1390 }1391 if (!name)1392 return errorSyntax(USAGE_CREATEVM, "Parameter -name is required");1393 1394 if (!!baseFolder && !!settingsFile)1395 return errorSyntax(USAGE_CREATEVM, "Either -basefolder or -settingsfile must be specified");1396 1397 do1398 {1399 ComPtr<IMachine> machine;1400 1401 if (!settingsFile)1402 CHECK_ERROR_BREAK(virtualBox,1403 CreateMachine(baseFolder, name, Guid(id), machine.asOutParam()));1404 else1405 CHECK_ERROR_BREAK(virtualBox,1406 CreateLegacyMachine(settingsFile, name, Guid(id), machine.asOutParam()));1407 1408 CHECK_ERROR_BREAK(machine, SaveSettings());1409 if (fRegister)1410 {1411 CHECK_ERROR_BREAK(virtualBox, RegisterMachine(machine));1412 }1413 Guid uuid;1414 CHECK_ERROR_BREAK(machine, COMGETTER(Id)(uuid.asOutParam()));1415 CHECK_ERROR_BREAK(machine, COMGETTER(SettingsFilePath)(settingsFile.asOutParam()));1416 RTPrintf("Virtual machine '%ls' is created%s.\n"1417 "UUID: %s\n"1418 "Settings file: '%ls'\n",1419 name.raw(), fRegister ? " and registered" : "",1420 uuid.toString().raw(), settingsFile.raw());1421 }1422 while (0);1423 1424 return SUCCEEDED(rc) ? 0 : 1;1425 }1426 1427 /**1428 * Parses a number.1429 *1430 * @returns Valid number on success.1431 * @returns 0 if invalid number. All necesary bitching has been done.1432 * @param psz Pointer to the nic number.1433 */1434 static unsigned parseNum(const char *psz, unsigned cMaxNum, const char *name)1435 {1436 uint32_t u32;1437 char *pszNext;1438 int rc = RTStrToUInt32Ex(psz, &pszNext, 10, &u32);1439 if ( RT_SUCCESS(rc)1440 && *pszNext == '\0'1441 && u32 >= 11442 && u32 <= cMaxNum)1443 return (unsigned)u32;1444 errorArgument("Invalid %s number '%s'", name, psz);1445 return 0;1446 }1447 1448 static int handleModifyVM(int argc, char *argv[],1449 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)1450 {1451 HRESULT rc;1452 Bstr name;1453 Bstr ostype;1454 ULONG memorySize = 0;1455 ULONG vramSize = 0;1456 char *acpi = NULL;1457 char *hwvirtex = NULL;1458 char *nestedpaging = NULL;1459 char *vtxvpid = NULL;1460 char *pae = NULL;1461 char *ioapic = NULL;1462 int monitorcount = -1;1463 char *accelerate3d = NULL;1464 char *bioslogofadein = NULL;1465 char *bioslogofadeout = NULL;1466 uint32_t bioslogodisplaytime = ~0;1467 char *bioslogoimagepath = NULL;1468 char *biosbootmenumode = NULL;1469 char *biossystemtimeoffset = NULL;1470 char *biospxedebug = NULL;1471 DeviceType_T bootDevice[4];1472 int bootDeviceChanged[4] = { false };1473 char *hdds[34] = {0};1474 char *dvd = NULL;1475 char *dvdpassthrough = NULL;1476 char *idecontroller = NULL;1477 char *floppy = NULL;1478 char *audio = NULL;1479 char *audiocontroller = NULL;1480 char *clipboard = NULL;1481 #ifdef VBOX_WITH_VRDP1482 char *vrdp = NULL;1483 uint16_t vrdpport = UINT16_MAX;1484 char *vrdpaddress = NULL;1485 char *vrdpauthtype = NULL;1486 char *vrdpmulticon = NULL;1487 char *vrdpreusecon = NULL;1488 #endif1489 int fUsbEnabled = -1;1490 int fUsbEhciEnabled = -1;1491 char *snapshotFolder = NULL;1492 ULONG guestMemBalloonSize = (ULONG)-1;1493 ULONG guestStatInterval = (ULONG)-1;1494 int fSataEnabled = -1;1495 int sataPortCount = -1;1496 int sataBootDevices[4] = {-1,-1,-1,-1};1497 1498 /* VM ID + at least one parameter. Parameter arguments are checked1499 * individually. */1500 if (argc < 2)1501 return errorSyntax(USAGE_MODIFYVM, "Not enough parameters");1502 1503 /* Get the number of network adapters */1504 ULONG NetworkAdapterCount = 0;1505 {1506 ComPtr <ISystemProperties> info;1507 CHECK_ERROR_RET (virtualBox, COMGETTER(SystemProperties) (info.asOutParam()), 1);1508 CHECK_ERROR_RET (info, COMGETTER(NetworkAdapterCount) (&NetworkAdapterCount), 1);1509 }1510 ULONG SerialPortCount = 0;1511 {1512 ComPtr <ISystemProperties> info;1513 CHECK_ERROR_RET (virtualBox, COMGETTER(SystemProperties) (info.asOutParam()), 1);1514 CHECK_ERROR_RET (info, COMGETTER(SerialPortCount) (&SerialPortCount), 1);1515 }1516 1517 std::vector <char *> nics (NetworkAdapterCount, 0);1518 std::vector <char *> nictype (NetworkAdapterCount, 0);1519 std::vector <char *> cableconnected (NetworkAdapterCount, 0);1520 std::vector <char *> nictrace (NetworkAdapterCount, 0);1521 std::vector <char *> nictracefile (NetworkAdapterCount, 0);1522 std::vector <char *> nicspeed (NetworkAdapterCount, 0);1523 std::vector <char *> hostifdev (NetworkAdapterCount, 0);1524 std::vector <const char *> intnet (NetworkAdapterCount, 0);1525 std::vector <const char *> natnet (NetworkAdapterCount, 0);1526 #ifdef RT_OS_LINUX1527 std::vector <char *> tapsetup (NetworkAdapterCount, 0);1528 std::vector <char *> tapterm (NetworkAdapterCount, 0);1529 #endif1530 std::vector <char *> macs (NetworkAdapterCount, 0);1531 std::vector <char *> uarts_mode (SerialPortCount, 0);1532 std::vector <ULONG> uarts_base (SerialPortCount, 0);1533 std::vector <ULONG> uarts_irq (SerialPortCount, 0);1534 std::vector <char *> uarts_path (SerialPortCount, 0);1535 1536 for (int i = 1; i < argc; i++)1537 {1538 if (strcmp(argv[i], "-name") == 0)1539 {1540 if (argc <= i + 1)1541 return errorArgument("Missing argument to '%s'", argv[i]);1542 i++;1543 name = argv[i];1544 }1545 else if (strcmp(argv[i], "-ostype") == 0)1546 {1547 if (argc <= i + 1)1548 return errorArgument("Missing argument to '%s'", argv[i]);1549 i++;1550 ostype = argv[i];1551 }1552 else if (strcmp(argv[i], "-memory") == 0)1553 {1554 if (argc <= i + 1)1555 return errorArgument("Missing argument to '%s'", argv[i]);1556 i++;1557 memorySize = atoi(argv[i]);1558 }1559 else if (strcmp(argv[i], "-vram") == 0)1560 {1561 if (argc <= i + 1)1562 return errorArgument("Missing argument to '%s'", argv[i]);1563 i++;1564 vramSize = atoi(argv[i]);1565 }1566 else if (strcmp(argv[i], "-acpi") == 0)1567 {1568 if (argc <= i + 1)1569 return errorArgument("Missing argument to '%s'", argv[i]);1570 i++;1571 acpi = argv[i];1572 }1573 else if (strcmp(argv[i], "-ioapic") == 0)1574 {1575 if (argc <= i + 1)1576 return errorArgument("Missing argument to '%s'", argv[i]);1577 i++;1578 ioapic = argv[i];1579 }1580 else if (strcmp(argv[i], "-hwvirtex") == 0)1581 {1582 if (argc <= i + 1)1583 return errorArgument("Missing argument to '%s'", argv[i]);1584 i++;1585 hwvirtex = argv[i];1586 }1587 else if (strcmp(argv[i], "-nestedpaging") == 0)1588 {1589 if (argc <= i + 1)1590 return errorArgument("Missing argument to '%s'", argv[i]);1591 i++;1592 nestedpaging = argv[i];1593 }1594 else if (strcmp(argv[i], "-vtxvpid") == 0)1595 {1596 if (argc <= i + 1)1597 return errorArgument("Missing argument to '%s'", argv[i]);1598 i++;1599 vtxvpid = argv[i];1600 }1601 else if (strcmp(argv[i], "-pae") == 0)1602 {1603 if (argc <= i + 1)1604 return errorArgument("Missing argument to '%s'", argv[i]);1605 i++;1606 pae = argv[i];1607 }1608 else if (strcmp(argv[i], "-monitorcount") == 0)1609 {1610 if (argc <= i + 1)1611 return errorArgument("Missing argument to '%s'", argv[i]);1612 i++;1613 monitorcount = atoi(argv[i]);1614 }1615 else if (strcmp(argv[i], "-accelerate3d") == 0)1616 {1617 if (argc <= i + 1)1618 return errorArgument("Missing argument to '%s'", argv[i]);1619 i++;1620 accelerate3d = argv[i];1621 }1622 else if (strcmp(argv[i], "-bioslogofadein") == 0)1623 {1624 if (argc <= i + 1)1625 return errorArgument("Missing argument to '%s'", argv[i]);1626 i++;1627 bioslogofadein = argv[i];1628 }1629 else if (strcmp(argv[i], "-bioslogofadeout") == 0)1630 {1631 if (argc <= i + 1)1632 return errorArgument("Missing argument to '%s'", argv[i]);1633 i++;1634 bioslogofadeout = argv[i];1635 }1636 else if (strcmp(argv[i], "-bioslogodisplaytime") == 0)1637 {1638 if (argc <= i + 1)1639 return errorArgument("Missing argument to '%s'", argv[i]);1640 i++;1641 bioslogodisplaytime = atoi(argv[i]);1642 }1643 else if (strcmp(argv[i], "-bioslogoimagepath") == 0)1644 {1645 if (argc <= i + 1)1646 return errorArgument("Missing argument to '%s'", argv[i]);1647 i++;1648 bioslogoimagepath = argv[i];1649 }1650 else if (strcmp(argv[i], "-biosbootmenu") == 0)1651 {1652 if (argc <= i + 1)1653 return errorArgument("Missing argument to '%s'", argv[i]);1654 i++;1655 biosbootmenumode = argv[i];1656 }1657 else if (strcmp(argv[i], "-biossystemtimeoffset") == 0)1658 {1659 if (argc <= i + 1)1660 return errorArgument("Missing argument to '%s'", argv[i]);1661 i++;1662 biossystemtimeoffset = argv[i];1663 }1664 else if (strcmp(argv[i], "-biospxedebug") == 0)1665 {1666 if (argc <= i + 1)1667 return errorArgument("Missing argument to '%s'", argv[i]);1668 i++;1669 biospxedebug = argv[i];1670 }1671 else if (strncmp(argv[i], "-boot", 5) == 0)1672 {1673 ULONG n = 0;1674 if (!argv[i][5])1675 return errorSyntax(USAGE_MODIFYVM, "Missing boot slot number in '%s'", argv[i]);1676 if ((n = strtoul(&argv[i][5], NULL, 10)) < 1)1677 return errorSyntax(USAGE_MODIFYVM, "Invalid boot slot number in '%s'", argv[i]);1678 if (argc <= i + 1)1679 return errorArgument("Missing argument to '%s'", argv[i]);1680 i++;1681 if (strcmp(argv[i], "none") == 0)1682 {1683 bootDevice[n - 1] = DeviceType_Null;1684 }1685 else if (strcmp(argv[i], "floppy") == 0)1686 {1687 bootDevice[n - 1] = DeviceType_Floppy;1688 }1689 else if (strcmp(argv[i], "dvd") == 0)1690 {1691 bootDevice[n - 1] = DeviceType_DVD;1692 }1693 else if (strcmp(argv[i], "disk") == 0)1694 {1695 bootDevice[n - 1] = DeviceType_HardDisk;1696 }1697 else if (strcmp(argv[i], "net") == 0)1698 {1699 bootDevice[n - 1] = DeviceType_Network;1700 }1701 else1702 return errorArgument("Invalid boot device '%s'", argv[i]);1703 1704 bootDeviceChanged[n - 1] = true;1705 }1706 else if (strcmp(argv[i], "-hda") == 0)1707 {1708 if (argc <= i + 1)1709 return errorArgument("Missing argument to '%s'", argv[i]);1710 i++;1711 hdds[0] = argv[i];1712 }1713 else if (strcmp(argv[i], "-hdb") == 0)1714 {1715 if (argc <= i + 1)1716 return errorArgument("Missing argument to '%s'", argv[i]);1717 i++;1718 hdds[1] = argv[i];1719 }1720 else if (strcmp(argv[i], "-hdd") == 0)1721 {1722 if (argc <= i + 1)1723 return errorArgument("Missing argument to '%s'", argv[i]);1724 i++;1725 hdds[2] = argv[i];1726 }1727 else if (strcmp(argv[i], "-dvd") == 0)1728 {1729 if (argc <= i + 1)1730 return errorArgument("Missing argument to '%s'", argv[i]);1731 i++;1732 dvd = argv[i];1733 }1734 else if (strcmp(argv[i], "-dvdpassthrough") == 0)1735 {1736 if (argc <= i + 1)1737 return errorArgument("Missing argument to '%s'", argv[i]);1738 i++;1739 dvdpassthrough = argv[i];1740 }1741 else if (strcmp(argv[i], "-idecontroller") == 0)1742 {1743 if (argc <= i + 1)1744 return errorArgument("Missing argument to '%s'", argv[i]);1745 i++;1746 idecontroller = argv[i];1747 }1748 else if (strcmp(argv[i], "-floppy") == 0)1749 {1750 if (argc <= i + 1)1751 return errorArgument("Missing argument to '%s'", argv[i]);1752 i++;1753 floppy = argv[i];1754 }1755 else if (strcmp(argv[i], "-audio") == 0)1756 {1757 if (argc <= i + 1)1758 return errorArgument("Missing argument to '%s'", argv[i]);1759 i++;1760 audio = argv[i];1761 }1762 else if (strcmp(argv[i], "-audiocontroller") == 0)1763 {1764 if (argc <= i + 1)1765 return errorArgument("Missing argument to '%s'", argv[i]);1766 i++;1767 audiocontroller = argv[i];1768 }1769 else if (strcmp(argv[i], "-clipboard") == 0)1770 {1771 if (argc <= i + 1)1772 return errorArgument("Missing argument to '%s'", argv[i]);1773 i++;1774 clipboard = argv[i];1775 }1776 else if (strncmp(argv[i], "-cableconnected", 15) == 0)1777 {1778 unsigned n = parseNum(&argv[i][15], NetworkAdapterCount, "NIC");1779 if (!n)1780 return 1;1781 1782 if (argc <= i + 1)1783 return errorArgument("Missing argument to '%s'", argv[i]);1784 1785 cableconnected[n - 1] = argv[i + 1];1786 i++;1787 }1788 /* watch for the right order of these -nic* comparisons! */1789 else if (strncmp(argv[i], "-nictracefile", 13) == 0)1790 {1791 unsigned n = parseNum(&argv[i][13], NetworkAdapterCount, "NIC");1792 if (!n)1793 return 1;1794 if (argc <= i + 1)1795 {1796 return errorArgument("Missing argument to '%s'", argv[i]);1797 }1798 nictracefile[n - 1] = argv[i + 1];1799 i++;1800 }1801 else if (strncmp(argv[i], "-nictrace", 9) == 0)1802 {1803 unsigned n = parseNum(&argv[i][9], NetworkAdapterCount, "NIC");1804 if (!n)1805 return 1;1806 if (argc <= i + 1)1807 return errorArgument("Missing argument to '%s'", argv[i]);1808 nictrace[n - 1] = argv[i + 1];1809 i++;1810 }1811 else if (strncmp(argv[i], "-nictype", 8) == 0)1812 {1813 unsigned n = parseNum(&argv[i][8], NetworkAdapterCount, "NIC");1814 if (!n)1815 return 1;1816 if (argc <= i + 1)1817 return errorArgument("Missing argument to '%s'", argv[i]);1818 nictype[n - 1] = argv[i + 1];1819 i++;1820 }1821 else if (strncmp(argv[i], "-nicspeed", 9) == 0)1822 {1823 unsigned n = parseNum(&argv[i][9], NetworkAdapterCount, "NIC");1824 if (!n)1825 return 1;1826 if (argc <= i + 1)1827 return errorArgument("Missing argument to '%s'", argv[i]);1828 nicspeed[n - 1] = argv[i + 1];1829 i++;1830 }1831 else if (strncmp(argv[i], "-nic", 4) == 0)1832 {1833 unsigned n = parseNum(&argv[i][4], NetworkAdapterCount, "NIC");1834 if (!n)1835 return 1;1836 if (argc <= i + 1)1837 return errorArgument("Missing argument to '%s'", argv[i]);1838 nics[n - 1] = argv[i + 1];1839 i++;1840 }1841 else if (strncmp(argv[i], "-hostifdev", 10) == 0)1842 {1843 unsigned n = parseNum(&argv[i][10], NetworkAdapterCount, "NIC");1844 if (!n)1845 return 1;1846 if (argc <= i + 1)1847 return errorArgument("Missing argument to '%s'", argv[i]);1848 hostifdev[n - 1] = argv[i + 1];1849 i++;1850 }1851 else if (strncmp(argv[i], "-intnet", 7) == 0)1852 {1853 unsigned n = parseNum(&argv[i][7], NetworkAdapterCount, "NIC");1854 if (!n)1855 return 1;1856 if (argc <= i + 1)1857 return errorArgument("Missing argument to '%s'", argv[i]);1858 intnet[n - 1] = argv[i + 1];1859 i++;1860 }1861 else if (strncmp(argv[i], "-natnet", 7) == 0)1862 {1863 unsigned n = parseNum(&argv[i][7], NetworkAdapterCount, "NIC");1864 if (!n)1865 return 1;1866 if (argc <= i + 1)1867 return errorArgument("Missing argument to '%s'", argv[i]);1868 1869 if (!strcmp(argv[i + 1], "default"))1870 natnet[n - 1] = "";1871 else1872 {1873 RTIPV4ADDR Network;1874 RTIPV4ADDR Netmask;1875 int rc = RTCidrStrToIPv4(argv[i + 1], &Network, &Netmask);1876 if (RT_FAILURE(rc))1877 return errorArgument("Invalid IPv4 network '%s' specified -- CIDR notation expected.\n", argv[i + 1]);1878 if (Netmask & 0x1f)1879 return errorArgument("Prefix length of the NAT network must be less than 28.\n");1880 natnet[n - 1] = argv[i + 1];1881 }1882 i++;1883 }1884 #ifdef RT_OS_LINUX1885 else if (strncmp(argv[i], "-tapsetup", 9) == 0)1886 {1887 unsigned n = parseNum(&argv[i][9], NetworkAdapterCount, "NIC");1888 if (!n)1889 return 1;1890 if (argc <= i + 1)1891 return errorArgument("Missing argument to '%s'", argv[i]);1892 tapsetup[n - 1] = argv[i + 1];1893 i++;1894 }1895 else if (strncmp(argv[i], "-tapterminate", 13) == 0)1896 {1897 unsigned n = parseNum(&argv[i][13], NetworkAdapterCount, "NIC");1898 if (!n)1899 return 1;1900 if (argc <= i + 1)1901 return errorArgument("Missing argument to '%s'", argv[i]);1902 tapterm[n - 1] = argv[i + 1];1903 i++;1904 }1905 #endif /* RT_OS_LINUX */1906 else if (strncmp(argv[i], "-macaddress", 11) == 0)1907 {1908 unsigned n = parseNum(&argv[i][11], NetworkAdapterCount, "NIC");1909 if (!n)1910 return 1;1911 if (argc <= i + 1)1912 return errorArgument("Missing argument to '%s'", argv[i]);1913 macs[n - 1] = argv[i + 1];1914 i++;1915 }1916 #ifdef VBOX_WITH_VRDP1917 else if (strcmp(argv[i], "-vrdp") == 0)1918 {1919 if (argc <= i + 1)1920 return errorArgument("Missing argument to '%s'", argv[i]);1921 i++;1922 vrdp = argv[i];1923 }1924 else if (strcmp(argv[i], "-vrdpport") == 0)1925 {1926 if (argc <= i + 1)1927 return errorArgument("Missing argument to '%s'", argv[i]);1928 i++;1929 if (strcmp(argv[i], "default") == 0)1930 vrdpport = 0;1931 else1932 vrdpport = atoi(argv[i]);1933 }1934 else if (strcmp(argv[i], "-vrdpaddress") == 0)1935 {1936 if (argc <= i + 1)1937 return errorArgument("Missing argument to '%s'", argv[i]);1938 i++;1939 vrdpaddress = argv[i];1940 }1941 else if (strcmp(argv[i], "-vrdpauthtype") == 0)1942 {1943 if (argc <= i + 1)1944 return errorArgument("Missing argument to '%s'", argv[i]);1945 i++;1946 vrdpauthtype = argv[i];1947 }1948 else if (strcmp(argv[i], "-vrdpmulticon") == 0)1949 {1950 if (argc <= i + 1)1951 return errorArgument("Missing argument to '%s'", argv[i]);1952 i++;1953 vrdpmulticon = argv[i];1954 }1955 else if (strcmp(argv[i], "-vrdpreusecon") == 0)1956 {1957 if (argc <= i + 1)1958 return errorArgument("Missing argument to '%s'", argv[i]);1959 i++;1960 vrdpreusecon = argv[i];1961 }1962 #endif /* VBOX_WITH_VRDP */1963 else if (strcmp(argv[i], "-usb") == 0)1964 {1965 if (argc <= i + 1)1966 return errorArgument("Missing argument to '%s'", argv[i]);1967 i++;1968 if (strcmp(argv[i], "on") == 0 || strcmp(argv[i], "enable") == 0)1969 fUsbEnabled = 1;1970 else if (strcmp(argv[i], "off") == 0 || strcmp(argv[i], "disable") == 0)1971 fUsbEnabled = 0;1972 else1973 return errorArgument("Invalid -usb argument '%s'", argv[i]);1974 }1975 else if (strcmp(argv[i], "-usbehci") == 0)1976 {1977 if (argc <= i + 1)1978 return errorArgument("Missing argument to '%s'", argv[i]);1979 i++;1980 if (strcmp(argv[i], "on") == 0 || strcmp(argv[i], "enable") == 0)1981 fUsbEhciEnabled = 1;1982 else if (strcmp(argv[i], "off") == 0 || strcmp(argv[i], "disable") == 0)1983 fUsbEhciEnabled = 0;1984 else1985 return errorArgument("Invalid -usbehci argument '%s'", argv[i]);1986 }1987 else if (strcmp(argv[i], "-snapshotfolder") == 0)1988 {1989 if (argc <= i + 1)1990 return errorArgument("Missing argument to '%s'", argv[i]);1991 i++;1992 snapshotFolder = argv[i];1993 }1994 else if (strncmp(argv[i], "-uartmode", 9) == 0)1995 {1996 unsigned n = parseNum(&argv[i][9], SerialPortCount, "UART");1997 if (!n)1998 return 1;1999 i++;2000 if (strcmp(argv[i], "disconnected") == 0)2001 {2002 uarts_mode[n - 1] = argv[i];2003 }2004 else2005 {2006 if (strcmp(argv[i], "server") == 0 || strcmp(argv[i], "client") == 0)2007 {2008 uarts_mode[n - 1] = argv[i];2009 i++;2010 #ifdef RT_OS_WINDOWS2011 if (strncmp(argv[i], "\\\\.\\pipe\\", 9))2012 return errorArgument("Uart pipe must start with \\\\.\\pipe\\");2013 #endif2014 }2015 else2016 {2017 uarts_mode[n - 1] = (char*)"device";2018 }2019 if (argc <= i)2020 return errorArgument("Missing argument to -uartmode");2021 uarts_path[n - 1] = argv[i];2022 }2023 }2024 else if (strncmp(argv[i], "-uart", 5) == 0)2025 {2026 unsigned n = parseNum(&argv[i][5], SerialPortCount, "UART");2027 if (!n)2028 return 1;2029 if (argc <= i + 1)2030 return errorArgument("Missing argument to '%s'", argv[i]);2031 i++;2032 if (strcmp(argv[i], "off") == 0 || strcmp(argv[i], "disable") == 0)2033 {2034 uarts_base[n - 1] = (ULONG)-1;2035 }2036 else2037 {2038 if (argc <= i + 1)2039 return errorArgument("Missing argument to '%s'", argv[i-1]);2040 uint32_t uVal;2041 int vrc;2042 vrc = RTStrToUInt32Ex(argv[i], NULL, 0, &uVal);2043 if (vrc != VINF_SUCCESS || uVal == 0)2044 return errorArgument("Error parsing UART I/O base '%s'", argv[i]);2045 uarts_base[n - 1] = uVal;2046 i++;2047 vrc = RTStrToUInt32Ex(argv[i], NULL, 0, &uVal);2048 if (vrc != VINF_SUCCESS)2049 return errorArgument("Error parsing UART IRQ '%s'", argv[i]);2050 uarts_irq[n - 1] = uVal;2051 }2052 }2053 #ifdef VBOX_WITH_MEM_BALLOONING2054 else if (strncmp(argv[i], "-guestmemoryballoon", 19) == 0)2055 {2056 if (argc <= i + 1)2057 return errorArgument("Missing argument to '%s'", argv[i]);2058 i++;2059 uint32_t uVal;2060 int vrc;2061 vrc = RTStrToUInt32Ex(argv[i], NULL, 0, &uVal);2062 if (vrc != VINF_SUCCESS)2063 return errorArgument("Error parsing guest memory balloon size '%s'", argv[i]);2064 guestMemBalloonSize = uVal;2065 }2066 #endif2067 else if (strncmp(argv[i], "-gueststatisticsinterval", 24) == 0)2068 {2069 if (argc <= i + 1)2070 return errorArgument("Missing argument to '%s'", argv[i]);2071 i++;2072 uint32_t uVal;2073 int vrc;2074 vrc = RTStrToUInt32Ex(argv[i], NULL, 0, &uVal);2075 if (vrc != VINF_SUCCESS)2076 return errorArgument("Error parsing guest statistics interval '%s'", argv[i]);2077 guestStatInterval = uVal;2078 }2079 else if (strcmp(argv[i], "-sata") == 0)2080 {2081 if (argc <= i + 1)2082 return errorArgument("Missing argument to '%s'", argv[i]);2083 i++;2084 if (strcmp(argv[i], "on") == 0 || strcmp(argv[i], "enable") == 0)2085 fSataEnabled = 1;2086 else if (strcmp(argv[i], "off") == 0 || strcmp(argv[i], "disable") == 0)2087 fSataEnabled = 0;2088 else2089 return errorArgument("Invalid -usb argument '%s'", argv[i]);2090 }2091 else if (strcmp(argv[i], "-sataportcount") == 0)2092 {2093 unsigned n;2094 2095 if (argc <= i + 1)2096 return errorArgument("Missing arguments to '%s'", argv[i]);2097 i++;2098 2099 n = parseNum(argv[i], 30, "SATA");2100 if (!n)2101 return 1;2102 sataPortCount = n;2103 }2104 else if (strncmp(argv[i], "-sataport", 9) == 0)2105 {2106 unsigned n = parseNum(&argv[i][9], 30, "SATA");2107 if (!n)2108 return 1;2109 if (argc <= i + 1)2110 return errorArgument("Missing argument to '%s'", argv[i]);2111 i++;2112 hdds[n-1+4] = argv[i];2113 }2114 else if (strncmp(argv[i], "-sataideemulation", 17) == 0)2115 {2116 unsigned bootDevicePos = 0;2117 unsigned n;2118 2119 bootDevicePos = parseNum(&argv[i][17], 4, "SATA");2120 if (!bootDevicePos)2121 return 1;2122 bootDevicePos--;2123 2124 if (argc <= i + 1)2125 return errorArgument("Missing arguments to '%s'", argv[i]);2126 i++;2127 2128 n = parseNum(argv[i], 30, "SATA");2129 if (!n)2130 return 1;2131 2132 sataBootDevices[bootDevicePos] = n-1;2133 }2134 else2135 return errorSyntax(USAGE_MODIFYVM, "Invalid parameter '%s'", Utf8Str(argv[i]).raw());2136 }2137 2138 /* try to find the given machine */2139 ComPtr <IMachine> machine;2140 Guid uuid (argv[0]);2141 if (!uuid.isEmpty())2142 {2143 CHECK_ERROR (virtualBox, GetMachine (uuid, machine.asOutParam()));2144 }2145 else2146 {2147 CHECK_ERROR (virtualBox, FindMachine(Bstr(argv[0]), machine.asOutParam()));2148 if (SUCCEEDED (rc))2149 machine->COMGETTER(Id)(uuid.asOutParam());2150 }2151 if (FAILED (rc))2152 return 1;2153 2154 /* open a session for the VM */2155 CHECK_ERROR_RET (virtualBox, OpenSession(session, uuid), 1);2156 2157 do2158 {2159 /* get the mutable session machine */2160 session->COMGETTER(Machine)(machine.asOutParam());2161 2162 ComPtr <IBIOSSettings> biosSettings;2163 machine->COMGETTER(BIOSSettings)(biosSettings.asOutParam());2164 2165 if (name)2166 CHECK_ERROR(machine, COMSETTER(Name)(name));2167 if (ostype)2168 {2169 ComPtr<IGuestOSType> guestOSType;2170 CHECK_ERROR(virtualBox, GetGuestOSType(ostype, guestOSType.asOutParam()));2171 if (SUCCEEDED(rc) && guestOSType)2172 {2173 CHECK_ERROR(machine, COMSETTER(OSTypeId)(ostype));2174 }2175 else2176 {2177 errorArgument("Invalid guest OS type '%s'", Utf8Str(ostype).raw());2178 rc = E_FAIL;2179 break;2180 }2181 }2182 if (memorySize > 0)2183 CHECK_ERROR(machine, COMSETTER(MemorySize)(memorySize));2184 if (vramSize > 0)2185 CHECK_ERROR(machine, COMSETTER(VRAMSize)(vramSize));2186 if (acpi)2187 {2188 if (strcmp(acpi, "on") == 0)2189 {2190 CHECK_ERROR(biosSettings, COMSETTER(ACPIEnabled)(true));2191 }2192 else if (strcmp(acpi, "off") == 0)2193 {2194 CHECK_ERROR(biosSettings, COMSETTER(ACPIEnabled)(false));2195 }2196 else2197 {2198 errorArgument("Invalid -acpi argument '%s'", acpi);2199 rc = E_FAIL;2200 break;2201 }2202 }2203 if (ioapic)2204 {2205 if (strcmp(ioapic, "on") == 0)2206 {2207 CHECK_ERROR(biosSettings, COMSETTER(IOAPICEnabled)(true));2208 }2209 else if (strcmp(ioapic, "off") == 0)2210 {2211 CHECK_ERROR(biosSettings, COMSETTER(IOAPICEnabled)(false));2212 }2213 else2214 {2215 errorArgument("Invalid -ioapic argument '%s'", ioapic);2216 rc = E_FAIL;2217 break;2218 }2219 }2220 if (hwvirtex)2221 {2222 if (strcmp(hwvirtex, "on") == 0)2223 {2224 CHECK_ERROR(machine, COMSETTER(HWVirtExEnabled)(TSBool_True));2225 }2226 else if (strcmp(hwvirtex, "off") == 0)2227 {2228 CHECK_ERROR(machine, COMSETTER(HWVirtExEnabled)(TSBool_False));2229 }2230 else if (strcmp(hwvirtex, "default") == 0)2231 {2232 CHECK_ERROR(machine, COMSETTER(HWVirtExEnabled)(TSBool_Default));2233 }2234 else2235 {2236 errorArgument("Invalid -hwvirtex argument '%s'", hwvirtex);2237 rc = E_FAIL;2238 break;2239 }2240 }2241 if (nestedpaging)2242 {2243 if (strcmp(nestedpaging, "on") == 0)2244 {2245 CHECK_ERROR(machine, COMSETTER(HWVirtExNestedPagingEnabled)(true));2246 }2247 else if (strcmp(nestedpaging, "off") == 0)2248 {2249 CHECK_ERROR(machine, COMSETTER(HWVirtExNestedPagingEnabled)(false));2250 }2251 else2252 {2253 errorArgument("Invalid -nestedpaging argument '%s'", ioapic);2254 rc = E_FAIL;2255 break;2256 }2257 }2258 if (vtxvpid)2259 {2260 if (strcmp(vtxvpid, "on") == 0)2261 {2262 CHECK_ERROR(machine, COMSETTER(HWVirtExVPIDEnabled)(true));2263 }2264 else if (strcmp(vtxvpid, "off") == 0)2265 {2266 CHECK_ERROR(machine, COMSETTER(HWVirtExVPIDEnabled)(false));2267 }2268 else2269 {2270 errorArgument("Invalid -vtxvpid argument '%s'", ioapic);2271 rc = E_FAIL;2272 break;2273 }2274 }2275 if (pae)2276 {2277 if (strcmp(pae, "on") == 0)2278 {2279 CHECK_ERROR(machine, COMSETTER(PAEEnabled)(true));2280 }2281 else if (strcmp(pae, "off") == 0)2282 {2283 CHECK_ERROR(machine, COMSETTER(PAEEnabled)(false));2284 }2285 else2286 {2287 errorArgument("Invalid -pae argument '%s'", ioapic);2288 rc = E_FAIL;2289 break;2290 }2291 }2292 if (monitorcount != -1)2293 {2294 CHECK_ERROR(machine, COMSETTER(MonitorCount)(monitorcount));2295 }2296 if (accelerate3d)2297 {2298 if (strcmp(accelerate3d, "on") == 0)2299 {2300 CHECK_ERROR(machine, COMSETTER(Accelerate3DEnabled)(true));2301 }2302 else if (strcmp(accelerate3d, "off") == 0)2303 {2304 CHECK_ERROR(machine, COMSETTER(Accelerate3DEnabled)(false));2305 }2306 else2307 {2308 errorArgument("Invalid -accelerate3d argument '%s'", ioapic);2309 rc = E_FAIL;2310 break;2311 }2312 }2313 if (bioslogofadein)2314 {2315 if (strcmp(bioslogofadein, "on") == 0)2316 {2317 CHECK_ERROR(biosSettings, COMSETTER(LogoFadeIn)(true));2318 }2319 else if (strcmp(bioslogofadein, "off") == 0)2320 {2321 CHECK_ERROR(biosSettings, COMSETTER(LogoFadeIn)(false));2322 }2323 else2324 {2325 errorArgument("Invalid -bioslogofadein argument '%s'", bioslogofadein);2326 rc = E_FAIL;2327 break;2328 }2329 }2330 if (bioslogofadeout)2331 {2332 if (strcmp(bioslogofadeout, "on") == 0)2333 {2334 CHECK_ERROR(biosSettings, COMSETTER(LogoFadeOut)(true));2335 }2336 else if (strcmp(bioslogofadeout, "off") == 0)2337 {2338 CHECK_ERROR(biosSettings, COMSETTER(LogoFadeOut)(false));2339 }2340 else2341 {2342 errorArgument("Invalid -bioslogofadeout argument '%s'", bioslogofadeout);2343 rc = E_FAIL;2344 break;2345 }2346 }2347 if (bioslogodisplaytime != ~0U)2348 {2349 CHECK_ERROR(biosSettings, COMSETTER(LogoDisplayTime)(bioslogodisplaytime));2350 }2351 if (bioslogoimagepath)2352 {2353 CHECK_ERROR(biosSettings, COMSETTER(LogoImagePath)(Bstr(bioslogoimagepath)));2354 }2355 if (biosbootmenumode)2356 {2357 if (strcmp(biosbootmenumode, "disabled") == 0)2358 CHECK_ERROR(biosSettings, COMSETTER(BootMenuMode)(BIOSBootMenuMode_Disabled));2359 else if (strcmp(biosbootmenumode, "menuonly") == 0)2360 CHECK_ERROR(biosSettings, COMSETTER(BootMenuMode)(BIOSBootMenuMode_MenuOnly));2361 else if (strcmp(biosbootmenumode, "messageandmenu") == 0)2362 CHECK_ERROR(biosSettings, COMSETTER(BootMenuMode)(BIOSBootMenuMode_MessageAndMenu));2363 else2364 {2365 errorArgument("Invalid -biosbootmenu argument '%s'", biosbootmenumode);2366 rc = E_FAIL;2367 break;2368 }2369 2370 }2371 if (biossystemtimeoffset)2372 {2373 LONG64 timeOffset = RTStrToInt64(biossystemtimeoffset);2374 CHECK_ERROR(biosSettings, COMSETTER(TimeOffset)(timeOffset));2375 }2376 if (biospxedebug)2377 {2378 if (strcmp(biospxedebug, "on") == 0)2379 {2380 CHECK_ERROR(biosSettings, COMSETTER(PXEDebugEnabled)(true));2381 }2382 else if (strcmp(biospxedebug, "off") == 0)2383 {2384 CHECK_ERROR(biosSettings, COMSETTER(PXEDebugEnabled)(false));2385 }2386 else2387 {2388 errorArgument("Invalid -biospxedebug argument '%s'", biospxedebug);2389 rc = E_FAIL;2390 break;2391 }2392 }2393 for (int curBootDev = 0; curBootDev < 4; curBootDev++)2394 {2395 if (bootDeviceChanged[curBootDev])2396 CHECK_ERROR(machine, SetBootOrder (curBootDev + 1, bootDevice[curBootDev]));2397 }2398 if (hdds[0])2399 {2400 if (strcmp(hdds[0], "none") == 0)2401 {2402 machine->DetachHardDisk2(StorageBus_IDE, 0, 0);2403 }2404 else2405 {2406 /* first guess is that it's a UUID */2407 Guid uuid(hdds[0]);2408 ComPtr<IHardDisk2> hardDisk;2409 rc = virtualBox->GetHardDisk2(uuid, hardDisk.asOutParam());2410 /* not successful? Then it must be a filename */2411 if (!hardDisk)2412 {2413 CHECK_ERROR(virtualBox, FindHardDisk2(Bstr(hdds[0]), hardDisk.asOutParam()));2414 if (FAILED(rc))2415 {2416 /* open the new hard disk object */2417 CHECK_ERROR(virtualBox, OpenHardDisk2(Bstr(hdds[0]), hardDisk.asOutParam()));2418 }2419 }2420 if (hardDisk)2421 {2422 hardDisk->COMGETTER(Id)(uuid.asOutParam());2423 CHECK_ERROR(machine, AttachHardDisk2(uuid, StorageBus_IDE, 0, 0));2424 }2425 else2426 rc = E_FAIL;2427 if (FAILED(rc))2428 break;2429 }2430 }2431 if (hdds[1])2432 {2433 if (strcmp(hdds[1], "none") == 0)2434 {2435 machine->DetachHardDisk2(StorageBus_IDE, 0, 1);2436 }2437 else2438 {2439 /* first guess is that it's a UUID */2440 Guid uuid(hdds[1]);2441 ComPtr<IHardDisk2> hardDisk;2442 rc = virtualBox->GetHardDisk2(uuid, hardDisk.asOutParam());2443 /* not successful? Then it must be a filename */2444 if (!hardDisk)2445 {2446 CHECK_ERROR(virtualBox, FindHardDisk2(Bstr(hdds[1]), hardDisk.asOutParam()));2447 if (FAILED(rc))2448 {2449 /* open the new hard disk object */2450 CHECK_ERROR(virtualBox, OpenHardDisk2(Bstr(hdds[1]), hardDisk.asOutParam()));2451 }2452 }2453 if (hardDisk)2454 {2455 hardDisk->COMGETTER(Id)(uuid.asOutParam());2456 CHECK_ERROR(machine, AttachHardDisk2(uuid, StorageBus_IDE, 0, 1));2457 }2458 else2459 rc = E_FAIL;2460 if (FAILED(rc))2461 break;2462 }2463 }2464 if (hdds[2])2465 {2466 if (strcmp(hdds[2], "none") == 0)2467 {2468 machine->DetachHardDisk2(StorageBus_IDE, 1, 1);2469 }2470 else2471 {2472 /* first guess is that it's a UUID */2473 Guid uuid(hdds[2]);2474 ComPtr<IHardDisk2> hardDisk;2475 rc = virtualBox->GetHardDisk2(uuid, hardDisk.asOutParam());2476 /* not successful? Then it must be a filename */2477 if (!hardDisk)2478 {2479 CHECK_ERROR(virtualBox, FindHardDisk2(Bstr(hdds[2]), hardDisk.asOutParam()));2480 if (FAILED(rc))2481 {2482 /* open the new hard disk object */2483 CHECK_ERROR(virtualBox, OpenHardDisk2(Bstr(hdds[2]), hardDisk.asOutParam()));2484 }2485 }2486 if (hardDisk)2487 {2488 hardDisk->COMGETTER(Id)(uuid.asOutParam());2489 CHECK_ERROR(machine, AttachHardDisk2(uuid, StorageBus_IDE, 1, 1));2490 }2491 else2492 rc = E_FAIL;2493 if (FAILED(rc))2494 break;2495 }2496 }2497 if (dvd)2498 {2499 ComPtr<IDVDDrive> dvdDrive;2500 machine->COMGETTER(DVDDrive)(dvdDrive.asOutParam());2501 ASSERT(dvdDrive);2502 2503 /* unmount? */2504 if (strcmp(dvd, "none") == 0)2505 {2506 CHECK_ERROR(dvdDrive, Unmount());2507 }2508 /* host drive? */2509 else if (strncmp(dvd, "host:", 5) == 0)2510 {2511 ComPtr<IHost> host;2512 CHECK_ERROR(virtualBox, COMGETTER(Host)(host.asOutParam()));2513 ComPtr<IHostDVDDriveCollection> hostDVDs;2514 CHECK_ERROR(host, COMGETTER(DVDDrives)(hostDVDs.asOutParam()));2515 ComPtr<IHostDVDDrive> hostDVDDrive;2516 rc = hostDVDs->FindByName(Bstr(dvd + 5), hostDVDDrive.asOutParam());2517 if (!hostDVDDrive)2518 {2519 /* 2nd try: try with the real name, important on Linux+libhal */2520 char szPathReal[RTPATH_MAX];2521 if (RT_FAILURE(RTPathReal(dvd + 5, szPathReal, sizeof(szPathReal))))2522 {2523 errorArgument("Invalid host DVD drive name");2524 rc = E_FAIL;2525 break;2526 }2527 rc = hostDVDs->FindByName(Bstr(szPathReal), hostDVDDrive.asOutParam());2528 if (!hostDVDDrive)2529 {2530 errorArgument("Invalid host DVD drive name");2531 rc = E_FAIL;2532 break;2533 }2534 }2535 CHECK_ERROR(dvdDrive, CaptureHostDrive(hostDVDDrive));2536 }2537 else2538 {2539 /* first assume it's a UUID */2540 Guid uuid(dvd);2541 ComPtr<IDVDImage2> dvdImage;2542 rc = virtualBox->GetDVDImage(uuid, dvdImage.asOutParam());2543 if (FAILED(rc) || !dvdImage)2544 {2545 /* must be a filename, check if it's in the collection */2546 rc = virtualBox->FindDVDImage(Bstr(dvd), dvdImage.asOutParam());2547 /* not registered, do that on the fly */2548 if (!dvdImage)2549 {2550 Guid emptyUUID;2551 CHECK_ERROR(virtualBox, OpenDVDImage(Bstr(dvd), emptyUUID, dvdImage.asOutParam()));2552 }2553 }2554 if (!dvdImage)2555 {2556 rc = E_FAIL;2557 break;2558 }2559 2560 dvdImage->COMGETTER(Id)(uuid.asOutParam());2561 CHECK_ERROR(dvdDrive, MountImage(uuid));2562 }2563 }2564 if (dvdpassthrough)2565 {2566 ComPtr<IDVDDrive> dvdDrive;2567 machine->COMGETTER(DVDDrive)(dvdDrive.asOutParam());2568 ASSERT(dvdDrive);2569 2570 CHECK_ERROR(dvdDrive, COMSETTER(Passthrough)(strcmp(dvdpassthrough, "on") == 0));2571 }2572 if (idecontroller)2573 {2574 if (RTStrICmp(idecontroller, "PIIX3") == 0)2575 {2576 CHECK_ERROR(biosSettings, COMSETTER(IDEControllerType)(IDEControllerType_PIIX3));2577 }2578 else if (RTStrICmp(idecontroller, "PIIX4") == 0)2579 {2580 CHECK_ERROR(biosSettings, COMSETTER(IDEControllerType)(IDEControllerType_PIIX4));2581 }2582 else2583 {2584 errorArgument("Invalid -idecontroller argument '%s'", idecontroller);2585 rc = E_FAIL;2586 break;2587 }2588 }2589 if (floppy)2590 {2591 ComPtr<IFloppyDrive> floppyDrive;2592 machine->COMGETTER(FloppyDrive)(floppyDrive.asOutParam());2593 ASSERT(floppyDrive);2594 2595 /* disable? */2596 if (strcmp(floppy, "disabled") == 0)2597 {2598 /* disable the controller */2599 CHECK_ERROR(floppyDrive, COMSETTER(Enabled)(false));2600 }2601 else2602 {2603 /* enable the controller */2604 CHECK_ERROR(floppyDrive, COMSETTER(Enabled)(true));2605 2606 /* unmount? */2607 if (strcmp(floppy, "empty") == 0)2608 {2609 CHECK_ERROR(floppyDrive, Unmount());2610 }2611 /* host drive? */2612 else if (strncmp(floppy, "host:", 5) == 0)2613 {2614 ComPtr<IHost> host;2615 CHECK_ERROR(virtualBox, COMGETTER(Host)(host.asOutParam()));2616 ComPtr<IHostFloppyDriveCollection> hostFloppies;2617 CHECK_ERROR(host, COMGETTER(FloppyDrives)(hostFloppies.asOutParam()));2618 ComPtr<IHostFloppyDrive> hostFloppyDrive;2619 rc = hostFloppies->FindByName(Bstr(floppy + 5), hostFloppyDrive.asOutParam());2620 if (!hostFloppyDrive)2621 {2622 errorArgument("Invalid host floppy drive name");2623 rc = E_FAIL;2624 break;2625 }2626 CHECK_ERROR(floppyDrive, CaptureHostDrive(hostFloppyDrive));2627 }2628 else2629 {2630 /* first assume it's a UUID */2631 Guid uuid(floppy);2632 ComPtr<IFloppyImage2> floppyImage;2633 rc = virtualBox->GetFloppyImage(uuid, floppyImage.asOutParam());2634 if (FAILED(rc) || !floppyImage)2635 {2636 /* must be a filename, check if it's in the collection */2637 rc = virtualBox->FindFloppyImage(Bstr(floppy), floppyImage.asOutParam());2638 /* not registered, do that on the fly */2639 if (!floppyImage)2640 {2641 Guid emptyUUID;2642 CHECK_ERROR(virtualBox, OpenFloppyImage(Bstr(floppy), emptyUUID, floppyImage.asOutParam()));2643 }2644 }2645 if (!floppyImage)2646 {2647 rc = E_FAIL;2648 break;2649 }2650 2651 floppyImage->COMGETTER(Id)(uuid.asOutParam());2652 CHECK_ERROR(floppyDrive, MountImage(uuid));2653 }2654 }2655 }2656 if (audio || audiocontroller)2657 {2658 ComPtr<IAudioAdapter> audioAdapter;2659 machine->COMGETTER(AudioAdapter)(audioAdapter.asOutParam());2660 ASSERT(audioAdapter);2661 2662 if (audio)2663 {2664 /* disable? */2665 if (strcmp(audio, "none") == 0)2666 {2667 CHECK_ERROR(audioAdapter, COMSETTER(Enabled)(false));2668 }2669 else if (strcmp(audio, "null") == 0)2670 {2671 CHECK_ERROR(audioAdapter, COMSETTER(AudioDriver)(AudioDriverType_Null));2672 CHECK_ERROR(audioAdapter, COMSETTER(Enabled)(true));2673 }2674 #ifdef RT_OS_WINDOWS2675 #ifdef VBOX_WITH_WINMM2676 else if (strcmp(audio, "winmm") == 0)2677 {2678 CHECK_ERROR(audioAdapter, COMSETTER(AudioDriver)(AudioDriverType_WinMM));2679 CHECK_ERROR(audioAdapter, COMSETTER(Enabled)(true));2680 }2681 #endif2682 else if (strcmp(audio, "dsound") == 0)2683 {2684 CHECK_ERROR(audioAdapter, COMSETTER(AudioDriver)(AudioDriverType_DirectSound));2685 CHECK_ERROR(audioAdapter, COMSETTER(Enabled)(true));2686 }2687 #endif /* RT_OS_WINDOWS */2688 #ifdef RT_OS_LINUX2689 else if (strcmp(audio, "oss") == 0)2690 {2691 CHECK_ERROR(audioAdapter, COMSETTER(AudioDriver)(AudioDriverType_OSS));2692 CHECK_ERROR(audioAdapter, COMSETTER(Enabled)(true));2693 }2694 # ifdef VBOX_WITH_ALSA2695 else if (strcmp(audio, "alsa") == 0)2696 {2697 CHECK_ERROR(audioAdapter, COMSETTER(AudioDriver)(AudioDriverType_ALSA));2698 CHECK_ERROR(audioAdapter, COMSETTER(Enabled)(true));2699 }2700 # endif2701 # ifdef VBOX_WITH_PULSE2702 else if (strcmp(audio, "pulse") == 0)2703 {2704 CHECK_ERROR(audioAdapter, COMSETTER(AudioDriver)(AudioDriverType_Pulse));2705 CHECK_ERROR(audioAdapter, COMSETTER(Enabled)(true));2706 }2707 # endif2708 #endif /* !RT_OS_LINUX */2709 #ifdef RT_OS_SOLARIS2710 else if (strcmp(audio, "solaudio") == 0)2711 {2712 CHECK_ERROR(audioAdapter, COMSETTER(AudioDriver)(AudioDriverType_SolAudio));2713 CHECK_ERROR(audioAdapter, COMSETTER(Enabled)(true));2714 }2715 2716 #endif /* !RT_OS_SOLARIS */2717 #ifdef RT_OS_DARWIN2718 else if (strcmp(audio, "coreaudio") == 0)2719 {2720 CHECK_ERROR(audioAdapter, COMSETTER(AudioDriver)(AudioDriverType_CoreAudio));2721 CHECK_ERROR(audioAdapter, COMSETTER(Enabled)(true));2722 }2723 2724 #endif /* !RT_OS_DARWIN */2725 else2726 {2727 errorArgument("Invalid -audio argument '%s'", audio);2728 rc = E_FAIL;2729 break;2730 }2731 }2732 if (audiocontroller)2733 {2734 if (strcmp(audiocontroller, "sb16") == 0)2735 CHECK_ERROR(audioAdapter, COMSETTER(AudioController)(AudioControllerType_SB16));2736 else if (strcmp(audiocontroller, "ac97") == 0)2737 CHECK_ERROR(audioAdapter, COMSETTER(AudioController)(AudioControllerType_AC97));2738 else2739 {2740 errorArgument("Invalid -audiocontroller argument '%s'", audiocontroller);2741 rc = E_FAIL;2742 break;2743 }2744 }2745 }2746 /* Shared clipboard state */2747 if (clipboard)2748 {2749 /* ComPtr<IClipboardMode> clipboardMode;2750 machine->COMGETTER(ClipboardMode)(clipboardMode.asOutParam());2751 ASSERT(clipboardMode);2752 */2753 if (strcmp(clipboard, "disabled") == 0)2754 {2755 CHECK_ERROR(machine, COMSETTER(ClipboardMode)(ClipboardMode_Disabled));2756 }2757 else if (strcmp(clipboard, "hosttoguest") == 0)2758 {2759 CHECK_ERROR(machine, COMSETTER(ClipboardMode)(ClipboardMode_HostToGuest));2760 }2761 else if (strcmp(clipboard, "guesttohost") == 0)2762 {2763 CHECK_ERROR(machine, COMSETTER(ClipboardMode)(ClipboardMode_GuestToHost));2764 }2765 else if (strcmp(clipboard, "bidirectional") == 0)2766 {2767 CHECK_ERROR(machine, COMSETTER(ClipboardMode)(ClipboardMode_Bidirectional));2768 }2769 else2770 {2771 errorArgument("Invalid -clipboard argument '%s'", clipboard);2772 rc = E_FAIL;2773 break;2774 }2775 }2776 /* iterate through all possible NICs */2777 for (ULONG n = 0; n < NetworkAdapterCount; n ++)2778 {2779 ComPtr<INetworkAdapter> nic;2780 CHECK_ERROR_RET (machine, GetNetworkAdapter (n, nic.asOutParam()), 1);2781 2782 ASSERT(nic);2783 2784 /* something about the NIC? */2785 if (nics[n])2786 {2787 if (strcmp(nics[n], "none") == 0)2788 {2789 CHECK_ERROR_RET(nic, COMSETTER(Enabled) (FALSE), 1);2790 }2791 else if (strcmp(nics[n], "null") == 0)2792 {2793 CHECK_ERROR_RET(nic, COMSETTER(Enabled) (TRUE), 1);2794 CHECK_ERROR_RET(nic, Detach(), 1);2795 }2796 else if (strcmp(nics[n], "nat") == 0)2797 {2798 CHECK_ERROR_RET(nic, COMSETTER(Enabled) (TRUE), 1);2799 CHECK_ERROR_RET(nic, AttachToNAT(), 1);2800 }2801 else if (strcmp(nics[n], "hostif") == 0)2802 {2803 CHECK_ERROR_RET(nic, COMSETTER(Enabled) (TRUE), 1);2804 CHECK_ERROR_RET(nic, AttachToHostInterface(), 1);2805 }2806 else if (strcmp(nics[n], "intnet") == 0)2807 {2808 CHECK_ERROR_RET(nic, COMSETTER(Enabled) (TRUE), 1);2809 CHECK_ERROR_RET(nic, AttachToInternalNetwork(), 1);2810 }2811 else2812 {2813 errorArgument("Invalid type '%s' specfied for NIC %lu", nics[n], n + 1);2814 rc = E_FAIL;2815 break;2816 }2817 }2818 2819 /* something about the NIC type? */2820 if (nictype[n])2821 {2822 if (strcmp(nictype[n], "Am79C970A") == 0)2823 {2824 CHECK_ERROR_RET(nic, COMSETTER(AdapterType)(NetworkAdapterType_Am79C970A), 1);2825 }2826 else if (strcmp(nictype[n], "Am79C973") == 0)2827 {2828 CHECK_ERROR_RET(nic, COMSETTER(AdapterType)(NetworkAdapterType_Am79C973), 1);2829 }2830 #ifdef VBOX_WITH_E10002831 else if (strcmp(nictype[n], "82540EM") == 0)2832 {2833 CHECK_ERROR_RET(nic, COMSETTER(AdapterType)(NetworkAdapterType_I82540EM), 1);2834 }2835 else if (strcmp(nictype[n], "82543GC") == 0)2836 {2837 CHECK_ERROR_RET(nic, COMSETTER(AdapterType)(NetworkAdapterType_I82543GC), 1);2838 }2839 #endif2840 else2841 {2842 errorArgument("Invalid NIC type '%s' specified for NIC %lu", nictype[n], n + 1);2843 rc = E_FAIL;2844 break;2845 }2846 }2847 2848 /* something about the MAC address? */2849 if (macs[n])2850 {2851 /* generate one? */2852 if (strcmp(macs[n], "auto") == 0)2853 {2854 CHECK_ERROR_RET(nic, COMSETTER(MACAddress)(NULL), 1);2855 }2856 else2857 {2858 CHECK_ERROR_RET(nic, COMSETTER(MACAddress)(Bstr(macs[n])), 1);2859 }2860 }2861 2862 /* something about the reported link speed? */2863 if (nicspeed[n])2864 {2865 uint32_t u32LineSpeed;2866 2867 u32LineSpeed = atoi(nicspeed[n]);2868 2869 if (u32LineSpeed < 1000 || u32LineSpeed > 4000000)2870 {2871 errorArgument("Invalid -nicspeed%lu argument '%s'", n + 1, nicspeed[n]);2872 rc = E_FAIL;2873 break;2874 }2875 CHECK_ERROR_RET(nic, COMSETTER(LineSpeed)(u32LineSpeed), 1);2876 }2877 2878 /* the link status flag? */2879 if (cableconnected[n])2880 {2881 if (strcmp(cableconnected[n], "on") == 0)2882 {2883 CHECK_ERROR_RET(nic, COMSETTER(CableConnected)(TRUE), 1);2884 }2885 else if (strcmp(cableconnected[n], "off") == 0)2886 {2887 CHECK_ERROR_RET(nic, COMSETTER(CableConnected)(FALSE), 1);2888 }2889 else2890 {2891 errorArgument("Invalid -cableconnected%lu argument '%s'", n + 1, cableconnected[n]);2892 rc = E_FAIL;2893 break;2894 }2895 }2896 2897 /* the trace flag? */2898 if (nictrace[n])2899 {2900 if (strcmp(nictrace[n], "on") == 0)2901 {2902 CHECK_ERROR_RET(nic, COMSETTER(TraceEnabled)(TRUE), 1);2903 }2904 else if (strcmp(nictrace[n], "off") == 0)2905 {2906 CHECK_ERROR_RET(nic, COMSETTER(TraceEnabled)(FALSE), 1);2907 }2908 else2909 {2910 errorArgument("Invalid -nictrace%lu argument '%s'", n + 1, nictrace[n]);2911 rc = E_FAIL;2912 break;2913 }2914 }2915 2916 /* the tracefile flag? */2917 if (nictracefile[n])2918 {2919 CHECK_ERROR_RET(nic, COMSETTER(TraceFile)(Bstr(nictracefile[n])), 1);2920 }2921 2922 /* the host interface device? */2923 if (hostifdev[n])2924 {2925 /* remove it? */2926 if (strcmp(hostifdev[n], "none") == 0)2927 {2928 CHECK_ERROR_RET(nic, COMSETTER(HostInterface)(NULL), 1);2929 }2930 else2931 {2932 CHECK_ERROR_RET(nic, COMSETTER(HostInterface)(Bstr(hostifdev[n])), 1);2933 }2934 }2935 2936 /* the internal network name? */2937 if (intnet[n])2938 {2939 /* remove it? */2940 if (strcmp(intnet[n], "none") == 0)2941 {2942 CHECK_ERROR_RET(nic, COMSETTER(InternalNetwork)(NULL), 1);2943 }2944 else2945 {2946 CHECK_ERROR_RET(nic, COMSETTER(InternalNetwork)(Bstr(intnet[n])), 1);2947 }2948 }2949 /* the network of the NAT */2950 if (natnet[n])2951 {2952 CHECK_ERROR_RET(nic, COMSETTER(NATNetwork)(Bstr(natnet[n])), 1);2953 }2954 #ifdef RT_OS_LINUX2955 /* the TAP setup application? */2956 if (tapsetup[n])2957 {2958 /* remove it? */2959 if (strcmp(tapsetup[n], "none") == 0)2960 {2961 CHECK_ERROR_RET(nic, COMSETTER(TAPSetupApplication)(NULL), 1);2962 }2963 else2964 {2965 CHECK_ERROR_RET(nic, COMSETTER(TAPSetupApplication)(Bstr(tapsetup[n])), 1);2966 }2967 }2968 2969 /* the TAP terminate application? */2970 if (tapterm[n])2971 {2972 /* remove it? */2973 if (strcmp(tapterm[n], "none") == 0)2974 {2975 CHECK_ERROR_RET(nic, COMSETTER(TAPTerminateApplication)(NULL), 1);2976 }2977 else2978 {2979 CHECK_ERROR_RET(nic, COMSETTER(TAPTerminateApplication)(Bstr(tapterm[n])), 1);2980 }2981 }2982 #endif /* RT_OS_LINUX */2983 2984 }2985 if (FAILED(rc))2986 break;2987 2988 /* iterate through all possible serial ports */2989 for (ULONG n = 0; n < SerialPortCount; n ++)2990 {2991 ComPtr<ISerialPort> uart;2992 CHECK_ERROR_RET (machine, GetSerialPort (n, uart.asOutParam()), 1);2993 2994 ASSERT(uart);2995 2996 if (uarts_base[n])2997 {2998 if (uarts_base[n] == (ULONG)-1)2999 {3000 CHECK_ERROR_RET(uart, COMSETTER(Enabled) (FALSE), 1);3001 }3002 else3003 {3004 CHECK_ERROR_RET(uart, COMSETTER(IOBase) (uarts_base[n]), 1);3005 CHECK_ERROR_RET(uart, COMSETTER(IRQ) (uarts_irq[n]), 1);3006 CHECK_ERROR_RET(uart, COMSETTER(Enabled) (TRUE), 1);3007 }3008 }3009 if (uarts_mode[n])3010 {3011 if (strcmp(uarts_mode[n], "disconnected") == 0)3012 {3013 CHECK_ERROR_RET(uart, COMSETTER(HostMode) (PortMode_Disconnected), 1);3014 }3015 else3016 {3017 if (strcmp(uarts_mode[n], "server") == 0)3018 {3019 CHECK_ERROR_RET(uart, COMSETTER(HostMode) (PortMode_HostPipe), 1);3020 CHECK_ERROR_RET(uart, COMSETTER(Server) (TRUE), 1);3021 }3022 else if (strcmp(uarts_mode[n], "client") == 0)3023 {3024 CHECK_ERROR_RET(uart, COMSETTER(HostMode) (PortMode_HostPipe), 1);3025 CHECK_ERROR_RET(uart, COMSETTER(Server) (FALSE), 1);3026 }3027 else3028 {3029 CHECK_ERROR_RET(uart, COMSETTER(HostMode) (PortMode_HostDevice), 1);3030 }3031 CHECK_ERROR_RET(uart, COMSETTER(Path) (Bstr(uarts_path[n])), 1);3032 }3033 }3034 }3035 if (FAILED(rc))3036 break;3037 3038 #ifdef VBOX_WITH_VRDP3039 if (vrdp || (vrdpport != UINT16_MAX) || vrdpaddress || vrdpauthtype || vrdpmulticon || vrdpreusecon)3040 {3041 ComPtr<IVRDPServer> vrdpServer;3042 machine->COMGETTER(VRDPServer)(vrdpServer.asOutParam());3043 ASSERT(vrdpServer);3044 if (vrdpServer)3045 {3046 if (vrdp)3047 {3048 if (strcmp(vrdp, "on") == 0)3049 {3050 CHECK_ERROR(vrdpServer, COMSETTER(Enabled)(true));3051 }3052 else if (strcmp(vrdp, "off") == 0)3053 {3054 CHECK_ERROR(vrdpServer, COMSETTER(Enabled)(false));3055 }3056 else3057 {3058 errorArgument("Invalid -vrdp argument '%s'", vrdp);3059 rc = E_FAIL;3060 break;3061 }3062 }3063 if (vrdpport != UINT16_MAX)3064 {3065 CHECK_ERROR(vrdpServer, COMSETTER(Port)(vrdpport));3066 }3067 if (vrdpaddress)3068 {3069 CHECK_ERROR(vrdpServer, COMSETTER(NetAddress)(Bstr(vrdpaddress)));3070 }3071 if (vrdpauthtype)3072 {3073 if (strcmp(vrdpauthtype, "null") == 0)3074 {3075 CHECK_ERROR(vrdpServer, COMSETTER(AuthType)(VRDPAuthType_Null));3076 }3077 else if (strcmp(vrdpauthtype, "external") == 0)3078 {3079 CHECK_ERROR(vrdpServer, COMSETTER(AuthType)(VRDPAuthType_External));3080 }3081 else if (strcmp(vrdpauthtype, "guest") == 0)3082 {3083 CHECK_ERROR(vrdpServer, COMSETTER(AuthType)(VRDPAuthType_Guest));3084 }3085 else3086 {3087 errorArgument("Invalid -vrdpauthtype argument '%s'", vrdpauthtype);3088 rc = E_FAIL;3089 break;3090 }3091 }3092 if (vrdpmulticon)3093 {3094 if (strcmp(vrdpmulticon, "on") == 0)3095 {3096 CHECK_ERROR(vrdpServer, COMSETTER(AllowMultiConnection)(true));3097 }3098 else if (strcmp(vrdpmulticon, "off") == 0)3099 {3100 CHECK_ERROR(vrdpServer, COMSETTER(AllowMultiConnection)(false));3101 }3102 else3103 {3104 errorArgument("Invalid -vrdpmulticon argument '%s'", vrdpmulticon);3105 rc = E_FAIL;3106 break;3107 }3108 }3109 if (vrdpreusecon)3110 {3111 if (strcmp(vrdpreusecon, "on") == 0)3112 {3113 CHECK_ERROR(vrdpServer, COMSETTER(ReuseSingleConnection)(true));3114 }3115 else if (strcmp(vrdpreusecon, "off") == 0)3116 {3117 CHECK_ERROR(vrdpServer, COMSETTER(ReuseSingleConnection)(false));3118 }3119 else3120 {3121 errorArgument("Invalid -vrdpreusecon argument '%s'", vrdpreusecon);3122 rc = E_FAIL;3123 break;3124 }3125 }3126 }3127 }3128 #endif /* VBOX_WITH_VRDP */3129 3130 /*3131 * USB enable/disable3132 */3133 if (fUsbEnabled != -1)3134 {3135 ComPtr<IUSBController> UsbCtl;3136 CHECK_ERROR(machine, COMGETTER(USBController)(UsbCtl.asOutParam()));3137 if (SUCCEEDED(rc))3138 {3139 CHECK_ERROR(UsbCtl, COMSETTER(Enabled)(!!fUsbEnabled));3140 }3141 }3142 /*3143 * USB EHCI enable/disable3144 */3145 if (fUsbEhciEnabled != -1)3146 {3147 ComPtr<IUSBController> UsbCtl;3148 CHECK_ERROR(machine, COMGETTER(USBController)(UsbCtl.asOutParam()));3149 if (SUCCEEDED(rc))3150 {3151 CHECK_ERROR(UsbCtl, COMSETTER(EnabledEhci)(!!fUsbEhciEnabled));3152 }3153 }3154 3155 if (snapshotFolder)3156 {3157 if (strcmp(snapshotFolder, "default") == 0)3158 {3159 CHECK_ERROR(machine, COMSETTER(SnapshotFolder)(NULL));3160 }3161 else3162 {3163 CHECK_ERROR(machine, COMSETTER(SnapshotFolder)(Bstr(snapshotFolder)));3164 }3165 }3166 3167 if (guestMemBalloonSize != (ULONG)-1)3168 CHECK_ERROR(machine, COMSETTER(MemoryBalloonSize)(guestMemBalloonSize));3169 3170 if (guestStatInterval != (ULONG)-1)3171 CHECK_ERROR(machine, COMSETTER(StatisticsUpdateInterval)(guestStatInterval));3172 3173 /*3174 * SATA controller enable/disable3175 */3176 if (fSataEnabled != -1)3177 {3178 ComPtr<ISATAController> SataCtl;3179 CHECK_ERROR(machine, COMGETTER(SATAController)(SataCtl.asOutParam()));3180 if (SUCCEEDED(rc))3181 {3182 CHECK_ERROR(SataCtl, COMSETTER(Enabled)(!!fSataEnabled));3183 }3184 }3185 3186 for (uint32_t i = 4; i < 34; i++)3187 {3188 if (hdds[i])3189 {3190 if (strcmp(hdds[i], "none") == 0)3191 {3192 machine->DetachHardDisk2(StorageBus_SATA, i-4, 0);3193 }3194 else3195 {3196 /* first guess is that it's a UUID */3197 Guid uuid(hdds[i]);3198 ComPtr<IHardDisk2> hardDisk;3199 rc = virtualBox->GetHardDisk2(uuid, hardDisk.asOutParam());3200 /* not successful? Then it must be a filename */3201 if (!hardDisk)3202 {3203 CHECK_ERROR(virtualBox, FindHardDisk2(Bstr(hdds[i]), hardDisk.asOutParam()));3204 if (FAILED(rc))3205 {3206 /* open the new hard disk object */3207 CHECK_ERROR(virtualBox, OpenHardDisk2(Bstr(hdds[i]), hardDisk.asOutParam()));3208 }3209 }3210 if (hardDisk)3211 {3212 hardDisk->COMGETTER(Id)(uuid.asOutParam());3213 CHECK_ERROR(machine, AttachHardDisk2(uuid, StorageBus_SATA, i-4, 0));3214 }3215 else3216 rc = E_FAIL;3217 if (FAILED(rc))3218 break;3219 }3220 }3221 }3222 3223 for (uint32_t i = 0; i < 4; i++)3224 {3225 if (sataBootDevices[i] != -1)3226 {3227 ComPtr<ISATAController> SataCtl;3228 CHECK_ERROR(machine, COMGETTER(SATAController)(SataCtl.asOutParam()));3229 if (SUCCEEDED(rc))3230 {3231 CHECK_ERROR(SataCtl, SetIDEEmulationPort(i, sataBootDevices[i]));3232 }3233 }3234 }3235 3236 if (sataPortCount != -1)3237 {3238 ComPtr<ISATAController> SataCtl;3239 CHECK_ERROR(machine, COMGETTER(SATAController)(SataCtl.asOutParam()));3240 if (SUCCEEDED(rc))3241 {3242 CHECK_ERROR(SataCtl, COMSETTER(PortCount)(sataPortCount));3243 }3244 }3245 3246 /* commit changes */3247 CHECK_ERROR(machine, SaveSettings());3248 }3249 while (0);3250 3251 /* it's important to always close sessions */3252 session->Close();3253 3254 return SUCCEEDED(rc) ? 0 : 1;3255 }3256 3257 static int handleStartVM(int argc, char *argv[],3258 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)3259 {3260 HRESULT rc;3261 3262 if (argc < 1)3263 return errorSyntax(USAGE_STARTVM, "Not enough parameters");3264 3265 ComPtr<IMachine> machine;3266 /* assume it's a UUID */3267 rc = virtualBox->GetMachine(Guid(argv[0]), machine.asOutParam());3268 if (FAILED(rc) || !machine)3269 {3270 /* must be a name */3271 CHECK_ERROR(virtualBox, FindMachine(Bstr(argv[0]), machine.asOutParam()));3272 }3273 if (machine)3274 {3275 Guid uuid;3276 machine->COMGETTER(Id)(uuid.asOutParam());3277 3278 /* default to GUI session type */3279 Bstr sessionType = "gui";3280 /* has a session type been specified? */3281 if ((argc > 2) && (strcmp(argv[1], "-type") == 0))3282 {3283 if (strcmp(argv[2], "gui") == 0)3284 {3285 sessionType = "gui";3286 }3287 else if (strcmp(argv[2], "vrdp") == 0)3288 {3289 sessionType = "vrdp";3290 }3291 else if (strcmp(argv[2], "capture") == 0)3292 {3293 sessionType = "capture";3294 }3295 else3296 return errorArgument("Invalid session type argument '%s'", argv[2]);3297 }3298 3299 Bstr env;3300 #ifdef RT_OS_LINUX3301 /* make sure the VM process will start on the same display as VBoxManage */3302 {3303 const char *display = RTEnvGet ("DISPLAY");3304 if (display)3305 env = Utf8StrFmt ("DISPLAY=%s", display);3306 }3307 #endif3308 ComPtr<IProgress> progress;3309 CHECK_ERROR_RET(virtualBox, OpenRemoteSession(session, uuid, sessionType,3310 env, progress.asOutParam()), rc);3311 RTPrintf("Waiting for the remote session to open...\n");3312 CHECK_ERROR_RET(progress, WaitForCompletion (-1), 1);3313 3314 BOOL completed;3315 CHECK_ERROR_RET(progress, COMGETTER(Completed)(&completed), rc);3316 ASSERT(completed);3317 3318 HRESULT resultCode;3319 CHECK_ERROR_RET(progress, COMGETTER(ResultCode)(&resultCode), rc);3320 if (FAILED(resultCode))3321 {3322 ComPtr <IVirtualBoxErrorInfo> errorInfo;3323 CHECK_ERROR_RET(progress, COMGETTER(ErrorInfo)(errorInfo.asOutParam()), 1);3324 ErrorInfo info (errorInfo);3325 PRINT_ERROR_INFO(info);3326 }3327 else3328 {3329 RTPrintf("Remote session has been successfully opened.\n");3330 }3331 }3332 3333 /* it's important to always close sessions */3334 session->Close();3335 3336 return SUCCEEDED(rc) ? 0 : 1;3337 }3338 3339 static int handleControlVM(int argc, char *argv[],3340 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)3341 {3342 HRESULT rc;3343 3344 if (argc < 2)3345 return errorSyntax(USAGE_CONTROLVM, "Not enough parameters");3346 3347 /* try to find the given machine */3348 ComPtr <IMachine> machine;3349 Guid uuid (argv[0]);3350 if (!uuid.isEmpty())3351 {3352 CHECK_ERROR (virtualBox, GetMachine (uuid, machine.asOutParam()));3353 }3354 else3355 {3356 CHECK_ERROR (virtualBox, FindMachine (Bstr(argv[0]), machine.asOutParam()));3357 if (SUCCEEDED (rc))3358 machine->COMGETTER(Id) (uuid.asOutParam());3359 }3360 if (FAILED (rc))3361 return 1;3362 3363 /* open a session for the VM */3364 CHECK_ERROR_RET (virtualBox, OpenExistingSession (session, uuid), 1);3365 3366 do3367 {3368 /* get the associated console */3369 ComPtr<IConsole> console;3370 CHECK_ERROR_BREAK (session, COMGETTER(Console)(console.asOutParam()));3371 /* ... and session machine */3372 ComPtr<IMachine> sessionMachine;3373 CHECK_ERROR_BREAK (session, COMGETTER(Machine)(sessionMachine.asOutParam()));3374 3375 /* which command? */3376 if (strcmp(argv[1], "pause") == 0)3377 {3378 CHECK_ERROR_BREAK (console, Pause());3379 }3380 else if (strcmp(argv[1], "resume") == 0)3381 {3382 CHECK_ERROR_BREAK (console, Resume());3383 }3384 else if (strcmp(argv[1], "reset") == 0)3385 {3386 CHECK_ERROR_BREAK (console, Reset());3387 }3388 else if (strcmp(argv[1], "poweroff") == 0)3389 {3390 CHECK_ERROR_BREAK (console, PowerDown());3391 }3392 else if (strcmp(argv[1], "savestate") == 0)3393 {3394 ComPtr<IProgress> progress;3395 CHECK_ERROR_BREAK (console, SaveState(progress.asOutParam()));3396 3397 showProgress(progress);3398 3399 progress->COMGETTER(ResultCode)(&rc);3400 if (FAILED(rc))3401 {3402 com::ProgressErrorInfo info(progress);3403 if (info.isBasicAvailable())3404 {3405 RTPrintf("Error: failed to save machine state. Error message: %lS\n", info.getText().raw());3406 }3407 else3408 {3409 RTPrintf("Error: failed to save machine state. No error message available!\n");3410 }3411 }3412 }3413 else if (strcmp(argv[1], "acpipowerbutton") == 0)3414 {3415 CHECK_ERROR_BREAK (console, PowerButton());3416 }3417 else if (strcmp(argv[1], "acpisleepbutton") == 0)3418 {3419 CHECK_ERROR_BREAK (console, SleepButton());3420 }3421 else if (strcmp(argv[1], "injectnmi") == 0)3422 {3423 /* get the machine debugger. */3424 ComPtr <IMachineDebugger> debugger;3425 CHECK_ERROR_BREAK(console, COMGETTER(Debugger)(debugger.asOutParam()));3426 CHECK_ERROR_BREAK(debugger, InjectNMI());3427 }3428 else if (strcmp(argv[1], "keyboardputscancode") == 0)3429 {3430 ComPtr<IKeyboard> keyboard;3431 CHECK_ERROR_BREAK(console, COMGETTER(Keyboard)(keyboard.asOutParam()));3432 3433 if (argc <= 1 + 1)3434 {3435 errorArgument("Missing argument to '%s'. Expected IBM PC AT set 2 keyboard scancode(s) as hex byte(s).", argv[1]);3436 rc = E_FAIL;3437 break;3438 }3439 3440 /* Arbitrary restrict the length of a sequence of scancodes to 1024. */3441 LONG alScancodes[1024];3442 int cScancodes = 0;3443 3444 /* Process the command line. */3445 int i;3446 for (i = 1 + 1; i < argc && cScancodes < (int)RT_ELEMENTS(alScancodes); i++, cScancodes++)3447 {3448 if ( isxdigit (argv[i][0])3449 && isxdigit (argv[i][1])3450 && argv[i][2] == 0)3451 {3452 uint8_t u8Scancode;3453 int rc = RTStrToUInt8Ex(argv[i], NULL, 16, &u8Scancode);3454 if (RT_FAILURE (rc))3455 {3456 RTPrintf("Error: converting '%s' returned %Rrc!\n", argv[i], rc);3457 rc = E_FAIL;3458 break;3459 }3460 3461 alScancodes[cScancodes] = u8Scancode;3462 }3463 else3464 {3465 RTPrintf("Error: '%s' is not a hex byte!\n", argv[i]);3466 rc = E_FAIL;3467 break;3468 }3469 }3470 3471 if (FAILED(rc))3472 break;3473 3474 if ( cScancodes == RT_ELEMENTS(alScancodes)3475 && i < argc)3476 {3477 RTPrintf("Error: too many scancodes, maximum %d allowed!\n", RT_ELEMENTS(alScancodes));3478 rc = E_FAIL;3479 break;3480 }3481 3482 /* Send scancodes to the VM.3483 * Note: 'PutScancodes' did not work here. Only the first scancode was transmitted.3484 */3485 for (i = 0; i < cScancodes; i++)3486 {3487 CHECK_ERROR_BREAK(keyboard, PutScancode(alScancodes[i]));3488 RTPrintf("Scancode[%d]: 0x%02X\n", i, alScancodes[i]);3489 }3490 }3491 else if (strncmp(argv[1], "setlinkstate", 12) == 0)3492 {3493 /* Get the number of network adapters */3494 ULONG NetworkAdapterCount = 0;3495 ComPtr <ISystemProperties> info;3496 CHECK_ERROR_BREAK (virtualBox, COMGETTER(SystemProperties) (info.asOutParam()));3497 CHECK_ERROR_BREAK (info, COMGETTER(NetworkAdapterCount) (&NetworkAdapterCount));3498 3499 unsigned n = parseNum(&argv[1][12], NetworkAdapterCount, "NIC");3500 if (!n)3501 {3502 rc = E_FAIL;3503 break;3504 }3505 if (argc <= 1 + 1)3506 {3507 errorArgument("Missing argument to '%s'", argv[1]);3508 rc = E_FAIL;3509 break;3510 }3511 /* get the corresponding network adapter */3512 ComPtr<INetworkAdapter> adapter;3513 CHECK_ERROR_BREAK (sessionMachine, GetNetworkAdapter(n - 1, adapter.asOutParam()));3514 if (adapter)3515 {3516 if (strcmp(argv[2], "on") == 0)3517 {3518 CHECK_ERROR_BREAK (adapter, COMSETTER(CableConnected)(TRUE));3519 }3520 else if (strcmp(argv[2], "off") == 0)3521 {3522 CHECK_ERROR_BREAK (adapter, COMSETTER(CableConnected)(FALSE));3523 }3524 else3525 {3526 errorArgument("Invalid link state '%s'", Utf8Str(argv[2]).raw());3527 rc = E_FAIL;3528 break;3529 }3530 }3531 }3532 else if (strcmp (argv[1], "usbattach") == 0 ||3533 strcmp (argv[1], "usbdetach") == 0)3534 {3535 if (argc < 3)3536 {3537 errorSyntax(USAGE_CONTROLVM, "Not enough parameters");3538 rc = E_FAIL;3539 break;3540 }3541 3542 bool attach = strcmp (argv[1], "usbattach") == 0;3543 3544 Guid usbId = argv [2];3545 if (usbId.isEmpty())3546 {3547 // assume address3548 if (attach)3549 {3550 ComPtr <IHost> host;3551 CHECK_ERROR_BREAK (virtualBox, COMGETTER(Host) (host.asOutParam()));3552 ComPtr <IHostUSBDeviceCollection> coll;3553 CHECK_ERROR_BREAK (host, COMGETTER(USBDevices) (coll.asOutParam()));3554 ComPtr <IHostUSBDevice> dev;3555 CHECK_ERROR_BREAK (coll, FindByAddress (Bstr (argv [2]), dev.asOutParam()));3556 CHECK_ERROR_BREAK (dev, COMGETTER(Id) (usbId.asOutParam()));3557 }3558 else3559 {3560 ComPtr <IUSBDeviceCollection> coll;3561 CHECK_ERROR_BREAK (console, COMGETTER(USBDevices)(coll.asOutParam()));3562 ComPtr <IUSBDevice> dev;3563 CHECK_ERROR_BREAK (coll, FindByAddress (Bstr (argv [2]), dev.asOutParam()));3564 CHECK_ERROR_BREAK (dev, COMGETTER(Id) (usbId.asOutParam()));3565 }3566 }3567 3568 if (attach)3569 CHECK_ERROR_BREAK (console, AttachUSBDevice (usbId));3570 else3571 {3572 ComPtr <IUSBDevice> dev;3573 CHECK_ERROR_BREAK (console, DetachUSBDevice (usbId, dev.asOutParam()));3574 }3575 }3576 else if (strcmp(argv[1], "setvideomodehint") == 0)3577 {3578 if (argc != 5 && argc != 6)3579 {3580 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");3581 rc = E_FAIL;3582 break;3583 }3584 uint32_t xres = atoi(argv[2]);3585 uint32_t yres = atoi(argv[3]);3586 uint32_t bpp = atoi(argv[4]);3587 uint32_t displayIdx = 0;3588 if (argc == 6)3589 displayIdx = atoi(argv[5]);3590 3591 ComPtr<IDisplay> display;3592 CHECK_ERROR_BREAK(console, COMGETTER(Display)(display.asOutParam()));3593 CHECK_ERROR_BREAK(display, SetVideoModeHint(xres, yres, bpp, displayIdx));3594 }3595 else if (strcmp(argv[1], "setcredentials") == 0)3596 {3597 bool fAllowLocalLogon = true;3598 if (argc == 7)3599 {3600 if (strcmp(argv[5], "-allowlocallogon") != 0)3601 {3602 errorArgument("Invalid parameter '%s'", argv[5]);3603 rc = E_FAIL;3604 break;3605 }3606 if (strcmp(argv[6], "no") == 0)3607 fAllowLocalLogon = false;3608 }3609 else if (argc != 5)3610 {3611 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");3612 rc = E_FAIL;3613 break;3614 }3615 3616 ComPtr<IGuest> guest;3617 CHECK_ERROR_BREAK(console, COMGETTER(Guest)(guest.asOutParam()));3618 CHECK_ERROR_BREAK(guest, SetCredentials(Bstr(argv[2]), Bstr(argv[3]), Bstr(argv[4]), fAllowLocalLogon));3619 }3620 else if (strcmp(argv[1], "dvdattach") == 0)3621 {3622 if (argc != 3)3623 {3624 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");3625 rc = E_FAIL;3626 break;3627 }3628 ComPtr<IDVDDrive> dvdDrive;3629 sessionMachine->COMGETTER(DVDDrive)(dvdDrive.asOutParam());3630 ASSERT(dvdDrive);3631 3632 /* unmount? */3633 if (strcmp(argv[2], "none") == 0)3634 {3635 CHECK_ERROR(dvdDrive, Unmount());3636 }3637 /* host drive? */3638 else if (strncmp(argv[2], "host:", 5) == 0)3639 {3640 ComPtr<IHost> host;3641 CHECK_ERROR(virtualBox, COMGETTER(Host)(host.asOutParam()));3642 ComPtr<IHostDVDDriveCollection> hostDVDs;3643 CHECK_ERROR(host, COMGETTER(DVDDrives)(hostDVDs.asOutParam()));3644 ComPtr<IHostDVDDrive> hostDVDDrive;3645 rc = hostDVDs->FindByName(Bstr(argv[2] + 5), hostDVDDrive.asOutParam());3646 if (!hostDVDDrive)3647 {3648 errorArgument("Invalid host DVD drive name");3649 rc = E_FAIL;3650 break;3651 }3652 CHECK_ERROR(dvdDrive, CaptureHostDrive(hostDVDDrive));3653 }3654 else3655 {3656 /* first assume it's a UUID */3657 Guid uuid(argv[2]);3658 ComPtr<IDVDImage2> dvdImage;3659 rc = virtualBox->GetDVDImage(uuid, dvdImage.asOutParam());3660 if (FAILED(rc) || !dvdImage)3661 {3662 /* must be a filename, check if it's in the collection */3663 rc = virtualBox->FindDVDImage(Bstr(argv[2]), dvdImage.asOutParam());3664 /* not registered, do that on the fly */3665 if (!dvdImage)3666 {3667 Guid emptyUUID;3668 CHECK_ERROR(virtualBox, OpenDVDImage(Bstr(argv[2]), emptyUUID, dvdImage.asOutParam()));3669 }3670 }3671 if (!dvdImage)3672 {3673 rc = E_FAIL;3674 break;3675 }3676 dvdImage->COMGETTER(Id)(uuid.asOutParam());3677 CHECK_ERROR(dvdDrive, MountImage(uuid));3678 }3679 }3680 else if (strcmp(argv[1], "floppyattach") == 0)3681 {3682 if (argc != 3)3683 {3684 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");3685 rc = E_FAIL;3686 break;3687 }3688 3689 ComPtr<IFloppyDrive> floppyDrive;3690 sessionMachine->COMGETTER(FloppyDrive)(floppyDrive.asOutParam());3691 ASSERT(floppyDrive);3692 3693 /* unmount? */3694 if (strcmp(argv[2], "none") == 0)3695 {3696 CHECK_ERROR(floppyDrive, Unmount());3697 }3698 /* host drive? */3699 else if (strncmp(argv[2], "host:", 5) == 0)3700 {3701 ComPtr<IHost> host;3702 CHECK_ERROR(virtualBox, COMGETTER(Host)(host.asOutParam()));3703 ComPtr<IHostFloppyDriveCollection> hostFloppies;3704 CHECK_ERROR(host, COMGETTER(FloppyDrives)(hostFloppies.asOutParam()));3705 ComPtr<IHostFloppyDrive> hostFloppyDrive;3706 rc = hostFloppies->FindByName(Bstr(argv[2] + 5), hostFloppyDrive.asOutParam());3707 if (!hostFloppyDrive)3708 {3709 errorArgument("Invalid host floppy drive name");3710 rc = E_FAIL;3711 break;3712 }3713 CHECK_ERROR(floppyDrive, CaptureHostDrive(hostFloppyDrive));3714 }3715 else3716 {3717 /* first assume it's a UUID */3718 Guid uuid(argv[2]);3719 ComPtr<IFloppyImage2> floppyImage;3720 rc = virtualBox->GetFloppyImage(uuid, floppyImage.asOutParam());3721 if (FAILED(rc) || !floppyImage)3722 {3723 /* must be a filename, check if it's in the collection */3724 rc = virtualBox->FindFloppyImage(Bstr(argv[2]), floppyImage.asOutParam());3725 /* not registered, do that on the fly */3726 if (!floppyImage)3727 {3728 Guid emptyUUID;3729 CHECK_ERROR(virtualBox, OpenFloppyImage(Bstr(argv[2]), emptyUUID, floppyImage.asOutParam()));3730 }3731 }3732 if (!floppyImage)3733 {3734 rc = E_FAIL;3735 break;3736 }3737 floppyImage->COMGETTER(Id)(uuid.asOutParam());3738 CHECK_ERROR(floppyDrive, MountImage(uuid));3739 }3740 }3741 #ifdef VBOX_WITH_MEM_BALLOONING3742 else if (strncmp(argv[1], "-guestmemoryballoon", 19) == 0)3743 {3744 if (argc != 3)3745 {3746 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");3747 rc = E_FAIL;3748 break;3749 }3750 uint32_t uVal;3751 int vrc;3752 vrc = RTStrToUInt32Ex(argv[2], NULL, 0, &uVal);3753 if (vrc != VINF_SUCCESS)3754 {3755 errorArgument("Error parsing guest memory balloon size '%s'", argv[2]);3756 rc = E_FAIL;3757 break;3758 }3759 3760 /* guest is running; update IGuest */3761 ComPtr <IGuest> guest;3762 3763 rc = console->COMGETTER(Guest)(guest.asOutParam());3764 if (SUCCEEDED(rc))3765 CHECK_ERROR(guest, COMSETTER(MemoryBalloonSize)(uVal));3766 }3767 #endif3768 else if (strncmp(argv[1], "-gueststatisticsinterval", 24) == 0)3769 {3770 if (argc != 3)3771 {3772 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");3773 rc = E_FAIL;3774 break;3775 }3776 uint32_t uVal;3777 int vrc;3778 vrc = RTStrToUInt32Ex(argv[2], NULL, 0, &uVal);3779 if (vrc != VINF_SUCCESS)3780 {3781 errorArgument("Error parsing guest statistics interval '%s'", argv[2]);3782 rc = E_FAIL;3783 break;3784 }3785 3786 /* guest is running; update IGuest */3787 ComPtr <IGuest> guest;3788 3789 rc = console->COMGETTER(Guest)(guest.asOutParam());3790 if (SUCCEEDED(rc))3791 CHECK_ERROR(guest, COMSETTER(StatisticsUpdateInterval)(uVal));3792 }3793 else3794 {3795 errorSyntax(USAGE_CONTROLVM, "Invalid parameter '%s'", Utf8Str(argv[1]).raw());3796 rc = E_FAIL;3797 }3798 }3799 while (0);3800 3801 session->Close();3802 3803 return SUCCEEDED (rc) ? 0 : 1;3804 }3805 3806 static int handleDiscardState(int argc, char *argv[],3807 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)3808 {3809 HRESULT rc;3810 3811 if (argc != 1)3812 return errorSyntax(USAGE_DISCARDSTATE, "Incorrect number of parameters");3813 3814 ComPtr<IMachine> machine;3815 /* assume it's a UUID */3816 rc = virtualBox->GetMachine(Guid(argv[0]), machine.asOutParam());3817 if (FAILED(rc) || !machine)3818 {3819 /* must be a name */3820 CHECK_ERROR(virtualBox, FindMachine(Bstr(argv[0]), machine.asOutParam()));3821 }3822 if (machine)3823 {3824 do3825 {3826 /* we have to open a session for this task */3827 Guid guid;3828 machine->COMGETTER(Id)(guid.asOutParam());3829 CHECK_ERROR_BREAK(virtualBox, OpenSession(session, guid));3830 do3831 {3832 ComPtr<IConsole> console;3833 CHECK_ERROR_BREAK(session, COMGETTER(Console)(console.asOutParam()));3834 CHECK_ERROR_BREAK(console, DiscardSavedState());3835 }3836 while (0);3837 CHECK_ERROR_BREAK(session, Close());3838 }3839 while (0);3840 }3841 3842 return SUCCEEDED(rc) ? 0 : 1;3843 }3844 3845 static int handleAdoptdState(int argc, char *argv[],3846 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)3847 {3848 HRESULT rc;3849 3850 if (argc != 2)3851 return errorSyntax(USAGE_ADOPTSTATE, "Incorrect number of parameters");3852 3853 ComPtr<IMachine> machine;3854 /* assume it's a UUID */3855 rc = virtualBox->GetMachine(Guid(argv[0]), machine.asOutParam());3856 if (FAILED(rc) || !machine)3857 {3858 /* must be a name */3859 CHECK_ERROR(virtualBox, FindMachine(Bstr(argv[0]), machine.asOutParam()));3860 }3861 if (machine)3862 {3863 do3864 {3865 /* we have to open a session for this task */3866 Guid guid;3867 machine->COMGETTER(Id)(guid.asOutParam());3868 CHECK_ERROR_BREAK(virtualBox, OpenSession(session, guid));3869 do3870 {3871 ComPtr<IConsole> console;3872 CHECK_ERROR_BREAK(session, COMGETTER(Console)(console.asOutParam()));3873 CHECK_ERROR_BREAK(console, AdoptSavedState (Bstr (argv[1])));3874 }3875 while (0);3876 CHECK_ERROR_BREAK(session, Close());3877 }3878 while (0);3879 }3880 3881 return SUCCEEDED(rc) ? 0 : 1;3882 }3883 3884 static int handleSnapshot(int argc, char *argv[],3885 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)3886 {3887 HRESULT rc;3888 3889 /* we need at least a VM and a command */3890 if (argc < 2)3891 return errorSyntax(USAGE_SNAPSHOT, "Not enough parameters");3892 3893 /* the first argument must be the VM */3894 ComPtr<IMachine> machine;3895 /* assume it's a UUID */3896 rc = virtualBox->GetMachine(Guid(argv[0]), machine.asOutParam());3897 if (FAILED(rc) || !machine)3898 {3899 /* must be a name */3900 CHECK_ERROR(virtualBox, FindMachine(Bstr(argv[0]), machine.asOutParam()));3901 }3902 if (!machine)3903 return 1;3904 Guid guid;3905 machine->COMGETTER(Id)(guid.asOutParam());3906 3907 do3908 {3909 /* we have to open a session for this task. First try an existing session */3910 rc = virtualBox->OpenExistingSession(session, guid);3911 if (FAILED(rc))3912 CHECK_ERROR_BREAK(virtualBox, OpenSession(session, guid));3913 ComPtr<IConsole> console;3914 CHECK_ERROR_BREAK(session, COMGETTER(Console)(console.asOutParam()));3915 3916 /* switch based on the command */3917 if (strcmp(argv[1], "take") == 0)3918 {3919 /* there must be a name */3920 if (argc < 3)3921 {3922 errorSyntax(USAGE_SNAPSHOT, "Missing snapshot name");3923 rc = E_FAIL;3924 break;3925 }3926 Bstr name(argv[2]);3927 if ((argc > 3) && ((argc != 5) || (strcmp(argv[3], "-desc") != 0)))3928 {3929 errorSyntax(USAGE_SNAPSHOT, "Incorrect description format");3930 rc = E_FAIL;3931 break;3932 }3933 Bstr desc;3934 if (argc == 5)3935 desc = argv[4];3936 ComPtr<IProgress> progress;3937 CHECK_ERROR_BREAK(console, TakeSnapshot(name, desc, progress.asOutParam()));3938 3939 showProgress(progress);3940 progress->COMGETTER(ResultCode)(&rc);3941 if (FAILED(rc))3942 {3943 com::ProgressErrorInfo info(progress);3944 if (info.isBasicAvailable())3945 RTPrintf("Error: failed to take snapshot. Error message: %lS\n", info.getText().raw());3946 else3947 RTPrintf("Error: failed to take snapshot. No error message available!\n");3948 }3949 }3950 else if (strcmp(argv[1], "discard") == 0)3951 {3952 /* exactly one parameter: snapshot name */3953 if (argc != 3)3954 {3955 errorSyntax(USAGE_SNAPSHOT, "Expecting snapshot name only");3956 rc = E_FAIL;3957 break;3958 }3959 3960 ComPtr<ISnapshot> snapshot;3961 3962 /* assume it's a UUID */3963 Guid guid(argv[2]);3964 if (!guid.isEmpty())3965 {3966 CHECK_ERROR_BREAK(machine, GetSnapshot(guid, snapshot.asOutParam()));3967 }3968 else3969 {3970 /* then it must be a name */3971 CHECK_ERROR_BREAK(machine, FindSnapshot(Bstr(argv[2]), snapshot.asOutParam()));3972 }3973 3974 snapshot->COMGETTER(Id)(guid.asOutParam());3975 3976 ComPtr<IProgress> progress;3977 CHECK_ERROR_BREAK(console, DiscardSnapshot(guid, progress.asOutParam()));3978 3979 showProgress(progress);3980 progress->COMGETTER(ResultCode)(&rc);3981 if (FAILED(rc))3982 {3983 com::ProgressErrorInfo info(progress);3984 if (info.isBasicAvailable())3985 RTPrintf("Error: failed to discard snapshot. Error message: %lS\n", info.getText().raw());3986 else3987 RTPrintf("Error: failed to discard snapshot. No error message available!\n");3988 }3989 }3990 else if (strcmp(argv[1], "discardcurrent") == 0)3991 {3992 if ( (argc != 3)3993 || ( (strcmp(argv[2], "-state") != 0)3994 && (strcmp(argv[2], "-all") != 0)))3995 {3996 errorSyntax(USAGE_SNAPSHOT, "Invalid parameter '%s'", Utf8Str(argv[2]).raw());3997 rc = E_FAIL;3998 break;3999 }4000 bool fAll = false;4001 if (strcmp(argv[2], "-all") == 0)4002 fAll = true;4003 4004 ComPtr<IProgress> progress;4005 4006 if (fAll)4007 {4008 CHECK_ERROR_BREAK(console, DiscardCurrentSnapshotAndState(progress.asOutParam()));4009 }4010 else4011 {4012 CHECK_ERROR_BREAK(console, DiscardCurrentState(progress.asOutParam()));4013 }4014 4015 showProgress(progress);4016 progress->COMGETTER(ResultCode)(&rc);4017 if (FAILED(rc))4018 {4019 com::ProgressErrorInfo info(progress);4020 if (info.isBasicAvailable())4021 RTPrintf("Error: failed to discard. Error message: %lS\n", info.getText().raw());4022 else4023 RTPrintf("Error: failed to discard. No error message available!\n");4024 }4025 4026 }4027 else if (strcmp(argv[1], "edit") == 0)4028 {4029 if (argc < 3)4030 {4031 errorSyntax(USAGE_SNAPSHOT, "Missing snapshot name");4032 rc = E_FAIL;4033 break;4034 }4035 4036 ComPtr<ISnapshot> snapshot;4037 4038 if (strcmp(argv[2], "-current") == 0)4039 {4040 CHECK_ERROR_BREAK(machine, COMGETTER(CurrentSnapshot)(snapshot.asOutParam()));4041 }4042 else4043 {4044 /* assume it's a UUID */4045 Guid guid(argv[2]);4046 if (!guid.isEmpty())4047 {4048 CHECK_ERROR_BREAK(machine, GetSnapshot(guid, snapshot.asOutParam()));4049 }4050 else4051 {4052 /* then it must be a name */4053 CHECK_ERROR_BREAK(machine, FindSnapshot(Bstr(argv[2]), snapshot.asOutParam()));4054 }4055 }4056 4057 /* parse options */4058 for (int i = 3; i < argc; i++)4059 {4060 if (strcmp(argv[i], "-newname") == 0)4061 {4062 if (argc <= i + 1)4063 {4064 errorArgument("Missing argument to '%s'", argv[i]);4065 rc = E_FAIL;4066 break;4067 }4068 i++;4069 snapshot->COMSETTER(Name)(Bstr(argv[i]));4070 }4071 else if (strcmp(argv[i], "-newdesc") == 0)4072 {4073 if (argc <= i + 1)4074 {4075 errorArgument("Missing argument to '%s'", argv[i]);4076 rc = E_FAIL;4077 break;4078 }4079 i++;4080 snapshot->COMSETTER(Description)(Bstr(argv[i]));4081 }4082 else4083 {4084 errorSyntax(USAGE_SNAPSHOT, "Invalid parameter '%s'", Utf8Str(argv[i]).raw());4085 rc = E_FAIL;4086 break;4087 }4088 }4089 4090 }4091 else if (strcmp(argv[1], "showvminfo") == 0)4092 {4093 /* exactly one parameter: snapshot name */4094 if (argc != 3)4095 {4096 errorSyntax(USAGE_SNAPSHOT, "Expecting snapshot name only");4097 rc = E_FAIL;4098 break;4099 }4100 4101 ComPtr<ISnapshot> snapshot;4102 4103 /* assume it's a UUID */4104 Guid guid(argv[2]);4105 if (!guid.isEmpty())4106 {4107 CHECK_ERROR_BREAK(machine, GetSnapshot(guid, snapshot.asOutParam()));4108 }4109 else4110 {4111 /* then it must be a name */4112 CHECK_ERROR_BREAK(machine, FindSnapshot(Bstr(argv[2]), snapshot.asOutParam()));4113 }4114 4115 /* get the machine of the given snapshot */4116 ComPtr<IMachine> machine;4117 snapshot->COMGETTER(Machine)(machine.asOutParam());4118 showVMInfo(virtualBox, machine, console);4119 }4120 else4121 {4122 errorSyntax(USAGE_SNAPSHOT, "Invalid parameter '%s'", Utf8Str(argv[1]).raw());4123 rc = E_FAIL;4124 }4125 } while (0);4126 4127 session->Close();4128 4129 return SUCCEEDED(rc) ? 0 : 1;4130 }4131 4132 static int handleShowHardDiskInfo(int argc, char *argv[],4133 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)4134 {4135 HRESULT rc;4136 4137 if (argc != 1)4138 return errorSyntax(USAGE_SHOWHDINFO, "Incorrect number of parameters");4139 4140 ComPtr<IHardDisk2> hardDisk;4141 Bstr filepath;4142 4143 bool unknown = false;4144 4145 /* first guess is that it's a UUID */4146 Guid uuid(argv[0]);4147 rc = virtualBox->GetHardDisk2(uuid, hardDisk.asOutParam());4148 /* no? then it must be a filename */4149 if (FAILED (rc))4150 {4151 filepath = argv[0];4152 rc = virtualBox->FindHardDisk2(filepath, hardDisk.asOutParam());4153 /* no? well, then it's an unkwnown image */4154 if (FAILED (rc))4155 {4156 CHECK_ERROR(virtualBox, OpenHardDisk2(filepath, hardDisk.asOutParam()));4157 if (SUCCEEDED (rc))4158 {4159 unknown = true;4160 }4161 }4162 }4163 do4164 {4165 if (!SUCCEEDED(rc))4166 break;4167 4168 hardDisk->COMGETTER(Id)(uuid.asOutParam());4169 RTPrintf("UUID: %s\n", uuid.toString().raw());4170 4171 /* check for accessibility */4172 /// @todo NEWMEDIA check accessibility of all parents4173 /// @todo NEWMEDIA print the full state value4174 MediaState_T state;4175 CHECK_ERROR_BREAK (hardDisk, COMGETTER(State)(&state));4176 RTPrintf("Accessible: %s\n", state != MediaState_Inaccessible ? "yes" : "no");4177 4178 if (state == MediaState_Inaccessible)4179 {4180 Bstr err;4181 CHECK_ERROR_BREAK (hardDisk, COMGETTER(LastAccessError)(err.asOutParam()));4182 RTPrintf("Access Error: %lS\n", err.raw());4183 }4184 4185 Bstr description;4186 hardDisk->COMGETTER(Description)(description.asOutParam());4187 if (description)4188 {4189 RTPrintf("Description: %lS\n", description.raw());4190 }4191 4192 ULONG64 logicalSize;4193 hardDisk->COMGETTER(LogicalSize)(&logicalSize);4194 RTPrintf("Logical size: %llu MBytes\n", logicalSize);4195 ULONG64 actualSize;4196 hardDisk->COMGETTER(Size)(&actualSize);4197 RTPrintf("Current size on disk: %llu MBytes\n", actualSize >> 20);4198 4199 HardDiskType_T type;4200 hardDisk->COMGETTER(Type)(&type);4201 const char *typeStr = "unknown";4202 switch (type)4203 {4204 case HardDiskType_Normal:4205 typeStr = "normal";4206 break;4207 case HardDiskType_Immutable:4208 typeStr = "immutable";4209 break;4210 case HardDiskType_Writethrough:4211 typeStr = "writethrough";4212 break;4213 }4214 RTPrintf("Type: %s\n", typeStr);4215 4216 Bstr format;4217 hardDisk->COMGETTER(Format)(format.asOutParam());4218 RTPrintf("Storage format: %lS\n", format.raw());4219 4220 if (!unknown)4221 {4222 com::SafeGUIDArray machineIds;4223 hardDisk->COMGETTER(MachineIds)(ComSafeArrayAsOutParam(machineIds));4224 for (size_t j = 0; j < machineIds.size(); ++ j)4225 {4226 ComPtr<IMachine> machine;4227 CHECK_ERROR(virtualBox, GetMachine(machineIds[j], machine.asOutParam()));4228 ASSERT(machine);4229 Bstr name;4230 machine->COMGETTER(Name)(name.asOutParam());4231 machine->COMGETTER(Id)(uuid.asOutParam());4232 RTPrintf("%s%lS (UUID: %RTuuid)\n",4233 j == 0 ? "In use by VMs: " : " ",4234 name.raw(), &machineIds[j]);4235 }4236 /// @todo NEWMEDIA check usage in snapshots too4237 /// @todo NEWMEDIA also list children and say 'differencing' for4238 /// hard disks with the parent or 'base' otherwise.4239 }4240 4241 Bstr loc;4242 hardDisk->COMGETTER(Location)(loc.asOutParam());4243 RTPrintf("Location: %lS\n", loc.raw());4244 }4245 while (0);4246 4247 if (unknown)4248 {4249 /* close the unknown hard disk to forget it again */4250 hardDisk->Close();4251 }4252 4253 return SUCCEEDED(rc) ? 0 : 1;4254 }4255 4256 static int handleOpenMedium(int argc, char *argv[],4257 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)4258 {4259 HRESULT rc;4260 4261 if (argc < 2)4262 return errorSyntax(USAGE_REGISTERIMAGE, "Not enough parameters");4263 4264 Bstr filepath(argv[1]);4265 4266 if (strcmp(argv[0], "disk") == 0)4267 {4268 const char *type = NULL;4269 /* there can be a type parameter */4270 if ((argc > 2) && (argc != 4))4271 return errorSyntax(USAGE_REGISTERIMAGE, "Incorrect number of parameters");4272 if (argc == 4)4273 {4274 if (strcmp(argv[2], "-type") != 0)4275 return errorSyntax(USAGE_REGISTERIMAGE, "Invalid parameter '%s'", Utf8Str(argv[2]).raw());4276 if ( (strcmp(argv[3], "normal") != 0)4277 && (strcmp(argv[3], "immutable") != 0)4278 && (strcmp(argv[3], "writethrough") != 0))4279 return errorArgument("Invalid hard disk type '%s' specified", Utf8Str(argv[3]).raw());4280 type = argv[3];4281 }4282 4283 ComPtr<IHardDisk2> hardDisk;4284 CHECK_ERROR(virtualBox, OpenHardDisk2(filepath, hardDisk.asOutParam()));4285 if (SUCCEEDED(rc) && hardDisk)4286 {4287 /* change the type if requested */4288 if (type)4289 {4290 if (strcmp(type, "normal") == 0)4291 CHECK_ERROR(hardDisk, COMSETTER(Type)(HardDiskType_Normal));4292 else if (strcmp(type, "immutable") == 0)4293 CHECK_ERROR(hardDisk, COMSETTER(Type)(HardDiskType_Immutable));4294 else if (strcmp(type, "writethrough") == 0)4295 CHECK_ERROR(hardDisk, COMSETTER(Type)(HardDiskType_Writethrough));4296 }4297 }4298 }4299 else if (strcmp(argv[0], "dvd") == 0)4300 {4301 ComPtr<IDVDImage2> dvdImage;4302 CHECK_ERROR(virtualBox, OpenDVDImage(filepath, Guid(), dvdImage.asOutParam()));4303 }4304 else if (strcmp(argv[0], "floppy") == 0)4305 {4306 ComPtr<IFloppyImage2> floppyImage;4307 CHECK_ERROR(virtualBox, OpenFloppyImage(filepath, Guid(), floppyImage.asOutParam()));4308 }4309 else4310 return errorSyntax(USAGE_REGISTERIMAGE, "Invalid parameter '%s'", Utf8Str(argv[1]).raw());4311 4312 return SUCCEEDED(rc) ? 0 : 1;4313 }4314 4315 static int handleCloseMedium(int argc, char *argv[],4316 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)4317 {4318 HRESULT rc;4319 4320 if (argc != 2)4321 return errorSyntax(USAGE_UNREGISTERIMAGE, "Incorrect number of parameters");4322 4323 /* first guess is that it's a UUID */4324 Guid uuid(argv[1]);4325 4326 if (strcmp(argv[0], "disk") == 0)4327 {4328 ComPtr<IHardDisk2> hardDisk;4329 rc = virtualBox->GetHardDisk2(uuid, hardDisk.asOutParam());4330 /* not a UUID or not registered? Then it must be a filename */4331 if (!hardDisk)4332 {4333 CHECK_ERROR(virtualBox, FindHardDisk2(Bstr(argv[1]), hardDisk.asOutParam()));4334 }4335 if (SUCCEEDED(rc) && hardDisk)4336 {4337 CHECK_ERROR(hardDisk, Close());4338 }4339 }4340 else4341 if (strcmp(argv[0], "dvd") == 0)4342 {4343 ComPtr<IDVDImage2> dvdImage;4344 rc = virtualBox->GetDVDImage(uuid, dvdImage.asOutParam());4345 /* not a UUID or not registered? Then it must be a filename */4346 if (!dvdImage)4347 {4348 CHECK_ERROR(virtualBox, FindDVDImage(Bstr(argv[1]), dvdImage.asOutParam()));4349 }4350 if (SUCCEEDED(rc) && dvdImage)4351 {4352 CHECK_ERROR(dvdImage, Close());4353 }4354 }4355 else4356 if (strcmp(argv[0], "floppy") == 0)4357 {4358 ComPtr<IFloppyImage2> floppyImage;4359 rc = virtualBox->GetFloppyImage(uuid, floppyImage.asOutParam());4360 /* not a UUID or not registered? Then it must be a filename */4361 if (!floppyImage)4362 {4363 CHECK_ERROR(virtualBox, FindFloppyImage(Bstr(argv[1]), floppyImage.asOutParam()));4364 }4365 if (SUCCEEDED(rc) && floppyImage)4366 {4367 CHECK_ERROR(floppyImage, Close());4368 }4369 }4370 else4371 return errorSyntax(USAGE_UNREGISTERIMAGE, "Invalid parameter '%s'", Utf8Str(argv[1]).raw());4372 4373 return SUCCEEDED(rc) ? 0 : 1;4374 }4375 4376 #ifdef RT_OS_WINDOWS4377 static int handleCreateHostIF(int argc, char *argv[],4378 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)4379 {4380 if (argc != 1)4381 return errorSyntax(USAGE_CREATEHOSTIF, "Incorrect number of parameters");4382 4383 HRESULT rc = S_OK;4384 4385 do4386 {4387 ComPtr<IHost> host;4388 CHECK_ERROR_BREAK(virtualBox, COMGETTER(Host)(host.asOutParam()));4389 4390 ComPtr<IHostNetworkInterface> hostif;4391 ComPtr<IProgress> progress;4392 CHECK_ERROR_BREAK(host,4393 CreateHostNetworkInterface(Bstr(argv[0]),4394 hostif.asOutParam(),4395 progress.asOutParam()));4396 4397 showProgress(progress);4398 HRESULT result;4399 CHECK_ERROR_BREAK(progress, COMGETTER(ResultCode)(&result));4400 if (FAILED(result))4401 {4402 com::ProgressErrorInfo info(progress);4403 PRINT_ERROR_INFO(info);4404 rc = result;4405 }4406 }4407 while (0);4408 4409 return SUCCEEDED(rc) ? 0 : 1;4410 }4411 4412 static int handleRemoveHostIF(int argc, char *argv[],4413 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)4414 {4415 if (argc != 1)4416 return errorSyntax(USAGE_REMOVEHOSTIF, "Incorrect number of parameters");4417 4418 HRESULT rc = S_OK;4419 4420 do4421 {4422 ComPtr<IHost> host;4423 CHECK_ERROR_BREAK(virtualBox, COMGETTER(Host)(host.asOutParam()));4424 4425 ComPtr<IHostNetworkInterface> hostif;4426 4427 /* first guess is that it's a UUID */4428 Guid uuid(argv[0]);4429 if (uuid.isEmpty())4430 {4431 /* not a valid UUID, search for it */4432 ComPtr<IHostNetworkInterfaceCollection> coll;4433 CHECK_ERROR_BREAK(host, COMGETTER(NetworkInterfaces)(coll.asOutParam()));4434 CHECK_ERROR_BREAK(coll, FindByName(Bstr(argv[0]), hostif.asOutParam()));4435 CHECK_ERROR_BREAK(hostif, COMGETTER(Id)(uuid.asOutParam()));4436 }4437 4438 ComPtr<IProgress> progress;4439 CHECK_ERROR_BREAK(host,4440 RemoveHostNetworkInterface(uuid,4441 hostif.asOutParam(),4442 progress.asOutParam()));4443 4444 showProgress(progress);4445 HRESULT result;4446 CHECK_ERROR_BREAK(progress, COMGETTER(ResultCode)(&result));4447 if (FAILED(result))4448 {4449 com::ProgressErrorInfo info(progress);4450 PRINT_ERROR_INFO(info);4451 rc = result;4452 }4453 }4454 while (0);4455 4456 return SUCCEEDED(rc) ? 0 : 1;4457 }4458 #endif /* RT_OS_WINDOWS */4459 4460 static int handleGetExtraData(int argc, char *argv[],4461 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)4462 {4463 HRESULT rc = S_OK;4464 4465 if (argc != 2)4466 return errorSyntax(USAGE_GETEXTRADATA, "Incorrect number of parameters");4467 4468 /* global data? */4469 if (strcmp(argv[0], "global") == 0)4470 {4471 /* enumeration? */4472 if (strcmp(argv[1], "enumerate") == 0)4473 {4474 Bstr extraDataKey;4475 4476 do4477 {4478 Bstr nextExtraDataKey;4479 Bstr nextExtraDataValue;4480 HRESULT rcEnum = virtualBox->GetNextExtraDataKey(extraDataKey, nextExtraDataKey.asOutParam(),4481 nextExtraDataValue.asOutParam());4482 extraDataKey = nextExtraDataKey;4483 4484 if (SUCCEEDED(rcEnum) && extraDataKey)4485 RTPrintf("Key: %lS, Value: %lS\n", nextExtraDataKey.raw(), nextExtraDataValue.raw());4486 } while (extraDataKey);4487 }4488 else4489 {4490 Bstr value;4491 CHECK_ERROR(virtualBox, GetExtraData(Bstr(argv[1]), value.asOutParam()));4492 if (value)4493 RTPrintf("Value: %lS\n", value.raw());4494 else4495 RTPrintf("No value set!\n");4496 }4497 }4498 else4499 {4500 ComPtr<IMachine> machine;4501 /* assume it's a UUID */4502 rc = virtualBox->GetMachine(Guid(argv[0]), machine.asOutParam());4503 if (FAILED(rc) || !machine)4504 {4505 /* must be a name */4506 CHECK_ERROR(virtualBox, FindMachine(Bstr(argv[0]), machine.asOutParam()));4507 }4508 if (machine)4509 {4510 /* enumeration? */4511 if (strcmp(argv[1], "enumerate") == 0)4512 {4513 Bstr extraDataKey;4514 4515 do4516 {4517 Bstr nextExtraDataKey;4518 Bstr nextExtraDataValue;4519 HRESULT rcEnum = machine->GetNextExtraDataKey(extraDataKey, nextExtraDataKey.asOutParam(),4520 nextExtraDataValue.asOutParam());4521 extraDataKey = nextExtraDataKey;4522 4523 if (SUCCEEDED(rcEnum) && extraDataKey)4524 {4525 RTPrintf("Key: %lS, Value: %lS\n", nextExtraDataKey.raw(), nextExtraDataValue.raw());4526 }4527 } while (extraDataKey);4528 }4529 else4530 {4531 Bstr value;4532 CHECK_ERROR(machine, GetExtraData(Bstr(argv[1]), value.asOutParam()));4533 if (value)4534 RTPrintf("Value: %lS\n", value.raw());4535 else4536 RTPrintf("No value set!\n");4537 }4538 }4539 }4540 return SUCCEEDED(rc) ? 0 : 1;4541 }4542 4543 static int handleSetExtraData(int argc, char *argv[],4544 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)4545 {4546 HRESULT rc = S_OK;4547 4548 if (argc < 2)4549 return errorSyntax(USAGE_SETEXTRADATA, "Not enough parameters");4550 4551 /* global data? */4552 if (strcmp(argv[0], "global") == 0)4553 {4554 if (argc < 3)4555 CHECK_ERROR(virtualBox, SetExtraData(Bstr(argv[1]), NULL));4556 else if (argc == 3)4557 CHECK_ERROR(virtualBox, SetExtraData(Bstr(argv[1]), Bstr(argv[2])));4558 else4559 return errorSyntax(USAGE_SETEXTRADATA, "Too many parameters");4560 }4561 else4562 {4563 ComPtr<IMachine> machine;4564 /* assume it's a UUID */4565 rc = virtualBox->GetMachine(Guid(argv[0]), machine.asOutParam());4566 if (FAILED(rc) || !machine)4567 {4568 /* must be a name */4569 CHECK_ERROR(virtualBox, FindMachine(Bstr(argv[0]), machine.asOutParam()));4570 }4571 if (machine)4572 {4573 if (argc < 3)4574 CHECK_ERROR(machine, SetExtraData(Bstr(argv[1]), NULL));4575 else if (argc == 3)4576 CHECK_ERROR(machine, SetExtraData(Bstr(argv[1]), Bstr(argv[2])));4577 else4578 return errorSyntax(USAGE_SETEXTRADATA, "Too many parameters");4579 }4580 }4581 return SUCCEEDED(rc) ? 0 : 1;4582 }4583 4584 static int handleSetProperty(int argc, char *argv[],4585 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)4586 {4587 HRESULT rc;4588 4589 /* there must be two arguments: property name and value */4590 if (argc != 2)4591 return errorSyntax(USAGE_SETPROPERTY, "Incorrect number of parameters");4592 4593 ComPtr<ISystemProperties> systemProperties;4594 virtualBox->COMGETTER(SystemProperties)(systemProperties.asOutParam());4595 4596 if (strcmp(argv[0], "hdfolder") == 0)4597 {4598 /* reset to default? */4599 if (strcmp(argv[1], "default") == 0)4600 CHECK_ERROR(systemProperties, COMSETTER(DefaultHardDiskFolder)(NULL));4601 else4602 CHECK_ERROR(systemProperties, COMSETTER(DefaultHardDiskFolder)(Bstr(argv[1])));4603 }4604 else if (strcmp(argv[0], "machinefolder") == 0)4605 {4606 /* reset to default? */4607 if (strcmp(argv[1], "default") == 0)4608 CHECK_ERROR(systemProperties, COMSETTER(DefaultMachineFolder)(NULL));4609 else4610 CHECK_ERROR(systemProperties, COMSETTER(DefaultMachineFolder)(Bstr(argv[1])));4611 }4612 else if (strcmp(argv[0], "vrdpauthlibrary") == 0)4613 {4614 /* reset to default? */4615 if (strcmp(argv[1], "default") == 0)4616 CHECK_ERROR(systemProperties, COMSETTER(RemoteDisplayAuthLibrary)(NULL));4617 else4618 CHECK_ERROR(systemProperties, COMSETTER(RemoteDisplayAuthLibrary)(Bstr(argv[1])));4619 }4620 else if (strcmp(argv[0], "websrvauthlibrary") == 0)4621 {4622 /* reset to default? */4623 if (strcmp(argv[1], "default") == 0)4624 CHECK_ERROR(systemProperties, COMSETTER(WebServiceAuthLibrary)(NULL));4625 else4626 CHECK_ERROR(systemProperties, COMSETTER(WebServiceAuthLibrary)(Bstr(argv[1])));4627 }4628 else if (strcmp(argv[0], "hwvirtexenabled") == 0)4629 {4630 if (strcmp(argv[1], "yes") == 0)4631 CHECK_ERROR(systemProperties, COMSETTER(HWVirtExEnabled)(TRUE));4632 else if (strcmp(argv[1], "no") == 0)4633 CHECK_ERROR(systemProperties, COMSETTER(HWVirtExEnabled)(FALSE));4634 else4635 return errorArgument("Invalid value '%s' for hardware virtualization extension flag", argv[1]);4636 }4637 else if (strcmp(argv[0], "loghistorycount") == 0)4638 {4639 uint32_t uVal;4640 int vrc;4641 vrc = RTStrToUInt32Ex(argv[1], NULL, 0, &uVal);4642 if (vrc != VINF_SUCCESS)4643 return errorArgument("Error parsing Log history count '%s'", argv[1]);4644 CHECK_ERROR(systemProperties, COMSETTER(LogHistoryCount)(uVal));4645 }4646 else4647 return errorSyntax(USAGE_SETPROPERTY, "Invalid parameter '%s'", argv[0]);4648 4649 return SUCCEEDED(rc) ? 0 : 1;4650 }4651 4652 static int handleUSBFilter (int argc, char *argv[],4653 ComPtr <IVirtualBox> aVirtualBox, ComPtr<ISession> aSession)4654 {4655 HRESULT rc = S_OK;4656 USBFilterCmd cmd;4657 4658 /* at least: 0: command, 1: index, 2: -target, 3: <target value> */4659 if (argc < 4)4660 return errorSyntax(USAGE_USBFILTER, "Not enough parameters");4661 4662 /* which command? */4663 cmd.mAction = USBFilterCmd::Invalid;4664 if (strcmp (argv [0], "add") == 0) cmd.mAction = USBFilterCmd::Add;4665 else if (strcmp (argv [0], "modify") == 0) cmd.mAction = USBFilterCmd::Modify;4666 else if (strcmp (argv [0], "remove") == 0) cmd.mAction = USBFilterCmd::Remove;4667 4668 if (cmd.mAction == USBFilterCmd::Invalid)4669 return errorSyntax(USAGE_USBFILTER, "Invalid parameter '%s'", argv[0]);4670 4671 /* which index? */4672 char *endptr = NULL;4673 cmd.mIndex = strtoul (argv[1], &endptr, 10);4674 if (!endptr || *endptr)4675 return errorSyntax(USAGE_USBFILTER, "Invalid index '%s'", argv[1]);4676 4677 switch (cmd.mAction)4678 {4679 case USBFilterCmd::Add:4680 case USBFilterCmd::Modify:4681 {4682 /* at least: 0: command, 1: index, 2: -target, 3: <target value>, 4: -name, 5: <name value> */4683 if (argc < 6)4684 {4685 if (cmd.mAction == USBFilterCmd::Add)4686 return errorSyntax(USAGE_USBFILTER_ADD, "Not enough parameters");4687 4688 return errorSyntax(USAGE_USBFILTER_MODIFY, "Not enough parameters");4689 }4690 4691 // set Active to true by default4692 // (assuming that the user sets up all necessary attributes4693 // at once and wants the filter to be active immediately)4694 if (cmd.mAction == USBFilterCmd::Add)4695 cmd.mFilter.mActive = true;4696 4697 for (int i = 2; i < argc; i++)4698 {4699 if (strcmp(argv [i], "-target") == 0)4700 {4701 if (argc <= i + 1 || !*argv[i+1])4702 return errorArgument("Missing argument to '%s'", argv[i]);4703 i++;4704 if (strcmp (argv [i], "global") == 0)4705 cmd.mGlobal = true;4706 else4707 {4708 /* assume it's a UUID of a machine */4709 rc = aVirtualBox->GetMachine(Guid(argv[i]), cmd.mMachine.asOutParam());4710 if (FAILED(rc) || !cmd.mMachine)4711 {4712 /* must be a name */4713 CHECK_ERROR_RET(aVirtualBox, FindMachine(Bstr(argv[i]), cmd.mMachine.asOutParam()), 1);4714 }4715 }4716 }4717 else if (strcmp(argv [i], "-name") == 0)4718 {4719 if (argc <= i + 1 || !*argv[i+1])4720 return errorArgument("Missing argument to '%s'", argv[i]);4721 i++;4722 cmd.mFilter.mName = argv [i];4723 }4724 else if (strcmp(argv [i], "-active") == 0)4725 {4726 if (argc <= i + 1)4727 return errorArgument("Missing argument to '%s'", argv[i]);4728 i++;4729 if (strcmp (argv [i], "yes") == 0)4730 cmd.mFilter.mActive = true;4731 else if (strcmp (argv [i], "no") == 0)4732 cmd.mFilter.mActive = false;4733 else4734 return errorArgument("Invalid -active argument '%s'", argv[i]);4735 }4736 else if (strcmp(argv [i], "-vendorid") == 0)4737 {4738 if (argc <= i + 1)4739 return errorArgument("Missing argument to '%s'", argv[i]);4740 i++;4741 cmd.mFilter.mVendorId = argv [i];4742 }4743 else if (strcmp(argv [i], "-productid") == 0)4744 {4745 if (argc <= i + 1)4746 return errorArgument("Missing argument to '%s'", argv[i]);4747 i++;4748 cmd.mFilter.mProductId = argv [i];4749 }4750 else if (strcmp(argv [i], "-revision") == 0)4751 {4752 if (argc <= i + 1)4753 return errorArgument("Missing argument to '%s'", argv[i]);4754 i++;4755 cmd.mFilter.mRevision = argv [i];4756 }4757 else if (strcmp(argv [i], "-manufacturer") == 0)4758 {4759 if (argc <= i + 1)4760 return errorArgument("Missing argument to '%s'", argv[i]);4761 i++;4762 cmd.mFilter.mManufacturer = argv [i];4763 }4764 else if (strcmp(argv [i], "-product") == 0)4765 {4766 if (argc <= i + 1)4767 return errorArgument("Missing argument to '%s'", argv[i]);4768 i++;4769 cmd.mFilter.mProduct = argv [i];4770 }4771 else if (strcmp(argv [i], "-remote") == 0)4772 {4773 if (argc <= i + 1)4774 return errorArgument("Missing argument to '%s'", argv[i]);4775 i++;4776 cmd.mFilter.mRemote = argv[i];4777 }4778 else if (strcmp(argv [i], "-serialnumber") == 0)4779 {4780 if (argc <= i + 1)4781 return errorArgument("Missing argument to '%s'", argv[i]);4782 i++;4783 cmd.mFilter.mSerialNumber = argv [i];4784 }4785 else if (strcmp(argv [i], "-maskedinterfaces") == 0)4786 {4787 if (argc <= i + 1)4788 return errorArgument("Missing argument to '%s'", argv[i]);4789 i++;4790 uint32_t u32;4791 rc = RTStrToUInt32Full(argv[i], 0, &u32);4792 if (RT_FAILURE(rc))4793 return errorArgument("Failed to convert the -maskedinterfaces value '%s' to a number, rc=%Rrc", argv[i], rc);4794 cmd.mFilter.mMaskedInterfaces = u32;4795 }4796 else if (strcmp(argv [i], "-action") == 0)4797 {4798 if (argc <= i + 1)4799 return errorArgument("Missing argument to '%s'", argv[i]);4800 i++;4801 if (strcmp (argv [i], "ignore") == 0)4802 cmd.mFilter.mAction = USBDeviceFilterAction_Ignore;4803 else if (strcmp (argv [i], "hold") == 0)4804 cmd.mFilter.mAction = USBDeviceFilterAction_Hold;4805 else4806 return errorArgument("Invalid USB filter action '%s'", argv[i]);4807 }4808 else4809 return errorSyntax(cmd.mAction == USBFilterCmd::Add ? USAGE_USBFILTER_ADD : USAGE_USBFILTER_MODIFY,4810 "Unknown option '%s'", argv[i]);4811 }4812 4813 if (cmd.mAction == USBFilterCmd::Add)4814 {4815 // mandatory/forbidden options4816 if ( cmd.mFilter.mName.isEmpty()4817 ||4818 ( cmd.mGlobal4819 && cmd.mFilter.mAction == USBDeviceFilterAction_Null4820 )4821 || ( !cmd.mGlobal4822 && !cmd.mMachine)4823 || ( cmd.mGlobal4824 && cmd.mFilter.mRemote)4825 )4826 {4827 return errorSyntax(USAGE_USBFILTER_ADD, "Mandatory options not supplied");4828 }4829 }4830 break;4831 }4832 4833 case USBFilterCmd::Remove:4834 {4835 /* at least: 0: command, 1: index, 2: -target, 3: <target value> */4836 if (argc < 4)4837 return errorSyntax(USAGE_USBFILTER_REMOVE, "Not enough parameters");4838 4839 for (int i = 2; i < argc; i++)4840 {4841 if (strcmp(argv [i], "-target") == 0)4842 {4843 if (argc <= i + 1 || !*argv[i+1])4844 return errorArgument("Missing argument to '%s'", argv[i]);4845 i++;4846 if (strcmp (argv [i], "global") == 0)4847 cmd.mGlobal = true;4848 else4849 {4850 /* assume it's a UUID of a machine */4851 rc = aVirtualBox->GetMachine(Guid(argv[i]), cmd.mMachine.asOutParam());4852 if (FAILED(rc) || !cmd.mMachine)4853 {4854 /* must be a name */4855 CHECK_ERROR_RET(aVirtualBox, FindMachine(Bstr(argv[i]), cmd.mMachine.asOutParam()), 1);4856 }4857 }4858 }4859 }4860 4861 // mandatory options4862 if (!cmd.mGlobal && !cmd.mMachine)4863 return errorSyntax(USAGE_USBFILTER_REMOVE, "Mandatory options not supplied");4864 4865 break;4866 }4867 4868 default: break;4869 }4870 4871 USBFilterCmd::USBFilter &f = cmd.mFilter;4872 4873 ComPtr <IHost> host;4874 ComPtr <IUSBController> ctl;4875 if (cmd.mGlobal)4876 CHECK_ERROR_RET (aVirtualBox, COMGETTER(Host) (host.asOutParam()), 1);4877 else4878 {4879 Guid uuid;4880 cmd.mMachine->COMGETTER(Id)(uuid.asOutParam());4881 /* open a session for the VM */4882 CHECK_ERROR_RET (aVirtualBox, OpenSession(aSession, uuid), 1);4883 /* get the mutable session machine */4884 aSession->COMGETTER(Machine)(cmd.mMachine.asOutParam());4885 /* and get the USB controller */4886 CHECK_ERROR_RET (cmd.mMachine, COMGETTER(USBController) (ctl.asOutParam()), 1);4887 }4888 4889 switch (cmd.mAction)4890 {4891 case USBFilterCmd::Add:4892 {4893 if (cmd.mGlobal)4894 {4895 ComPtr <IHostUSBDeviceFilter> flt;4896 CHECK_ERROR_BREAK (host, CreateUSBDeviceFilter (f.mName, flt.asOutParam()));4897 4898 if (!f.mActive.isNull())4899 CHECK_ERROR_BREAK (flt, COMSETTER(Active) (f.mActive));4900 if (!f.mVendorId.isNull())4901 CHECK_ERROR_BREAK (flt, COMSETTER(VendorId) (f.mVendorId.setNullIfEmpty()));4902 if (!f.mProductId.isNull())4903 CHECK_ERROR_BREAK (flt, COMSETTER(ProductId) (f.mProductId.setNullIfEmpty()));4904 if (!f.mRevision.isNull())4905 CHECK_ERROR_BREAK (flt, COMSETTER(Revision) (f.mRevision.setNullIfEmpty()));4906 if (!f.mManufacturer.isNull())4907 CHECK_ERROR_BREAK (flt, COMSETTER(Manufacturer) (f.mManufacturer.setNullIfEmpty()));4908 if (!f.mSerialNumber.isNull())4909 CHECK_ERROR_BREAK (flt, COMSETTER(SerialNumber) (f.mSerialNumber.setNullIfEmpty()));4910 if (!f.mMaskedInterfaces.isNull())4911 CHECK_ERROR_BREAK (flt, COMSETTER(MaskedInterfaces) (f.mMaskedInterfaces));4912 4913 if (f.mAction != USBDeviceFilterAction_Null)4914 CHECK_ERROR_BREAK (flt, COMSETTER(Action) (f.mAction));4915 4916 CHECK_ERROR_BREAK (host, InsertUSBDeviceFilter (cmd.mIndex, flt));4917 }4918 else4919 {4920 ComPtr <IUSBDeviceFilter> flt;4921 CHECK_ERROR_BREAK (ctl, CreateDeviceFilter (f.mName, flt.asOutParam()));4922 4923 if (!f.mActive.isNull())4924 CHECK_ERROR_BREAK (flt, COMSETTER(Active) (f.mActive));4925 if (!f.mVendorId.isNull())4926 CHECK_ERROR_BREAK (flt, COMSETTER(VendorId) (f.mVendorId.setNullIfEmpty()));4927 if (!f.mProductId.isNull())4928 CHECK_ERROR_BREAK (flt, COMSETTER(ProductId) (f.mProductId.setNullIfEmpty()));4929 if (!f.mRevision.isNull())4930 CHECK_ERROR_BREAK (flt, COMSETTER(Revision) (f.mRevision.setNullIfEmpty()));4931 if (!f.mManufacturer.isNull())4932 CHECK_ERROR_BREAK (flt, COMSETTER(Manufacturer) (f.mManufacturer.setNullIfEmpty()));4933 if (!f.mRemote.isNull())4934 CHECK_ERROR_BREAK (flt, COMSETTER(Remote) (f.mRemote.setNullIfEmpty()));4935 if (!f.mSerialNumber.isNull())4936 CHECK_ERROR_BREAK (flt, COMSETTER(SerialNumber) (f.mSerialNumber.setNullIfEmpty()));4937 if (!f.mMaskedInterfaces.isNull())4938 CHECK_ERROR_BREAK (flt, COMSETTER(MaskedInterfaces) (f.mMaskedInterfaces));4939 4940 CHECK_ERROR_BREAK (ctl, InsertDeviceFilter (cmd.mIndex, flt));4941 }4942 break;4943 }4944 case USBFilterCmd::Modify:4945 {4946 if (cmd.mGlobal)4947 {4948 ComPtr <IHostUSBDeviceFilterCollection> coll;4949 CHECK_ERROR_BREAK (host, COMGETTER(USBDeviceFilters) (coll.asOutParam()));4950 ComPtr <IHostUSBDeviceFilter> flt;4951 CHECK_ERROR_BREAK (coll, GetItemAt (cmd.mIndex, flt.asOutParam()));4952 4953 if (!f.mName.isNull())4954 CHECK_ERROR_BREAK (flt, COMSETTER(Name) (f.mName.setNullIfEmpty()));4955 if (!f.mActive.isNull())4956 CHECK_ERROR_BREAK (flt, COMSETTER(Active) (f.mActive));4957 if (!f.mVendorId.isNull())4958 CHECK_ERROR_BREAK (flt, COMSETTER(VendorId) (f.mVendorId.setNullIfEmpty()));4959 if (!f.mProductId.isNull())4960 CHECK_ERROR_BREAK (flt, COMSETTER(ProductId) (f.mProductId.setNullIfEmpty()));4961 if (!f.mRevision.isNull())4962 CHECK_ERROR_BREAK (flt, COMSETTER(Revision) (f.mRevision.setNullIfEmpty()));4963 if (!f.mManufacturer.isNull())4964 CHECK_ERROR_BREAK (flt, COMSETTER(Manufacturer) (f.mManufacturer.setNullIfEmpty()));4965 if (!f.mSerialNumber.isNull())4966 CHECK_ERROR_BREAK (flt, COMSETTER(SerialNumber) (f.mSerialNumber.setNullIfEmpty()));4967 if (!f.mMaskedInterfaces.isNull())4968 CHECK_ERROR_BREAK (flt, COMSETTER(MaskedInterfaces) (f.mMaskedInterfaces));4969 4970 if (f.mAction != USBDeviceFilterAction_Null)4971 CHECK_ERROR_BREAK (flt, COMSETTER(Action) (f.mAction));4972 }4973 else4974 {4975 ComPtr <IUSBDeviceFilterCollection> coll;4976 CHECK_ERROR_BREAK (ctl, COMGETTER(DeviceFilters) (coll.asOutParam()));4977 4978 ComPtr <IUSBDeviceFilter> flt;4979 CHECK_ERROR_BREAK (coll, GetItemAt (cmd.mIndex, flt.asOutParam()));4980 4981 if (!f.mName.isNull())4982 CHECK_ERROR_BREAK (flt, COMSETTER(Name) (f.mName.setNullIfEmpty()));4983 if (!f.mActive.isNull())4984 CHECK_ERROR_BREAK (flt, COMSETTER(Active) (f.mActive));4985 if (!f.mVendorId.isNull())4986 CHECK_ERROR_BREAK (flt, COMSETTER(VendorId) (f.mVendorId.setNullIfEmpty()));4987 if (!f.mProductId.isNull())4988 CHECK_ERROR_BREAK (flt, COMSETTER(ProductId) (f.mProductId.setNullIfEmpty()));4989 if (!f.mRevision.isNull())4990 CHECK_ERROR_BREAK (flt, COMSETTER(Revision) (f.mRevision.setNullIfEmpty()));4991 if (!f.mManufacturer.isNull())4992 CHECK_ERROR_BREAK (flt, COMSETTER(Manufacturer) (f.mManufacturer.setNullIfEmpty()));4993 if (!f.mRemote.isNull())4994 CHECK_ERROR_BREAK (flt, COMSETTER(Remote) (f.mRemote.setNullIfEmpty()));4995 if (!f.mSerialNumber.isNull())4996 CHECK_ERROR_BREAK (flt, COMSETTER(SerialNumber) (f.mSerialNumber.setNullIfEmpty()));4997 if (!f.mMaskedInterfaces.isNull())4998 CHECK_ERROR_BREAK (flt, COMSETTER(MaskedInterfaces) (f.mMaskedInterfaces));4999 }5000 break;5001 }5002 case USBFilterCmd::Remove:5003 {5004 if (cmd.mGlobal)5005 {5006 ComPtr <IHostUSBDeviceFilter> flt;5007 CHECK_ERROR_BREAK (host, RemoveUSBDeviceFilter (cmd.mIndex, flt.asOutParam()));5008 }5009 else5010 {5011 ComPtr <IUSBDeviceFilter> flt;5012 CHECK_ERROR_BREAK (ctl, RemoveDeviceFilter (cmd.mIndex, flt.asOutParam()));5013 }5014 break;5015 }5016 default:5017 break;5018 }5019 5020 if (cmd.mMachine)5021 {5022 /* commit and close the session */5023 CHECK_ERROR(cmd.mMachine, SaveSettings());5024 aSession->Close();5025 }5026 5027 return SUCCEEDED (rc) ? 0 : 1;5028 }5029 5030 static int handleSharedFolder (int argc, char *argv[],5031 ComPtr <IVirtualBox> aVirtualBox, ComPtr<ISession> aSession)5032 {5033 HRESULT rc;5034 5035 /* we need at least a command and target */5036 if (argc < 2)5037 return errorSyntax(USAGE_SHAREDFOLDER, "Not enough parameters");5038 5039 ComPtr<IMachine> machine;5040 /* assume it's a UUID */5041 rc = aVirtualBox->GetMachine(Guid(argv[1]), machine.asOutParam());5042 if (FAILED(rc) || !machine)5043 {5044 /* must be a name */5045 CHECK_ERROR(aVirtualBox, FindMachine(Bstr(argv[1]), machine.asOutParam()));5046 }5047 if (!machine)5048 return 1;5049 Guid uuid;5050 machine->COMGETTER(Id)(uuid.asOutParam());5051 5052 if (strcmp(argv[0], "add") == 0)5053 {5054 /* we need at least four more parameters */5055 if (argc < 5)5056 return errorSyntax(USAGE_SHAREDFOLDER_ADD, "Not enough parameters");5057 5058 char *name = NULL;5059 char *hostpath = NULL;5060 bool fTransient = false;5061 bool fWritable = true;5062 5063 for (int i = 2; i < argc; i++)5064 {5065 if (strcmp(argv[i], "-name") == 0)5066 {5067 if (argc <= i + 1 || !*argv[i+1])5068 return errorArgument("Missing argument to '%s'", argv[i]);5069 i++;5070 name = argv[i];5071 }5072 else if (strcmp(argv[i], "-hostpath") == 0)5073 {5074 if (argc <= i + 1 || !*argv[i+1])5075 return errorArgument("Missing argument to '%s'", argv[i]);5076 i++;5077 hostpath = argv[i];5078 }5079 else if (strcmp(argv[i], "-readonly") == 0)5080 {5081 fWritable = false;5082 }5083 else if (strcmp(argv[i], "-transient") == 0)5084 {5085 fTransient = true;5086 }5087 else5088 return errorSyntax(USAGE_SHAREDFOLDER_ADD, "Invalid parameter '%s'", Utf8Str(argv[i]).raw());5089 }5090 5091 if (NULL != strstr(name, " "))5092 return errorSyntax(USAGE_SHAREDFOLDER_ADD, "No spaces allowed in parameter '-name'!");5093 5094 /* required arguments */5095 if (!name || !hostpath)5096 {5097 return errorSyntax(USAGE_SHAREDFOLDER_ADD, "Parameters -name and -hostpath are required");5098 }5099 5100 if (fTransient)5101 {5102 ComPtr <IConsole> console;5103 5104 /* open an existing session for the VM */5105 CHECK_ERROR_RET(aVirtualBox, OpenExistingSession (aSession, uuid), 1);5106 /* get the session machine */5107 CHECK_ERROR_RET(aSession, COMGETTER(Machine)(machine.asOutParam()), 1);5108 /* get the session console */5109 CHECK_ERROR_RET(aSession, COMGETTER(Console)(console.asOutParam()), 1);5110 5111 CHECK_ERROR(console, CreateSharedFolder(Bstr(name), Bstr(hostpath), fWritable));5112 5113 if (console)5114 aSession->Close();5115 }5116 else5117 {5118 /* open a session for the VM */5119 CHECK_ERROR_RET (aVirtualBox, OpenSession(aSession, uuid), 1);5120 5121 /* get the mutable session machine */5122 aSession->COMGETTER(Machine)(machine.asOutParam());5123 5124 CHECK_ERROR(machine, CreateSharedFolder(Bstr(name), Bstr(hostpath), fWritable));5125 5126 if (SUCCEEDED(rc))5127 CHECK_ERROR(machine, SaveSettings());5128 5129 aSession->Close();5130 }5131 }5132 else if (strcmp(argv[0], "remove") == 0)5133 {5134 /* we need at least two more parameters */5135 if (argc < 3)5136 return errorSyntax(USAGE_SHAREDFOLDER_REMOVE, "Not enough parameters");5137 5138 char *name = NULL;5139 bool fTransient = false;5140 5141 for (int i = 2; i < argc; i++)5142 {5143 if (strcmp(argv[i], "-name") == 0)5144 {5145 if (argc <= i + 1 || !*argv[i+1])5146 return errorArgument("Missing argument to '%s'", argv[i]);5147 i++;5148 name = argv[i];5149 }5150 else if (strcmp(argv[i], "-transient") == 0)5151 {5152 fTransient = true;5153 }5154 else5155 return errorSyntax(USAGE_SHAREDFOLDER_REMOVE, "Invalid parameter '%s'", Utf8Str(argv[i]).raw());5156 }5157 5158 /* required arguments */5159 if (!name)5160 return errorSyntax(USAGE_SHAREDFOLDER_REMOVE, "Parameter -name is required");5161 5162 if (fTransient)5163 {5164 ComPtr <IConsole> console;5165 5166 /* open an existing session for the VM */5167 CHECK_ERROR_RET(aVirtualBox, OpenExistingSession (aSession, uuid), 1);5168 /* get the session machine */5169 CHECK_ERROR_RET(aSession, COMGETTER(Machine)(machine.asOutParam()), 1);5170 /* get the session console */5171 CHECK_ERROR_RET(aSession, COMGETTER(Console)(console.asOutParam()), 1);5172 5173 CHECK_ERROR(console, RemoveSharedFolder(Bstr(name)));5174 5175 if (console)5176 aSession->Close();5177 }5178 else5179 {5180 /* open a session for the VM */5181 CHECK_ERROR_RET (aVirtualBox, OpenSession(aSession, uuid), 1);5182 5183 /* get the mutable session machine */5184 aSession->COMGETTER(Machine)(machine.asOutParam());5185 5186 CHECK_ERROR(machine, RemoveSharedFolder(Bstr(name)));5187 5188 /* commit and close the session */5189 CHECK_ERROR(machine, SaveSettings());5190 aSession->Close();5191 }5192 }5193 else5194 return errorSyntax(USAGE_SETPROPERTY, "Invalid parameter '%s'", Utf8Str(argv[0]).raw());5195 5196 return 0;5197 }5198 5199 static int handleVMStatistics(int argc, char *argv[],5200 ComPtr<IVirtualBox> aVirtualBox, ComPtr<ISession> aSession)5201 {5202 HRESULT rc;5203 5204 /* at least one option: the UUID or name of the VM */5205 if (argc < 1)5206 return errorSyntax(USAGE_VM_STATISTICS, "Incorrect number of parameters");5207 5208 /* try to find the given machine */5209 ComPtr <IMachine> machine;5210 Guid uuid (argv[0]);5211 if (!uuid.isEmpty())5212 CHECK_ERROR(aVirtualBox, GetMachine(uuid, machine.asOutParam()));5213 else5214 {5215 CHECK_ERROR(aVirtualBox, FindMachine(Bstr(argv[0]), machine.asOutParam()));5216 if (SUCCEEDED (rc))5217 machine->COMGETTER(Id)(uuid.asOutParam());5218 }5219 if (FAILED(rc))5220 return 1;5221 5222 /* parse arguments. */5223 bool fReset = false;5224 bool fWithDescriptions = false;5225 const char *pszPattern = NULL; /* all */5226 for (int i = 1; i < argc; i++)5227 {5228 if (!strcmp(argv[i], "-pattern"))5229 {5230 if (pszPattern)5231 return errorSyntax(USAGE_VM_STATISTICS, "Multiple -patterns options is not permitted");5232 if (i + 1 >= argc)5233 return errorArgument("Missing argument to '%s'", argv[i]);5234 pszPattern = argv[++i];5235 }5236 else if (!strcmp(argv[i], "-descriptions"))5237 fWithDescriptions = true;5238 /* add: -file <filename> and -formatted */5239 else if (!strcmp(argv[i], "-reset"))5240 fReset = true;5241 else5242 return errorSyntax(USAGE_VM_STATISTICS, "Unknown option '%s'", argv[i]);5243 }5244 if (fReset && fWithDescriptions)5245 return errorSyntax(USAGE_VM_STATISTICS, "The -reset and -descriptions options does not mix");5246 5247 5248 /* open an existing session for the VM. */5249 CHECK_ERROR(aVirtualBox, OpenExistingSession(aSession, uuid));5250 if (SUCCEEDED(rc))5251 {5252 /* get the session console. */5253 ComPtr <IConsole> console;5254 CHECK_ERROR(aSession, COMGETTER(Console)(console.asOutParam()));5255 if (SUCCEEDED(rc))5256 {5257 /* get the machine debugger. */5258 ComPtr <IMachineDebugger> debugger;5259 CHECK_ERROR(console, COMGETTER(Debugger)(debugger.asOutParam()));5260 if (SUCCEEDED(rc))5261 {5262 if (fReset)5263 CHECK_ERROR(debugger, ResetStats(Bstr(pszPattern).raw()));5264 else5265 {5266 Bstr stats;5267 CHECK_ERROR(debugger, GetStats(Bstr(pszPattern).raw(), fWithDescriptions, stats.asOutParam()));5268 if (SUCCEEDED(rc))5269 {5270 /* if (fFormatted)5271 { big mess }5272 else5273 */5274 RTPrintf("%ls\n", stats.raw());5275 }5276 }5277 }5278 aSession->Close();5279 }5280 }5281 5282 return SUCCEEDED(rc) ? 0 : 1;5283 }5284 66 5285 67 static char *toBaseMetricNames(const char *metricList) … … 5765 547 } 5766 548 5767 staticint handleMetrics(int argc, char *argv[],5768 549 int handleMetrics(int argc, char *argv[], 550 ComPtr<IVirtualBox> aVirtualBox, ComPtr<ISession> aSession) 5769 551 { 5770 552 int rc; … … 5790 572 return rc; 5791 573 } 5792 #endif /* !VBOX_ONLY_DOCS */ 5793 5794 enum ConvertSettings 5795 { 5796 ConvertSettings_No = 0, 5797 ConvertSettings_Yes = 1, 5798 ConvertSettings_Backup = 2, 5799 ConvertSettings_Ignore = 3, 5800 }; 5801 5802 #ifndef VBOX_ONLY_DOCS 5803 /** 5804 * Checks if any of the settings files were auto-converted and informs the 5805 * user if so. 5806 * 5807 * @return @false if the program should terminate and @true otherwise. 5808 */ 5809 static bool checkForAutoConvertedSettings (ComPtr<IVirtualBox> virtualBox, 5810 ComPtr<ISession> session, 5811 ConvertSettings fConvertSettings) 5812 { 5813 /* return early if nothing to do */ 5814 if (fConvertSettings == ConvertSettings_Ignore) 5815 return true; 5816 5817 HRESULT rc; 5818 5819 do 5820 { 5821 Bstr formatVersion; 5822 CHECK_RC_BREAK (virtualBox-> 5823 COMGETTER(SettingsFormatVersion) (formatVersion.asOutParam())); 5824 5825 bool isGlobalConverted = false; 5826 std::list <ComPtr <IMachine> > cvtMachines; 5827 std::list <Utf8Str> fileList; 5828 Bstr version; 5829 Bstr filePath; 5830 5831 com::SafeIfaceArray <IMachine> machines; 5832 CHECK_RC_BREAK (virtualBox-> 5833 COMGETTER(Machines2) (ComSafeArrayAsOutParam (machines))); 5834 5835 for (size_t i = 0; i < machines.size(); ++ i) 5836 { 5837 BOOL accessible; 5838 CHECK_RC_BREAK (machines [i]-> 5839 COMGETTER(Accessible) (&accessible)); 5840 if (!accessible) 5841 continue; 5842 5843 CHECK_RC_BREAK (machines [i]-> 5844 COMGETTER(SettingsFileVersion) (version.asOutParam())); 5845 5846 if (version != formatVersion) 5847 { 5848 cvtMachines.push_back (machines [i]); 5849 Bstr filePath; 5850 CHECK_RC_BREAK (machines [i]-> 5851 COMGETTER(SettingsFilePath) (filePath.asOutParam())); 5852 fileList.push_back (Utf8StrFmt ("%ls (%ls)", filePath.raw(), 5853 version.raw())); 5854 } 5855 } 5856 5857 CHECK_RC_BREAK (rc); 5858 5859 CHECK_RC_BREAK (virtualBox-> 5860 COMGETTER(SettingsFileVersion) (version.asOutParam())); 5861 if (version != formatVersion) 5862 { 5863 isGlobalConverted = true; 5864 CHECK_RC_BREAK (virtualBox-> 5865 COMGETTER(SettingsFilePath) (filePath.asOutParam())); 5866 fileList.push_back (Utf8StrFmt ("%ls (%ls)", filePath.raw(), 5867 version.raw())); 5868 } 5869 5870 if (fileList.size() > 0) 5871 { 5872 switch (fConvertSettings) 5873 { 5874 case ConvertSettings_No: 5875 { 5876 RTPrintf ( 5877 "WARNING! The following VirtualBox settings files have been automatically\n" 5878 "converted to the new settings file format version '%ls':\n" 5879 "\n", 5880 formatVersion.raw()); 5881 5882 for (std::list <Utf8Str>::const_iterator f = fileList.begin(); 5883 f != fileList.end(); ++ f) 5884 RTPrintf (" %S\n", (*f).raw()); 5885 RTPrintf ( 5886 "\n" 5887 "The current command was aborted to prevent overwriting the above settings\n" 5888 "files with the results of the auto-conversion without your permission.\n" 5889 "Please put one of the following command line switches to the beginning of\n" 5890 "the VBoxManage command line and repeat the command:\n" 5891 "\n" 5892 " -convertSettings - to save all auto-converted files (it will not\n" 5893 " be possible to use these settings files with an\n" 5894 " older version of VirtualBox in the future);\n" 5895 " -convertSettingsBackup - to create backup copies of the settings files in\n" 5896 " the old format before saving them in the new format;\n" 5897 " -convertSettingsIgnore - to not save the auto-converted settings files.\n" 5898 "\n" 5899 "Note that if you use -convertSettingsIgnore, the auto-converted settings files\n" 5900 "will be implicitly saved in the new format anyway once you change a setting or\n" 5901 "start a virtual machine, but NO backup copies will be created in this case.\n"); 5902 return false; 5903 } 5904 case ConvertSettings_Yes: 5905 case ConvertSettings_Backup: 5906 { 5907 break; 5908 } 5909 default: 5910 AssertFailedReturn (false); 5911 } 5912 5913 for (std::list <ComPtr <IMachine> >::const_iterator m = cvtMachines.begin(); 5914 m != cvtMachines.end(); ++ m) 5915 { 5916 Guid id; 5917 CHECK_RC_BREAK ((*m)->COMGETTER(Id) (id.asOutParam())); 5918 5919 /* open a session for the VM */ 5920 CHECK_ERROR_BREAK (virtualBox, OpenSession (session, id)); 5921 5922 ComPtr <IMachine> sm; 5923 CHECK_RC_BREAK (session->COMGETTER(Machine) (sm.asOutParam())); 5924 5925 Bstr bakFileName; 5926 if (fConvertSettings == ConvertSettings_Backup) 5927 CHECK_ERROR (sm, SaveSettingsWithBackup (bakFileName.asOutParam())); 5928 else 5929 CHECK_ERROR (sm, SaveSettings()); 5930 5931 session->Close(); 5932 5933 CHECK_RC_BREAK (rc); 5934 } 5935 5936 CHECK_RC_BREAK (rc); 5937 5938 if (isGlobalConverted) 5939 { 5940 Bstr bakFileName; 5941 if (fConvertSettings == ConvertSettings_Backup) 5942 CHECK_ERROR (virtualBox, SaveSettingsWithBackup (bakFileName.asOutParam())); 5943 else 5944 CHECK_ERROR (virtualBox, SaveSettings()); 5945 } 5946 5947 CHECK_RC_BREAK (rc); 5948 } 5949 } 5950 while (0); 5951 5952 return SUCCEEDED (rc); 5953 } 5954 #endif /* !VBOX_ONLY_DOCS */ 5955 5956 // main 5957 /////////////////////////////////////////////////////////////////////////////// 5958 5959 int main(int argc, char *argv[]) 5960 { 5961 /* 5962 * Before we do anything, init the runtime without loading 5963 * the support driver. 5964 */ 5965 RTR3Init(); 5966 5967 bool fShowLogo = true; 5968 int iCmd = 1; 5969 int iCmdArg; 5970 5971 ConvertSettings fConvertSettings = ConvertSettings_No; 5972 5973 /* global options */ 5974 for (int i = 1; i < argc || argc <= iCmd; i++) 5975 { 5976 if ( argc <= iCmd 5977 || (strcmp(argv[i], "help") == 0) 5978 || (strcmp(argv[i], "-?") == 0) 5979 || (strcmp(argv[i], "-h") == 0) 5980 || (strcmp(argv[i], "-help") == 0) 5981 || (strcmp(argv[i], "--help") == 0)) 5982 { 5983 showLogo(); 5984 printUsage(USAGE_ALL); 5985 return 0; 5986 } 5987 else if ( strcmp(argv[i], "-v") == 0 5988 || strcmp(argv[i], "-version") == 0 5989 || strcmp(argv[i], "-Version") == 0 5990 || strcmp(argv[i], "--version") == 0) 5991 { 5992 /* Print version number, and do nothing else. */ 5993 RTPrintf("%sr%d\n", VBOX_VERSION_STRING, VBoxSVNRev ()); 5994 exit(0); 5995 } 5996 else if (strcmp(argv[i], "-dumpopts") == 0) 5997 { 5998 /* Special option to dump really all commands, 5999 * even the ones not understood on this platform. */ 6000 printUsage(USAGE_DUMPOPTS); 6001 return 0; 6002 } 6003 else if (strcmp(argv[i], "-nologo") == 0) 6004 { 6005 /* suppress the logo */ 6006 fShowLogo = false; 6007 iCmd++; 6008 } 6009 else if (strcmp(argv[i], "-convertSettings") == 0) 6010 { 6011 fConvertSettings = ConvertSettings_Yes; 6012 iCmd++; 6013 } 6014 else if (strcmp(argv[i], "-convertSettingsBackup") == 0) 6015 { 6016 fConvertSettings = ConvertSettings_Backup; 6017 iCmd++; 6018 } 6019 else if (strcmp(argv[i], "-convertSettingsIgnore") == 0) 6020 { 6021 fConvertSettings = ConvertSettings_Ignore; 6022 iCmd++; 6023 } 6024 else 6025 { 6026 break; 6027 } 6028 } 6029 6030 iCmdArg = iCmd + 1; 6031 6032 if (fShowLogo) 6033 showLogo(); 6034 6035 6036 #ifdef VBOX_ONLY_DOCS 6037 int rc = 0; 6038 #else /* !VBOX_ONLY_DOCS */ 6039 HRESULT rc = 0; 6040 6041 CHECK_RC_RET (com::Initialize()); 6042 6043 /* 6044 * The input is in the host OS'es codepage (NT guarantees ACP). 6045 * For VBox we use UTF-8 and convert to UCS-2 when calling (XP)COM APIs. 6046 * For simplicity, just convert the argv[] array here. 6047 */ 6048 for (int i = iCmdArg; i < argc; i++) 6049 { 6050 char *converted; 6051 RTStrCurrentCPToUtf8(&converted, argv[i]); 6052 argv[i] = converted; 6053 } 6054 6055 do 6056 { 6057 // scopes all the stuff till shutdown 6058 //////////////////////////////////////////////////////////////////////////// 6059 6060 /* convertdd: does not need a VirtualBox instantiation) */ 6061 if (argc >= iCmdArg && (strcmp(argv[iCmd], "convertdd") == 0)) 6062 { 6063 rc = handleConvertDDImage(argc - iCmdArg, argv + iCmdArg); 6064 break; 6065 } 6066 6067 ComPtr <IVirtualBox> virtualBox; 6068 ComPtr <ISession> session; 6069 6070 rc = virtualBox.createLocalObject (CLSID_VirtualBox); 6071 if (FAILED(rc)) 6072 { 6073 RTPrintf ("[!] Failed to create the VirtualBox object!\n"); 6074 PRINT_RC_MESSAGE (rc); 6075 6076 com::ErrorInfo info; 6077 if (!info.isFullAvailable() && !info.isBasicAvailable()) 6078 RTPrintf ("[!] Most likely, the VirtualBox COM server is not running " 6079 "or failed to start.\n"); 6080 else 6081 PRINT_ERROR_INFO (info); 6082 break; 6083 } 6084 6085 CHECK_RC_BREAK (session.createInprocObject (CLSID_Session)); 6086 6087 /* create the event queue 6088 * (here it is necessary only to process remaining XPCOM/IPC events 6089 * after the session is closed) */ 6090 6091 #ifdef USE_XPCOM_QUEUE 6092 NS_GetMainEventQ(getter_AddRefs(g_pEventQ)); 6093 #endif 6094 6095 if (!checkForAutoConvertedSettings (virtualBox, session, fConvertSettings)) 6096 break; 6097 6098 /* 6099 * All registered command handlers 6100 */ 6101 struct 6102 { 6103 const char *command; 6104 PFNHANDLER handler; 6105 } commandHandlers[] = 6106 { 6107 { "internalcommands", handleInternalCommands }, 6108 { "list", handleList }, 6109 { "showvminfo", handleShowVMInfo }, 6110 { "registervm", handleRegisterVM }, 6111 { "unregistervm", handleUnregisterVM }, 6112 { "createhd", handleCreateHardDisk }, 6113 { "createvdi", handleCreateHardDisk }, /* backward compatiblity */ 6114 { "modifyhd", handleModifyHardDisk }, 6115 { "modifyvdi", handleModifyHardDisk }, /* backward compatiblity */ 6116 { "addiscsidisk", handleAddiSCSIDisk }, 6117 { "createvm", handleCreateVM }, 6118 { "modifyvm", handleModifyVM }, 6119 { "clonehd", handleCloneHardDisk }, 6120 { "clonevdi", handleCloneHardDisk }, /* backward compatiblity */ 6121 { "startvm", handleStartVM }, 6122 { "controlvm", handleControlVM }, 6123 { "discardstate", handleDiscardState }, 6124 { "adoptstate", handleAdoptdState }, 6125 { "snapshot", handleSnapshot }, 6126 { "openmedium", handleOpenMedium }, 6127 { "registerimage", handleOpenMedium }, /* backward compatiblity */ 6128 { "closemedium", handleCloseMedium }, 6129 { "unregisterimage", handleCloseMedium }, /* backward compatiblity */ 6130 { "showhdinfo", handleShowHardDiskInfo }, 6131 { "showvdiinfo", handleShowHardDiskInfo }, /* backward compatiblity */ 6132 #ifdef RT_OS_WINDOWS 6133 { "createhostif", handleCreateHostIF }, 6134 { "removehostif", handleRemoveHostIF }, 6135 #endif 6136 { "getextradata", handleGetExtraData }, 6137 { "setextradata", handleSetExtraData }, 6138 { "setproperty", handleSetProperty }, 6139 { "usbfilter", handleUSBFilter }, 6140 { "sharedfolder", handleSharedFolder }, 6141 { "vmstatistics", handleVMStatistics }, 6142 #ifdef VBOX_WITH_GUEST_PROPS 6143 { "guestproperty", handleGuestProperty }, 6144 #endif /* VBOX_WITH_GUEST_PROPS defined */ 6145 { "metrics", handleMetrics }, 6146 { NULL, NULL } 6147 }; 6148 6149 int commandIndex; 6150 for (commandIndex = 0; commandHandlers[commandIndex].command != NULL; commandIndex++) 6151 { 6152 if (strcmp(commandHandlers[commandIndex].command, argv[iCmd]) == 0) 6153 { 6154 rc = commandHandlers[commandIndex].handler(argc - iCmdArg, &argv[iCmdArg], virtualBox, session); 6155 break; 6156 } 6157 } 6158 if (!commandHandlers[commandIndex].command) 6159 { 6160 rc = errorSyntax(USAGE_ALL, "Invalid command '%s'", Utf8Str(argv[iCmd]).raw()); 6161 } 6162 6163 /* Although all handlers should always close the session if they open it, 6164 * we do it here just in case if some of the handlers contains a bug -- 6165 * leaving the direct session not closed will turn the machine state to 6166 * Aborted which may have unwanted side effects like killing the saved 6167 * state file (if the machine was in the Saved state before). */ 6168 session->Close(); 6169 6170 #ifdef USE_XPCOM_QUEUE 6171 g_pEventQ->ProcessPendingEvents(); 6172 #endif 6173 6174 // end "all-stuff" scope 6175 //////////////////////////////////////////////////////////////////////////// 6176 } 6177 while (0); 6178 6179 com::Shutdown(); 6180 #endif /* !VBOX_ONLY_DOCS */ 6181 6182 /* 6183 * Free converted argument vector 6184 */ 6185 for (int i = iCmdArg; i < argc; i++) 6186 RTStrFree(argv[i]); 6187 6188 return rc != 0; 6189 } 574 575 #endif /* VBOX_ONLY_DOCS */ 576
Note:
See TracChangeset
for help on using the changeset viewer.