- Timestamp:
- Nov 24, 2009 2:07:11 PM (15 years ago)
- Location:
- trunk/src/VBox/Frontends/VBoxManage
- Files:
-
- 3 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VBoxManage/Makefile.kmk
r23802 r24903 58 58 VBoxManage_SOURCES = \ 59 59 VBoxManage.cpp \ 60 VBoxInternalManage.cpp \ 61 VBoxManageControlVM.cpp \ 62 VBoxManageDHCPServer.cpp \ 63 VBoxManageDisk.cpp \ 64 $(if $(VBOX_WITH_GUEST_PROPS),VBoxManageGuestProp.cpp) \ 60 65 VBoxManageHelp.cpp \ 66 VBoxManageHostonly.cpp \ 67 VBoxManageImport.cpp \ 68 VBoxManageInfo.cpp \ 69 VBoxManageList.cpp \ 70 VBoxManageMetrics.cpp \ 61 71 VBoxManageModifyVM.cpp \ 62 VBoxManageInfo.cpp \ 63 VBoxManageImport.cpp \ 64 VBoxManageMetrics.cpp \ 65 VBoxManageList.cpp \ 66 VBoxManageDisk.cpp \ 72 VBoxManageSnapshot.cpp \ 67 73 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 74 75 endif # !VBOX_ONLY_DOCS 75 76 ifneq ($(KBUILD_TARGET),win) -
trunk/src/VBox/Frontends/VBoxManage/VBoxManage.cpp
r24901 r24903 374 374 } 375 375 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 >= 1391 && 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 #endif402 403 static const RTGETOPTDEF g_aStartVMOptions[] =404 {405 { "--type", 't', RTGETOPT_REQ_STRING },406 { "-type", 't', RTGETOPT_REQ_STRING }, // deprecated407 };408 409 376 static int handleStartVM(HandlerArg *a) 410 377 { … … 413 380 Bstr sessionType = "gui"; 414 381 382 static const RTGETOPTDEF s_aStartVMOptions[] = 383 { 384 { "--type", 't', RTGETOPT_REQ_STRING }, 385 { "-type", 't', RTGETOPT_REQ_STRING }, // deprecated 386 }; 415 387 int c; 416 388 RTGETOPTUNION ValueUnion; 417 389 RTGETOPTSTATE GetState; 418 390 // 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 */); 420 392 while ((c = RTGetOpt(&GetState, &ValueUnion))) 421 393 { … … 533 505 534 506 /* 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 else555 {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 do567 {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 else602 {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 else621 {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 else677 {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 else738 {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_ATTACH746 /* here the order in which strncmp is called is important747 * cause nictracefile can be very well compared with748 * nictrace and nic and thus everything will always fail749 * if the order is changed750 */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 else786 {787 errorArgument("Invalid filename or filename not specified for NIC %lu", n);788 rc = E_FAIL;789 break;790 }791 }792 else793 {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 else837 {838 errorArgument("Invalid nictrace%lu argument '%s'", n, Utf8Str(a->argv[2]).raw());839 rc = E_FAIL;840 break;841 }842 }843 else844 {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 #endif930 else931 {932 errorArgument("Invalid type '%s' specfied for NIC %lu", Utf8Str(a->argv[2]).raw(), n);933 rc = E_FAIL;934 break;935 }936 }937 else938 {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_VRDP945 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 else968 {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 else994 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 address1016 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 else1027 {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 else1040 {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 else1123 {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 drives1146 * and as a consequence multiple attachments and different1147 * storage controllers. */1148 if (dvdMedium)1149 dvdMedium->COMGETTER(Id)(uuid.asOutParam());1150 else1151 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 else1186 {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_BALLOONING1211 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 #endif1238 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 else1309 RTPrintf("Error: teleportation failed. No error message available!\n");1310 }1311 }1312 else1313 {1314 errorSyntax(USAGE_CONTROLVM, "Invalid parameter '%s'", Utf8Str(a->argv[1]).raw());1315 rc = E_FAIL;1316 }1317 } while (0);1318 1319 507 a->session->Close(); 1320 508 -
trunk/src/VBox/Frontends/VBoxManage/VBoxManage.h
r24879 r24903 156 156 #ifndef VBOX_ONLY_DOCS 157 157 int handleInternalCommands(HandlerArg *a); 158 159 unsigned parseNum(const char *psz, unsigned cMaxNum, const char *name);160 158 #endif /* !VBOX_ONLY_DOCS */ 159 160 /* VBoxManageControlVM.cpp */ 161 int handleControlVM(HandlerArg *a); 161 162 162 163 /* VBoxManageModifyVM.cpp */ -
trunk/src/VBox/Frontends/VBoxManage/VBoxManageControlVM.cpp
r24901 r24903 24 24 * Header Files * 25 25 *******************************************************************************/ 26 #ifndef VBOX_ONLY_DOCS27 26 #include <VBox/com/com.h> 28 27 #include <VBox/com/string.h> … … 35 34 #include <VBox/com/VirtualBox.h> 36 35 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>44 36 #include <iprt/ctype.h> 45 #include <iprt/dir.h>46 #include <iprt/env.h>47 37 #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> 52 39 #include <iprt/stream.h> 53 40 #include <iprt/string.h> 54 #include <iprt/stdarg.h>55 #include <iprt/thread.h>56 41 #include <iprt/uuid.h> 57 #include <iprt/getopt.h>58 #include <iprt/ctype.h>59 #include <VBox/version.h>60 42 #include <VBox/log.h> 61 43 62 44 #include "VBoxManage.h" 63 45 64 #ifndef VBOX_ONLY_DOCS65 using namespace com;66 #endif /* !VBOX_ONLY_DOCS */67 68 /*******************************************************************************69 * Global Variables *70 *******************************************************************************/71 /*extern*/ bool g_fDetailedProgress = false;72 73 ////////////////////////////////////////////////////////////////////////////////74 //75 // functions76 //77 ////////////////////////////////////////////////////////////////////////////////78 79 #ifndef VBOX_ONLY_DOCS80 /**81 * Print out progress on the console82 */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 print118 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 else134 {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 else164 RTPrintf("FAILED\n");165 }166 else167 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 paths181 * and the client's interpretation of relative paths. Remove after the API182 * 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 }, // deprecated209 };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 us221 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': // --delete227 fDelete = true;228 break;229 230 case VINF_GETOPT_NOT_OPTION:231 if (!VMName)232 VMName = ValueUnion.psz;233 else234 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 else243 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 else250 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 else338 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 do347 {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 else354 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 }375 46 376 47 /** … … 381 52 * @param psz Pointer to the nic number. 382 53 */ 383 unsigned parseNum(const char *psz, unsigned cMaxNum, const char *name)54 static unsigned parseNum(const char *psz, unsigned cMaxNum, const char *name) 384 55 { 385 56 uint32_t u32; … … 396 67 397 68 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[] = 69 int handleControlVM(HandlerArg *a) 404 70 { 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; 542 72 HRESULT rc; 543 73 … … 1322 852 } 1323 853 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 do1342 {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 do1348 {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 do1378 {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 do1384 {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 else1424 {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 else1430 RTPrintf("No value set!\n");1431 }1432 }1433 else1434 {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 else1463 {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 else1469 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 else1491 return errorSyntax(USAGE_SETEXTRADATA, "Too many parameters");1492 }1493 else1494 {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 else1510 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 else1533 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 else1541 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 else1549 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 else1557 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 else1569 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 else1635 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 else1664 {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 else1704 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 else1728 {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 else1743 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 else1762 {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 else1793 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 else1816 {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 else1824 */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 // main1838 ///////////////////////////////////////////////////////////////////////////////1839 1840 int main(int argc, char *argv[])1841 {1842 /*1843 * Before we do anything, init the runtime without loading1844 * 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 <= iCmd1856 || !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 else1895 {1896 break;1897 }1898 }1899 1900 iCmdArg = iCmd + 1;1901 1902 if (fShowLogo)1903 showLogo();1904 1905 1906 #ifdef VBOX_ONLY_DOCS1907 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 do1931 {1932 // scopes all the stuff till shutdown1933 ////////////////////////////////////////////////////////////////////////////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 else1950 {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 else1965 com::GluePrintErrorInfo(info);1966 break;1967 }1968 1969 HandlerArg handlerArg = { 0, NULL, virtualBox, session };1970 1971 /*1972 * All registered command handlers1973 */1974 static const struct1975 {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_PROPS2014 { "guestproperty", handleGuestProperty },2015 #endif2016 { "metrics", handleMetrics },2017 { "import", handleImportAppliance },2018 { "export", handleExportAppliance },2019 #ifdef VBOX_WITH_NETFLT2020 { "hostonlyif", handleHostonlyIf },2021 #endif2022 { "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 to2046 * Aborted which may have unwanted side effects like killing the saved2047 * state file (if the machine was in the Saved state before). */2048 session->Close();2049 2050 EventQueue::getMainEventQueue()->processEventQueue(0);2051 // end "all-stuff" scope2052 ////////////////////////////////////////////////////////////////////////////2053 } while (0);2054 2055 com::Shutdown();2056 #endif /* !VBOX_ONLY_DOCS */2057 2058 /*2059 * Free converted argument vector2060 */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.