168
/* process async cancelation */
169
if (g_fCanceled && !fCanceledAlready)
171
hrc = progress->Cancel();
173
fCanceledAlready = true;
159
178
/* make sure the loop is not too tight */
160
179
progress->WaitForCompletion(100);
182
/* undo signal handling */
185
signal(SIGINT, SIG_DFL);
187
signal(SIGBREAK, SIG_DFL);
163
191
/* complete the line. */
165
193
if (SUCCEEDED(progress->COMGETTER(ResultCode)(&iRc)))
167
195
if (SUCCEEDED(iRc))
168
196
RTPrintf("100%%\n");
197
else if (g_fCanceled)
198
RTPrintf("CANCELED\n");
170
200
RTPrintf("FAILED\n");
174
204
RTStrmFlush(g_pStdOut);
176
#endif /* !VBOX_ONLY_DOCS */
180
static bool fShown; /* show only once */
184
RTPrintf("VirtualBox Command Line Management Interface Version "
185
VBOX_VERSION_STRING "\n"
186
"(C) 2005-2009 Sun Microsystems, Inc.\n"
187
"All rights reserved.\n"
193
#ifndef VBOX_ONLY_DOCS
195
static int handleRegisterVM(HandlerArg *a)
200
return errorSyntax(USAGE_REGISTERVM, "Incorrect number of parameters");
202
ComPtr<IMachine> machine;
203
/** @todo Ugly hack to get both the API interpretation of relative paths
204
* and the client's interpretation of relative paths. Remove after the API
205
* has been redesigned. */
206
rc = a->virtualBox->OpenMachine(Bstr(a->argv[0]), machine.asOutParam());
207
if (rc == VBOX_E_FILE_ERROR)
209
char szVMFileAbs[RTPATH_MAX] = "";
210
int vrc = RTPathAbs(a->argv[0], szVMFileAbs, sizeof(szVMFileAbs));
213
RTPrintf("Cannot convert filename \"%s\" to absolute path\n", a->argv[0]);
216
CHECK_ERROR(a->virtualBox, OpenMachine(Bstr(szVMFileAbs), machine.asOutParam()));
219
CHECK_ERROR(a->virtualBox, OpenMachine(Bstr(a->argv[0]), machine.asOutParam()));
223
CHECK_ERROR(a->virtualBox, RegisterMachine(machine));
225
return SUCCEEDED(rc) ? 0 : 1;
228
static const RTGETOPTDEF g_aUnregisterVMOptions[] =
230
{ "--delete", 'd', RTGETOPT_REQ_NOTHING },
231
{ "-delete", 'd', RTGETOPT_REQ_NOTHING }, // deprecated
234
static int handleUnregisterVM(HandlerArg *a)
237
const char *VMName = NULL;
238
bool fDelete = false;
241
RTGETOPTUNION ValueUnion;
242
RTGETOPTSTATE GetState;
243
// start at 0 because main() has hacked both the argc and argv given to us
244
RTGetOptInit(&GetState, a->argc, a->argv, g_aUnregisterVMOptions, RT_ELEMENTS(g_aUnregisterVMOptions), 0, 0 /* fFlags */);
245
while ((c = RTGetOpt(&GetState, &ValueUnion)))
249
case 'd': // --delete
253
case VINF_GETOPT_NOT_OPTION:
255
VMName = ValueUnion.psz;
257
return errorSyntax(USAGE_UNREGISTERVM, "Invalid parameter '%s'", ValueUnion.psz);
263
if (RT_C_IS_PRINT(c))
264
return errorSyntax(USAGE_UNREGISTERVM, "Invalid option -%c", c);
266
return errorSyntax(USAGE_UNREGISTERVM, "Invalid option case %i", c);
268
else if (c == VERR_GETOPT_UNKNOWN_OPTION)
269
return errorSyntax(USAGE_UNREGISTERVM, "unknown option: %s\n", ValueUnion.psz);
270
else if (ValueUnion.pDef)
271
return errorSyntax(USAGE_UNREGISTERVM, "%s: %Rrs", ValueUnion.pDef->pszLong, c);
273
return errorSyntax(USAGE_UNREGISTERVM, "error: %Rrs", c);
277
/* check for required options */
279
return errorSyntax(USAGE_UNREGISTERVM, "VM name required");
281
ComPtr<IMachine> machine;
282
/* assume it's a UUID */
283
rc = a->virtualBox->GetMachine(Guid(VMName).toUtf16(), machine.asOutParam());
284
if (FAILED(rc) || !machine)
287
CHECK_ERROR(a->virtualBox, FindMachine(Bstr(VMName), machine.asOutParam()));
292
machine->COMGETTER(Id)(uuid.asOutParam());
294
CHECK_ERROR(a->virtualBox, UnregisterMachine(uuid, machine.asOutParam()));
295
if (SUCCEEDED(rc) && machine && fDelete)
296
CHECK_ERROR(machine, DeleteSettings());
298
return SUCCEEDED(rc) ? 0 : 1;
301
static int handleCreateVM(HandlerArg *a)
309
bool fRegister = false;
312
for (int i = 0; i < a->argc; i++)
314
if ( !strcmp(a->argv[i], "--basefolder")
315
|| !strcmp(a->argv[i], "-basefolder"))
317
if (a->argc <= i + 1)
318
return errorArgument("Missing argument to '%s'", a->argv[i]);
320
baseFolder = a->argv[i];
322
else if ( !strcmp(a->argv[i], "--settingsfile")
323
|| !strcmp(a->argv[i], "-settingsfile"))
325
if (a->argc <= i + 1)
326
return errorArgument("Missing argument to '%s'", a->argv[i]);
328
settingsFile = a->argv[i];
330
else if ( !strcmp(a->argv[i], "--name")
331
|| !strcmp(a->argv[i], "-name"))
333
if (a->argc <= i + 1)
334
return errorArgument("Missing argument to '%s'", a->argv[i]);
338
else if ( !strcmp(a->argv[i], "--ostype")
339
|| !strcmp(a->argv[i], "-ostype"))
341
if (a->argc <= i + 1)
342
return errorArgument("Missing argument to '%s'", a->argv[i]);
344
osTypeId = a->argv[i];
346
else if ( !strcmp(a->argv[i], "--uuid")
347
|| !strcmp(a->argv[i], "-uuid"))
349
if (a->argc <= i + 1)
350
return errorArgument("Missing argument to '%s'", a->argv[i]);
352
if (RT_FAILURE(RTUuidFromStr(&id, a->argv[i])))
353
return errorArgument("Invalid UUID format %s\n", a->argv[i]);
355
else if ( !strcmp(a->argv[i], "--register")
356
|| !strcmp(a->argv[i], "-register"))
361
return errorSyntax(USAGE_CREATEVM, "Invalid parameter '%s'", Utf8Str(a->argv[i]).raw());
364
return errorSyntax(USAGE_CREATEVM, "Parameter --name is required");
366
if (!!baseFolder && !!settingsFile)
367
return errorSyntax(USAGE_CREATEVM, "Either --basefolder or --settingsfile must be specified");
371
ComPtr<IMachine> machine;
374
CHECK_ERROR_BREAK(a->virtualBox,
375
CreateMachine(name, osTypeId, baseFolder, Guid(id).toUtf16(), machine.asOutParam()));
377
CHECK_ERROR_BREAK(a->virtualBox,
378
CreateLegacyMachine(name, osTypeId, settingsFile, Guid(id).toUtf16(), machine.asOutParam()));
380
CHECK_ERROR_BREAK(machine, SaveSettings());
383
CHECK_ERROR_BREAK(a->virtualBox, RegisterMachine(machine));
386
CHECK_ERROR_BREAK(machine, COMGETTER(Id)(uuid.asOutParam()));
387
CHECK_ERROR_BREAK(machine, COMGETTER(SettingsFilePath)(settingsFile.asOutParam()));
388
RTPrintf("Virtual machine '%ls' is created%s.\n"
390
"Settings file: '%ls'\n",
391
name.raw(), fRegister ? " and registered" : "",
392
Utf8Str(uuid).raw(), settingsFile.raw());
396
return SUCCEEDED(rc) ? 0 : 1;
402
* @returns Valid number on success.
403
* @returns 0 if invalid number. All necesary bitching has been done.
404
* @param psz Pointer to the nic number.
406
unsigned parseNum(const char *psz, unsigned cMaxNum, const char *name)
410
int rc = RTStrToUInt32Ex(psz, &pszNext, 10, &u32);
415
return (unsigned)u32;
416
errorArgument("Invalid %s number '%s'", name, psz);
421
/** @todo refine this after HDD changes; MSC 8.0/64 has trouble with handleModifyVM. */
422
#if defined(_MSC_VER)
423
# pragma optimize("", on)
426
static const RTGETOPTDEF g_aStartVMOptions[] =
428
{ "--type", 't', RTGETOPT_REQ_STRING },
429
{ "-type", 't', RTGETOPT_REQ_STRING }, // deprecated
432
static int handleStartVM(HandlerArg *a)
435
const char *VMName = NULL;
436
Bstr sessionType = "gui";
439
RTGETOPTUNION ValueUnion;
440
RTGETOPTSTATE GetState;
441
// start at 0 because main() has hacked both the argc and argv given to us
442
RTGetOptInit(&GetState, a->argc, a->argv, g_aStartVMOptions, RT_ELEMENTS(g_aStartVMOptions), 0, 0 /* fFlags */);
443
while ((c = RTGetOpt(&GetState, &ValueUnion)))
448
if (!RTStrICmp(ValueUnion.psz, "gui"))
452
#ifdef VBOX_WITH_VBOXSDL
453
else if (!RTStrICmp(ValueUnion.psz, "sdl"))
458
#ifdef VBOX_WITH_VRDP
459
else if (!RTStrICmp(ValueUnion.psz, "vrdp"))
461
sessionType = "vrdp";
464
#ifdef VBOX_WITH_HEADLESS
465
else if (!RTStrICmp(ValueUnion.psz, "capture"))
467
sessionType = "capture";
469
else if (!RTStrICmp(ValueUnion.psz, "headless"))
471
sessionType = "headless";
475
return errorArgument("Invalid session type '%s'", ValueUnion.psz);
478
case VINF_GETOPT_NOT_OPTION:
480
VMName = ValueUnion.psz;
482
return errorSyntax(USAGE_STARTVM, "Invalid parameter '%s'", ValueUnion.psz);
488
if (RT_C_IS_PRINT(c))
489
return errorSyntax(USAGE_STARTVM, "Invalid option -%c", c);
491
return errorSyntax(USAGE_STARTVM, "Invalid option case %i", c);
493
else if (c == VERR_GETOPT_UNKNOWN_OPTION)
494
return errorSyntax(USAGE_STARTVM, "unknown option: %s\n", ValueUnion.psz);
495
else if (ValueUnion.pDef)
496
return errorSyntax(USAGE_STARTVM, "%s: %Rrs", ValueUnion.pDef->pszLong, c);
498
return errorSyntax(USAGE_STARTVM, "error: %Rrs", c);
502
/* check for required options */
504
return errorSyntax(USAGE_STARTVM, "VM name required");
506
ComPtr<IMachine> machine;
507
/* assume it's a UUID */
508
rc = a->virtualBox->GetMachine(Guid(VMName).toUtf16(), machine.asOutParam());
509
if (FAILED(rc) || !machine)
512
CHECK_ERROR(a->virtualBox, FindMachine(Bstr(VMName), machine.asOutParam()));
517
machine->COMGETTER(Id)(uuid.asOutParam());
521
#if defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS)
522
/* make sure the VM process will start on the same display as VBoxManage */
524
const char *pszDisplay = RTEnvGet("DISPLAY");
526
str = Utf8StrFmt("DISPLAY=%s\n", pszDisplay);
527
const char *pszXAuth = RTEnvGet("XAUTHORITY");
529
str.append(Utf8StrFmt("XAUTHORITY=%s\n", pszXAuth));
532
ComPtr<IProgress> progress;
533
CHECK_ERROR_RET(a->virtualBox, OpenRemoteSession(a->session, uuid, sessionType,
534
env, progress.asOutParam()), rc);
535
RTPrintf("Waiting for the remote session to open...\n");
536
CHECK_ERROR_RET(progress, WaitForCompletion (-1), 1);
539
CHECK_ERROR_RET(progress, COMGETTER(Completed)(&completed), rc);
543
CHECK_ERROR_RET(progress, COMGETTER(ResultCode)(&iRc), rc);
546
ComPtr <IVirtualBoxErrorInfo> errorInfo;
547
CHECK_ERROR_RET(progress, COMGETTER(ErrorInfo)(errorInfo.asOutParam()), 1);
548
ErrorInfo info (errorInfo);
549
com::GluePrintErrorInfo(info);
553
RTPrintf("Remote session has been successfully opened.\n");
557
/* it's important to always close sessions */
560
return SUCCEEDED(rc) ? 0 : 1;
563
static int handleControlVM(HandlerArg *a)
568
return errorSyntax(USAGE_CONTROLVM, "Not enough parameters");
570
/* try to find the given machine */
571
ComPtr <IMachine> machine;
572
Bstr uuid (a->argv[0]);
573
if (!Guid(uuid).isEmpty())
575
CHECK_ERROR (a->virtualBox, GetMachine (uuid, machine.asOutParam()));
579
CHECK_ERROR (a->virtualBox, FindMachine (uuid, machine.asOutParam()));
581
machine->COMGETTER(Id) (uuid.asOutParam());
586
/* open a session for the VM */
587
CHECK_ERROR_RET (a->virtualBox, OpenExistingSession (a->session, uuid), 1);
591
/* get the associated console */
592
ComPtr<IConsole> console;
593
CHECK_ERROR_BREAK (a->session, COMGETTER(Console)(console.asOutParam()));
594
/* ... and session machine */
595
ComPtr<IMachine> sessionMachine;
596
CHECK_ERROR_BREAK (a->session, COMGETTER(Machine)(sessionMachine.asOutParam()));
599
if (!strcmp(a->argv[1], "pause"))
601
CHECK_ERROR_BREAK (console, Pause());
603
else if (!strcmp(a->argv[1], "resume"))
605
CHECK_ERROR_BREAK (console, Resume());
607
else if (!strcmp(a->argv[1], "reset"))
609
CHECK_ERROR_BREAK (console, Reset());
611
else if (!strcmp(a->argv[1], "poweroff"))
613
ComPtr<IProgress> progress;
614
CHECK_ERROR_BREAK (console, PowerDown(progress.asOutParam()));
616
showProgress(progress);
619
progress->COMGETTER(ResultCode)(&iRc);
622
com::ProgressErrorInfo info(progress);
623
if (info.isBasicAvailable())
625
RTPrintf("Error: failed to power off machine. Error message: %lS\n", info.getText().raw());
629
RTPrintf("Error: failed to power off machine. No error message available!\n");
633
else if (!strcmp(a->argv[1], "savestate"))
635
ComPtr<IProgress> progress;
636
CHECK_ERROR_BREAK (console, SaveState(progress.asOutParam()));
638
showProgress(progress);
641
progress->COMGETTER(ResultCode)(&iRc);
644
com::ProgressErrorInfo info(progress);
645
if (info.isBasicAvailable())
647
RTPrintf("Error: failed to save machine state. Error message: %lS\n", info.getText().raw());
651
RTPrintf("Error: failed to save machine state. No error message available!\n");
655
else if (!strcmp(a->argv[1], "acpipowerbutton"))
657
CHECK_ERROR_BREAK (console, PowerButton());
659
else if (!strcmp(a->argv[1], "acpisleepbutton"))
661
CHECK_ERROR_BREAK (console, SleepButton());
663
else if (!strcmp(a->argv[1], "injectnmi"))
665
/* get the machine debugger. */
666
ComPtr <IMachineDebugger> debugger;
667
CHECK_ERROR_BREAK(console, COMGETTER(Debugger)(debugger.asOutParam()));
668
CHECK_ERROR_BREAK(debugger, InjectNMI());
670
else if (!strcmp(a->argv[1], "keyboardputscancode"))
672
ComPtr<IKeyboard> keyboard;
673
CHECK_ERROR_BREAK(console, COMGETTER(Keyboard)(keyboard.asOutParam()));
675
if (a->argc <= 1 + 1)
677
errorArgument("Missing argument to '%s'. Expected IBM PC AT set 2 keyboard scancode(s) as hex byte(s).", a->argv[1]);
682
/* Arbitrary restrict the length of a sequence of scancodes to 1024. */
683
LONG alScancodes[1024];
686
/* Process the command line. */
688
for (i = 1 + 1; i < a->argc && cScancodes < (int)RT_ELEMENTS(alScancodes); i++, cScancodes++)
690
if ( RT_C_IS_XDIGIT (a->argv[i][0])
691
&& RT_C_IS_XDIGIT (a->argv[i][1])
692
&& a->argv[i][2] == 0)
695
int rc = RTStrToUInt8Ex(a->argv[i], NULL, 16, &u8Scancode);
698
RTPrintf("Error: converting '%s' returned %Rrc!\n", a->argv[i], rc);
703
alScancodes[cScancodes] = u8Scancode;
707
RTPrintf("Error: '%s' is not a hex byte!\n", a->argv[i]);
716
if ( cScancodes == RT_ELEMENTS(alScancodes)
719
RTPrintf("Error: too many scancodes, maximum %d allowed!\n", RT_ELEMENTS(alScancodes));
724
/* Send scancodes to the VM.
725
* Note: 'PutScancodes' did not work here. Only the first scancode was transmitted.
727
for (i = 0; i < cScancodes; i++)
729
CHECK_ERROR_BREAK(keyboard, PutScancode(alScancodes[i]));
730
RTPrintf("Scancode[%d]: 0x%02X\n", i, alScancodes[i]);
733
else if (!strncmp(a->argv[1], "setlinkstate", 12))
735
/* Get the number of network adapters */
736
ULONG NetworkAdapterCount = 0;
737
ComPtr <ISystemProperties> info;
738
CHECK_ERROR_BREAK (a->virtualBox, COMGETTER(SystemProperties) (info.asOutParam()));
739
CHECK_ERROR_BREAK (info, COMGETTER(NetworkAdapterCount) (&NetworkAdapterCount));
741
unsigned n = parseNum(&a->argv[1][12], NetworkAdapterCount, "NIC");
747
if (a->argc <= 1 + 1)
749
errorArgument("Missing argument to '%s'", a->argv[1]);
753
/* get the corresponding network adapter */
754
ComPtr<INetworkAdapter> adapter;
755
CHECK_ERROR_BREAK (sessionMachine, GetNetworkAdapter(n - 1, adapter.asOutParam()));
758
if (!strcmp(a->argv[2], "on"))
760
CHECK_ERROR_BREAK (adapter, COMSETTER(CableConnected)(TRUE));
762
else if (!strcmp(a->argv[2], "off"))
764
CHECK_ERROR_BREAK (adapter, COMSETTER(CableConnected)(FALSE));
768
errorArgument("Invalid link state '%s'", Utf8Str(a->argv[2]).raw());
774
#ifdef VBOX_DYNAMIC_NET_ATTACH
775
else if (!strncmp(a->argv[1], "nic", 3))
777
/* Get the number of network adapters */
778
ULONG NetworkAdapterCount = 0;
779
ComPtr <ISystemProperties> info;
780
CHECK_ERROR_BREAK (a->virtualBox, COMGETTER(SystemProperties) (info.asOutParam()));
781
CHECK_ERROR_BREAK (info, COMGETTER(NetworkAdapterCount) (&NetworkAdapterCount));
783
unsigned n = parseNum(&a->argv[1][3], NetworkAdapterCount, "NIC");
789
if (a->argc <= 1 + 1)
791
errorArgument("Missing argument to '%s'", a->argv[1]);
796
/* get the corresponding network adapter */
797
ComPtr<INetworkAdapter> adapter;
798
CHECK_ERROR_BREAK (sessionMachine, GetNetworkAdapter(n - 1, adapter.asOutParam()));
801
if (!strcmp(a->argv[2], "none"))
803
CHECK_ERROR_RET(adapter, COMSETTER(Enabled) (FALSE), 1);
805
else if (!strcmp(a->argv[2], "null"))
807
CHECK_ERROR_RET(adapter, COMSETTER(Enabled) (TRUE), 1);
808
CHECK_ERROR_RET(adapter, Detach(), 1);
810
else if (!strcmp(a->argv[2], "nat"))
813
CHECK_ERROR_RET(adapter, COMSETTER(NATNetwork)(Bstr(a->argv[3])), 1);
814
CHECK_ERROR_RET(adapter, COMSETTER(Enabled) (TRUE), 1);
815
CHECK_ERROR_RET(adapter, AttachToNAT(), 1);
817
else if ( !strcmp(a->argv[2], "bridged")
818
|| !strcmp(a->argv[2], "hostif")) /* backward compatibility */
820
if (a->argc <= 1 + 2)
822
errorArgument("Missing argument to '%s'", a->argv[2]);
826
CHECK_ERROR_RET(adapter, COMSETTER(HostInterface)(Bstr(a->argv[3])), 1);
827
CHECK_ERROR_RET(adapter, COMSETTER(Enabled) (TRUE), 1);
828
CHECK_ERROR_RET(adapter, AttachToBridgedInterface(), 1);
830
else if (!strcmp(a->argv[2], "intnet"))
832
if (a->argc <= 1 + 2)
834
errorArgument("Missing argument to '%s'", a->argv[2]);
838
CHECK_ERROR_RET(adapter, COMSETTER(InternalNetwork)(Bstr(a->argv[3])), 1);
839
CHECK_ERROR_RET(adapter, COMSETTER(Enabled) (TRUE), 1);
840
CHECK_ERROR_RET(adapter, AttachToInternalNetwork(), 1);
842
#if defined(VBOX_WITH_NETFLT)
843
else if (!strcmp(a->argv[2], "hostonly"))
845
if (a->argc <= 1 + 2)
847
errorArgument("Missing argument to '%s'", a->argv[2]);
851
CHECK_ERROR_RET(adapter, COMSETTER(HostInterface)(Bstr(a->argv[3])), 1);
852
CHECK_ERROR_RET(adapter, COMSETTER(Enabled) (TRUE), 1);
853
CHECK_ERROR_RET(adapter, AttachToHostOnlyInterface(), 1);
858
errorArgument("Invalid type '%s' specfied for NIC %lu", Utf8Str(a->argv[2]).raw(), n + 1);
864
#endif /* VBOX_DYNAMIC_NET_ATTACH */
865
#ifdef VBOX_WITH_VRDP
866
else if (!strcmp(a->argv[1], "vrdp"))
868
if (a->argc <= 1 + 1)
870
errorArgument("Missing argument to '%s'", a->argv[1]);
874
/* get the corresponding VRDP server */
875
ComPtr<IVRDPServer> vrdpServer;
876
sessionMachine->COMGETTER(VRDPServer)(vrdpServer.asOutParam());
880
if (!strcmp(a->argv[2], "on"))
882
CHECK_ERROR_BREAK (vrdpServer, COMSETTER(Enabled)(TRUE));
884
else if (!strcmp(a->argv[2], "off"))
886
CHECK_ERROR_BREAK (vrdpServer, COMSETTER(Enabled)(FALSE));
890
errorArgument("Invalid vrdp server state '%s'", Utf8Str(a->argv[2]).raw());
896
else if (!strcmp(a->argv[1], "vrdpport"))
898
if (a->argc <= 1 + 1)
900
errorArgument("Missing argument to '%s'", a->argv[1]);
904
/* get the corresponding VRDP server */
905
ComPtr<IVRDPServer> vrdpServer;
906
sessionMachine->COMGETTER(VRDPServer)(vrdpServer.asOutParam());
912
if (!strcmp(a->argv[2], "default"))
918
int vrc = RTStrToUInt16Full(a->argv[2], 0, &vrdpport);
920
if (vrc != VINF_SUCCESS)
922
vrdpport = UINT16_MAX;
926
if (vrdpport != UINT16_MAX)
928
CHECK_ERROR_BREAK(vrdpServer, COMSETTER(Port)(vrdpport));
932
errorArgument("Invalid vrdp server port '%s'", Utf8Str(a->argv[2]).raw());
938
#endif /* VBOX_WITH_VRDP */
939
else if ( !strcmp (a->argv[1], "usbattach")
940
|| !strcmp (a->argv[1], "usbdetach"))
944
errorSyntax(USAGE_CONTROLVM, "Not enough parameters");
949
bool attach = !strcmp(a->argv[1], "usbattach");
951
Bstr usbId = a->argv [2];
952
if (Guid(usbId).isEmpty())
958
CHECK_ERROR_BREAK (a->virtualBox, COMGETTER(Host) (host.asOutParam()));
959
SafeIfaceArray <IHostUSBDevice> coll;
960
CHECK_ERROR_BREAK (host, COMGETTER(USBDevices) (ComSafeArrayAsOutParam(coll)));
961
ComPtr <IHostUSBDevice> dev;
962
CHECK_ERROR_BREAK (host, FindUSBDeviceByAddress (Bstr (a->argv [2]), dev.asOutParam()));
963
CHECK_ERROR_BREAK (dev, COMGETTER(Id) (usbId.asOutParam()));
967
SafeIfaceArray <IUSBDevice> coll;
968
CHECK_ERROR_BREAK (console, COMGETTER(USBDevices)(ComSafeArrayAsOutParam(coll)));
969
ComPtr <IUSBDevice> dev;
970
CHECK_ERROR_BREAK (console, FindUSBDeviceByAddress (Bstr (a->argv [2]),
972
CHECK_ERROR_BREAK (dev, COMGETTER(Id) (usbId.asOutParam()));
977
CHECK_ERROR_BREAK (console, AttachUSBDevice (usbId));
980
ComPtr <IUSBDevice> dev;
981
CHECK_ERROR_BREAK (console, DetachUSBDevice (usbId, dev.asOutParam()));
984
else if (!strcmp(a->argv[1], "setvideomodehint"))
986
if (a->argc != 5 && a->argc != 6)
988
errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
992
uint32_t xres = RTStrToUInt32(a->argv[2]);
993
uint32_t yres = RTStrToUInt32(a->argv[3]);
994
uint32_t bpp = RTStrToUInt32(a->argv[4]);
995
uint32_t displayIdx = 0;
997
displayIdx = RTStrToUInt32(a->argv[5]);
999
ComPtr<IDisplay> display;
1000
CHECK_ERROR_BREAK(console, COMGETTER(Display)(display.asOutParam()));
1001
CHECK_ERROR_BREAK(display, SetVideoModeHint(xres, yres, bpp, displayIdx));
1003
else if (!strcmp(a->argv[1], "setcredentials"))
1005
bool fAllowLocalLogon = true;
1008
if ( strcmp(a->argv[5], "--allowlocallogon")
1009
&& strcmp(a->argv[5], "-allowlocallogon"))
1011
errorArgument("Invalid parameter '%s'", a->argv[5]);
1015
if (!strcmp(a->argv[6], "no"))
1016
fAllowLocalLogon = false;
1018
else if (a->argc != 5)
1020
errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
1025
ComPtr<IGuest> guest;
1026
CHECK_ERROR_BREAK(console, COMGETTER(Guest)(guest.asOutParam()));
1027
CHECK_ERROR_BREAK(guest, SetCredentials(Bstr(a->argv[2]), Bstr(a->argv[3]), Bstr(a->argv[4]), fAllowLocalLogon));
1029
else if (!strcmp(a->argv[1], "dvdattach"))
1033
errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
1037
ComPtr<IDVDDrive> dvdDrive;
1038
sessionMachine->COMGETTER(DVDDrive)(dvdDrive.asOutParam());
1042
if (!strcmp(a->argv[2], "none"))
1044
CHECK_ERROR(dvdDrive, Unmount());
1047
else if (!strncmp(a->argv[2], "host:", 5))
1050
CHECK_ERROR(a->virtualBox, COMGETTER(Host)(host.asOutParam()));
1051
com::SafeIfaceArray <IHostDVDDrive> hostDVDs;
1052
rc = host->COMGETTER(DVDDrives)(ComSafeArrayAsOutParam(hostDVDs));
1054
ComPtr<IHostDVDDrive> hostDVDDrive;
1055
rc = host->FindHostDVDDrive(Bstr(a->argv[2] + 5), hostDVDDrive.asOutParam());
1058
errorArgument("Invalid host DVD drive name");
1062
CHECK_ERROR(dvdDrive, CaptureHostDrive(hostDVDDrive));
1066
/* first assume it's a UUID */
1067
Bstr uuid(a->argv[2]);
1068
ComPtr<IDVDImage> dvdImage;
1069
rc = a->virtualBox->GetDVDImage(uuid, dvdImage.asOutParam());
1070
if (FAILED(rc) || !dvdImage)
1072
/* must be a filename, check if it's in the collection */
1073
rc = a->virtualBox->FindDVDImage(Bstr(a->argv[2]), dvdImage.asOutParam());
1074
/* not registered, do that on the fly */
1078
CHECK_ERROR(a->virtualBox, OpenDVDImage(Bstr(a->argv[2]), emptyUUID, dvdImage.asOutParam()));
1086
dvdImage->COMGETTER(Id)(uuid.asOutParam());
1087
CHECK_ERROR(dvdDrive, MountImage(uuid));
1090
else if (!strcmp(a->argv[1], "floppyattach"))
1094
errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
1099
ComPtr<IFloppyDrive> floppyDrive;
1100
sessionMachine->COMGETTER(FloppyDrive)(floppyDrive.asOutParam());
1101
ASSERT(floppyDrive);
1104
if (!strcmp(a->argv[2], "none"))
1106
CHECK_ERROR(floppyDrive, Unmount());
1109
else if (!strncmp(a->argv[2], "host:", 5))
1112
CHECK_ERROR(a->virtualBox, COMGETTER(Host)(host.asOutParam()));
1113
com::SafeIfaceArray <IHostFloppyDrive> hostFloppies;
1114
rc = host->COMGETTER(FloppyDrives)(ComSafeArrayAsOutParam(hostFloppies));
1115
CheckComRCReturnRC (rc);
1116
ComPtr<IHostFloppyDrive> hostFloppyDrive;
1117
host->FindHostFloppyDrive(Bstr(a->argv[2] + 5), hostFloppyDrive.asOutParam());
1118
if (!hostFloppyDrive)
1120
errorArgument("Invalid host floppy drive name");
1124
CHECK_ERROR(floppyDrive, CaptureHostDrive(hostFloppyDrive));
1128
/* first assume it's a UUID */
1129
Bstr uuid(a->argv[2]);
1130
ComPtr<IFloppyImage> floppyImage;
1131
rc = a->virtualBox->GetFloppyImage(uuid, floppyImage.asOutParam());
1132
if (FAILED(rc) || !floppyImage)
1134
/* must be a filename, check if it's in the collection */
1135
rc = a->virtualBox->FindFloppyImage(Bstr(a->argv[2]), floppyImage.asOutParam());
1136
/* not registered, do that on the fly */
1140
CHECK_ERROR(a->virtualBox, OpenFloppyImage(Bstr(a->argv[2]), emptyUUID, floppyImage.asOutParam()));
1148
floppyImage->COMGETTER(Id)(uuid.asOutParam());
1149
CHECK_ERROR(floppyDrive, MountImage(uuid));
1152
#ifdef VBOX_WITH_MEM_BALLOONING
1153
else if ( !strcmp(a->argv[1], "--guestmemoryballoon")
1154
|| !strcmp(a->argv[1], "-guestmemoryballoon"))
1158
errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
1164
vrc = RTStrToUInt32Ex(a->argv[2], NULL, 0, &uVal);
1165
if (vrc != VINF_SUCCESS)
1167
errorArgument("Error parsing guest memory balloon size '%s'", a->argv[2]);
1172
/* guest is running; update IGuest */
1173
ComPtr <IGuest> guest;
1175
rc = console->COMGETTER(Guest)(guest.asOutParam());
1177
CHECK_ERROR(guest, COMSETTER(MemoryBalloonSize)(uVal));
1180
else if ( !strcmp(a->argv[1], "--gueststatisticsinterval")
1181
|| !strcmp(a->argv[1], "-gueststatisticsinterval"))
1185
errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
1191
vrc = RTStrToUInt32Ex(a->argv[2], NULL, 0, &uVal);
1192
if (vrc != VINF_SUCCESS)
1194
errorArgument("Error parsing guest statistics interval '%s'", a->argv[2]);
1199
/* guest is running; update IGuest */
1200
ComPtr <IGuest> guest;
1202
rc = console->COMGETTER(Guest)(guest.asOutParam());
1204
CHECK_ERROR(guest, COMSETTER(StatisticsUpdateInterval)(uVal));
1208
errorSyntax(USAGE_CONTROLVM, "Invalid parameter '%s'", Utf8Str(a->argv[1]).raw());
1214
a->session->Close();
1216
return SUCCEEDED (rc) ? 0 : 1;
1219
static int handleDiscardState(HandlerArg *a)
1224
return errorSyntax(USAGE_DISCARDSTATE, "Incorrect number of parameters");
1226
ComPtr<IMachine> machine;
1227
/* assume it's a UUID */
1228
rc = a->virtualBox->GetMachine(Bstr(a->argv[0]), machine.asOutParam());
1229
if (FAILED(rc) || !machine)
1231
/* must be a name */
1232
CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]), machine.asOutParam()));
1238
/* we have to open a session for this task */
1240
machine->COMGETTER(Id)(guid.asOutParam());
1241
CHECK_ERROR_BREAK(a->virtualBox, OpenSession(a->session, guid));
1244
ComPtr<IConsole> console;
1245
CHECK_ERROR_BREAK(a->session, COMGETTER(Console)(console.asOutParam()));
1246
CHECK_ERROR_BREAK(console, ForgetSavedState(true));
1249
CHECK_ERROR_BREAK(a->session, Close());
1254
return SUCCEEDED(rc) ? 0 : 1;
1257
static int handleAdoptdState(HandlerArg *a)
1262
return errorSyntax(USAGE_ADOPTSTATE, "Incorrect number of parameters");
1264
ComPtr<IMachine> machine;
1265
/* assume it's a UUID */
1266
rc = a->virtualBox->GetMachine(Bstr(a->argv[0]), machine.asOutParam());
1267
if (FAILED(rc) || !machine)
1269
/* must be a name */
1270
CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]), machine.asOutParam()));
1276
/* we have to open a session for this task */
1278
machine->COMGETTER(Id)(guid.asOutParam());
1279
CHECK_ERROR_BREAK(a->virtualBox, OpenSession(a->session, guid));
1282
ComPtr<IConsole> console;
1283
CHECK_ERROR_BREAK(a->session, COMGETTER(Console)(console.asOutParam()));
1284
CHECK_ERROR_BREAK(console, AdoptSavedState (Bstr (a->argv[1])));
1287
CHECK_ERROR_BREAK(a->session, Close());
1292
return SUCCEEDED(rc) ? 0 : 1;
1295
static int handleGetExtraData(HandlerArg *a)
1300
return errorSyntax(USAGE_GETEXTRADATA, "Incorrect number of parameters");
1303
if (!strcmp(a->argv[0], "global"))
1306
if (!strcmp(a->argv[1], "enumerate"))
1312
Bstr nextExtraDataKey;
1313
Bstr nextExtraDataValue;
1314
HRESULT rcEnum = a->virtualBox->GetNextExtraDataKey(extraDataKey, nextExtraDataKey.asOutParam(),
1315
nextExtraDataValue.asOutParam());
1316
extraDataKey = nextExtraDataKey;
1318
if (SUCCEEDED(rcEnum) && !extraDataKey.isEmpty())
1319
RTPrintf("Key: %lS, Value: %lS\n", nextExtraDataKey.raw(), nextExtraDataValue.raw());
1320
} while (!extraDataKey.isEmpty());
1325
CHECK_ERROR(a->virtualBox, GetExtraData(Bstr(a->argv[1]), value.asOutParam()));
1326
if (!value.isEmpty())
1327
RTPrintf("Value: %lS\n", value.raw());
1329
RTPrintf("No value set!\n");
1334
ComPtr<IMachine> machine;
1335
/* assume it's a UUID */
1336
rc = a->virtualBox->GetMachine(Bstr(a->argv[0]), machine.asOutParam());
1337
if (FAILED(rc) || !machine)
1339
/* must be a name */
1340
CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]), machine.asOutParam()));
1345
if (!strcmp(a->argv[1], "enumerate"))
1351
Bstr nextExtraDataKey;
1352
Bstr nextExtraDataValue;
1353
HRESULT rcEnum = machine->GetNextExtraDataKey(extraDataKey, nextExtraDataKey.asOutParam(),
1354
nextExtraDataValue.asOutParam());
1355
extraDataKey = nextExtraDataKey;
1357
if (SUCCEEDED(rcEnum) && !extraDataKey.isEmpty())
1359
RTPrintf("Key: %lS, Value: %lS\n", nextExtraDataKey.raw(), nextExtraDataValue.raw());
1361
} while (!extraDataKey.isEmpty());
1366
CHECK_ERROR(machine, GetExtraData(Bstr(a->argv[1]), value.asOutParam()));
1367
if (!value.isEmpty())
1368
RTPrintf("Value: %lS\n", value.raw());
1370
RTPrintf("No value set!\n");
1374
return SUCCEEDED(rc) ? 0 : 1;
1377
static int handleSetExtraData(HandlerArg *a)
1382
return errorSyntax(USAGE_SETEXTRADATA, "Not enough parameters");
1385
if (!strcmp(a->argv[0], "global"))
1388
CHECK_ERROR(a->virtualBox, SetExtraData(Bstr(a->argv[1]), NULL));
1389
else if (a->argc == 3)
1390
CHECK_ERROR(a->virtualBox, SetExtraData(Bstr(a->argv[1]), Bstr(a->argv[2])));
1392
return errorSyntax(USAGE_SETEXTRADATA, "Too many parameters");
1396
ComPtr<IMachine> machine;
1397
/* assume it's a UUID */
1398
rc = a->virtualBox->GetMachine(Bstr(a->argv[0]), machine.asOutParam());
1399
if (FAILED(rc) || !machine)
1401
/* must be a name */
1402
CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]), machine.asOutParam()));
1407
CHECK_ERROR(machine, SetExtraData(Bstr(a->argv[1]), NULL));
1408
else if (a->argc == 3)
1409
CHECK_ERROR(machine, SetExtraData(Bstr(a->argv[1]), Bstr(a->argv[2])));
1411
return errorSyntax(USAGE_SETEXTRADATA, "Too many parameters");
1414
return SUCCEEDED(rc) ? 0 : 1;
1417
static int handleSetProperty(HandlerArg *a)
1421
/* there must be two arguments: property name and value */
1423
return errorSyntax(USAGE_SETPROPERTY, "Incorrect number of parameters");
1425
ComPtr<ISystemProperties> systemProperties;
1426
a->virtualBox->COMGETTER(SystemProperties)(systemProperties.asOutParam());
1428
if (!strcmp(a->argv[0], "hdfolder"))
1430
/* reset to default? */
1431
if (!strcmp(a->argv[1], "default"))
1432
CHECK_ERROR(systemProperties, COMSETTER(DefaultHardDiskFolder)(NULL));
1434
CHECK_ERROR(systemProperties, COMSETTER(DefaultHardDiskFolder)(Bstr(a->argv[1])));
1436
else if (!strcmp(a->argv[0], "machinefolder"))
1438
/* reset to default? */
1439
if (!strcmp(a->argv[1], "default"))
1440
CHECK_ERROR(systemProperties, COMSETTER(DefaultMachineFolder)(NULL));
1442
CHECK_ERROR(systemProperties, COMSETTER(DefaultMachineFolder)(Bstr(a->argv[1])));
1444
else if (!strcmp(a->argv[0], "vrdpauthlibrary"))
1446
/* reset to default? */
1447
if (!strcmp(a->argv[1], "default"))
1448
CHECK_ERROR(systemProperties, COMSETTER(RemoteDisplayAuthLibrary)(NULL));
1450
CHECK_ERROR(systemProperties, COMSETTER(RemoteDisplayAuthLibrary)(Bstr(a->argv[1])));
1452
else if (!strcmp(a->argv[0], "websrvauthlibrary"))
1454
/* reset to default? */
1455
if (!strcmp(a->argv[1], "default"))
1456
CHECK_ERROR(systemProperties, COMSETTER(WebServiceAuthLibrary)(NULL));
1458
CHECK_ERROR(systemProperties, COMSETTER(WebServiceAuthLibrary)(Bstr(a->argv[1])));
1460
else if (!strcmp(a->argv[0], "loghistorycount"))
1464
vrc = RTStrToUInt32Ex(a->argv[1], NULL, 0, &uVal);
1465
if (vrc != VINF_SUCCESS)
1466
return errorArgument("Error parsing Log history count '%s'", a->argv[1]);
1467
CHECK_ERROR(systemProperties, COMSETTER(LogHistoryCount)(uVal));
1470
return errorSyntax(USAGE_SETPROPERTY, "Invalid parameter '%s'", a->argv[0]);
1472
return SUCCEEDED(rc) ? 0 : 1;
1475
static int handleSharedFolder (HandlerArg *a)
1479
/* we need at least a command and target */
1481
return errorSyntax(USAGE_SHAREDFOLDER, "Not enough parameters");
1483
ComPtr<IMachine> machine;
1484
/* assume it's a UUID */
1485
rc = a->virtualBox->GetMachine(Bstr(a->argv[1]), machine.asOutParam());
1486
if (FAILED(rc) || !machine)
1488
/* must be a name */
1489
CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[1]), machine.asOutParam()));
1494
machine->COMGETTER(Id)(uuid.asOutParam());
1496
if (!strcmp(a->argv[0], "add"))
1498
/* we need at least four more parameters */
1500
return errorSyntax(USAGE_SHAREDFOLDER_ADD, "Not enough parameters");
1503
char *hostpath = NULL;
1504
bool fTransient = false;
1505
bool fWritable = true;
1507
for (int i = 2; i < a->argc; i++)
1509
if ( !strcmp(a->argv[i], "--name")
1510
|| !strcmp(a->argv[i], "-name"))
1512
if (a->argc <= i + 1 || !*a->argv[i+1])
1513
return errorArgument("Missing argument to '%s'", a->argv[i]);
1517
else if ( !strcmp(a->argv[i], "--hostpath")
1518
|| !strcmp(a->argv[i], "-hostpath"))
1520
if (a->argc <= i + 1 || !*a->argv[i+1])
1521
return errorArgument("Missing argument to '%s'", a->argv[i]);
1523
hostpath = a->argv[i];
1525
else if ( !strcmp(a->argv[i], "--readonly")
1526
|| !strcmp(a->argv[i], "-readonly"))
1530
else if ( !strcmp(a->argv[i], "--transient")
1531
|| !strcmp(a->argv[i], "-transient"))
1536
return errorSyntax(USAGE_SHAREDFOLDER_ADD, "Invalid parameter '%s'", Utf8Str(a->argv[i]).raw());
1539
if (NULL != strstr(name, " "))
1540
return errorSyntax(USAGE_SHAREDFOLDER_ADD, "No spaces allowed in parameter '-name'!");
1542
/* required arguments */
1543
if (!name || !hostpath)
1545
return errorSyntax(USAGE_SHAREDFOLDER_ADD, "Parameters --name and --hostpath are required");
1550
ComPtr <IConsole> console;
1552
/* open an existing session for the VM */
1553
CHECK_ERROR_RET(a->virtualBox, OpenExistingSession (a->session, uuid), 1);
1554
/* get the session machine */
1555
CHECK_ERROR_RET(a->session, COMGETTER(Machine)(machine.asOutParam()), 1);
1556
/* get the session console */
1557
CHECK_ERROR_RET(a->session, COMGETTER(Console)(console.asOutParam()), 1);
1559
CHECK_ERROR(console, CreateSharedFolder(Bstr(name), Bstr(hostpath), fWritable));
1562
a->session->Close();
1566
/* open a session for the VM */
1567
CHECK_ERROR_RET (a->virtualBox, OpenSession(a->session, uuid), 1);
1569
/* get the mutable session machine */
1570
a->session->COMGETTER(Machine)(machine.asOutParam());
1572
CHECK_ERROR(machine, CreateSharedFolder(Bstr(name), Bstr(hostpath), fWritable));
1575
CHECK_ERROR(machine, SaveSettings());
1577
a->session->Close();
1580
else if (!strcmp(a->argv[0], "remove"))
1582
/* we need at least two more parameters */
1584
return errorSyntax(USAGE_SHAREDFOLDER_REMOVE, "Not enough parameters");
1587
bool fTransient = false;
1589
for (int i = 2; i < a->argc; i++)
1591
if ( !strcmp(a->argv[i], "--name")
1592
|| !strcmp(a->argv[i], "-name"))
1594
if (a->argc <= i + 1 || !*a->argv[i+1])
1595
return errorArgument("Missing argument to '%s'", a->argv[i]);
1599
else if ( !strcmp(a->argv[i], "--transient")
1600
|| !strcmp(a->argv[i], "-transient"))
1605
return errorSyntax(USAGE_SHAREDFOLDER_REMOVE, "Invalid parameter '%s'", Utf8Str(a->argv[i]).raw());
1608
/* required arguments */
1610
return errorSyntax(USAGE_SHAREDFOLDER_REMOVE, "Parameter --name is required");
1614
ComPtr <IConsole> console;
1616
/* open an existing session for the VM */
1617
CHECK_ERROR_RET(a->virtualBox, OpenExistingSession (a->session, uuid), 1);
1618
/* get the session machine */
1619
CHECK_ERROR_RET(a->session, COMGETTER(Machine)(machine.asOutParam()), 1);
1620
/* get the session console */
1621
CHECK_ERROR_RET(a->session, COMGETTER(Console)(console.asOutParam()), 1);
1623
CHECK_ERROR(console, RemoveSharedFolder(Bstr(name)));
1626
a->session->Close();
1630
/* open a session for the VM */
1631
CHECK_ERROR_RET (a->virtualBox, OpenSession(a->session, uuid), 1);
1633
/* get the mutable session machine */
1634
a->session->COMGETTER(Machine)(machine.asOutParam());
1636
CHECK_ERROR(machine, RemoveSharedFolder(Bstr(name)));
1638
/* commit and close the session */
1639
CHECK_ERROR(machine, SaveSettings());
1640
a->session->Close();
1644
return errorSyntax(USAGE_SETPROPERTY, "Invalid parameter '%s'", Utf8Str(a->argv[0]).raw());
1649
static int handleVMStatistics(HandlerArg *a)
1653
/* at least one option: the UUID or name of the VM */
1655
return errorSyntax(USAGE_VM_STATISTICS, "Incorrect number of parameters");
1657
/* try to find the given machine */
1658
ComPtr <IMachine> machine;
1659
Bstr uuid (a->argv[0]);
1660
if (!Guid (a->argv[0]).isEmpty())
1661
CHECK_ERROR(a->virtualBox, GetMachine(uuid, machine.asOutParam()));
1664
CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]), machine.asOutParam()));
1666
machine->COMGETTER(Id)(uuid.asOutParam());
1671
/* parse arguments. */
1672
bool fReset = false;
1673
bool fWithDescriptions = false;
1674
const char *pszPattern = NULL; /* all */
1675
for (int i = 1; i < a->argc; i++)
1677
if ( !strcmp(a->argv[i], "--pattern")
1678
|| !strcmp(a->argv[i], "-pattern"))
1681
return errorSyntax(USAGE_VM_STATISTICS, "Multiple --patterns options is not permitted");
1682
if (i + 1 >= a->argc)
1683
return errorArgument("Missing argument to '%s'", a->argv[i]);
1684
pszPattern = a->argv[++i];
1686
else if ( !strcmp(a->argv[i], "--descriptions")
1687
|| !strcmp(a->argv[i], "-descriptions"))
1688
fWithDescriptions = true;
1689
/* add: --file <filename> and --formatted */
1690
else if ( !strcmp(a->argv[i], "--reset")
1691
|| !strcmp(a->argv[i], "-reset"))
1694
return errorSyntax(USAGE_VM_STATISTICS, "Unknown option '%s'", a->argv[i]);
1696
if (fReset && fWithDescriptions)
1697
return errorSyntax(USAGE_VM_STATISTICS, "The --reset and --descriptions options does not mix");
1700
/* open an existing session for the VM. */
1701
CHECK_ERROR(a->virtualBox, OpenExistingSession(a->session, uuid));
1704
/* get the session console. */
1705
ComPtr <IConsole> console;
1706
CHECK_ERROR(a->session, COMGETTER(Console)(console.asOutParam()));
1709
/* get the machine debugger. */
1710
ComPtr <IMachineDebugger> debugger;
1711
CHECK_ERROR(console, COMGETTER(Debugger)(debugger.asOutParam()));
1715
CHECK_ERROR(debugger, ResetStats(Bstr(pszPattern)));
1719
CHECK_ERROR(debugger, GetStats(Bstr(pszPattern), fWithDescriptions, stats.asOutParam()));
1726
RTPrintf("%ls\n", stats.raw());
1730
a->session->Close();
1734
return SUCCEEDED(rc) ? 0 : 1;
1736
#endif /* !VBOX_ONLY_DOCS */
1738
enum ConvertSettings
1740
ConvertSettings_No = 0,
1741
ConvertSettings_Yes = 1,
1742
ConvertSettings_Backup = 2,
1743
ConvertSettings_Ignore = 3,
1746
#ifndef VBOX_ONLY_DOCS
1748
* Checks if any of the settings files were auto-converted and informs the
1751
* @return @false if the program should terminate and @true otherwise.
1753
static bool checkForAutoConvertedSettings (ComPtr<IVirtualBox> virtualBox,
1754
ComPtr<ISession> session,
1755
ConvertSettings fConvertSettings)
1757
/* return early if nothing to do */
1758
if (fConvertSettings == ConvertSettings_Ignore)
1766
CHECK_ERROR_BREAK(virtualBox, COMGETTER(SettingsFormatVersion) (formatVersion.asOutParam()));
1768
bool isGlobalConverted = false;
1769
std::list <ComPtr <IMachine> > cvtMachines;
1770
std::list <Utf8Str> fileList;
1774
com::SafeIfaceArray <IMachine> machines;
1775
CHECK_ERROR_BREAK(virtualBox, COMGETTER(Machines)(ComSafeArrayAsOutParam (machines)));
1777
for (size_t i = 0; i < machines.size(); ++ i)
1780
CHECK_ERROR_BREAK(machines[i], COMGETTER(Accessible) (&accessible));
1784
CHECK_ERROR_BREAK(machines[i], COMGETTER(SettingsFileVersion) (version.asOutParam()));
1786
if (version != formatVersion)
1788
cvtMachines.push_back (machines [i]);
1790
CHECK_ERROR_BREAK(machines[i], COMGETTER(SettingsFilePath) (filePath.asOutParam()));
1791
fileList.push_back (Utf8StrFmt ("%ls (%ls)", filePath.raw(),
1799
CHECK_ERROR_BREAK(virtualBox, COMGETTER(SettingsFileVersion) (version.asOutParam()));
1800
if (version != formatVersion)
1802
isGlobalConverted = true;
1803
CHECK_ERROR_BREAK(virtualBox, COMGETTER(SettingsFilePath) (filePath.asOutParam()));
1804
fileList.push_back (Utf8StrFmt ("%ls (%ls)", filePath.raw(),
1808
if (fileList.size() > 0)
1810
switch (fConvertSettings)
1812
case ConvertSettings_No:
1815
"WARNING! The following VirtualBox settings files have been automatically\n"
1816
"converted to the new settings file format version '%ls':\n"
1818
formatVersion.raw());
1820
for (std::list <Utf8Str>::const_iterator f = fileList.begin();
1821
f != fileList.end(); ++ f)
1822
RTPrintf (" %S\n", (*f).raw());
1825
"The current command was aborted to prevent overwriting the above settings\n"
1826
"files with the results of the auto-conversion without your permission.\n"
1827
"Please put one of the following command line switches to the beginning of\n"
1828
"the VBoxManage command line and repeat the command:\n"
1830
" --convertSettings - to save all auto-converted files (it will not\n"
1831
" be possible to use these settings files with an\n"
1832
" older version of VirtualBox in the future);\n"
1833
" --convertSettingsBackup - to create backup copies of the settings files in\n"
1834
" the old format before saving them in the new format;\n"
1835
" --convertSettingsIgnore - to not save the auto-converted settings files.\n"
1837
"Note that if you use --convertSettingsIgnore, the auto-converted settings files\n"
1838
"will be implicitly saved in the new format anyway once you change a setting or\n"
1839
"start a virtual machine, but NO backup copies will be created in this case.\n");
1842
case ConvertSettings_Yes:
1843
case ConvertSettings_Backup:
1848
AssertFailedReturn (false);
1851
for (std::list <ComPtr <IMachine> >::const_iterator m = cvtMachines.begin();
1852
m != cvtMachines.end(); ++ m)
1855
CHECK_ERROR_BREAK((*m), COMGETTER(Id) (id.asOutParam()));
1857
/* open a session for the VM */
1858
CHECK_ERROR_BREAK (virtualBox, OpenSession (session, id));
1860
ComPtr <IMachine> sm;
1861
CHECK_ERROR_BREAK(session, COMGETTER(Machine) (sm.asOutParam()));
1864
if (fConvertSettings == ConvertSettings_Backup)
1865
CHECK_ERROR (sm, SaveSettingsWithBackup (bakFileName.asOutParam()));
1867
CHECK_ERROR (sm, SaveSettings());
1878
if (isGlobalConverted)
1881
if (fConvertSettings == ConvertSettings_Backup)
1882
CHECK_ERROR (virtualBox, SaveSettingsWithBackup (bakFileName.asOutParam()));
1884
CHECK_ERROR (virtualBox, SaveSettings());
1893
return SUCCEEDED (rc);
1895
#endif /* !VBOX_ONLY_DOCS */
1898
///////////////////////////////////////////////////////////////////////////////
208
#endif /* !VBOX_ONLY_DOCS */
1900
210
int main(int argc, char *argv[])