VirtualBox

Changeset 14646 in vbox for trunk/src


Ignore:
Timestamp:
Nov 26, 2008 2:30:34 PM (16 years ago)
Author:
vboxsync
Message:

Frontends/VBoxManage: split off metrics command to reduce chance of compiler screwup.

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

Legend:

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

    r14612 r14646  
    4444        VBoxManage.cpp \
    4545        VBoxManageInfo.cpp \
     46        VBoxManageMetrics.cpp \
    4647        VBoxManageList.cpp \
    4748        VBoxInternalManage.cpp \
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManage.cpp

    r14621 r14646  
    52885288    return SUCCEEDED(rc) ? 0 : 1;
    52895289}
    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         else
    5310             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     else
    5340     {
    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         else
    5358         {
    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             else
    5367             {
    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     else
    5424     {
    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 setup
    5482  */
    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         else
    5515             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 query
    5539  */
    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             else
    5588                 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_WINDOWS
    5619 /**
    5620  * Handler routine for catching Ctrl-C, Ctrl-Break and closing of
    5621  * 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  * collect
    5647  */
    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         else
    5682             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_WINDOWS
    5712     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' seconds
    5721         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                 else
    5753                     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_WINDOWS
    5762     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     else
    5789         return errorSyntax(USAGE_METRICS, "Invalid subcommand '%s'", argv[0]);
    5790 
    5791     return rc;
    5792 }
    57935290#endif /* !VBOX_ONLY_DOCS */
    57945291
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManage.h

    r14612 r14646  
    141141               ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session);
    142142
     143/* VBoxManageMetrics.cpp */
     144int handleMetrics(int argc, char *argv[],
     145                  ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session);
     146
    143147/* VBoxManageVD.cpp */
    144148/* VBoxManageUSB.cpp */
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManageInfo.cpp

    r14613 r14646  
    22/** @file
    33 * VBoxManage - VirtualBox's command-line interface.
     4 * Information dumping code.
    45 */
    56
    67/*
    7  * Copyright (C) 2006-2007 Sun Microsystems, Inc.
     8 * Copyright (C) 2006-2008 Sun Microsystems, Inc.
    89 *
    910 * This file is part of VirtualBox Open Source Edition (OSE), as
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManageMetrics.cpp

    r14562 r14646  
    22/** @file
    33 * VBoxManage - VirtualBox's command-line interface.
     4 * Metrics handling code.
    45 */
    56
    67/*
    7  * Copyright (C) 2006-2007 Sun Microsystems, Inc.
     8 * Copyright (C) 2006-2008 Sun Microsystems, Inc.
    89 *
    910 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    2021 */
    2122
     23#ifndef VBOX_ONLY_DOCS
    2224
    2325/*******************************************************************************
    2426*   Header Files                                                               *
    2527*******************************************************************************/
    26 #ifndef VBOX_ONLY_DOCS
    2728#include <VBox/com/com.h>
    2829#include <VBox/com/string.h>
     
    3940#include <vector>
    4041#include <list>
    41 #endif /* !VBOX_ONLY_DOCS */
    4242
    4343#include <iprt/runtime.h>
     
    5858
    5959#include "VBoxManage.h"
    60 
    61 #ifndef VBOX_ONLY_DOCS
    6260using namespace com;
    6361
    64 /* missing XPCOM <-> COM wrappers */
    65 #ifndef STDMETHOD_
    66 # define STDMETHOD_(ret, meth) NS_IMETHOD_(ret) meth
    67 #endif
    68 #ifndef NS_GET_IID
    69 # define NS_GET_IID(I) IID_##I
    70 #endif
    71 #ifndef RT_OS_WINDOWS
    72 #define IUnknown nsISupports
    73 #endif
    74 
    75 /** command handler type */
    76 typedef DECLCALLBACK(int) FNHANDLER(int argc, char *argv[], ComPtr<IVirtualBox> aVirtualBox, ComPtr<ISession> aSession);
    77 typedef FNHANDLER *PFNHANDLER;
    78 
    79 #ifdef USE_XPCOM_QUEUE
    80 /** A pointer to the event queue, set by main() before calling any handlers. */
    81 nsCOMPtr<nsIEventQueue> g_pEventQ;
    82 #endif
    83 
    84 /**
    85  * Quick IUSBDevice implementation for detaching / attaching
    86  * devices to the USB Controller.
    87  */
    88 class MyUSBDevice : public IUSBDevice
    89 {
    90 public:
    91     // public initializer/uninitializer for internal purposes only
    92     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         else
    119             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 // types
    152 ///////////////////////////////////////////////////////////////////////////////
    153 
    154 template <typename T>
    155 class Nullable
    156 {
    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 USBFilterCmd
    183 {
    184     struct USBFilter
    185     {
    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 */
    21662
    21763// funcs
    21864///////////////////////////////////////////////////////////////////////////////
    21965
    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_LINUX
    238     bool fLinux = true;
    239 #else
    240     bool fLinux = false;
    241 #endif
    242 #ifdef RT_OS_WINDOWS
    243     bool fWin = true;
    244 #else
    245     bool fWin = false;
    246 #endif
    247 #ifdef RT_OS_SOLARIS
    248     bool fSolaris = true;
    249 #else
    250     bool fSolaris = false;
    251 #endif
    252 #ifdef RT_OS_DARWIN
    253     bool fDarwin = true;
    254 #else
    255     bool fDarwin = false;
    256 #endif
    257 #ifdef VBOX_WITH_VRDP
    258     bool fVRDP = true;
    259 #else
    260     bool fVRDP = false;
    261 #endif
    262 
    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_AHCI
    355                  "                            [-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 #endif
    360                  "                            [-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_E1000
    367                                                                               "|82540EM|82543GC"
    368 #endif
    369                  "]\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_BALLOONING
    384                  "                            [-guestmemoryballoon <balloonsize>]\n"
    385 #endif
    386                  "                            [-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_WINMM
    397             RTPrintf(                        "|winmm|dsound");
    398 #else
    399             RTPrintf(                        "|dsound");
    400 #endif
    401         }
    402         if (fSolaris)
    403         {
    404             RTPrintf(                        "|solaudio");
    405         }
    406         if (fLinux)
    407         {
    408             RTPrintf(                        "|oss"
    409 #ifdef VBOX_WITH_ALSA
    410                                              "|alsa"
    411 #endif
    412 #ifdef VBOX_WITH_PULSE
    413                                              "|pulse"
    414 #endif
    415                                              );
    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 backend
    513         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_PROPS
    660     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 suppressed
    691 #ifndef VBOX_ONLY_DOCS
    692     if (g_fInternalMode)
    693         printUsageInternal(u64Cmd);
    694     else
    695         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_DOCS
    717 /**
    718  * Print out progress on the console
    719  */
    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(&currentPercent));
    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         else
    760             RTPrintf("FAILED\n");
    761     }
    762     else
    763         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         else
    870             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 successfully
    884          * 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         else
    894         {
    895             CHECK_ERROR(hardDisk, CreateDynamicStorage(sizeMB, progress.asOutParam()));
    896         }
    897         if (SUCCEEDED(rc) && progress)
    898         {
    899             if (fStatic)
    900                 showProgress(progress);
    901             else
    902                 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                     else
    912                         RTPrintf("Error: failed to create hard disk. No error message available!\n");
    913                 }
    914                 else
    915                 {
    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             else
    1014             {
    1015                 return errorArgument("Invalid hard disk type '%s' specified", Utf8Str(type).raw());
    1016             }
    1017         }
    1018         else
    1019             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     else
    1053         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 1
    1062     RTPrintf("Error: Clone hard disk operation is temporarily unavailable!\n");
    1063     return 1;
    1064 #else
    1065     /// @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                 else
    1097                 {
    1098                     RTPrintf("Error: failed to clone disk image. No error message available!\n");
    1099                 }
    1100             }
    1101         }
    1102     }
    1103     return SUCCEEDED(rc) ? 0 : 1;
    1104 #endif
    1105 }
    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 #else
    1120     const bool fReadFromStdIn = false;
    1121 #endif
    1122 
    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     else
    1135         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     else
    1147         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                 else
    1186                     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         else
    1199             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 1
    1210     RTPrintf("Error: Create iSCSI hard disk operation is temporarily unavailable!\n");
    1211     return 1;
    1212 #else
    1213     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             else
    1266             {
    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         else
    1303             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 #endif
    1340 }
    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         else
    1389             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     do
    1398     {
    1399         ComPtr<IMachine> machine;
    1400 
    1401         if (!settingsFile)
    1402             CHECK_ERROR_BREAK(virtualBox,
    1403                 CreateMachine(baseFolder, name, Guid(id), machine.asOutParam()));
    1404         else
    1405             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 >= 1
    1442         &&  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_VRDP
    1482     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 #endif
    1489     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 checked
    1499      * 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_LINUX
    1527     std::vector <char *> tapsetup (NetworkAdapterCount, 0);
    1528     std::vector <char *> tapterm (NetworkAdapterCount, 0);
    1529 #endif
    1530     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             else
    1702                 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             else
    1872             {
    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_LINUX
    1885         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_VRDP
    1917         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             else
    1932                 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             else
    1973                 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             else
    1985                 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             else
    2005             {
    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_WINDOWS
    2011                     if (strncmp(argv[i], "\\\\.\\pipe\\", 9))
    2012                         return errorArgument("Uart pipe must start with \\\\.\\pipe\\");
    2013 #endif
    2014                 }
    2015                 else
    2016                 {
    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             else
    2037             {
    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_BALLOONING
    2054         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 #endif
    2067         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             else
    2089                 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         else
    2135             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     else
    2146     {
    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     do
    2158     {
    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             else
    2176             {
    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             else
    2197             {
    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             else
    2214             {
    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             else
    2235             {
    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             else
    2252             {
    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             else
    2269             {
    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             else
    2286             {
    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             else
    2307             {
    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             else
    2324             {
    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             else
    2341             {
    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             else
    2364             {
    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             else
    2387             {
    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             else
    2405             {
    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                 else
    2426                     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             else
    2438             {
    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                 else
    2459                     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             else
    2471             {
    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                 else
    2492                     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             else
    2538             {
    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             else
    2583             {
    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             else
    2602             {
    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                 else
    2629                 {
    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_WINDOWS
    2675 #ifdef VBOX_WITH_WINMM
    2676                 else if (strcmp(audio, "winmm") == 0)
    2677                 {
    2678                     CHECK_ERROR(audioAdapter, COMSETTER(AudioDriver)(AudioDriverType_WinMM));
    2679                     CHECK_ERROR(audioAdapter, COMSETTER(Enabled)(true));
    2680                 }
    2681 #endif
    2682                 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_LINUX
    2689                 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_ALSA
    2695                 else if (strcmp(audio, "alsa") == 0)
    2696                 {
    2697                     CHECK_ERROR(audioAdapter, COMSETTER(AudioDriver)(AudioDriverType_ALSA));
    2698                     CHECK_ERROR(audioAdapter, COMSETTER(Enabled)(true));
    2699                 }
    2700 # endif
    2701 # ifdef VBOX_WITH_PULSE
    2702                 else if (strcmp(audio, "pulse") == 0)
    2703                 {
    2704                     CHECK_ERROR(audioAdapter, COMSETTER(AudioDriver)(AudioDriverType_Pulse));
    2705                     CHECK_ERROR(audioAdapter, COMSETTER(Enabled)(true));
    2706                 }
    2707 # endif
    2708 #endif /* !RT_OS_LINUX */
    2709 #ifdef RT_OS_SOLARIS
    2710                 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_DARWIN
    2718                 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                 else
    2726                 {
    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                 else
    2739                 {
    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             else
    2770             {
    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                 else
    2812                 {
    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_E1000
    2831                 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 #endif
    2840                 else
    2841                 {
    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                 else
    2857                 {
    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                 else
    2890                 {
    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                 else
    2909                 {
    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                 else
    2931                 {
    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                 else
    2945                 {
    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_LINUX
    2955             /* 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                 else
    2964                 {
    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                 else
    2978                 {
    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                 else
    3003                 {
    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                 else
    3016                 {
    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                     else
    3028                     {
    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_VRDP
    3039         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                     else
    3057                     {
    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                     else
    3086                     {
    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                     else
    3103                     {
    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                     else
    3120                     {
    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/disable
    3132          */
    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/disable
    3144          */
    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             else
    3162             {
    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/disable
    3175          */
    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                 else
    3195                 {
    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                     else
    3216                         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             else
    3296                 return errorArgument("Invalid session type argument '%s'", argv[2]);
    3297         }
    3298 
    3299         Bstr env;
    3300 #ifdef RT_OS_LINUX
    3301         /* 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 #endif
    3308         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         else
    3328         {
    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     else
    3355     {
    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     do
    3367     {
    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                 else
    3408                 {
    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                 else
    3464                 {
    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                 else
    3525                 {
    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 address
    3548                 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                 else
    3559                 {
    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             else
    3571             {
    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             else
    3655             {
    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             else
    3716             {
    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_BALLOONING
    3742         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 #endif
    3768         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         else
    3794         {
    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         do
    3825         {
    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             do
    3831             {
    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         do
    3864         {
    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             do
    3870             {
    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     do
    3908     {
    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                 else
    3947                     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             else
    3969             {
    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                 else
    3987                     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             else
    4011             {
    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                 else
    4023                     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             else
    4043             {
    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                 else
    4051                 {
    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                 else
    4083                 {
    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             else
    4110             {
    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         else
    4121         {
    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     do
    4164     {
    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 parents
    4173         /// @todo NEWMEDIA print the full state value
    4174         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 too
    4237             /// @todo NEWMEDIA also list children and say 'differencing' for
    4238             /// 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     else
    4310         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     else
    4341     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     else
    4356     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     else
    4371         return errorSyntax(USAGE_UNREGISTERIMAGE, "Invalid parameter '%s'", Utf8Str(argv[1]).raw());
    4372 
    4373     return SUCCEEDED(rc) ? 0 : 1;
    4374 }
    4375 
    4376 #ifdef RT_OS_WINDOWS
    4377 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     do
    4386     {
    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     do
    4421     {
    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             do
    4477             {
    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         else
    4489         {
    4490             Bstr value;
    4491             CHECK_ERROR(virtualBox, GetExtraData(Bstr(argv[1]), value.asOutParam()));
    4492             if (value)
    4493                 RTPrintf("Value: %lS\n", value.raw());
    4494             else
    4495                 RTPrintf("No value set!\n");
    4496         }
    4497     }
    4498     else
    4499     {
    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                 do
    4516                 {
    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             else
    4530             {
    4531                 Bstr value;
    4532                 CHECK_ERROR(machine, GetExtraData(Bstr(argv[1]), value.asOutParam()));
    4533                 if (value)
    4534                     RTPrintf("Value: %lS\n", value.raw());
    4535                 else
    4536                     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         else
    4559             return errorSyntax(USAGE_SETEXTRADATA, "Too many parameters");
    4560     }
    4561     else
    4562     {
    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             else
    4578                 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         else
    4602             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         else
    4610             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         else
    4618             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         else
    4626             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         else
    4635             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     else
    4647         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 default
    4692             // (assuming that the user sets up all necessary attributes
    4693             // 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                     else
    4707                     {
    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                     else
    4734                         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                     else
    4806                         return errorArgument("Invalid USB filter action '%s'", argv[i]);
    4807                 }
    4808                 else
    4809                     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 options
    4816                 if (   cmd.mFilter.mName.isEmpty()
    4817                     ||
    4818                        (   cmd.mGlobal
    4819                         && cmd.mFilter.mAction == USBDeviceFilterAction_Null
    4820                        )
    4821                     || (   !cmd.mGlobal
    4822                         && !cmd.mMachine)
    4823                     || (   cmd.mGlobal
    4824                         && 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                     else
    4849                     {
    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 options
    4862             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     else
    4878     {
    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             else
    4919             {
    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             else
    4974             {
    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             else
    5010             {
    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             else
    5088                 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         else
    5117         {
    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             else
    5155                 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         else
    5179         {
    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     else
    5194         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     else
    5214     {
    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         else
    5242             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                 else
    5265                 {
    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                          else
    5273                          */
    5274                         RTPrintf("%ls\n", stats.raw());
    5275                     }
    5276                 }
    5277             }
    5278             aSession->Close();
    5279         }
    5280     }
    5281 
    5282     return SUCCEEDED(rc) ? 0 : 1;
    5283 }
    528466
    528567static char *toBaseMetricNames(const char *metricList)
     
    5765547}
    5766548
    5767 static int handleMetrics(int argc, char *argv[],
    5768                          ComPtr<IVirtualBox> aVirtualBox, ComPtr<ISession> aSession)
     549int handleMetrics(int argc, char *argv[],
     550                  ComPtr<IVirtualBox> aVirtualBox, ComPtr<ISession> aSession)
    5769551{
    5770552    int rc;
     
    5790572    return rc;
    5791573}
    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.

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