VirtualBox

source: vbox/trunk/src/VBox/Frontends/VBoxManage/VBoxManage.cpp@ 23286

Last change on this file since 23286 was 23286, checked in by vboxsync, 15 years ago

simplification to r52775

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 69.2 KB
Line 
1/* $Id: VBoxManage.cpp 23286 2009-09-24 15:01:36Z vboxsync $ */
2/** @file
3 * VBoxManage - VirtualBox's command-line interface.
4 */
5
6/*
7 * Copyright (C) 2006-2009 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22
23/*******************************************************************************
24* Header Files *
25*******************************************************************************/
26#ifndef VBOX_ONLY_DOCS
27#include <VBox/com/com.h>
28#include <VBox/com/string.h>
29#include <VBox/com/Guid.h>
30#include <VBox/com/array.h>
31#include <VBox/com/ErrorInfo.h>
32#include <VBox/com/errorprint.h>
33#include <VBox/com/EventQueue.h>
34
35#include <VBox/com/VirtualBox.h>
36
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#include <iprt/ctype.h>
45#include <iprt/dir.h>
46#include <iprt/env.h>
47#include <VBox/err.h>
48#include <iprt/file.h>
49#include <iprt/initterm.h>
50#include <iprt/param.h>
51#include <iprt/path.h>
52#include <iprt/stream.h>
53#include <iprt/string.h>
54#include <iprt/stdarg.h>
55#include <iprt/thread.h>
56#include <iprt/uuid.h>
57#include <iprt/getopt.h>
58#include <iprt/ctype.h>
59#include <VBox/version.h>
60#include <VBox/log.h>
61
62#include "VBoxManage.h"
63
64#ifndef VBOX_ONLY_DOCS
65using namespace com;
66
67/** command handler type */
68typedef int (*PFNHANDLER)(HandlerArg *a);
69
70#endif /* !VBOX_ONLY_DOCS */
71
72////////////////////////////////////////////////////////////////////////////////
73//
74// global variables
75//
76////////////////////////////////////////////////////////////////////////////////
77
78/*extern*/ bool g_fDetailedProgress = false;
79
80////////////////////////////////////////////////////////////////////////////////
81//
82// functions
83//
84////////////////////////////////////////////////////////////////////////////////
85
86#ifndef VBOX_ONLY_DOCS
87/**
88 * Print out progress on the console
89 */
90LONG showProgress(ComPtr<IProgress> progress)
91{
92 BOOL fCompleted;
93 ULONG ulCurrentPercent;
94 ULONG ulLastPercent = 0;
95
96 ULONG ulCurrentOperationPercent;
97 ULONG ulLastOperationPercent = (ULONG)-1;
98
99 ULONG ulLastOperation = (ULONG)-1;
100 Bstr bstrOperationDescription;
101
102 ULONG cOperations;
103 progress->COMGETTER(OperationCount)(&cOperations);
104
105 if (!g_fDetailedProgress)
106 {
107 RTPrintf("0%%...");
108 RTStrmFlush(g_pStdOut);
109 }
110
111 while (SUCCEEDED(progress->COMGETTER(Completed(&fCompleted))))
112 {
113 ULONG ulOperation;
114 progress->COMGETTER(Operation)(&ulOperation);
115
116 progress->COMGETTER(Percent(&ulCurrentPercent));
117 progress->COMGETTER(OperationPercent(&ulCurrentOperationPercent));
118
119 if (g_fDetailedProgress)
120 {
121 if (ulLastOperation != ulOperation)
122 {
123 progress->COMGETTER(OperationDescription(bstrOperationDescription.asOutParam()));
124 ulLastPercent = (ULONG)-1; // force print
125 ulLastOperation = ulOperation;
126 }
127
128 if ( (ulCurrentPercent != ulLastPercent)
129 || (ulCurrentOperationPercent != ulLastOperationPercent)
130 )
131 {
132 LONG lSecsRem;
133 progress->COMGETTER(TimeRemaining)(&lSecsRem);
134
135 RTPrintf("(%ld/%ld) %ls %ld%% => %ld%% (%d s remaining)\n", ulOperation + 1, cOperations, bstrOperationDescription.raw(), ulCurrentOperationPercent, ulCurrentPercent, lSecsRem);
136 ulLastPercent = ulCurrentPercent;
137 ulLastOperationPercent = ulCurrentOperationPercent;
138 }
139 }
140 else
141 {
142 /* did we cross a 10% mark? */
143 if (((ulCurrentPercent / 10) > (ulLastPercent / 10)))
144 {
145 /* make sure to also print out missed steps */
146 for (ULONG curVal = (ulLastPercent / 10) * 10 + 10; curVal <= (ulCurrentPercent / 10) * 10; curVal += 10)
147 {
148 if (curVal < 100)
149 {
150 RTPrintf("%ld%%...", curVal);
151 RTStrmFlush(g_pStdOut);
152 }
153 }
154 ulLastPercent = (ulCurrentPercent / 10) * 10;
155 }
156 }
157 if (fCompleted)
158 break;
159
160 /* make sure the loop is not too tight */
161 progress->WaitForCompletion(100);
162 }
163
164 /* complete the line. */
165 LONG iRc;
166 if (SUCCEEDED(progress->COMGETTER(ResultCode)(&iRc)))
167 {
168 if (SUCCEEDED(iRc))
169 RTPrintf("100%%\n");
170 else
171 RTPrintf("FAILED\n");
172 }
173 else
174 RTPrintf("\n");
175 RTStrmFlush(g_pStdOut);
176 return iRc;
177}
178#endif /* !VBOX_ONLY_DOCS */
179
180void showLogo(void)
181{
182 static bool fShown; /* show only once */
183
184 if (!fShown)
185 {
186 RTPrintf("VirtualBox Command Line Management Interface Version "
187 VBOX_VERSION_STRING "\n"
188 "(C) 2005-2009 Sun Microsystems, Inc.\n"
189 "All rights reserved.\n"
190 "\n");
191 fShown = true;
192 }
193}
194
195#ifndef VBOX_ONLY_DOCS
196
197static int handleRegisterVM(HandlerArg *a)
198{
199 HRESULT rc;
200
201 if (a->argc != 1)
202 return errorSyntax(USAGE_REGISTERVM, "Incorrect number of parameters");
203
204 ComPtr<IMachine> machine;
205 /** @todo Ugly hack to get both the API interpretation of relative paths
206 * and the client's interpretation of relative paths. Remove after the API
207 * has been redesigned. */
208 rc = a->virtualBox->OpenMachine(Bstr(a->argv[0]), machine.asOutParam());
209 if (rc == VBOX_E_FILE_ERROR)
210 {
211 char szVMFileAbs[RTPATH_MAX] = "";
212 int vrc = RTPathAbs(a->argv[0], szVMFileAbs, sizeof(szVMFileAbs));
213 if (RT_FAILURE(vrc))
214 {
215 RTPrintf("Cannot convert filename \"%s\" to absolute path\n", a->argv[0]);
216 return 1;
217 }
218 CHECK_ERROR(a->virtualBox, OpenMachine(Bstr(szVMFileAbs), machine.asOutParam()));
219 }
220 else if (FAILED(rc))
221 CHECK_ERROR(a->virtualBox, OpenMachine(Bstr(a->argv[0]), machine.asOutParam()));
222 if (SUCCEEDED(rc))
223 {
224 ASSERT(machine);
225 CHECK_ERROR(a->virtualBox, RegisterMachine(machine));
226 }
227 return SUCCEEDED(rc) ? 0 : 1;
228}
229
230static const RTGETOPTDEF g_aUnregisterVMOptions[] =
231{
232 { "--delete", 'd', RTGETOPT_REQ_NOTHING },
233 { "-delete", 'd', RTGETOPT_REQ_NOTHING }, // deprecated
234};
235
236static int handleUnregisterVM(HandlerArg *a)
237{
238 HRESULT rc;
239 const char *VMName = NULL;
240 bool fDelete = false;
241
242 int c;
243 RTGETOPTUNION ValueUnion;
244 RTGETOPTSTATE GetState;
245 // start at 0 because main() has hacked both the argc and argv given to us
246 RTGetOptInit(&GetState, a->argc, a->argv, g_aUnregisterVMOptions, RT_ELEMENTS(g_aUnregisterVMOptions), 0, 0 /* fFlags */);
247 while ((c = RTGetOpt(&GetState, &ValueUnion)))
248 {
249 switch (c)
250 {
251 case 'd': // --delete
252 fDelete = true;
253 break;
254
255 case VINF_GETOPT_NOT_OPTION:
256 if (!VMName)
257 VMName = ValueUnion.psz;
258 else
259 return errorSyntax(USAGE_UNREGISTERVM, "Invalid parameter '%s'", ValueUnion.psz);
260 break;
261
262 default:
263 if (c > 0)
264 {
265 if (RT_C_IS_PRINT(c))
266 return errorSyntax(USAGE_UNREGISTERVM, "Invalid option -%c", c);
267 else
268 return errorSyntax(USAGE_UNREGISTERVM, "Invalid option case %i", c);
269 }
270 else if (c == VERR_GETOPT_UNKNOWN_OPTION)
271 return errorSyntax(USAGE_UNREGISTERVM, "unknown option: %s\n", ValueUnion.psz);
272 else if (ValueUnion.pDef)
273 return errorSyntax(USAGE_UNREGISTERVM, "%s: %Rrs", ValueUnion.pDef->pszLong, c);
274 else
275 return errorSyntax(USAGE_UNREGISTERVM, "error: %Rrs", c);
276 }
277 }
278
279 /* check for required options */
280 if (!VMName)
281 return errorSyntax(USAGE_UNREGISTERVM, "VM name required");
282
283 ComPtr<IMachine> machine;
284 /* assume it's a UUID */
285 rc = a->virtualBox->GetMachine(Guid(VMName).toUtf16(), machine.asOutParam());
286 if (FAILED(rc) || !machine)
287 {
288 /* must be a name */
289 CHECK_ERROR(a->virtualBox, FindMachine(Bstr(VMName), machine.asOutParam()));
290 }
291 if (machine)
292 {
293 Bstr uuid;
294 machine->COMGETTER(Id)(uuid.asOutParam());
295 machine = NULL;
296 CHECK_ERROR(a->virtualBox, UnregisterMachine(uuid, machine.asOutParam()));
297 if (SUCCEEDED(rc) && machine && fDelete)
298 CHECK_ERROR(machine, DeleteSettings());
299 }
300 return SUCCEEDED(rc) ? 0 : 1;
301}
302
303static int handleCreateVM(HandlerArg *a)
304{
305 HRESULT rc;
306 Bstr baseFolder;
307 Bstr settingsFile;
308 Bstr name;
309 Bstr osTypeId;
310 RTUUID id;
311 bool fRegister = false;
312
313 RTUuidClear(&id);
314 for (int i = 0; i < a->argc; i++)
315 {
316 if ( !strcmp(a->argv[i], "--basefolder")
317 || !strcmp(a->argv[i], "-basefolder"))
318 {
319 if (a->argc <= i + 1)
320 return errorArgument("Missing argument to '%s'", a->argv[i]);
321 i++;
322 baseFolder = a->argv[i];
323 }
324 else if ( !strcmp(a->argv[i], "--settingsfile")
325 || !strcmp(a->argv[i], "-settingsfile"))
326 {
327 if (a->argc <= i + 1)
328 return errorArgument("Missing argument to '%s'", a->argv[i]);
329 i++;
330 settingsFile = a->argv[i];
331 }
332 else if ( !strcmp(a->argv[i], "--name")
333 || !strcmp(a->argv[i], "-name"))
334 {
335 if (a->argc <= i + 1)
336 return errorArgument("Missing argument to '%s'", a->argv[i]);
337 i++;
338 name = a->argv[i];
339 }
340 else if ( !strcmp(a->argv[i], "--ostype")
341 || !strcmp(a->argv[i], "-ostype"))
342 {
343 if (a->argc <= i + 1)
344 return errorArgument("Missing argument to '%s'", a->argv[i]);
345 i++;
346 osTypeId = a->argv[i];
347 }
348 else if ( !strcmp(a->argv[i], "--uuid")
349 || !strcmp(a->argv[i], "-uuid"))
350 {
351 if (a->argc <= i + 1)
352 return errorArgument("Missing argument to '%s'", a->argv[i]);
353 i++;
354 if (RT_FAILURE(RTUuidFromStr(&id, a->argv[i])))
355 return errorArgument("Invalid UUID format %s\n", a->argv[i]);
356 }
357 else if ( !strcmp(a->argv[i], "--register")
358 || !strcmp(a->argv[i], "-register"))
359 {
360 fRegister = true;
361 }
362 else
363 return errorSyntax(USAGE_CREATEVM, "Invalid parameter '%s'", Utf8Str(a->argv[i]).raw());
364 }
365 if (!name)
366 return errorSyntax(USAGE_CREATEVM, "Parameter --name is required");
367
368 if (!!baseFolder && !!settingsFile)
369 return errorSyntax(USAGE_CREATEVM, "Either --basefolder or --settingsfile must be specified");
370
371 do
372 {
373 ComPtr<IMachine> machine;
374
375 if (!settingsFile)
376 CHECK_ERROR_BREAK(a->virtualBox,
377 CreateMachine(name, osTypeId, baseFolder, Guid(id).toUtf16(), machine.asOutParam()));
378 else
379 CHECK_ERROR_BREAK(a->virtualBox,
380 CreateLegacyMachine(name, osTypeId, settingsFile, Guid(id).toUtf16(), machine.asOutParam()));
381
382 CHECK_ERROR_BREAK(machine, SaveSettings());
383 if (fRegister)
384 {
385 CHECK_ERROR_BREAK(a->virtualBox, RegisterMachine(machine));
386 }
387 Bstr uuid;
388 CHECK_ERROR_BREAK(machine, COMGETTER(Id)(uuid.asOutParam()));
389 CHECK_ERROR_BREAK(machine, COMGETTER(SettingsFilePath)(settingsFile.asOutParam()));
390 RTPrintf("Virtual machine '%ls' is created%s.\n"
391 "UUID: %s\n"
392 "Settings file: '%ls'\n",
393 name.raw(), fRegister ? " and registered" : "",
394 Utf8Str(uuid).raw(), settingsFile.raw());
395 }
396 while (0);
397
398 return SUCCEEDED(rc) ? 0 : 1;
399}
400
401/**
402 * Parses a number.
403 *
404 * @returns Valid number on success.
405 * @returns 0 if invalid number. All necesary bitching has been done.
406 * @param psz Pointer to the nic number.
407 */
408unsigned parseNum(const char *psz, unsigned cMaxNum, const char *name)
409{
410 uint32_t u32;
411 char *pszNext;
412 int rc = RTStrToUInt32Ex(psz, &pszNext, 10, &u32);
413 if ( RT_SUCCESS(rc)
414 && *pszNext == '\0'
415 && u32 >= 1
416 && u32 <= cMaxNum)
417 return (unsigned)u32;
418 errorArgument("Invalid %s number '%s'", name, psz);
419 return 0;
420}
421
422
423/** @todo refine this after HDD changes; MSC 8.0/64 has trouble with handleModifyVM. */
424#if defined(_MSC_VER)
425# pragma optimize("", on)
426#endif
427
428static const RTGETOPTDEF g_aStartVMOptions[] =
429{
430 { "--type", 't', RTGETOPT_REQ_STRING },
431 { "-type", 't', RTGETOPT_REQ_STRING }, // deprecated
432};
433
434static int handleStartVM(HandlerArg *a)
435{
436 HRESULT rc;
437 const char *VMName = NULL;
438 Bstr sessionType = "gui";
439
440 int c;
441 RTGETOPTUNION ValueUnion;
442 RTGETOPTSTATE GetState;
443 // start at 0 because main() has hacked both the argc and argv given to us
444 RTGetOptInit(&GetState, a->argc, a->argv, g_aStartVMOptions, RT_ELEMENTS(g_aStartVMOptions), 0, 0 /* fFlags */);
445 while ((c = RTGetOpt(&GetState, &ValueUnion)))
446 {
447 switch (c)
448 {
449 case 't': // --type
450 if (!RTStrICmp(ValueUnion.psz, "gui"))
451 {
452 sessionType = "gui";
453 }
454#ifdef VBOX_WITH_VBOXSDL
455 else if (!RTStrICmp(ValueUnion.psz, "sdl"))
456 {
457 sessionType = "sdl";
458 }
459#endif
460#ifdef VBOX_WITH_VRDP
461 else if (!RTStrICmp(ValueUnion.psz, "vrdp"))
462 {
463 sessionType = "vrdp";
464 }
465#endif
466#ifdef VBOX_WITH_HEADLESS
467 else if (!RTStrICmp(ValueUnion.psz, "capture"))
468 {
469 sessionType = "capture";
470 }
471 else if (!RTStrICmp(ValueUnion.psz, "headless"))
472 {
473 sessionType = "headless";
474 }
475#endif
476 else
477 return errorArgument("Invalid session type '%s'", ValueUnion.psz);
478 break;
479
480 case VINF_GETOPT_NOT_OPTION:
481 if (!VMName)
482 VMName = ValueUnion.psz;
483 else
484 return errorSyntax(USAGE_STARTVM, "Invalid parameter '%s'", ValueUnion.psz);
485 break;
486
487 default:
488 if (c > 0)
489 {
490 if (RT_C_IS_PRINT(c))
491 return errorSyntax(USAGE_STARTVM, "Invalid option -%c", c);
492 else
493 return errorSyntax(USAGE_STARTVM, "Invalid option case %i", c);
494 }
495 else if (c == VERR_GETOPT_UNKNOWN_OPTION)
496 return errorSyntax(USAGE_STARTVM, "unknown option: %s\n", ValueUnion.psz);
497 else if (ValueUnion.pDef)
498 return errorSyntax(USAGE_STARTVM, "%s: %Rrs", ValueUnion.pDef->pszLong, c);
499 else
500 return errorSyntax(USAGE_STARTVM, "error: %Rrs", c);
501 }
502 }
503
504 /* check for required options */
505 if (!VMName)
506 return errorSyntax(USAGE_STARTVM, "VM name required");
507
508 ComPtr<IMachine> machine;
509 /* assume it's a UUID */
510 rc = a->virtualBox->GetMachine(Guid(VMName).toUtf16(), machine.asOutParam());
511 if (FAILED(rc) || !machine)
512 {
513 /* must be a name */
514 CHECK_ERROR(a->virtualBox, FindMachine(Bstr(VMName), machine.asOutParam()));
515 }
516 if (machine)
517 {
518 Bstr uuid;
519 machine->COMGETTER(Id)(uuid.asOutParam());
520
521
522 Bstr env;
523#if defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS)
524 /* make sure the VM process will start on the same display as VBoxManage */
525 Utf8Str str;
526 const char *pszDisplay = RTEnvGet("DISPLAY");
527 str = Utf8StrFmt("DISPLAY=%s\n", pszDisplay);
528 const char *pszXAuth = RTEnvGet("XAUTHORITY");
529 if (pszXAuth)
530 str.append(Utf8StrFmt("XAUTHORITY=%s\n", pszXAuth));
531 env = str;
532#endif
533 ComPtr<IProgress> progress;
534 CHECK_ERROR_RET(a->virtualBox, OpenRemoteSession(a->session, uuid, sessionType,
535 env, progress.asOutParam()), rc);
536 RTPrintf("Waiting for the remote session to open...\n");
537 CHECK_ERROR_RET(progress, WaitForCompletion (-1), 1);
538
539 BOOL completed;
540 CHECK_ERROR_RET(progress, COMGETTER(Completed)(&completed), rc);
541 ASSERT(completed);
542
543 LONG iRc;
544 CHECK_ERROR_RET(progress, COMGETTER(ResultCode)(&iRc), rc);
545 if (FAILED(iRc))
546 {
547 ComPtr <IVirtualBoxErrorInfo> errorInfo;
548 CHECK_ERROR_RET(progress, COMGETTER(ErrorInfo)(errorInfo.asOutParam()), 1);
549 ErrorInfo info (errorInfo);
550 com::GluePrintErrorInfo(info);
551 }
552 else
553 {
554 RTPrintf("Remote session has been successfully opened.\n");
555 }
556 }
557
558 /* it's important to always close sessions */
559 a->session->Close();
560
561 return SUCCEEDED(rc) ? 0 : 1;
562}
563
564static int handleControlVM(HandlerArg *a)
565{
566 HRESULT rc;
567
568 if (a->argc < 2)
569 return errorSyntax(USAGE_CONTROLVM, "Not enough parameters");
570
571 /* try to find the given machine */
572 ComPtr <IMachine> machine;
573 Bstr uuid (a->argv[0]);
574 if (!Guid(uuid).isEmpty())
575 {
576 CHECK_ERROR (a->virtualBox, GetMachine (uuid, machine.asOutParam()));
577 }
578 else
579 {
580 CHECK_ERROR (a->virtualBox, FindMachine (uuid, machine.asOutParam()));
581 if (SUCCEEDED (rc))
582 machine->COMGETTER(Id) (uuid.asOutParam());
583 }
584 if (FAILED (rc))
585 return 1;
586
587 /* open a session for the VM */
588 CHECK_ERROR_RET (a->virtualBox, OpenExistingSession (a->session, uuid), 1);
589
590 do
591 {
592 /* get the associated console */
593 ComPtr<IConsole> console;
594 CHECK_ERROR_BREAK (a->session, COMGETTER(Console)(console.asOutParam()));
595 /* ... and session machine */
596 ComPtr<IMachine> sessionMachine;
597 CHECK_ERROR_BREAK (a->session, COMGETTER(Machine)(sessionMachine.asOutParam()));
598
599 /* which command? */
600 if (!strcmp(a->argv[1], "pause"))
601 {
602 CHECK_ERROR_BREAK (console, Pause());
603 }
604 else if (!strcmp(a->argv[1], "resume"))
605 {
606 CHECK_ERROR_BREAK (console, Resume());
607 }
608 else if (!strcmp(a->argv[1], "reset"))
609 {
610 CHECK_ERROR_BREAK (console, Reset());
611 }
612 else if (!strcmp(a->argv[1], "poweroff"))
613 {
614 ComPtr<IProgress> progress;
615 CHECK_ERROR_BREAK (console, PowerDown(progress.asOutParam()));
616
617 showProgress(progress);
618
619 LONG iRc;
620 progress->COMGETTER(ResultCode)(&iRc);
621 if (FAILED(iRc))
622 {
623 com::ProgressErrorInfo info(progress);
624 if (info.isBasicAvailable())
625 {
626 RTPrintf("Error: failed to power off machine. Error message: %lS\n", info.getText().raw());
627 }
628 else
629 {
630 RTPrintf("Error: failed to power off machine. No error message available!\n");
631 }
632 }
633 }
634 else if (!strcmp(a->argv[1], "savestate"))
635 {
636 ComPtr<IProgress> progress;
637 CHECK_ERROR_BREAK (console, SaveState(progress.asOutParam()));
638
639 showProgress(progress);
640
641 LONG iRc;
642 progress->COMGETTER(ResultCode)(&iRc);
643 if (FAILED(iRc))
644 {
645 com::ProgressErrorInfo info(progress);
646 if (info.isBasicAvailable())
647 {
648 RTPrintf("Error: failed to save machine state. Error message: %lS\n", info.getText().raw());
649 }
650 else
651 {
652 RTPrintf("Error: failed to save machine state. No error message available!\n");
653 }
654 }
655 }
656 else if (!strcmp(a->argv[1], "acpipowerbutton"))
657 {
658 CHECK_ERROR_BREAK (console, PowerButton());
659 }
660 else if (!strcmp(a->argv[1], "acpisleepbutton"))
661 {
662 CHECK_ERROR_BREAK (console, SleepButton());
663 }
664 else if (!strcmp(a->argv[1], "injectnmi"))
665 {
666 /* get the machine debugger. */
667 ComPtr <IMachineDebugger> debugger;
668 CHECK_ERROR_BREAK(console, COMGETTER(Debugger)(debugger.asOutParam()));
669 CHECK_ERROR_BREAK(debugger, InjectNMI());
670 }
671 else if (!strcmp(a->argv[1], "keyboardputscancode"))
672 {
673 ComPtr<IKeyboard> keyboard;
674 CHECK_ERROR_BREAK(console, COMGETTER(Keyboard)(keyboard.asOutParam()));
675
676 if (a->argc <= 1 + 1)
677 {
678 errorArgument("Missing argument to '%s'. Expected IBM PC AT set 2 keyboard scancode(s) as hex byte(s).", a->argv[1]);
679 rc = E_FAIL;
680 break;
681 }
682
683 /* Arbitrary restrict the length of a sequence of scancodes to 1024. */
684 LONG alScancodes[1024];
685 int cScancodes = 0;
686
687 /* Process the command line. */
688 int i;
689 for (i = 1 + 1; i < a->argc && cScancodes < (int)RT_ELEMENTS(alScancodes); i++, cScancodes++)
690 {
691 if ( RT_C_IS_XDIGIT (a->argv[i][0])
692 && RT_C_IS_XDIGIT (a->argv[i][1])
693 && a->argv[i][2] == 0)
694 {
695 uint8_t u8Scancode;
696 int rc = RTStrToUInt8Ex(a->argv[i], NULL, 16, &u8Scancode);
697 if (RT_FAILURE (rc))
698 {
699 RTPrintf("Error: converting '%s' returned %Rrc!\n", a->argv[i], rc);
700 rc = E_FAIL;
701 break;
702 }
703
704 alScancodes[cScancodes] = u8Scancode;
705 }
706 else
707 {
708 RTPrintf("Error: '%s' is not a hex byte!\n", a->argv[i]);
709 rc = E_FAIL;
710 break;
711 }
712 }
713
714 if (FAILED(rc))
715 break;
716
717 if ( cScancodes == RT_ELEMENTS(alScancodes)
718 && i < a->argc)
719 {
720 RTPrintf("Error: too many scancodes, maximum %d allowed!\n", RT_ELEMENTS(alScancodes));
721 rc = E_FAIL;
722 break;
723 }
724
725 /* Send scancodes to the VM.
726 * Note: 'PutScancodes' did not work here. Only the first scancode was transmitted.
727 */
728 for (i = 0; i < cScancodes; i++)
729 {
730 CHECK_ERROR_BREAK(keyboard, PutScancode(alScancodes[i]));
731 RTPrintf("Scancode[%d]: 0x%02X\n", i, alScancodes[i]);
732 }
733 }
734 else if (!strncmp(a->argv[1], "setlinkstate", 12))
735 {
736 /* Get the number of network adapters */
737 ULONG NetworkAdapterCount = 0;
738 ComPtr <ISystemProperties> info;
739 CHECK_ERROR_BREAK (a->virtualBox, COMGETTER(SystemProperties) (info.asOutParam()));
740 CHECK_ERROR_BREAK (info, COMGETTER(NetworkAdapterCount) (&NetworkAdapterCount));
741
742 unsigned n = parseNum(&a->argv[1][12], NetworkAdapterCount, "NIC");
743 if (!n)
744 {
745 rc = E_FAIL;
746 break;
747 }
748 if (a->argc <= 1 + 1)
749 {
750 errorArgument("Missing argument to '%s'", a->argv[1]);
751 rc = E_FAIL;
752 break;
753 }
754 /* get the corresponding network adapter */
755 ComPtr<INetworkAdapter> adapter;
756 CHECK_ERROR_BREAK (sessionMachine, GetNetworkAdapter(n - 1, adapter.asOutParam()));
757 if (adapter)
758 {
759 if (!strcmp(a->argv[2], "on"))
760 {
761 CHECK_ERROR_BREAK (adapter, COMSETTER(CableConnected)(TRUE));
762 }
763 else if (!strcmp(a->argv[2], "off"))
764 {
765 CHECK_ERROR_BREAK (adapter, COMSETTER(CableConnected)(FALSE));
766 }
767 else
768 {
769 errorArgument("Invalid link state '%s'", Utf8Str(a->argv[2]).raw());
770 rc = E_FAIL;
771 break;
772 }
773 }
774 }
775#ifdef VBOX_DYNAMIC_NET_ATTACH
776 /* here the order in which strncmp is called is important
777 * cause nictracefile can be very well compared with
778 * nictrace and nic and thus everything will always fail
779 * if the order is changed
780 */
781 else if (!strncmp(a->argv[1], "nictracefile", 12))
782 {
783 /* Get the number of network adapters */
784 ULONG NetworkAdapterCount = 0;
785 ComPtr <ISystemProperties> info;
786 CHECK_ERROR_BREAK (a->virtualBox, COMGETTER(SystemProperties) (info.asOutParam()));
787 CHECK_ERROR_BREAK (info, COMGETTER(NetworkAdapterCount) (&NetworkAdapterCount));
788
789 unsigned n = parseNum(&a->argv[1][12], NetworkAdapterCount, "NIC");
790 if (!n)
791 {
792 rc = E_FAIL;
793 break;
794 }
795 if (a->argc <= 2)
796 {
797 errorArgument("Missing argument to '%s'", a->argv[1]);
798 rc = E_FAIL;
799 break;
800 }
801
802 /* get the corresponding network adapter */
803 ComPtr<INetworkAdapter> adapter;
804 CHECK_ERROR_BREAK (sessionMachine, GetNetworkAdapter(n - 1, adapter.asOutParam()));
805 if (adapter)
806 {
807 BOOL fEnabled;
808 adapter->COMGETTER(Enabled)(&fEnabled);
809 if (fEnabled)
810 {
811 if (a->argv[2])
812 {
813 CHECK_ERROR_RET(adapter, COMSETTER(TraceFile) (Bstr(a->argv[2])), 1);
814 }
815 else
816 {
817 errorArgument("Invalid filename or filename not specified for NIC %lu", n);
818 rc = E_FAIL;
819 break;
820 }
821 }
822 else
823 {
824 RTPrintf("The NIC %d is currently disabled and thus can't change its tracefile\n", n);
825 }
826 }
827 }
828 else if (!strncmp(a->argv[1], "nictrace", 8))
829 {
830 /* Get the number of network adapters */
831 ULONG NetworkAdapterCount = 0;
832 ComPtr <ISystemProperties> info;
833 CHECK_ERROR_BREAK (a->virtualBox, COMGETTER(SystemProperties) (info.asOutParam()));
834 CHECK_ERROR_BREAK (info, COMGETTER(NetworkAdapterCount) (&NetworkAdapterCount));
835
836 unsigned n = parseNum(&a->argv[1][8], NetworkAdapterCount, "NIC");
837 if (!n)
838 {
839 rc = E_FAIL;
840 break;
841 }
842 if (a->argc <= 2)
843 {
844 errorArgument("Missing argument to '%s'", a->argv[1]);
845 rc = E_FAIL;
846 break;
847 }
848
849 /* get the corresponding network adapter */
850 ComPtr<INetworkAdapter> adapter;
851 CHECK_ERROR_BREAK (sessionMachine, GetNetworkAdapter(n - 1, adapter.asOutParam()));
852 if (adapter)
853 {
854 BOOL fEnabled;
855 adapter->COMGETTER(Enabled)(&fEnabled);
856 if (fEnabled)
857 {
858 if (!strcmp(a->argv[2], "on"))
859 {
860 CHECK_ERROR_RET(adapter, COMSETTER(TraceEnabled)(TRUE), 1);
861 }
862 else if (!strcmp(a->argv[2], "off"))
863 {
864 CHECK_ERROR_RET(adapter, COMSETTER(TraceEnabled)(FALSE), 1);
865 }
866 else
867 {
868 errorArgument("Invalid nictrace%lu argument '%s'", n, Utf8Str(a->argv[2]).raw());
869 rc = E_FAIL;
870 break;
871 }
872 }
873 else
874 {
875 RTPrintf("The NIC %d is currently disabled and thus can't change its tracefile\n", n);
876 }
877 }
878 }
879 else if (!strncmp(a->argv[1], "nic", 3))
880 {
881 /* Get the number of network adapters */
882 ULONG NetworkAdapterCount = 0;
883 ComPtr <ISystemProperties> info;
884 CHECK_ERROR_BREAK (a->virtualBox, COMGETTER(SystemProperties) (info.asOutParam()));
885 CHECK_ERROR_BREAK (info, COMGETTER(NetworkAdapterCount) (&NetworkAdapterCount));
886
887 unsigned n = parseNum(&a->argv[1][3], NetworkAdapterCount, "NIC");
888 if (!n)
889 {
890 rc = E_FAIL;
891 break;
892 }
893 if (a->argc <= 2)
894 {
895 errorArgument("Missing argument to '%s'", a->argv[1]);
896 rc = E_FAIL;
897 break;
898 }
899
900 /* get the corresponding network adapter */
901 ComPtr<INetworkAdapter> adapter;
902 CHECK_ERROR_BREAK (sessionMachine, GetNetworkAdapter(n - 1, adapter.asOutParam()));
903 if (adapter)
904 {
905 BOOL fEnabled;
906 adapter->COMGETTER(Enabled)(&fEnabled);
907 if (fEnabled)
908 {
909 if (!strcmp(a->argv[2], "null"))
910 {
911 CHECK_ERROR_RET(adapter, COMSETTER(Enabled) (TRUE), 1);
912 CHECK_ERROR_RET(adapter, Detach(), 1);
913 }
914 else if (!strcmp(a->argv[2], "nat"))
915 {
916 CHECK_ERROR_RET(adapter, COMSETTER(Enabled) (TRUE), 1);
917 if (a->argc == 4)
918 CHECK_ERROR_RET(adapter, COMSETTER(NATNetwork)(Bstr(a->argv[3])), 1);
919 CHECK_ERROR_RET(adapter, AttachToNAT(), 1);
920 }
921 else if ( !strcmp(a->argv[2], "bridged")
922 || !strcmp(a->argv[2], "hostif")) /* backward compatibility */
923 {
924 if (a->argc <= 3)
925 {
926 errorArgument("Missing argument to '%s'", a->argv[2]);
927 rc = E_FAIL;
928 break;
929 }
930 CHECK_ERROR_RET(adapter, COMSETTER(Enabled) (TRUE), 1);
931 CHECK_ERROR_RET(adapter, COMSETTER(HostInterface)(Bstr(a->argv[3])), 1);
932 CHECK_ERROR_RET(adapter, AttachToBridgedInterface(), 1);
933 }
934 else if (!strcmp(a->argv[2], "intnet"))
935 {
936 if (a->argc <= 3)
937 {
938 errorArgument("Missing argument to '%s'", a->argv[2]);
939 rc = E_FAIL;
940 break;
941 }
942 CHECK_ERROR_RET(adapter, COMSETTER(Enabled) (TRUE), 1);
943 CHECK_ERROR_RET(adapter, COMSETTER(InternalNetwork)(Bstr(a->argv[3])), 1);
944 CHECK_ERROR_RET(adapter, AttachToInternalNetwork(), 1);
945 }
946#if defined(VBOX_WITH_NETFLT)
947 else if (!strcmp(a->argv[2], "hostonly"))
948 {
949 if (a->argc <= 3)
950 {
951 errorArgument("Missing argument to '%s'", a->argv[2]);
952 rc = E_FAIL;
953 break;
954 }
955 CHECK_ERROR_RET(adapter, COMSETTER(Enabled) (TRUE), 1);
956 CHECK_ERROR_RET(adapter, COMSETTER(HostInterface)(Bstr(a->argv[3])), 1);
957 CHECK_ERROR_RET(adapter, AttachToHostOnlyInterface(), 1);
958 }
959#endif
960 else
961 {
962 errorArgument("Invalid type '%s' specfied for NIC %lu", Utf8Str(a->argv[2]).raw(), n);
963 rc = E_FAIL;
964 break;
965 }
966 }
967 else
968 {
969 RTPrintf("The NIC %d is currently disabled and thus can't change its attachment type\n", n);
970 }
971 }
972 }
973#endif /* VBOX_DYNAMIC_NET_ATTACH */
974#ifdef VBOX_WITH_VRDP
975 else if (!strcmp(a->argv[1], "vrdp"))
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 if (!strcmp(a->argv[2], "on"))
990 {
991 CHECK_ERROR_BREAK (vrdpServer, COMSETTER(Enabled)(TRUE));
992 }
993 else if (!strcmp(a->argv[2], "off"))
994 {
995 CHECK_ERROR_BREAK (vrdpServer, COMSETTER(Enabled)(FALSE));
996 }
997 else
998 {
999 errorArgument("Invalid vrdp server state '%s'", Utf8Str(a->argv[2]).raw());
1000 rc = E_FAIL;
1001 break;
1002 }
1003 }
1004 }
1005 else if (!strcmp(a->argv[1], "vrdpport"))
1006 {
1007 if (a->argc <= 1 + 1)
1008 {
1009 errorArgument("Missing argument to '%s'", a->argv[1]);
1010 rc = E_FAIL;
1011 break;
1012 }
1013 /* get the corresponding VRDP server */
1014 ComPtr<IVRDPServer> vrdpServer;
1015 sessionMachine->COMGETTER(VRDPServer)(vrdpServer.asOutParam());
1016 ASSERT(vrdpServer);
1017 if (vrdpServer)
1018 {
1019 uint16_t vrdpport;
1020
1021 if (!strcmp(a->argv[2], "default"))
1022 {
1023 vrdpport = 0;
1024 }
1025 else
1026 {
1027 int vrc = RTStrToUInt16Full(a->argv[2], 0, &vrdpport);
1028
1029 if (vrc != VINF_SUCCESS)
1030 {
1031 vrdpport = UINT16_MAX;
1032 }
1033 }
1034
1035 if (vrdpport != UINT16_MAX)
1036 {
1037 CHECK_ERROR_BREAK(vrdpServer, COMSETTER(Port)(vrdpport));
1038 }
1039 else
1040 {
1041 errorArgument("Invalid vrdp server port '%s'", Utf8Str(a->argv[2]).raw());
1042 rc = E_FAIL;
1043 break;
1044 }
1045 }
1046 }
1047#endif /* VBOX_WITH_VRDP */
1048 else if ( !strcmp (a->argv[1], "usbattach")
1049 || !strcmp (a->argv[1], "usbdetach"))
1050 {
1051 if (a->argc < 3)
1052 {
1053 errorSyntax(USAGE_CONTROLVM, "Not enough parameters");
1054 rc = E_FAIL;
1055 break;
1056 }
1057
1058 bool attach = !strcmp(a->argv[1], "usbattach");
1059
1060 Bstr usbId = a->argv [2];
1061 if (Guid(usbId).isEmpty())
1062 {
1063 // assume address
1064 if (attach)
1065 {
1066 ComPtr <IHost> host;
1067 CHECK_ERROR_BREAK (a->virtualBox, COMGETTER(Host) (host.asOutParam()));
1068 SafeIfaceArray <IHostUSBDevice> coll;
1069 CHECK_ERROR_BREAK (host, COMGETTER(USBDevices) (ComSafeArrayAsOutParam(coll)));
1070 ComPtr <IHostUSBDevice> dev;
1071 CHECK_ERROR_BREAK (host, FindUSBDeviceByAddress (Bstr (a->argv [2]), dev.asOutParam()));
1072 CHECK_ERROR_BREAK (dev, COMGETTER(Id) (usbId.asOutParam()));
1073 }
1074 else
1075 {
1076 SafeIfaceArray <IUSBDevice> coll;
1077 CHECK_ERROR_BREAK (console, COMGETTER(USBDevices)(ComSafeArrayAsOutParam(coll)));
1078 ComPtr <IUSBDevice> dev;
1079 CHECK_ERROR_BREAK (console, FindUSBDeviceByAddress (Bstr (a->argv [2]),
1080 dev.asOutParam()));
1081 CHECK_ERROR_BREAK (dev, COMGETTER(Id) (usbId.asOutParam()));
1082 }
1083 }
1084
1085 if (attach)
1086 CHECK_ERROR_BREAK (console, AttachUSBDevice (usbId));
1087 else
1088 {
1089 ComPtr <IUSBDevice> dev;
1090 CHECK_ERROR_BREAK (console, DetachUSBDevice (usbId, dev.asOutParam()));
1091 }
1092 }
1093 else if (!strcmp(a->argv[1], "setvideomodehint"))
1094 {
1095 if (a->argc != 5 && a->argc != 6)
1096 {
1097 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
1098 rc = E_FAIL;
1099 break;
1100 }
1101 uint32_t xres = RTStrToUInt32(a->argv[2]);
1102 uint32_t yres = RTStrToUInt32(a->argv[3]);
1103 uint32_t bpp = RTStrToUInt32(a->argv[4]);
1104 uint32_t displayIdx = 0;
1105 if (a->argc == 6)
1106 displayIdx = RTStrToUInt32(a->argv[5]);
1107
1108 ComPtr<IDisplay> display;
1109 CHECK_ERROR_BREAK(console, COMGETTER(Display)(display.asOutParam()));
1110 CHECK_ERROR_BREAK(display, SetVideoModeHint(xres, yres, bpp, displayIdx));
1111 }
1112 else if (!strcmp(a->argv[1], "setcredentials"))
1113 {
1114 bool fAllowLocalLogon = true;
1115 if (a->argc == 7)
1116 {
1117 if ( strcmp(a->argv[5], "--allowlocallogon")
1118 && strcmp(a->argv[5], "-allowlocallogon"))
1119 {
1120 errorArgument("Invalid parameter '%s'", a->argv[5]);
1121 rc = E_FAIL;
1122 break;
1123 }
1124 if (!strcmp(a->argv[6], "no"))
1125 fAllowLocalLogon = false;
1126 }
1127 else if (a->argc != 5)
1128 {
1129 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
1130 rc = E_FAIL;
1131 break;
1132 }
1133
1134 ComPtr<IGuest> guest;
1135 CHECK_ERROR_BREAK(console, COMGETTER(Guest)(guest.asOutParam()));
1136 CHECK_ERROR_BREAK(guest, SetCredentials(Bstr(a->argv[2]), Bstr(a->argv[3]), Bstr(a->argv[4]), fAllowLocalLogon));
1137 }
1138 else if (!strcmp(a->argv[1], "dvdattach"))
1139 {
1140 if (a->argc != 3)
1141 {
1142 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
1143 rc = E_FAIL;
1144 break;
1145 }
1146
1147 ComPtr<IMedium> dvdMedium;
1148
1149 /* unmount? */
1150 if (!strcmp(a->argv[2], "none"))
1151 {
1152 /* nothing to do, NULL object will cause unmount */
1153 }
1154 /* host drive? */
1155 else if (!strncmp(a->argv[2], "host:", 5))
1156 {
1157 ComPtr<IHost> host;
1158 CHECK_ERROR(a->virtualBox, COMGETTER(Host)(host.asOutParam()));
1159
1160 rc = host->FindHostDVDDrive(Bstr(a->argv[2] + 5), dvdMedium.asOutParam());
1161 if (!dvdMedium)
1162 {
1163 errorArgument("Invalid host DVD drive name \"%s\"",
1164 a->argv[2] + 5);
1165 rc = E_FAIL;
1166 break;
1167 }
1168 }
1169 else
1170 {
1171 /* first assume it's a UUID */
1172 Bstr uuid(a->argv[2]);
1173 rc = a->virtualBox->GetDVDImage(uuid, dvdMedium.asOutParam());
1174 if (FAILED(rc) || !dvdMedium)
1175 {
1176 /* must be a filename, check if it's in the collection */
1177 rc = a->virtualBox->FindDVDImage(Bstr(a->argv[2]), dvdMedium.asOutParam());
1178 /* not registered, do that on the fly */
1179 if (!dvdMedium)
1180 {
1181 Bstr emptyUUID;
1182 CHECK_ERROR(a->virtualBox, OpenDVDImage(Bstr(a->argv[2]), emptyUUID, dvdMedium.asOutParam()));
1183 }
1184 }
1185 if (!dvdMedium)
1186 {
1187 rc = E_FAIL;
1188 break;
1189 }
1190 }
1191
1192 /** @todo generalize this, allow arbitrary number of DVD drives
1193 * and as a consequence multiple attachments and different
1194 * storage controllers. */
1195 if (dvdMedium)
1196 dvdMedium->COMGETTER(Id)(uuid.asOutParam());
1197 else
1198 uuid = Guid().toString();
1199 CHECK_ERROR(machine, MountMedium(Bstr("IDE Controller"), 1, 0, uuid));
1200 }
1201 else if (!strcmp(a->argv[1], "floppyattach"))
1202 {
1203 if (a->argc != 3)
1204 {
1205 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
1206 rc = E_FAIL;
1207 break;
1208 }
1209
1210 ComPtr<IMedium> floppyMedium;
1211
1212 /* unmount? */
1213 if (!strcmp(a->argv[2], "none"))
1214 {
1215 /* nothing to do, NULL object will cause unmount */
1216 }
1217 /* host drive? */
1218 else if (!strncmp(a->argv[2], "host:", 5))
1219 {
1220 ComPtr<IHost> host;
1221 CHECK_ERROR(a->virtualBox, COMGETTER(Host)(host.asOutParam()));
1222 host->FindHostFloppyDrive(Bstr(a->argv[2] + 5), floppyMedium.asOutParam());
1223 if (!floppyMedium)
1224 {
1225 errorArgument("Invalid host floppy drive name \"%s\"",
1226 a->argv[2] + 5);
1227 rc = E_FAIL;
1228 break;
1229 }
1230 }
1231 else
1232 {
1233 /* first assume it's a UUID */
1234 Bstr uuid(a->argv[2]);
1235 rc = a->virtualBox->GetFloppyImage(uuid, floppyMedium.asOutParam());
1236 if (FAILED(rc) || !floppyMedium)
1237 {
1238 /* must be a filename, check if it's in the collection */
1239 rc = a->virtualBox->FindFloppyImage(Bstr(a->argv[2]), floppyMedium.asOutParam());
1240 /* not registered, do that on the fly */
1241 if (!floppyMedium)
1242 {
1243 Bstr emptyUUID;
1244 CHECK_ERROR(a->virtualBox, OpenFloppyImage(Bstr(a->argv[2]), emptyUUID, floppyMedium.asOutParam()));
1245 }
1246 }
1247 if (!floppyMedium)
1248 {
1249 rc = E_FAIL;
1250 break;
1251 }
1252 }
1253 floppyMedium->COMGETTER(Id)(uuid.asOutParam());
1254 CHECK_ERROR(machine, MountMedium(Bstr("Floppy Controller"), 0, 0, uuid));
1255 }
1256#ifdef VBOX_WITH_MEM_BALLOONING
1257 else if ( !strcmp(a->argv[1], "--guestmemoryballoon")
1258 || !strcmp(a->argv[1], "-guestmemoryballoon"))
1259 {
1260 if (a->argc != 3)
1261 {
1262 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
1263 rc = E_FAIL;
1264 break;
1265 }
1266 uint32_t uVal;
1267 int vrc;
1268 vrc = RTStrToUInt32Ex(a->argv[2], NULL, 0, &uVal);
1269 if (vrc != VINF_SUCCESS)
1270 {
1271 errorArgument("Error parsing guest memory balloon size '%s'", a->argv[2]);
1272 rc = E_FAIL;
1273 break;
1274 }
1275
1276 /* guest is running; update IGuest */
1277 ComPtr <IGuest> guest;
1278
1279 rc = console->COMGETTER(Guest)(guest.asOutParam());
1280 if (SUCCEEDED(rc))
1281 CHECK_ERROR(guest, COMSETTER(MemoryBalloonSize)(uVal));
1282 }
1283#endif
1284 else if ( !strcmp(a->argv[1], "--gueststatisticsinterval")
1285 || !strcmp(a->argv[1], "-gueststatisticsinterval"))
1286 {
1287 if (a->argc != 3)
1288 {
1289 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
1290 rc = E_FAIL;
1291 break;
1292 }
1293 uint32_t uVal;
1294 int vrc;
1295 vrc = RTStrToUInt32Ex(a->argv[2], NULL, 0, &uVal);
1296 if (vrc != VINF_SUCCESS)
1297 {
1298 errorArgument("Error parsing guest statistics interval '%s'", a->argv[2]);
1299 rc = E_FAIL;
1300 break;
1301 }
1302
1303 /* guest is running; update IGuest */
1304 ComPtr <IGuest> guest;
1305
1306 rc = console->COMGETTER(Guest)(guest.asOutParam());
1307 if (SUCCEEDED(rc))
1308 CHECK_ERROR(guest, COMSETTER(StatisticsUpdateInterval)(uVal));
1309 }
1310 else
1311 {
1312 errorSyntax(USAGE_CONTROLVM, "Invalid parameter '%s'", Utf8Str(a->argv[1]).raw());
1313 rc = E_FAIL;
1314 }
1315 }
1316 while (0);
1317
1318 a->session->Close();
1319
1320 return SUCCEEDED (rc) ? 0 : 1;
1321}
1322
1323static int handleDiscardState(HandlerArg *a)
1324{
1325 HRESULT rc;
1326
1327 if (a->argc != 1)
1328 return errorSyntax(USAGE_DISCARDSTATE, "Incorrect number of parameters");
1329
1330 ComPtr<IMachine> machine;
1331 /* assume it's a UUID */
1332 rc = a->virtualBox->GetMachine(Bstr(a->argv[0]), machine.asOutParam());
1333 if (FAILED(rc) || !machine)
1334 {
1335 /* must be a name */
1336 CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]), machine.asOutParam()));
1337 }
1338 if (machine)
1339 {
1340 do
1341 {
1342 /* we have to open a session for this task */
1343 Bstr guid;
1344 machine->COMGETTER(Id)(guid.asOutParam());
1345 CHECK_ERROR_BREAK(a->virtualBox, OpenSession(a->session, guid));
1346 do
1347 {
1348 ComPtr<IConsole> console;
1349 CHECK_ERROR_BREAK(a->session, COMGETTER(Console)(console.asOutParam()));
1350 CHECK_ERROR_BREAK(console, ForgetSavedState(true));
1351 }
1352 while (0);
1353 CHECK_ERROR_BREAK(a->session, Close());
1354 }
1355 while (0);
1356 }
1357
1358 return SUCCEEDED(rc) ? 0 : 1;
1359}
1360
1361static int handleAdoptdState(HandlerArg *a)
1362{
1363 HRESULT rc;
1364
1365 if (a->argc != 2)
1366 return errorSyntax(USAGE_ADOPTSTATE, "Incorrect number of parameters");
1367
1368 ComPtr<IMachine> machine;
1369 /* assume it's a UUID */
1370 rc = a->virtualBox->GetMachine(Bstr(a->argv[0]), machine.asOutParam());
1371 if (FAILED(rc) || !machine)
1372 {
1373 /* must be a name */
1374 CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]), machine.asOutParam()));
1375 }
1376 if (machine)
1377 {
1378 do
1379 {
1380 /* we have to open a session for this task */
1381 Bstr guid;
1382 machine->COMGETTER(Id)(guid.asOutParam());
1383 CHECK_ERROR_BREAK(a->virtualBox, OpenSession(a->session, guid));
1384 do
1385 {
1386 ComPtr<IConsole> console;
1387 CHECK_ERROR_BREAK(a->session, COMGETTER(Console)(console.asOutParam()));
1388 CHECK_ERROR_BREAK(console, AdoptSavedState (Bstr (a->argv[1])));
1389 }
1390 while (0);
1391 CHECK_ERROR_BREAK(a->session, Close());
1392 }
1393 while (0);
1394 }
1395
1396 return SUCCEEDED(rc) ? 0 : 1;
1397}
1398
1399static int handleGetExtraData(HandlerArg *a)
1400{
1401 HRESULT rc = S_OK;
1402
1403 if (a->argc != 2)
1404 return errorSyntax(USAGE_GETEXTRADATA, "Incorrect number of parameters");
1405
1406 /* global data? */
1407 if (!strcmp(a->argv[0], "global"))
1408 {
1409 /* enumeration? */
1410 if (!strcmp(a->argv[1], "enumerate"))
1411 {
1412 SafeArray<BSTR> aKeys;
1413 CHECK_ERROR(a->virtualBox, GetExtraDataKeys(ComSafeArrayAsOutParam(aKeys)));
1414
1415 for (size_t i = 0;
1416 i < aKeys.size();
1417 ++i)
1418 {
1419 Bstr bstrKey(aKeys[i]);
1420 Bstr bstrValue;
1421 CHECK_ERROR(a->virtualBox, GetExtraData(bstrKey, bstrValue.asOutParam()));
1422
1423 RTPrintf("Key: %lS, Value: %lS\n", bstrKey.raw(), bstrValue.raw());
1424 }
1425 }
1426 else
1427 {
1428 Bstr value;
1429 CHECK_ERROR(a->virtualBox, GetExtraData(Bstr(a->argv[1]), value.asOutParam()));
1430 if (!value.isEmpty())
1431 RTPrintf("Value: %lS\n", value.raw());
1432 else
1433 RTPrintf("No value set!\n");
1434 }
1435 }
1436 else
1437 {
1438 ComPtr<IMachine> machine;
1439 /* assume it's a UUID */
1440 rc = a->virtualBox->GetMachine(Bstr(a->argv[0]), machine.asOutParam());
1441 if (FAILED(rc) || !machine)
1442 {
1443 /* must be a name */
1444 CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]), machine.asOutParam()));
1445 }
1446 if (machine)
1447 {
1448 /* enumeration? */
1449 if (!strcmp(a->argv[1], "enumerate"))
1450 {
1451 SafeArray<BSTR> aKeys;
1452 CHECK_ERROR(machine, GetExtraDataKeys(ComSafeArrayAsOutParam(aKeys)));
1453
1454 for (size_t i = 0;
1455 i < aKeys.size();
1456 ++i)
1457 {
1458 Bstr bstrKey(aKeys[i]);
1459 Bstr bstrValue;
1460 CHECK_ERROR(machine, GetExtraData(bstrKey, bstrValue.asOutParam()));
1461
1462 RTPrintf("Key: %lS, Value: %lS\n", bstrKey.raw(), bstrValue.raw());
1463 }
1464 }
1465 else
1466 {
1467 Bstr value;
1468 CHECK_ERROR(machine, GetExtraData(Bstr(a->argv[1]), value.asOutParam()));
1469 if (!value.isEmpty())
1470 RTPrintf("Value: %lS\n", value.raw());
1471 else
1472 RTPrintf("No value set!\n");
1473 }
1474 }
1475 }
1476 return SUCCEEDED(rc) ? 0 : 1;
1477}
1478
1479static int handleSetExtraData(HandlerArg *a)
1480{
1481 HRESULT rc = S_OK;
1482
1483 if (a->argc < 2)
1484 return errorSyntax(USAGE_SETEXTRADATA, "Not enough parameters");
1485
1486 /* global data? */
1487 if (!strcmp(a->argv[0], "global"))
1488 {
1489 if (a->argc < 3)
1490 CHECK_ERROR(a->virtualBox, SetExtraData(Bstr(a->argv[1]), NULL));
1491 else if (a->argc == 3)
1492 CHECK_ERROR(a->virtualBox, SetExtraData(Bstr(a->argv[1]), Bstr(a->argv[2])));
1493 else
1494 return errorSyntax(USAGE_SETEXTRADATA, "Too many parameters");
1495 }
1496 else
1497 {
1498 ComPtr<IMachine> machine;
1499 /* assume it's a UUID */
1500 rc = a->virtualBox->GetMachine(Bstr(a->argv[0]), machine.asOutParam());
1501 if (FAILED(rc) || !machine)
1502 {
1503 /* must be a name */
1504 CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]), machine.asOutParam()));
1505 }
1506 if (machine)
1507 {
1508 if (a->argc < 3)
1509 CHECK_ERROR(machine, SetExtraData(Bstr(a->argv[1]), NULL));
1510 else if (a->argc == 3)
1511 CHECK_ERROR(machine, SetExtraData(Bstr(a->argv[1]), Bstr(a->argv[2])));
1512 else
1513 return errorSyntax(USAGE_SETEXTRADATA, "Too many parameters");
1514 }
1515 }
1516 return SUCCEEDED(rc) ? 0 : 1;
1517}
1518
1519static int handleSetProperty(HandlerArg *a)
1520{
1521 HRESULT rc;
1522
1523 /* there must be two arguments: property name and value */
1524 if (a->argc != 2)
1525 return errorSyntax(USAGE_SETPROPERTY, "Incorrect number of parameters");
1526
1527 ComPtr<ISystemProperties> systemProperties;
1528 a->virtualBox->COMGETTER(SystemProperties)(systemProperties.asOutParam());
1529
1530 if (!strcmp(a->argv[0], "hdfolder"))
1531 {
1532 /* reset to default? */
1533 if (!strcmp(a->argv[1], "default"))
1534 CHECK_ERROR(systemProperties, COMSETTER(DefaultHardDiskFolder)(NULL));
1535 else
1536 CHECK_ERROR(systemProperties, COMSETTER(DefaultHardDiskFolder)(Bstr(a->argv[1])));
1537 }
1538 else if (!strcmp(a->argv[0], "machinefolder"))
1539 {
1540 /* reset to default? */
1541 if (!strcmp(a->argv[1], "default"))
1542 CHECK_ERROR(systemProperties, COMSETTER(DefaultMachineFolder)(NULL));
1543 else
1544 CHECK_ERROR(systemProperties, COMSETTER(DefaultMachineFolder)(Bstr(a->argv[1])));
1545 }
1546 else if (!strcmp(a->argv[0], "vrdpauthlibrary"))
1547 {
1548 /* reset to default? */
1549 if (!strcmp(a->argv[1], "default"))
1550 CHECK_ERROR(systemProperties, COMSETTER(RemoteDisplayAuthLibrary)(NULL));
1551 else
1552 CHECK_ERROR(systemProperties, COMSETTER(RemoteDisplayAuthLibrary)(Bstr(a->argv[1])));
1553 }
1554 else if (!strcmp(a->argv[0], "websrvauthlibrary"))
1555 {
1556 /* reset to default? */
1557 if (!strcmp(a->argv[1], "default"))
1558 CHECK_ERROR(systemProperties, COMSETTER(WebServiceAuthLibrary)(NULL));
1559 else
1560 CHECK_ERROR(systemProperties, COMSETTER(WebServiceAuthLibrary)(Bstr(a->argv[1])));
1561 }
1562 else if (!strcmp(a->argv[0], "loghistorycount"))
1563 {
1564 uint32_t uVal;
1565 int vrc;
1566 vrc = RTStrToUInt32Ex(a->argv[1], NULL, 0, &uVal);
1567 if (vrc != VINF_SUCCESS)
1568 return errorArgument("Error parsing Log history count '%s'", a->argv[1]);
1569 CHECK_ERROR(systemProperties, COMSETTER(LogHistoryCount)(uVal));
1570 }
1571 else
1572 return errorSyntax(USAGE_SETPROPERTY, "Invalid parameter '%s'", a->argv[0]);
1573
1574 return SUCCEEDED(rc) ? 0 : 1;
1575}
1576
1577static int handleSharedFolder (HandlerArg *a)
1578{
1579 HRESULT rc;
1580
1581 /* we need at least a command and target */
1582 if (a->argc < 2)
1583 return errorSyntax(USAGE_SHAREDFOLDER, "Not enough parameters");
1584
1585 ComPtr<IMachine> machine;
1586 /* assume it's a UUID */
1587 rc = a->virtualBox->GetMachine(Bstr(a->argv[1]), machine.asOutParam());
1588 if (FAILED(rc) || !machine)
1589 {
1590 /* must be a name */
1591 CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[1]), machine.asOutParam()));
1592 }
1593 if (!machine)
1594 return 1;
1595 Bstr uuid;
1596 machine->COMGETTER(Id)(uuid.asOutParam());
1597
1598 if (!strcmp(a->argv[0], "add"))
1599 {
1600 /* we need at least four more parameters */
1601 if (a->argc < 5)
1602 return errorSyntax(USAGE_SHAREDFOLDER_ADD, "Not enough parameters");
1603
1604 char *name = NULL;
1605 char *hostpath = NULL;
1606 bool fTransient = false;
1607 bool fWritable = true;
1608
1609 for (int i = 2; i < a->argc; i++)
1610 {
1611 if ( !strcmp(a->argv[i], "--name")
1612 || !strcmp(a->argv[i], "-name"))
1613 {
1614 if (a->argc <= i + 1 || !*a->argv[i+1])
1615 return errorArgument("Missing argument to '%s'", a->argv[i]);
1616 i++;
1617 name = a->argv[i];
1618 }
1619 else if ( !strcmp(a->argv[i], "--hostpath")
1620 || !strcmp(a->argv[i], "-hostpath"))
1621 {
1622 if (a->argc <= i + 1 || !*a->argv[i+1])
1623 return errorArgument("Missing argument to '%s'", a->argv[i]);
1624 i++;
1625 hostpath = a->argv[i];
1626 }
1627 else if ( !strcmp(a->argv[i], "--readonly")
1628 || !strcmp(a->argv[i], "-readonly"))
1629 {
1630 fWritable = false;
1631 }
1632 else if ( !strcmp(a->argv[i], "--transient")
1633 || !strcmp(a->argv[i], "-transient"))
1634 {
1635 fTransient = true;
1636 }
1637 else
1638 return errorSyntax(USAGE_SHAREDFOLDER_ADD, "Invalid parameter '%s'", Utf8Str(a->argv[i]).raw());
1639 }
1640
1641 if (NULL != strstr(name, " "))
1642 return errorSyntax(USAGE_SHAREDFOLDER_ADD, "No spaces allowed in parameter '-name'!");
1643
1644 /* required arguments */
1645 if (!name || !hostpath)
1646 {
1647 return errorSyntax(USAGE_SHAREDFOLDER_ADD, "Parameters --name and --hostpath are required");
1648 }
1649
1650 if (fTransient)
1651 {
1652 ComPtr <IConsole> console;
1653
1654 /* open an existing session for the VM */
1655 CHECK_ERROR_RET(a->virtualBox, OpenExistingSession (a->session, uuid), 1);
1656 /* get the session machine */
1657 CHECK_ERROR_RET(a->session, COMGETTER(Machine)(machine.asOutParam()), 1);
1658 /* get the session console */
1659 CHECK_ERROR_RET(a->session, COMGETTER(Console)(console.asOutParam()), 1);
1660
1661 CHECK_ERROR(console, CreateSharedFolder(Bstr(name), Bstr(hostpath), fWritable));
1662
1663 if (console)
1664 a->session->Close();
1665 }
1666 else
1667 {
1668 /* open a session for the VM */
1669 CHECK_ERROR_RET (a->virtualBox, OpenSession(a->session, uuid), 1);
1670
1671 /* get the mutable session machine */
1672 a->session->COMGETTER(Machine)(machine.asOutParam());
1673
1674 CHECK_ERROR(machine, CreateSharedFolder(Bstr(name), Bstr(hostpath), fWritable));
1675
1676 if (SUCCEEDED(rc))
1677 CHECK_ERROR(machine, SaveSettings());
1678
1679 a->session->Close();
1680 }
1681 }
1682 else if (!strcmp(a->argv[0], "remove"))
1683 {
1684 /* we need at least two more parameters */
1685 if (a->argc < 3)
1686 return errorSyntax(USAGE_SHAREDFOLDER_REMOVE, "Not enough parameters");
1687
1688 char *name = NULL;
1689 bool fTransient = false;
1690
1691 for (int i = 2; i < a->argc; i++)
1692 {
1693 if ( !strcmp(a->argv[i], "--name")
1694 || !strcmp(a->argv[i], "-name"))
1695 {
1696 if (a->argc <= i + 1 || !*a->argv[i+1])
1697 return errorArgument("Missing argument to '%s'", a->argv[i]);
1698 i++;
1699 name = a->argv[i];
1700 }
1701 else if ( !strcmp(a->argv[i], "--transient")
1702 || !strcmp(a->argv[i], "-transient"))
1703 {
1704 fTransient = true;
1705 }
1706 else
1707 return errorSyntax(USAGE_SHAREDFOLDER_REMOVE, "Invalid parameter '%s'", Utf8Str(a->argv[i]).raw());
1708 }
1709
1710 /* required arguments */
1711 if (!name)
1712 return errorSyntax(USAGE_SHAREDFOLDER_REMOVE, "Parameter --name is required");
1713
1714 if (fTransient)
1715 {
1716 ComPtr <IConsole> console;
1717
1718 /* open an existing session for the VM */
1719 CHECK_ERROR_RET(a->virtualBox, OpenExistingSession (a->session, uuid), 1);
1720 /* get the session machine */
1721 CHECK_ERROR_RET(a->session, COMGETTER(Machine)(machine.asOutParam()), 1);
1722 /* get the session console */
1723 CHECK_ERROR_RET(a->session, COMGETTER(Console)(console.asOutParam()), 1);
1724
1725 CHECK_ERROR(console, RemoveSharedFolder(Bstr(name)));
1726
1727 if (console)
1728 a->session->Close();
1729 }
1730 else
1731 {
1732 /* open a session for the VM */
1733 CHECK_ERROR_RET (a->virtualBox, OpenSession(a->session, uuid), 1);
1734
1735 /* get the mutable session machine */
1736 a->session->COMGETTER(Machine)(machine.asOutParam());
1737
1738 CHECK_ERROR(machine, RemoveSharedFolder(Bstr(name)));
1739
1740 /* commit and close the session */
1741 CHECK_ERROR(machine, SaveSettings());
1742 a->session->Close();
1743 }
1744 }
1745 else
1746 return errorSyntax(USAGE_SETPROPERTY, "Invalid parameter '%s'", Utf8Str(a->argv[0]).raw());
1747
1748 return 0;
1749}
1750
1751static int handleVMStatistics(HandlerArg *a)
1752{
1753 HRESULT rc;
1754
1755 /* at least one option: the UUID or name of the VM */
1756 if (a->argc < 1)
1757 return errorSyntax(USAGE_VM_STATISTICS, "Incorrect number of parameters");
1758
1759 /* try to find the given machine */
1760 ComPtr <IMachine> machine;
1761 Bstr uuid (a->argv[0]);
1762 if (!Guid (a->argv[0]).isEmpty())
1763 CHECK_ERROR(a->virtualBox, GetMachine(uuid, machine.asOutParam()));
1764 else
1765 {
1766 CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]), machine.asOutParam()));
1767 if (SUCCEEDED (rc))
1768 machine->COMGETTER(Id)(uuid.asOutParam());
1769 }
1770 if (FAILED(rc))
1771 return 1;
1772
1773 /* parse arguments. */
1774 bool fReset = false;
1775 bool fWithDescriptions = false;
1776 const char *pszPattern = NULL; /* all */
1777 for (int i = 1; i < a->argc; i++)
1778 {
1779 if ( !strcmp(a->argv[i], "--pattern")
1780 || !strcmp(a->argv[i], "-pattern"))
1781 {
1782 if (pszPattern)
1783 return errorSyntax(USAGE_VM_STATISTICS, "Multiple --patterns options is not permitted");
1784 if (i + 1 >= a->argc)
1785 return errorArgument("Missing argument to '%s'", a->argv[i]);
1786 pszPattern = a->argv[++i];
1787 }
1788 else if ( !strcmp(a->argv[i], "--descriptions")
1789 || !strcmp(a->argv[i], "-descriptions"))
1790 fWithDescriptions = true;
1791 /* add: --file <filename> and --formatted */
1792 else if ( !strcmp(a->argv[i], "--reset")
1793 || !strcmp(a->argv[i], "-reset"))
1794 fReset = true;
1795 else
1796 return errorSyntax(USAGE_VM_STATISTICS, "Unknown option '%s'", a->argv[i]);
1797 }
1798 if (fReset && fWithDescriptions)
1799 return errorSyntax(USAGE_VM_STATISTICS, "The --reset and --descriptions options does not mix");
1800
1801
1802 /* open an existing session for the VM. */
1803 CHECK_ERROR(a->virtualBox, OpenExistingSession(a->session, uuid));
1804 if (SUCCEEDED(rc))
1805 {
1806 /* get the session console. */
1807 ComPtr <IConsole> console;
1808 CHECK_ERROR(a->session, COMGETTER(Console)(console.asOutParam()));
1809 if (SUCCEEDED(rc))
1810 {
1811 /* get the machine debugger. */
1812 ComPtr <IMachineDebugger> debugger;
1813 CHECK_ERROR(console, COMGETTER(Debugger)(debugger.asOutParam()));
1814 if (SUCCEEDED(rc))
1815 {
1816 if (fReset)
1817 CHECK_ERROR(debugger, ResetStats(Bstr(pszPattern)));
1818 else
1819 {
1820 Bstr stats;
1821 CHECK_ERROR(debugger, GetStats(Bstr(pszPattern), fWithDescriptions, stats.asOutParam()));
1822 if (SUCCEEDED(rc))
1823 {
1824 /* if (fFormatted)
1825 { big mess }
1826 else
1827 */
1828 RTPrintf("%ls\n", stats.raw());
1829 }
1830 }
1831 }
1832 a->session->Close();
1833 }
1834 }
1835
1836 return SUCCEEDED(rc) ? 0 : 1;
1837}
1838#endif /* !VBOX_ONLY_DOCS */
1839
1840// main
1841///////////////////////////////////////////////////////////////////////////////
1842
1843int main(int argc, char *argv[])
1844{
1845 /*
1846 * Before we do anything, init the runtime without loading
1847 * the support driver.
1848 */
1849 RTR3Init();
1850
1851 bool fShowLogo = true;
1852 int iCmd = 1;
1853 int iCmdArg;
1854
1855 /* global options */
1856 for (int i = 1; i < argc || argc <= iCmd; i++)
1857 {
1858 if ( argc <= iCmd
1859 || !strcmp(argv[i], "help")
1860 || !strcmp(argv[i], "-?")
1861 || !strcmp(argv[i], "-h")
1862 || !strcmp(argv[i], "-help")
1863 || !strcmp(argv[i], "--help"))
1864 {
1865 showLogo();
1866 printUsage(USAGE_ALL);
1867 return 0;
1868 }
1869 else if ( !strcmp(argv[i], "-v")
1870 || !strcmp(argv[i], "-version")
1871 || !strcmp(argv[i], "-Version")
1872 || !strcmp(argv[i], "--version"))
1873 {
1874 /* Print version number, and do nothing else. */
1875 RTPrintf("%sr%d\n", VBOX_VERSION_STRING, RTBldCfgRevision());
1876 return 0;
1877 }
1878 else if ( !strcmp(argv[i], "--dumpopts")
1879 || !strcmp(argv[i], "-dumpopts"))
1880 {
1881 /* Special option to dump really all commands,
1882 * even the ones not understood on this platform. */
1883 printUsage(USAGE_DUMPOPTS);
1884 return 0;
1885 }
1886 else if ( !strcmp(argv[i], "--nologo")
1887 || !strcmp(argv[i], "-nologo")
1888 || !strcmp(argv[i], "-q"))
1889 {
1890 /* suppress the logo */
1891 fShowLogo = false;
1892 iCmd++;
1893 }
1894 else
1895 {
1896 break;
1897 }
1898 }
1899
1900 iCmdArg = iCmd + 1;
1901
1902 if (fShowLogo)
1903 showLogo();
1904
1905
1906#ifdef VBOX_ONLY_DOCS
1907 int rc = 0;
1908#else /* !VBOX_ONLY_DOCS */
1909 HRESULT rc = 0;
1910
1911 rc = com::Initialize();
1912 if (FAILED(rc))
1913 {
1914 RTPrintf("ERROR: failed to initialize COM!\n");
1915 return rc;
1916 }
1917
1918 /*
1919 * The input is in the host OS'es codepage (NT guarantees ACP).
1920 * For VBox we use UTF-8 and convert to UCS-2 when calling (XP)COM APIs.
1921 * For simplicity, just convert the argv[] array here.
1922 */
1923 for (int i = iCmdArg; i < argc; i++)
1924 {
1925 char *converted;
1926 RTStrCurrentCPToUtf8(&converted, argv[i]);
1927 argv[i] = converted;
1928 }
1929
1930 do
1931 {
1932 // scopes all the stuff till shutdown
1933 ////////////////////////////////////////////////////////////////////////////
1934
1935 /* convertfromraw: does not need a VirtualBox instantiation. */
1936 if (argc >= iCmdArg && ( !strcmp(argv[iCmd], "convertfromraw")
1937 || !strcmp(argv[iCmd], "convertdd")))
1938 {
1939 rc = handleConvertFromRaw(argc - iCmdArg, argv + iCmdArg);
1940 break;
1941 }
1942
1943 ComPtr<IVirtualBox> virtualBox;
1944 ComPtr<ISession> session;
1945
1946 rc = virtualBox.createLocalObject(CLSID_VirtualBox);
1947 if (FAILED(rc))
1948 RTPrintf("ERROR: failed to create the VirtualBox object!\n");
1949 else
1950 {
1951 rc = session.createInprocObject(CLSID_Session);
1952 if (FAILED(rc))
1953 RTPrintf("ERROR: failed to create a session object!\n");
1954 }
1955
1956 if (FAILED(rc))
1957 {
1958 com::ErrorInfo info;
1959 if (!info.isFullAvailable() && !info.isBasicAvailable())
1960 {
1961 com::GluePrintRCMessage(rc);
1962 RTPrintf("Most likely, the VirtualBox COM server is not running or failed to start.\n");
1963 }
1964 else
1965 com::GluePrintErrorInfo(info);
1966 break;
1967 }
1968
1969 HandlerArg handlerArg = { 0, NULL, virtualBox, session };
1970
1971 /*
1972 * All registered command handlers
1973 */
1974 struct
1975 {
1976 const char *command;
1977 PFNHANDLER handler;
1978 } 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 { "showhdinfo", handleShowHardDiskInfo },
2004 { "showvdiinfo", handleShowHardDiskInfo }, /* backward compatiblity */
2005 { "getextradata", handleGetExtraData },
2006 { "setextradata", handleSetExtraData },
2007 { "setproperty", handleSetProperty },
2008 { "usbfilter", handleUSBFilter },
2009 { "sharedfolder", handleSharedFolder },
2010 { "vmstatistics", handleVMStatistics },
2011#ifdef VBOX_WITH_GUEST_PROPS
2012 { "guestproperty", handleGuestProperty },
2013#endif /* VBOX_WITH_GUEST_PROPS defined */
2014 { "metrics", handleMetrics },
2015 { "import", handleImportAppliance },
2016 { "export", handleExportAppliance },
2017#if defined(VBOX_WITH_NETFLT)
2018 { "hostonlyif", handleHostonlyIf },
2019#endif
2020 { "dhcpserver", handleDHCPServer},
2021 { NULL, NULL }
2022 };
2023
2024 int commandIndex;
2025 for (commandIndex = 0; commandHandlers[commandIndex].command != NULL; commandIndex++)
2026 {
2027 if (!strcmp(commandHandlers[commandIndex].command, argv[iCmd]))
2028 {
2029 handlerArg.argc = argc - iCmdArg;
2030 handlerArg.argv = &argv[iCmdArg];
2031
2032 rc = commandHandlers[commandIndex].handler(&handlerArg);
2033 break;
2034 }
2035 }
2036 if (!commandHandlers[commandIndex].command)
2037 {
2038 rc = errorSyntax(USAGE_ALL, "Invalid command '%s'", Utf8Str(argv[iCmd]).raw());
2039 }
2040
2041 /* Although all handlers should always close the session if they open it,
2042 * we do it here just in case if some of the handlers contains a bug --
2043 * leaving the direct session not closed will turn the machine state to
2044 * Aborted which may have unwanted side effects like killing the saved
2045 * state file (if the machine was in the Saved state before). */
2046 session->Close();
2047
2048 EventQueue::getMainEventQueue()->processEventQueue(0);
2049 // end "all-stuff" scope
2050 ////////////////////////////////////////////////////////////////////////////
2051 }
2052 while (0);
2053
2054 com::Shutdown();
2055#endif /* !VBOX_ONLY_DOCS */
2056
2057 /*
2058 * Free converted argument vector
2059 */
2060 for (int i = iCmdArg; i < argc; i++)
2061 RTStrFree(argv[i]);
2062
2063 return rc != 0;
2064}
Note: See TracBrowser for help on using the repository browser.

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