VirtualBox

Changeset 24903 in vbox for trunk/src


Ignore:
Timestamp:
Nov 24, 2009 2:07:11 PM (15 years ago)
Author:
vboxsync
Message:

VBoxManage: A little clean up in progress.

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

Legend:

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

    r23802 r24903  
    5858 VBoxManage_SOURCES = \
    5959        VBoxManage.cpp \
     60        VBoxInternalManage.cpp \
     61        VBoxManageControlVM.cpp \
     62        VBoxManageDHCPServer.cpp \
     63        VBoxManageDisk.cpp \
     64        $(if $(VBOX_WITH_GUEST_PROPS),VBoxManageGuestProp.cpp) \
    6065        VBoxManageHelp.cpp \
     66        VBoxManageHostonly.cpp \
     67        VBoxManageImport.cpp \
     68        VBoxManageInfo.cpp \
     69        VBoxManageList.cpp \
     70        VBoxManageMetrics.cpp \
    6171        VBoxManageModifyVM.cpp \
    62         VBoxManageInfo.cpp \
    63         VBoxManageImport.cpp \
    64         VBoxManageMetrics.cpp \
    65         VBoxManageList.cpp \
    66         VBoxManageDisk.cpp \
     72        VBoxManageSnapshot.cpp \
    6773        VBoxManageStorageController.cpp \
    68         VBoxManageSnapshot.cpp \
    69         VBoxManageUSB.cpp \
    70         VBoxInternalManage.cpp \
    71         VBoxManageHostonly.cpp \
    72         VBoxManageDHCPServer.cpp \
    73         $(if $(VBOX_WITH_GUEST_PROPS),VBoxManageGuestProp.cpp)
     74        VBoxManageUSB.cpp
    7475endif # !VBOX_ONLY_DOCS
    7576ifneq ($(KBUILD_TARGET),win)
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManage.cpp

    r24901 r24903  
    374374}
    375375
    376 /**
    377  * Parses a number.
    378  *
    379  * @returns Valid number on success.
    380  * @returns 0 if invalid number. All necesary bitching has been done.
    381  * @param   psz     Pointer to the nic number.
    382  */
    383 unsigned parseNum(const char *psz, unsigned cMaxNum, const char *name)
    384 {
    385     uint32_t u32;
    386     char *pszNext;
    387     int rc = RTStrToUInt32Ex(psz, &pszNext, 10, &u32);
    388     if (    RT_SUCCESS(rc)
    389         &&  *pszNext == '\0'
    390         &&  u32 >= 1
    391         &&  u32 <= cMaxNum)
    392         return (unsigned)u32;
    393     errorArgument("Invalid %s number '%s'", name, psz);
    394     return 0;
    395 }
    396 
    397 
    398 /** @todo refine this after HDD changes; MSC 8.0/64 has trouble with handleModifyVM.  */
    399 #if defined(_MSC_VER)
    400 # pragma optimize("", on)
    401 #endif
    402 
    403 static const RTGETOPTDEF g_aStartVMOptions[] =
    404 {
    405     { "--type",         't', RTGETOPT_REQ_STRING },
    406     { "-type",          't', RTGETOPT_REQ_STRING },     // deprecated
    407 };
    408 
    409376static int handleStartVM(HandlerArg *a)
    410377{
     
    413380    Bstr sessionType = "gui";
    414381
     382    static const RTGETOPTDEF s_aStartVMOptions[] =
     383    {
     384        { "--type",         't', RTGETOPT_REQ_STRING },
     385        { "-type",          't', RTGETOPT_REQ_STRING },     // deprecated
     386    };
    415387    int c;
    416388    RTGETOPTUNION ValueUnion;
    417389    RTGETOPTSTATE GetState;
    418390    // start at 0 because main() has hacked both the argc and argv given to us
    419     RTGetOptInit(&GetState, a->argc, a->argv, g_aStartVMOptions, RT_ELEMENTS(g_aStartVMOptions), 0, 0 /* fFlags */);
     391    RTGetOptInit(&GetState, a->argc, a->argv, s_aStartVMOptions, RT_ELEMENTS(s_aStartVMOptions), 0, 0 /* fFlags */);
    420392    while ((c = RTGetOpt(&GetState, &ValueUnion)))
    421393    {
     
    533505
    534506    /* it's important to always close sessions */
    535     a->session->Close();
    536 
    537     return SUCCEEDED(rc) ? 0 : 1;
    538 }
    539 
    540 static int handleControlVM(HandlerArg *a)
    541 {
    542     HRESULT rc;
    543 
    544     if (a->argc < 2)
    545         return errorSyntax(USAGE_CONTROLVM, "Not enough parameters");
    546 
    547     /* try to find the given machine */
    548     ComPtr <IMachine> machine;
    549     Bstr machineuuid (a->argv[0]);
    550     if (!Guid(machineuuid).isEmpty())
    551     {
    552         CHECK_ERROR(a->virtualBox, GetMachine(machineuuid, machine.asOutParam()));
    553     }
    554     else
    555     {
    556         CHECK_ERROR(a->virtualBox, FindMachine(machineuuid, machine.asOutParam()));
    557         if (SUCCEEDED (rc))
    558             machine->COMGETTER(Id)(machineuuid.asOutParam());
    559     }
    560     if (FAILED (rc))
    561         return 1;
    562 
    563     /* open a session for the VM */
    564     CHECK_ERROR_RET(a->virtualBox, OpenExistingSession(a->session, machineuuid), 1);
    565 
    566     do
    567     {
    568         /* get the associated console */
    569         ComPtr<IConsole> console;
    570         CHECK_ERROR_BREAK(a->session, COMGETTER(Console)(console.asOutParam()));
    571         /* ... and session machine */
    572         ComPtr<IMachine> sessionMachine;
    573         CHECK_ERROR_BREAK(a->session, COMGETTER(Machine)(sessionMachine.asOutParam()));
    574 
    575         /* which command? */
    576         if (!strcmp(a->argv[1], "pause"))
    577         {
    578             CHECK_ERROR_BREAK(console, Pause());
    579         }
    580         else if (!strcmp(a->argv[1], "resume"))
    581         {
    582             CHECK_ERROR_BREAK(console, Resume());
    583         }
    584         else if (!strcmp(a->argv[1], "reset"))
    585         {
    586             CHECK_ERROR_BREAK(console, Reset());
    587         }
    588         else if (!strcmp(a->argv[1], "poweroff"))
    589         {
    590             ComPtr<IProgress> progress;
    591             CHECK_ERROR_BREAK(console, PowerDown(progress.asOutParam()));
    592 
    593             rc = showProgress(progress);
    594             if (FAILED(rc))
    595             {
    596                 com::ProgressErrorInfo info(progress);
    597                 if (info.isBasicAvailable())
    598                 {
    599                     RTPrintf("Error: failed to power off machine. Error message: %lS\n", info.getText().raw());
    600                 }
    601                 else
    602                 {
    603                     RTPrintf("Error: failed to power off machine. No error message available!\n");
    604                 }
    605             }
    606         }
    607         else if (!strcmp(a->argv[1], "savestate"))
    608         {
    609             ComPtr<IProgress> progress;
    610             CHECK_ERROR_BREAK(console, SaveState(progress.asOutParam()));
    611 
    612             rc = showProgress(progress);
    613             if (FAILED(rc))
    614             {
    615                 com::ProgressErrorInfo info(progress);
    616                 if (info.isBasicAvailable())
    617                 {
    618                     RTPrintf("Error: failed to save machine state. Error message: %lS\n", info.getText().raw());
    619                 }
    620                 else
    621                 {
    622                     RTPrintf("Error: failed to save machine state. No error message available!\n");
    623                 }
    624             }
    625         }
    626         else if (!strcmp(a->argv[1], "acpipowerbutton"))
    627         {
    628             CHECK_ERROR_BREAK(console, PowerButton());
    629         }
    630         else if (!strcmp(a->argv[1], "acpisleepbutton"))
    631         {
    632             CHECK_ERROR_BREAK(console, SleepButton());
    633         }
    634         else if (!strcmp(a->argv[1], "injectnmi"))
    635         {
    636             /* get the machine debugger. */
    637             ComPtr <IMachineDebugger> debugger;
    638             CHECK_ERROR_BREAK(console, COMGETTER(Debugger)(debugger.asOutParam()));
    639             CHECK_ERROR_BREAK(debugger, InjectNMI());
    640         }
    641         else if (!strcmp(a->argv[1], "keyboardputscancode"))
    642         {
    643             ComPtr<IKeyboard> keyboard;
    644             CHECK_ERROR_BREAK(console, COMGETTER(Keyboard)(keyboard.asOutParam()));
    645 
    646             if (a->argc <= 1 + 1)
    647             {
    648                 errorArgument("Missing argument to '%s'. Expected IBM PC AT set 2 keyboard scancode(s) as hex byte(s).", a->argv[1]);
    649                 rc = E_FAIL;
    650                 break;
    651             }
    652 
    653             /* Arbitrary restrict the length of a sequence of scancodes to 1024. */
    654             LONG alScancodes[1024];
    655             int cScancodes = 0;
    656 
    657             /* Process the command line. */
    658             int i;
    659             for (i = 1 + 1; i < a->argc && cScancodes < (int)RT_ELEMENTS(alScancodes); i++, cScancodes++)
    660             {
    661                 if (   RT_C_IS_XDIGIT (a->argv[i][0])
    662                     && RT_C_IS_XDIGIT (a->argv[i][1])
    663                     && a->argv[i][2] == 0)
    664                 {
    665                     uint8_t u8Scancode;
    666                     int rc = RTStrToUInt8Ex(a->argv[i], NULL, 16, &u8Scancode);
    667                     if (RT_FAILURE (rc))
    668                     {
    669                         RTPrintf("Error: converting '%s' returned %Rrc!\n", a->argv[i], rc);
    670                         rc = E_FAIL;
    671                         break;
    672                     }
    673 
    674                     alScancodes[cScancodes] = u8Scancode;
    675                 }
    676                 else
    677                 {
    678                     RTPrintf("Error: '%s' is not a hex byte!\n", a->argv[i]);
    679                     rc = E_FAIL;
    680                     break;
    681                 }
    682             }
    683 
    684             if (FAILED(rc))
    685                 break;
    686 
    687             if (   cScancodes == RT_ELEMENTS(alScancodes)
    688                 && i < a->argc)
    689             {
    690                 RTPrintf("Error: too many scancodes, maximum %d allowed!\n", RT_ELEMENTS(alScancodes));
    691                 rc = E_FAIL;
    692                 break;
    693             }
    694 
    695             /* Send scancodes to the VM.
    696              * Note: 'PutScancodes' did not work here. Only the first scancode was transmitted.
    697              */
    698             for (i = 0; i < cScancodes; i++)
    699             {
    700                 CHECK_ERROR_BREAK(keyboard, PutScancode(alScancodes[i]));
    701                 RTPrintf("Scancode[%d]: 0x%02X\n", i, alScancodes[i]);
    702             }
    703         }
    704         else if (!strncmp(a->argv[1], "setlinkstate", 12))
    705         {
    706             /* Get the number of network adapters */
    707             ULONG NetworkAdapterCount = 0;
    708             ComPtr <ISystemProperties> info;
    709             CHECK_ERROR_BREAK(a->virtualBox, COMGETTER(SystemProperties)(info.asOutParam()));
    710             CHECK_ERROR_BREAK(info, COMGETTER(NetworkAdapterCount)(&NetworkAdapterCount));
    711 
    712             unsigned n = parseNum(&a->argv[1][12], NetworkAdapterCount, "NIC");
    713             if (!n)
    714             {
    715                 rc = E_FAIL;
    716                 break;
    717             }
    718             if (a->argc <= 1 + 1)
    719             {
    720                 errorArgument("Missing argument to '%s'", a->argv[1]);
    721                 rc = E_FAIL;
    722                 break;
    723             }
    724             /* get the corresponding network adapter */
    725             ComPtr<INetworkAdapter> adapter;
    726             CHECK_ERROR_BREAK(sessionMachine, GetNetworkAdapter(n - 1, adapter.asOutParam()));
    727             if (adapter)
    728             {
    729                 if (!strcmp(a->argv[2], "on"))
    730                 {
    731                     CHECK_ERROR_BREAK(adapter, COMSETTER(CableConnected)(TRUE));
    732                 }
    733                 else if (!strcmp(a->argv[2], "off"))
    734                 {
    735                     CHECK_ERROR_BREAK(adapter, COMSETTER(CableConnected)(FALSE));
    736                 }
    737                 else
    738                 {
    739                     errorArgument("Invalid link state '%s'", Utf8Str(a->argv[2]).raw());
    740                     rc = E_FAIL;
    741                     break;
    742                 }
    743             }
    744         }
    745 #ifdef VBOX_DYNAMIC_NET_ATTACH
    746         /* here the order in which strncmp is called is important
    747          * cause nictracefile can be very well compared with
    748          * nictrace and nic and thus everything will always fail
    749          * if the order is changed
    750          */
    751         else if (!strncmp(a->argv[1], "nictracefile", 12))
    752         {
    753             /* Get the number of network adapters */
    754             ULONG NetworkAdapterCount = 0;
    755             ComPtr <ISystemProperties> info;
    756             CHECK_ERROR_BREAK(a->virtualBox, COMGETTER(SystemProperties)(info.asOutParam()));
    757             CHECK_ERROR_BREAK(info, COMGETTER(NetworkAdapterCount)(&NetworkAdapterCount));
    758 
    759             unsigned n = parseNum(&a->argv[1][12], NetworkAdapterCount, "NIC");
    760             if (!n)
    761             {
    762                 rc = E_FAIL;
    763                 break;
    764             }
    765             if (a->argc <= 2)
    766             {
    767                 errorArgument("Missing argument to '%s'", a->argv[1]);
    768                 rc = E_FAIL;
    769                 break;
    770             }
    771 
    772             /* get the corresponding network adapter */
    773             ComPtr<INetworkAdapter> adapter;
    774             CHECK_ERROR_BREAK(sessionMachine, GetNetworkAdapter(n - 1, adapter.asOutParam()));
    775             if (adapter)
    776             {
    777                 BOOL fEnabled;
    778                 adapter->COMGETTER(Enabled)(&fEnabled);
    779                 if (fEnabled)
    780                 {
    781                     if (a->argv[2])
    782                     {
    783                         CHECK_ERROR_RET(adapter, COMSETTER(TraceFile)(Bstr(a->argv[2])), 1);
    784                     }
    785                     else
    786                     {
    787                         errorArgument("Invalid filename or filename not specified for NIC %lu", n);
    788                         rc = E_FAIL;
    789                         break;
    790                     }
    791                 }
    792                 else
    793                 {
    794                     RTPrintf("The NIC %d is currently disabled and thus can't change its tracefile\n", n);
    795                 }
    796             }
    797         }
    798         else if (!strncmp(a->argv[1], "nictrace", 8))
    799         {
    800             /* Get the number of network adapters */
    801             ULONG NetworkAdapterCount = 0;
    802             ComPtr <ISystemProperties> info;
    803             CHECK_ERROR_BREAK(a->virtualBox, COMGETTER(SystemProperties)(info.asOutParam()));
    804             CHECK_ERROR_BREAK(info, COMGETTER(NetworkAdapterCount)(&NetworkAdapterCount));
    805 
    806             unsigned n = parseNum(&a->argv[1][8], NetworkAdapterCount, "NIC");
    807             if (!n)
    808             {
    809                 rc = E_FAIL;
    810                 break;
    811             }
    812             if (a->argc <= 2)
    813             {
    814                 errorArgument("Missing argument to '%s'", a->argv[1]);
    815                 rc = E_FAIL;
    816                 break;
    817             }
    818 
    819             /* get the corresponding network adapter */
    820             ComPtr<INetworkAdapter> adapter;
    821             CHECK_ERROR_BREAK(sessionMachine, GetNetworkAdapter(n - 1, adapter.asOutParam()));
    822             if (adapter)
    823             {
    824                 BOOL fEnabled;
    825                 adapter->COMGETTER(Enabled)(&fEnabled);
    826                 if (fEnabled)
    827                 {
    828                     if (!strcmp(a->argv[2], "on"))
    829                     {
    830                         CHECK_ERROR_RET(adapter, COMSETTER(TraceEnabled)(TRUE), 1);
    831                     }
    832                     else if (!strcmp(a->argv[2], "off"))
    833                     {
    834                         CHECK_ERROR_RET(adapter, COMSETTER(TraceEnabled)(FALSE), 1);
    835                     }
    836                     else
    837                     {
    838                         errorArgument("Invalid nictrace%lu argument '%s'", n, Utf8Str(a->argv[2]).raw());
    839                         rc = E_FAIL;
    840                         break;
    841                     }
    842                 }
    843                 else
    844                 {
    845                     RTPrintf("The NIC %d is currently disabled and thus can't change its tracefile\n", n);
    846                 }
    847             }
    848         }
    849         else if (!strncmp(a->argv[1], "nic", 3))
    850         {
    851             /* Get the number of network adapters */
    852             ULONG NetworkAdapterCount = 0;
    853             ComPtr <ISystemProperties> info;
    854             CHECK_ERROR_BREAK(a->virtualBox, COMGETTER(SystemProperties)(info.asOutParam()));
    855             CHECK_ERROR_BREAK(info, COMGETTER(NetworkAdapterCount)(&NetworkAdapterCount));
    856 
    857             unsigned n = parseNum(&a->argv[1][3], NetworkAdapterCount, "NIC");
    858             if (!n)
    859             {
    860                 rc = E_FAIL;
    861                 break;
    862             }
    863             if (a->argc <= 2)
    864             {
    865                 errorArgument("Missing argument to '%s'", a->argv[1]);
    866                 rc = E_FAIL;
    867                 break;
    868             }
    869 
    870             /* get the corresponding network adapter */
    871             ComPtr<INetworkAdapter> adapter;
    872             CHECK_ERROR_BREAK(sessionMachine, GetNetworkAdapter(n - 1, adapter.asOutParam()));
    873             if (adapter)
    874             {
    875                 BOOL fEnabled;
    876                 adapter->COMGETTER(Enabled)(&fEnabled);
    877                 if (fEnabled)
    878                 {
    879                     if (!strcmp(a->argv[2], "null"))
    880                     {
    881                         CHECK_ERROR_RET(adapter, COMSETTER(Enabled)(TRUE), 1);
    882                         CHECK_ERROR_RET(adapter, Detach(), 1);
    883                     }
    884                     else if (!strcmp(a->argv[2], "nat"))
    885                     {
    886                         CHECK_ERROR_RET(adapter, COMSETTER(Enabled)(TRUE), 1);
    887                         if (a->argc == 4)
    888                             CHECK_ERROR_RET(adapter, COMSETTER(NATNetwork)(Bstr(a->argv[3])), 1);
    889                         CHECK_ERROR_RET(adapter, AttachToNAT(), 1);
    890                     }
    891                     else if (  !strcmp(a->argv[2], "bridged")
    892                             || !strcmp(a->argv[2], "hostif")) /* backward compatibility */
    893                     {
    894                         if (a->argc <= 3)
    895                         {
    896                             errorArgument("Missing argument to '%s'", a->argv[2]);
    897                             rc = E_FAIL;
    898                             break;
    899                         }
    900                         CHECK_ERROR_RET(adapter, COMSETTER(Enabled)(TRUE), 1);
    901                         CHECK_ERROR_RET(adapter, COMSETTER(HostInterface)(Bstr(a->argv[3])), 1);
    902                         CHECK_ERROR_RET(adapter, AttachToBridgedInterface(), 1);
    903                     }
    904                     else if (!strcmp(a->argv[2], "intnet"))
    905                     {
    906                         if (a->argc <= 3)
    907                         {
    908                             errorArgument("Missing argument to '%s'", a->argv[2]);
    909                             rc = E_FAIL;
    910                             break;
    911                         }
    912                         CHECK_ERROR_RET(adapter, COMSETTER(Enabled)(TRUE), 1);
    913                         CHECK_ERROR_RET(adapter, COMSETTER(InternalNetwork)(Bstr(a->argv[3])), 1);
    914                         CHECK_ERROR_RET(adapter, AttachToInternalNetwork(), 1);
    915                     }
    916 #if defined(VBOX_WITH_NETFLT)
    917                     else if (!strcmp(a->argv[2], "hostonly"))
    918                     {
    919                         if (a->argc <= 3)
    920                         {
    921                             errorArgument("Missing argument to '%s'", a->argv[2]);
    922                             rc = E_FAIL;
    923                             break;
    924                         }
    925                         CHECK_ERROR_RET(adapter, COMSETTER(Enabled)(TRUE), 1);
    926                         CHECK_ERROR_RET(adapter, COMSETTER(HostInterface)(Bstr(a->argv[3])), 1);
    927                         CHECK_ERROR_RET(adapter, AttachToHostOnlyInterface(), 1);
    928                     }
    929 #endif
    930                     else
    931                     {
    932                         errorArgument("Invalid type '%s' specfied for NIC %lu", Utf8Str(a->argv[2]).raw(), n);
    933                         rc = E_FAIL;
    934                         break;
    935                     }
    936                 }
    937                 else
    938                 {
    939                     RTPrintf("The NIC %d is currently disabled and thus can't change its attachment type\n", n);
    940                 }
    941             }
    942         }
    943 #endif /* VBOX_DYNAMIC_NET_ATTACH */
    944 #ifdef VBOX_WITH_VRDP
    945         else if (!strcmp(a->argv[1], "vrdp"))
    946         {
    947             if (a->argc <= 1 + 1)
    948             {
    949                 errorArgument("Missing argument to '%s'", a->argv[1]);
    950                 rc = E_FAIL;
    951                 break;
    952             }
    953             /* get the corresponding VRDP server */
    954             ComPtr<IVRDPServer> vrdpServer;
    955             sessionMachine->COMGETTER(VRDPServer)(vrdpServer.asOutParam());
    956             ASSERT(vrdpServer);
    957             if (vrdpServer)
    958             {
    959                 if (!strcmp(a->argv[2], "on"))
    960                 {
    961                     CHECK_ERROR_BREAK(vrdpServer, COMSETTER(Enabled)(TRUE));
    962                 }
    963                 else if (!strcmp(a->argv[2], "off"))
    964                 {
    965                     CHECK_ERROR_BREAK(vrdpServer, COMSETTER(Enabled)(FALSE));
    966                 }
    967                 else
    968                 {
    969                     errorArgument("Invalid vrdp server state '%s'", Utf8Str(a->argv[2]).raw());
    970                     rc = E_FAIL;
    971                     break;
    972                 }
    973             }
    974         }
    975         else if (!strcmp(a->argv[1], "vrdpport"))
    976         {
    977             if (a->argc <= 1 + 1)
    978             {
    979                 errorArgument("Missing argument to '%s'", a->argv[1]);
    980                 rc = E_FAIL;
    981                 break;
    982             }
    983             /* get the corresponding VRDP server */
    984             ComPtr<IVRDPServer> vrdpServer;
    985             sessionMachine->COMGETTER(VRDPServer)(vrdpServer.asOutParam());
    986             ASSERT(vrdpServer);
    987             if (vrdpServer)
    988             {
    989                 Bstr vrdpports;
    990 
    991                 if (!strcmp(a->argv[2], "default"))
    992                     vrdpports = "0";
    993                 else
    994                     vrdpports = a->argv [2];
    995 
    996                 CHECK_ERROR_BREAK(vrdpServer, COMSETTER(Ports)(vrdpports));
    997             }
    998         }
    999 #endif /* VBOX_WITH_VRDP */
    1000         else if (   !strcmp(a->argv[1], "usbattach")
    1001                  || !strcmp(a->argv[1], "usbdetach"))
    1002         {
    1003             if (a->argc < 3)
    1004             {
    1005                 errorSyntax(USAGE_CONTROLVM, "Not enough parameters");
    1006                 rc = E_FAIL;
    1007                 break;
    1008             }
    1009 
    1010             bool attach = !strcmp(a->argv[1], "usbattach");
    1011 
    1012             Bstr usbId = a->argv [2];
    1013             if (Guid(usbId).isEmpty())
    1014             {
    1015                 // assume address
    1016                 if (attach)
    1017                 {
    1018                     ComPtr <IHost> host;
    1019                     CHECK_ERROR_BREAK(a->virtualBox, COMGETTER(Host)(host.asOutParam()));
    1020                     SafeIfaceArray <IHostUSBDevice> coll;
    1021                     CHECK_ERROR_BREAK(host, COMGETTER(USBDevices)(ComSafeArrayAsOutParam(coll)));
    1022                     ComPtr <IHostUSBDevice> dev;
    1023                     CHECK_ERROR_BREAK(host, FindUSBDeviceByAddress(Bstr(a->argv [2]), dev.asOutParam()));
    1024                     CHECK_ERROR_BREAK(dev, COMGETTER(Id)(usbId.asOutParam()));
    1025                 }
    1026                 else
    1027                 {
    1028                     SafeIfaceArray <IUSBDevice> coll;
    1029                     CHECK_ERROR_BREAK(console, COMGETTER(USBDevices)(ComSafeArrayAsOutParam(coll)));
    1030                     ComPtr <IUSBDevice> dev;
    1031                     CHECK_ERROR_BREAK(console, FindUSBDeviceByAddress(Bstr(a->argv [2]),
    1032                                                        dev.asOutParam()));
    1033                     CHECK_ERROR_BREAK(dev, COMGETTER(Id)(usbId.asOutParam()));
    1034                 }
    1035             }
    1036 
    1037             if (attach)
    1038                 CHECK_ERROR_BREAK(console, AttachUSBDevice(usbId));
    1039             else
    1040             {
    1041                 ComPtr <IUSBDevice> dev;
    1042                 CHECK_ERROR_BREAK(console, DetachUSBDevice(usbId, dev.asOutParam()));
    1043             }
    1044         }
    1045         else if (!strcmp(a->argv[1], "setvideomodehint"))
    1046         {
    1047             if (a->argc != 5 && a->argc != 6)
    1048             {
    1049                 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
    1050                 rc = E_FAIL;
    1051                 break;
    1052             }
    1053             uint32_t xres = RTStrToUInt32(a->argv[2]);
    1054             uint32_t yres = RTStrToUInt32(a->argv[3]);
    1055             uint32_t bpp  = RTStrToUInt32(a->argv[4]);
    1056             uint32_t displayIdx = 0;
    1057             if (a->argc == 6)
    1058                 displayIdx = RTStrToUInt32(a->argv[5]);
    1059 
    1060             ComPtr<IDisplay> display;
    1061             CHECK_ERROR_BREAK(console, COMGETTER(Display)(display.asOutParam()));
    1062             CHECK_ERROR_BREAK(display, SetVideoModeHint(xres, yres, bpp, displayIdx));
    1063         }
    1064         else if (!strcmp(a->argv[1], "setcredentials"))
    1065         {
    1066             bool fAllowLocalLogon = true;
    1067             if (a->argc == 7)
    1068             {
    1069                 if (   strcmp(a->argv[5], "--allowlocallogon")
    1070                     && strcmp(a->argv[5], "-allowlocallogon"))
    1071                 {
    1072                     errorArgument("Invalid parameter '%s'", a->argv[5]);
    1073                     rc = E_FAIL;
    1074                     break;
    1075                 }
    1076                 if (!strcmp(a->argv[6], "no"))
    1077                     fAllowLocalLogon = false;
    1078             }
    1079             else if (a->argc != 5)
    1080             {
    1081                 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
    1082                 rc = E_FAIL;
    1083                 break;
    1084             }
    1085 
    1086             ComPtr<IGuest> guest;
    1087             CHECK_ERROR_BREAK(console, COMGETTER(Guest)(guest.asOutParam()));
    1088             CHECK_ERROR_BREAK(guest, SetCredentials(Bstr(a->argv[2]), Bstr(a->argv[3]), Bstr(a->argv[4]), fAllowLocalLogon));
    1089         }
    1090         else if (!strcmp(a->argv[1], "dvdattach"))
    1091         {
    1092             Bstr uuid;
    1093             if (a->argc != 3)
    1094             {
    1095                 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
    1096                 rc = E_FAIL;
    1097                 break;
    1098             }
    1099 
    1100             ComPtr<IMedium> dvdMedium;
    1101 
    1102             /* unmount? */
    1103             if (!strcmp(a->argv[2], "none"))
    1104             {
    1105                 /* nothing to do, NULL object will cause unmount */
    1106             }
    1107             /* host drive? */
    1108             else if (!strncmp(a->argv[2], "host:", 5))
    1109             {
    1110                 ComPtr<IHost> host;
    1111                 CHECK_ERROR(a->virtualBox, COMGETTER(Host)(host.asOutParam()));
    1112 
    1113                 rc = host->FindHostDVDDrive(Bstr(a->argv[2] + 5), dvdMedium.asOutParam());
    1114                 if (!dvdMedium)
    1115                 {
    1116                     errorArgument("Invalid host DVD drive name \"%s\"",
    1117                                   a->argv[2] + 5);
    1118                     rc = E_FAIL;
    1119                     break;
    1120                 }
    1121             }
    1122             else
    1123             {
    1124                 /* first assume it's a UUID */
    1125                 uuid = a->argv[2];
    1126                 rc = a->virtualBox->GetDVDImage(uuid, dvdMedium.asOutParam());
    1127                 if (FAILED(rc) || !dvdMedium)
    1128                 {
    1129                     /* must be a filename, check if it's in the collection */
    1130                     rc = a->virtualBox->FindDVDImage(Bstr(a->argv[2]), dvdMedium.asOutParam());
    1131                     /* not registered, do that on the fly */
    1132                     if (!dvdMedium)
    1133                     {
    1134                         Bstr emptyUUID;
    1135                         CHECK_ERROR(a->virtualBox, OpenDVDImage(Bstr(a->argv[2]), emptyUUID, dvdMedium.asOutParam()));
    1136                     }
    1137                 }
    1138                 if (!dvdMedium)
    1139                 {
    1140                     rc = E_FAIL;
    1141                     break;
    1142                 }
    1143             }
    1144 
    1145             /** @todo generalize this, allow arbitrary number of DVD drives
    1146              * and as a consequence multiple attachments and different
    1147              * storage controllers. */
    1148             if (dvdMedium)
    1149                 dvdMedium->COMGETTER(Id)(uuid.asOutParam());
    1150             else
    1151                 uuid = Guid().toString();
    1152             CHECK_ERROR(machine, MountMedium(Bstr("IDE Controller"), 1, 0, uuid, FALSE /* aForce */));
    1153         }
    1154         else if (!strcmp(a->argv[1], "floppyattach"))
    1155         {
    1156             Bstr uuid;
    1157             if (a->argc != 3)
    1158             {
    1159                 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
    1160                 rc = E_FAIL;
    1161                 break;
    1162             }
    1163 
    1164             ComPtr<IMedium> floppyMedium;
    1165 
    1166             /* unmount? */
    1167             if (!strcmp(a->argv[2], "none"))
    1168             {
    1169                 /* nothing to do, NULL object will cause unmount */
    1170             }
    1171             /* host drive? */
    1172             else if (!strncmp(a->argv[2], "host:", 5))
    1173             {
    1174                 ComPtr<IHost> host;
    1175                 CHECK_ERROR(a->virtualBox, COMGETTER(Host)(host.asOutParam()));
    1176                 host->FindHostFloppyDrive(Bstr(a->argv[2] + 5), floppyMedium.asOutParam());
    1177                 if (!floppyMedium)
    1178                 {
    1179                     errorArgument("Invalid host floppy drive name \"%s\"",
    1180                                   a->argv[2] + 5);
    1181                     rc = E_FAIL;
    1182                     break;
    1183                 }
    1184             }
    1185             else
    1186             {
    1187                 /* first assume it's a UUID */
    1188                 uuid = a->argv[2];
    1189                 rc = a->virtualBox->GetFloppyImage(uuid, floppyMedium.asOutParam());
    1190                 if (FAILED(rc) || !floppyMedium)
    1191                 {
    1192                     /* must be a filename, check if it's in the collection */
    1193                     rc = a->virtualBox->FindFloppyImage(Bstr(a->argv[2]), floppyMedium.asOutParam());
    1194                     /* not registered, do that on the fly */
    1195                     if (!floppyMedium)
    1196                     {
    1197                         Bstr emptyUUID;
    1198                         CHECK_ERROR(a->virtualBox, OpenFloppyImage(Bstr(a->argv[2]), emptyUUID, floppyMedium.asOutParam()));
    1199                     }
    1200                 }
    1201                 if (!floppyMedium)
    1202                 {
    1203                     rc = E_FAIL;
    1204                     break;
    1205                 }
    1206             }
    1207             floppyMedium->COMGETTER(Id)(uuid.asOutParam());
    1208             CHECK_ERROR(machine, MountMedium(Bstr("Floppy Controller"), 0, 0, uuid, FALSE /* aForce */));
    1209         }
    1210 #ifdef VBOX_WITH_MEM_BALLOONING
    1211         else if (   !strcmp(a->argv[1], "--guestmemoryballoon")
    1212                  || !strcmp(a->argv[1], "-guestmemoryballoon"))
    1213         {
    1214             if (a->argc != 3)
    1215             {
    1216                 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
    1217                 rc = E_FAIL;
    1218                 break;
    1219             }
    1220             uint32_t uVal;
    1221             int vrc;
    1222             vrc = RTStrToUInt32Ex(a->argv[2], NULL, 0, &uVal);
    1223             if (vrc != VINF_SUCCESS)
    1224             {
    1225                 errorArgument("Error parsing guest memory balloon size '%s'", a->argv[2]);
    1226                 rc = E_FAIL;
    1227                 break;
    1228             }
    1229 
    1230             /* guest is running; update IGuest */
    1231             ComPtr <IGuest> guest;
    1232 
    1233             rc = console->COMGETTER(Guest)(guest.asOutParam());
    1234             if (SUCCEEDED(rc))
    1235                 CHECK_ERROR(guest, COMSETTER(MemoryBalloonSize)(uVal));
    1236         }
    1237 #endif
    1238         else if (   !strcmp(a->argv[1], "--gueststatisticsinterval")
    1239                  || !strcmp(a->argv[1], "-gueststatisticsinterval"))
    1240         {
    1241             if (a->argc != 3)
    1242             {
    1243                 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
    1244                 rc = E_FAIL;
    1245                 break;
    1246             }
    1247             uint32_t uVal;
    1248             int vrc;
    1249             vrc = RTStrToUInt32Ex(a->argv[2], NULL, 0, &uVal);
    1250             if (vrc != VINF_SUCCESS)
    1251             {
    1252                 errorArgument("Error parsing guest statistics interval '%s'", a->argv[2]);
    1253                 rc = E_FAIL;
    1254                 break;
    1255             }
    1256 
    1257             /* guest is running; update IGuest */
    1258             ComPtr <IGuest> guest;
    1259 
    1260             rc = console->COMGETTER(Guest)(guest.asOutParam());
    1261             if (SUCCEEDED(rc))
    1262                 CHECK_ERROR(guest, COMSETTER(StatisticsUpdateInterval)(uVal));
    1263         }
    1264         else if (!strcmp(a->argv[1], "teleport"))
    1265         {
    1266             Bstr        bstrHostname;
    1267             uint32_t    uMaxDowntime = 250 /*ms*/;
    1268             uint32_t    uPort        = UINT32_MAX;
    1269             Bstr        bstrPassword("");
    1270             static const RTGETOPTDEF s_aTeleportOptions[] =
    1271             {
    1272                 { "--host",        'h', RTGETOPT_REQ_STRING }, /** @todo RTGETOPT_FLAG_MANDATORY */
    1273                 { "--hostname",    'h', RTGETOPT_REQ_STRING }, /** @todo remove this */
    1274                 { "--maxdowntime", 'd', RTGETOPT_REQ_UINT32 },
    1275                 { "--port",        'p', RTGETOPT_REQ_UINT32 }, /** @todo RTGETOPT_FLAG_MANDATORY */
    1276                 { "--password",    'P', RTGETOPT_REQ_STRING }
    1277             };
    1278             RTGETOPTSTATE GetOptState;
    1279             RTGetOptInit(&GetOptState, a->argc, a->argv, s_aTeleportOptions, RT_ELEMENTS(s_aTeleportOptions), 2, 0 /*fFlags*/);
    1280             int ch;
    1281             RTGETOPTUNION Value;
    1282             while (   SUCCEEDED(rc)
    1283                    && (ch = RTGetOpt(&GetOptState, &Value)))
    1284             {
    1285                 switch (ch)
    1286                 {
    1287                     case 'h': bstrHostname  = Value.psz; break;
    1288                     case 'd': uMaxDowntime  = Value.u32; break;
    1289                     case 'p': uPort         = Value.u32; break;
    1290                     case 'P': bstrPassword  = Value.psz; break;
    1291                     default:
    1292                         errorGetOpt(USAGE_CONTROLVM, ch, &Value);
    1293                         rc = E_FAIL;
    1294                         break;
    1295                 }
    1296             }
    1297             if (FAILED(rc))
    1298                 break;
    1299 
    1300             ComPtr<IProgress> progress;
    1301             CHECK_ERROR_BREAK(console, Teleport(bstrHostname, uPort, bstrPassword, uMaxDowntime, progress.asOutParam()));
    1302             rc = showProgress(progress);
    1303             if (FAILED(rc))
    1304             {
    1305                 com::ProgressErrorInfo info(progress);
    1306                 if (info.isBasicAvailable())
    1307                     RTPrintf("Error: teleportation failed. Error message: %lS\n", info.getText().raw());
    1308                 else
    1309                     RTPrintf("Error: teleportation failed. No error message available!\n");
    1310             }
    1311         }
    1312         else
    1313         {
    1314             errorSyntax(USAGE_CONTROLVM, "Invalid parameter '%s'", Utf8Str(a->argv[1]).raw());
    1315             rc = E_FAIL;
    1316         }
    1317     } while (0);
    1318 
    1319507    a->session->Close();
    1320508
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManage.h

    r24879 r24903  
    156156#ifndef VBOX_ONLY_DOCS
    157157int handleInternalCommands(HandlerArg *a);
    158 
    159 unsigned parseNum(const char *psz, unsigned cMaxNum, const char *name);
    160158#endif /* !VBOX_ONLY_DOCS */
     159
     160/* VBoxManageControlVM.cpp */
     161int handleControlVM(HandlerArg *a);
    161162
    162163/* VBoxManageModifyVM.cpp */
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManageControlVM.cpp

    r24901 r24903  
    2424*   Header Files                                                               *
    2525*******************************************************************************/
    26 #ifndef VBOX_ONLY_DOCS
    2726#include <VBox/com/com.h>
    2827#include <VBox/com/string.h>
     
    3534#include <VBox/com/VirtualBox.h>
    3635
    37 #include <vector>
    38 #include <list>
    39 #endif /* !VBOX_ONLY_DOCS */
    40 
    41 #include <iprt/asm.h>
    42 #include <iprt/buildconfig.h>
    43 #include <iprt/cidr.h>
    4436#include <iprt/ctype.h>
    45 #include <iprt/dir.h>
    46 #include <iprt/env.h>
    4737#include <VBox/err.h>
    48 #include <iprt/file.h>
    49 #include <iprt/initterm.h>
    50 #include <iprt/param.h>
    51 #include <iprt/path.h>
     38#include <iprt/getopt.h>
    5239#include <iprt/stream.h>
    5340#include <iprt/string.h>
    54 #include <iprt/stdarg.h>
    55 #include <iprt/thread.h>
    5641#include <iprt/uuid.h>
    57 #include <iprt/getopt.h>
    58 #include <iprt/ctype.h>
    59 #include <VBox/version.h>
    6042#include <VBox/log.h>
    6143
    6244#include "VBoxManage.h"
    6345
    64 #ifndef VBOX_ONLY_DOCS
    65 using namespace com;
    66 #endif /* !VBOX_ONLY_DOCS */
    67 
    68 /*******************************************************************************
    69 *   Global Variables                                                           *
    70 *******************************************************************************/
    71 /*extern*/ bool g_fDetailedProgress = false;
    72 
    73 ////////////////////////////////////////////////////////////////////////////////
    74 //
    75 // functions
    76 //
    77 ////////////////////////////////////////////////////////////////////////////////
    78 
    79 #ifndef VBOX_ONLY_DOCS
    80 /**
    81  * Print out progress on the console
    82  */
    83 HRESULT showProgress(ComPtr<IProgress> progress)
    84 {
    85     BOOL fCompleted;
    86     ULONG ulCurrentPercent;
    87     ULONG ulLastPercent = 0;
    88 
    89     ULONG ulCurrentOperationPercent;
    90     ULONG ulLastOperationPercent = (ULONG)-1;
    91 
    92     ULONG ulLastOperation = (ULONG)-1;
    93     Bstr bstrOperationDescription;
    94 
    95     ULONG cOperations;
    96     progress->COMGETTER(OperationCount)(&cOperations);
    97 
    98     if (!g_fDetailedProgress)
    99     {
    100         RTPrintf("0%%...");
    101         RTStrmFlush(g_pStdOut);
    102     }
    103 
    104     while (SUCCEEDED(progress->COMGETTER(Completed(&fCompleted))))
    105     {
    106         ULONG ulOperation;
    107         progress->COMGETTER(Operation)(&ulOperation);
    108 
    109         progress->COMGETTER(Percent(&ulCurrentPercent));
    110         progress->COMGETTER(OperationPercent(&ulCurrentOperationPercent));
    111 
    112         if (g_fDetailedProgress)
    113         {
    114             if (ulLastOperation != ulOperation)
    115             {
    116                 progress->COMGETTER(OperationDescription(bstrOperationDescription.asOutParam()));
    117                 ulLastPercent = (ULONG)-1;        // force print
    118                 ulLastOperation = ulOperation;
    119             }
    120 
    121             if (    (ulCurrentPercent != ulLastPercent)
    122                  || (ulCurrentOperationPercent != ulLastOperationPercent)
    123                )
    124             {
    125                 LONG lSecsRem;
    126                 progress->COMGETTER(TimeRemaining)(&lSecsRem);
    127 
    128                 RTPrintf("(%ld/%ld) %ls %ld%% => %ld%% (%d s remaining)\n", ulOperation + 1, cOperations, bstrOperationDescription.raw(), ulCurrentOperationPercent, ulCurrentPercent, lSecsRem);
    129                 ulLastPercent = ulCurrentPercent;
    130                 ulLastOperationPercent = ulCurrentOperationPercent;
    131             }
    132         }
    133         else
    134         {
    135             /* did we cross a 10% mark? */
    136             if (((ulCurrentPercent / 10) > (ulLastPercent / 10)))
    137             {
    138                 /* make sure to also print out missed steps */
    139                 for (ULONG curVal = (ulLastPercent / 10) * 10 + 10; curVal <= (ulCurrentPercent / 10) * 10; curVal += 10)
    140                 {
    141                     if (curVal < 100)
    142                     {
    143                         RTPrintf("%ld%%...", curVal);
    144                         RTStrmFlush(g_pStdOut);
    145                     }
    146                 }
    147                 ulLastPercent = (ulCurrentPercent / 10) * 10;
    148             }
    149         }
    150         if (fCompleted)
    151             break;
    152 
    153         /* make sure the loop is not too tight */
    154         progress->WaitForCompletion(100);
    155     }
    156 
    157     /* complete the line. */
    158     LONG iRc = E_FAIL;
    159     if (SUCCEEDED(progress->COMGETTER(ResultCode)(&iRc)))
    160     {
    161         if (SUCCEEDED(iRc))
    162             RTPrintf("100%%\n");
    163         else
    164             RTPrintf("FAILED\n");
    165     }
    166     else
    167         RTPrintf("\n");
    168     RTStrmFlush(g_pStdOut);
    169     return iRc;
    170 }
    171 
    172 static int handleRegisterVM(HandlerArg *a)
    173 {
    174     HRESULT rc;
    175 
    176     if (a->argc != 1)
    177         return errorSyntax(USAGE_REGISTERVM, "Incorrect number of parameters");
    178 
    179     ComPtr<IMachine> machine;
    180     /** @todo Ugly hack to get both the API interpretation of relative paths
    181      * and the client's interpretation of relative paths. Remove after the API
    182      * has been redesigned. */
    183     rc = a->virtualBox->OpenMachine(Bstr(a->argv[0]), machine.asOutParam());
    184     if (rc == VBOX_E_FILE_ERROR)
    185     {
    186         char szVMFileAbs[RTPATH_MAX] = "";
    187         int vrc = RTPathAbs(a->argv[0], szVMFileAbs, sizeof(szVMFileAbs));
    188         if (RT_FAILURE(vrc))
    189         {
    190             RTPrintf("Cannot convert filename \"%s\" to absolute path\n", a->argv[0]);
    191             return 1;
    192         }
    193         CHECK_ERROR(a->virtualBox, OpenMachine(Bstr(szVMFileAbs), machine.asOutParam()));
    194     }
    195     else if (FAILED(rc))
    196         CHECK_ERROR(a->virtualBox, OpenMachine(Bstr(a->argv[0]), machine.asOutParam()));
    197     if (SUCCEEDED(rc))
    198     {
    199         ASSERT(machine);
    200         CHECK_ERROR(a->virtualBox, RegisterMachine(machine));
    201     }
    202     return SUCCEEDED(rc) ? 0 : 1;
    203 }
    204 
    205 static const RTGETOPTDEF g_aUnregisterVMOptions[] =
    206 {
    207     { "--delete",       'd', RTGETOPT_REQ_NOTHING },
    208     { "-delete",        'd', RTGETOPT_REQ_NOTHING },    // deprecated
    209 };
    210 
    211 static int handleUnregisterVM(HandlerArg *a)
    212 {
    213     HRESULT rc;
    214     const char *VMName = NULL;
    215     bool fDelete = false;
    216 
    217     int c;
    218     RTGETOPTUNION ValueUnion;
    219     RTGETOPTSTATE GetState;
    220     // start at 0 because main() has hacked both the argc and argv given to us
    221     RTGetOptInit(&GetState, a->argc, a->argv, g_aUnregisterVMOptions, RT_ELEMENTS(g_aUnregisterVMOptions), 0, 0 /* fFlags */);
    222     while ((c = RTGetOpt(&GetState, &ValueUnion)))
    223     {
    224         switch (c)
    225         {
    226             case 'd':   // --delete
    227                 fDelete = true;
    228                 break;
    229 
    230             case VINF_GETOPT_NOT_OPTION:
    231                 if (!VMName)
    232                     VMName = ValueUnion.psz;
    233                 else
    234                     return errorSyntax(USAGE_UNREGISTERVM, "Invalid parameter '%s'", ValueUnion.psz);
    235                 break;
    236 
    237             default:
    238                 if (c > 0)
    239                 {
    240                     if (RT_C_IS_PRINT(c))
    241                         return errorSyntax(USAGE_UNREGISTERVM, "Invalid option -%c", c);
    242                     else
    243                         return errorSyntax(USAGE_UNREGISTERVM, "Invalid option case %i", c);
    244                 }
    245                 else if (c == VERR_GETOPT_UNKNOWN_OPTION)
    246                     return errorSyntax(USAGE_UNREGISTERVM, "unknown option: %s\n", ValueUnion.psz);
    247                 else if (ValueUnion.pDef)
    248                     return errorSyntax(USAGE_UNREGISTERVM, "%s: %Rrs", ValueUnion.pDef->pszLong, c);
    249                 else
    250                     return errorSyntax(USAGE_UNREGISTERVM, "error: %Rrs", c);
    251         }
    252     }
    253 
    254     /* check for required options */
    255     if (!VMName)
    256         return errorSyntax(USAGE_UNREGISTERVM, "VM name required");
    257 
    258     ComPtr<IMachine> machine;
    259     /* assume it's a UUID */
    260     rc = a->virtualBox->GetMachine(Guid(VMName).toUtf16(), machine.asOutParam());
    261     if (FAILED(rc) || !machine)
    262     {
    263         /* must be a name */
    264         CHECK_ERROR(a->virtualBox, FindMachine(Bstr(VMName), machine.asOutParam()));
    265     }
    266     if (machine)
    267     {
    268         Bstr uuid;
    269         machine->COMGETTER(Id)(uuid.asOutParam());
    270         machine = NULL;
    271         CHECK_ERROR(a->virtualBox, UnregisterMachine(uuid, machine.asOutParam()));
    272         if (SUCCEEDED(rc) && machine && fDelete)
    273             CHECK_ERROR(machine, DeleteSettings());
    274     }
    275     return SUCCEEDED(rc) ? 0 : 1;
    276 }
    277 
    278 static int handleCreateVM(HandlerArg *a)
    279 {
    280     HRESULT rc;
    281     Bstr baseFolder;
    282     Bstr settingsFile;
    283     Bstr name;
    284     Bstr osTypeId;
    285     RTUUID id;
    286     bool fRegister = false;
    287 
    288     RTUuidClear(&id);
    289     for (int i = 0; i < a->argc; i++)
    290     {
    291         if (   !strcmp(a->argv[i], "--basefolder")
    292             || !strcmp(a->argv[i], "-basefolder"))
    293         {
    294             if (a->argc <= i + 1)
    295                 return errorArgument("Missing argument to '%s'", a->argv[i]);
    296             i++;
    297             baseFolder = a->argv[i];
    298         }
    299         else if (   !strcmp(a->argv[i], "--settingsfile")
    300                  || !strcmp(a->argv[i], "-settingsfile"))
    301         {
    302             if (a->argc <= i + 1)
    303                 return errorArgument("Missing argument to '%s'", a->argv[i]);
    304             i++;
    305             settingsFile = a->argv[i];
    306         }
    307         else if (   !strcmp(a->argv[i], "--name")
    308                  || !strcmp(a->argv[i], "-name"))
    309         {
    310             if (a->argc <= i + 1)
    311                 return errorArgument("Missing argument to '%s'", a->argv[i]);
    312             i++;
    313             name = a->argv[i];
    314         }
    315         else if (   !strcmp(a->argv[i], "--ostype")
    316                  || !strcmp(a->argv[i], "-ostype"))
    317         {
    318             if (a->argc <= i + 1)
    319                 return errorArgument("Missing argument to '%s'", a->argv[i]);
    320             i++;
    321             osTypeId = a->argv[i];
    322         }
    323         else if (   !strcmp(a->argv[i], "--uuid")
    324                  || !strcmp(a->argv[i], "-uuid"))
    325         {
    326             if (a->argc <= i + 1)
    327                 return errorArgument("Missing argument to '%s'", a->argv[i]);
    328             i++;
    329             if (RT_FAILURE(RTUuidFromStr(&id, a->argv[i])))
    330                 return errorArgument("Invalid UUID format %s\n", a->argv[i]);
    331         }
    332         else if (   !strcmp(a->argv[i], "--register")
    333                  || !strcmp(a->argv[i], "-register"))
    334         {
    335             fRegister = true;
    336         }
    337         else
    338             return errorSyntax(USAGE_CREATEVM, "Invalid parameter '%s'", Utf8Str(a->argv[i]).raw());
    339     }
    340     if (!name)
    341         return errorSyntax(USAGE_CREATEVM, "Parameter --name is required");
    342 
    343     if (!!baseFolder && !!settingsFile)
    344         return errorSyntax(USAGE_CREATEVM, "Either --basefolder or --settingsfile must be specified");
    345 
    346     do
    347     {
    348         ComPtr<IMachine> machine;
    349 
    350         if (!settingsFile)
    351             CHECK_ERROR_BREAK(a->virtualBox,
    352                 CreateMachine(name, osTypeId, baseFolder, Guid(id).toUtf16(), machine.asOutParam()));
    353         else
    354             CHECK_ERROR_BREAK(a->virtualBox,
    355                 CreateLegacyMachine(name, osTypeId, settingsFile, Guid(id).toUtf16(), machine.asOutParam()));
    356 
    357         CHECK_ERROR_BREAK(machine, SaveSettings());
    358         if (fRegister)
    359         {
    360             CHECK_ERROR_BREAK(a->virtualBox, RegisterMachine(machine));
    361         }
    362         Bstr uuid;
    363         CHECK_ERROR_BREAK(machine, COMGETTER(Id)(uuid.asOutParam()));
    364         CHECK_ERROR_BREAK(machine, COMGETTER(SettingsFilePath)(settingsFile.asOutParam()));
    365         RTPrintf("Virtual machine '%ls' is created%s.\n"
    366                  "UUID: %s\n"
    367                  "Settings file: '%ls'\n",
    368                  name.raw(), fRegister ? " and registered" : "",
    369                  Utf8Str(uuid).raw(), settingsFile.raw());
    370     }
    371     while (0);
    372 
    373     return SUCCEEDED(rc) ? 0 : 1;
    374 }
    37546
    37647/**
     
    38152 * @param   psz     Pointer to the nic number.
    38253 */
    383 unsigned parseNum(const char *psz, unsigned cMaxNum, const char *name)
     54static unsigned parseNum(const char *psz, unsigned cMaxNum, const char *name)
    38455{
    38556    uint32_t u32;
     
    39667
    39768
    398 /** @todo refine this after HDD changes; MSC 8.0/64 has trouble with handleModifyVM.  */
    399 #if defined(_MSC_VER)
    400 # pragma optimize("", on)
    401 #endif
    402 
    403 static const RTGETOPTDEF g_aStartVMOptions[] =
     69int handleControlVM(HandlerArg *a)
    40470{
    405     { "--type",         't', RTGETOPT_REQ_STRING },
    406     { "-type",          't', RTGETOPT_REQ_STRING },     // deprecated
    407 };
    408 
    409 static int handleStartVM(HandlerArg *a)
    410 {
    411     HRESULT rc;
    412     const char *VMName = NULL;
    413     Bstr sessionType = "gui";
    414 
    415     int c;
    416     RTGETOPTUNION ValueUnion;
    417     RTGETOPTSTATE GetState;
    418     // start at 0 because main() has hacked both the argc and argv given to us
    419     RTGetOptInit(&GetState, a->argc, a->argv, g_aStartVMOptions, RT_ELEMENTS(g_aStartVMOptions), 0, 0 /* fFlags */);
    420     while ((c = RTGetOpt(&GetState, &ValueUnion)))
    421     {
    422         switch (c)
    423         {
    424             case 't':   // --type
    425                 if (!RTStrICmp(ValueUnion.psz, "gui"))
    426                 {
    427                     sessionType = "gui";
    428                 }
    429 #ifdef VBOX_WITH_VBOXSDL
    430                 else if (!RTStrICmp(ValueUnion.psz, "sdl"))
    431                 {
    432                     sessionType = "sdl";
    433                 }
    434 #endif
    435 #ifdef VBOX_WITH_VRDP
    436                 else if (!RTStrICmp(ValueUnion.psz, "vrdp"))
    437                 {
    438                     sessionType = "vrdp";
    439                 }
    440 #endif
    441 #ifdef VBOX_WITH_HEADLESS
    442                 else if (!RTStrICmp(ValueUnion.psz, "capture"))
    443                 {
    444                     sessionType = "capture";
    445                 }
    446                 else if (!RTStrICmp(ValueUnion.psz, "headless"))
    447                 {
    448                     sessionType = "headless";
    449                 }
    450 #endif
    451                 else
    452                     return errorArgument("Invalid session type '%s'", ValueUnion.psz);
    453                 break;
    454 
    455             case VINF_GETOPT_NOT_OPTION:
    456                 if (!VMName)
    457                     VMName = ValueUnion.psz;
    458                 else
    459                     return errorSyntax(USAGE_STARTVM, "Invalid parameter '%s'", ValueUnion.psz);
    460                 break;
    461 
    462             default:
    463                 if (c > 0)
    464                 {
    465                     if (RT_C_IS_PRINT(c))
    466                         return errorSyntax(USAGE_STARTVM, "Invalid option -%c", c);
    467                     else
    468                         return errorSyntax(USAGE_STARTVM, "Invalid option case %i", c);
    469                 }
    470                 else if (c == VERR_GETOPT_UNKNOWN_OPTION)
    471                     return errorSyntax(USAGE_STARTVM, "unknown option: %s\n", ValueUnion.psz);
    472                 else if (ValueUnion.pDef)
    473                     return errorSyntax(USAGE_STARTVM, "%s: %Rrs", ValueUnion.pDef->pszLong, c);
    474                 else
    475                     return errorSyntax(USAGE_STARTVM, "error: %Rrs", c);
    476         }
    477     }
    478 
    479     /* check for required options */
    480     if (!VMName)
    481         return errorSyntax(USAGE_STARTVM, "VM name required");
    482 
    483     ComPtr<IMachine> machine;
    484     /* assume it's a UUID */
    485     rc = a->virtualBox->GetMachine(Guid(VMName).toUtf16(), machine.asOutParam());
    486     if (FAILED(rc) || !machine)
    487     {
    488         /* must be a name */
    489         CHECK_ERROR(a->virtualBox, FindMachine(Bstr(VMName), machine.asOutParam()));
    490     }
    491     if (machine)
    492     {
    493         Bstr uuid;
    494         machine->COMGETTER(Id)(uuid.asOutParam());
    495 
    496 
    497         Bstr env;
    498 #if defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS)
    499         /* make sure the VM process will start on the same display as VBoxManage */
    500         Utf8Str str;
    501         const char *pszDisplay = RTEnvGet("DISPLAY");
    502         if (pszDisplay)
    503             str = Utf8StrFmt("DISPLAY=%s\n", pszDisplay);
    504         const char *pszXAuth = RTEnvGet("XAUTHORITY");
    505         if (pszXAuth)
    506             str.append(Utf8StrFmt("XAUTHORITY=%s\n", pszXAuth));
    507         env = str;
    508 #endif
    509         ComPtr<IProgress> progress;
    510         CHECK_ERROR_RET(a->virtualBox, OpenRemoteSession(a->session, uuid, sessionType,
    511                                                          env, progress.asOutParam()), rc);
    512         RTPrintf("Waiting for the remote session to open...\n");
    513         CHECK_ERROR_RET(progress, WaitForCompletion (-1), 1);
    514 
    515         BOOL completed;
    516         CHECK_ERROR_RET(progress, COMGETTER(Completed)(&completed), rc);
    517         ASSERT(completed);
    518 
    519         LONG iRc;
    520         CHECK_ERROR_RET(progress, COMGETTER(ResultCode)(&iRc), rc);
    521         if (FAILED(iRc))
    522         {
    523             ComPtr <IVirtualBoxErrorInfo> errorInfo;
    524             CHECK_ERROR_RET(progress, COMGETTER(ErrorInfo)(errorInfo.asOutParam()), 1);
    525             ErrorInfo info (errorInfo);
    526             com::GluePrintErrorInfo(info);
    527         }
    528         else
    529         {
    530             RTPrintf("Remote session has been successfully opened.\n");
    531         }
    532     }
    533 
    534     /* it's important to always close sessions */
    535     a->session->Close();
    536 
    537     return SUCCEEDED(rc) ? 0 : 1;
    538 }
    539 
    540 static int handleControlVM(HandlerArg *a)
    541 {
     71    using namespace com;
    54272    HRESULT rc;
    54373
     
    1322852}
    1323853
    1324 static int handleDiscardState(HandlerArg *a)
    1325 {
    1326     HRESULT rc;
    1327 
    1328     if (a->argc != 1)
    1329         return errorSyntax(USAGE_DISCARDSTATE, "Incorrect number of parameters");
    1330 
    1331     ComPtr<IMachine> machine;
    1332     /* assume it's a UUID */
    1333     rc = a->virtualBox->GetMachine(Bstr(a->argv[0]), machine.asOutParam());
    1334     if (FAILED(rc) || !machine)
    1335     {
    1336         /* must be a name */
    1337         CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]), machine.asOutParam()));
    1338     }
    1339     if (machine)
    1340     {
    1341         do
    1342         {
    1343             /* we have to open a session for this task */
    1344             Bstr guid;
    1345             machine->COMGETTER(Id)(guid.asOutParam());
    1346             CHECK_ERROR_BREAK(a->virtualBox, OpenSession(a->session, guid));
    1347             do
    1348             {
    1349                 ComPtr<IConsole> console;
    1350                 CHECK_ERROR_BREAK(a->session, COMGETTER(Console)(console.asOutParam()));
    1351                 CHECK_ERROR_BREAK(console, ForgetSavedState(true));
    1352             } while (0);
    1353             CHECK_ERROR_BREAK(a->session, Close());
    1354         } while (0);
    1355     }
    1356 
    1357     return SUCCEEDED(rc) ? 0 : 1;
    1358 }
    1359 
    1360 static int handleAdoptdState(HandlerArg *a)
    1361 {
    1362     HRESULT rc;
    1363 
    1364     if (a->argc != 2)
    1365         return errorSyntax(USAGE_ADOPTSTATE, "Incorrect number of parameters");
    1366 
    1367     ComPtr<IMachine> machine;
    1368     /* assume it's a UUID */
    1369     rc = a->virtualBox->GetMachine(Bstr(a->argv[0]), machine.asOutParam());
    1370     if (FAILED(rc) || !machine)
    1371     {
    1372         /* must be a name */
    1373         CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]), machine.asOutParam()));
    1374     }
    1375     if (machine)
    1376     {
    1377         do
    1378         {
    1379             /* we have to open a session for this task */
    1380             Bstr guid;
    1381             machine->COMGETTER(Id)(guid.asOutParam());
    1382             CHECK_ERROR_BREAK(a->virtualBox, OpenSession(a->session, guid));
    1383             do
    1384             {
    1385                 ComPtr<IConsole> console;
    1386                 CHECK_ERROR_BREAK(a->session, COMGETTER(Console)(console.asOutParam()));
    1387                 CHECK_ERROR_BREAK(console, AdoptSavedState(Bstr(a->argv[1])));
    1388             } while (0);
    1389             CHECK_ERROR_BREAK(a->session, Close());
    1390         } while (0);
    1391     }
    1392 
    1393     return SUCCEEDED(rc) ? 0 : 1;
    1394 }
    1395 
    1396 static int handleGetExtraData(HandlerArg *a)
    1397 {
    1398     HRESULT rc = S_OK;
    1399 
    1400     if (a->argc != 2)
    1401         return errorSyntax(USAGE_GETEXTRADATA, "Incorrect number of parameters");
    1402 
    1403     /* global data? */
    1404     if (!strcmp(a->argv[0], "global"))
    1405     {
    1406         /* enumeration? */
    1407         if (!strcmp(a->argv[1], "enumerate"))
    1408         {
    1409             SafeArray<BSTR> aKeys;
    1410             CHECK_ERROR(a->virtualBox, GetExtraDataKeys(ComSafeArrayAsOutParam(aKeys)));
    1411 
    1412             for (size_t i = 0;
    1413                  i < aKeys.size();
    1414                  ++i)
    1415             {
    1416                 Bstr bstrKey(aKeys[i]);
    1417                 Bstr bstrValue;
    1418                 CHECK_ERROR(a->virtualBox, GetExtraData(bstrKey, bstrValue.asOutParam()));
    1419 
    1420                 RTPrintf("Key: %lS, Value: %lS\n", bstrKey.raw(), bstrValue.raw());
    1421             }
    1422         }
    1423         else
    1424         {
    1425             Bstr value;
    1426             CHECK_ERROR(a->virtualBox, GetExtraData(Bstr(a->argv[1]), value.asOutParam()));
    1427             if (!value.isEmpty())
    1428                 RTPrintf("Value: %lS\n", value.raw());
    1429             else
    1430                 RTPrintf("No value set!\n");
    1431         }
    1432     }
    1433     else
    1434     {
    1435         ComPtr<IMachine> machine;
    1436         /* assume it's a UUID */
    1437         rc = a->virtualBox->GetMachine(Bstr(a->argv[0]), machine.asOutParam());
    1438         if (FAILED(rc) || !machine)
    1439         {
    1440             /* must be a name */
    1441             CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]), machine.asOutParam()));
    1442         }
    1443         if (machine)
    1444         {
    1445             /* enumeration? */
    1446             if (!strcmp(a->argv[1], "enumerate"))
    1447             {
    1448                 SafeArray<BSTR> aKeys;
    1449                 CHECK_ERROR(machine, GetExtraDataKeys(ComSafeArrayAsOutParam(aKeys)));
    1450 
    1451                 for (size_t i = 0;
    1452                     i < aKeys.size();
    1453                     ++i)
    1454                 {
    1455                     Bstr bstrKey(aKeys[i]);
    1456                     Bstr bstrValue;
    1457                     CHECK_ERROR(machine, GetExtraData(bstrKey, bstrValue.asOutParam()));
    1458 
    1459                     RTPrintf("Key: %lS, Value: %lS\n", bstrKey.raw(), bstrValue.raw());
    1460                 }
    1461             }
    1462             else
    1463             {
    1464                 Bstr value;
    1465                 CHECK_ERROR(machine, GetExtraData(Bstr(a->argv[1]), value.asOutParam()));
    1466                 if (!value.isEmpty())
    1467                     RTPrintf("Value: %lS\n", value.raw());
    1468                 else
    1469                     RTPrintf("No value set!\n");
    1470             }
    1471         }
    1472     }
    1473     return SUCCEEDED(rc) ? 0 : 1;
    1474 }
    1475 
    1476 static int handleSetExtraData(HandlerArg *a)
    1477 {
    1478     HRESULT rc = S_OK;
    1479 
    1480     if (a->argc < 2)
    1481         return errorSyntax(USAGE_SETEXTRADATA, "Not enough parameters");
    1482 
    1483     /* global data? */
    1484     if (!strcmp(a->argv[0], "global"))
    1485     {
    1486         if (a->argc < 3)
    1487             CHECK_ERROR(a->virtualBox, SetExtraData(Bstr(a->argv[1]), NULL));
    1488         else if (a->argc == 3)
    1489             CHECK_ERROR(a->virtualBox, SetExtraData(Bstr(a->argv[1]), Bstr(a->argv[2])));
    1490         else
    1491             return errorSyntax(USAGE_SETEXTRADATA, "Too many parameters");
    1492     }
    1493     else
    1494     {
    1495         ComPtr<IMachine> machine;
    1496         /* assume it's a UUID */
    1497         rc = a->virtualBox->GetMachine(Bstr(a->argv[0]), machine.asOutParam());
    1498         if (FAILED(rc) || !machine)
    1499         {
    1500             /* must be a name */
    1501             CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]), machine.asOutParam()));
    1502         }
    1503         if (machine)
    1504         {
    1505             if (a->argc < 3)
    1506                 CHECK_ERROR(machine, SetExtraData(Bstr(a->argv[1]), NULL));
    1507             else if (a->argc == 3)
    1508                 CHECK_ERROR(machine, SetExtraData(Bstr(a->argv[1]), Bstr(a->argv[2])));
    1509             else
    1510                 return errorSyntax(USAGE_SETEXTRADATA, "Too many parameters");
    1511         }
    1512     }
    1513     return SUCCEEDED(rc) ? 0 : 1;
    1514 }
    1515 
    1516 static int handleSetProperty(HandlerArg *a)
    1517 {
    1518     HRESULT rc;
    1519 
    1520     /* there must be two arguments: property name and value */
    1521     if (a->argc != 2)
    1522         return errorSyntax(USAGE_SETPROPERTY, "Incorrect number of parameters");
    1523 
    1524     ComPtr<ISystemProperties> systemProperties;
    1525     a->virtualBox->COMGETTER(SystemProperties)(systemProperties.asOutParam());
    1526 
    1527     if (!strcmp(a->argv[0], "hdfolder"))
    1528     {
    1529         /* reset to default? */
    1530         if (!strcmp(a->argv[1], "default"))
    1531             CHECK_ERROR(systemProperties, COMSETTER(DefaultHardDiskFolder)(NULL));
    1532         else
    1533             CHECK_ERROR(systemProperties, COMSETTER(DefaultHardDiskFolder)(Bstr(a->argv[1])));
    1534     }
    1535     else if (!strcmp(a->argv[0], "machinefolder"))
    1536     {
    1537         /* reset to default? */
    1538         if (!strcmp(a->argv[1], "default"))
    1539             CHECK_ERROR(systemProperties, COMSETTER(DefaultMachineFolder)(NULL));
    1540         else
    1541             CHECK_ERROR(systemProperties, COMSETTER(DefaultMachineFolder)(Bstr(a->argv[1])));
    1542     }
    1543     else if (!strcmp(a->argv[0], "vrdpauthlibrary"))
    1544     {
    1545         /* reset to default? */
    1546         if (!strcmp(a->argv[1], "default"))
    1547             CHECK_ERROR(systemProperties, COMSETTER(RemoteDisplayAuthLibrary)(NULL));
    1548         else
    1549             CHECK_ERROR(systemProperties, COMSETTER(RemoteDisplayAuthLibrary)(Bstr(a->argv[1])));
    1550     }
    1551     else if (!strcmp(a->argv[0], "websrvauthlibrary"))
    1552     {
    1553         /* reset to default? */
    1554         if (!strcmp(a->argv[1], "default"))
    1555             CHECK_ERROR(systemProperties, COMSETTER(WebServiceAuthLibrary)(NULL));
    1556         else
    1557             CHECK_ERROR(systemProperties, COMSETTER(WebServiceAuthLibrary)(Bstr(a->argv[1])));
    1558     }
    1559     else if (!strcmp(a->argv[0], "loghistorycount"))
    1560     {
    1561         uint32_t uVal;
    1562         int vrc;
    1563         vrc = RTStrToUInt32Ex(a->argv[1], NULL, 0, &uVal);
    1564         if (vrc != VINF_SUCCESS)
    1565             return errorArgument("Error parsing Log history count '%s'", a->argv[1]);
    1566         CHECK_ERROR(systemProperties, COMSETTER(LogHistoryCount)(uVal));
    1567     }
    1568     else
    1569         return errorSyntax(USAGE_SETPROPERTY, "Invalid parameter '%s'", a->argv[0]);
    1570 
    1571     return SUCCEEDED(rc) ? 0 : 1;
    1572 }
    1573 
    1574 static int handleSharedFolder(HandlerArg *a)
    1575 {
    1576     HRESULT rc;
    1577 
    1578     /* we need at least a command and target */
    1579     if (a->argc < 2)
    1580         return errorSyntax(USAGE_SHAREDFOLDER, "Not enough parameters");
    1581 
    1582     ComPtr<IMachine> machine;
    1583     /* assume it's a UUID */
    1584     rc = a->virtualBox->GetMachine(Bstr(a->argv[1]), machine.asOutParam());
    1585     if (FAILED(rc) || !machine)
    1586     {
    1587         /* must be a name */
    1588         CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[1]), machine.asOutParam()));
    1589     }
    1590     if (!machine)
    1591         return 1;
    1592     Bstr uuid;
    1593     machine->COMGETTER(Id)(uuid.asOutParam());
    1594 
    1595     if (!strcmp(a->argv[0], "add"))
    1596     {
    1597         /* we need at least four more parameters */
    1598         if (a->argc < 5)
    1599             return errorSyntax(USAGE_SHAREDFOLDER_ADD, "Not enough parameters");
    1600 
    1601         char *name = NULL;
    1602         char *hostpath = NULL;
    1603         bool fTransient = false;
    1604         bool fWritable = true;
    1605 
    1606         for (int i = 2; i < a->argc; i++)
    1607         {
    1608             if (   !strcmp(a->argv[i], "--name")
    1609                 || !strcmp(a->argv[i], "-name"))
    1610             {
    1611                 if (a->argc <= i + 1 || !*a->argv[i+1])
    1612                     return errorArgument("Missing argument to '%s'", a->argv[i]);
    1613                 i++;
    1614                 name = a->argv[i];
    1615             }
    1616             else if (   !strcmp(a->argv[i], "--hostpath")
    1617                      || !strcmp(a->argv[i], "-hostpath"))
    1618             {
    1619                 if (a->argc <= i + 1 || !*a->argv[i+1])
    1620                     return errorArgument("Missing argument to '%s'", a->argv[i]);
    1621                 i++;
    1622                 hostpath = a->argv[i];
    1623             }
    1624             else if (   !strcmp(a->argv[i], "--readonly")
    1625                      || !strcmp(a->argv[i], "-readonly"))
    1626             {
    1627                 fWritable = false;
    1628             }
    1629             else if (   !strcmp(a->argv[i], "--transient")
    1630                      || !strcmp(a->argv[i], "-transient"))
    1631             {
    1632                 fTransient = true;
    1633             }
    1634             else
    1635                 return errorSyntax(USAGE_SHAREDFOLDER_ADD, "Invalid parameter '%s'", Utf8Str(a->argv[i]).raw());
    1636         }
    1637 
    1638         if (NULL != strstr(name, " "))
    1639             return errorSyntax(USAGE_SHAREDFOLDER_ADD, "No spaces allowed in parameter '-name'!");
    1640 
    1641         /* required arguments */
    1642         if (!name || !hostpath)
    1643         {
    1644             return errorSyntax(USAGE_SHAREDFOLDER_ADD, "Parameters --name and --hostpath are required");
    1645         }
    1646 
    1647         if (fTransient)
    1648         {
    1649             ComPtr <IConsole> console;
    1650 
    1651             /* open an existing session for the VM */
    1652             CHECK_ERROR_RET(a->virtualBox, OpenExistingSession(a->session, uuid), 1);
    1653             /* get the session machine */
    1654             CHECK_ERROR_RET(a->session, COMGETTER(Machine)(machine.asOutParam()), 1);
    1655             /* get the session console */
    1656             CHECK_ERROR_RET(a->session, COMGETTER(Console)(console.asOutParam()), 1);
    1657 
    1658             CHECK_ERROR(console, CreateSharedFolder(Bstr(name), Bstr(hostpath), fWritable));
    1659 
    1660             if (console)
    1661                 a->session->Close();
    1662         }
    1663         else
    1664         {
    1665             /* open a session for the VM */
    1666             CHECK_ERROR_RET(a->virtualBox, OpenSession(a->session, uuid), 1);
    1667 
    1668             /* get the mutable session machine */
    1669             a->session->COMGETTER(Machine)(machine.asOutParam());
    1670 
    1671             CHECK_ERROR(machine, CreateSharedFolder(Bstr(name), Bstr(hostpath), fWritable));
    1672 
    1673             if (SUCCEEDED(rc))
    1674                 CHECK_ERROR(machine, SaveSettings());
    1675 
    1676             a->session->Close();
    1677         }
    1678     }
    1679     else if (!strcmp(a->argv[0], "remove"))
    1680     {
    1681         /* we need at least two more parameters */
    1682         if (a->argc < 3)
    1683             return errorSyntax(USAGE_SHAREDFOLDER_REMOVE, "Not enough parameters");
    1684 
    1685         char *name = NULL;
    1686         bool fTransient = false;
    1687 
    1688         for (int i = 2; i < a->argc; i++)
    1689         {
    1690             if (   !strcmp(a->argv[i], "--name")
    1691                 || !strcmp(a->argv[i], "-name"))
    1692             {
    1693                 if (a->argc <= i + 1 || !*a->argv[i+1])
    1694                     return errorArgument("Missing argument to '%s'", a->argv[i]);
    1695                 i++;
    1696                 name = a->argv[i];
    1697             }
    1698             else if (   !strcmp(a->argv[i], "--transient")
    1699                      || !strcmp(a->argv[i], "-transient"))
    1700             {
    1701                 fTransient = true;
    1702             }
    1703             else
    1704                 return errorSyntax(USAGE_SHAREDFOLDER_REMOVE, "Invalid parameter '%s'", Utf8Str(a->argv[i]).raw());
    1705         }
    1706 
    1707         /* required arguments */
    1708         if (!name)
    1709             return errorSyntax(USAGE_SHAREDFOLDER_REMOVE, "Parameter --name is required");
    1710 
    1711         if (fTransient)
    1712         {
    1713             ComPtr <IConsole> console;
    1714 
    1715             /* open an existing session for the VM */
    1716             CHECK_ERROR_RET(a->virtualBox, OpenExistingSession(a->session, uuid), 1);
    1717             /* get the session machine */
    1718             CHECK_ERROR_RET(a->session, COMGETTER(Machine)(machine.asOutParam()), 1);
    1719             /* get the session console */
    1720             CHECK_ERROR_RET(a->session, COMGETTER(Console)(console.asOutParam()), 1);
    1721 
    1722             CHECK_ERROR(console, RemoveSharedFolder(Bstr(name)));
    1723 
    1724             if (console)
    1725                 a->session->Close();
    1726         }
    1727         else
    1728         {
    1729             /* open a session for the VM */
    1730             CHECK_ERROR_RET(a->virtualBox, OpenSession(a->session, uuid), 1);
    1731 
    1732             /* get the mutable session machine */
    1733             a->session->COMGETTER(Machine)(machine.asOutParam());
    1734 
    1735             CHECK_ERROR(machine, RemoveSharedFolder(Bstr(name)));
    1736 
    1737             /* commit and close the session */
    1738             CHECK_ERROR(machine, SaveSettings());
    1739             a->session->Close();
    1740         }
    1741     }
    1742     else
    1743         return errorSyntax(USAGE_SETPROPERTY, "Invalid parameter '%s'", Utf8Str(a->argv[0]).raw());
    1744 
    1745     return 0;
    1746 }
    1747 
    1748 static int handleVMStatistics(HandlerArg *a)
    1749 {
    1750     HRESULT rc;
    1751 
    1752     /* at least one option: the UUID or name of the VM */
    1753     if (a->argc < 1)
    1754         return errorSyntax(USAGE_VM_STATISTICS, "Incorrect number of parameters");
    1755 
    1756     /* try to find the given machine */
    1757     ComPtr <IMachine> machine;
    1758     Bstr uuid (a->argv[0]);
    1759     if (!Guid (a->argv[0]).isEmpty())
    1760         CHECK_ERROR(a->virtualBox, GetMachine(uuid, machine.asOutParam()));
    1761     else
    1762     {
    1763         CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]), machine.asOutParam()));
    1764         if (SUCCEEDED (rc))
    1765             machine->COMGETTER(Id)(uuid.asOutParam());
    1766     }
    1767     if (FAILED(rc))
    1768         return 1;
    1769 
    1770     /* parse arguments. */
    1771     bool fReset = false;
    1772     bool fWithDescriptions = false;
    1773     const char *pszPattern = NULL; /* all */
    1774     for (int i = 1; i < a->argc; i++)
    1775     {
    1776         if (   !strcmp(a->argv[i], "--pattern")
    1777             || !strcmp(a->argv[i], "-pattern"))
    1778         {
    1779             if (pszPattern)
    1780                 return errorSyntax(USAGE_VM_STATISTICS, "Multiple --patterns options is not permitted");
    1781             if (i + 1 >= a->argc)
    1782                 return errorArgument("Missing argument to '%s'", a->argv[i]);
    1783             pszPattern = a->argv[++i];
    1784         }
    1785         else if (   !strcmp(a->argv[i], "--descriptions")
    1786                  || !strcmp(a->argv[i], "-descriptions"))
    1787             fWithDescriptions = true;
    1788         /* add: --file <filename> and --formatted */
    1789         else if (   !strcmp(a->argv[i], "--reset")
    1790                  || !strcmp(a->argv[i], "-reset"))
    1791             fReset = true;
    1792         else
    1793             return errorSyntax(USAGE_VM_STATISTICS, "Unknown option '%s'", a->argv[i]);
    1794     }
    1795     if (fReset && fWithDescriptions)
    1796         return errorSyntax(USAGE_VM_STATISTICS, "The --reset and --descriptions options does not mix");
    1797 
    1798 
    1799     /* open an existing session for the VM. */
    1800     CHECK_ERROR(a->virtualBox, OpenExistingSession(a->session, uuid));
    1801     if (SUCCEEDED(rc))
    1802     {
    1803         /* get the session console. */
    1804         ComPtr <IConsole> console;
    1805         CHECK_ERROR(a->session, COMGETTER(Console)(console.asOutParam()));
    1806         if (SUCCEEDED(rc))
    1807         {
    1808             /* get the machine debugger. */
    1809             ComPtr <IMachineDebugger> debugger;
    1810             CHECK_ERROR(console, COMGETTER(Debugger)(debugger.asOutParam()));
    1811             if (SUCCEEDED(rc))
    1812             {
    1813                 if (fReset)
    1814                     CHECK_ERROR(debugger, ResetStats(Bstr(pszPattern)));
    1815                 else
    1816                 {
    1817                     Bstr stats;
    1818                     CHECK_ERROR(debugger, GetStats(Bstr(pszPattern), fWithDescriptions, stats.asOutParam()));
    1819                     if (SUCCEEDED(rc))
    1820                     {
    1821                         /* if (fFormatted)
    1822                          { big mess }
    1823                          else
    1824                          */
    1825                         RTPrintf("%ls\n", stats.raw());
    1826                     }
    1827                 }
    1828             }
    1829             a->session->Close();
    1830         }
    1831     }
    1832 
    1833     return SUCCEEDED(rc) ? 0 : 1;
    1834 }
    1835 #endif /* !VBOX_ONLY_DOCS */
    1836 
    1837 // main
    1838 ///////////////////////////////////////////////////////////////////////////////
    1839 
    1840 int main(int argc, char *argv[])
    1841 {
    1842     /*
    1843      * Before we do anything, init the runtime without loading
    1844      * the support driver.
    1845      */
    1846     RTR3Init();
    1847 
    1848     bool fShowLogo = true;
    1849     int  iCmd      = 1;
    1850     int  iCmdArg;
    1851 
    1852     /* global options */
    1853     for (int i = 1; i < argc || argc <= iCmd; i++)
    1854     {
    1855         if (    argc <= iCmd
    1856             ||  !strcmp(argv[i], "help")
    1857             ||  !strcmp(argv[i], "-?")
    1858             ||  !strcmp(argv[i], "-h")
    1859             ||  !strcmp(argv[i], "-help")
    1860             ||  !strcmp(argv[i], "--help"))
    1861         {
    1862             showLogo();
    1863             printUsage(USAGE_ALL);
    1864             return 0;
    1865         }
    1866 
    1867         if (   !strcmp(argv[i], "-v")
    1868             || !strcmp(argv[i], "-version")
    1869             || !strcmp(argv[i], "-Version")
    1870             || !strcmp(argv[i], "--version"))
    1871         {
    1872             /* Print version number, and do nothing else. */
    1873             RTPrintf("%sr%d\n", VBOX_VERSION_STRING, RTBldCfgRevision());
    1874             return 0;
    1875         }
    1876 
    1877         if (   !strcmp(argv[i], "--dumpopts")
    1878             || !strcmp(argv[i], "-dumpopts"))
    1879         {
    1880             /* Special option to dump really all commands,
    1881              * even the ones not understood on this platform. */
    1882             printUsage(USAGE_DUMPOPTS);
    1883             return 0;
    1884         }
    1885 
    1886         if (   !strcmp(argv[i], "--nologo")
    1887             || !strcmp(argv[i], "-nologo")
    1888             || !strcmp(argv[i], "-q"))
    1889         {
    1890             /* suppress the logo */
    1891             fShowLogo = false;
    1892             iCmd++;
    1893         }
    1894         else
    1895         {
    1896             break;
    1897         }
    1898     }
    1899 
    1900     iCmdArg = iCmd + 1;
    1901 
    1902     if (fShowLogo)
    1903         showLogo();
    1904 
    1905 
    1906 #ifdef VBOX_ONLY_DOCS
    1907     int rc = 0;
    1908 #else /* !VBOX_ONLY_DOCS */
    1909     HRESULT rc = 0;
    1910 
    1911     rc = com::Initialize();
    1912     if (FAILED(rc))
    1913     {
    1914         RTPrintf("ERROR: failed to initialize COM!\n");
    1915         return rc;
    1916     }
    1917 
    1918     /*
    1919      * The input is in the host OS'es codepage (NT guarantees ACP).
    1920      * For VBox we use UTF-8 and convert to UCS-2 when calling (XP)COM APIs.
    1921      * For simplicity, just convert the argv[] array here.
    1922      */
    1923     for (int i = iCmdArg; i < argc; i++)
    1924     {
    1925         char *converted;
    1926         RTStrCurrentCPToUtf8(&converted, argv[i]);
    1927         argv[i] = converted;
    1928     }
    1929 
    1930     do
    1931     {
    1932     // scopes all the stuff till shutdown
    1933     ////////////////////////////////////////////////////////////////////////////
    1934 
    1935     /* convertfromraw: does not need a VirtualBox instantiation. */
    1936     if (argc >= iCmdArg && (   !strcmp(argv[iCmd], "convertfromraw")
    1937                             || !strcmp(argv[iCmd], "convertdd")))
    1938     {
    1939         rc = handleConvertFromRaw(argc - iCmdArg, argv + iCmdArg);
    1940         break;
    1941     }
    1942 
    1943     ComPtr<IVirtualBox> virtualBox;
    1944     ComPtr<ISession> session;
    1945 
    1946     rc = virtualBox.createLocalObject(CLSID_VirtualBox);
    1947     if (FAILED(rc))
    1948         RTPrintf("ERROR: failed to create the VirtualBox object!\n");
    1949     else
    1950     {
    1951         rc = session.createInprocObject(CLSID_Session);
    1952         if (FAILED(rc))
    1953             RTPrintf("ERROR: failed to create a session object!\n");
    1954     }
    1955 
    1956     if (FAILED(rc))
    1957     {
    1958         com::ErrorInfo info;
    1959         if (!info.isFullAvailable() && !info.isBasicAvailable())
    1960         {
    1961             com::GluePrintRCMessage(rc);
    1962             RTPrintf("Most likely, the VirtualBox COM server is not running or failed to start.\n");
    1963         }
    1964         else
    1965             com::GluePrintErrorInfo(info);
    1966         break;
    1967     }
    1968 
    1969     HandlerArg handlerArg = { 0, NULL, virtualBox, session };
    1970 
    1971     /*
    1972      * All registered command handlers
    1973      */
    1974     static const struct
    1975     {
    1976         const char *command;
    1977         int (*handler)(HandlerArg *a);
    1978     } s_commandHandlers[] =
    1979     {
    1980         { "internalcommands", handleInternalCommands },
    1981         { "list",             handleList },
    1982         { "showvminfo",       handleShowVMInfo },
    1983         { "registervm",       handleRegisterVM },
    1984         { "unregistervm",     handleUnregisterVM },
    1985         { "createhd",         handleCreateHardDisk },
    1986         { "createvdi",        handleCreateHardDisk }, /* backward compatiblity */
    1987         { "modifyhd",         handleModifyHardDisk },
    1988         { "modifyvdi",        handleModifyHardDisk }, /* backward compatiblity */
    1989         { "clonehd",          handleCloneHardDisk },
    1990         { "clonevdi",         handleCloneHardDisk }, /* backward compatiblity */
    1991         { "addiscsidisk",     handleAddiSCSIDisk },
    1992         { "createvm",         handleCreateVM },
    1993         { "modifyvm",         handleModifyVM },
    1994         { "startvm",          handleStartVM },
    1995         { "controlvm",        handleControlVM },
    1996         { "discardstate",     handleDiscardState },
    1997         { "adoptstate",       handleAdoptdState },
    1998         { "snapshot",         handleSnapshot },
    1999         { "openmedium",       handleOpenMedium },
    2000         { "registerimage",    handleOpenMedium }, /* backward compatiblity */
    2001         { "closemedium",      handleCloseMedium },
    2002         { "unregisterimage",  handleCloseMedium }, /* backward compatiblity */
    2003         { "storageattach",    handleStorageAttach },
    2004         { "storagectl",       handleStorageController },
    2005         { "showhdinfo",       handleShowHardDiskInfo },
    2006         { "showvdiinfo",      handleShowHardDiskInfo }, /* backward compatiblity */
    2007         { "getextradata",     handleGetExtraData },
    2008         { "setextradata",     handleSetExtraData },
    2009         { "setproperty",      handleSetProperty },
    2010         { "usbfilter",        handleUSBFilter },
    2011         { "sharedfolder",     handleSharedFolder },
    2012         { "vmstatistics",     handleVMStatistics },
    2013 #ifdef VBOX_WITH_GUEST_PROPS
    2014         { "guestproperty",    handleGuestProperty },
    2015 #endif
    2016         { "metrics",          handleMetrics },
    2017         { "import",           handleImportAppliance },
    2018         { "export",           handleExportAppliance },
    2019 #ifdef VBOX_WITH_NETFLT
    2020         { "hostonlyif",       handleHostonlyIf },
    2021 #endif
    2022         { "dhcpserver",       handleDHCPServer},
    2023         { NULL,               NULL }
    2024     };
    2025 
    2026     int commandIndex;
    2027     for (commandIndex = 0; s_commandHandlers[commandIndex].command != NULL; commandIndex++)
    2028     {
    2029         if (!strcmp(s_commandHandlers[commandIndex].command, argv[iCmd]))
    2030         {
    2031             handlerArg.argc = argc - iCmdArg;
    2032             handlerArg.argv = &argv[iCmdArg];
    2033 
    2034             rc = s_commandHandlers[commandIndex].handler(&handlerArg);
    2035             break;
    2036         }
    2037     }
    2038     if (!s_commandHandlers[commandIndex].command)
    2039     {
    2040         rc = errorSyntax(USAGE_ALL, "Invalid command '%s'", Utf8Str(argv[iCmd]).raw());
    2041     }
    2042 
    2043     /* Although all handlers should always close the session if they open it,
    2044      * we do it here just in case if some of the handlers contains a bug --
    2045      * leaving the direct session not closed will turn the machine state to
    2046      * Aborted which may have unwanted side effects like killing the saved
    2047      * state file (if the machine was in the Saved state before). */
    2048     session->Close();
    2049 
    2050     EventQueue::getMainEventQueue()->processEventQueue(0);
    2051     // end "all-stuff" scope
    2052     ////////////////////////////////////////////////////////////////////////////
    2053     } while (0);
    2054 
    2055     com::Shutdown();
    2056 #endif /* !VBOX_ONLY_DOCS */
    2057 
    2058     /*
    2059      * Free converted argument vector
    2060      */
    2061     for (int i = iCmdArg; i < argc; i++)
    2062         RTStrFree(argv[i]);
    2063 
    2064     return rc != 0;
    2065 }
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