VirtualBox

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

Last change on this file since 5129 was 5129, checked in by vboxsync, 17 years ago

Added 'nicspeed' argument to 'vboxmanage modifyvm'. Also display reported NIC speed and
selected NIC type in 'vboxmanage showvminfo'.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 257.5 KB
Line 
1/** @file
2 *
3 * VBox frontends: VBoxManage (command-line interface)
4 *
5 * VBoxManage is VirtualBox's command-line interface. This is its rather
6 * long source.
7 */
8
9/*
10 * Copyright (C) 2006-2007 innotek GmbH
11 *
12 * This file is part of VirtualBox Open Source Edition (OSE), as
13 * available from http://www.virtualbox.org. This file is free software;
14 * you can redistribute it and/or modify it under the terms of the GNU
15 * General Public License as published by the Free Software Foundation,
16 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
17 * distribution. VirtualBox OSE is distributed in the hope that it will
18 * be useful, but WITHOUT ANY WARRANTY of any kind.
19 */
20
21
22/*******************************************************************************
23* Header Files *
24*******************************************************************************/
25
26#include <VBox/com/com.h>
27#include <VBox/com/string.h>
28#include <VBox/com/Guid.h>
29#include <VBox/com/ErrorInfo.h>
30#include <VBox/com/EventQueue.h>
31
32#include <VBox/com/VirtualBox.h>
33
34#define CFGLDR_HAVE_COM
35#include <VBox/cfgldr.h>
36
37#include <stdlib.h>
38#include <stdarg.h>
39
40#include <vector>
41
42#include <iprt/runtime.h>
43#include <iprt/stream.h>
44#include <iprt/string.h>
45#include <iprt/asm.h>
46#include <iprt/uuid.h>
47#include <iprt/thread.h>
48#include <iprt/path.h>
49#include <iprt/param.h>
50#include <iprt/dir.h>
51#include <iprt/file.h>
52#include <iprt/env.h>
53#include <VBox/err.h>
54#include <VBox/version.h>
55#include <VBox/VBoxHDD.h>
56
57#include "VBoxManage.h"
58
59using namespace com;
60
61/* missing XPCOM <-> COM wrappers */
62#ifndef STDMETHOD_
63# define STDMETHOD_(ret, meth) NS_IMETHOD_(ret) meth
64#endif
65#ifndef NS_GET_IID
66# define NS_GET_IID(I) IID_##I
67#endif
68#ifndef RT_OS_WINDOWS
69#define IUnknown nsISupports
70#endif
71
72/** command handler type */
73typedef DECLCALLBACK(int) FNHANDLER(int argc, char *argv[], ComPtr<IVirtualBox> aVirtualBox, ComPtr<ISession> aSession);
74typedef FNHANDLER *PFNHANDLER;
75
76/**
77 * Quick IUSBDevice implementation for detaching / attaching
78 * devices to the USB Controller.
79 */
80class MyUSBDevice : public IUSBDevice
81{
82public:
83 // public initializer/uninitializer for internal purposes only
84 MyUSBDevice(uint16_t a_u16VendorId, uint16_t a_u16ProductId, uint16_t a_bcdRevision, uint64_t a_u64SerialHash, const char *a_pszComment)
85 : m_usVendorId(a_u16VendorId), m_usProductId(a_u16ProductId),
86 m_bcdRevision(a_bcdRevision), m_u64SerialHash(a_u64SerialHash),
87 m_bstrComment(a_pszComment),
88 m_cRefs(0)
89 {
90 }
91
92 STDMETHOD_(ULONG, AddRef)(void)
93 {
94 return ASMAtomicIncU32(&m_cRefs);
95 }
96 STDMETHOD_(ULONG, Release)(void)
97 {
98 ULONG cRefs = ASMAtomicDecU32(&m_cRefs);
99 if (!cRefs)
100 delete this;
101 return cRefs;
102 }
103 STDMETHOD(QueryInterface)(const IID &iid, void **ppvObject)
104 {
105 Guid guid(iid);
106 if (guid == Guid(NS_GET_IID(IUnknown)))
107 *ppvObject = (IUnknown *)this;
108 else if (guid == Guid(NS_GET_IID(IUSBDevice)))
109 *ppvObject = (IUSBDevice *)this;
110 else
111 return E_NOINTERFACE;
112 AddRef();
113 return S_OK;
114 }
115
116 STDMETHOD(COMGETTER(Id))(GUIDPARAMOUT a_pId) { return E_NOTIMPL; }
117 STDMETHOD(COMGETTER(VendorId))(USHORT *a_pusVendorId) { *a_pusVendorId = m_usVendorId; return S_OK; }
118 STDMETHOD(COMGETTER(ProductId))(USHORT *a_pusProductId) { *a_pusProductId = m_usProductId; return S_OK; }
119 STDMETHOD(COMGETTER(Revision))(USHORT *a_pusRevision) { *a_pusRevision = m_bcdRevision; return S_OK; }
120 STDMETHOD(COMGETTER(SerialHash))(ULONG64 *a_pullSerialHash) { *a_pullSerialHash = m_u64SerialHash; return S_OK; }
121 STDMETHOD(COMGETTER(Manufacturer))(BSTR *a_pManufacturer) { return E_NOTIMPL; }
122 STDMETHOD(COMGETTER(Product))(BSTR *a_pProduct) { return E_NOTIMPL; }
123 STDMETHOD(COMGETTER(SerialNumber))(BSTR *a_pSerialNumber) { return E_NOTIMPL; }
124 STDMETHOD(COMGETTER(Address))(BSTR *a_pAddress) { return E_NOTIMPL; }
125
126private:
127 /** The vendor id of this USB device. */
128 USHORT m_usVendorId;
129 /** The product id of this USB device. */
130 USHORT m_usProductId;
131 /** The product revision number of this USB device.
132 * (high byte = integer; low byte = decimal) */
133 USHORT m_bcdRevision;
134 /** The USB serial hash of the device. */
135 uint64_t m_u64SerialHash;
136 /** The user comment string. */
137 Bstr m_bstrComment;
138 /** Reference counter. */
139 uint32_t volatile m_cRefs;
140};
141
142
143// types
144///////////////////////////////////////////////////////////////////////////////
145
146template <typename T>
147class Nullable
148{
149public:
150
151 Nullable() : mIsNull (true) {}
152 Nullable (const T &aValue, bool aIsNull = false)
153 : mIsNull (aIsNull), mValue (aValue) {}
154
155 bool isNull() const { return mIsNull; };
156 void setNull (bool aIsNull = true) { mIsNull = aIsNull; }
157
158 operator const T&() const { return mValue; }
159
160 Nullable &operator= (const T &aValue)
161 {
162 mValue = aValue;
163 mIsNull = false;
164 return *this;
165 }
166
167private:
168
169 bool mIsNull;
170 T mValue;
171};
172
173/** helper structure to encapsulate USB filter manipulation commands */
174struct USBFilterCmd
175{
176 struct USBFilter
177 {
178 USBFilter ()
179 : mAction (USBDeviceFilterAction_InvalidUSBDeviceFilterAction)
180 {}
181
182 Bstr mName;
183 Nullable <bool> mActive;
184 Bstr mVendorId;
185 Bstr mProductId;
186 Bstr mRevision;
187 Bstr mManufacturer;
188 Bstr mProduct;
189 Bstr mRemote;
190 Bstr mSerialNumber;
191 USBDeviceFilterAction_T mAction;
192 };
193
194 enum Action { Invalid, Add, Modify, Remove };
195
196 USBFilterCmd() : mAction (Invalid), mIndex (0), mGlobal (false) {}
197
198 Action mAction;
199 ULONG mIndex;
200 /** flag whether the command target is a global filter */
201 bool mGlobal;
202 /** machine this command is targeted at (null for global filters) */
203 ComPtr<IMachine> mMachine;
204 USBFilter mFilter;
205};
206
207// funcs
208///////////////////////////////////////////////////////////////////////////////
209
210static void showLogo(void)
211{
212 static bool fShown; /* show only once */
213
214 if (!fShown)
215 {
216 RTPrintf("VirtualBox Command Line Management Interface Version "
217 VBOX_VERSION_STRING "\n"
218 "(C) 2005-2007 innotek GmbH\n"
219 "All rights reserved.\n"
220 "\n");
221 fShown = true;
222 }
223}
224
225static void printUsage(USAGECATEGORY u64Cmd)
226{
227#ifdef RT_OS_LINUX
228 bool fLinux = true;
229#else
230 bool fLinux = false;
231#endif
232#ifdef RT_OS_WINDOWS
233 bool fWin = true;
234#else
235 bool fWin = false;
236#endif
237#ifdef RT_OS_DARWIN
238 bool fDarwin = true;
239#else
240 bool fDarwin = false;
241#endif
242#ifdef VBOX_VRDP
243 bool fVRDP = true;
244#else
245 bool fVRDP = false;
246#endif
247
248 if (u64Cmd == USAGE_DUMPOPTS)
249 {
250 fLinux = true;
251 fWin = true;
252 fVRDP = true;
253 u64Cmd = USAGE_ALL;
254 }
255
256 RTPrintf("Usage:\n"
257 "\n");
258
259 if (u64Cmd == USAGE_ALL)
260 {
261 RTPrintf("VBoxManage [-v|-version] print version number and exit\n");
262 RTPrintf("VBoxManage -nologo ... suppress the logo\n"
263 "\n");
264 }
265
266 if (u64Cmd & USAGE_LIST)
267 {
268 RTPrintf("VBoxManage list vms|ostypes|hostdvds|hostfloppies|");
269 if (fWin)
270 RTPrintf( "hostifs|");
271 RTPrintf( "\n"
272 " hdds|dvds|floppies|usbhost|usbfilters|\n"
273 " systemproperties\n"
274 "\n");
275 }
276
277 if (u64Cmd & USAGE_SHOWVMINFO)
278 {
279 RTPrintf("VBoxManage showvminfo <uuid>|<name>\n"
280 " [-details]\n"
281 " [-statistics]\n"
282 " [-machinereadable]\n"
283 "\n");
284 }
285
286 if (u64Cmd & USAGE_REGISTERVM)
287 {
288 RTPrintf("VBoxManage registervm <filename>\n"
289 "\n");
290 }
291
292 if (u64Cmd & USAGE_UNREGISTERVM)
293 {
294 RTPrintf("VBoxManage unregistervm <uuid>|<name>\n"
295 " [-delete]\n"
296 "\n");
297 }
298
299 if (u64Cmd & USAGE_CREATEVM)
300 {
301 RTPrintf("VBoxManage createvm -name <name>\n"
302 " [-register]\n"
303 " [-basefolder <path> | -settingsfile <path>]\n"
304 " \n"
305 "\n");
306 }
307
308 if (u64Cmd & USAGE_MODIFYVM)
309 {
310 RTPrintf("VBoxManage modifyvm <uuid|name>\n"
311 " [-name <name>]\n"
312 " [-ostype <ostype>]\n"
313 " [-memory <memorysize>]\n"
314 " [-vram <vramsize>]\n"
315 " [-acpi on|off]\n"
316 " [-ioapic on|off]\n"
317 " [-hwvirtex on|off|default]\n"
318 " [-monitorcount <number>]\n"
319 " [-bioslogofadein on|off]\n"
320 " [-bioslogofadeout on|off]\n"
321 " [-bioslogodisplaytime <msec>]\n"
322 " [-bioslogoimagepath <imagepath>]\n"
323 " [-biosbootmenu disabled|menuonly|messageandmenu]\n"
324 " [-biossystemtimeoffset <msec>]\n"
325 " [-boot<1-4> none|floppy|dvd|disk|net>]\n"
326 " [-hd<a|b|d> none|<uuid>|<filename>]\n"
327 " [-dvd none|<uuid>|<filename>|host:<drive>]\n"
328 " [-dvdpassthrough on|off]\n"
329 " [-floppy disabled|empty|<uuid>|\n"
330 " <filename>|host:<drive>]\n"
331 " [-nic<1-N> none|null|nat|hostif|intnet]\n"
332 " [-nictype<1-N> Am79C970A|Am79C973]\n"
333 " [-cableconnected<1-N> on|off]\n"
334 " [-nictrace<1-N> on|off]\n"
335 " [-nictracefile<1-N> <filename>]\n"
336 " [-nicspeed<1-N> <kbps>]\n"
337 " [-hostifdev<1-N> none|<devicename>]\n"
338 " [-intnet<1-N> <network>]\n"
339 " [-macaddress<1-N> auto|<mac>]\n"
340 " [-uart<1-N> off|<I/O base> <IRQ>]\n"
341 " [-uartmode<1-N> disconnected|\n"
342 " server <pipe>|\n"
343 " client <pipe>|\n"
344 " <devicename>]\n"
345 " [-guestmemoryballoon <balloonsize>]\n"
346 " [-gueststatisticsinterval <seconds>]\n"
347 );
348 if (fLinux)
349 {
350 RTPrintf(" [-tapsetup<1-N> none|<application>]\n"
351 " [-tapterminate<1-N> none|<application>]\n");
352 }
353 RTPrintf(" [-audio none|null");
354 if (fWin)
355 {
356#ifdef VBOX_WITH_WINMM
357 RTPrintf( "|winmm|dsound");
358#else
359 RTPrintf( "|dsound");
360#endif
361 }
362 if (fLinux)
363 {
364 RTPrintf( "|oss"
365#ifdef VBOX_WITH_ALSA
366 "|alsa"
367#endif
368 );
369 }
370 if (fDarwin)
371 {
372 RTPrintf( "|coreaudio");
373 }
374 RTPrintf( "]\n");
375 RTPrintf(" [-clipboard disabled|hosttoguest|guesttohost|\n"
376 " bidirectional]\n");
377 if (fVRDP)
378 {
379 RTPrintf(" [-vrdp on|off]\n"
380 " [-vrdpport default|<port>]\n"
381 " [-vrdpaddress <host>]\n"
382 " [-vrdpauthtype null|external|guest]\n"
383 " [-vrdpmulticon on|off]\n");
384 }
385 RTPrintf(" [-usb on|off]\n"
386 " [-snapshotfolder default|<path>]\n"
387 "\n");
388 }
389
390 if (u64Cmd & USAGE_STARTVM)
391 {
392 RTPrintf("VBoxManage startvm <uuid>|<name>\n"
393 " [-type gui|vrdp]\n"
394 "\n");
395 }
396
397 if (u64Cmd & USAGE_CONTROLVM)
398 {
399 RTPrintf("VBoxManage controlvm <uuid>|<name>\n"
400 " pause|resume|reset|poweroff|savestate|\n"
401 " acpipowerbutton |\n"
402 " setlinkstate<1-4> on|off |\n"
403 " usbattach <uuid>|<address> |\n"
404 " usbdetach <uuid>|<address> |\n"
405 " dvdattach none|<uuid>|<filename>|host:<drive> |\n"
406 " floppyattach none|<uuid>|<filename>|host:<drive> |\n"
407 " setvideomodehint <xres> <yres> <bpp> [display]|\n"
408 " setcredentials <username> <password> <domain>\n"
409 " [-allowlocallogon <yes|no>]\n"
410 "\n");
411 }
412
413 if (u64Cmd & USAGE_DISCARDSTATE)
414 {
415 RTPrintf("VBoxManage discardstate <uuid>|<name>\n"
416 "\n");
417 }
418
419 if (u64Cmd & USAGE_SNAPSHOT)
420 {
421 RTPrintf("VBoxManage snapshot <uuid>|<name>\n"
422 " take <name> [-desc <desc>] |\n"
423 " discard <uuid>|<name> |\n"
424 " discardcurrent -state|-all |\n"
425 " edit <uuid>|<name>|-current\n"
426 " [-newname <name>]\n"
427 " [-newdesc <desc>] |\n"
428 " showvminfo <uuid>|<name>\n"
429 "\n");
430 }
431
432 if (u64Cmd & USAGE_REGISTERIMAGE)
433 {
434 RTPrintf("VBoxManage registerimage disk|dvd|floppy <filename>\n"
435 " [-type normal|immutable|writethrough] (disk only)\n"
436 "\n");
437 }
438
439 if (u64Cmd & USAGE_UNREGISTERIMAGE)
440 {
441 RTPrintf("VBoxManage unregisterimage disk|dvd|floppy <uuid>|<filename>\n"
442 "\n");
443 }
444
445 if (u64Cmd & USAGE_SHOWVDIINFO)
446 {
447 RTPrintf("VBoxManage showvdiinfo <uuid>|<filename>\n"
448 "\n");
449 }
450
451 if (u64Cmd & USAGE_CREATEVDI)
452 {
453 RTPrintf("VBoxManage createvdi -filename <filename>\n"
454 " -size <megabytes>\n"
455 " [-static]\n"
456 " [-comment <comment>]\n"
457 " [-register]\n"
458 " [-type normal|writethrough] (default: normal)\n"
459 "\n");
460 }
461
462 if (u64Cmd & USAGE_MODIFYVDI)
463 {
464 RTPrintf("VBoxManage modifyvdi <uuid>|<filename>\n"
465#if 0 /* doesn't currently work */
466 " settype normal|writethrough|immutable |\n"
467#endif
468 " compact\n"
469 "\n");
470 }
471
472 if (u64Cmd & USAGE_CLONEVDI)
473 {
474 RTPrintf("VBoxManage clonevdi <uuid>|<filename> <outputfile>\n"
475 "\n");
476 }
477
478 if (u64Cmd & USAGE_CONVERTDD)
479 {
480 RTPrintf("VBoxManage convertdd <filename> <outputfile>\n"
481 "VBoxManage convertdd stdin <outputfile> <bytes>\n"
482 "\n");
483 }
484
485 if (u64Cmd & USAGE_ADDISCSIDISK)
486 {
487 RTPrintf("VBoxManage addiscsidisk -server <name>|<ip>\n"
488 " -target <target>\n"
489 " [-port <port>]\n"
490 " [-lun <lun>]\n"
491 " [-encodedlun <lun>]\n"
492 " [-username <username>]\n"
493 " [-password <password>]\n"
494 " [-comment <comment>]\n"
495 "\n");
496 }
497
498 if (u64Cmd & USAGE_CREATEHOSTIF && fWin)
499 {
500 RTPrintf("VBoxManage createhostif <name>\n"
501 "\n");
502 }
503
504 if (u64Cmd & USAGE_REMOVEHOSTIF && fWin)
505 {
506 RTPrintf("VBoxManage removehostif <uuid>|<name>\n"
507 "\n");
508 }
509
510 if (u64Cmd & USAGE_GETEXTRADATA)
511 {
512 RTPrintf("VBoxManage getextradata global|<uuid>|<name>\n"
513 " <key>|enumerate\n"
514 "\n");
515 }
516
517 if (u64Cmd & USAGE_SETEXTRADATA)
518 {
519 RTPrintf("VBoxManage setextradata global|<uuid>|<name>\n"
520 " <key>\n"
521 " [<value>] (no value deletes key)\n"
522 "\n");
523 }
524
525 if (u64Cmd & USAGE_SETPROPERTY)
526 {
527 RTPrintf("VBoxManage setproperty vdifolder default|<folder> |\n"
528 " machinefolder default|<folder> |\n"
529 " vrdpauthlibrary default|<library> |\n"
530 " hwvirtexenabled yes|no\n"
531 "\n");
532 }
533
534 if (u64Cmd & USAGE_USBFILTER_ADD)
535 {
536 RTPrintf("VBoxManage usbfilter add <index,0-N>\n"
537 " -target <uuid>|<name>|global\n"
538 " -name <string>\n"
539 " -action ignore|hold (global filters only)\n"
540 " [-active yes|no] (yes)\n"
541 " [-vendorid <XXXX>] (null)\n"
542 " [-productid <XXXX>] (null)\n"
543 " [-revision <IIFF>] (null)\n"
544 " [-manufacturer <string>] (null)\n"
545 " [-product <string>] (null)\n"
546 " [-remote yes|no] (null, VM filters only)\n"
547 " [-serialnumber <string>] (null)\n"
548 "\n");
549 }
550
551 if (u64Cmd & USAGE_USBFILTER_MODIFY)
552 {
553 RTPrintf("VBoxManage usbfilter modify <index,0-N>\n"
554 " -target <uuid>|<name>|global\n"
555 " [-name <string>]\n"
556 " [-action ignore|hold] (global filters only)\n"
557 " [-active yes|no]\n"
558 " [-vendorid <XXXX>|\"\"]\n"
559 " [-productid <XXXX>|\"\"]\n"
560 " [-revision <IIFF>|\"\"]\n"
561 " [-manufacturer <string>|\"\"]\n"
562 " [-product <string>|\"\"]\n"
563 " [-remote yes|no] (null, VM filters only)\n"
564 " [-serialnumber <string>|\"\"]\n"
565 "\n");
566 }
567
568 if (u64Cmd & USAGE_USBFILTER_REMOVE)
569 {
570 RTPrintf("VBoxManage usbfilter remove <index,0-N>\n"
571 " -target <uuid>|<name>|global\n"
572 "\n");
573 }
574
575 if (u64Cmd & USAGE_SHAREDFOLDER_ADD)
576 {
577 RTPrintf("VBoxManage sharedfolder add <vmname>|<uuid>\n"
578 " -name <name> -hostpath <hostpath>\n"
579 " [-transient]\n"
580 "\n");
581 }
582
583 if (u64Cmd & USAGE_SHAREDFOLDER_REMOVE)
584 {
585 RTPrintf("VBoxManage sharedfolder remove <vmname>|<uuid>\n"
586 " -name <name> [-transient]\n"
587 "\n");
588 }
589
590 if (u64Cmd & USAGE_UPDATESETTINGS)
591 {
592 RTPrintf("VBoxManage updatesettings [<dir>|<file>] [-apply]\n"
593 " [-nobackup] [-skipinvalid]\n"
594 "\n");
595 }
596}
597
598/**
599 * Print a usage synopsis and the syntax error message.
600 */
601int errorSyntax(USAGECATEGORY u64Cmd, const char *pszFormat, ...)
602{
603 va_list args;
604 showLogo(); // show logo even if suppressed
605 if (fInternalMode)
606 printUsageInternal(u64Cmd);
607 else
608 printUsage(u64Cmd);
609 va_start(args, pszFormat);
610 RTPrintf("\n"
611 "Syntax error: %N\n", pszFormat, &args);
612 va_end(args);
613 return 1;
614}
615
616/**
617 * Print an error message without the syntax stuff.
618 */
619int errorArgument(const char *pszFormat, ...)
620{
621 va_list args;
622 va_start(args, pszFormat);
623 RTPrintf("error: %N\n", pszFormat, &args);
624 va_end(args);
625 return 1;
626}
627
628/**
629 * Print out progress on the console
630 */
631static void showProgress(ComPtr<IProgress> progress)
632{
633 BOOL fCompleted;
634 LONG currentPercent, lastPercent = 0;
635
636 RTPrintf("0%%...");
637 RTStrmFlush(g_pStdOut);
638 while (SUCCEEDED(progress->COMGETTER(Completed(&fCompleted))))
639 {
640 progress->COMGETTER(Percent(&currentPercent));
641 /* did we cross a 10% mark? */
642 if (((currentPercent / 10) > (lastPercent / 10)))
643 {
644 /* make sure to also print out missed steps */
645 for (LONG curVal = (lastPercent / 10) * 10 + 10; curVal <= (currentPercent / 10) * 10; curVal += 10)
646 {
647 if (curVal < 100)
648 {
649 RTPrintf("%ld%%...", curVal);
650 RTStrmFlush(g_pStdOut);
651 }
652 }
653 }
654 lastPercent = currentPercent;
655 if (fCompleted)
656 {
657 RTPrintf("100%%\n");
658 RTStrmFlush(g_pStdOut);
659 break;
660 }
661 /* make sure the loop is not too tight */
662 RTThreadSleep(100);
663 }
664}
665
666static void showSnapshots(ComPtr<ISnapshot> rootSnapshot, VMINFO_DETAILS details, const Bstr &prefix = "", int level = 0)
667{
668 /* start with the root */
669 Bstr name;
670 Guid uuid;
671 rootSnapshot->COMGETTER(Name)(name.asOutParam());
672 rootSnapshot->COMGETTER(Id)(uuid.asOutParam());
673 if (details == VMINFO_MACHINEREADABLE)
674 {
675 /* print with hierarchical numbering */
676 RTPrintf("SnapshotName%lS=\"%lS\"\n", prefix.raw(), name.raw());
677 RTPrintf("SnapshotUUID%lS=\"%s\"\n", prefix.raw(), uuid.toString().raw());
678 }
679 else
680 {
681 /* print with indentation */
682 RTPrintf(" %lSName: %lS (UUID: %s)\n", prefix.raw(), name.raw(), uuid.toString().raw());
683 }
684
685 /* get the children */
686 ComPtr<ISnapshotCollection> coll;
687 rootSnapshot->COMGETTER(Children)(coll.asOutParam());
688 if (coll)
689 {
690 ComPtr<ISnapshotEnumerator> enumerator;
691 coll->Enumerate(enumerator.asOutParam());
692 ULONG index = 0;
693 BOOL hasMore = FALSE;
694 while (enumerator->HasMore(&hasMore), hasMore)
695 {
696 ComPtr<ISnapshot> snapshot;
697 enumerator->GetNext(snapshot.asOutParam());
698 if (snapshot)
699 {
700 Bstr newPrefix;
701 if (details == VMINFO_MACHINEREADABLE)
702 newPrefix = Utf8StrFmt("%lS-%d", prefix.raw(), index + 1);
703 else
704 newPrefix = Utf8StrFmt("%lS ", prefix.raw());
705 /* recursive call */
706 showSnapshots(snapshot, details, newPrefix, level + 1);
707 }
708 index++;
709 }
710 }
711}
712
713static void makeTimeStr (char *s, int cb, int64_t millies)
714{
715 RTTIME t;
716 RTTIMESPEC ts;
717
718 RTTimeSpecSetMilli(&ts, millies);
719
720 RTTimeExplode (&t, &ts);
721
722 RTStrPrintf(s, cb, "%04d/%02d/%02d %02d:%02d:%02d UTC",
723 t.i32Year, t.u8Month, t.u8MonthDay,
724 t.u8Hour, t.u8Minute, t.u8Second);
725}
726
727static HRESULT showVMInfo (ComPtr <IVirtualBox> virtualBox, ComPtr<IMachine> machine,
728 ComPtr <IConsole> console = ComPtr <IConsole> (),
729 VMINFO_DETAILS details = VMINFO_NONE)
730{
731 HRESULT rc;
732
733 /*
734 * The rules for output in -argdump format:
735 * 1) the key part (the [0-9a-zA-Z_]+ string before the '=' delimiter)
736 * is all lowercase for "VBoxManage modifyvm" parameters. Any
737 * other values printed are in CamelCase.
738 * 2) strings (anything non-decimal) are printed surrounded by
739 * double quotes '"'. If the strings themselves contain double
740 * quotes, these characters are escaped by '\'. Any '\' character
741 * in the original string is also escaped by '\'.
742 * 3) numbers (containing just [0-9\-]) are written out unchanged.
743 */
744
745 /** @todo the quoting is not yet implemented! */
746
747 BOOL accessible = FALSE;
748 CHECK_ERROR (machine, COMGETTER(Accessible) (&accessible));
749 CheckComRCReturnRC (rc);
750
751 if (!accessible)
752 {
753 if (details == VMINFO_MACHINEREADABLE)
754 RTPrintf("name=\"<inaccessible>\"\n");
755 else
756 RTPrintf ("Name: <inaccessible!>\n");
757 Guid uuid;
758 rc = machine->COMGETTER(Id) (uuid.asOutParam());
759 if (details == VMINFO_MACHINEREADABLE)
760 RTPrintf ("UUID=\"%s\"\n", uuid.toString().raw());
761 else
762 RTPrintf ("UUID: %s\n", uuid.toString().raw());
763 if (details != VMINFO_MACHINEREADABLE)
764 {
765 Bstr settingsFilePath;
766 rc = machine->COMGETTER(SettingsFilePath) (settingsFilePath.asOutParam());
767 RTPrintf ("Config file: %lS\n", settingsFilePath.raw());
768 ComPtr<IVirtualBoxErrorInfo> accessError;
769 rc = machine->COMGETTER(AccessError) (accessError.asOutParam());
770 RTPrintf ("Access error details:\n");
771 ErrorInfo ei (accessError);
772 ei.print ("[-] ");
773 RTPrintf ("\n");
774 }
775 return S_OK;
776 }
777
778 Bstr machineName;
779 rc = machine->COMGETTER(Name)(machineName.asOutParam());
780 if (details == VMINFO_MACHINEREADABLE)
781 RTPrintf("name=\"%lS\"\n", machineName.raw());
782 else
783 RTPrintf("Name: %lS\n", machineName.raw());
784
785 Bstr osTypeId;
786 rc = machine->COMGETTER(OSTypeId)(osTypeId.asOutParam());
787 ComPtr<IGuestOSType> osType;
788 rc = virtualBox->GetGuestOSType (osTypeId, osType.asOutParam());
789 Bstr osName;
790 rc = osType->COMGETTER(Description)(osName.asOutParam());
791 if (details == VMINFO_MACHINEREADABLE)
792 RTPrintf("ostype=\"%lS\"\n", osTypeId.raw());
793 else
794 RTPrintf("Guest OS: %lS\n", osName.raw());
795
796 Guid uuid;
797 rc = machine->COMGETTER(Id)(uuid.asOutParam());
798 if (details == VMINFO_MACHINEREADABLE)
799 RTPrintf("UUID=\"%s\"\n", uuid.toString().raw());
800 else
801 RTPrintf("UUID: %s\n", uuid.toString().raw());
802
803 Bstr settingsFilePath;
804 rc = machine->COMGETTER(SettingsFilePath)(settingsFilePath.asOutParam());
805 if (details == VMINFO_MACHINEREADABLE)
806 RTPrintf("CfgFile=\"%lS\"\n", settingsFilePath.raw());
807 else
808 RTPrintf("Config file: %lS\n", settingsFilePath.raw());
809
810 ULONG memorySize;
811 rc = machine->COMGETTER(MemorySize)(&memorySize);
812 if (details == VMINFO_MACHINEREADABLE)
813 RTPrintf("memory=%u\n", memorySize);
814 else
815 RTPrintf("Memory size: %uMB\n", memorySize);
816
817 ULONG vramSize;
818 rc = machine->COMGETTER(VRAMSize)(&vramSize);
819 if (details == VMINFO_MACHINEREADABLE)
820 RTPrintf("vram=%u\n", vramSize);
821 else
822 RTPrintf("VRAM size: %uMB\n", vramSize);
823
824 ComPtr <IBIOSSettings> biosSettings;
825 machine->COMGETTER(BIOSSettings)(biosSettings.asOutParam());
826
827 BIOSBootMenuMode_T bootMenuMode;
828 biosSettings->COMGETTER(BootMenuMode)(&bootMenuMode);
829 const char *pszBootMenu = NULL;
830 switch (bootMenuMode)
831 {
832 case BIOSBootMenuMode_Disabled:
833 pszBootMenu = "disabled";
834 break;
835 case BIOSBootMenuMode_MenuOnly:
836 if (details == VMINFO_MACHINEREADABLE)
837 pszBootMenu = "menuonly";
838 else
839 pszBootMenu = "menu only";
840 break;
841 default:
842 if (details == VMINFO_MACHINEREADABLE)
843 pszBootMenu = "messageandmenu";
844 else
845 pszBootMenu = "message and menu";
846 }
847 if (details == VMINFO_MACHINEREADABLE)
848 RTPrintf("bootmenu=\"%s\"\n", pszBootMenu);
849 else
850 RTPrintf("Boot menu mode: %s\n", pszBootMenu);
851
852 BOOL acpiEnabled;
853 biosSettings->COMGETTER(ACPIEnabled)(&acpiEnabled);
854 if (details == VMINFO_MACHINEREADABLE)
855 RTPrintf("acpi=\"%s\"\n", acpiEnabled ? "on" : "off");
856 else
857 RTPrintf("ACPI: %s\n", acpiEnabled ? "on" : "off");
858
859 BOOL ioapicEnabled;
860 biosSettings->COMGETTER(IOAPICEnabled)(&ioapicEnabled);
861 if (details == VMINFO_MACHINEREADABLE)
862 RTPrintf("ioapic=\"%s\"\n", ioapicEnabled ? "on" : "off");
863 else
864 RTPrintf("IOAPIC: %s\n", ioapicEnabled ? "on" : "off");
865
866 LONG64 timeOffset;
867 biosSettings->COMGETTER(TimeOffset)(&timeOffset);
868 if (details == VMINFO_MACHINEREADABLE)
869 RTPrintf("biossystemtimeoffset=%lld\n", timeOffset);
870 else
871 RTPrintf("Time offset: %lld ms\n", timeOffset);
872
873 TriStateBool_T hwVirtExEnabled;
874 machine->COMGETTER(HWVirtExEnabled)(&hwVirtExEnabled);
875 if (hwVirtExEnabled == TriStateBool_Default)
876 {
877 BOOL fHWVirtExEnabled;
878 ComPtr<ISystemProperties> systemProperties;
879 virtualBox->COMGETTER(SystemProperties)(systemProperties.asOutParam());
880 systemProperties->COMGETTER(HWVirtExEnabled)(&fHWVirtExEnabled);
881 if (details == VMINFO_MACHINEREADABLE)
882 RTPrintf("hwvirtex=\"default\"\n");
883 else
884 RTPrintf("Hardw. virt.ext: Default (%s)\n", fHWVirtExEnabled ? "on" : "off");
885 }
886 else
887 {
888 if (details == VMINFO_MACHINEREADABLE)
889 RTPrintf("hwvirtex=\"%s\"\n", hwVirtExEnabled == TriStateBool_True ? "on" : "off");
890 else
891 RTPrintf("Hardw. virt.ext: %s\n", hwVirtExEnabled == TriStateBool_True ? "on" : "off");
892 }
893
894 MachineState_T machineState;
895 const char *pszState = NULL;
896 rc = machine->COMGETTER(State)(&machineState);
897 switch (machineState)
898 {
899 case MachineState_PoweredOff:
900 if (details == VMINFO_MACHINEREADABLE)
901 pszState = "poweroff";
902 else
903 pszState = "powered off";
904 break;
905 case MachineState_Saved:
906 pszState = "saved";
907 break;
908 case MachineState_Aborted:
909 pszState = "aborted";
910 break;
911 case MachineState_Running:
912 pszState = "running";
913 break;
914 case MachineState_Paused:
915 pszState = "paused";
916 break;
917 case MachineState_Starting:
918 pszState = "starting";
919 break;
920 case MachineState_Stopping:
921 pszState = "stopping";
922 break;
923 case MachineState_Saving:
924 pszState = "saving";
925 break;
926 case MachineState_Restoring:
927 pszState = "restoring";
928 break;
929 default:
930 pszState = "unknown";
931 break;
932 }
933 LONG64 stateSince;
934 machine->COMGETTER(LastStateChange)(&stateSince);
935 RTTIMESPEC timeSpec;
936 RTTimeSpecSetMilli(&timeSpec, stateSince);
937 char pszTime[30] = {0};
938 RTTimeSpecToString(&timeSpec, pszTime, 30);
939 if (details == VMINFO_MACHINEREADABLE)
940 {
941 RTPrintf("VMState=\"%s\"\n", pszState);
942 RTPrintf("VMStateChangeTime=\"%s\"\n", pszTime);
943 }
944 else
945 RTPrintf("State: %s (since %s)\n", pszState, pszTime);
946
947 ULONG numMonitors;
948 machine->COMGETTER(MonitorCount)(&numMonitors);
949 if (details == VMINFO_MACHINEREADABLE)
950 RTPrintf("monitorcount=%d\n", numMonitors);
951 else
952 RTPrintf("Monitor count: %d\n", numMonitors);
953
954 ComPtr<IFloppyDrive> floppyDrive;
955 rc = machine->COMGETTER(FloppyDrive)(floppyDrive.asOutParam());
956 if (SUCCEEDED(rc) && floppyDrive)
957 {
958 BOOL fFloppyEnabled;
959 floppyDrive->COMGETTER(Enabled)(&fFloppyEnabled);
960 Utf8Str pszFloppy = "invalid";
961 if (fFloppyEnabled)
962 {
963 DriveState_T floppyState;
964 floppyDrive->COMGETTER(State)(&floppyState);
965 switch (floppyState)
966 {
967 case DriveState_ImageMounted:
968 {
969 ComPtr<IFloppyImage> floppyImage;
970 rc = floppyDrive->GetImage(floppyImage.asOutParam());
971 if (SUCCEEDED(rc) && floppyImage)
972 {
973 Bstr imagePath;
974 floppyImage->COMGETTER(FilePath)(imagePath.asOutParam());
975 Guid imageGuid;
976 floppyImage->COMGETTER(Id)(imageGuid.asOutParam());
977 if (details == VMINFO_MACHINEREADABLE)
978 {
979 RTPrintf("FloppyImageUUID=\"%s\"\n", imageGuid.toString().raw());
980 pszFloppy = Utf8StrFmt("%lS", imagePath.raw());
981 }
982 else
983 pszFloppy = Utf8StrFmt("%lS (UUID: %s)", imagePath.raw(), imageGuid.toString().raw());
984 }
985 break;
986 }
987
988 case DriveState_HostDriveCaptured:
989 {
990 ComPtr<IHostFloppyDrive> hostFloppyDrive;
991 rc = floppyDrive->GetHostDrive(hostFloppyDrive.asOutParam());
992 if (SUCCEEDED(rc) && floppyDrive)
993 {
994 Bstr driveName;
995 hostFloppyDrive->COMGETTER(Name)(driveName.asOutParam());
996 if (details == VMINFO_MACHINEREADABLE)
997 pszFloppy = Utf8StrFmt("host:%lS", driveName.raw());
998 else
999 pszFloppy = Utf8StrFmt("Host drive %lS", driveName.raw());
1000 }
1001 break;
1002 }
1003
1004 case DriveState_NotMounted:
1005 {
1006 pszFloppy = "empty";
1007 break;
1008 }
1009 }
1010 }
1011 else
1012 {
1013 pszFloppy = "disabled";
1014 }
1015 if (details == VMINFO_MACHINEREADABLE)
1016 RTPrintf("floppy=\"%s\"\n", pszFloppy.raw());
1017 else
1018 RTPrintf("Floppy: %s\n", pszFloppy.raw());
1019 }
1020
1021 ComPtr<IHardDisk> hardDisk;
1022 Bstr filePath;
1023 rc = machine->GetHardDisk(DiskControllerType_IDE0Controller, 0, hardDisk.asOutParam());
1024 if (SUCCEEDED(rc) && hardDisk)
1025 {
1026 /// @todo (dmik) we temporarily use the location property to
1027 // determine the image file name. This is subject to change
1028 // when iSCSI disks are here (we should either query a
1029 // storage-specific interface from IHardDisk, or "standardize"
1030 // the location property)
1031 hardDisk->COMGETTER(Location)(filePath.asOutParam());
1032 hardDisk->COMGETTER(Id)(uuid.asOutParam());
1033 if (details == VMINFO_MACHINEREADABLE)
1034 {
1035 RTPrintf("hda=\"%lS\"\n", filePath.raw());
1036 RTPrintf("HdaImageUUID=\"%s\"\n", uuid.toString().raw());
1037 }
1038 else
1039 RTPrintf("Primary master: %lS (UUID: %s)\n", filePath.raw(), uuid.toString().raw());
1040 }
1041 else
1042 {
1043 if (details == VMINFO_MACHINEREADABLE)
1044 RTPrintf("hda=\"none\"\n");
1045 }
1046 rc = machine->GetHardDisk(DiskControllerType_IDE0Controller, 1, hardDisk.asOutParam());
1047 if (SUCCEEDED(rc) && hardDisk)
1048 {
1049 /// @todo (dmik) we temporarily use the location property to
1050 // determine the image file name. This is subject to change
1051 // when iSCSI disks are here (we should either query a
1052 // storage-specific interface from IHardDisk, or "standardize"
1053 // the location property)
1054 hardDisk->COMGETTER(Location)(filePath.asOutParam());
1055 hardDisk->COMGETTER(Id)(uuid.asOutParam());
1056 if (details == VMINFO_MACHINEREADABLE)
1057 {
1058 RTPrintf("hdb=\"%lS\"\n", filePath.raw());
1059 RTPrintf("HdbImageUUID=\"%s\"\n", uuid.toString().raw());
1060 }
1061 else
1062 RTPrintf("Primary slave: %lS (UUID: %s)\n", filePath.raw(), uuid.toString().raw());
1063 }
1064 else
1065 {
1066 if (details == VMINFO_MACHINEREADABLE)
1067 RTPrintf("hdb=\"none\"\n");
1068 }
1069 rc = machine->GetHardDisk(DiskControllerType_IDE1Controller, 1, hardDisk.asOutParam());
1070 if (SUCCEEDED(rc) && hardDisk)
1071 {
1072 /// @todo (dmik) we temporarily use the location property to
1073 // determine the image file name. This is subject to change
1074 // when iSCSI disks are here (we should either query a
1075 // storage-specific interface from IHardDisk, or "standardize"
1076 // the location property)
1077 hardDisk->COMGETTER(Location)(filePath.asOutParam());
1078 hardDisk->COMGETTER(Id)(uuid.asOutParam());
1079 if (details == VMINFO_MACHINEREADABLE)
1080 {
1081 RTPrintf("hdd=\"%lS\"\n", filePath.raw());
1082 RTPrintf("HddImageUUID=\"%s\"\n", uuid.toString().raw());
1083 }
1084 else
1085 RTPrintf("Secondary slave: %lS (UUID: %s)\n", filePath.raw(), uuid.toString().raw());
1086 }
1087 else
1088 {
1089 if (details == VMINFO_MACHINEREADABLE)
1090 RTPrintf("hdd=\"none\"\n");
1091 }
1092 ComPtr<IDVDDrive> dvdDrive;
1093 rc = machine->COMGETTER(DVDDrive)(dvdDrive.asOutParam());
1094 if (SUCCEEDED(rc) && dvdDrive)
1095 {
1096 ComPtr<IDVDImage> dvdImage;
1097 rc = dvdDrive->GetImage(dvdImage.asOutParam());
1098 if (SUCCEEDED(rc) && dvdImage)
1099 {
1100 rc = dvdImage->COMGETTER(FilePath)(filePath.asOutParam());
1101 if (SUCCEEDED(rc) && filePath)
1102 {
1103 rc = dvdImage->COMGETTER(Id)(uuid.asOutParam());
1104 if (details == VMINFO_MACHINEREADABLE)
1105 {
1106 RTPrintf("dvd=\"%lS\"\n", filePath.raw());
1107 RTPrintf("DvdImageUUID=\"%s\"\n", uuid.toString().raw());
1108 }
1109 else
1110 RTPrintf("DVD: %lS (UUID: %s)\n", filePath.raw(), uuid.toString().raw());
1111 }
1112 }
1113 else
1114 {
1115 ComPtr<IHostDVDDrive> hostDVDDrive;
1116 rc = dvdDrive->GetHostDrive(hostDVDDrive.asOutParam());
1117 if (SUCCEEDED(rc) && hostDVDDrive)
1118 {
1119 Bstr name;
1120 hostDVDDrive->COMGETTER(Name)(name.asOutParam());
1121 if (details == VMINFO_MACHINEREADABLE)
1122 RTPrintf("dvd=\"host:%lS\"\n", name.raw());
1123 else
1124 RTPrintf("DVD: Host drive %lS", name.raw());
1125 }
1126 else
1127 {
1128 if (details == VMINFO_MACHINEREADABLE)
1129 RTPrintf("dvd=\"none\"\n");
1130 else
1131 RTPrintf("DVD: empty");
1132 }
1133 BOOL fPassthrough;
1134 dvdDrive->COMGETTER(Passthrough)(&fPassthrough);
1135 if (details == VMINFO_MACHINEREADABLE)
1136 {
1137 RTPrintf("dvdpassthrough=\"%s\"\n", fPassthrough ? "on" : "off");
1138 }
1139 else
1140 {
1141 if (fPassthrough)
1142 RTPrintf(" (passthrough enabled)");
1143 RTPrintf("\n");
1144 }
1145 }
1146 }
1147
1148 /* get the maximum amount of NICS */
1149 ComPtr<ISystemProperties> sysProps;
1150 virtualBox->COMGETTER(SystemProperties)(sysProps.asOutParam());
1151 ULONG maxNICs = 0;
1152 sysProps->COMGETTER(NetworkAdapterCount)(&maxNICs);
1153 for (ULONG currentNIC = 0; currentNIC < maxNICs; currentNIC++)
1154 {
1155 ComPtr<INetworkAdapter> nic;
1156 rc = machine->GetNetworkAdapter(currentNIC, nic.asOutParam());
1157 if (SUCCEEDED(rc) && nic)
1158 {
1159 BOOL fEnabled;
1160 nic->COMGETTER(Enabled)(&fEnabled);
1161 if (!fEnabled)
1162 {
1163 if (details == VMINFO_MACHINEREADABLE)
1164 RTPrintf("nic%d=\"none\"\n", currentNIC + 1);
1165 else
1166 RTPrintf("NIC %d: disabled\n", currentNIC + 1);
1167 }
1168 else
1169 {
1170 Bstr strMACAddress;
1171 nic->COMGETTER(MACAddress)(strMACAddress.asOutParam());
1172 Utf8Str strAttachment;
1173 NetworkAttachmentType_T attachment;
1174 nic->COMGETTER(AttachmentType)(&attachment);
1175 switch (attachment)
1176 {
1177 case NetworkAttachmentType_NoNetworkAttachment:
1178 if (details == VMINFO_MACHINEREADABLE)
1179 strAttachment = "null";
1180 else
1181 strAttachment = "none";
1182 break;
1183 case NetworkAttachmentType_NATNetworkAttachment:
1184 if (details == VMINFO_MACHINEREADABLE)
1185 strAttachment = "nat";
1186 else
1187 strAttachment = "NAT";
1188 break;
1189 case NetworkAttachmentType_HostInterfaceNetworkAttachment:
1190 {
1191 Bstr strHostIfDev;
1192 nic->COMGETTER(HostInterface)(strHostIfDev.asOutParam());
1193 if (details == VMINFO_MACHINEREADABLE)
1194 {
1195 RTPrintf("hostifdev%d=\"%lS\"\n", currentNIC + 1, strHostIfDev.raw());
1196 strAttachment = "hostif";
1197 }
1198 else
1199 strAttachment = Utf8StrFmt("Host Interface '%lS'", strHostIfDev.raw());
1200 break;
1201 }
1202 case NetworkAttachmentType_InternalNetworkAttachment:
1203 {
1204 Bstr strNetwork;
1205 nic->COMGETTER(InternalNetwork)(strNetwork.asOutParam());
1206 if (details == VMINFO_MACHINEREADABLE)
1207 {
1208 RTPrintf("intnet%d=\"%lS\"\n", currentNIC + 1, strNetwork.raw());
1209 strAttachment = "intnet";
1210 }
1211 else
1212 strAttachment = Utf8StrFmt("Internal Network '%s'", Utf8Str(strNetwork).raw());
1213 break;
1214 }
1215 default:
1216 strAttachment = "unknown";
1217 break;
1218 }
1219
1220 /* cable connected */
1221 BOOL fConnected;
1222 nic->COMGETTER(CableConnected)(&fConnected);
1223
1224 /* trace stuff */
1225 BOOL fTraceEnabled;
1226 nic->COMGETTER(TraceEnabled)(&fTraceEnabled);
1227 Bstr traceFile;
1228 nic->COMGETTER(TraceFile)(traceFile.asOutParam());
1229
1230 /* NIC type */
1231 Utf8Str strNICType;
1232 NetworkAdapterType NICType;
1233 nic->COMGETTER(AdapterType)(&NICType);
1234 switch (NICType) {
1235 case NetworkAdapterType_NetworkAdapterAm79C970A:
1236 strNICType = "Am79C970A";
1237 break;
1238 case NetworkAdapterType_NetworkAdapterAm79C973:
1239 strNICType = "Am79C973";
1240 break;
1241 default:
1242 strNICType = "unknown";
1243 break;
1244 }
1245
1246 /* reported line speed */
1247 ULONG ulLineSpeed;
1248 nic->COMGETTER(LineSpeed)(&ulLineSpeed);
1249
1250 if (details == VMINFO_MACHINEREADABLE)
1251 {
1252 RTPrintf("macaddress%d=\"%lS\"\n", currentNIC + 1, strMACAddress.raw());
1253 RTPrintf("cableconnected%d=\"%s\"\n", currentNIC + 1, fConnected ? "on" : "off");
1254 RTPrintf("nic%d=\"%s\"\n", currentNIC + 1, strAttachment.raw());
1255 }
1256 else
1257 RTPrintf("NIC %d: MAC: %lS, Attachment: %s, Cable connected: %s, Trace: %s (file: %lS), Type: %s, Reported speed: %d Mbps\n",
1258 currentNIC + 1, strMACAddress.raw(), strAttachment.raw(),
1259 fConnected ? "on" : "off",
1260 fTraceEnabled ? "on" : "off", traceFile.raw(),
1261 strNICType.raw(),
1262 ulLineSpeed / 1000);
1263 }
1264 }
1265 }
1266
1267 /* get the maximum amount of UARTs */
1268 ULONG maxUARTs = 0;
1269 sysProps->COMGETTER(SerialPortCount)(&maxUARTs);
1270 for (ULONG currentUART = 0; currentUART < maxUARTs; currentUART++)
1271 {
1272 ComPtr<ISerialPort> uart;
1273 rc = machine->GetSerialPort(currentUART, uart.asOutParam());
1274 if (SUCCEEDED(rc) && uart)
1275 {
1276 BOOL fEnabled;
1277 uart->COMGETTER(Enabled)(&fEnabled);
1278 if (!fEnabled)
1279 {
1280 if (details == VMINFO_MACHINEREADABLE)
1281 RTPrintf("uart%d=\"off\"\n", currentUART + 1);
1282 else
1283 RTPrintf("UART %d: disabled\n", currentUART + 1);
1284 }
1285 else
1286 {
1287 ULONG ulIRQ, ulIOBase;
1288 PortMode_T HostMode;
1289 Bstr path;
1290 BOOL fServer;
1291 uart->COMGETTER(IRQ)(&ulIRQ);
1292 uart->COMGETTER(IOBase)(&ulIOBase);
1293 uart->COMGETTER(Path)(path.asOutParam());
1294 uart->COMGETTER(Server)(&fServer);
1295 uart->COMGETTER(HostMode)(&HostMode);
1296
1297 if (details == VMINFO_MACHINEREADABLE)
1298 RTPrintf("uart%d=\"%#06x,%d\"\n", currentUART + 1,
1299 ulIOBase, ulIRQ);
1300 else
1301 RTPrintf("UART %d: I/O base: 0x%04x, IRQ: %d",
1302 currentUART + 1, ulIOBase, ulIRQ);
1303 switch (HostMode)
1304 {
1305 default:
1306 case PortMode_DisconnectedPort:
1307 if (details == VMINFO_MACHINEREADABLE)
1308 RTPrintf("uartmode%d=\"disconnected\"\n", currentUART + 1);
1309 else
1310 RTPrintf(", disconnected\n");
1311 break;
1312 case PortMode_HostPipePort:
1313 if (details == VMINFO_MACHINEREADABLE)
1314 RTPrintf("uartmode%d=\"%s,%lS\"\n", currentUART + 1,
1315 fServer ? "server" : "client", path.raw());
1316 else
1317 RTPrintf(", attached to pipe (%s) '%lS'\n",
1318 fServer ? "server" : "client", path.raw());
1319 break;
1320 case PortMode_HostDevicePort:
1321 if (details == VMINFO_MACHINEREADABLE)
1322 RTPrintf("uartmode%d=\"%lS\"\n", currentUART + 1,
1323 path.raw());
1324 else
1325 RTPrintf(", attached to device '%lS'\n", path.raw());
1326 break;
1327 }
1328 }
1329 }
1330 }
1331
1332 ComPtr<IAudioAdapter> AudioAdapter;
1333 rc = machine->COMGETTER(AudioAdapter)(AudioAdapter.asOutParam());
1334 if (SUCCEEDED(rc))
1335 {
1336 const char *psz = "Unknown";
1337 BOOL fEnabled;
1338 rc = AudioAdapter->COMGETTER(Enabled)(&fEnabled);
1339 if (SUCCEEDED(rc) && fEnabled)
1340 {
1341 AudioDriverType_T enmType;
1342 rc = AudioAdapter->COMGETTER(AudioDriver)(&enmType);
1343 switch (enmType)
1344 {
1345 case AudioDriverType_NullAudioDriver:
1346 if (details == VMINFO_MACHINEREADABLE)
1347 psz = "null";
1348 else
1349 psz = "Null";
1350 break;
1351 case AudioDriverType_WINMMAudioDriver:
1352 if (details == VMINFO_MACHINEREADABLE)
1353 psz = "winmm";
1354 else
1355 psz = "WINMM";
1356 break;
1357 case AudioDriverType_DSOUNDAudioDriver:
1358 if (details == VMINFO_MACHINEREADABLE)
1359 psz = "dsound";
1360 else
1361 psz = "DSOUND";
1362 break;
1363 case AudioDriverType_OSSAudioDriver:
1364 if (details == VMINFO_MACHINEREADABLE)
1365 psz = "oss";
1366 else
1367 psz = "OSS";
1368 break;
1369 case AudioDriverType_ALSAAudioDriver:
1370 if (details == VMINFO_MACHINEREADABLE)
1371 psz = "alsa";
1372 else
1373 psz = "ALSA";
1374 break;
1375 case AudioDriverType_CoreAudioDriver:
1376 if (details == VMINFO_MACHINEREADABLE)
1377 psz = "coreaudio";
1378 else
1379 psz = "CoreAudio";
1380 break;
1381 default:
1382 if (details == VMINFO_MACHINEREADABLE)
1383 psz = "unknown";
1384 break;
1385 }
1386 }
1387 else
1388 fEnabled = FALSE;
1389 if (details == VMINFO_MACHINEREADABLE)
1390 {
1391 if (fEnabled)
1392 RTPrintf("audio=\"%s\"\n", psz);
1393 else
1394 RTPrintf("audio=\"none\"\n");
1395 }
1396 else
1397 RTPrintf("Audio: %s (Driver: %s)\n", fEnabled ? "enabled" : "disabled", psz);
1398 }
1399
1400 /* Shared clipboard */
1401 {
1402 const char *psz = "Unknown";
1403 ClipboardMode_T enmMode;
1404 rc = machine->COMGETTER(ClipboardMode)(&enmMode);
1405 switch (enmMode)
1406 {
1407 case ClipboardMode_ClipDisabled:
1408 if (details == VMINFO_MACHINEREADABLE)
1409 psz = "disabled";
1410 else
1411 psz = "disabled";
1412 break;
1413 case ClipboardMode_ClipHostToGuest:
1414 if (details == VMINFO_MACHINEREADABLE)
1415 psz = "hosttoguest";
1416 else
1417 psz = "HostToGuest";
1418 break;
1419 case ClipboardMode_ClipGuestToHost:
1420 if (details == VMINFO_MACHINEREADABLE)
1421 psz = "guesttohost";
1422 else
1423 psz = "GuestToHost";
1424 break;
1425 case ClipboardMode_ClipBidirectional:
1426 if (details == VMINFO_MACHINEREADABLE)
1427 psz = "bidirectional";
1428 else
1429 psz = "Bidirectional";
1430 break;
1431 default:
1432 if (details == VMINFO_MACHINEREADABLE)
1433 psz = "unknown";
1434 break;
1435 }
1436 if (details == VMINFO_MACHINEREADABLE)
1437 RTPrintf("clipboard=\"%s\"\n", psz);
1438 else
1439 RTPrintf("Clipboard Mode: %s\n", psz);
1440 }
1441
1442 if (console)
1443 {
1444 ComPtr<IDisplay> display;
1445 CHECK_ERROR_RET(console, COMGETTER(Display)(display.asOutParam()), rc);
1446 ULONG xRes, yRes, bpp;
1447 CHECK_ERROR_RET(display, COMGETTER(Width)(&xRes), rc);
1448 CHECK_ERROR_RET(display, COMGETTER(Height)(&yRes), rc);
1449 CHECK_ERROR_RET(display, COMGETTER(BitsPerPixel)(&bpp), rc);
1450 if (details == VMINFO_MACHINEREADABLE)
1451 RTPrintf("VideoMode=\"%d,%d,%d\"\n", xRes, yRes, bpp);
1452 else
1453 RTPrintf("Video mode: %dx%dx%d\n", xRes, yRes, bpp);
1454 }
1455
1456 /*
1457 * VRDP
1458 */
1459 ComPtr<IVRDPServer> vrdpServer;
1460 rc = machine->COMGETTER(VRDPServer)(vrdpServer.asOutParam());
1461 if (SUCCEEDED(rc) && vrdpServer)
1462 {
1463 BOOL fEnabled = false;
1464 vrdpServer->COMGETTER(Enabled)(&fEnabled);
1465 if (fEnabled)
1466 {
1467 ULONG port;
1468 vrdpServer->COMGETTER(Port)(&port);
1469 Bstr address;
1470 vrdpServer->COMGETTER(NetAddress)(address.asOutParam());
1471 BOOL fMultiCon;
1472 vrdpServer->COMGETTER(AllowMultiConnection)(&fMultiCon);
1473 VRDPAuthType_T vrdpAuthType;
1474 const char *strAuthType;
1475 vrdpServer->COMGETTER(AuthType)(&vrdpAuthType);
1476 switch (vrdpAuthType)
1477 {
1478 case VRDPAuthType_VRDPAuthNull:
1479 strAuthType = "null";
1480 break;
1481 case VRDPAuthType_VRDPAuthExternal:
1482 strAuthType = "external";
1483 break;
1484 case VRDPAuthType_VRDPAuthGuest:
1485 strAuthType = "guest";
1486 break;
1487 default:
1488 strAuthType = "unknown";
1489 break;
1490 }
1491 if (details == VMINFO_MACHINEREADABLE)
1492 {
1493 RTPrintf("vrdp=\"on\"\n");
1494 RTPrintf("vrdpport=%d\n", port);
1495 RTPrintf("vrdpaddress=\"%lS\"\n", address.raw());
1496 RTPrintf("vrdpauthtype=\"%s\"\n", strAuthType);
1497 RTPrintf("vrdpmulticon=\"%s\"\n", fMultiCon ? "on" : "off");
1498 }
1499 else
1500 {
1501 if (address.isEmpty())
1502 address = "0.0.0.0";
1503 RTPrintf("VRDP: enabled (Address %lS, Port %d, MultiConn: %s, Authentication type: %s)\n", address.raw(), port, fMultiCon ? "on" : "off", strAuthType);
1504 }
1505 }
1506 else
1507 {
1508 if (details == VMINFO_MACHINEREADABLE)
1509 RTPrintf("vrdp=\"off\"\n");
1510 else
1511 RTPrintf("VRDP: disabled\n");
1512 }
1513 }
1514
1515 /*
1516 * USB.
1517 */
1518 ComPtr<IUSBController> USBCtl;
1519 rc = machine->COMGETTER(USBController)(USBCtl.asOutParam());
1520 if (SUCCEEDED(rc))
1521 {
1522 BOOL fEnabled;
1523 rc = USBCtl->COMGETTER(Enabled)(&fEnabled);
1524 if (FAILED(rc))
1525 fEnabled = false;
1526 if (details == VMINFO_MACHINEREADABLE)
1527 RTPrintf("usb=\"%s\"\n", fEnabled ? "on" : "off");
1528 else
1529 RTPrintf("USB: %s\n", fEnabled ? "enabled" : "disabled");
1530
1531 if (details != VMINFO_MACHINEREADABLE)
1532 RTPrintf("\nUSB Device Filters:\n\n");
1533
1534 ComPtr<IUSBDeviceFilterCollection> Coll;
1535 CHECK_ERROR_RET (USBCtl, COMGETTER(DeviceFilters)(Coll.asOutParam()), rc);
1536
1537 ComPtr<IUSBDeviceFilterEnumerator> Enum;
1538 CHECK_ERROR_RET (Coll, Enumerate(Enum.asOutParam()), rc);
1539
1540 ULONG index = 0;
1541 BOOL fMore = FALSE;
1542 rc = Enum->HasMore (&fMore);
1543 ASSERT_RET (SUCCEEDED (rc), rc);
1544
1545 if (!fMore)
1546 {
1547 if (details != VMINFO_MACHINEREADABLE)
1548 RTPrintf("<none>\n\n");
1549 }
1550 else
1551 while (fMore)
1552 {
1553 ComPtr<IUSBDeviceFilter> DevPtr;
1554 rc = Enum->GetNext(DevPtr.asOutParam());
1555 ASSERT_RET (SUCCEEDED (rc), rc);
1556
1557 /* Query info. */
1558
1559 if (details == VMINFO_MACHINEREADABLE)
1560 RTPrintf("Index: %lu\n", index);
1561
1562 BOOL bActive = FALSE;
1563 CHECK_ERROR_RET (DevPtr, COMGETTER (Active) (&bActive), rc);
1564 if (details == VMINFO_MACHINEREADABLE)
1565 RTPrintf("USBFilterActive%d=\"%s\"\n", index + 1, bActive ? "on" : "off");
1566 else
1567 RTPrintf("Active: %s\n", bActive ? "yes" : "no");
1568
1569 Bstr bstr;
1570 CHECK_ERROR_RET (DevPtr, COMGETTER (Name) (bstr.asOutParam()), rc);
1571 if (details == VMINFO_MACHINEREADABLE)
1572 RTPrintf("USBFilterName%d=\"%lS\"\n", index + 1, bstr.raw());
1573 else
1574 RTPrintf("Name: %lS\n", bstr.raw());
1575 CHECK_ERROR_RET (DevPtr, COMGETTER (VendorId) (bstr.asOutParam()), rc);
1576 if (details == VMINFO_MACHINEREADABLE)
1577 RTPrintf("USBFilterVendorId%d=\"%lS\"\n", index + 1, bstr.raw());
1578 else
1579 RTPrintf("VendorId: %lS\n", bstr.raw());
1580 CHECK_ERROR_RET (DevPtr, COMGETTER (ProductId) (bstr.asOutParam()), rc);
1581 if (details == VMINFO_MACHINEREADABLE)
1582 RTPrintf("USBFilterProductId%d=\"%lS\"\n", index + 1, bstr.raw());
1583 else
1584 RTPrintf("ProductId: %lS\n", bstr.raw());
1585 CHECK_ERROR_RET (DevPtr, COMGETTER (Revision) (bstr.asOutParam()), rc);
1586 if (details == VMINFO_MACHINEREADABLE)
1587 RTPrintf("USBFilterRevision%d=\"%lS\"\n", index + 1, bstr.raw());
1588 else
1589 RTPrintf("Revision: %lS\n", bstr.raw());
1590 CHECK_ERROR_RET (DevPtr, COMGETTER (Manufacturer) (bstr.asOutParam()), rc);
1591 if (details == VMINFO_MACHINEREADABLE)
1592 RTPrintf("USBFilterManufacturer%d=\"%lS\"\n", index + 1, bstr.raw());
1593 else
1594 RTPrintf("Manufacturer: %lS\n", bstr.raw());
1595 CHECK_ERROR_RET (DevPtr, COMGETTER (Product) (bstr.asOutParam()), rc);
1596 if (details == VMINFO_MACHINEREADABLE)
1597 RTPrintf("USBFilterProduct%d=\"%lS\"\n", index + 1, bstr.raw());
1598 else
1599 RTPrintf("Product: %lS\n", bstr.raw());
1600 CHECK_ERROR_RET (DevPtr, COMGETTER (Remote) (bstr.asOutParam()), rc);
1601 if (details == VMINFO_MACHINEREADABLE)
1602 RTPrintf("USBFilterRemote%d=\"%lS\"\n", index + 1, bstr.raw());
1603 else
1604 RTPrintf("Remote: %lS\n\n", bstr.raw());
1605 CHECK_ERROR_RET (DevPtr, COMGETTER (SerialNumber) (bstr.asOutParam()), rc);
1606 if (details == VMINFO_MACHINEREADABLE)
1607 RTPrintf("USBFilterSerialNumber%d=\"%lS\"\n", index + 1, bstr.raw());
1608 else
1609 RTPrintf("Serial Number: %lS\n\n", bstr.raw());
1610
1611 rc = Enum->HasMore (&fMore);
1612 ASSERT_RET (SUCCEEDED (rc), rc);
1613
1614 index ++;
1615 }
1616
1617 if (console)
1618 {
1619 index = 0;
1620 /* scope */
1621 {
1622 if (details != VMINFO_MACHINEREADABLE)
1623 RTPrintf("Available remote USB devices:\n\n");
1624
1625 ComPtr<IHostUSBDeviceCollection> coll;
1626 CHECK_ERROR_RET (console, COMGETTER(RemoteUSBDevices) (coll.asOutParam()), rc);
1627
1628 ComPtr <IHostUSBDeviceEnumerator> en;
1629 CHECK_ERROR_RET (coll, Enumerate (en.asOutParam()), rc);
1630
1631 BOOL more = FALSE;
1632 rc = en->HasMore (&more);
1633 ASSERT_RET (SUCCEEDED (rc), rc);
1634
1635 if (!more)
1636 {
1637 if (details != VMINFO_MACHINEREADABLE)
1638 RTPrintf("<none>\n\n");
1639 }
1640 else
1641 while (more)
1642 {
1643 ComPtr <IHostUSBDevice> dev;
1644 rc = en->GetNext (dev.asOutParam());
1645 ASSERT_RET (SUCCEEDED (rc), rc);
1646
1647 /* Query info. */
1648 Guid id;
1649 CHECK_ERROR_RET (dev, COMGETTER(Id)(id.asOutParam()), rc);
1650 USHORT usVendorId;
1651 CHECK_ERROR_RET (dev, COMGETTER(VendorId)(&usVendorId), rc);
1652 USHORT usProductId;
1653 CHECK_ERROR_RET (dev, COMGETTER(ProductId)(&usProductId), rc);
1654 USHORT bcdRevision;
1655 CHECK_ERROR_RET (dev, COMGETTER(Revision)(&bcdRevision), rc);
1656
1657 if (details == VMINFO_MACHINEREADABLE)
1658 RTPrintf("USBRemoteUUID%d=\"%S\"\n"
1659 "USBRemoteVendorId%d=\"%#06x\"\n"
1660 "USBRemoteProductId%d=\"%#06x\"\n"
1661 "USBRemoteRevision%d=\"%#04x%02x\"\n",
1662 index + 1, id.toString().raw(),
1663 index + 1, usVendorId,
1664 index + 1, usProductId,
1665 index + 1, bcdRevision >> 8, bcdRevision & 0xff);
1666 else
1667 RTPrintf("UUID: %S\n"
1668 "VendorId: 0x%04x (%04X)\n"
1669 "ProductId: 0x%04x (%04X)\n"
1670 "Revision: %u.%u (%02u%02u)\n",
1671 id.toString().raw(),
1672 usVendorId, usVendorId, usProductId, usProductId,
1673 bcdRevision >> 8, bcdRevision & 0xff,
1674 bcdRevision >> 8, bcdRevision & 0xff);
1675
1676 /* optional stuff. */
1677 Bstr bstr;
1678 CHECK_ERROR_RET (dev, COMGETTER(Manufacturer)(bstr.asOutParam()), rc);
1679 if (!bstr.isEmpty())
1680 {
1681 if (details == VMINFO_MACHINEREADABLE)
1682 RTPrintf("USBRemoteManufacturer%d=\"%lS\"\n", index + 1, bstr.raw());
1683 else
1684 RTPrintf("Manufacturer: %lS\n", bstr.raw());
1685 }
1686 CHECK_ERROR_RET (dev, COMGETTER(Product)(bstr.asOutParam()), rc);
1687 if (!bstr.isEmpty())
1688 {
1689 if (details == VMINFO_MACHINEREADABLE)
1690 RTPrintf("USBRemoteProduct%d=\"%lS\"\n", index + 1, bstr.raw());
1691 else
1692 RTPrintf("Product: %lS\n", bstr.raw());
1693 }
1694 CHECK_ERROR_RET (dev, COMGETTER(SerialNumber)(bstr.asOutParam()), rc);
1695 if (!bstr.isEmpty())
1696 {
1697 if (details == VMINFO_MACHINEREADABLE)
1698 RTPrintf("USBRemoteSerialNumber%d=\"%lS\"\n", index + 1, bstr.raw());
1699 else
1700 RTPrintf("SerialNumber: %lS\n", bstr.raw());
1701 }
1702 CHECK_ERROR_RET (dev, COMGETTER(Address)(bstr.asOutParam()), rc);
1703 if (!bstr.isEmpty())
1704 {
1705 if (details == VMINFO_MACHINEREADABLE)
1706 RTPrintf("USBRemoteAddress%d=\"%lS\"\n", index + 1, bstr.raw());
1707 else
1708 RTPrintf("Address: %lS\n", bstr.raw());
1709 }
1710
1711 if (details != VMINFO_MACHINEREADABLE)
1712 RTPrintf("\n");
1713
1714 rc = en->HasMore (&more);
1715 ASSERT_RET (SUCCEEDED (rc), rc);
1716
1717 index ++;
1718 }
1719 }
1720
1721 index = 0;
1722 /* scope */
1723 {
1724 if (details != VMINFO_MACHINEREADABLE)
1725 RTPrintf ("Currently Attached USB Devices:\n\n");
1726
1727 ComPtr <IUSBDeviceCollection> coll;
1728 CHECK_ERROR_RET (console, COMGETTER(USBDevices) (coll.asOutParam()), rc);
1729
1730 ComPtr <IUSBDeviceEnumerator> en;
1731 CHECK_ERROR_RET (coll, Enumerate (en.asOutParam()), rc);
1732
1733 BOOL more = FALSE;
1734 rc = en->HasMore (&more);
1735 ASSERT_RET (SUCCEEDED (rc), rc);
1736
1737 if (!more)
1738 {
1739 if (details != VMINFO_MACHINEREADABLE)
1740 RTPrintf("<none>\n\n");
1741 }
1742 else
1743 while (more)
1744 {
1745 ComPtr <IUSBDevice> dev;
1746 rc = en->GetNext (dev.asOutParam());
1747 ASSERT_RET (SUCCEEDED (rc), rc);
1748
1749 /* Query info. */
1750 Guid id;
1751 CHECK_ERROR_RET (dev, COMGETTER(Id)(id.asOutParam()), rc);
1752 USHORT usVendorId;
1753 CHECK_ERROR_RET (dev, COMGETTER(VendorId)(&usVendorId), rc);
1754 USHORT usProductId;
1755 CHECK_ERROR_RET (dev, COMGETTER(ProductId)(&usProductId), rc);
1756 USHORT bcdRevision;
1757 CHECK_ERROR_RET (dev, COMGETTER(Revision)(&bcdRevision), rc);
1758
1759 if (details == VMINFO_MACHINEREADABLE)
1760 RTPrintf("USBAttachedUUID%d=\"%S\"\n"
1761 "USBAttachedVendorId%d=\"%#06x\"\n"
1762 "USBAttachedProductId%d=\"%#06x\"\n"
1763 "USBAttachedRevision%d=\"%#04x%02x\"\n",
1764 index + 1, id.toString().raw(),
1765 index + 1, usVendorId,
1766 index + 1, usProductId,
1767 index + 1, bcdRevision >> 8, bcdRevision & 0xff);
1768 else
1769 RTPrintf("UUID: %S\n"
1770 "VendorId: 0x%04x (%04X)\n"
1771 "ProductId: 0x%04x (%04X)\n"
1772 "Revision: %u.%u (%02u%02u)\n",
1773 id.toString().raw(),
1774 usVendorId, usVendorId, usProductId, usProductId,
1775 bcdRevision >> 8, bcdRevision & 0xff,
1776 bcdRevision >> 8, bcdRevision & 0xff);
1777
1778 /* optional stuff. */
1779 Bstr bstr;
1780 CHECK_ERROR_RET (dev, COMGETTER(Manufacturer)(bstr.asOutParam()), rc);
1781 if (!bstr.isEmpty())
1782 {
1783 if (details == VMINFO_MACHINEREADABLE)
1784 RTPrintf("USBAttachedManufacturer%d=\"%lS\"\n", index + 1, bstr.raw());
1785 else
1786 RTPrintf("Manufacturer: %lS\n", bstr.raw());
1787 }
1788 CHECK_ERROR_RET (dev, COMGETTER(Product)(bstr.asOutParam()), rc);
1789 if (!bstr.isEmpty())
1790 {
1791 if (details == VMINFO_MACHINEREADABLE)
1792 RTPrintf("USBAttachedProduct%d=\"%lS\"\n", index + 1, bstr.raw());
1793 else
1794 RTPrintf("Product: %lS\n", bstr.raw());
1795 }
1796 CHECK_ERROR_RET (dev, COMGETTER(SerialNumber)(bstr.asOutParam()), rc);
1797 if (!bstr.isEmpty())
1798 {
1799 if (details == VMINFO_MACHINEREADABLE)
1800 RTPrintf("USBAttachedSerialNumber%d=\"%lS\"\n", index + 1, bstr.raw());
1801 else
1802 RTPrintf("SerialNumber: %lS\n", bstr.raw());
1803 }
1804 CHECK_ERROR_RET (dev, COMGETTER(Address)(bstr.asOutParam()), rc);
1805 if (!bstr.isEmpty())
1806 {
1807 if (details == VMINFO_MACHINEREADABLE)
1808 RTPrintf("USBAttachedAddress%d=\"%lS\"\n", index + 1, bstr.raw());
1809 else
1810 RTPrintf("Address: %lS\n", bstr.raw());
1811 }
1812
1813 if (details != VMINFO_MACHINEREADABLE)
1814 RTPrintf("\n");
1815
1816 rc = en->HasMore (&more);
1817 ASSERT_RET (SUCCEEDED (rc), rc);
1818
1819 index ++;
1820 }
1821 }
1822 }
1823 } /* USB */
1824
1825 /*
1826 * Shared folders
1827 */
1828 if (details != VMINFO_MACHINEREADABLE)
1829 RTPrintf("Shared folders: ");
1830 uint32_t numSharedFolders = 0;
1831#if 0 // not yet implemented
1832 /* globally shared folders first */
1833 {
1834 ComPtr<ISharedFolderCollection> sfColl;
1835 ComPtr<ISharedFolderEnumerator> sfEnum;
1836 CHECK_ERROR_RET(virtualBox, COMGETTER(SharedFolders)(sfColl.asOutParam()), rc);
1837 CHECK_ERROR_RET(sfColl, Enumerate(sfEnum.asOutParam()), rc);
1838 BOOL fMore;
1839 sfEnum->HasMore(&fMore);
1840 while (fMore)
1841 {
1842 ComPtr<ISharedFolder> sf;
1843 CHECK_ERROR_RET(sfEnum, GetNext(sf.asOutParam()), rc);
1844 Bstr name, hostPath;
1845 sf->COMGETTER(Name)(name.asOutParam());
1846 sf->COMGETTER(HostPath)(hostPath.asOutParam());
1847 RTPrintf("Name: '%lS', Host path: '%lS' (global mapping)\n", name.raw(), hostPath.raw());
1848 ++numSharedFolders;
1849 CHECK_ERROR_RET(sfEnum, HasMore(&fMore), rc);
1850 }
1851 }
1852#endif
1853 /* now VM mappings */
1854 {
1855 ComPtr<ISharedFolderCollection> sfColl;
1856 ComPtr<ISharedFolderEnumerator> sfEnum;
1857 CHECK_ERROR_RET(machine, COMGETTER(SharedFolders)(sfColl.asOutParam()), rc);
1858 CHECK_ERROR_RET(sfColl, Enumerate(sfEnum.asOutParam()), rc);
1859 ULONG index = 0;
1860 BOOL fMore;
1861 sfEnum->HasMore(&fMore);
1862 while (fMore)
1863 {
1864 ComPtr<ISharedFolder> sf;
1865 CHECK_ERROR_RET(sfEnum, GetNext(sf.asOutParam()), rc);
1866 Bstr name, hostPath;
1867 sf->COMGETTER(Name)(name.asOutParam());
1868 sf->COMGETTER(HostPath)(hostPath.asOutParam());
1869 if (!numSharedFolders && details != VMINFO_MACHINEREADABLE)
1870 RTPrintf("\n\n");
1871 if (details == VMINFO_MACHINEREADABLE)
1872 {
1873 RTPrintf("SharedFolderNameMachineMapping%d=\"%lS\"\n", index + 1,
1874 name.raw());
1875 RTPrintf("SharedFolderPathMachineMapping%d=\"%lS\"\n", index + 1,
1876 hostPath.raw());
1877 }
1878 else
1879 RTPrintf("Name: '%lS', Host path: '%lS' (machine mapping)\n", name.raw(), hostPath.raw());
1880 ++numSharedFolders;
1881 CHECK_ERROR_RET(sfEnum, HasMore(&fMore), rc);
1882 }
1883 }
1884 /* transient mappings */
1885 if (console)
1886 {
1887 ComPtr<ISharedFolderCollection> sfColl;
1888 ComPtr<ISharedFolderEnumerator> sfEnum;
1889 CHECK_ERROR_RET(console, COMGETTER(SharedFolders)(sfColl.asOutParam()), rc);
1890 CHECK_ERROR_RET(sfColl, Enumerate(sfEnum.asOutParam()), rc);
1891 ULONG index = 0;
1892 BOOL fMore;
1893 sfEnum->HasMore(&fMore);
1894 while (fMore)
1895 {
1896 ComPtr<ISharedFolder> sf;
1897 CHECK_ERROR_RET(sfEnum, GetNext(sf.asOutParam()), rc);
1898 Bstr name, hostPath;
1899 sf->COMGETTER(Name)(name.asOutParam());
1900 sf->COMGETTER(HostPath)(hostPath.asOutParam());
1901 if (!numSharedFolders && details != VMINFO_MACHINEREADABLE)
1902 RTPrintf("\n\n");
1903 if (details == VMINFO_MACHINEREADABLE)
1904 {
1905 RTPrintf("SharedFolderNameTransientMapping%d=\"%lS\"\n", index + 1,
1906 name.raw());
1907 RTPrintf("SharedFolderPathTransientMapping%d=\"%lS\"\n", index + 1,
1908 hostPath.raw());
1909 }
1910 else
1911 RTPrintf("Name: '%lS', Host path: '%lS' (transient mapping)\n", name.raw(), hostPath.raw());
1912 ++numSharedFolders;
1913 CHECK_ERROR_RET(sfEnum, HasMore(&fMore), rc);
1914 }
1915 }
1916 if (!numSharedFolders && details != VMINFO_MACHINEREADABLE)
1917 RTPrintf("<none>\n");
1918 if (details != VMINFO_MACHINEREADABLE)
1919 RTPrintf("\n");
1920
1921 if (console)
1922 {
1923 /*
1924 * Live VRDP info.
1925 */
1926 ComPtr<IRemoteDisplayInfo> remoteDisplayInfo;
1927 CHECK_ERROR_RET(console, COMGETTER(RemoteDisplayInfo)(remoteDisplayInfo.asOutParam()), rc);
1928 BOOL Active;
1929 ULONG NumberOfClients;
1930 LONG64 BeginTime;
1931 LONG64 EndTime;
1932 ULONG64 BytesSent;
1933 ULONG64 BytesSentTotal;
1934 ULONG64 BytesReceived;
1935 ULONG64 BytesReceivedTotal;
1936 Bstr User;
1937 Bstr Domain;
1938 Bstr ClientName;
1939 Bstr ClientIP;
1940 ULONG ClientVersion;
1941 ULONG EncryptionStyle;
1942
1943 CHECK_ERROR_RET(remoteDisplayInfo, COMGETTER(Active) (&Active), rc);
1944 CHECK_ERROR_RET(remoteDisplayInfo, COMGETTER(NumberOfClients) (&NumberOfClients), rc);
1945 CHECK_ERROR_RET(remoteDisplayInfo, COMGETTER(BeginTime) (&BeginTime), rc);
1946 CHECK_ERROR_RET(remoteDisplayInfo, COMGETTER(EndTime) (&EndTime), rc);
1947 CHECK_ERROR_RET(remoteDisplayInfo, COMGETTER(BytesSent) (&BytesSent), rc);
1948 CHECK_ERROR_RET(remoteDisplayInfo, COMGETTER(BytesSentTotal) (&BytesSentTotal), rc);
1949 CHECK_ERROR_RET(remoteDisplayInfo, COMGETTER(BytesReceived) (&BytesReceived), rc);
1950 CHECK_ERROR_RET(remoteDisplayInfo, COMGETTER(BytesReceivedTotal) (&BytesReceivedTotal), rc);
1951 CHECK_ERROR_RET(remoteDisplayInfo, COMGETTER(User) (User.asOutParam ()), rc);
1952 CHECK_ERROR_RET(remoteDisplayInfo, COMGETTER(Domain) (Domain.asOutParam ()), rc);
1953 CHECK_ERROR_RET(remoteDisplayInfo, COMGETTER(ClientName) (ClientName.asOutParam ()), rc);
1954 CHECK_ERROR_RET(remoteDisplayInfo, COMGETTER(ClientIP) (ClientIP.asOutParam ()), rc);
1955 CHECK_ERROR_RET(remoteDisplayInfo, COMGETTER(ClientVersion) (&ClientVersion), rc);
1956 CHECK_ERROR_RET(remoteDisplayInfo, COMGETTER(EncryptionStyle) (&EncryptionStyle), rc);
1957
1958 if (details == VMINFO_MACHINEREADABLE)
1959 RTPrintf("VRDPActiveConnection=\"%s\"\n", Active ? "on": "off");
1960 else
1961 RTPrintf("VRDP Connection: %s\n", Active? "active": "not active");
1962
1963 if (details == VMINFO_MACHINEREADABLE)
1964 RTPrintf("VRDPClients=%d\n", NumberOfClients);
1965 else
1966 RTPrintf("Clients so far: %d\n", NumberOfClients);
1967
1968 if (NumberOfClients > 0)
1969 {
1970 char timestr[128];
1971
1972 if (Active)
1973 {
1974 makeTimeStr (timestr, sizeof (timestr), BeginTime);
1975 if (details == VMINFO_MACHINEREADABLE)
1976 RTPrintf("VRDPStartTime=\"%s\"\n", timestr);
1977 else
1978 RTPrintf("Start time: %s\n", timestr);
1979 }
1980 else
1981 {
1982 makeTimeStr (timestr, sizeof (timestr), BeginTime);
1983 if (details == VMINFO_MACHINEREADABLE)
1984 RTPrintf("VRDPLastStartTime=\"%s\"\n", timestr);
1985 else
1986 RTPrintf("Last started: %s\n", timestr);
1987 makeTimeStr (timestr, sizeof (timestr), EndTime);
1988 if (details == VMINFO_MACHINEREADABLE)
1989 RTPrintf("VRDPLastEndTime=\"%s\"\n", timestr);
1990 else
1991 RTPrintf("Last ended: %s\n", timestr);
1992 }
1993
1994 if (details == VMINFO_MACHINEREADABLE)
1995 {
1996 RTPrintf("VRDPBytesSent=%llu\n", BytesSent);
1997 RTPrintf("VRDPThroughputSend=%llu\n", (BytesSent * 1000) / (EndTime - BeginTime) );
1998 RTPrintf("VRDPBytesSentTotal=%llu\n", BytesSentTotal);
1999
2000 RTPrintf("VRDPBytesReceived=%llu\n", BytesReceived);
2001 RTPrintf("VRDPThroughputReceive=%llu\n", (BytesReceived * 1000) / (EndTime - BeginTime) );
2002 RTPrintf("VRDPBytesReceivedTotal=%llu\n", BytesReceivedTotal);
2003 }
2004 else
2005 {
2006 RTPrintf("Sent: %llu Bytes\n", BytesSent);
2007 RTPrintf("Average speed: %llu B/s\n", (BytesSent * 1000) / (EndTime - BeginTime) );
2008 RTPrintf("Sent total: %llu Bytes\n", BytesSentTotal);
2009
2010 RTPrintf("Received: %llu Bytes\n", BytesReceived);
2011 RTPrintf("Speed: %llu B/s\n", (BytesReceived * 1000) / (EndTime - BeginTime) );
2012 RTPrintf("Received total: %llu Bytes\n", BytesReceivedTotal);
2013 }
2014
2015 if (Active)
2016 {
2017 if (details == VMINFO_MACHINEREADABLE)
2018 {
2019 RTPrintf("VRDPUserName=\"%lS\"\n", User.raw());
2020 RTPrintf("VRDPDomain=\"%lS\"\n", Domain.raw());
2021 RTPrintf("VRDPClientName=\"%lS\"\n", ClientName.raw());
2022 RTPrintf("VRDPClientIP=\"%lS\"\n", ClientIP.raw());
2023 RTPrintf("VRDPClientVersion=%d\n", ClientVersion);
2024 RTPrintf("VRDPEncryption=\"%s\"\n", EncryptionStyle == 0? "RDP4": "RDP5 (X.509)");
2025 }
2026 else
2027 {
2028 RTPrintf("User name: %lS\n", User.raw());
2029 RTPrintf("Domain: %lS\n", Domain.raw());
2030 RTPrintf("Client name: %lS\n", ClientName.raw());
2031 RTPrintf("Client IP: %lS\n", ClientIP.raw());
2032 RTPrintf("Client version: %d\n", ClientVersion);
2033 RTPrintf("Encryption: %s\n", EncryptionStyle == 0? "RDP4": "RDP5 (X.509)");
2034 }
2035 }
2036 }
2037
2038 if (details != VMINFO_MACHINEREADABLE)
2039 RTPrintf("\n");
2040 }
2041
2042 if ( details == VMINFO_STANDARD
2043 || details == VMINFO_FULL
2044 || details == VMINFO_MACHINEREADABLE)
2045 {
2046 Bstr description;
2047 machine->COMGETTER(Description)(description.asOutParam());
2048 if (!description.isEmpty())
2049 {
2050 if (details == VMINFO_MACHINEREADABLE)
2051 RTPrintf("description=\"%lS\"\n", description.raw());
2052 else
2053 RTPrintf("Description:\n%lS\n", description.raw());
2054 }
2055 }
2056
2057 ULONG guestVal;
2058 if (details != VMINFO_MACHINEREADABLE)
2059 RTPrintf("Guest:\n\n");
2060
2061 rc = machine->COMGETTER(MemoryBalloonSize)(&guestVal);
2062 if (SUCCEEDED(rc))
2063 {
2064 if (details == VMINFO_MACHINEREADABLE)
2065 RTPrintf("GuestMemoryBalloon=%d\n", guestVal);
2066 else
2067 RTPrintf("Configured memory balloon size: %d MB\n", guestVal);
2068 }
2069
2070 rc = machine->COMGETTER(StatisticsUpdateInterval)(&guestVal);
2071 if (SUCCEEDED(rc))
2072 {
2073 if (details == VMINFO_MACHINEREADABLE)
2074 RTPrintf("GuestStatisticsUpdateInterval=%d\n", guestVal);
2075 else
2076 {
2077 if (guestVal == 0)
2078 RTPrintf("Statistics update: disabled\n");
2079 else
2080 RTPrintf("Statistics update interval: %d seconds\n", guestVal);
2081 }
2082 }
2083 if (details != VMINFO_MACHINEREADABLE)
2084 RTPrintf("\n");
2085
2086 if ( console
2087 && ( details == VMINFO_STATISTICS
2088 || details == VMINFO_FULL
2089 || details == VMINFO_MACHINEREADABLE))
2090 {
2091 ComPtr <IGuest> guest;
2092
2093 rc = console->COMGETTER(Guest)(guest.asOutParam());
2094 if (SUCCEEDED(rc))
2095 {
2096 ULONG statVal;
2097
2098 rc = guest->GetStatistic(0, GuestStatisticType_SampleNumber, &statVal);
2099 if (details == VMINFO_MACHINEREADABLE)
2100 RTPrintf("StatGuestSample=%d\n", statVal);
2101 else
2102 RTPrintf("Guest statistics for sample %d:\n\n", statVal);
2103
2104 rc = guest->GetStatistic(0, GuestStatisticType_CPULoad_Idle, &statVal);
2105 if (SUCCEEDED(rc))
2106 {
2107 if (details == VMINFO_MACHINEREADABLE)
2108 RTPrintf("StatGuestLoadIdleCPU%d=%d\n", 0, statVal);
2109 else
2110 RTPrintf("CPU%d: CPU Load Idle %-3d%%\n", 0, statVal);
2111 }
2112
2113 rc = guest->GetStatistic(0, GuestStatisticType_CPULoad_Kernel, &statVal);
2114 if (SUCCEEDED(rc))
2115 {
2116 if (details == VMINFO_MACHINEREADABLE)
2117 RTPrintf("StatGuestLoadKernelCPU%d=%d\n", 0, statVal);
2118 else
2119 RTPrintf("CPU%d: CPU Load Kernel %-3d%%\n", 0, statVal);
2120 }
2121
2122 rc = guest->GetStatistic(0, GuestStatisticType_CPULoad_User, &statVal);
2123 if (SUCCEEDED(rc))
2124 {
2125 if (details == VMINFO_MACHINEREADABLE)
2126 RTPrintf("StatGuestLoadUserCPU%d=%d\n", 0, statVal);
2127 else
2128 RTPrintf("CPU%d: CPU Load User %-3d%%\n", 0, statVal);
2129 }
2130
2131 rc = guest->GetStatistic(0, GuestStatisticType_Threads, &statVal);
2132 if (SUCCEEDED(rc))
2133 {
2134 if (details == VMINFO_MACHINEREADABLE)
2135 RTPrintf("StatGuestThreadsCPU%d=%d\n", 0, statVal);
2136 else
2137 RTPrintf("CPU%d: Threads %d\n", 0, statVal);
2138 }
2139
2140 rc = guest->GetStatistic(0, GuestStatisticType_Processes, &statVal);
2141 if (SUCCEEDED(rc))
2142 {
2143 if (details == VMINFO_MACHINEREADABLE)
2144 RTPrintf("StatGuestProcessesCPU%d=%d\n", 0, statVal);
2145 else
2146 RTPrintf("CPU%d: Processes %d\n", 0, statVal);
2147 }
2148
2149 rc = guest->GetStatistic(0, GuestStatisticType_Handles, &statVal);
2150 if (SUCCEEDED(rc))
2151 {
2152 if (details == VMINFO_MACHINEREADABLE)
2153 RTPrintf("StatGuestHandlesCPU%d=%d\n", 0, statVal);
2154 else
2155 RTPrintf("CPU%d: Handles %d\n", 0, statVal);
2156 }
2157
2158 rc = guest->GetStatistic(0, GuestStatisticType_MemoryLoad, &statVal);
2159 if (SUCCEEDED(rc))
2160 {
2161 if (details == VMINFO_MACHINEREADABLE)
2162 RTPrintf("StatGuestMemoryLoadCPU%d=%d\n", 0, statVal);
2163 else
2164 RTPrintf("CPU%d: Memory Load %d%%\n", 0, statVal);
2165 }
2166
2167 rc = guest->GetStatistic(0, GuestStatisticType_PhysMemTotal, &statVal);
2168 if (SUCCEEDED(rc))
2169 {
2170 if (details == VMINFO_MACHINEREADABLE)
2171 RTPrintf("StatGuestMemoryTotalPhysCPU%d=%d\n", 0, statVal);
2172 else
2173 RTPrintf("CPU%d: Total physical memory %-4d MB\n", 0, statVal);
2174 }
2175
2176 rc = guest->GetStatistic(0, GuestStatisticType_PhysMemAvailable, &statVal);
2177 if (SUCCEEDED(rc))
2178 {
2179 if (details == VMINFO_MACHINEREADABLE)
2180 RTPrintf("StatGuestMemoryFreePhysCPU%d=%d\n", 0, statVal);
2181 else
2182 RTPrintf("CPU%d: Free physical memory %-4d MB\n", 0, statVal);
2183 }
2184
2185 rc = guest->GetStatistic(0, GuestStatisticType_PhysMemBalloon, &statVal);
2186 if (SUCCEEDED(rc))
2187 {
2188 if (details == VMINFO_MACHINEREADABLE)
2189 RTPrintf("StatGuestMemoryBalloonCPU%d=%d\n", 0, statVal);
2190 else
2191 RTPrintf("CPU%d: Memory balloon size %-4d MB\n", 0, statVal);
2192 }
2193
2194 rc = guest->GetStatistic(0, GuestStatisticType_MemCommitTotal, &statVal);
2195 if (SUCCEEDED(rc))
2196 {
2197 if (details == VMINFO_MACHINEREADABLE)
2198 RTPrintf("StatGuestMemoryCommittedCPU%d=%d\n", 0, statVal);
2199 else
2200 RTPrintf("CPU%d: Committed memory %-4d MB\n", 0, statVal);
2201 }
2202
2203 rc = guest->GetStatistic(0, GuestStatisticType_MemKernelTotal, &statVal);
2204 if (SUCCEEDED(rc))
2205 {
2206 if (details == VMINFO_MACHINEREADABLE)
2207 RTPrintf("StatGuestMemoryTotalKernelCPU%d=%d\n", 0, statVal);
2208 else
2209 RTPrintf("CPU%d: Total kernel memory %-4d MB\n", 0, statVal);
2210 }
2211
2212 rc = guest->GetStatistic(0, GuestStatisticType_MemKernelPaged, &statVal);
2213 if (SUCCEEDED(rc))
2214 {
2215 if (details == VMINFO_MACHINEREADABLE)
2216 RTPrintf("StatGuestMemoryPagedKernelCPU%d=%d\n", 0, statVal);
2217 else
2218 RTPrintf("CPU%d: Paged kernel memory %-4d MB\n", 0, statVal);
2219 }
2220
2221 rc = guest->GetStatistic(0, GuestStatisticType_MemKernelNonpaged, &statVal);
2222 if (SUCCEEDED(rc))
2223 {
2224 if (details == VMINFO_MACHINEREADABLE)
2225 RTPrintf("StatGuestMemoryNonpagedKernelCPU%d=%d\n", 0, statVal);
2226 else
2227 RTPrintf("CPU%d: Nonpaged kernel memory %-4d MB\n", 0, statVal);
2228 }
2229
2230 rc = guest->GetStatistic(0, GuestStatisticType_MemSystemCache, &statVal);
2231 if (SUCCEEDED(rc))
2232 {
2233 if (details == VMINFO_MACHINEREADABLE)
2234 RTPrintf("StatGuestSystemCacheSizeCPU%d=%d\n", 0, statVal);
2235 else
2236 RTPrintf("CPU%d: System cache size %-4d MB\n", 0, statVal);
2237 }
2238
2239 rc = guest->GetStatistic(0, GuestStatisticType_PageFileSize, &statVal);
2240 if (SUCCEEDED(rc))
2241 {
2242 if (details == VMINFO_MACHINEREADABLE)
2243 RTPrintf("StatGuestPageFileSizeCPU%d=%d\n", 0, statVal);
2244 else
2245 RTPrintf("CPU%d: Page file size %-4d MB\n", 0, statVal);
2246 }
2247
2248 RTPrintf("\n");
2249 }
2250 else
2251 {
2252 if (details != VMINFO_MACHINEREADABLE)
2253 {
2254 RTPrintf("[!] FAILED calling console->getGuest at line %d!\n", __LINE__);
2255 PRINT_RC_MESSAGE(rc);
2256 }
2257 }
2258 }
2259
2260 /*
2261 * snapshots
2262 */
2263 ComPtr<ISnapshot> snapshot;
2264 rc = machine->GetSnapshot(Guid(), snapshot.asOutParam());
2265 if (SUCCEEDED(rc) && snapshot)
2266 {
2267 if (details != VMINFO_MACHINEREADABLE)
2268 RTPrintf("Snapshots:\n\n");
2269 showSnapshots(snapshot, details);
2270 }
2271
2272 if (details != VMINFO_MACHINEREADABLE)
2273 RTPrintf("\n");
2274 return S_OK;
2275}
2276
2277static int handleShowVMInfo(int argc, char *argv[],
2278 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)
2279{
2280 HRESULT rc;
2281
2282 /* at least one option: the UUID or name of the VM */
2283 if (argc < 1)
2284 {
2285 return errorSyntax(USAGE_SHOWVMINFO, "Incorrect number of parameters");
2286 }
2287
2288 /* try to find the given machine */
2289 ComPtr <IMachine> machine;
2290 Guid uuid (argv[0]);
2291 if (!uuid.isEmpty())
2292 {
2293 CHECK_ERROR (virtualBox, GetMachine (uuid, machine.asOutParam()));
2294 }
2295 else
2296 {
2297 CHECK_ERROR (virtualBox, FindMachine (Bstr(argv[0]), machine.asOutParam()));
2298 if (SUCCEEDED (rc))
2299 machine->COMGETTER(Id) (uuid.asOutParam());
2300 }
2301 if (FAILED (rc))
2302 return 1;
2303
2304 /* 2nd option can be -details, -statistics or -argdump */
2305 VMINFO_DETAILS details = VMINFO_NONE;
2306 bool fDetails = false;
2307 bool fStatistics = false;
2308 bool fMachinereadable = false;
2309 for (int i=1;i<argc;i++)
2310 {
2311 if (!strcmp(argv[i], "-details"))
2312 fDetails = true;
2313 else
2314 if (!strcmp(argv[i], "-statistics"))
2315 fStatistics = true;
2316 if (!strcmp(argv[1], "-machinereadable"))
2317 fMachinereadable = true;
2318 }
2319 if (fMachinereadable)
2320 details = VMINFO_MACHINEREADABLE;
2321 else
2322 if (fDetails && fStatistics)
2323 details = VMINFO_FULL;
2324 else
2325 if (fDetails)
2326 details = VMINFO_STANDARD;
2327 else
2328 if (fStatistics)
2329 details = VMINFO_STATISTICS;
2330
2331 ComPtr <IConsole> console;
2332
2333 /* open an existing session for the VM */
2334 rc = virtualBox->OpenExistingSession (session, uuid);
2335 if (SUCCEEDED(rc))
2336 /* get the session machine */
2337 rc = session->COMGETTER(Machine)(machine.asOutParam());
2338 if (SUCCEEDED(rc))
2339 /* get the session console */
2340 rc = session->COMGETTER(Console)(console.asOutParam());
2341
2342 rc = showVMInfo (virtualBox, machine, console, details);
2343
2344 if (console)
2345 session->Close();
2346
2347 return SUCCEEDED (rc) ? 0 : 1;
2348}
2349
2350
2351static int handleList(int argc, char *argv[],
2352 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)
2353{
2354 HRESULT rc = S_OK;
2355
2356 /* exactly one option: the object */
2357 if (argc != 1)
2358 {
2359 return errorSyntax(USAGE_LIST, "Incorrect number of parameters");
2360 }
2361
2362 /* which object? */
2363 if (strcmp(argv[0], "vms") == 0)
2364 {
2365 /*
2366 * Get the list of all registered VMs
2367 */
2368 ComPtr<IMachineCollection> collection;
2369 rc = virtualBox->COMGETTER(Machines)(collection.asOutParam());
2370 ComPtr<IMachineEnumerator> enumerator;
2371 if (SUCCEEDED(rc))
2372 rc = collection->Enumerate(enumerator.asOutParam());
2373 if (SUCCEEDED(rc))
2374 {
2375 /*
2376 * Iterate through the collection
2377 */
2378 BOOL hasMore = FALSE;
2379 while (enumerator->HasMore(&hasMore), hasMore)
2380 {
2381 ComPtr<IMachine> machine;
2382 rc = enumerator->GetNext(machine.asOutParam());
2383 if ((SUCCEEDED(rc)) && machine)
2384 {
2385 rc = showVMInfo(virtualBox, machine);
2386 }
2387 }
2388 }
2389 }
2390 else
2391 if (strcmp(argv[0], "ostypes") == 0)
2392 {
2393 ComPtr<IGuestOSTypeCollection> coll;
2394 ComPtr<IGuestOSTypeEnumerator> enumerator;
2395 CHECK_ERROR(virtualBox, COMGETTER(GuestOSTypes)(coll.asOutParam()));
2396 if (SUCCEEDED(rc) && coll)
2397 {
2398 CHECK_ERROR(coll, Enumerate(enumerator.asOutParam()));
2399 BOOL hasMore;
2400 while (SUCCEEDED(enumerator->HasMore(&hasMore)) && hasMore)
2401 {
2402 ComPtr<IGuestOSType> guestOS;
2403 CHECK_RC_BREAK(enumerator->GetNext(guestOS.asOutParam()));
2404 Bstr guestId;
2405 guestOS->COMGETTER(Id)(guestId.asOutParam());
2406 RTPrintf("ID: %lS\n", guestId.raw());
2407 Bstr guestDescription;
2408 guestOS->COMGETTER(Description)(guestDescription.asOutParam());
2409 RTPrintf("Description: %lS\n\n", guestDescription.raw());
2410 }
2411 }
2412 }
2413 else
2414 if (strcmp(argv[0], "hostdvds") == 0)
2415 {
2416 ComPtr<IHost> host;
2417 CHECK_ERROR(virtualBox, COMGETTER(Host)(host.asOutParam()));
2418 ComPtr<IHostDVDDriveCollection> coll;
2419 ComPtr<IHostDVDDriveEnumerator> enumerator;
2420 CHECK_ERROR(host, COMGETTER(DVDDrives)(coll.asOutParam()));
2421 if (SUCCEEDED(rc) && coll)
2422 {
2423 CHECK_ERROR(coll, Enumerate(enumerator.asOutParam()));
2424 BOOL hasMore;
2425 while (SUCCEEDED(enumerator->HasMore(&hasMore)) && hasMore)
2426 {
2427 ComPtr<IHostDVDDrive> dvdDrive;
2428 CHECK_RC_BREAK(enumerator->GetNext(dvdDrive.asOutParam()));
2429 Bstr name;
2430 dvdDrive->COMGETTER(Name)(name.asOutParam());
2431 RTPrintf("Name: %lS\n\n", name.raw());
2432 }
2433 }
2434 }
2435 else
2436 if (strcmp(argv[0], "hostfloppies") == 0)
2437 {
2438 ComPtr<IHost> host;
2439 CHECK_ERROR(virtualBox, COMGETTER(Host)(host.asOutParam()));
2440 ComPtr<IHostFloppyDriveCollection> coll;
2441 ComPtr<IHostFloppyDriveEnumerator> enumerator;
2442 CHECK_ERROR(host, COMGETTER(FloppyDrives)(coll.asOutParam()));
2443 if (SUCCEEDED(rc) && coll)
2444 {
2445 CHECK_ERROR(coll, Enumerate(enumerator.asOutParam()));
2446 BOOL hasMore;
2447 while (SUCCEEDED(enumerator->HasMore(&hasMore)) && hasMore)
2448 {
2449 ComPtr<IHostFloppyDrive> floppyDrive;
2450 CHECK_RC_BREAK(enumerator->GetNext(floppyDrive.asOutParam()));
2451 Bstr name;
2452 floppyDrive->COMGETTER(Name)(name.asOutParam());
2453 RTPrintf("Name: %lS\n\n", name.raw());
2454 }
2455 }
2456 }
2457#ifdef RT_OS_WINDOWS
2458 else
2459 if (strcmp(argv[0], "hostifs") == 0)
2460 {
2461 ComPtr<IHost> host;
2462 CHECK_ERROR(virtualBox, COMGETTER(Host)(host.asOutParam()));
2463 ComPtr<IHostNetworkInterfaceCollection> coll;
2464 ComPtr<IHostNetworkInterfaceEnumerator> enumerator;
2465 CHECK_ERROR(host, COMGETTER(NetworkInterfaces)(coll.asOutParam()));
2466 if (SUCCEEDED(rc) && coll)
2467 {
2468 CHECK_ERROR(coll, Enumerate(enumerator.asOutParam()));
2469 BOOL hasMore;
2470 while (SUCCEEDED(enumerator->HasMore(&hasMore)) && hasMore)
2471 {
2472 ComPtr<IHostNetworkInterface> networkInterface;
2473 CHECK_RC_BREAK(enumerator->GetNext(networkInterface.asOutParam()));
2474 Bstr interfaceName;
2475 networkInterface->COMGETTER(Name)(interfaceName.asOutParam());
2476 RTPrintf("Name: %lS\n", interfaceName.raw());
2477 Guid interfaceGuid;
2478 networkInterface->COMGETTER(Id)(interfaceGuid.asOutParam());
2479 RTPrintf("GUID: %lS\n\n", Bstr(interfaceGuid.toString()));
2480 }
2481 }
2482 }
2483#endif /* RT_OS_WINDOWS */
2484 else
2485 if (strcmp(argv[0], "hdds") == 0)
2486 {
2487 ComPtr<IHardDiskCollection> hddColl;
2488 CHECK_ERROR(virtualBox, COMGETTER(HardDisks)(hddColl.asOutParam()));
2489 ComPtr<IHardDiskEnumerator> enumerator;
2490 CHECK_ERROR(hddColl, Enumerate(enumerator.asOutParam()));
2491 BOOL hasMore;
2492 while (SUCCEEDED(enumerator->HasMore(&hasMore)) && hasMore)
2493 {
2494 ComPtr<IHardDisk> hdd;
2495 CHECK_RC_BREAK(enumerator->GetNext(hdd.asOutParam()));
2496 Guid uuid;
2497 hdd->COMGETTER(Id)(uuid.asOutParam());
2498 RTPrintf("UUID: %s\n", uuid.toString().raw());
2499 HardDiskStorageType_T storageType;
2500 hdd->COMGETTER(StorageType)(&storageType);
2501 const char *storageTypeString = "unknown";
2502 switch (storageType)
2503 {
2504 case HardDiskStorageType_VirtualDiskImage:
2505 storageTypeString = "Virtual Disk Image";
2506 break;
2507 case HardDiskStorageType_ISCSIHardDisk:
2508 storageTypeString = "iSCSI hard disk";
2509 break;
2510 }
2511 RTPrintf("Storage type: %s\n", storageTypeString);
2512 Bstr filepath;
2513 /// @todo (dmik) we temporarily use the location property to
2514 // determine the image file name. This is subject to change
2515 // when iSCSI disks are here (we should either query a
2516 // storage-specific interface from IHardDisk, or "standardize"
2517 // the location property)
2518 hdd->COMGETTER(Location)(filepath.asOutParam());
2519 RTPrintf("Path: %lS\n", filepath.raw());
2520 BOOL fAccessible;
2521 hdd->COMGETTER(AllAccessible)(&fAccessible);
2522 RTPrintf("Accessible: %s\n", fAccessible ? "yes" : "no");
2523 Guid machineUUID;
2524 hdd->COMGETTER(MachineId)(machineUUID.asOutParam());
2525 if (!machineUUID.isEmpty())
2526 {
2527 ComPtr<IMachine> machine;
2528 CHECK_ERROR(virtualBox, GetMachine(machineUUID, machine.asOutParam()));
2529 ASSERT(machine);
2530 Bstr name;
2531 machine->COMGETTER(Name)(name.asOutParam());
2532 machine->COMGETTER(Id)(uuid.asOutParam());
2533 RTPrintf("Usage: %lS (UUID: %s)\n", name.raw(), uuid.toString().raw());
2534 }
2535 RTPrintf("\n");
2536 }
2537 }
2538 else
2539 if (strcmp(argv[0], "dvds") == 0)
2540 {
2541 ComPtr<IDVDImageCollection> dvdColl;
2542 CHECK_ERROR(virtualBox, COMGETTER(DVDImages)(dvdColl.asOutParam()));
2543 ComPtr<IDVDImageEnumerator> enumerator;
2544 CHECK_ERROR(dvdColl, Enumerate(enumerator.asOutParam()));
2545 BOOL hasMore;
2546 while (SUCCEEDED(enumerator->HasMore(&hasMore)) && hasMore)
2547 {
2548 ComPtr<IDVDImage> dvdImage;
2549 CHECK_RC_BREAK(enumerator->GetNext(dvdImage.asOutParam()));
2550 Guid uuid;
2551 dvdImage->COMGETTER(Id)(uuid.asOutParam());
2552 RTPrintf("UUID: %s\n", uuid.toString().raw());
2553 Bstr filePath;
2554 dvdImage->COMGETTER(FilePath)(filePath.asOutParam());
2555 RTPrintf("Path: %lS\n", filePath.raw());
2556 BOOL fAccessible;
2557 dvdImage->COMGETTER(Accessible)(&fAccessible);
2558 RTPrintf("Accessible: %s\n", fAccessible ? "yes" : "no");
2559 Bstr machineUUIDs;
2560 CHECK_ERROR(virtualBox, GetDVDImageUsage(uuid, ResourceUsage_AllUsage, machineUUIDs.asOutParam()));
2561 /** @todo usage */
2562 RTPrintf("\n");
2563 }
2564 }
2565 else
2566 if (strcmp(argv[0], "floppies") == 0)
2567 {
2568 ComPtr<IFloppyImageCollection> floppyColl;
2569 CHECK_ERROR(virtualBox, COMGETTER(FloppyImages)(floppyColl.asOutParam()));
2570 ComPtr<IFloppyImageEnumerator> enumerator;
2571 CHECK_ERROR(floppyColl, Enumerate(enumerator.asOutParam()));
2572 BOOL hasMore;
2573 while (SUCCEEDED(enumerator->HasMore(&hasMore)) && hasMore)
2574 {
2575 ComPtr<IFloppyImage> floppyImage;
2576 CHECK_RC_BREAK(enumerator->GetNext(floppyImage.asOutParam()));
2577 Guid uuid;
2578 floppyImage->COMGETTER(Id)(uuid.asOutParam());
2579 RTPrintf("UUID: %s\n", uuid.toString().raw());
2580 Bstr filePath;
2581 floppyImage->COMGETTER(FilePath)(filePath.asOutParam());
2582 RTPrintf("Path: %lS\n", filePath.raw());
2583 BOOL fAccessible;
2584 floppyImage->COMGETTER(Accessible)(&fAccessible);
2585 RTPrintf("Accessible: %s\n", fAccessible ? "yes" : "no");
2586 Bstr machineUUIDs;
2587 CHECK_ERROR(virtualBox, GetFloppyImageUsage(uuid, ResourceUsage_AllUsage, machineUUIDs.asOutParam()));
2588 /** @todo usage */
2589 RTPrintf("\n");
2590 }
2591 }
2592 else
2593 if (strcmp(argv[0], "usbhost") == 0)
2594 {
2595 ComPtr<IHost> Host;
2596 CHECK_ERROR_RET (virtualBox, COMGETTER(Host)(Host.asOutParam()), 1);
2597
2598 ComPtr<IHostUSBDeviceCollection> CollPtr;
2599 CHECK_ERROR_RET (Host, COMGETTER(USBDevices)(CollPtr.asOutParam()), 1);
2600
2601 ComPtr<IHostUSBDeviceEnumerator> EnumPtr;
2602 CHECK_ERROR_RET (CollPtr, Enumerate(EnumPtr.asOutParam()), 1);
2603
2604 RTPrintf("Host USB Devices:\n\n");
2605
2606 BOOL fMore = FALSE;
2607 rc = EnumPtr->HasMore (&fMore);
2608 ASSERT_RET (SUCCEEDED (rc), 1);
2609
2610 if (!fMore)
2611 {
2612 RTPrintf("<none>\n\n");
2613 }
2614 else
2615 while (fMore)
2616 {
2617 ComPtr <IHostUSBDevice> dev;
2618 rc = EnumPtr->GetNext (dev.asOutParam());
2619 ASSERT_RET (SUCCEEDED (rc), 1);
2620
2621 /* Query info. */
2622 Guid id;
2623 CHECK_ERROR_RET (dev, COMGETTER(Id)(id.asOutParam()), 1);
2624 USHORT usVendorId;
2625 CHECK_ERROR_RET (dev, COMGETTER(VendorId)(&usVendorId), 1);
2626 USHORT usProductId;
2627 CHECK_ERROR_RET (dev, COMGETTER(ProductId)(&usProductId), 1);
2628 USHORT bcdRevision;
2629 CHECK_ERROR_RET (dev, COMGETTER(Revision)(&bcdRevision), 1);
2630
2631 RTPrintf("UUID: %S\n"
2632 "VendorId: 0x%04x (%04X)\n"
2633 "ProductId: 0x%04x (%04X)\n"
2634 "Revision: %u.%u (%02u%02u)\n",
2635 id.toString().raw(),
2636 usVendorId, usVendorId, usProductId, usProductId,
2637 bcdRevision >> 8, bcdRevision & 0xff,
2638 bcdRevision >> 8, bcdRevision & 0xff);
2639
2640 /* optional stuff. */
2641 Bstr bstr;
2642 CHECK_ERROR_RET (dev, COMGETTER(Manufacturer)(bstr.asOutParam()), 1);
2643 if (!bstr.isEmpty())
2644 RTPrintf("Manufacturer: %lS\n", bstr.raw());
2645 CHECK_ERROR_RET (dev, COMGETTER(Product)(bstr.asOutParam()), 1);
2646 if (!bstr.isEmpty())
2647 RTPrintf("Product: %lS\n", bstr.raw());
2648 CHECK_ERROR_RET (dev, COMGETTER(SerialNumber)(bstr.asOutParam()), 1);
2649 if (!bstr.isEmpty())
2650 RTPrintf("SerialNumber: %lS\n", bstr.raw());
2651 CHECK_ERROR_RET (dev, COMGETTER(Address)(bstr.asOutParam()), 1);
2652 if (!bstr.isEmpty())
2653 RTPrintf("Address: %lS\n", bstr.raw());
2654
2655 /* current state */
2656 USBDeviceState_T state;
2657 CHECK_ERROR_RET (dev, COMGETTER(State)(&state), 1);
2658 const char *pszState = "?";
2659 switch (state)
2660 {
2661 case USBDeviceState_USBDeviceNotSupported:
2662 pszState = "Not supported"; break;
2663 case USBDeviceState_USBDeviceUnavailable:
2664 pszState = "Unavailable"; break;
2665 case USBDeviceState_USBDeviceBusy:
2666 pszState = "Busy"; break;
2667 case USBDeviceState_USBDeviceAvailable:
2668 pszState = "Available"; break;
2669 case USBDeviceState_USBDeviceHeld:
2670 pszState = "Held"; break;
2671 case USBDeviceState_USBDeviceCaptured:
2672 pszState = "Captured"; break;
2673 default:
2674 ASSERT (false);
2675 break;
2676 }
2677 RTPrintf("Current State: %s\n\n", pszState);
2678
2679 rc = EnumPtr->HasMore (&fMore);
2680 ASSERT_RET (SUCCEEDED (rc), rc);
2681 }
2682 }
2683 else
2684 if (strcmp(argv[0], "usbfilters") == 0)
2685 {
2686 RTPrintf("Global USB Device Filters:\n\n");
2687
2688 ComPtr <IHost> host;
2689 CHECK_ERROR_RET (virtualBox, COMGETTER(Host) (host.asOutParam()), 1);
2690
2691 ComPtr<IHostUSBDeviceFilterCollection> coll;
2692 CHECK_ERROR_RET (host, COMGETTER (USBDeviceFilters)(coll.asOutParam()), 1);
2693
2694 ComPtr<IHostUSBDeviceFilterEnumerator> en;
2695 CHECK_ERROR_RET (coll, Enumerate(en.asOutParam()), 1);
2696
2697 ULONG index = 0;
2698 BOOL more = FALSE;
2699 rc = en->HasMore (&more);
2700 ASSERT_RET (SUCCEEDED (rc), 1);
2701
2702 if (!more)
2703 {
2704 RTPrintf("<none>\n\n");
2705 }
2706 else
2707 while (more)
2708 {
2709 ComPtr<IHostUSBDeviceFilter> flt;
2710 rc = en->GetNext (flt.asOutParam());
2711 ASSERT_RET (SUCCEEDED (rc), 1);
2712
2713 /* Query info. */
2714
2715 RTPrintf("Index: %lu\n", index);
2716
2717 BOOL active = FALSE;
2718 CHECK_ERROR_RET (flt, COMGETTER (Active) (&active), 1);
2719 RTPrintf("Active: %s\n", active ? "yes" : "no");
2720
2721 USBDeviceFilterAction_T action;
2722 CHECK_ERROR_RET (flt, COMGETTER (Action) (&action), 1);
2723 const char *pszAction = "<invalid>";
2724 switch (action)
2725 {
2726 case USBDeviceFilterAction_USBDeviceFilterIgnore:
2727 pszAction = "Ignore";
2728 break;
2729 case USBDeviceFilterAction_USBDeviceFilterHold:
2730 pszAction = "Hold";
2731 break;
2732 default:
2733 break;
2734 }
2735 RTPrintf("Action: %s\n", pszAction);
2736
2737 Bstr bstr;
2738 CHECK_ERROR_RET (flt, COMGETTER (Name) (bstr.asOutParam()), 1);
2739 RTPrintf("Name: %lS\n", bstr.raw());
2740 CHECK_ERROR_RET (flt, COMGETTER (VendorId) (bstr.asOutParam()), 1);
2741 RTPrintf("VendorId: %lS\n", bstr.raw());
2742 CHECK_ERROR_RET (flt, COMGETTER (ProductId) (bstr.asOutParam()), 1);
2743 RTPrintf("ProductId: %lS\n", bstr.raw());
2744 CHECK_ERROR_RET (flt, COMGETTER (Revision) (bstr.asOutParam()), 1);
2745 RTPrintf("Revision: %lS\n", bstr.raw());
2746 CHECK_ERROR_RET (flt, COMGETTER (Manufacturer) (bstr.asOutParam()), 1);
2747 RTPrintf("Manufacturer: %lS\n", bstr.raw());
2748 CHECK_ERROR_RET (flt, COMGETTER (Product) (bstr.asOutParam()), 1);
2749 RTPrintf("Product: %lS\n", bstr.raw());
2750 CHECK_ERROR_RET (flt, COMGETTER (SerialNumber) (bstr.asOutParam()), 1);
2751 RTPrintf("Serial Number: %lS\n\n", bstr.raw());
2752
2753 rc = en->HasMore (&more);
2754 ASSERT_RET (SUCCEEDED (rc), 1);
2755
2756 index ++;
2757 }
2758 }
2759 else if (strcmp(argv[0], "systemproperties") == 0)
2760 {
2761 ComPtr<ISystemProperties> systemProperties;
2762 virtualBox->COMGETTER(SystemProperties)(systemProperties.asOutParam());
2763
2764 Bstr str;
2765 ULONG ulValue;
2766 ULONG64 ul64Value;
2767 BOOL flag;
2768
2769 systemProperties->COMGETTER(MinGuestRAM)(&ulValue);
2770 RTPrintf("Minimum guest RAM size: %u Megabytes\n", ulValue);
2771 systemProperties->COMGETTER(MaxGuestRAM)(&ulValue);
2772 RTPrintf("Maximum guest RAM size: %u Megabytes\n", ulValue);
2773 systemProperties->COMGETTER(MaxGuestVRAM)(&ulValue);
2774 RTPrintf("Maximum video RAM size: %u Megabytes\n", ulValue);
2775 systemProperties->COMGETTER(MaxVDISize)(&ul64Value);
2776 RTPrintf("Maximum VDI size: %lu Megabytes\n", ul64Value);
2777 systemProperties->COMGETTER(DefaultVDIFolder)(str.asOutParam());
2778 RTPrintf("Default VDI filder: %lS\n", str.raw());
2779 systemProperties->COMGETTER(DefaultMachineFolder)(str.asOutParam());
2780 RTPrintf("Default machine folder: %lS\n", str.raw());
2781 systemProperties->COMGETTER(RemoteDisplayAuthLibrary)(str.asOutParam());
2782 RTPrintf("VRDP authentication library: %lS\n", str.raw());
2783 systemProperties->COMGETTER(HWVirtExEnabled)(&flag);
2784 RTPrintf("Hardware virt. extensions: %s\n", flag ? "yes" : "no");
2785
2786 }
2787 else
2788 {
2789 return errorSyntax(USAGE_LIST, "Invalid parameter '%s'", Utf8Str(argv[0]).raw());
2790 }
2791 return SUCCEEDED(rc) ? 0 : 1;
2792}
2793
2794static int handleRegisterVM(int argc, char *argv[],
2795 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)
2796{
2797 HRESULT rc;
2798
2799 if (argc != 1)
2800 {
2801 return errorSyntax(USAGE_REGISTERVM, "Incorrect number of parameters");
2802 }
2803
2804 ComPtr<IMachine> machine;
2805 CHECK_ERROR(virtualBox, OpenMachine(Bstr(argv[0]), machine.asOutParam()));
2806 if (SUCCEEDED(rc))
2807 {
2808 ASSERT(machine);
2809 CHECK_ERROR(virtualBox, RegisterMachine(machine));
2810 }
2811 return SUCCEEDED(rc) ? 0 : 1;
2812}
2813
2814static int handleUnregisterVM(int argc, char *argv[],
2815 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)
2816{
2817 HRESULT rc;
2818
2819 if ((argc != 1) && (argc != 2))
2820 {
2821 return errorSyntax(USAGE_UNREGISTERVM, "Incorrect number of parameters");
2822 }
2823
2824 ComPtr<IMachine> machine;
2825 /* assume it's a UUID */
2826 rc = virtualBox->GetMachine(Guid(argv[0]), machine.asOutParam());
2827 if (FAILED(rc) || !machine)
2828 {
2829 /* must be a name */
2830 CHECK_ERROR(virtualBox, FindMachine(Bstr(argv[0]), machine.asOutParam()));
2831 }
2832 if (machine)
2833 {
2834 Guid uuid;
2835 machine->COMGETTER(Id)(uuid.asOutParam());
2836 machine = NULL;
2837 CHECK_ERROR(virtualBox, UnregisterMachine(uuid, machine.asOutParam()));
2838 if (SUCCEEDED(rc) && machine)
2839 {
2840 /* are we supposed to delete the config file? */
2841 if ((argc == 2) && (strcmp(argv[1], "-delete") == 0))
2842 {
2843 CHECK_ERROR(machine, DeleteSettings());
2844 }
2845 }
2846 }
2847 return SUCCEEDED(rc) ? 0 : 1;
2848}
2849
2850static int handleCreateVDI(int argc, char *argv[],
2851 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)
2852{
2853 HRESULT rc;
2854 Bstr filename;
2855 uint64_t sizeMB = 0;
2856 bool fStatic = false;
2857 Bstr comment;
2858 bool fRegister = false;
2859 const char *type = "normal";
2860
2861 /* let's have a closer look at the arguments */
2862 for (int i = 0; i < argc; i++)
2863 {
2864 if (strcmp(argv[i], "-filename") == 0)
2865 {
2866 if (argc <= i + 1)
2867 {
2868 return errorArgument("Missing argument to '%s'", argv[i]);
2869 }
2870 i++;
2871 filename = argv[i];
2872 }
2873 else if (strcmp(argv[i], "-size") == 0)
2874 {
2875 if (argc <= i + 1)
2876 {
2877 return errorArgument("Missing argument to '%s'", argv[i]);
2878 }
2879 i++;
2880 sizeMB = RTStrToUInt64(argv[i]);
2881 }
2882 else if (strcmp(argv[i], "-static") == 0)
2883 {
2884 fStatic = true;
2885 }
2886 else if (strcmp(argv[i], "-comment") == 0)
2887 {
2888 if (argc <= i + 1)
2889 {
2890 return errorArgument("Missing argument to '%s'", argv[i]);
2891 }
2892 i++;
2893 comment = argv[i];
2894 }
2895 else if (strcmp(argv[i], "-register") == 0)
2896 {
2897 fRegister = true;
2898 }
2899 else if (strcmp(argv[i], "-type") == 0)
2900 {
2901 if (argc <= i + 1)
2902 {
2903 return errorArgument("Missing argument to '%s'", argv[i]);
2904 }
2905 i++;
2906 type = argv[i];
2907 }
2908 else
2909 {
2910 return errorSyntax(USAGE_CREATEVDI, "Invalid parameter '%s'", Utf8Str(argv[i]).raw());
2911 }
2912 }
2913 /* check the outcome */
2914 if (!filename || (sizeMB == 0))
2915 {
2916 return errorSyntax(USAGE_CREATEVDI, "Parameters -filename and -size are required");
2917 }
2918 if (strcmp(type, "normal") && strcmp(type, "writethrough"))
2919 {
2920 return errorArgument("Invalid VDI type '%s' specified", Utf8Str(type).raw());
2921 }
2922
2923 ComPtr<IHardDisk> hardDisk;
2924 CHECK_ERROR(virtualBox, CreateHardDisk(HardDiskStorageType_VirtualDiskImage, hardDisk.asOutParam()));
2925 if (SUCCEEDED(rc) && hardDisk)
2926 {
2927 CHECK_ERROR(hardDisk,COMSETTER(Description)(comment));
2928 ComPtr<IVirtualDiskImage> vdi = hardDisk;
2929 CHECK_ERROR(vdi, COMSETTER(FilePath)(filename));
2930 ComPtr<IProgress> progress;
2931 if (fStatic)
2932 {
2933 CHECK_ERROR(vdi, CreateFixedImage(sizeMB, progress.asOutParam()));
2934 }
2935 else
2936 {
2937 CHECK_ERROR(vdi, CreateDynamicImage(sizeMB, progress.asOutParam()));
2938 }
2939 if (SUCCEEDED(rc) && progress)
2940 {
2941 CHECK_ERROR(progress, WaitForCompletion(-1));
2942 if (SUCCEEDED(rc))
2943 {
2944 progress->COMGETTER(ResultCode)(&rc);
2945 if (FAILED(rc))
2946 {
2947 com::ProgressErrorInfo info(progress);
2948 if (info.isBasicAvailable())
2949 {
2950 RTPrintf("Error: failed to create disk image. Error message: %lS\n", info.getText().raw());
2951 }
2952 else
2953 {
2954 RTPrintf("Error: failed to create disk image. No error message available!\n");
2955 }
2956 }
2957 else
2958 {
2959 Guid uuid;
2960 CHECK_ERROR(hardDisk, COMGETTER(Id)(uuid.asOutParam()));
2961
2962 if (strcmp(type, "normal") == 0)
2963 {
2964 /* nothing required, default */
2965 }
2966 else if (strcmp(type, "writethrough") == 0)
2967 {
2968 CHECK_ERROR(hardDisk, COMSETTER(Type)(HardDiskType_WritethroughHardDisk));
2969 }
2970
2971 RTPrintf("Disk image created. UUID: %s\n", uuid.toString().raw());
2972 }
2973 }
2974 }
2975 if (SUCCEEDED(rc) && fRegister)
2976 {
2977 CHECK_ERROR(virtualBox, RegisterHardDisk(hardDisk));
2978 }
2979 }
2980 return SUCCEEDED(rc) ? 0 : 1;
2981}
2982
2983static DECLCALLBACK(int) vdiProgressCallback(PVM pVM, unsigned uPercent, void *pvUser)
2984{
2985 unsigned *pPercent = (unsigned *)pvUser;
2986
2987 if (*pPercent != uPercent)
2988 {
2989 *pPercent = uPercent;
2990 RTPrintf(".");
2991 if ((uPercent % 10) == 0 && uPercent)
2992 RTPrintf("%d%%", uPercent);
2993 RTStrmFlush(g_pStdOut);
2994 }
2995
2996 return VINF_SUCCESS;
2997}
2998
2999
3000static int handleModifyVDI(int argc, char *argv[],
3001 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)
3002{
3003 HRESULT rc;
3004
3005 /* The uuid/filename and a command */
3006 if (argc < 2)
3007 {
3008 return errorSyntax(USAGE_MODIFYVDI, "Incorrect number of parameters");
3009 }
3010
3011 ComPtr<IHardDisk> hardDisk;
3012 ComPtr<IVirtualDiskImage> vdi;
3013 Bstr filepath;
3014
3015 /* first guess is that it's a UUID */
3016 Guid uuid(argv[0]);
3017 rc = virtualBox->GetHardDisk(uuid, hardDisk.asOutParam());
3018 /* no? then it must be a filename */
3019 if (!hardDisk)
3020 {
3021 filepath = argv[0];
3022 CHECK_ERROR(virtualBox, FindVirtualDiskImage(filepath, vdi.asOutParam()));
3023 hardDisk = vdi;
3024 }
3025 else
3026 {
3027 vdi = hardDisk;
3028 }
3029
3030 /* let's find out which command */
3031// doesn't currently work if (strcmp(argv[1], "settype") == 0)
3032 if (0)
3033 {
3034 /* hard disk must be registered */
3035 if (SUCCEEDED(rc) && hardDisk && vdi)
3036 {
3037 char *type = NULL;
3038
3039 if (argc <= 2)
3040 {
3041 return errorArgument("Missing argument to for settype");
3042 }
3043 type = argv[2];
3044
3045 HardDiskType_T hddType;
3046 CHECK_ERROR(hardDisk, COMGETTER(Type)(&hddType));
3047
3048 if (strcmp(type, "normal") == 0)
3049 {
3050 if (hddType != HardDiskType_NormalHardDisk)
3051 CHECK_ERROR(hardDisk, COMSETTER(Type)(HardDiskType_NormalHardDisk));
3052 }
3053 else if (strcmp(type, "writethrough") == 0)
3054 {
3055 if (hddType != HardDiskType_WritethroughHardDisk)
3056 CHECK_ERROR(hardDisk, COMSETTER(Type)(HardDiskType_WritethroughHardDisk));
3057
3058 }
3059 else if (strcmp(type, "immutable") == 0)
3060 {
3061 if (hddType != HardDiskType_ImmutableHardDisk)
3062 CHECK_ERROR(hardDisk, COMSETTER(Type)(HardDiskType_ImmutableHardDisk));
3063 }
3064 else
3065 {
3066 return errorArgument("Invalid VDI type '%s' specified", Utf8Str(type).raw());
3067 }
3068 }
3069 else
3070 {
3071 return errorArgument("Hard disk image not registered");
3072 }
3073 }
3074 else if (strcmp(argv[1], "compact") == 0)
3075 {
3076 ComPtr<IVirtualDiskImage> vdi;
3077
3078 /* the hard disk image might not be registered */
3079 if (!hardDisk)
3080 {
3081 virtualBox->OpenVirtualDiskImage(Bstr(argv[0]), vdi.asOutParam());
3082 if (!vdi)
3083 {
3084 return errorArgument("Hard disk image not found");
3085 }
3086 }
3087 else
3088 vdi = hardDisk;
3089
3090 if (!vdi)
3091 return errorArgument("Invalid hard disk type. The command only works on VDI files\n");
3092
3093 Bstr fileName;
3094 vdi->COMGETTER(FilePath)(fileName.asOutParam());
3095
3096 /* close the file */
3097 hardDisk = NULL;
3098 vdi = NULL;
3099
3100 unsigned uProcent;
3101
3102 RTPrintf("Shrinking '%lS': 0%%", fileName.raw());
3103 int vrc = VDIShrinkImage(Utf8Str(fileName).raw(), vdiProgressCallback, &uProcent);
3104 if (VBOX_FAILURE(vrc))
3105 {
3106 RTPrintf("Error while shrinking hard disk image: %Vrc\n", vrc);
3107 rc = E_FAIL;
3108 }
3109 }
3110 else
3111 {
3112 return errorSyntax(USAGE_MODIFYVDI, "Invalid parameter '%s'", Utf8Str(argv[1]).raw());
3113 }
3114 return SUCCEEDED(rc) ? 0 : 1;
3115}
3116
3117static int handleCloneVDI(int argc, char *argv[],
3118 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)
3119{
3120 HRESULT rc;
3121
3122 /* source VDI and target path */
3123 if (argc != 2)
3124 {
3125 return errorSyntax(USAGE_CLONEVDI, "Incorrect number of parameters");
3126 }
3127
3128 /* first guess is that it's a UUID */
3129 Guid uuid(argv[0]);
3130 ComPtr<IHardDisk> hardDisk;
3131 rc = virtualBox->GetHardDisk(uuid, hardDisk.asOutParam());
3132 if (!hardDisk)
3133 {
3134 /* not successful? Then it must be a filename */
3135 ComPtr<IVirtualDiskImage> vdi;
3136 CHECK_ERROR(virtualBox, OpenVirtualDiskImage(Bstr(argv[0]), vdi.asOutParam()));
3137 hardDisk = vdi;
3138 }
3139 if (hardDisk)
3140 {
3141 ComPtr<IVirtualDiskImage> vdiOut;
3142 ComPtr<IProgress> progress;
3143 CHECK_ERROR(hardDisk, CloneToImage(Bstr(argv[1]), vdiOut.asOutParam(), progress.asOutParam()));
3144 if (SUCCEEDED(rc))
3145 {
3146 showProgress(progress);
3147 progress->COMGETTER(ResultCode)(&rc);
3148 if (FAILED(rc))
3149 {
3150 com::ProgressErrorInfo info(progress);
3151 if (info.isBasicAvailable())
3152 {
3153 RTPrintf("Error: failed to clone disk image. Error message: %lS\n", info.getText().raw());
3154 }
3155 else
3156 {
3157 RTPrintf("Error: failed to clone disk image. No error message available!\n");
3158 }
3159 }
3160 }
3161 }
3162 return SUCCEEDED(rc) ? 0 : 1;
3163}
3164
3165static int handleConvertDDImage(int argc, char *argv[])
3166{
3167#ifdef RT_OS_LINUX
3168 const bool fReadFromStdIn = (argc >= 1) && !strcmp(argv[0], "stdin");
3169#else
3170 const bool fReadFromStdIn = false;
3171#endif
3172
3173 if ((!fReadFromStdIn && argc != 2) || (fReadFromStdIn && argc != 3))
3174 return errorSyntax(USAGE_CONVERTDD, "Incorrect number of parameters");
3175
3176 RTPrintf("Converting VDI: from DD image file=\"%s\" to file=\"%s\"...\n",
3177 argv[0], argv[1]);
3178
3179 /* open raw image file. */
3180 RTFILE File;
3181 int rc = VINF_SUCCESS;
3182 if (fReadFromStdIn)
3183 File = 0;
3184 else
3185 rc = RTFileOpen(&File, argv[0], RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE);
3186 if (VBOX_FAILURE(rc))
3187 {
3188 RTPrintf("File=\"%s\" open error: %Rrf\n", argv[0], rc);
3189 return rc;
3190 }
3191
3192 uint64_t cbFile;
3193 /* get image size. */
3194 if (fReadFromStdIn)
3195 cbFile = RTStrToUInt64(argv[2]);
3196 else
3197 rc = RTFileGetSize(File, &cbFile);
3198 if (VBOX_SUCCESS(rc))
3199 {
3200 RTPrintf("Creating fixed image with size %RU64Bytes (%RU64MB)...\n", cbFile, (cbFile + _1M - 1) / _1M);
3201 char pszComment[256];
3202 RTStrPrintf(pszComment, sizeof(pszComment), "Converted image from %s", argv[0]);
3203 rc = VDICreateBaseImage(argv[1],
3204 VDI_IMAGE_TYPE_FIXED,
3205 cbFile,
3206 pszComment, NULL, NULL);
3207 if (VBOX_SUCCESS(rc))
3208 {
3209 PVDIDISK pVdi = VDIDiskCreate();
3210 rc = VDIDiskOpenImage(pVdi, argv[1], VDI_OPEN_FLAGS_NORMAL);
3211 if (VBOX_SUCCESS(rc))
3212 {
3213 /* alloc work buffer. */
3214 void *pvBuf = RTMemAlloc(VDIDiskGetBufferSize(pVdi));
3215 if (pvBuf)
3216 {
3217 uint64_t off = 0;
3218 while (off < cbFile)
3219 {
3220 size_t cbRead = 0;
3221 rc = RTFileRead(File, pvBuf, VDIDiskGetBufferSize(pVdi), &cbRead);
3222 if (VBOX_FAILURE(rc) || !cbRead)
3223 break;
3224 rc = VDIDiskWrite(pVdi, off, pvBuf, cbRead);
3225 if (VBOX_FAILURE(rc))
3226 break;
3227 off += cbRead;
3228 }
3229
3230 RTMemFree(pvBuf);
3231 }
3232 else
3233 rc = VERR_NO_MEMORY;
3234
3235 VDIDiskCloseImage(pVdi);
3236 }
3237
3238 if (VBOX_FAILURE(rc))
3239 {
3240 /* delete image on error */
3241 RTPrintf("Failed (%Vrc)!\n", rc);
3242 VDIDeleteImage(argv[1]);
3243 }
3244 }
3245 else
3246 RTPrintf("Failed to create output file (%Vrc)!\n", rc);
3247 }
3248 RTFileClose(File);
3249
3250 return rc;
3251}
3252
3253static int handleAddiSCSIDisk(int argc, char *argv[],
3254 ComPtr <IVirtualBox> aVirtualBox, ComPtr<ISession> aSession)
3255{
3256 HRESULT rc;
3257 Bstr server;
3258 Bstr target;
3259 uint16_t port = UINT16_MAX;
3260 uint64_t lun = UINT64_MAX;
3261 Bstr username;
3262 Bstr password;
3263 Bstr comment;
3264
3265 /* at least server and target */
3266 if (argc < 4)
3267 {
3268 return errorSyntax(USAGE_ADDISCSIDISK, "Not enough parameters");
3269 }
3270
3271 /* let's have a closer look at the arguments */
3272 for (int i = 0; i < argc; i++)
3273 {
3274 if (strcmp(argv[i], "-server") == 0)
3275 {
3276 if (argc <= i + 1)
3277 {
3278 return errorArgument("Missing argument to '%s'", argv[i]);
3279 }
3280 i++;
3281 server = argv[i];
3282 }
3283 else if (strcmp(argv[i], "-target") == 0)
3284 {
3285 if (argc <= i + 1)
3286 {
3287 return errorArgument("Missing argument to '%s'", argv[i]);
3288 }
3289 i++;
3290 target = argv[i];
3291 }
3292 else if (strcmp(argv[i], "-port") == 0)
3293 {
3294 if (argc <= i + 1)
3295 {
3296 return errorArgument("Missing argument to '%s'", argv[i]);
3297 }
3298 i++;
3299 port = atoi(argv[i]);
3300 }
3301 else if (strcmp(argv[i], "-lun") == 0)
3302 {
3303 /** @todo move the LUN encoding algorithm into IISCSIHardDisk, add decoding */
3304 if (argc <= i + 1)
3305 {
3306 return errorArgument("Missing argument to '%s'", argv[i]);
3307 }
3308 i++;
3309 char *pszNext;
3310 int rc = RTStrToUInt64Ex(argv[i], &pszNext, 0, &lun);
3311 if (VBOX_FAILURE(rc) || *pszNext != '\0' || lun >= 16384)
3312 return errorArgument("Invalid LUN number '%s'", argv[i]);
3313 if (lun <= 255)
3314 {
3315 /* Assume bus identifier = 0. */
3316 lun = (lun << 48); /* uses peripheral device addressing method */
3317 }
3318 else
3319 {
3320 /* Check above already limited the LUN to 14 bits. */
3321 lun = (lun << 48) | RT_BIT_64(62); /* uses flat space addressing method */
3322 }
3323 }
3324 else if (strcmp(argv[i], "-encodedlun") == 0)
3325 {
3326 if (argc <= i + 1)
3327 {
3328 return errorArgument("Missing argument to '%s'", argv[i]);
3329 }
3330 i++;
3331 char *pszNext;
3332 int rc = RTStrToUInt64Ex(argv[i], &pszNext, 0, &lun);
3333 if (VBOX_FAILURE(rc) || *pszNext != '\0')
3334 return errorArgument("Invalid encoded LUN number '%s'", argv[i]);
3335 }
3336 else if (strcmp(argv[i], "-username") == 0)
3337 {
3338 if (argc <= i + 1)
3339 {
3340 return errorArgument("Missing argument to '%s'", argv[i]);
3341 }
3342 i++;
3343 username = argv[i];
3344 }
3345 else if (strcmp(argv[i], "-password") == 0)
3346 {
3347 if (argc <= i + 1)
3348 {
3349 return errorArgument("Missing argument to '%s'", argv[i]);
3350 }
3351 i++;
3352 password = argv[i];
3353 }
3354 else if (strcmp(argv[i], "-comment") == 0)
3355 {
3356 if (argc <= i + 1)
3357 {
3358 return errorArgument("Missing argument to '%s'", argv[i]);
3359 }
3360 i++;
3361 comment = argv[i];
3362 }
3363 else
3364 {
3365 return errorSyntax(USAGE_ADDISCSIDISK, "Invalid parameter '%s'", Utf8Str(argv[i]).raw());
3366 }
3367 }
3368
3369 /* check for required options */
3370 if (!server || !target)
3371 {
3372 return errorSyntax(USAGE_ADDISCSIDISK, "Parameters -server and -target are required");
3373 }
3374
3375 ComPtr<IHardDisk> hardDisk;
3376 CHECK_ERROR(aVirtualBox, CreateHardDisk(HardDiskStorageType_ISCSIHardDisk, hardDisk.asOutParam()));
3377 if (SUCCEEDED(rc) && hardDisk)
3378 {
3379 CHECK_ERROR(hardDisk, COMSETTER(Description)(comment));
3380 ComPtr<IISCSIHardDisk> iSCSIDisk = hardDisk;
3381 CHECK_ERROR(iSCSIDisk, COMSETTER(Server)(server));
3382 if (port != UINT16_MAX)
3383 CHECK_ERROR(iSCSIDisk, COMSETTER(Port)(port));
3384 CHECK_ERROR(iSCSIDisk, COMSETTER(Target)(target));
3385 if (lun != UINT64_MAX)
3386 CHECK_ERROR(iSCSIDisk, COMSETTER(Lun)(lun));
3387 CHECK_ERROR(iSCSIDisk, COMSETTER(UserName)(username));
3388 CHECK_ERROR(iSCSIDisk, COMSETTER(Password)(password));
3389
3390 if (SUCCEEDED(rc))
3391 {
3392 CHECK_ERROR(aVirtualBox, RegisterHardDisk(hardDisk));
3393 }
3394
3395 if (SUCCEEDED(rc))
3396 {
3397 Guid guid;
3398 CHECK_ERROR(hardDisk, COMGETTER(Id)(guid.asOutParam()));
3399 RTPrintf("iSCSI disk created. UUID: %s\n", guid.toString().raw());
3400 }
3401 }
3402
3403 return SUCCEEDED(rc) ? 0 : 1;
3404}
3405
3406static int handleCreateVM(int argc, char *argv[],
3407 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)
3408{
3409 HRESULT rc;
3410 Bstr baseFolder;
3411 Bstr settingsFile;
3412 Bstr name;
3413 bool fRegister = false;
3414
3415 for (int i = 0; i < argc; i++)
3416 {
3417 if (strcmp(argv[i], "-basefolder") == 0)
3418 {
3419 if (argc <= i + 1)
3420 {
3421 return errorArgument("Missing argument to '%s'", argv[i]);
3422 }
3423 i++;
3424 baseFolder = argv[i];
3425 }
3426 else if (strcmp(argv[i], "-settingsfile") == 0)
3427 {
3428 if (argc <= i + 1)
3429 {
3430 return errorArgument("Missing argument to '%s'", argv[i]);
3431 }
3432 i++;
3433 settingsFile = argv[i];
3434 }
3435 else if (strcmp(argv[i], "-name") == 0)
3436 {
3437 if (argc <= i + 1)
3438 {
3439 return errorArgument("Missing argument to '%s'", argv[i]);
3440 }
3441 i++;
3442 name = argv[i];
3443 }
3444 else if (strcmp(argv[i], "-register") == 0)
3445 {
3446 fRegister = true;
3447 }
3448 else
3449 {
3450 return errorSyntax(USAGE_CREATEVM, "Invalid parameter '%s'", Utf8Str(argv[i]).raw());
3451 }
3452 }
3453 if (!name)
3454 {
3455 return errorSyntax(USAGE_CREATEVM, "Parameter -name is required");
3456 }
3457 if (!!baseFolder && !!settingsFile)
3458 {
3459 return errorSyntax(USAGE_CREATEVM, "Either -basefolder or -settingsfile must be specified");
3460 }
3461
3462 do
3463 {
3464 ComPtr<IMachine> machine;
3465
3466 if (!settingsFile)
3467 CHECK_ERROR_BREAK(virtualBox,
3468 CreateMachine(baseFolder, name, machine.asOutParam()));
3469 else
3470 CHECK_ERROR_BREAK(virtualBox,
3471 CreateLegacyMachine(settingsFile, name, machine.asOutParam()));
3472
3473 CHECK_ERROR_BREAK(machine, SaveSettings());
3474 if (fRegister)
3475 {
3476 CHECK_ERROR_BREAK(virtualBox, RegisterMachine(machine));
3477 }
3478 Guid uuid;
3479 CHECK_ERROR_BREAK(machine, COMGETTER(Id)(uuid.asOutParam()));
3480 CHECK_ERROR_BREAK(machine, COMGETTER(SettingsFilePath)(settingsFile.asOutParam()));
3481 RTPrintf("Virtual machine '%ls' is created%s.\n"
3482 "UUID: %s\n"
3483 "Settings file: '%ls'\n",
3484 name.raw(), fRegister ? " and registered" : "",
3485 uuid.toString().raw(), settingsFile.raw());
3486 }
3487 while (0);
3488
3489 return SUCCEEDED(rc) ? 0 : 1;
3490}
3491
3492/**
3493 * Parses a number.
3494 *
3495 * @returns Valid number on success.
3496 * @returns 0 if invalid number. All necesary bitching has been done.
3497 * @param psz Pointer to the nic number.
3498 */
3499static unsigned parseNum(const char *psz, unsigned cMaxNum, const char *name)
3500{
3501 uint32_t u32;
3502 char *pszNext;
3503 int rc = RTStrToUInt32Ex(psz, &pszNext, 10, &u32);
3504 if ( VBOX_SUCCESS(rc)
3505 && *pszNext == '\0'
3506 && u32 >= 1
3507 && u32 <= cMaxNum)
3508 return (unsigned)u32;
3509 errorArgument("Invalid %s number '%s'", name, psz);
3510 return 0;
3511}
3512
3513static int handleModifyVM(int argc, char *argv[],
3514 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)
3515{
3516 HRESULT rc;
3517 Bstr name;
3518 Bstr ostype;
3519 ULONG memorySize = 0;
3520 ULONG vramSize = 0;
3521 char *acpi = NULL;
3522 char *hwvirtex = NULL;
3523 char *ioapic = NULL;
3524 int monitorcount = -1;
3525 char *bioslogofadein = NULL;
3526 char *bioslogofadeout = NULL;
3527 uint32_t bioslogodisplaytime = ~0;
3528 char *bioslogoimagepath = NULL;
3529 char *biosbootmenumode = NULL;
3530 char *biossystemtimeoffset = NULL;
3531 DeviceType_T bootDevice[4];
3532 int bootDeviceChanged[4] = { false };
3533 char *hdds[4] = {0};
3534 char *dvd = NULL;
3535 char *dvdpassthrough = NULL;
3536 char *floppy = NULL;
3537 char *audio = NULL;
3538 char *clipboard = NULL;
3539#ifdef VBOX_VRDP
3540 char *vrdp = NULL;
3541 uint16_t vrdpport = UINT16_MAX;
3542 char *vrdpaddress = NULL;
3543 char *vrdpauthtype = NULL;
3544 char *vrdpmulticon = NULL;
3545#endif
3546 int fUsbEnabled = -1;
3547 char *snapshotFolder = NULL;
3548 ULONG guestMemBalloonSize = (ULONG)-1;
3549 ULONG guestStatInterval = (ULONG)-1;
3550
3551 /* VM ID + at least one parameter + value */
3552 if (argc < 3)
3553 {
3554 return errorSyntax(USAGE_MODIFYVM, "Not enough parameters");
3555 }
3556
3557 /* Get the number of network adapters */
3558 ULONG NetworkAdapterCount = 0;
3559 {
3560 ComPtr <ISystemProperties> info;
3561 CHECK_ERROR_RET (virtualBox, COMGETTER(SystemProperties) (info.asOutParam()), 1);
3562 CHECK_ERROR_RET (info, COMGETTER(NetworkAdapterCount) (&NetworkAdapterCount), 1);
3563 }
3564 ULONG SerialPortCount = 0;
3565 {
3566 ComPtr <ISystemProperties> info;
3567 CHECK_ERROR_RET (virtualBox, COMGETTER(SystemProperties) (info.asOutParam()), 1);
3568 CHECK_ERROR_RET (info, COMGETTER(SerialPortCount) (&SerialPortCount), 1);
3569 }
3570
3571 std::vector <char *> nics (NetworkAdapterCount, 0);
3572 std::vector <char *> nictype (NetworkAdapterCount, 0);
3573 std::vector <char *> cableconnected (NetworkAdapterCount, 0);
3574 std::vector <char *> nictrace (NetworkAdapterCount, 0);
3575 std::vector <char *> nictracefile (NetworkAdapterCount, 0);
3576 std::vector <char *> nicspeed (NetworkAdapterCount, 0);
3577 std::vector <char *> hostifdev (NetworkAdapterCount, 0);
3578 std::vector <const char *> intnet (NetworkAdapterCount, 0);
3579#ifdef RT_OS_LINUX
3580 std::vector <char *> tapsetup (NetworkAdapterCount, 0);
3581 std::vector <char *> tapterm (NetworkAdapterCount, 0);
3582#endif
3583 std::vector <char *> macs (NetworkAdapterCount, 0);
3584 std::vector <char *> uarts_mode (SerialPortCount, 0);
3585 std::vector <ULONG> uarts_base (SerialPortCount, 0);
3586 std::vector <ULONG> uarts_irq (SerialPortCount, 0);
3587 std::vector <char *> uarts_path (SerialPortCount, 0);
3588
3589 for (int i = 1; i < argc; i++)
3590 {
3591 if (strcmp(argv[i], "-name") == 0)
3592 {
3593 if (argc <= i + 1)
3594 {
3595 return errorArgument("Missing argument to '%s'", argv[i]);
3596 }
3597 i++;
3598 name = argv[i];
3599 }
3600 else if (strcmp(argv[i], "-ostype") == 0)
3601 {
3602 if (argc <= i + 1)
3603 {
3604 return errorArgument("Missing argument to '%s'", argv[i]);
3605 }
3606 i++;
3607 ostype = argv[i];
3608 }
3609 else if (strcmp(argv[i], "-memory") == 0)
3610 {
3611 if (argc <= i + 1)
3612 {
3613 return errorArgument("Missing argument to '%s'", argv[i]);
3614 }
3615 i++;
3616 memorySize = atoi(argv[i]);
3617 }
3618 else if (strcmp(argv[i], "-vram") == 0)
3619 {
3620 if (argc <= i + 1)
3621 {
3622 return errorArgument("Missing argument to '%s'", argv[i]);
3623 }
3624 i++;
3625 vramSize = atoi(argv[i]);
3626 }
3627 else if (strcmp(argv[i], "-acpi") == 0)
3628 {
3629 if (argc <= i + 1)
3630 {
3631 return errorArgument("Missing argument to '%s'", argv[i]);
3632 }
3633 i++;
3634 acpi = argv[i];
3635 }
3636 else if (strcmp(argv[i], "-ioapic") == 0)
3637 {
3638 if (argc <= i + 1)
3639 {
3640 return errorArgument("Missing argument to '%s'", argv[i]);
3641 }
3642 i++;
3643 ioapic = argv[i];
3644 }
3645 else if (strcmp(argv[i], "-hwvirtex") == 0)
3646 {
3647 if (argc <= i + 1)
3648 {
3649 return errorArgument("Missing argument to '%s'", argv[i]);
3650 }
3651 i++;
3652 hwvirtex = argv[i];
3653 }
3654 else if (strcmp(argv[i], "-monitorcount") == 0)
3655 {
3656 if (argc <= i + 1)
3657 {
3658 return errorArgument("Missing argument to '%s'", argv[i]);
3659 }
3660 i++;
3661 monitorcount = atoi(argv[i]);
3662 }
3663 else if (strcmp(argv[i], "-bioslogofadein") == 0)
3664 {
3665 if (argc <= i + 1)
3666 {
3667 return errorArgument("Missing argument to '%s'", argv[i]);
3668 }
3669 i++;
3670 bioslogofadein = argv[i];
3671 }
3672 else if (strcmp(argv[i], "-bioslogofadeout") == 0)
3673 {
3674 if (argc <= i + 1)
3675 {
3676 return errorArgument("Missing argument to '%s'", argv[i]);
3677 }
3678 i++;
3679 bioslogofadeout = argv[i];
3680 }
3681 else if (strcmp(argv[i], "-bioslogodisplaytime") == 0)
3682 {
3683 if (argc <= i + 1)
3684 {
3685 return errorArgument("Missing argument to '%s'", argv[i]);
3686 }
3687 i++;
3688 bioslogodisplaytime = atoi(argv[i]);
3689 }
3690 else if (strcmp(argv[i], "-bioslogoimagepath") == 0)
3691 {
3692 if (argc <= i + 1)
3693 {
3694 return errorArgument("Missing argument to '%s'", argv[i]);
3695 }
3696 i++;
3697 bioslogoimagepath = argv[i];
3698 }
3699 else if (strcmp(argv[i], "-biosbootmenu") == 0)
3700 {
3701 if (argc <= i + 1)
3702 {
3703 return errorArgument("Missing argument to '%s'", argv[i]);
3704 }
3705 i++;
3706 biosbootmenumode = argv[i];
3707 }
3708 else if (strcmp(argv[i], "-biossystemtimeoffset") == 0)
3709 {
3710 if (argc <= i + 1)
3711 {
3712 return errorArgument("Missing argument to '%s'", argv[i]);
3713 }
3714 i++;
3715 biossystemtimeoffset = argv[i];
3716 }
3717 else if (strncmp(argv[i], "-boot", 5) == 0)
3718 {
3719 ULONG n = 0;
3720 if (!argv[i][5])
3721 {
3722 return errorSyntax(USAGE_MODIFYVM, "Missing boot slot number in '%s'", argv[i]);
3723 }
3724 if ((n = strtoul(&argv[i][5], NULL, 10)) < 1)
3725 {
3726 return errorSyntax(USAGE_MODIFYVM, "Invalid boot slot number in '%s'", argv[i]);
3727 }
3728 if (argc <= i + 1)
3729 {
3730 return errorArgument("Missing argument to '%s'", argv[i]);
3731 }
3732 i++;
3733 if (strcmp(argv[i], "none") == 0)
3734 {
3735 bootDevice[n - 1] = DeviceType_NoDevice;
3736 }
3737 else if (strcmp(argv[i], "floppy") == 0)
3738 {
3739 bootDevice[n - 1] = DeviceType_FloppyDevice;
3740 }
3741 else if (strcmp(argv[i], "dvd") == 0)
3742 {
3743 bootDevice[n - 1] = DeviceType_DVDDevice;
3744 }
3745 else if (strcmp(argv[i], "disk") == 0)
3746 {
3747 bootDevice[n - 1] = DeviceType_HardDiskDevice;
3748 }
3749 else if (strcmp(argv[i], "net") == 0)
3750 {
3751 bootDevice[n - 1] = DeviceType_NetworkDevice;
3752 }
3753 else
3754 {
3755 return errorArgument("Invalid boot device '%s'", argv[i]);
3756 }
3757 bootDeviceChanged[n - 1] = true;
3758 }
3759 else if (strcmp(argv[i], "-hda") == 0)
3760 {
3761 if (argc <= i + 1)
3762 {
3763 return errorArgument("Missing argument to '%s'", argv[i]);
3764 }
3765 i++;
3766 hdds[0] = argv[i];
3767 }
3768 else if (strcmp(argv[i], "-hdb") == 0)
3769 {
3770 if (argc <= i + 1)
3771 {
3772 return errorArgument("Missing argument to '%s'", argv[i]);
3773 }
3774 i++;
3775 hdds[1] = argv[i];
3776 }
3777 else if (strcmp(argv[i], "-hdd") == 0)
3778 {
3779 if (argc <= i + 1)
3780 {
3781 return errorArgument("Missing argument to '%s'", argv[i]);
3782 }
3783 i++;
3784 hdds[2] = argv[i];
3785 }
3786 else if (strcmp(argv[i], "-dvd") == 0)
3787 {
3788 if (argc <= i + 1)
3789 {
3790 return errorArgument("Missing argument to '%s'", argv[i]);
3791 }
3792 i++;
3793 dvd = argv[i];
3794 }
3795 else if (strcmp(argv[i], "-dvdpassthrough") == 0)
3796 {
3797 if (argc <= i + 1)
3798 {
3799 return errorArgument("Missing argument to '%s'", argv[i]);
3800 }
3801 i++;
3802 dvdpassthrough = argv[i];
3803 }
3804 else if (strcmp(argv[i], "-floppy") == 0)
3805 {
3806 if (argc <= i + 1)
3807 {
3808 return errorArgument("Missing argument to '%s'", argv[i]);
3809 }
3810 i++;
3811 floppy = argv[i];
3812 }
3813 else if (strcmp(argv[i], "-audio") == 0)
3814 {
3815 if (argc <= i + 1)
3816 {
3817 return errorArgument("Missing argument to '%s'", argv[i]);
3818 }
3819 i++;
3820 audio = argv[i];
3821 }
3822 else if (strcmp(argv[i], "-clipboard") == 0)
3823 {
3824 if (argc <= i + 1)
3825 {
3826 return errorArgument("Missing argument to '%s'", argv[i]);
3827 }
3828 i++;
3829 clipboard = argv[i];
3830 }
3831 else if (strncmp(argv[i], "-cableconnected", 15) == 0)
3832 {
3833 unsigned n = parseNum(&argv[i][15], NetworkAdapterCount, "NIC");
3834 if (!n)
3835 return 1;
3836 if (argc <= i + 1)
3837 {
3838 return errorArgument("Missing argument to '%s'", argv[i]);
3839 }
3840 cableconnected[n - 1] = argv[i + 1];
3841 i++;
3842 }
3843 /* watch for the right order of these -nic* comparisons! */
3844 else if (strncmp(argv[i], "-nictracefile", 13) == 0)
3845 {
3846 unsigned n = parseNum(&argv[i][13], NetworkAdapterCount, "NIC");
3847 if (!n)
3848 return 1;
3849 if (argc <= i + 1)
3850 {
3851 return errorArgument("Missing argument to '%s'", argv[i]);
3852 }
3853 nictracefile[n - 1] = argv[i + 1];
3854 i++;
3855 }
3856 else if (strncmp(argv[i], "-nictrace", 9) == 0)
3857 {
3858 unsigned n = parseNum(&argv[i][9], NetworkAdapterCount, "NIC");
3859 if (!n)
3860 return 1;
3861 if (argc <= i + 1)
3862 {
3863 return errorArgument("Missing argument to '%s'", argv[i]);
3864 }
3865 nictrace[n - 1] = argv[i + 1];
3866 i++;
3867 }
3868 else if (strncmp(argv[i], "-nictype", 8) == 0)
3869 {
3870 unsigned n = parseNum(&argv[i][8], NetworkAdapterCount, "NIC");
3871 if (!n)
3872 return 1;
3873 if (argc <= i + 1)
3874 {
3875 return errorArgument("Missing argument to '%s'", argv[i]);
3876 }
3877 nictype[n - 1] = argv[i + 1];
3878 i++;
3879 }
3880 else if (strncmp(argv[i], "-nicspeed", 9) == 0)
3881 {
3882 unsigned n = parseNum(&argv[i][9], NetworkAdapterCount, "NIC");
3883 if (!n)
3884 return 1;
3885 if (argc <= i + 1)
3886 {
3887 return errorArgument("Missing argument to '%s'", argv[i]);
3888 }
3889 nicspeed[n - 1] = argv[i + 1];
3890 i++;
3891 }
3892 else if (strncmp(argv[i], "-nic", 4) == 0)
3893 {
3894 unsigned n = parseNum(&argv[i][4], NetworkAdapterCount, "NIC");
3895 if (!n)
3896 return 1;
3897 if (argc <= i + 1)
3898 {
3899 return errorArgument("Missing argument to '%s'", argv[i]);
3900 }
3901 nics[n - 1] = argv[i + 1];
3902 i++;
3903 }
3904 else if (strncmp(argv[i], "-hostifdev", 10) == 0)
3905 {
3906 unsigned n = parseNum(&argv[i][10], NetworkAdapterCount, "NIC");
3907 if (!n)
3908 return 1;
3909 if (argc <= i + 1)
3910 {
3911 return errorArgument("Missing argument to '%s'", argv[i]);
3912 }
3913 hostifdev[n - 1] = argv[i + 1];
3914 i++;
3915 }
3916 else if (strncmp(argv[i], "-intnet", 7) == 0)
3917 {
3918 unsigned n = parseNum(&argv[i][7], NetworkAdapterCount, "NIC");
3919 if (!n)
3920 return 1;
3921 if (argc <= i + 1)
3922 {
3923 return errorArgument("Missing argument to '%s'", argv[i]);
3924 }
3925 intnet[n - 1] = argv[i + 1];
3926 i++;
3927 }
3928#ifdef RT_OS_LINUX
3929 else if (strncmp(argv[i], "-tapsetup", 9) == 0)
3930 {
3931 unsigned n = parseNum(&argv[i][9], NetworkAdapterCount, "NIC");
3932 if (!n)
3933 return 1;
3934 if (argc <= i + 1)
3935 {
3936 return errorArgument("Missing argument to '%s'", argv[i]);
3937 }
3938 tapsetup[n - 1] = argv[i + 1];
3939 i++;
3940 }
3941 else if (strncmp(argv[i], "-tapterminate", 13) == 0)
3942 {
3943 unsigned n = parseNum(&argv[i][13], NetworkAdapterCount, "NIC");
3944 if (!n)
3945 return 1;
3946 if (argc <= i + 1)
3947 {
3948 return errorArgument("Missing argument to '%s'", argv[i]);
3949 }
3950 tapterm[n - 1] = argv[i + 1];
3951 i++;
3952 }
3953#endif /* RT_OS_LINUX */
3954 else if (strncmp(argv[i], "-macaddress", 11) == 0)
3955 {
3956 unsigned n = parseNum(&argv[i][11], NetworkAdapterCount, "NIC");
3957 if (!n)
3958 return 1;
3959 if (argc <= i + 1)
3960 {
3961 return errorArgument("Missing argument to '%s'", argv[i]);
3962 }
3963 macs[n - 1] = argv[i + 1];
3964 i++;
3965 }
3966#ifdef VBOX_VRDP
3967 else if (strcmp(argv[i], "-vrdp") == 0)
3968 {
3969 if (argc <= i + 1)
3970 {
3971 return errorArgument("Missing argument to '%s'", argv[i]);
3972 }
3973 i++;
3974 vrdp = argv[i];
3975 }
3976 else if (strcmp(argv[i], "-vrdpport") == 0)
3977 {
3978 if (argc <= i + 1)
3979 {
3980 return errorArgument("Missing argument to '%s'", argv[i]);
3981 }
3982 i++;
3983 if (strcmp(argv[i], "default") == 0)
3984 vrdpport = 0;
3985 else
3986 vrdpport = atoi(argv[i]);
3987 }
3988 else if (strcmp(argv[i], "-vrdpaddress") == 0)
3989 {
3990 if (argc <= i + 1)
3991 {
3992 return errorArgument("Missing argument to '%s'", argv[i]);
3993 }
3994 i++;
3995 vrdpaddress = argv[i];
3996 }
3997 else if (strcmp(argv[i], "-vrdpauthtype") == 0)
3998 {
3999 if (argc <= i + 1)
4000 {
4001 return errorArgument("Missing argument to '%s'", argv[i]);
4002 }
4003 i++;
4004 vrdpauthtype = argv[i];
4005 }
4006 else if (strcmp(argv[i], "-vrdpmulticon") == 0)
4007 {
4008 if (argc <= i + 1)
4009 {
4010 return errorArgument("Missing argument to '%s'", argv[i]);
4011 }
4012 i++;
4013 vrdpmulticon = argv[i];
4014 }
4015#endif /* VBOX_VRDP */
4016 else if (strcmp(argv[i], "-usb") == 0)
4017 {
4018 if (argc <= i + 1)
4019 {
4020 return errorArgument("Missing argument to '%s'", argv[i]);
4021 }
4022 i++;
4023 if (strcmp(argv[i], "on") == 0 || strcmp(argv[i], "enable") == 0)
4024 fUsbEnabled = 1;
4025 else if (strcmp(argv[i], "off") == 0 || strcmp(argv[i], "disable") == 0)
4026 fUsbEnabled = 0;
4027 else
4028 return errorArgument("Invalid -usb argument '%s'", argv[i]);
4029 }
4030 else if (strcmp(argv[i], "-snapshotfolder") == 0)
4031 {
4032 if (argc <= i + 1)
4033 {
4034 return errorArgument("Missing argument to '%s'", argv[i]);
4035 }
4036 i++;
4037 snapshotFolder = argv[i];
4038 }
4039 else if (strncmp(argv[i], "-uartmode", 9) == 0)
4040 {
4041 unsigned n = parseNum(&argv[i][9], SerialPortCount, "UART");
4042 if (!n)
4043 return 1;
4044 i++;
4045 if (strcmp(argv[i], "disconnected") == 0)
4046 {
4047 uarts_mode[n - 1] = argv[i];
4048 }
4049 else
4050 {
4051 if (strcmp(argv[i], "server") == 0 || strcmp(argv[i], "client") == 0)
4052 {
4053 uarts_mode[n - 1] = argv[i];
4054 i++;
4055#ifdef RT_OS_WINDOWS
4056 if (strncmp(argv[i], "\\\\.\\pipe\\", 9))
4057 return errorArgument("Uart pipe must start with \\\\.\\pipe\\");
4058#endif
4059 }
4060 else
4061 {
4062 uarts_mode[n - 1] = (char*)"device";
4063 }
4064 if (argc <= i)
4065 {
4066 return errorArgument("Missing argument to -uartmode");
4067 }
4068 uarts_path[n - 1] = argv[i];
4069 }
4070 }
4071 else if (strncmp(argv[i], "-uart", 5) == 0)
4072 {
4073 unsigned n = parseNum(&argv[i][5], SerialPortCount, "UART");
4074 if (!n)
4075 return 1;
4076 if (argc <= i + 1)
4077 {
4078 return errorArgument("Missing argument to '%s'", argv[i]);
4079 }
4080 i++;
4081 if (strcmp(argv[i], "off") == 0 || strcmp(argv[i], "disable") == 0)
4082 {
4083 uarts_base[n - 1] = (ULONG)-1;
4084 }
4085 else
4086 {
4087 if (argc <= i + 1)
4088 {
4089 return errorArgument("Missing argument to '%s'", argv[i-1]);
4090 }
4091 uint32_t uVal;
4092 int vrc;
4093 vrc = RTStrToUInt32Ex(argv[i], NULL, 0, &uVal);
4094 if (vrc != VINF_SUCCESS || uVal == 0)
4095 return errorArgument("Error parsing UART I/O base '%s'", argv[i]);
4096 uarts_base[n - 1] = uVal;
4097 i++;
4098 vrc = RTStrToUInt32Ex(argv[i], NULL, 0, &uVal);
4099 if (vrc != VINF_SUCCESS)
4100 return errorArgument("Error parsing UART IRQ '%s'", argv[i]);
4101 uarts_irq[n - 1] = uVal;
4102 }
4103 }
4104 else if (strncmp(argv[i], "-guestmemoryballoon", 19) == 0)
4105 {
4106 if (argc <= i + 1)
4107 return errorArgument("Missing argument to '%s'", argv[i-1]);
4108 i++;
4109 uint32_t uVal;
4110 int vrc;
4111 vrc = RTStrToUInt32Ex(argv[i], NULL, 0, &uVal);
4112 if (vrc != VINF_SUCCESS)
4113 return errorArgument("Error parsing guest memory balloon size '%s'", argv[i]);
4114 guestMemBalloonSize = uVal;
4115 }
4116 else if (strncmp(argv[i], "-gueststatisticsinterval", 24) == 0)
4117 {
4118 if (argc <= i + 1)
4119 return errorArgument("Missing argument to '%s'", argv[i-1]);
4120 i++;
4121 uint32_t uVal;
4122 int vrc;
4123 vrc = RTStrToUInt32Ex(argv[i], NULL, 0, &uVal);
4124 if (vrc != VINF_SUCCESS)
4125 return errorArgument("Error parsing guest statistics interval '%s'", argv[i]);
4126 guestStatInterval = uVal;
4127 }
4128 else
4129 {
4130 return errorSyntax(USAGE_MODIFYVM, "Invalid parameter '%s'", Utf8Str(argv[i]).raw());
4131 }
4132 }
4133
4134 /* try to find the given machine */
4135 ComPtr <IMachine> machine;
4136 Guid uuid (argv[0]);
4137 if (!uuid.isEmpty())
4138 {
4139 CHECK_ERROR (virtualBox, GetMachine (uuid, machine.asOutParam()));
4140 }
4141 else
4142 {
4143 CHECK_ERROR (virtualBox, FindMachine(Bstr(argv[0]), machine.asOutParam()));
4144 if (SUCCEEDED (rc))
4145 machine->COMGETTER(Id)(uuid.asOutParam());
4146 }
4147 if (FAILED (rc))
4148 return 1;
4149
4150 /* open a session for the VM */
4151 CHECK_ERROR_RET (virtualBox, OpenSession(session, uuid), 1);
4152
4153 do
4154 {
4155 /* get the mutable session machine */
4156 session->COMGETTER(Machine)(machine.asOutParam());
4157
4158 ComPtr <IBIOSSettings> biosSettings;
4159 machine->COMGETTER(BIOSSettings)(biosSettings.asOutParam());
4160
4161 if (name)
4162 CHECK_ERROR(machine, COMSETTER(Name)(name));
4163 if (ostype)
4164 {
4165 ComPtr<IGuestOSType> guestOSType;
4166 CHECK_ERROR(virtualBox, GetGuestOSType(ostype, guestOSType.asOutParam()));
4167 if (SUCCEEDED(rc) && guestOSType)
4168 {
4169 CHECK_ERROR(machine, COMSETTER(OSTypeId)(ostype));
4170 }
4171 else
4172 {
4173 errorArgument("Invalid guest OS type '%s'", Utf8Str(ostype).raw());
4174 rc = E_FAIL;
4175 break;
4176 }
4177 }
4178 if (memorySize > 0)
4179 CHECK_ERROR(machine, COMSETTER(MemorySize)(memorySize));
4180 if (vramSize > 0)
4181 CHECK_ERROR(machine, COMSETTER(VRAMSize)(vramSize));
4182 if (acpi)
4183 {
4184 if (strcmp(acpi, "on") == 0)
4185 {
4186 CHECK_ERROR(biosSettings, COMSETTER(ACPIEnabled)(true));
4187 }
4188 else if (strcmp(acpi, "off") == 0)
4189 {
4190 CHECK_ERROR(biosSettings, COMSETTER(ACPIEnabled)(false));
4191 }
4192 else
4193 {
4194 errorArgument("Invalid -acpi argument '%s'", acpi);
4195 rc = E_FAIL;
4196 break;
4197 }
4198 }
4199 if (ioapic)
4200 {
4201 if (strcmp(ioapic, "on") == 0)
4202 {
4203 CHECK_ERROR(biosSettings, COMSETTER(IOAPICEnabled)(true));
4204 }
4205 else if (strcmp(ioapic, "off") == 0)
4206 {
4207 CHECK_ERROR(biosSettings, COMSETTER(IOAPICEnabled)(false));
4208 }
4209 else
4210 {
4211 errorArgument("Invalid -ioapic argument '%s'", ioapic);
4212 rc = E_FAIL;
4213 break;
4214 }
4215 }
4216 if (hwvirtex)
4217 {
4218 if (strcmp(hwvirtex, "on") == 0)
4219 {
4220 CHECK_ERROR(machine, COMSETTER(HWVirtExEnabled)(TriStateBool_True));
4221 }
4222 else if (strcmp(hwvirtex, "off") == 0)
4223 {
4224 CHECK_ERROR(machine, COMSETTER(HWVirtExEnabled)(TriStateBool_False));
4225 }
4226 else if (strcmp(hwvirtex, "default") == 0)
4227 {
4228 CHECK_ERROR(machine, COMSETTER(HWVirtExEnabled)(TriStateBool_Default));
4229 }
4230 else
4231 {
4232 errorArgument("Invalid -hwvirtex argument '%s'", hwvirtex);
4233 rc = E_FAIL;
4234 break;
4235 }
4236 }
4237 if (monitorcount != -1)
4238 {
4239 CHECK_ERROR(machine, COMSETTER(MonitorCount)(monitorcount));
4240 }
4241 if (bioslogofadein)
4242 {
4243 if (strcmp(bioslogofadein, "on") == 0)
4244 {
4245 CHECK_ERROR(biosSettings, COMSETTER(LogoFadeIn)(true));
4246 }
4247 else if (strcmp(bioslogofadein, "off") == 0)
4248 {
4249 CHECK_ERROR(biosSettings, COMSETTER(LogoFadeIn)(false));
4250 }
4251 else
4252 {
4253 errorArgument("Invalid -bioslogofadein argument '%s'", bioslogofadein);
4254 rc = E_FAIL;
4255 break;
4256 }
4257 }
4258 if (bioslogofadeout)
4259 {
4260 if (strcmp(bioslogofadeout, "on") == 0)
4261 {
4262 CHECK_ERROR(biosSettings, COMSETTER(LogoFadeOut)(true));
4263 }
4264 else if (strcmp(bioslogofadeout, "off") == 0)
4265 {
4266 CHECK_ERROR(biosSettings, COMSETTER(LogoFadeOut)(false));
4267 }
4268 else
4269 {
4270 errorArgument("Invalid -bioslogofadeout argument '%s'", bioslogofadeout);
4271 rc = E_FAIL;
4272 break;
4273 }
4274 }
4275 if (bioslogodisplaytime != ~0U)
4276 {
4277 CHECK_ERROR(biosSettings, COMSETTER(LogoDisplayTime)(bioslogodisplaytime));
4278 }
4279 if (bioslogoimagepath)
4280 {
4281 CHECK_ERROR(biosSettings, COMSETTER(LogoImagePath)(Bstr(bioslogoimagepath)));
4282 }
4283 if (biosbootmenumode)
4284 {
4285 if (strcmp(biosbootmenumode, "disabled") == 0)
4286 CHECK_ERROR(biosSettings, COMSETTER(BootMenuMode)(BIOSBootMenuMode_Disabled));
4287 else if (strcmp(biosbootmenumode, "menuonly") == 0)
4288 CHECK_ERROR(biosSettings, COMSETTER(BootMenuMode)(BIOSBootMenuMode_MenuOnly));
4289 else if (strcmp(biosbootmenumode, "messageandmenu") == 0)
4290 CHECK_ERROR(biosSettings, COMSETTER(BootMenuMode)(BIOSBootMenuMode_MessageAndMenu));
4291 else
4292 {
4293 errorArgument("Invalid -biosbootmenu argument '%s'", biosbootmenumode);
4294 rc = E_FAIL;
4295 break;
4296 }
4297
4298 }
4299 if (biossystemtimeoffset)
4300 {
4301 LONG64 timeOffset = RTStrToInt64(biossystemtimeoffset);
4302 CHECK_ERROR(biosSettings, COMSETTER(TimeOffset)(timeOffset));
4303 }
4304 for (int curBootDev = 0; curBootDev < 4; curBootDev++)
4305 {
4306 if (bootDeviceChanged[curBootDev])
4307 CHECK_ERROR(machine, SetBootOrder (curBootDev + 1, bootDevice[curBootDev]));
4308 }
4309 if (hdds[0])
4310 {
4311 if (strcmp(hdds[0], "none") == 0)
4312 {
4313 machine->DetachHardDisk(DiskControllerType_IDE0Controller, 0);
4314 }
4315 else
4316 {
4317 /* first guess is that it's a UUID */
4318 Guid uuid(hdds[0]);
4319 ComPtr<IHardDisk> hardDisk;
4320 rc = virtualBox->GetHardDisk(uuid, hardDisk.asOutParam());
4321 /* not successful? Then it must be a filename */
4322 if (!hardDisk)
4323 {
4324 CHECK_ERROR(virtualBox, OpenHardDisk(Bstr(hdds[0]), hardDisk.asOutParam()));
4325 if (SUCCEEDED(rc) && hardDisk)
4326 {
4327 /* first check if it's already registered */
4328 Guid hddUUID;
4329 hardDisk->COMGETTER(Id)(hddUUID.asOutParam());
4330 ComPtr<IHardDisk> registeredHDD;
4331 rc = virtualBox->GetHardDisk(hddUUID, registeredHDD.asOutParam());
4332 if (SUCCEEDED(rc) && registeredHDD)
4333 hardDisk = registeredHDD;
4334 else
4335 {
4336 /* it has to be registered */
4337 CHECK_ERROR(virtualBox, RegisterHardDisk(hardDisk));
4338 if (FAILED(rc))
4339 break;
4340 }
4341 }
4342 }
4343 if (hardDisk)
4344 {
4345 hardDisk->COMGETTER(Id)(uuid.asOutParam());
4346 CHECK_ERROR(machine, AttachHardDisk(uuid, DiskControllerType_IDE0Controller, 0));
4347 }
4348 else
4349 rc = E_FAIL;
4350 if (FAILED(rc))
4351 break;
4352 }
4353 }
4354 if (hdds[1])
4355 {
4356 if (strcmp(hdds[1], "none") == 0)
4357 {
4358 machine->DetachHardDisk(DiskControllerType_IDE0Controller, 1);
4359 }
4360 else
4361 {
4362 /* first guess is that it's a UUID */
4363 Guid uuid(hdds[1]);
4364 ComPtr<IHardDisk> hardDisk;
4365 rc = virtualBox->GetHardDisk(uuid, hardDisk.asOutParam());
4366 /* not successful? Then it must be a filename */
4367 if (!hardDisk)
4368 {
4369 CHECK_ERROR(virtualBox, OpenHardDisk(Bstr(hdds[1]), hardDisk.asOutParam()));
4370 if (SUCCEEDED(rc) && hardDisk)
4371 {
4372 /* first check if it's already registered */
4373 Guid hddUUID;
4374 hardDisk->COMGETTER(Id)(hddUUID.asOutParam());
4375 ComPtr<IHardDisk> registeredHDD;
4376 rc = virtualBox->GetHardDisk(hddUUID, registeredHDD.asOutParam());
4377 if (SUCCEEDED(rc) && registeredHDD)
4378 hardDisk = registeredHDD;
4379 else
4380 {
4381 /* it has to be registered */
4382 CHECK_ERROR(virtualBox, RegisterHardDisk(hardDisk));
4383 if (FAILED(rc))
4384 break;
4385 }
4386 }
4387 }
4388 if (hardDisk)
4389 {
4390 hardDisk->COMGETTER(Id)(uuid.asOutParam());
4391 CHECK_ERROR(machine, AttachHardDisk(uuid, DiskControllerType_IDE0Controller, 1));
4392 }
4393 else
4394 rc = E_FAIL;
4395 if (FAILED(rc))
4396 break;
4397 }
4398 }
4399 if (hdds[2])
4400 {
4401 if (strcmp(hdds[2], "none") == 0)
4402 {
4403 machine->DetachHardDisk(DiskControllerType_IDE1Controller, 1);
4404 }
4405 else
4406 {
4407 /* first guess is that it's a UUID */
4408 Guid uuid(hdds[2]);
4409 ComPtr<IHardDisk> hardDisk;
4410 rc = virtualBox->GetHardDisk(uuid, hardDisk.asOutParam());
4411 /* not successful? Then it must be a filename */
4412 if (!hardDisk)
4413 {
4414 CHECK_ERROR(virtualBox, OpenHardDisk(Bstr(hdds[2]), hardDisk.asOutParam()));
4415 if (SUCCEEDED(rc) && hardDisk)
4416 {
4417 /* first check if it's already registered */
4418 Guid hddUUID;
4419 hardDisk->COMGETTER(Id)(hddUUID.asOutParam());
4420 ComPtr<IHardDisk> registeredHDD;
4421 rc = virtualBox->GetHardDisk(hddUUID, registeredHDD.asOutParam());
4422 if (SUCCEEDED(rc) && registeredHDD)
4423 hardDisk = registeredHDD;
4424 else
4425 {
4426 /* it has to be registered */
4427 CHECK_ERROR(virtualBox, RegisterHardDisk(hardDisk));
4428 if (FAILED(rc))
4429 break;
4430 }
4431 }
4432 }
4433 if (hardDisk)
4434 {
4435 hardDisk->COMGETTER(Id)(uuid.asOutParam());
4436 CHECK_ERROR(machine, AttachHardDisk(uuid, DiskControllerType_IDE1Controller, 1));
4437 }
4438 else
4439 rc = E_FAIL;
4440 if (FAILED(rc))
4441 break;
4442 }
4443 }
4444 if (dvd)
4445 {
4446 ComPtr<IDVDDrive> dvdDrive;
4447 machine->COMGETTER(DVDDrive)(dvdDrive.asOutParam());
4448 ASSERT(dvdDrive);
4449
4450 /* unmount? */
4451 if (strcmp(dvd, "none") == 0)
4452 {
4453 CHECK_ERROR(dvdDrive, Unmount());
4454 }
4455 /* host drive? */
4456 else if (strncmp(dvd, "host:", 5) == 0)
4457 {
4458 ComPtr<IHost> host;
4459 CHECK_ERROR(virtualBox, COMGETTER(Host)(host.asOutParam()));
4460 ComPtr<IHostDVDDriveCollection> hostDVDs;
4461 CHECK_ERROR(host, COMGETTER(DVDDrives)(hostDVDs.asOutParam()));
4462 ComPtr<IHostDVDDrive> hostDVDDrive;
4463 rc = hostDVDs->FindByName(Bstr(dvd + 5), hostDVDDrive.asOutParam());
4464 if (!hostDVDDrive)
4465 {
4466 /* 2nd try: try with the real name, important on Linux+libhal */
4467 char szPathReal[RTPATH_MAX];
4468 if (VBOX_FAILURE(RTPathReal(dvd + 5, szPathReal, sizeof(szPathReal))))
4469 {
4470 errorArgument("Invalid host DVD drive name");
4471 rc = E_FAIL;
4472 break;
4473 }
4474 rc = hostDVDs->FindByName(Bstr(szPathReal), hostDVDDrive.asOutParam());
4475 if (!hostDVDDrive)
4476 {
4477 errorArgument("Invalid host DVD drive name");
4478 rc = E_FAIL;
4479 break;
4480 }
4481 }
4482 CHECK_ERROR(dvdDrive, CaptureHostDrive(hostDVDDrive));
4483 }
4484 else
4485 {
4486 /* first assume it's a UUID */
4487 Guid uuid(dvd);
4488 ComPtr<IDVDImage> dvdImage;
4489 rc = virtualBox->GetDVDImage(uuid, dvdImage.asOutParam());
4490 if (FAILED(rc) || !dvdImage)
4491 {
4492 /* must be a filename, check if it's in the collection */
4493 ComPtr<IDVDImageCollection> dvdImages;
4494 virtualBox->COMGETTER(DVDImages)(dvdImages.asOutParam());
4495 rc = dvdImages->FindByPath(Bstr(dvd), dvdImage.asOutParam());
4496 /* not registered, do that on the fly */
4497 if (!dvdImage)
4498 {
4499 Guid emptyUUID;
4500 CHECK_ERROR(virtualBox, OpenDVDImage(Bstr(dvd), emptyUUID, dvdImage.asOutParam()));
4501 if (SUCCEEDED(rc) && dvdImage)
4502 {
4503 /* time to register the image */
4504 CHECK_ERROR(virtualBox, RegisterDVDImage(dvdImage));
4505 }
4506 }
4507 }
4508 if (!dvdImage)
4509 {
4510 rc = E_FAIL;
4511 break;
4512 }
4513
4514 dvdImage->COMGETTER(Id)(uuid.asOutParam());
4515 CHECK_ERROR(dvdDrive, MountImage(uuid));
4516 }
4517 }
4518 if (dvdpassthrough)
4519 {
4520 ComPtr<IDVDDrive> dvdDrive;
4521 machine->COMGETTER(DVDDrive)(dvdDrive.asOutParam());
4522 ASSERT(dvdDrive);
4523
4524 CHECK_ERROR(dvdDrive, COMSETTER(Passthrough)(strcmp(dvdpassthrough, "on") == 0));
4525 }
4526 if (floppy)
4527 {
4528 ComPtr<IFloppyDrive> floppyDrive;
4529 machine->COMGETTER(FloppyDrive)(floppyDrive.asOutParam());
4530 ASSERT(floppyDrive);
4531
4532 /* disable? */
4533 if (strcmp(floppy, "disabled") == 0)
4534 {
4535 /* disable the controller */
4536 CHECK_ERROR(floppyDrive, COMSETTER(Enabled)(false));
4537 }
4538 else
4539 {
4540 /* enable the controller */
4541 CHECK_ERROR(floppyDrive, COMSETTER(Enabled)(true));
4542
4543 /* unmount? */
4544 if (strcmp(floppy, "empty") == 0)
4545 {
4546 CHECK_ERROR(floppyDrive, Unmount());
4547 }
4548 /* host drive? */
4549 else if (strncmp(floppy, "host:", 5) == 0)
4550 {
4551 ComPtr<IHost> host;
4552 CHECK_ERROR(virtualBox, COMGETTER(Host)(host.asOutParam()));
4553 ComPtr<IHostFloppyDriveCollection> hostFloppies;
4554 CHECK_ERROR(host, COMGETTER(FloppyDrives)(hostFloppies.asOutParam()));
4555 ComPtr<IHostFloppyDrive> hostFloppyDrive;
4556 rc = hostFloppies->FindByName(Bstr(floppy + 5), hostFloppyDrive.asOutParam());
4557 if (!hostFloppyDrive)
4558 {
4559 errorArgument("Invalid host floppy drive name");
4560 rc = E_FAIL;
4561 break;
4562 }
4563 CHECK_ERROR(floppyDrive, CaptureHostDrive(hostFloppyDrive));
4564 }
4565 else
4566 {
4567 /* first assume it's a UUID */
4568 Guid uuid(floppy);
4569 ComPtr<IFloppyImage> floppyImage;
4570 rc = virtualBox->GetFloppyImage(uuid, floppyImage.asOutParam());
4571 if (FAILED(rc) || !floppyImage)
4572 {
4573 /* must be a filename */
4574 Guid emptyUUID;
4575 CHECK_ERROR(virtualBox, OpenFloppyImage(Bstr(floppy), emptyUUID, floppyImage.asOutParam()));
4576 if (SUCCEEDED(rc) && floppyImage)
4577 {
4578 /** @todo first iterate through the collection and try to find the image */
4579 /* time to register the image */
4580 CHECK_ERROR(virtualBox, RegisterFloppyImage(floppyImage));
4581 }
4582 }
4583 if (!floppyImage)
4584 {
4585 rc = E_FAIL;
4586 break;
4587 }
4588
4589 floppyImage->COMGETTER(Id)(uuid.asOutParam());
4590 CHECK_ERROR(floppyDrive, MountImage(uuid));
4591 }
4592 }
4593 }
4594 if (audio)
4595 {
4596 ComPtr<IAudioAdapter> audioAdapter;
4597 machine->COMGETTER(AudioAdapter)(audioAdapter.asOutParam());
4598 ASSERT(audioAdapter);
4599
4600 /* disable? */
4601 if (strcmp(audio, "none") == 0)
4602 {
4603 CHECK_ERROR(audioAdapter, COMSETTER(Enabled)(false));
4604 }
4605 else if (strcmp(audio, "null") == 0)
4606 {
4607 CHECK_ERROR(audioAdapter, COMSETTER(AudioDriver)(AudioDriverType_NullAudioDriver));
4608 CHECK_ERROR(audioAdapter, COMSETTER(Enabled)(true));
4609 }
4610#ifdef RT_OS_WINDOWS
4611#ifdef VBOX_WITH_WINMM
4612 else if (strcmp(audio, "winmm") == 0)
4613 {
4614 CHECK_ERROR(audioAdapter, COMSETTER(AudioDriver)(AudioDriverType_WINMMAudioDriver));
4615 CHECK_ERROR(audioAdapter, COMSETTER(Enabled)(true));
4616 }
4617#endif
4618 else if (strcmp(audio, "dsound") == 0)
4619 {
4620 CHECK_ERROR(audioAdapter, COMSETTER(AudioDriver)(AudioDriverType_DSOUNDAudioDriver));
4621 CHECK_ERROR(audioAdapter, COMSETTER(Enabled)(true));
4622 }
4623#endif /* RT_OS_WINDOWS */
4624#ifdef RT_OS_LINUX
4625 else if (strcmp(audio, "oss") == 0)
4626 {
4627 CHECK_ERROR(audioAdapter, COMSETTER(AudioDriver)(AudioDriverType_OSSAudioDriver));
4628 CHECK_ERROR(audioAdapter, COMSETTER(Enabled)(true));
4629 }
4630# ifdef VBOX_WITH_ALSA
4631 else if (strcmp(audio, "alsa") == 0)
4632 {
4633 CHECK_ERROR(audioAdapter, COMSETTER(AudioDriver)(AudioDriverType_ALSAAudioDriver));
4634 CHECK_ERROR(audioAdapter, COMSETTER(Enabled)(true));
4635 }
4636# endif
4637#endif /* !RT_OS_LINUX */
4638#ifdef RT_OS_DARWIN
4639 else if (strcmp(audio, "coreaudio") == 0)
4640 {
4641 CHECK_ERROR(audioAdapter, COMSETTER(AudioDriver)(AudioDriverType_CoreAudioDriver));
4642 CHECK_ERROR(audioAdapter, COMSETTER(Enabled)(true));
4643 }
4644#endif /* !RT_OS_DARWIN */
4645 else
4646 {
4647 errorArgument("Invalid -audio argument '%s'", audio);
4648 rc = E_FAIL;
4649 break;
4650 }
4651 }
4652 /* Shared clipboard state */
4653 if (clipboard)
4654 {
4655/* ComPtr<IClipboardMode> clipboardMode;
4656 machine->COMGETTER(ClipboardMode)(clipboardMode.asOutParam());
4657 ASSERT(clipboardMode);
4658*/
4659 if (strcmp(clipboard, "disabled") == 0)
4660 {
4661 CHECK_ERROR(machine, COMSETTER(ClipboardMode)(ClipboardMode_ClipDisabled));
4662 }
4663 else if (strcmp(clipboard, "hosttoguest") == 0)
4664 {
4665 CHECK_ERROR(machine, COMSETTER(ClipboardMode)(ClipboardMode_ClipHostToGuest));
4666 }
4667 else if (strcmp(clipboard, "guesttohost") == 0)
4668 {
4669 CHECK_ERROR(machine, COMSETTER(ClipboardMode)(ClipboardMode_ClipGuestToHost));
4670 }
4671 else if (strcmp(clipboard, "bidirectional") == 0)
4672 {
4673 CHECK_ERROR(machine, COMSETTER(ClipboardMode)(ClipboardMode_ClipBidirectional));
4674 }
4675 else
4676 {
4677 errorArgument("Invalid -clipboard argument '%s'", clipboard);
4678 rc = E_FAIL;
4679 break;
4680 }
4681 }
4682 /* iterate through all possible NICs */
4683 for (ULONG n = 0; n < NetworkAdapterCount; n ++)
4684 {
4685 ComPtr<INetworkAdapter> nic;
4686 CHECK_ERROR_RET (machine, GetNetworkAdapter (n, nic.asOutParam()), 1);
4687
4688 ASSERT(nic);
4689
4690 /* something about the NIC? */
4691 if (nics[n])
4692 {
4693 if (strcmp(nics[n], "none") == 0)
4694 {
4695 CHECK_ERROR_RET(nic, COMSETTER(Enabled) (FALSE), 1);
4696 }
4697 else if (strcmp(nics[n], "null") == 0)
4698 {
4699 CHECK_ERROR_RET(nic, COMSETTER(Enabled) (TRUE), 1);
4700 CHECK_ERROR_RET(nic, Detach(), 1);
4701 }
4702 else if (strcmp(nics[n], "nat") == 0)
4703 {
4704 CHECK_ERROR_RET(nic, COMSETTER(Enabled) (TRUE), 1);
4705 CHECK_ERROR_RET(nic, AttachToNAT(), 1);
4706 }
4707 else if (strcmp(nics[n], "hostif") == 0)
4708 {
4709 CHECK_ERROR_RET(nic, COMSETTER(Enabled) (TRUE), 1);
4710 CHECK_ERROR_RET(nic, AttachToHostInterface(), 1);
4711 }
4712 else if (strcmp(nics[n], "intnet") == 0)
4713 {
4714 CHECK_ERROR_RET(nic, COMSETTER(Enabled) (TRUE), 1);
4715 CHECK_ERROR_RET(nic, AttachToInternalNetwork(), 1);
4716 }
4717 else
4718 {
4719 errorArgument("Invalid type '%s' specfied for NIC %lu", nics[n], n + 1);
4720 rc = E_FAIL;
4721 break;
4722 }
4723 }
4724
4725 /* something about the NIC type? */
4726 if (nictype[n])
4727 {
4728 if (strcmp(nictype[n], "Am79C970A") == 0)
4729 {
4730 CHECK_ERROR_RET(nic, COMSETTER(AdapterType)(NetworkAdapterType_NetworkAdapterAm79C970A), 1);
4731 }
4732 else if (strcmp(nictype[n], "Am79C973") == 0)
4733 {
4734 CHECK_ERROR_RET(nic, COMSETTER(AdapterType)(NetworkAdapterType_NetworkAdapterAm79C973), 1);
4735 }
4736 else
4737 {
4738 errorArgument("Invalid NIC type '%s' specified for NIC %lu", nictype[n], n + 1);
4739 rc = E_FAIL;
4740 break;
4741 }
4742 }
4743
4744 /* something about the MAC address? */
4745 if (macs[n])
4746 {
4747 /* generate one? */
4748 if (strcmp(macs[n], "auto") == 0)
4749 {
4750 CHECK_ERROR_RET(nic, COMSETTER(MACAddress)(NULL), 1);
4751 }
4752 else
4753 {
4754 CHECK_ERROR_RET(nic, COMSETTER(MACAddress)(Bstr(macs[n])), 1);
4755 }
4756 }
4757
4758 /* something about the reported link speed? */
4759 if (nicspeed[n])
4760 {
4761 uint32_t u32LineSpeed;
4762
4763 u32LineSpeed = atoi(nicspeed[n]);
4764
4765 if (u32LineSpeed < 1000 || u32LineSpeed > 4000000)
4766 {
4767 errorArgument("Invalid -nicspeed%lu argument '%s'", n + 1, nicspeed[n]);
4768 rc = E_FAIL;
4769 break;
4770 }
4771 else
4772 {
4773 CHECK_ERROR_RET(nic, COMSETTER(LineSpeed)(u32LineSpeed), 1);
4774 }
4775 }
4776
4777 /* the link status flag? */
4778 if (cableconnected[n])
4779 {
4780 if (strcmp(cableconnected[n], "on") == 0)
4781 {
4782 CHECK_ERROR_RET(nic, COMSETTER(CableConnected)(TRUE), 1);
4783 }
4784 else if (strcmp(cableconnected[n], "off") == 0)
4785 {
4786 CHECK_ERROR_RET(nic, COMSETTER(CableConnected)(FALSE), 1);
4787 }
4788 else
4789 {
4790 errorArgument("Invalid -cableconnected%lu argument '%s'", n + 1, cableconnected[n]);
4791 rc = E_FAIL;
4792 break;
4793 }
4794 }
4795
4796 /* the trace flag? */
4797 if (nictrace[n])
4798 {
4799 if (strcmp(nictrace[n], "on") == 0)
4800 {
4801 CHECK_ERROR_RET(nic, COMSETTER(TraceEnabled)(TRUE), 1);
4802 }
4803 else if (strcmp(nictrace[n], "off") == 0)
4804 {
4805 CHECK_ERROR_RET(nic, COMSETTER(TraceEnabled)(FALSE), 1);
4806 }
4807 else
4808 {
4809 errorArgument("Invalid -nictrace%lu argument '%s'", n + 1, nictrace[n]);
4810 rc = E_FAIL;
4811 break;
4812 }
4813 }
4814
4815 /* the tracefile flag? */
4816 if (nictracefile[n])
4817 {
4818 CHECK_ERROR_RET(nic, COMSETTER(TraceFile)(Bstr(nictracefile[n])), 1);
4819 }
4820
4821 /* the host interface device? */
4822 if (hostifdev[n])
4823 {
4824 /* remove it? */
4825 if (strcmp(hostifdev[n], "none") == 0)
4826 {
4827 CHECK_ERROR_RET(nic, COMSETTER(HostInterface)(NULL), 1);
4828 }
4829 else
4830 {
4831 CHECK_ERROR_RET(nic, COMSETTER(HostInterface)(Bstr(hostifdev[n])), 1);
4832 }
4833 }
4834
4835 /* the internal network name? */
4836 if (intnet[n])
4837 {
4838 /* remove it? */
4839 if (strcmp(intnet[n], "none") == 0)
4840 {
4841 CHECK_ERROR_RET(nic, COMSETTER(InternalNetwork)(NULL), 1);
4842 }
4843 else
4844 {
4845 CHECK_ERROR_RET(nic, COMSETTER(InternalNetwork)(Bstr(intnet[n])), 1);
4846 }
4847 }
4848
4849#ifdef RT_OS_LINUX
4850 /* the TAP setup application? */
4851 if (tapsetup[n])
4852 {
4853 /* remove it? */
4854 if (strcmp(tapsetup[n], "none") == 0)
4855 {
4856 CHECK_ERROR_RET(nic, COMSETTER(TAPSetupApplication)(NULL), 1);
4857 }
4858 else
4859 {
4860 CHECK_ERROR_RET(nic, COMSETTER(TAPSetupApplication)(Bstr(tapsetup[n])), 1);
4861 }
4862 }
4863
4864 /* the TAP terminate application? */
4865 if (tapterm[n])
4866 {
4867 /* remove it? */
4868 if (strcmp(tapterm[n], "none") == 0)
4869 {
4870 CHECK_ERROR_RET(nic, COMSETTER(TAPTerminateApplication)(NULL), 1);
4871 }
4872 else
4873 {
4874 CHECK_ERROR_RET(nic, COMSETTER(TAPTerminateApplication)(Bstr(tapterm[n])), 1);
4875 }
4876 }
4877#endif /* RT_OS_LINUX */
4878
4879 }
4880 if (FAILED(rc))
4881 break;
4882
4883 /* iterate through all possible serial ports */
4884 for (ULONG n = 0; n < SerialPortCount; n ++)
4885 {
4886 ComPtr<ISerialPort> uart;
4887 CHECK_ERROR_RET (machine, GetSerialPort (n, uart.asOutParam()), 1);
4888
4889 ASSERT(uart);
4890
4891 if (uarts_base[n])
4892 {
4893 if (uarts_base[n] == (ULONG)-1)
4894 {
4895 CHECK_ERROR_RET(uart, COMSETTER(Enabled) (FALSE), 1);
4896 }
4897 else
4898 {
4899 CHECK_ERROR_RET(uart, COMSETTER(IOBase) (uarts_base[n]), 1);
4900 CHECK_ERROR_RET(uart, COMSETTER(IRQ) (uarts_irq[n]), 1);
4901 CHECK_ERROR_RET(uart, COMSETTER(Enabled) (TRUE), 1);
4902 }
4903 }
4904 if (uarts_mode[n])
4905 {
4906 if (strcmp(uarts_mode[n], "disconnected") == 0)
4907 {
4908 CHECK_ERROR_RET(uart, COMSETTER(HostMode) (PortMode_DisconnectedPort), 1);
4909 }
4910 else
4911 {
4912 if (strcmp(uarts_mode[n], "server") == 0)
4913 {
4914 CHECK_ERROR_RET(uart, COMSETTER(HostMode) (PortMode_HostPipePort), 1);
4915 CHECK_ERROR_RET(uart, COMSETTER(Server) (TRUE), 1);
4916 }
4917 else if (strcmp(uarts_mode[n], "client") == 0)
4918 {
4919 CHECK_ERROR_RET(uart, COMSETTER(HostMode) (PortMode_HostPipePort), 1);
4920 CHECK_ERROR_RET(uart, COMSETTER(Server) (FALSE), 1);
4921 }
4922 else
4923 {
4924 CHECK_ERROR_RET(uart, COMSETTER(HostMode) (PortMode_HostDevicePort), 1);
4925 }
4926 CHECK_ERROR_RET(uart, COMSETTER(Path) (Bstr(uarts_path[n])), 1);
4927 }
4928 }
4929 }
4930 if (FAILED(rc))
4931 break;
4932
4933#ifdef VBOX_VRDP
4934 if (vrdp || (vrdpport != UINT16_MAX) || vrdpaddress || vrdpauthtype || vrdpmulticon)
4935 {
4936 ComPtr<IVRDPServer> vrdpServer;
4937 machine->COMGETTER(VRDPServer)(vrdpServer.asOutParam());
4938 ASSERT(vrdpServer);
4939 if (vrdpServer)
4940 {
4941 if (vrdp)
4942 {
4943 if (strcmp(vrdp, "on") == 0)
4944 {
4945 CHECK_ERROR(vrdpServer, COMSETTER(Enabled)(true));
4946 }
4947 else if (strcmp(vrdp, "off") == 0)
4948 {
4949 CHECK_ERROR(vrdpServer, COMSETTER(Enabled)(false));
4950 }
4951 else
4952 {
4953 errorArgument("Invalid -vrdp argument '%s'", vrdp);
4954 rc = E_FAIL;
4955 break;
4956 }
4957 }
4958 if (vrdpport != UINT16_MAX)
4959 {
4960 CHECK_ERROR(vrdpServer, COMSETTER(Port)(vrdpport));
4961 }
4962 if (vrdpaddress)
4963 {
4964 CHECK_ERROR(vrdpServer, COMSETTER(NetAddress)(Bstr(vrdpaddress)));
4965 }
4966 if (vrdpauthtype)
4967 {
4968 if (strcmp(vrdpauthtype, "null") == 0)
4969 {
4970 CHECK_ERROR(vrdpServer, COMSETTER(AuthType)(VRDPAuthType_VRDPAuthNull));
4971 }
4972 else if (strcmp(vrdpauthtype, "external") == 0)
4973 {
4974 CHECK_ERROR(vrdpServer, COMSETTER(AuthType)(VRDPAuthType_VRDPAuthExternal));
4975 }
4976 else if (strcmp(vrdpauthtype, "guest") == 0)
4977 {
4978 CHECK_ERROR(vrdpServer, COMSETTER(AuthType)(VRDPAuthType_VRDPAuthGuest));
4979 }
4980 else
4981 {
4982 errorArgument("Invalid -vrdpauthtype argument '%s'", vrdpauthtype);
4983 rc = E_FAIL;
4984 break;
4985 }
4986 }
4987 if (vrdpmulticon)
4988 {
4989 if (strcmp(vrdpmulticon, "on") == 0)
4990 {
4991 CHECK_ERROR(vrdpServer, COMSETTER(AllowMultiConnection)(true));
4992 }
4993 else if (strcmp(vrdpmulticon, "off") == 0)
4994 {
4995 CHECK_ERROR(vrdpServer, COMSETTER(AllowMultiConnection)(false));
4996 }
4997 else
4998 {
4999 errorArgument("Invalid -vrdpmulticon argument '%s'", vrdpmulticon);
5000 rc = E_FAIL;
5001 break;
5002 }
5003 }
5004 }
5005 }
5006#endif /* VBOX_VRDP */
5007
5008 /*
5009 * USB enable/disable
5010 */
5011 if (fUsbEnabled != -1)
5012 {
5013 ComPtr<IUSBController> UsbCtl;
5014 CHECK_ERROR(machine, COMGETTER(USBController)(UsbCtl.asOutParam()));
5015 if (SUCCEEDED(rc))
5016 {
5017 CHECK_ERROR(UsbCtl, COMSETTER(Enabled)(!!fUsbEnabled));
5018 }
5019 }
5020
5021 if (snapshotFolder)
5022 {
5023 if (strcmp(snapshotFolder, "default") == 0)
5024 {
5025 CHECK_ERROR(machine, COMSETTER(SnapshotFolder)(NULL));
5026 }
5027 else
5028 {
5029 CHECK_ERROR(machine, COMSETTER(SnapshotFolder)(Bstr(snapshotFolder)));
5030 }
5031 }
5032
5033 if (guestMemBalloonSize != (ULONG)-1)
5034 CHECK_ERROR(machine, COMSETTER(MemoryBalloonSize)(guestMemBalloonSize));
5035
5036 if (guestStatInterval != (ULONG)-1)
5037 CHECK_ERROR(machine, COMSETTER(StatisticsUpdateInterval)(guestStatInterval));
5038
5039 /* commit changes */
5040 CHECK_ERROR(machine, SaveSettings());
5041 } while (0);
5042
5043 /* it's important to always close sessions */
5044 session->Close();
5045
5046 return SUCCEEDED(rc) ? 0 : 1;
5047}
5048
5049static int handleStartVM(int argc, char *argv[],
5050 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)
5051{
5052 HRESULT rc;
5053
5054 if (argc < 1)
5055 {
5056 return errorSyntax(USAGE_STARTVM, "Not enough parameters");
5057 }
5058
5059 ComPtr<IMachine> machine;
5060 /* assume it's a UUID */
5061 rc = virtualBox->GetMachine(Guid(argv[0]), machine.asOutParam());
5062 if (FAILED(rc) || !machine)
5063 {
5064 /* must be a name */
5065 CHECK_ERROR(virtualBox, FindMachine(Bstr(argv[0]), machine.asOutParam()));
5066 }
5067 if (machine)
5068 {
5069 Guid uuid;
5070 machine->COMGETTER(Id)(uuid.asOutParam());
5071
5072 /* default to GUI session type */
5073 Bstr sessionType = "gui";
5074 /* has a session type been specified? */
5075 if ((argc > 2) && (strcmp(argv[1], "-type") == 0))
5076 {
5077 if (strcmp(argv[2], "gui") == 0)
5078 {
5079 sessionType = "gui";
5080 }
5081 else if (strcmp(argv[2], "vrdp") == 0)
5082 {
5083 sessionType = "vrdp";
5084 }
5085 else if (strcmp(argv[2], "capture") == 0)
5086 {
5087 sessionType = "capture";
5088 }
5089 else
5090 {
5091 return errorArgument("Invalid session type argument '%s'", argv[2]);
5092 }
5093 }
5094
5095 Bstr env;
5096#ifdef RT_OS_LINUX
5097 /* make sure the VM process will start on the same display as VBoxManage */
5098 {
5099 const char *display = RTEnvGet ("DISPLAY");
5100 if (display)
5101 env = Utf8StrFmt ("DISPLAY=%s", display);
5102 }
5103#endif
5104 ComPtr<IProgress> progress;
5105 CHECK_ERROR_RET(virtualBox, OpenRemoteSession(session, uuid, sessionType,
5106 env, progress.asOutParam()), rc);
5107 RTPrintf("Waiting for the remote session to open...\n");
5108 CHECK_ERROR_RET(progress, WaitForCompletion (-1), 1);
5109
5110 BOOL completed;
5111 CHECK_ERROR_RET(progress, COMGETTER(Completed)(&completed), rc);
5112 ASSERT(completed);
5113
5114 HRESULT resultCode;
5115 CHECK_ERROR_RET(progress, COMGETTER(ResultCode)(&resultCode), rc);
5116 if (FAILED(resultCode))
5117 {
5118 ComPtr <IVirtualBoxErrorInfo> errorInfo;
5119 CHECK_ERROR_RET(progress, COMGETTER(ErrorInfo)(errorInfo.asOutParam()), 1);
5120 ErrorInfo info (errorInfo);
5121 PRINT_ERROR_INFO(info);
5122 }
5123 else
5124 {
5125 RTPrintf("Remote session has been successfully opened.\n");
5126 }
5127 }
5128
5129 /* it's important to always close sessions */
5130 session->Close();
5131
5132 return SUCCEEDED(rc) ? 0 : 1;
5133}
5134
5135static int handleControlVM(int argc, char *argv[],
5136 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)
5137{
5138 HRESULT rc;
5139
5140 if (argc < 2)
5141 {
5142 return errorSyntax(USAGE_CONTROLVM, "Not enough parameters");
5143 }
5144
5145 /* try to find the given machine */
5146 ComPtr <IMachine> machine;
5147 Guid uuid (argv[0]);
5148 if (!uuid.isEmpty())
5149 {
5150 CHECK_ERROR (virtualBox, GetMachine (uuid, machine.asOutParam()));
5151 }
5152 else
5153 {
5154 CHECK_ERROR (virtualBox, FindMachine (Bstr(argv[0]), machine.asOutParam()));
5155 if (SUCCEEDED (rc))
5156 machine->COMGETTER(Id) (uuid.asOutParam());
5157 }
5158 if (FAILED (rc))
5159 return 1;
5160
5161 /* open a session for the VM */
5162 CHECK_ERROR_RET (virtualBox, OpenExistingSession (session, uuid), 1);
5163
5164 do
5165 {
5166 /* get the associated console */
5167 ComPtr<IConsole> console;
5168 CHECK_ERROR_BREAK (session, COMGETTER(Console)(console.asOutParam()));
5169 /* ... and session machine */
5170 ComPtr<IMachine> sessionMachine;
5171 CHECK_ERROR_BREAK (session, COMGETTER(Machine)(sessionMachine.asOutParam()));
5172
5173 /* which command? */
5174 if (strcmp(argv[1], "pause") == 0)
5175 {
5176 CHECK_ERROR_BREAK (console, Pause());
5177 }
5178 else if (strcmp(argv[1], "resume") == 0)
5179 {
5180 CHECK_ERROR_BREAK (console, Resume());
5181 }
5182 else if (strcmp(argv[1], "reset") == 0)
5183 {
5184 CHECK_ERROR_BREAK (console, Reset());
5185 }
5186 else if (strcmp(argv[1], "poweroff") == 0)
5187 {
5188 CHECK_ERROR_BREAK (console, PowerDown());
5189 }
5190 else if (strcmp(argv[1], "savestate") == 0)
5191 {
5192 ComPtr<IProgress> progress;
5193 CHECK_ERROR_BREAK (console, SaveState(progress.asOutParam()));
5194
5195 showProgress(progress);
5196
5197 progress->COMGETTER(ResultCode)(&rc);
5198 if (FAILED(rc))
5199 {
5200 com::ProgressErrorInfo info(progress);
5201 if (info.isBasicAvailable())
5202 {
5203 RTPrintf("Error: failed to save machine state. Error message: %lS\n", info.getText().raw());
5204 }
5205 else
5206 {
5207 RTPrintf("Error: failed to save machine state. No error message available!\n");
5208 }
5209 }
5210 }
5211 else if (strcmp(argv[1], "acpipowerbutton") == 0)
5212 {
5213 CHECK_ERROR_BREAK (console, PowerButton());
5214 }
5215 else if (strncmp(argv[1], "setlinkstate", 12) == 0)
5216 {
5217 /* Get the number of network adapters */
5218 ULONG NetworkAdapterCount = 0;
5219 ComPtr <ISystemProperties> info;
5220 CHECK_ERROR_BREAK (virtualBox, COMGETTER(SystemProperties) (info.asOutParam()));
5221 CHECK_ERROR_BREAK (info, COMGETTER(NetworkAdapterCount) (&NetworkAdapterCount));
5222
5223 unsigned n = parseNum(&argv[1][12], NetworkAdapterCount, "NIC");
5224 if (!n)
5225 {
5226 rc = E_FAIL;
5227 break;
5228 }
5229 if (argc <= 1 + 1)
5230 {
5231 errorArgument("Missing argument to '%s'", argv[1]);
5232 rc = E_FAIL;
5233 break;
5234 }
5235 /* get the corresponding network adapter */
5236 ComPtr<INetworkAdapter> adapter;
5237 CHECK_ERROR_BREAK (sessionMachine, GetNetworkAdapter(n - 1, adapter.asOutParam()));
5238 if (adapter)
5239 {
5240 if (strcmp(argv[2], "on") == 0)
5241 {
5242 CHECK_ERROR_BREAK (adapter, COMSETTER(CableConnected)(TRUE));
5243 }
5244 else if (strcmp(argv[2], "off") == 0)
5245 {
5246 CHECK_ERROR_BREAK (adapter, COMSETTER(CableConnected)(FALSE));
5247 }
5248 else
5249 {
5250 errorArgument("Invalid link state '%s'", Utf8Str(argv[2]).raw());
5251 rc = E_FAIL;
5252 break;
5253 }
5254 }
5255 }
5256 else if (strcmp (argv[1], "usbattach") == 0 ||
5257 strcmp (argv[1], "usbdetach") == 0)
5258 {
5259 if (argc < 3)
5260 {
5261 errorSyntax(USAGE_CONTROLVM, "Not enough parameters");
5262 rc = E_FAIL;
5263 break;
5264 }
5265
5266 bool attach = strcmp (argv[1], "usbattach") == 0;
5267
5268 Guid usbId = argv [2];
5269 if (usbId.isEmpty())
5270 {
5271 // assume address
5272 if (attach)
5273 {
5274 ComPtr <IHost> host;
5275 CHECK_ERROR_BREAK (virtualBox, COMGETTER(Host) (host.asOutParam()));
5276 ComPtr <IHostUSBDeviceCollection> coll;
5277 CHECK_ERROR_BREAK (host, COMGETTER(USBDevices) (coll.asOutParam()));
5278 ComPtr <IHostUSBDevice> dev;
5279 CHECK_ERROR_BREAK (coll, FindByAddress (Bstr (argv [2]), dev.asOutParam()));
5280 CHECK_ERROR_BREAK (dev, COMGETTER(Id) (usbId.asOutParam()));
5281 }
5282 else
5283 {
5284 ComPtr <IUSBDeviceCollection> coll;
5285 CHECK_ERROR_BREAK (console, COMGETTER(USBDevices)(coll.asOutParam()));
5286 ComPtr <IUSBDevice> dev;
5287 CHECK_ERROR_BREAK (coll, FindByAddress (Bstr (argv [2]), dev.asOutParam()));
5288 CHECK_ERROR_BREAK (dev, COMGETTER(Id) (usbId.asOutParam()));
5289 }
5290 }
5291
5292 if (attach)
5293 CHECK_ERROR_BREAK (console, AttachUSBDevice (usbId));
5294 else
5295 {
5296 ComPtr <IUSBDevice> dev;
5297 CHECK_ERROR_BREAK (console, DetachUSBDevice (usbId, dev.asOutParam()));
5298 }
5299 }
5300 else if (strcmp(argv[1], "setvideomodehint") == 0)
5301 {
5302 if (argc != 5 && argc != 6)
5303 {
5304 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
5305 rc = E_FAIL;
5306 break;
5307 }
5308 uint32_t xres = atoi(argv[2]);
5309 uint32_t yres = atoi(argv[3]);
5310 uint32_t bpp = atoi(argv[4]);
5311 uint32_t displayIdx = 0;
5312 if (argc == 6)
5313 displayIdx = atoi(argv[5]);
5314
5315 ComPtr<IDisplay> display;
5316 CHECK_ERROR_BREAK(console, COMGETTER(Display)(display.asOutParam()));
5317 CHECK_ERROR_BREAK(display, SetVideoModeHint(xres, yres, bpp, displayIdx));
5318 }
5319 else if (strcmp(argv[1], "setcredentials") == 0)
5320 {
5321 bool fAllowLocalLogon = true;
5322 if (argc == 7)
5323 {
5324 if (strcmp(argv[5], "-allowlocallogon") != 0)
5325 {
5326 errorArgument("Invalid parameter '%s'", argv[5]);
5327 rc = E_FAIL;
5328 break;
5329 }
5330 if (strcmp(argv[6], "no") == 0)
5331 fAllowLocalLogon = false;
5332 }
5333 else if (argc != 5)
5334 {
5335 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
5336 rc = E_FAIL;
5337 break;
5338 }
5339
5340 ComPtr<IGuest> guest;
5341 CHECK_ERROR_BREAK(console, COMGETTER(Guest)(guest.asOutParam()));
5342 CHECK_ERROR_BREAK(guest, SetCredentials(Bstr(argv[2]), Bstr(argv[3]), Bstr(argv[4]), fAllowLocalLogon));
5343 }
5344 else if (strcmp(argv[1], "dvdattach") == 0)
5345 {
5346 if (argc != 3)
5347 {
5348 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
5349 rc = E_FAIL;
5350 break;
5351 }
5352 ComPtr<IDVDDrive> dvdDrive;
5353 sessionMachine->COMGETTER(DVDDrive)(dvdDrive.asOutParam());
5354 ASSERT(dvdDrive);
5355
5356 /* unmount? */
5357 if (strcmp(argv[2], "none") == 0)
5358 {
5359 CHECK_ERROR(dvdDrive, Unmount());
5360 }
5361 /* host drive? */
5362 else if (strncmp(argv[2], "host:", 5) == 0)
5363 {
5364 ComPtr<IHost> host;
5365 CHECK_ERROR(virtualBox, COMGETTER(Host)(host.asOutParam()));
5366 ComPtr<IHostDVDDriveCollection> hostDVDs;
5367 CHECK_ERROR(host, COMGETTER(DVDDrives)(hostDVDs.asOutParam()));
5368 ComPtr<IHostDVDDrive> hostDVDDrive;
5369 rc = hostDVDs->FindByName(Bstr(argv[2] + 5), hostDVDDrive.asOutParam());
5370 if (!hostDVDDrive)
5371 {
5372 errorArgument("Invalid host DVD drive name");
5373 rc = E_FAIL;
5374 break;
5375 }
5376 CHECK_ERROR(dvdDrive, CaptureHostDrive(hostDVDDrive));
5377 }
5378 else
5379 {
5380 /* first assume it's a UUID */
5381 Guid uuid(argv[2]);
5382 ComPtr<IDVDImage> dvdImage;
5383 rc = virtualBox->GetDVDImage(uuid, dvdImage.asOutParam());
5384 if (FAILED(rc) || !dvdImage)
5385 {
5386 /* must be a filename, check if it's in the collection */
5387 ComPtr<IDVDImageCollection> dvdImages;
5388 virtualBox->COMGETTER(DVDImages)(dvdImages.asOutParam());
5389 rc = dvdImages->FindByPath(Bstr(argv[2]), dvdImage.asOutParam());
5390 /* not registered, do that on the fly */
5391 if (!dvdImage)
5392 {
5393 Guid emptyUUID;
5394 CHECK_ERROR(virtualBox, OpenDVDImage(Bstr(argv[2]), emptyUUID, dvdImage.asOutParam()));
5395 if (SUCCEEDED(rc) && dvdImage)
5396 {
5397 /* time to register the image */
5398 CHECK_ERROR(virtualBox, RegisterDVDImage(dvdImage));
5399 }
5400 }
5401 }
5402 if (!dvdImage)
5403 {
5404 rc = E_FAIL;
5405 break;
5406 }
5407 dvdImage->COMGETTER(Id)(uuid.asOutParam());
5408 CHECK_ERROR(dvdDrive, MountImage(uuid));
5409 }
5410 }
5411 else if (strcmp(argv[1], "floppyattach") == 0)
5412 {
5413 if (argc != 3)
5414 {
5415 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
5416 rc = E_FAIL;
5417 break;
5418 }
5419
5420 ComPtr<IFloppyDrive> floppyDrive;
5421 sessionMachine->COMGETTER(FloppyDrive)(floppyDrive.asOutParam());
5422 ASSERT(floppyDrive);
5423
5424 /* unmount? */
5425 if (strcmp(argv[2], "none") == 0)
5426 {
5427 CHECK_ERROR(floppyDrive, Unmount());
5428 }
5429 /* host drive? */
5430 else if (strncmp(argv[2], "host:", 5) == 0)
5431 {
5432 ComPtr<IHost> host;
5433 CHECK_ERROR(virtualBox, COMGETTER(Host)(host.asOutParam()));
5434 ComPtr<IHostFloppyDriveCollection> hostFloppies;
5435 CHECK_ERROR(host, COMGETTER(FloppyDrives)(hostFloppies.asOutParam()));
5436 ComPtr<IHostFloppyDrive> hostFloppyDrive;
5437 rc = hostFloppies->FindByName(Bstr(argv[2] + 5), hostFloppyDrive.asOutParam());
5438 if (!hostFloppyDrive)
5439 {
5440 errorArgument("Invalid host floppy drive name");
5441 rc = E_FAIL;
5442 break;
5443 }
5444 CHECK_ERROR(floppyDrive, CaptureHostDrive(hostFloppyDrive));
5445 }
5446 else
5447 {
5448 /* first assume it's a UUID */
5449 Guid uuid(argv[2]);
5450 ComPtr<IFloppyImage> floppyImage;
5451 rc = virtualBox->GetFloppyImage(uuid, floppyImage.asOutParam());
5452 if (FAILED(rc) || !floppyImage)
5453 {
5454 /* must be a filename */
5455 Guid emptyUUID;
5456 CHECK_ERROR(virtualBox, OpenFloppyImage(Bstr(argv[2]), emptyUUID, floppyImage.asOutParam()));
5457 if (SUCCEEDED(rc) && floppyImage)
5458 {
5459 /** @todo first iterate through the collection and try to find the image */
5460 /* time to register the image */
5461 CHECK_ERROR(virtualBox, RegisterFloppyImage(floppyImage));
5462 }
5463 }
5464 if (!floppyImage)
5465 {
5466 rc = E_FAIL;
5467 break;
5468 }
5469 floppyImage->COMGETTER(Id)(uuid.asOutParam());
5470 CHECK_ERROR(floppyDrive, MountImage(uuid));
5471 }
5472 }
5473 else if (strncmp(argv[1], "-guestmemoryballoon", 19) == 0)
5474 {
5475 if (argc != 3)
5476 {
5477 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
5478 rc = E_FAIL;
5479 break;
5480 }
5481 uint32_t uVal;
5482 int vrc;
5483 vrc = RTStrToUInt32Ex(argv[2], NULL, 0, &uVal);
5484 if (vrc != VINF_SUCCESS)
5485 {
5486 errorArgument("Error parsing guest memory balloon size '%s'", argv[2]);
5487 rc = E_FAIL;
5488 break;
5489 }
5490
5491 /* guest is running; update IGuest */
5492 ComPtr <IGuest> guest;
5493
5494 rc = console->COMGETTER(Guest)(guest.asOutParam());
5495 if (SUCCEEDED(rc))
5496 CHECK_ERROR(guest, COMSETTER(MemoryBalloonSize)(uVal));
5497 }
5498 else if (strncmp(argv[1], "-gueststatisticsinterval", 24) == 0)
5499 {
5500 if (argc != 3)
5501 {
5502 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
5503 rc = E_FAIL;
5504 break;
5505 }
5506 uint32_t uVal;
5507 int vrc;
5508 vrc = RTStrToUInt32Ex(argv[2], NULL, 0, &uVal);
5509 if (vrc != VINF_SUCCESS)
5510 {
5511 errorArgument("Error parsing guest memory balloon size '%s'", argv[2]);
5512 rc = E_FAIL;
5513 break;
5514 }
5515
5516 /* guest is running; update IGuest */
5517 ComPtr <IGuest> guest;
5518
5519 rc = console->COMGETTER(Guest)(guest.asOutParam());
5520 if (SUCCEEDED(rc))
5521 CHECK_ERROR(guest, COMSETTER(StatisticsUpdateInterval)(uVal));
5522 }
5523 else
5524 {
5525 errorSyntax(USAGE_CONTROLVM, "Invalid parameter '%s'", Utf8Str(argv[1]).raw());
5526 rc = E_FAIL;
5527 }
5528 }
5529 while (0);
5530
5531 session->Close();
5532
5533 return SUCCEEDED (rc) ? 0 : 1;
5534}
5535
5536static int handleDiscardState(int argc, char *argv[],
5537 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)
5538{
5539 HRESULT rc;
5540
5541 if (argc != 1)
5542 {
5543 return errorSyntax(USAGE_DISCARDSTATE, "Incorrect number of parameters");
5544 }
5545
5546 ComPtr<IMachine> machine;
5547 /* assume it's a UUID */
5548 rc = virtualBox->GetMachine(Guid(argv[0]), machine.asOutParam());
5549 if (FAILED(rc) || !machine)
5550 {
5551 /* must be a name */
5552 CHECK_ERROR(virtualBox, FindMachine(Bstr(argv[0]), machine.asOutParam()));
5553 }
5554 if (machine)
5555 {
5556 do
5557 {
5558 /* we have to open a session for this task */
5559 Guid guid;
5560 machine->COMGETTER(Id)(guid.asOutParam());
5561 CHECK_ERROR_BREAK(virtualBox, OpenSession(session, guid));
5562 ComPtr<IConsole> console;
5563 CHECK_ERROR_BREAK(session, COMGETTER(Console)(console.asOutParam()));
5564 CHECK_ERROR_BREAK(console, DiscardSavedState());
5565 CHECK_ERROR_BREAK(session, Close());
5566 } while (0);
5567 }
5568
5569 return SUCCEEDED(rc) ? 0 : 1;
5570}
5571
5572static int handleSnapshot(int argc, char *argv[],
5573 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)
5574{
5575 HRESULT rc;
5576
5577 /* we need at least a VM and a command */
5578 if (argc < 2)
5579 {
5580 return errorSyntax(USAGE_SNAPSHOT, "Not enough parameters");
5581 }
5582
5583 /* the first argument must be the VM */
5584 ComPtr<IMachine> machine;
5585 /* assume it's a UUID */
5586 rc = virtualBox->GetMachine(Guid(argv[0]), machine.asOutParam());
5587 if (FAILED(rc) || !machine)
5588 {
5589 /* must be a name */
5590 CHECK_ERROR(virtualBox, FindMachine(Bstr(argv[0]), machine.asOutParam()));
5591 }
5592 if (!machine)
5593 return 1;
5594 Guid guid;
5595 machine->COMGETTER(Id)(guid.asOutParam());
5596
5597 do
5598 {
5599 /* we have to open a session for this task. First try an existing session */
5600 rc = virtualBox->OpenExistingSession(session, guid);
5601 if (FAILED(rc))
5602 CHECK_ERROR_BREAK(virtualBox, OpenSession(session, guid));
5603 ComPtr<IConsole> console;
5604 CHECK_ERROR_BREAK(session, COMGETTER(Console)(console.asOutParam()));
5605
5606 /* switch based on the command */
5607 if (strcmp(argv[1], "take") == 0)
5608 {
5609 /* there must be a name */
5610 if (argc < 3)
5611 {
5612 errorSyntax(USAGE_SNAPSHOT, "Missing snapshot name");
5613 rc = E_FAIL;
5614 break;
5615 }
5616 Bstr name(argv[2]);
5617 if ((argc > 3) && ((argc != 5) || (strcmp(argv[3], "-desc") != 0)))
5618 {
5619 errorSyntax(USAGE_SNAPSHOT, "Incorrect description format");
5620 rc = E_FAIL;
5621 break;
5622 }
5623 Bstr desc;
5624 if (argc == 5)
5625 desc = argv[4];
5626 ComPtr<IProgress> progress;
5627 CHECK_ERROR_BREAK(console, TakeSnapshot(name, desc, progress.asOutParam()));
5628
5629 showProgress(progress);
5630 progress->COMGETTER(ResultCode)(&rc);
5631 if (FAILED(rc))
5632 {
5633 com::ProgressErrorInfo info(progress);
5634 if (info.isBasicAvailable())
5635 {
5636 RTPrintf("Error: failed to take snapshot. Error message: %lS\n", info.getText().raw());
5637 }
5638 else
5639 {
5640 RTPrintf("Error: failed to take snapshot. No error message available!\n");
5641 }
5642 }
5643 }
5644 else if (strcmp(argv[1], "discard") == 0)
5645 {
5646 /* exactly one parameter: snapshot name */
5647 if (argc != 3)
5648 {
5649 errorSyntax(USAGE_SNAPSHOT, "Expecting snapshot name only");
5650 rc = E_FAIL;
5651 break;
5652 }
5653
5654 ComPtr<ISnapshot> snapshot;
5655
5656 /* assume it's a UUID */
5657 Guid guid(argv[2]);
5658 if (!guid.isEmpty())
5659 {
5660 CHECK_ERROR_BREAK(machine, GetSnapshot(guid, snapshot.asOutParam()));
5661 }
5662 else
5663 {
5664 /* then it must be a name */
5665 CHECK_ERROR_BREAK(machine, FindSnapshot(Bstr(argv[2]), snapshot.asOutParam()));
5666 }
5667
5668 snapshot->COMGETTER(Id)(guid.asOutParam());
5669
5670 ComPtr<IProgress> progress;
5671 CHECK_ERROR_BREAK(console, DiscardSnapshot(guid, progress.asOutParam()));
5672
5673 showProgress(progress);
5674 progress->COMGETTER(ResultCode)(&rc);
5675 if (FAILED(rc))
5676 {
5677 com::ProgressErrorInfo info(progress);
5678 if (info.isBasicAvailable())
5679 {
5680 RTPrintf("Error: failed to discard snapshot. Error message: %lS\n", info.getText().raw());
5681 }
5682 else
5683 {
5684 RTPrintf("Error: failed to discard snapshot. No error message available!\n");
5685 }
5686 }
5687 }
5688 else if (strcmp(argv[1], "discardcurrent") == 0)
5689 {
5690 if ( (argc != 3)
5691 || ( (strcmp(argv[2], "-state") != 0)
5692 && (strcmp(argv[2], "-all") != 0)))
5693 {
5694 errorSyntax(USAGE_SNAPSHOT, "Invalid parameter '%s'", Utf8Str(argv[2]).raw());
5695 rc = E_FAIL;
5696 break;
5697 }
5698 bool fAll = false;
5699 if (strcmp(argv[2], "-all") == 0)
5700 fAll = true;
5701
5702 ComPtr<IProgress> progress;
5703
5704 if (fAll)
5705 {
5706 CHECK_ERROR_BREAK(console, DiscardCurrentSnapshotAndState(progress.asOutParam()));
5707 }
5708 else
5709 {
5710 CHECK_ERROR_BREAK(console, DiscardCurrentState(progress.asOutParam()));
5711 }
5712
5713 showProgress(progress);
5714 progress->COMGETTER(ResultCode)(&rc);
5715 if (FAILED(rc))
5716 {
5717 com::ProgressErrorInfo info(progress);
5718 if (info.isBasicAvailable())
5719 {
5720 RTPrintf("Error: failed to discard. Error message: %lS\n", info.getText().raw());
5721 }
5722 else
5723 {
5724 RTPrintf("Error: failed to discard. No error message available!\n");
5725 }
5726 }
5727
5728 }
5729 else if (strcmp(argv[1], "edit") == 0)
5730 {
5731 if (argc < 3)
5732 {
5733 errorSyntax(USAGE_SNAPSHOT, "Missing snapshot name");
5734 rc = E_FAIL;
5735 break;
5736 }
5737
5738 ComPtr<ISnapshot> snapshot;
5739
5740 if (strcmp(argv[2], "-current") == 0)
5741 {
5742 CHECK_ERROR_BREAK(machine, COMGETTER(CurrentSnapshot)(snapshot.asOutParam()));
5743 }
5744 else
5745 {
5746 /* assume it's a UUID */
5747 Guid guid(argv[2]);
5748 if (!guid.isEmpty())
5749 {
5750 CHECK_ERROR_BREAK(machine, GetSnapshot(guid, snapshot.asOutParam()));
5751 }
5752 else
5753 {
5754 /* then it must be a name */
5755 CHECK_ERROR_BREAK(machine, FindSnapshot(Bstr(argv[2]), snapshot.asOutParam()));
5756 }
5757 }
5758
5759 /* parse options */
5760 for (int i = 3; i < argc; i++)
5761 {
5762 if (strcmp(argv[i], "-newname") == 0)
5763 {
5764 if (argc <= i + 1)
5765 {
5766 errorArgument("Missing argument to '%s'", argv[i]);
5767 rc = E_FAIL;
5768 break;
5769 }
5770 i++;
5771 snapshot->COMSETTER(Name)(Bstr(argv[i]));
5772 }
5773 else if (strcmp(argv[i], "-newdesc") == 0)
5774 {
5775 if (argc <= i + 1)
5776 {
5777 errorArgument("Missing argument to '%s'", argv[i]);
5778 rc = E_FAIL;
5779 break;
5780 }
5781 i++;
5782 snapshot->COMSETTER(Description)(Bstr(argv[i]));
5783 }
5784 else
5785 {
5786 errorSyntax(USAGE_SNAPSHOT, "Invalid parameter '%s'", Utf8Str(argv[i]).raw());
5787 rc = E_FAIL;
5788 break;
5789 }
5790 }
5791
5792 }
5793 else if (strcmp(argv[1], "showvminfo") == 0)
5794 {
5795 /* exactly one parameter: snapshot name */
5796 if (argc != 3)
5797 {
5798 errorSyntax(USAGE_SNAPSHOT, "Expecting snapshot name only");
5799 rc = E_FAIL;
5800 break;
5801 }
5802
5803 ComPtr<ISnapshot> snapshot;
5804
5805 /* assume it's a UUID */
5806 Guid guid(argv[2]);
5807 if (!guid.isEmpty())
5808 {
5809 CHECK_ERROR_BREAK(machine, GetSnapshot(guid, snapshot.asOutParam()));
5810 }
5811 else
5812 {
5813 /* then it must be a name */
5814 CHECK_ERROR_BREAK(machine, FindSnapshot(Bstr(argv[2]), snapshot.asOutParam()));
5815 }
5816
5817 /* get the machine of the given snapshot */
5818 ComPtr<IMachine> machine;
5819 snapshot->COMGETTER(Machine)(machine.asOutParam());
5820 showVMInfo(virtualBox, machine, console);
5821 }
5822 else
5823 {
5824 errorSyntax(USAGE_SNAPSHOT, "Invalid parameter '%s'", Utf8Str(argv[1]).raw());
5825 rc = E_FAIL;
5826 }
5827 } while (0);
5828
5829 session->Close();
5830
5831 return SUCCEEDED(rc) ? 0 : 1;
5832}
5833
5834static int handleShowVDIInfo(int argc, char *argv[],
5835 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)
5836{
5837 HRESULT rc;
5838
5839 if (argc != 1)
5840 {
5841 return errorSyntax(USAGE_SHOWVDIINFO, "Incorrect number of parameters");
5842 }
5843
5844 ComPtr<IHardDisk> hardDisk;
5845 Bstr filepath;
5846
5847 bool registered = true;
5848
5849 /* first guess is that it's a UUID */
5850 Guid uuid(argv[0]);
5851 rc = virtualBox->GetHardDisk(uuid, hardDisk.asOutParam());
5852 /* no? then it must be a filename */
5853 if (FAILED (rc))
5854 {
5855 filepath = argv[0];
5856 rc = virtualBox->FindHardDisk(filepath, hardDisk.asOutParam());
5857 /* no? well, then it's an unregistered image */
5858 if (FAILED (rc))
5859 {
5860 registered = false;
5861 CHECK_ERROR(virtualBox, OpenHardDisk(filepath, hardDisk.asOutParam()));
5862 }
5863 }
5864 if (SUCCEEDED(rc) && hardDisk)
5865 {
5866 /* query a VDI object (will remain null if it's not VDI) */
5867 ComPtr<IVirtualDiskImage> vdi = hardDisk;
5868
5869 hardDisk->COMGETTER(Id)(uuid.asOutParam());
5870 RTPrintf("UUID: %s\n", uuid.toString().raw());
5871
5872 RTPrintf("Registered: %s\n", registered ? "yes" : "no");
5873
5874 /* check for accessibility */
5875 BOOL accessible = FALSE;
5876 CHECK_ERROR_RET (hardDisk, COMGETTER(Accessible)(&accessible), 1);
5877 RTPrintf("Accessible: %s\n", accessible ? "yes" : "no");
5878
5879 if (!accessible)
5880 {
5881 Bstr err;
5882 CHECK_ERROR_RET (hardDisk, COMGETTER(LastAccessError)(err.asOutParam()), 1);
5883 RTPrintf("Access Error: %lS\n", err.raw());
5884 }
5885
5886 Bstr description;
5887 hardDisk->COMGETTER(Description)(description.asOutParam());
5888 if (description)
5889 {
5890 RTPrintf("Description: %lS\n", description.raw());
5891 }
5892
5893 ULONG64 size;
5894 hardDisk->COMGETTER(Size)(&size);
5895 RTPrintf("Size: %llu MBytes\n", size);
5896 ULONG64 actualSize;
5897 hardDisk->COMGETTER(ActualSize)(&actualSize);
5898 RTPrintf("Current size on disk: %llu MBytes\n", actualSize >> 20);
5899
5900 HardDiskType_T type;
5901 hardDisk->COMGETTER(Type)(&type);
5902 const char *typeStr = "unknown";
5903 switch (type)
5904 {
5905 case HardDiskType_NormalHardDisk:
5906 typeStr = "standard";
5907 break;
5908 case HardDiskType_ImmutableHardDisk:
5909 typeStr = "immutable";
5910 break;
5911 case HardDiskType_WritethroughHardDisk:
5912 typeStr = "writethrough";
5913 break;
5914 }
5915 RTPrintf("Type: %s\n", typeStr);
5916
5917 HardDiskStorageType_T storageType;
5918 const char *storageTypeStr = "unknown";
5919 hardDisk->COMGETTER(StorageType)(&storageType);
5920 switch (storageType)
5921 {
5922 case HardDiskStorageType_VirtualDiskImage:
5923 storageTypeStr = "Virtual Disk Image (VDI)";
5924 break;
5925 case HardDiskStorageType_VMDKImage:
5926 storageTypeStr = "VMDK Image";
5927 break;
5928 case HardDiskStorageType_ISCSIHardDisk:
5929 storageTypeStr = "iSCSI target";
5930 break;
5931 }
5932 RTPrintf("Storage type: %s\n", storageTypeStr);
5933
5934 if (registered)
5935 {
5936 hardDisk->COMGETTER(MachineId)(uuid.asOutParam());
5937 RTPrintf("In use by VM: %s\n", uuid ? uuid.toString().raw() : "<none>");
5938 }
5939
5940 if (vdi)
5941 {
5942 /* VDI specific information */
5943 vdi->COMGETTER(FilePath)(filepath.asOutParam());
5944 RTPrintf("Path: %lS\n", filepath.raw());
5945
5946 }
5947 else
5948 {
5949 /* Generic location information */
5950 Bstr loc;
5951 hardDisk->COMGETTER(Location)(loc.asOutParam());
5952 RTPrintf("Location: %lS\n", loc.raw());
5953 }
5954 }
5955 return SUCCEEDED(rc) ? 0 : 1;
5956}
5957
5958static int handleRegisterImage(int argc, char *argv[],
5959 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)
5960{
5961 HRESULT rc;
5962
5963 if (argc < 2)
5964 {
5965 return errorSyntax(USAGE_REGISTERIMAGE, "Not enough parameters");
5966 }
5967
5968 Bstr filepath(argv[1]);
5969
5970 if (strcmp(argv[0], "disk") == 0)
5971 {
5972 const char *type = NULL;
5973 /* there can be a type parameter */
5974 if ((argc > 2) && (argc != 4))
5975 {
5976 return errorSyntax(USAGE_REGISTERIMAGE, "Incorrect number of parameters");
5977 }
5978 if (argc == 4)
5979 {
5980 if (strcmp(argv[2], "-type") != 0)
5981 {
5982 return errorSyntax(USAGE_REGISTERIMAGE, "Invalid parameter '%s'", Utf8Str(argv[2]).raw());
5983 }
5984 if ( (strcmp(argv[3], "normal") != 0)
5985 && (strcmp(argv[3], "immutable") != 0)
5986 && (strcmp(argv[3], "writethrough") != 0))
5987 {
5988 return errorArgument("Invalid VDI type '%s' specified", Utf8Str(argv[3]).raw());
5989 }
5990 type = argv[3];
5991 }
5992
5993 ComPtr<IHardDisk> hardDisk;
5994 CHECK_ERROR(virtualBox, OpenHardDisk(filepath, hardDisk.asOutParam()));
5995 if (SUCCEEDED(rc) && hardDisk)
5996 {
5997 /* change the type if requested */
5998 if (type)
5999 {
6000 if (strcmp(type, "normal") == 0)
6001 CHECK_ERROR(hardDisk, COMSETTER(Type)(HardDiskType_NormalHardDisk));
6002 else if (strcmp(type, "immutable") == 0)
6003 CHECK_ERROR(hardDisk, COMSETTER(Type)(HardDiskType_ImmutableHardDisk));
6004 else if (strcmp(type, "writethrough") == 0)
6005 CHECK_ERROR(hardDisk, COMSETTER(Type)(HardDiskType_WritethroughHardDisk));
6006 }
6007 if (SUCCEEDED(rc))
6008 CHECK_ERROR(virtualBox, RegisterHardDisk(hardDisk));
6009 }
6010 }
6011 else if (strcmp(argv[0], "dvd") == 0)
6012 {
6013 ComPtr<IDVDImage> dvdImage;
6014 CHECK_ERROR(virtualBox, OpenDVDImage(filepath, Guid(), dvdImage.asOutParam()));
6015 if (SUCCEEDED(rc) && dvdImage)
6016 {
6017 CHECK_ERROR(virtualBox, RegisterDVDImage(dvdImage));
6018 }
6019 }
6020 else if (strcmp(argv[0], "floppy") == 0)
6021 {
6022 ComPtr<IFloppyImage> floppyImage;
6023 CHECK_ERROR(virtualBox, OpenFloppyImage(filepath, Guid(), floppyImage.asOutParam()));
6024 if (SUCCEEDED(rc) && floppyImage)
6025 {
6026 CHECK_ERROR(virtualBox, RegisterFloppyImage(floppyImage));
6027 }
6028 }
6029 else
6030 {
6031 return errorSyntax(USAGE_REGISTERIMAGE, "Invalid parameter '%s'", Utf8Str(argv[1]).raw());
6032 }
6033 return SUCCEEDED(rc) ? 0 : 1;
6034}
6035
6036static int handleUnregisterImage(int argc, char *argv[],
6037 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)
6038{
6039 HRESULT rc;
6040
6041 if (argc != 2)
6042 {
6043 return errorSyntax(USAGE_UNREGISTERIMAGE, "Incorrect number of parameters");
6044 }
6045
6046 /* first guess is that it's a UUID */
6047 Guid uuid(argv[1]);
6048
6049 if (strcmp(argv[0], "disk") == 0)
6050 {
6051 ComPtr<IHardDisk> hardDisk;
6052 rc = virtualBox->GetHardDisk(uuid, hardDisk.asOutParam());
6053 /* not a UUID or not registered? Then it must be a filename */
6054 if (!hardDisk)
6055 {
6056 ComPtr<IVirtualDiskImage> vdi;
6057 CHECK_ERROR(virtualBox, FindVirtualDiskImage(Bstr(argv[1]), vdi.asOutParam()));
6058 hardDisk = vdi;
6059 }
6060 if (SUCCEEDED(rc) && hardDisk)
6061 {
6062 hardDisk->COMGETTER(Id)(uuid.asOutParam());
6063 CHECK_ERROR(virtualBox, UnregisterHardDisk(uuid, hardDisk.asOutParam()));
6064 }
6065 }
6066 else
6067 if (strcmp(argv[0], "dvd") == 0)
6068 {
6069 ComPtr<IDVDImage> dvdImage;
6070 rc = virtualBox->GetDVDImage(uuid, dvdImage.asOutParam());
6071 /* not a UUID or not registered? Then it must be a filename */
6072 if (!dvdImage)
6073 {
6074 ComPtr<IDVDImageCollection> dvdColl;
6075 virtualBox->COMGETTER(DVDImages)(dvdColl.asOutParam());
6076 CHECK_ERROR(dvdColl, FindByPath(Bstr(argv[1]), dvdImage.asOutParam()));
6077 }
6078 if (SUCCEEDED(rc) && dvdImage)
6079 {
6080 dvdImage->COMGETTER(Id)(uuid.asOutParam());
6081 CHECK_ERROR(virtualBox, UnregisterDVDImage(uuid, dvdImage.asOutParam()));
6082 }
6083 }
6084 else
6085 if (strcmp(argv[0], "floppy") == 0)
6086 {
6087 ComPtr<IFloppyImage> floppyImage;
6088 rc = virtualBox->GetFloppyImage(uuid, floppyImage.asOutParam());
6089 /* not a UUID or not registered? Then it must be a filename */
6090 if (!floppyImage)
6091 {
6092 ComPtr<IFloppyImageCollection> floppyColl;
6093 virtualBox->COMGETTER(FloppyImages)(floppyColl.asOutParam());
6094 CHECK_ERROR(floppyColl, FindByPath(Bstr(argv[1]), floppyImage.asOutParam()));
6095 }
6096 if (SUCCEEDED(rc) && floppyImage)
6097 {
6098 floppyImage->COMGETTER(Id)(uuid.asOutParam());
6099 CHECK_ERROR(virtualBox, UnregisterFloppyImage(uuid, floppyImage.asOutParam()));
6100 }
6101 }
6102 else
6103 {
6104 return errorSyntax(USAGE_UNREGISTERIMAGE, "Invalid parameter '%s'", Utf8Str(argv[1]).raw());
6105 }
6106 return SUCCEEDED(rc) ? 0 : 1;
6107}
6108
6109#ifdef RT_OS_WINDOWS
6110static int handleCreateHostIF(int argc, char *argv[],
6111 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)
6112{
6113 if (argc != 1)
6114 {
6115 return errorSyntax(USAGE_CREATEHOSTIF, "Incorrect number of parameters");
6116 }
6117
6118 HRESULT rc = S_OK;
6119
6120 do
6121 {
6122 ComPtr<IHost> host;
6123 CHECK_ERROR_BREAK(virtualBox, COMGETTER(Host)(host.asOutParam()));
6124
6125 ComPtr<IHostNetworkInterface> hostif;
6126 ComPtr<IProgress> progress;
6127 CHECK_ERROR_BREAK(host,
6128 CreateHostNetworkInterface(Bstr(argv[0]),
6129 hostif.asOutParam(),
6130 progress.asOutParam()));
6131
6132 showProgress(progress);
6133 HRESULT result;
6134 CHECK_ERROR_BREAK(progress, COMGETTER(ResultCode)(&result));
6135 if (FAILED(result))
6136 {
6137 com::ProgressErrorInfo info(progress);
6138 PRINT_ERROR_INFO(info);
6139 rc = result;
6140 }
6141 }
6142 while (0);
6143
6144 return SUCCEEDED(rc) ? 0 : 1;
6145}
6146
6147static int handleRemoveHostIF(int argc, char *argv[],
6148 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)
6149{
6150 if (argc != 1)
6151 {
6152 return errorSyntax(USAGE_REMOVEHOSTIF, "Incorrect number of parameters");
6153 }
6154
6155 HRESULT rc = S_OK;
6156
6157 do
6158 {
6159 ComPtr<IHost> host;
6160 CHECK_ERROR_BREAK(virtualBox, COMGETTER(Host)(host.asOutParam()));
6161
6162 ComPtr<IHostNetworkInterface> hostif;
6163
6164 /* first guess is that it's a UUID */
6165 Guid uuid(argv[0]);
6166 if (uuid.isEmpty())
6167 {
6168 /* not a valid UUID, search for it */
6169 ComPtr<IHostNetworkInterfaceCollection> coll;
6170 CHECK_ERROR_BREAK(host, COMGETTER(NetworkInterfaces)(coll.asOutParam()));
6171 CHECK_ERROR_BREAK(coll, FindByName(Bstr(argv[0]), hostif.asOutParam()));
6172 CHECK_ERROR_BREAK(hostif, COMGETTER(Id)(uuid.asOutParam()));
6173 }
6174
6175 ComPtr<IProgress> progress;
6176 CHECK_ERROR_BREAK(host,
6177 RemoveHostNetworkInterface(uuid,
6178 hostif.asOutParam(),
6179 progress.asOutParam()));
6180
6181 showProgress(progress);
6182 HRESULT result;
6183 CHECK_ERROR_BREAK(progress, COMGETTER(ResultCode)(&result));
6184 if (FAILED(result))
6185 {
6186 com::ProgressErrorInfo info(progress);
6187 PRINT_ERROR_INFO(info);
6188 rc = result;
6189 }
6190 }
6191 while (0);
6192
6193 return SUCCEEDED(rc) ? 0 : 1;
6194}
6195#endif /* RT_OS_WINDOWS */
6196
6197static int handleGetExtraData(int argc, char *argv[],
6198 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)
6199{
6200 HRESULT rc = S_OK;
6201
6202 if (argc != 2)
6203 {
6204 return errorSyntax(USAGE_GETEXTRADATA, "Incorrect number of parameters");
6205 }
6206 /* global data? */
6207 if (strcmp(argv[0], "global") == 0)
6208 {
6209 /* enumeration? */
6210 if (strcmp(argv[1], "enumerate") == 0)
6211 {
6212 Bstr extraDataKey;
6213
6214 do
6215 {
6216 Bstr nextExtraDataKey;
6217 Bstr nextExtraDataValue;
6218 HRESULT rcEnum = virtualBox->GetNextExtraDataKey(extraDataKey, nextExtraDataKey.asOutParam(),
6219 nextExtraDataValue.asOutParam());
6220 extraDataKey = nextExtraDataKey;
6221
6222 if (SUCCEEDED(rcEnum) && extraDataKey)
6223 {
6224 RTPrintf("Key: %lS, Value: %lS\n", nextExtraDataKey.raw(), nextExtraDataValue.raw());
6225 }
6226 } while (extraDataKey);
6227 }
6228 else
6229 {
6230 Bstr value;
6231 CHECK_ERROR(virtualBox, GetExtraData(Bstr(argv[1]), value.asOutParam()));
6232 if (value)
6233 RTPrintf("Value: %lS\n", value.raw());
6234 else
6235 RTPrintf("No value set!\n");
6236 }
6237 }
6238 else
6239 {
6240 ComPtr<IMachine> machine;
6241 /* assume it's a UUID */
6242 rc = virtualBox->GetMachine(Guid(argv[0]), machine.asOutParam());
6243 if (FAILED(rc) || !machine)
6244 {
6245 /* must be a name */
6246 CHECK_ERROR(virtualBox, FindMachine(Bstr(argv[0]), machine.asOutParam()));
6247 }
6248 if (machine)
6249 {
6250 /* enumeration? */
6251 if (strcmp(argv[1], "enumerate") == 0)
6252 {
6253 Bstr extraDataKey;
6254
6255 do
6256 {
6257 Bstr nextExtraDataKey;
6258 Bstr nextExtraDataValue;
6259 HRESULT rcEnum = machine->GetNextExtraDataKey(extraDataKey, nextExtraDataKey.asOutParam(),
6260 nextExtraDataValue.asOutParam());
6261 extraDataKey = nextExtraDataKey;
6262
6263 if (SUCCEEDED(rcEnum) && extraDataKey)
6264 {
6265 RTPrintf("Key: %lS, Value: %lS\n", nextExtraDataKey.raw(), nextExtraDataValue.raw());
6266 }
6267 } while (extraDataKey);
6268 }
6269 else
6270 {
6271 Bstr value;
6272 CHECK_ERROR(machine, GetExtraData(Bstr(argv[1]), value.asOutParam()));
6273 if (value)
6274 RTPrintf("Value: %lS\n", value.raw());
6275 else
6276 RTPrintf("No value set!\n");
6277 }
6278 }
6279 }
6280 return SUCCEEDED(rc) ? 0 : 1;
6281}
6282
6283static int handleSetExtraData(int argc, char *argv[],
6284 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)
6285{
6286 HRESULT rc = S_OK;
6287
6288 if (argc < 2)
6289 {
6290 return errorSyntax(USAGE_SETEXTRADATA, "Not enough parameters");
6291 }
6292 /* global data? */
6293 if (strcmp(argv[0], "global") == 0)
6294 {
6295 if (argc < 3)
6296 CHECK_ERROR(virtualBox, SetExtraData(Bstr(argv[1]), NULL));
6297 else if (argc == 3)
6298 CHECK_ERROR(virtualBox, SetExtraData(Bstr(argv[1]), Bstr(argv[2])));
6299 else
6300 return errorSyntax(USAGE_SETEXTRADATA, "Too many parameters");
6301 }
6302 else
6303 {
6304 ComPtr<IMachine> machine;
6305 /* assume it's a UUID */
6306 rc = virtualBox->GetMachine(Guid(argv[0]), machine.asOutParam());
6307 if (FAILED(rc) || !machine)
6308 {
6309 /* must be a name */
6310 CHECK_ERROR(virtualBox, FindMachine(Bstr(argv[0]), machine.asOutParam()));
6311 }
6312 if (machine)
6313 {
6314 if (argc < 3)
6315 CHECK_ERROR(machine, SetExtraData(Bstr(argv[1]), NULL));
6316 else if (argc == 3)
6317 CHECK_ERROR(machine, SetExtraData(Bstr(argv[1]), Bstr(argv[2])));
6318 else
6319 return errorSyntax(USAGE_SETEXTRADATA, "Too many parameters");
6320 }
6321 }
6322 return SUCCEEDED(rc) ? 0 : 1;
6323}
6324
6325static int handleSetProperty(int argc, char *argv[],
6326 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)
6327{
6328 HRESULT rc;
6329
6330 /* there must be two arguments: property name and value */
6331 if (argc != 2)
6332 {
6333 return errorSyntax(USAGE_SETPROPERTY, "Incorrect number of parameters");
6334 }
6335 ComPtr<ISystemProperties> systemProperties;
6336 virtualBox->COMGETTER(SystemProperties)(systemProperties.asOutParam());
6337
6338 if (strcmp(argv[0], "vdifolder") == 0)
6339 {
6340 /* reset to default? */
6341 if (strcmp(argv[1], "default") == 0)
6342 {
6343 CHECK_ERROR(systemProperties, COMSETTER(DefaultVDIFolder)(NULL));
6344 }
6345 else
6346 {
6347 CHECK_ERROR(systemProperties, COMSETTER(DefaultVDIFolder)(Bstr(argv[1])));
6348 }
6349 }
6350 else if (strcmp(argv[0], "machinefolder") == 0)
6351 {
6352 /* reset to default? */
6353 if (strcmp(argv[1], "default") == 0)
6354 {
6355 CHECK_ERROR(systemProperties, COMSETTER(DefaultMachineFolder)(NULL));
6356 }
6357 else
6358 {
6359 CHECK_ERROR(systemProperties, COMSETTER(DefaultMachineFolder)(Bstr(argv[1])));
6360 }
6361 }
6362 else if (strcmp(argv[0], "vrdpauthlibrary") == 0)
6363 {
6364 /* reset to default? */
6365 if (strcmp(argv[1], "default") == 0)
6366 {
6367 CHECK_ERROR(systemProperties, COMSETTER(RemoteDisplayAuthLibrary)(NULL));
6368 }
6369 else
6370 {
6371 CHECK_ERROR(systemProperties, COMSETTER(RemoteDisplayAuthLibrary)(Bstr(argv[1])));
6372 }
6373 }
6374 else if (strcmp(argv[0], "hwvirtexenabled") == 0)
6375 {
6376 if (strcmp(argv[1], "yes") == 0)
6377 CHECK_ERROR(systemProperties, COMSETTER(HWVirtExEnabled)(TRUE));
6378 else if (strcmp(argv[1], "no") == 0)
6379 CHECK_ERROR(systemProperties, COMSETTER(HWVirtExEnabled)(FALSE));
6380 else
6381 return errorArgument("Invalid value '%s' for hardware virtualization extension flag", argv[1]);
6382 }
6383 else
6384 {
6385 return errorSyntax(USAGE_SETPROPERTY, "Invalid parameter '%s'", Utf8Str(argv[0]).raw());
6386 }
6387
6388 return SUCCEEDED(rc) ? 0 : 1;
6389}
6390
6391static int handleUSBFilter (int argc, char *argv[],
6392 ComPtr <IVirtualBox> aVirtualBox, ComPtr<ISession> aSession)
6393{
6394 HRESULT rc = S_OK;
6395 USBFilterCmd cmd;
6396
6397 /* at least: 0: command, 1: index, 2: -target, 3: <target value> */
6398 if (argc < 4)
6399 {
6400 return errorSyntax(USAGE_USBFILTER, "Not enough parameters");
6401 }
6402
6403 /* which command? */
6404 cmd.mAction = USBFilterCmd::Invalid;
6405 if (strcmp (argv [0], "add") == 0) cmd.mAction = USBFilterCmd::Add;
6406 else if (strcmp (argv [0], "modify") == 0) cmd.mAction = USBFilterCmd::Modify;
6407 else if (strcmp (argv [0], "remove") == 0) cmd.mAction = USBFilterCmd::Remove;
6408
6409 if (cmd.mAction == USBFilterCmd::Invalid)
6410 {
6411 return errorSyntax(USAGE_USBFILTER, "Invalid parameter '%s'", Utf8Str(argv[0]).raw());
6412 }
6413
6414 /* which index? */
6415 char *endptr = NULL;
6416 cmd.mIndex = strtoul (argv[1], &endptr, 10);
6417 if (!endptr || *endptr)
6418 {
6419 return errorSyntax(USAGE_USBFILTER, "Invalid index '%s'", argv[1]);
6420 }
6421
6422 switch (cmd.mAction)
6423 {
6424 case USBFilterCmd::Add:
6425 case USBFilterCmd::Modify:
6426 {
6427 /* at least: 0: command, 1: index, 2: -target, 3: <target value>, 4: -name, 5: <name value> */
6428 if (argc < 6)
6429 {
6430 if (cmd.mAction == USBFilterCmd::Add)
6431 {
6432 return errorSyntax(USAGE_USBFILTER_ADD, "Not enough parameters");
6433 }
6434 else
6435 {
6436 return errorSyntax(USAGE_USBFILTER_MODIFY, "Not enough parameters");
6437 }
6438 }
6439
6440 // set Active to true by default
6441 // (assuming that the user sets up all necessary attributes
6442 // at once and wants the filter to be active immediately)
6443 if (cmd.mAction == USBFilterCmd::Add)
6444 cmd.mFilter.mActive = true;
6445
6446 for (int i = 2; i < argc; i++)
6447 {
6448 if (strcmp(argv [i], "-target") == 0)
6449 {
6450 if (argc <= i + 1 || !*argv[i+1])
6451 {
6452 return errorArgument("Missing argument to '%s'", argv[i]);
6453 }
6454 i++;
6455 if (strcmp (argv [i], "global") == 0)
6456 cmd.mGlobal = true;
6457 else
6458 {
6459 /* assume it's a UUID of a machine */
6460 rc = aVirtualBox->GetMachine(Guid(argv[i]), cmd.mMachine.asOutParam());
6461 if (FAILED(rc) || !cmd.mMachine)
6462 {
6463 /* must be a name */
6464 CHECK_ERROR_RET(aVirtualBox, FindMachine(Bstr(argv[i]), cmd.mMachine.asOutParam()), 1);
6465 }
6466 }
6467 }
6468 else if (strcmp(argv [i], "-name") == 0)
6469 {
6470 if (argc <= i + 1 || !*argv[i+1])
6471 {
6472 return errorArgument("Missing argument to '%s'", argv[i]);
6473 }
6474 i++;
6475 cmd.mFilter.mName = argv [i];
6476 }
6477 else if (strcmp(argv [i], "-active") == 0)
6478 {
6479 if (argc <= i + 1)
6480 {
6481 return errorArgument("Missing argument to '%s'", argv[i]);
6482 }
6483 i++;
6484 if (strcmp (argv [i], "yes") == 0)
6485 cmd.mFilter.mActive = true;
6486 else if (strcmp (argv [i], "no") == 0)
6487 cmd.mFilter.mActive = false;
6488 else
6489 {
6490 return errorArgument("Invalid -active argument '%s'", Utf8Str(argv[i]).raw());
6491 }
6492 }
6493 else if (strcmp(argv [i], "-vendorid") == 0)
6494 {
6495 if (argc <= i + 1)
6496 {
6497 return errorArgument("Missing argument to '%s'", argv[i]);
6498 }
6499 i++;
6500 cmd.mFilter.mVendorId = argv [i];
6501 }
6502 else if (strcmp(argv [i], "-productid") == 0)
6503 {
6504 if (argc <= i + 1)
6505 {
6506 return errorArgument("Missing argument to '%s'", argv[i]);
6507 }
6508 i++;
6509 cmd.mFilter.mProductId = argv [i];
6510 }
6511 else if (strcmp(argv [i], "-revision") == 0)
6512 {
6513 if (argc <= i + 1)
6514 {
6515 return errorArgument("Missing argument to '%s'", argv[i]);
6516 }
6517 i++;
6518 cmd.mFilter.mRevision = argv [i];
6519 }
6520 else if (strcmp(argv [i], "-manufacturer") == 0)
6521 {
6522 if (argc <= i + 1)
6523 {
6524 return errorArgument("Missing argument to '%s'", argv[i]);
6525 }
6526 i++;
6527 cmd.mFilter.mManufacturer = argv [i];
6528 }
6529 else if (strcmp(argv [i], "-product") == 0)
6530 {
6531 if (argc <= i + 1)
6532 {
6533 return errorArgument("Missing argument to '%s'", argv[i]);
6534 }
6535 i++;
6536 cmd.mFilter.mProduct = argv [i];
6537 }
6538 else if (strcmp(argv [i], "-remote") == 0)
6539 {
6540 if (argc <= i + 1)
6541 {
6542 return errorArgument("Missing argument to '%s'", argv[i]);
6543 }
6544 i++;
6545 cmd.mFilter.mRemote = argv[i];
6546 }
6547 else if (strcmp(argv [i], "-serialnumber") == 0)
6548 {
6549 if (argc <= i + 1)
6550 {
6551 return errorArgument("Missing argument to '%s'", argv[i]);
6552 }
6553 i++;
6554 cmd.mFilter.mSerialNumber = argv [i];
6555 }
6556 else if (strcmp(argv [i], "-action") == 0)
6557 {
6558 if (argc <= i + 1)
6559 {
6560 return errorArgument("Missing argument to '%s'", argv[i]);
6561 }
6562 i++;
6563 if (strcmp (argv [i], "ignore") == 0)
6564 cmd.mFilter.mAction = USBDeviceFilterAction_USBDeviceFilterIgnore;
6565 else if (strcmp (argv [i], "hold") == 0)
6566 cmd.mFilter.mAction = USBDeviceFilterAction_USBDeviceFilterHold;
6567 else
6568 {
6569 return errorArgument("Invalid USB filter action '%s'", Utf8Str(argv[i]).raw());
6570 }
6571 }
6572
6573 }
6574
6575 if (cmd.mAction == USBFilterCmd::Add)
6576 {
6577 // mandatory/forbidden options
6578 if ( cmd.mFilter.mName.isEmpty()
6579 ||
6580 ( cmd.mGlobal
6581 && cmd.mFilter.mAction == USBDeviceFilterAction_InvalidUSBDeviceFilterAction
6582 )
6583 || ( !cmd.mGlobal
6584 && !cmd.mMachine)
6585 || ( cmd.mGlobal
6586 && cmd.mFilter.mRemote)
6587 )
6588 {
6589 return errorSyntax(USAGE_USBFILTER_ADD, "Mandatory options not supplied");
6590 }
6591 }
6592 break;
6593 }
6594
6595 case USBFilterCmd::Remove:
6596 {
6597 /* at least: 0: command, 1: index, 2: -target, 3: <target value> */
6598 if (argc < 4)
6599 {
6600 return errorSyntax(USAGE_USBFILTER_REMOVE, "Not enough parameters");
6601 }
6602
6603 for (int i = 2; i < argc; i++)
6604 {
6605 if (strcmp(argv [i], "-target") == 0)
6606 {
6607 if (argc <= i + 1 || !*argv[i+1])
6608 {
6609 return errorArgument("Missing argument to '%s'", argv[i]);
6610 }
6611 i++;
6612 if (strcmp (argv [i], "global") == 0)
6613 cmd.mGlobal = true;
6614 else
6615 {
6616 /* assume it's a UUID of a machine */
6617 rc = aVirtualBox->GetMachine(Guid(argv[i]), cmd.mMachine.asOutParam());
6618 if (FAILED(rc) || !cmd.mMachine)
6619 {
6620 /* must be a name */
6621 CHECK_ERROR_RET(aVirtualBox, FindMachine(Bstr(argv[i]), cmd.mMachine.asOutParam()), 1);
6622 }
6623 }
6624 }
6625 }
6626
6627 // mandatory options
6628 if (!cmd.mGlobal && !cmd.mMachine)
6629 {
6630 return errorSyntax(USAGE_USBFILTER_REMOVE, "Mandatory options not supplied");
6631 }
6632
6633 break;
6634 }
6635
6636 default: break;
6637 }
6638
6639 USBFilterCmd::USBFilter &f = cmd.mFilter;
6640
6641 ComPtr <IHost> host;
6642 ComPtr <IUSBController> ctl;
6643 if (cmd.mGlobal)
6644 CHECK_ERROR_RET (aVirtualBox, COMGETTER(Host) (host.asOutParam()), 1);
6645 else
6646 {
6647 Guid uuid;
6648 cmd.mMachine->COMGETTER(Id)(uuid.asOutParam());
6649 /* open a session for the VM */
6650 CHECK_ERROR_RET (aVirtualBox, OpenSession(aSession, uuid), 1);
6651 /* get the mutable session machine */
6652 aSession->COMGETTER(Machine)(cmd.mMachine.asOutParam());
6653 /* and get the USB controller */
6654 CHECK_ERROR_RET (cmd.mMachine, COMGETTER(USBController) (ctl.asOutParam()), 1);
6655 }
6656
6657 switch (cmd.mAction)
6658 {
6659 case USBFilterCmd::Add:
6660 {
6661 if (cmd.mGlobal)
6662 {
6663 ComPtr <IHostUSBDeviceFilter> flt;
6664 CHECK_ERROR_BREAK (host, CreateUSBDeviceFilter (f.mName, flt.asOutParam()));
6665
6666 if (!f.mActive.isNull())
6667 CHECK_ERROR_BREAK (flt, COMSETTER(Active) (f.mActive));
6668 if (!f.mVendorId.isNull())
6669 CHECK_ERROR_BREAK (flt, COMSETTER(VendorId) (f.mVendorId.setNullIfEmpty()));
6670 if (!f.mProductId.isNull())
6671 CHECK_ERROR_BREAK (flt, COMSETTER(ProductId) (f.mProductId.setNullIfEmpty()));
6672 if (!f.mRevision.isNull())
6673 CHECK_ERROR_BREAK (flt, COMSETTER(Revision) (f.mRevision.setNullIfEmpty()));
6674 if (!f.mManufacturer.isNull())
6675 CHECK_ERROR_BREAK (flt, COMSETTER(Manufacturer) (f.mManufacturer.setNullIfEmpty()));
6676 if (!f.mSerialNumber.isNull())
6677 CHECK_ERROR_BREAK (flt, COMSETTER(SerialNumber) (f.mSerialNumber.setNullIfEmpty()));
6678
6679 if (f.mAction != USBDeviceFilterAction_InvalidUSBDeviceFilterAction)
6680 CHECK_ERROR_BREAK (flt, COMSETTER(Action) (f.mAction));
6681
6682 CHECK_ERROR_BREAK (host, InsertUSBDeviceFilter (cmd.mIndex, flt));
6683 }
6684 else
6685 {
6686 ComPtr <IUSBDeviceFilter> flt;
6687 CHECK_ERROR_BREAK (ctl, CreateDeviceFilter (f.mName, flt.asOutParam()));
6688
6689 if (!f.mActive.isNull())
6690 CHECK_ERROR_BREAK (flt, COMSETTER(Active) (f.mActive));
6691 if (!f.mVendorId.isNull())
6692 CHECK_ERROR_BREAK (flt, COMSETTER(VendorId) (f.mVendorId.setNullIfEmpty()));
6693 if (!f.mProductId.isNull())
6694 CHECK_ERROR_BREAK (flt, COMSETTER(ProductId) (f.mProductId.setNullIfEmpty()));
6695 if (!f.mRevision.isNull())
6696 CHECK_ERROR_BREAK (flt, COMSETTER(Revision) (f.mRevision.setNullIfEmpty()));
6697 if (!f.mManufacturer.isNull())
6698 CHECK_ERROR_BREAK (flt, COMSETTER(Manufacturer) (f.mManufacturer.setNullIfEmpty()));
6699 if (!f.mRemote.isNull())
6700 CHECK_ERROR_BREAK (flt, COMSETTER(Remote) (f.mRemote.setNullIfEmpty()));
6701 if (!f.mSerialNumber.isNull())
6702 CHECK_ERROR_BREAK (flt, COMSETTER(SerialNumber) (f.mSerialNumber.setNullIfEmpty()));
6703
6704 CHECK_ERROR_BREAK (ctl, InsertDeviceFilter (cmd.mIndex, flt));
6705 }
6706 break;
6707 }
6708 case USBFilterCmd::Modify:
6709 {
6710 if (cmd.mGlobal)
6711 {
6712 ComPtr <IHostUSBDeviceFilterCollection> coll;
6713 CHECK_ERROR_BREAK (host, COMGETTER(USBDeviceFilters) (coll.asOutParam()));
6714 ComPtr <IHostUSBDeviceFilter> flt;
6715 CHECK_ERROR_BREAK (coll, GetItemAt (cmd.mIndex, flt.asOutParam()));
6716
6717 if (!f.mName.isNull())
6718 CHECK_ERROR_BREAK (flt, COMSETTER(Name) (f.mName.setNullIfEmpty()));
6719 if (!f.mActive.isNull())
6720 CHECK_ERROR_BREAK (flt, COMSETTER(Active) (f.mActive));
6721 if (!f.mVendorId.isNull())
6722 CHECK_ERROR_BREAK (flt, COMSETTER(VendorId) (f.mVendorId.setNullIfEmpty()));
6723 if (!f.mProductId.isNull())
6724 CHECK_ERROR_BREAK (flt, COMSETTER(ProductId) (f.mProductId.setNullIfEmpty()));
6725 if (!f.mRevision.isNull())
6726 CHECK_ERROR_BREAK (flt, COMSETTER(Revision) (f.mRevision.setNullIfEmpty()));
6727 if (!f.mManufacturer.isNull())
6728 CHECK_ERROR_BREAK (flt, COMSETTER(Manufacturer) (f.mManufacturer.setNullIfEmpty()));
6729 if (!f.mSerialNumber.isNull())
6730 CHECK_ERROR_BREAK (flt, COMSETTER(SerialNumber) (f.mSerialNumber.setNullIfEmpty()));
6731
6732 if (f.mAction != USBDeviceFilterAction_InvalidUSBDeviceFilterAction)
6733 CHECK_ERROR_BREAK (flt, COMSETTER(Action) (f.mAction));
6734 }
6735 else
6736 {
6737 ComPtr <IUSBDeviceFilterCollection> coll;
6738 CHECK_ERROR_BREAK (ctl, COMGETTER(DeviceFilters) (coll.asOutParam()));
6739
6740 ComPtr <IUSBDeviceFilter> flt;
6741 CHECK_ERROR_BREAK (coll, GetItemAt (cmd.mIndex, flt.asOutParam()));
6742
6743 if (!f.mName.isNull())
6744 CHECK_ERROR_BREAK (flt, COMSETTER(Name) (f.mName.setNullIfEmpty()));
6745 if (!f.mActive.isNull())
6746 CHECK_ERROR_BREAK (flt, COMSETTER(Active) (f.mActive));
6747 if (!f.mVendorId.isNull())
6748 CHECK_ERROR_BREAK (flt, COMSETTER(VendorId) (f.mVendorId.setNullIfEmpty()));
6749 if (!f.mProductId.isNull())
6750 CHECK_ERROR_BREAK (flt, COMSETTER(ProductId) (f.mProductId.setNullIfEmpty()));
6751 if (!f.mRevision.isNull())
6752 CHECK_ERROR_BREAK (flt, COMSETTER(Revision) (f.mRevision.setNullIfEmpty()));
6753 if (!f.mManufacturer.isNull())
6754 CHECK_ERROR_BREAK (flt, COMSETTER(Manufacturer) (f.mManufacturer.setNullIfEmpty()));
6755 if (!f.mRemote.isNull())
6756 CHECK_ERROR_BREAK (flt, COMSETTER(Remote) (f.mRemote.setNullIfEmpty()));
6757 if (!f.mSerialNumber.isNull())
6758 CHECK_ERROR_BREAK (flt, COMSETTER(SerialNumber) (f.mSerialNumber.setNullIfEmpty()));
6759 }
6760 break;
6761 }
6762 case USBFilterCmd::Remove:
6763 {
6764 if (cmd.mGlobal)
6765 {
6766 ComPtr <IHostUSBDeviceFilter> flt;
6767 CHECK_ERROR_BREAK (host, RemoveUSBDeviceFilter (cmd.mIndex, flt.asOutParam()));
6768 }
6769 else
6770 {
6771 ComPtr <IUSBDeviceFilter> flt;
6772 CHECK_ERROR_BREAK (ctl, RemoveDeviceFilter (cmd.mIndex, flt.asOutParam()));
6773 }
6774 break;
6775 }
6776 default:
6777 break;
6778 }
6779
6780 if (cmd.mMachine)
6781 {
6782 /* commit and close the session */
6783 CHECK_ERROR(cmd.mMachine, SaveSettings());
6784 aSession->Close();
6785 }
6786
6787 return SUCCEEDED (rc) ? 0 : 1;
6788}
6789
6790static int handleSharedFolder (int argc, char *argv[],
6791 ComPtr <IVirtualBox> aVirtualBox, ComPtr<ISession> aSession)
6792{
6793 HRESULT rc;
6794
6795 /* we need at least a command and target */
6796 if (argc < 2)
6797 {
6798 return errorSyntax(USAGE_SHAREDFOLDER, "Not enough parameters");
6799 }
6800
6801 ComPtr<IMachine> machine;
6802 /* assume it's a UUID */
6803 rc = aVirtualBox->GetMachine(Guid(argv[1]), machine.asOutParam());
6804 if (FAILED(rc) || !machine)
6805 {
6806 /* must be a name */
6807 CHECK_ERROR(aVirtualBox, FindMachine(Bstr(argv[1]), machine.asOutParam()));
6808 }
6809 if (!machine)
6810 return 1;
6811 Guid uuid;
6812 machine->COMGETTER(Id)(uuid.asOutParam());
6813
6814 if (strcmp(argv[0], "add") == 0)
6815 {
6816 /* we need at least four more parameters */
6817 if (argc < 5)
6818 {
6819 return errorSyntax(USAGE_SHAREDFOLDER_ADD, "Not enough parameters");
6820 }
6821
6822 char *name = NULL;
6823 char *hostpath = NULL;
6824 bool fTransient = false;
6825
6826 for (int i = 2; i < argc; i++)
6827 {
6828 if (strcmp(argv[i], "-name") == 0)
6829 {
6830 if (argc <= i + 1 || !*argv[i+1])
6831 {
6832 return errorArgument("Missing argument to '%s'", argv[i]);
6833 }
6834 i++;
6835 name = argv[i];
6836 }
6837 else if (strcmp(argv[i], "-hostpath") == 0)
6838 {
6839 if (argc <= i + 1 || !*argv[i+1])
6840 {
6841 return errorArgument("Missing argument to '%s'", argv[i]);
6842 }
6843 i++;
6844 hostpath = argv[i];
6845
6846 }
6847 else if (strcmp(argv[i], "-transient") == 0)
6848 {
6849 fTransient = true;
6850 }
6851 else
6852 {
6853 return errorSyntax(USAGE_SHAREDFOLDER_ADD, "Invalid parameter '%s'", Utf8Str(argv[i]).raw());
6854 }
6855 }
6856
6857 /* required arguments */
6858 if (!name || !hostpath)
6859 {
6860 return errorSyntax(USAGE_SHAREDFOLDER_ADD, "Parameters -name and -hostpath are required");
6861 }
6862
6863 if (fTransient)
6864 {
6865 ComPtr <IConsole> console;
6866
6867 /* open an existing session for the VM */
6868 CHECK_ERROR_RET(aVirtualBox, OpenExistingSession (aSession, uuid), 1);
6869 /* get the session machine */
6870 CHECK_ERROR_RET(aSession, COMGETTER(Machine)(machine.asOutParam()), 1);
6871 /* get the session console */
6872 CHECK_ERROR_RET(aSession, COMGETTER(Console)(console.asOutParam()), 1);
6873
6874 CHECK_ERROR(console, CreateSharedFolder(Bstr(name), Bstr(hostpath)));
6875
6876 if (console)
6877 aSession->Close();
6878 }
6879 else
6880 {
6881 /* open a session for the VM */
6882 CHECK_ERROR_RET (aVirtualBox, OpenSession(aSession, uuid), 1);
6883
6884 /* get the mutable session machine */
6885 aSession->COMGETTER(Machine)(machine.asOutParam());
6886
6887 CHECK_ERROR(machine, CreateSharedFolder(Bstr(name), Bstr(hostpath)));
6888
6889 if (SUCCEEDED(rc))
6890 CHECK_ERROR(machine, SaveSettings());
6891
6892 aSession->Close();
6893 }
6894 }
6895 else if (strcmp(argv[0], "remove") == 0)
6896 {
6897 /* we need at least two more parameters */
6898 if (argc < 3)
6899 {
6900 return errorSyntax(USAGE_SHAREDFOLDER_REMOVE, "Not enough parameters");
6901 }
6902
6903 char *name = NULL;
6904 bool fTransient = false;
6905
6906 for (int i = 2; i < argc; i++)
6907 {
6908 if (strcmp(argv[i], "-name") == 0)
6909 {
6910 if (argc <= i + 1 || !*argv[i+1])
6911 {
6912 return errorArgument("Missing argument to '%s'", argv[i]);
6913 }
6914 i++;
6915 name = argv[i];
6916 }
6917 else if (strcmp(argv[i], "-transient") == 0)
6918 {
6919 fTransient = true;
6920 }
6921 else
6922 {
6923 return errorSyntax(USAGE_SHAREDFOLDER_REMOVE, "Invalid parameter '%s'", Utf8Str(argv[i]).raw());
6924 }
6925 }
6926
6927 /* required arguments */
6928 if (!name)
6929 {
6930 return errorSyntax(USAGE_SHAREDFOLDER_REMOVE, "Parameter -name is required");
6931 }
6932
6933 if (fTransient)
6934 {
6935 ComPtr <IConsole> console;
6936
6937 /* open an existing session for the VM */
6938 CHECK_ERROR_RET(aVirtualBox, OpenExistingSession (aSession, uuid), 1);
6939 /* get the session machine */
6940 CHECK_ERROR_RET(aSession, COMGETTER(Machine)(machine.asOutParam()), 1);
6941 /* get the session console */
6942 CHECK_ERROR_RET(aSession, COMGETTER(Console)(console.asOutParam()), 1);
6943
6944 CHECK_ERROR(console, RemoveSharedFolder(Bstr(name)));
6945
6946 if (console)
6947 aSession->Close();
6948 }
6949 else
6950 {
6951 /* open a session for the VM */
6952 CHECK_ERROR_RET (aVirtualBox, OpenSession(aSession, uuid), 1);
6953
6954 /* get the mutable session machine */
6955 aSession->COMGETTER(Machine)(machine.asOutParam());
6956
6957 CHECK_ERROR(machine, RemoveSharedFolder(Bstr(name)));
6958
6959 /* commit and close the session */
6960 CHECK_ERROR(machine, SaveSettings());
6961 aSession->Close();
6962 }
6963 }
6964 else
6965 {
6966 return errorSyntax(USAGE_SETPROPERTY, "Invalid parameter '%s'", Utf8Str(argv[0]).raw());
6967 }
6968 return 0;
6969}
6970
6971enum HUSPD { HUSPD_DryRun, HUSPD_Apply, HUSPD_ApplyNoBackup };
6972
6973static int handleUpdateSettings_processFile (const char *filePath, HUSPD mode)
6974{
6975 RTPrintf ("%s\n", filePath);
6976
6977 CFGHANDLE config = 0;
6978 char *errMsg = NULL;
6979
6980 int vrc = CFGLDRLoad (&config, filePath, NIL_RTFILE,
6981 NULL, false, NULL, //cfgLdrEntityResolver,
6982 &errMsg);
6983 if (VBOX_SUCCESS (vrc))
6984 {
6985 CFGNODE vbox = 0;
6986 CFGLDRGetNode (config, "VirtualBox", 0, &vbox);
6987 Bstr version;
6988 CFGLDRQueryBSTR (vbox, "version", version.asOutParam());
6989 CFGLDRReleaseNode (vbox);
6990
6991 RTPrintf (" current version : %ls\n", version.raw());
6992
6993 /// @todo (dmik) use cfgLdrEntityResolver later
6994 vrc = CFGLDRTransform (config, "SettingsConverter.xsl", NULL, &errMsg);
6995 if (VBOX_SUCCESS (vrc))
6996 {
6997 CFGLDRGetNode (config, "VirtualBox", 0, &vbox);
6998 CFGLDRQueryBSTR (vbox, "version", version.asOutParam());
6999 CFGLDRReleaseNode (vbox);
7000
7001 RTPrintf (" new version : %ls\n\n", version.raw());
7002
7003 if (mode != HUSPD_DryRun)
7004 {
7005 if (mode != HUSPD_ApplyNoBackup)
7006 {
7007 Utf8StrFmt filePathBak ("%s.bak", filePath);
7008 vrc = RTFileCopy (filePath, filePathBak);
7009 if (VBOX_FAILURE (vrc))
7010 {
7011 RTPrintf ("Error copying '%s' to '%s' (%Vrc)\n",
7012 filePath, filePathBak.raw(), vrc);
7013 }
7014 }
7015
7016 if (VBOX_SUCCESS (vrc))
7017 {
7018 vrc = CFGLDRSave (config, &errMsg);
7019 if (VBOX_FAILURE (vrc))
7020 {
7021 RTPrintf ("Error saving the settings file '%s' (%Vrc)%s%s\n",
7022 filePath, vrc,
7023 errMsg ? "\n" : "", errMsg ? errMsg : "");
7024 }
7025 }
7026 }
7027 }
7028 else
7029 {
7030 RTPrintf ("Could not convert the settings file '%s' (%Vrc)%s%s\n",
7031 filePath, vrc, errMsg ? "\n" : "", errMsg ? errMsg : "");
7032 }
7033
7034 CFGLDRFree (config);
7035 }
7036 else
7037 {
7038 RTPrintf ("Error loading the settings file '%s' (%Vrc)%s%s\n",
7039 filePath, vrc, errMsg ? "\n" : "", errMsg ? errMsg : "");
7040 }
7041
7042 if (errMsg)
7043 RTStrFree (errMsg);
7044
7045 return vrc;
7046}
7047
7048static int handleUpdateSettings_processDir (const char *dirPath, HUSPD mode,
7049 bool skipInvalid)
7050{
7051 PRTDIR dir;
7052 int vrc = RTDirOpen (&dir, dirPath);
7053 if (VBOX_FAILURE (vrc))
7054 {
7055 return vrc;
7056 }
7057
7058 RTDIRENTRYEX entry;
7059 while (VBOX_SUCCESS (vrc))
7060 {
7061 vrc = RTDirReadEx (dir, &entry, NULL, RTFSOBJATTRADD_UNIX);
7062 if (VBOX_FAILURE (vrc))
7063 {
7064 if (vrc == VERR_NO_MORE_FILES)
7065 vrc = VINF_SUCCESS;
7066 else
7067 RTPrintf ("Error reading directory '%s' (%Vrc)\n", dirPath, vrc);
7068 break;
7069 }
7070
7071 if (RTFS_IS_DIRECTORY (entry.Info.Attr.fMode))
7072 {
7073 if (entry.szName[0] == '.' &&
7074 (entry.szName[1] == 0 ||
7075 (entry.szName[1] == '.' && entry.szName[2] == 0)))
7076 continue;
7077
7078 vrc = handleUpdateSettings_processDir (
7079 Utf8StrFmt ("%s%c%s", dirPath, RTPATH_DELIMITER, entry.szName),
7080 mode, skipInvalid);
7081 if (VBOX_FAILURE (vrc))
7082 break;
7083
7084 continue;
7085 }
7086 else if (RTFS_IS_FILE (entry.Info.Attr.fMode))
7087 {
7088 const char *ext = RTPathExt (entry.szName);
7089 if (!ext || strcmp (ext, ".xml") != 0)
7090 continue;
7091 }
7092 else
7093 continue;
7094
7095 Utf8Str filePath = Utf8StrFmt ("%s%c%s", dirPath, RTPATH_DELIMITER,
7096 entry.szName);
7097
7098 vrc = handleUpdateSettings_processFile (filePath, mode);
7099
7100 if (skipInvalid)
7101 vrc = VINF_SUCCESS;
7102 }
7103
7104 RTDirClose (dir);
7105
7106 return vrc;
7107}
7108
7109static int handleUpdateSettings (int argc, char *argv[])
7110{
7111 const char *dirOrFilePath = NULL;
7112 bool apply = false;
7113 bool nobackup = false;
7114 bool skipinvalid = false;
7115
7116 for (int i = 0; i < argc; i++)
7117 {
7118 if (i == 0 && argv[i][0] != '-')
7119 {
7120 dirOrFilePath = argv[i];
7121 }
7122 else if (argv[i][0] == '-')
7123 {
7124 if (strcmp (&argv[i][1], "apply") == 0)
7125 apply = true;
7126 else if (strcmp (&argv[i][1], "nobackup") == 0)
7127 nobackup = true;
7128 else if (strcmp (&argv[i][1], "skipinvalid") == 0)
7129 skipinvalid = true;
7130 else
7131 {
7132 return errorSyntax(USAGE_SETPROPERTY, "Invalid parameter '%s'", Utf8Str(argv[i]).raw());
7133 }
7134 }
7135 else
7136 {
7137 return errorSyntax(USAGE_SETPROPERTY, "Invalid parameter '%s'", Utf8Str(argv[i]).raw());
7138 }
7139 }
7140
7141 HUSPD mode = HUSPD_DryRun;
7142 if (apply)
7143 mode = nobackup ? HUSPD_ApplyNoBackup : HUSPD_Apply;
7144
7145 int vrc = CFGLDRInitialize();
7146 if (VBOX_FAILURE (vrc))
7147 {
7148 RTPrintf ("Could not initialize XML subsystem (%Vrc)\n", vrc);
7149 return 1;
7150 }
7151
7152 if (dirOrFilePath)
7153 {
7154 if (RTDirExists (dirOrFilePath))
7155 {
7156 char fullPath [RTPATH_MAX];
7157 vrc = RTPathReal (dirOrFilePath, fullPath, RTPATH_MAX);
7158 if (VBOX_FAILURE (vrc))
7159 {
7160 RTPrintf ("Invalid directory path '%s' (%Vrc)\n", dirOrFilePath, vrc);
7161 return 1;
7162 }
7163
7164 RTPrintf ("Updating settings files in the following directory:\n"
7165 "\n %s\n\n", fullPath);
7166
7167 vrc = handleUpdateSettings_processDir (dirOrFilePath, mode, skipinvalid);
7168 }
7169 else
7170 {
7171 vrc = handleUpdateSettings_processFile (dirOrFilePath, mode);
7172 }
7173 }
7174 else
7175 {
7176 char homeDir [RTPATH_MAX];
7177 vrc = GetVBoxUserHomeDirectory (homeDir, sizeof (homeDir));
7178
7179 AssertRC (vrc);
7180 if (VBOX_SUCCESS (vrc))
7181 {
7182 RTPrintf ("Updating settings files in the following VirtualBox Home Directory:\n"
7183 "\n %s\n\n", homeDir);
7184
7185 vrc = handleUpdateSettings_processDir (homeDir, mode, skipinvalid);
7186 }
7187 }
7188
7189 if (mode == HUSPD_DryRun)
7190 {
7191 RTPrintf ("NOTE: No actual changes to the setting files were made.\n"
7192 " Repeat the command with the -apply option supplied.\n");
7193 }
7194
7195 CFGLDRShutdown();
7196
7197 return VBOX_SUCCESS (vrc) ? 0 : 1;
7198}
7199
7200// main
7201///////////////////////////////////////////////////////////////////////////////
7202
7203int main(int argc, char *argv[])
7204{
7205 /*
7206 * Before we do anything, init the runtime without loading
7207 * the support driver.
7208 */
7209 RTR3Init(false);
7210
7211 bool fShowLogo = true;
7212 int iCmd = 1;
7213 int iCmdArg;
7214
7215 for (int i = 1; i < argc || argc <= iCmd; i++)
7216 {
7217 if ( argc <= iCmd
7218 || (strcmp(argv[i], "help") == 0)
7219 || (strcmp(argv[i], "-?") == 0)
7220 || (strcmp(argv[i], "-h") == 0)
7221 || (strcmp(argv[i], "-help") == 0)
7222 || (strcmp(argv[i], "--help") == 0))
7223 {
7224 showLogo();
7225 printUsage(USAGE_ALL);
7226 return 0;
7227 }
7228 else if ( strcmp(argv[i], "-v") == 0
7229 || strcmp(argv[i], "-version") == 0
7230 || strcmp(argv[i], "-Version") == 0
7231 || strcmp(argv[i], "--version") == 0)
7232 {
7233 /* Print version number, and do nothing else. */
7234 RTPrintf("%sr%d\n", VBOX_VERSION_STRING, VBOX_SVN_REV);
7235 exit(0);
7236 }
7237 else if (strcmp(argv[i], "-nologo") == 0)
7238 {
7239 /* suppress the logo */
7240 fShowLogo = false;
7241 iCmd++;
7242 }
7243 else if (strcmp(argv[i], "-dumpopts") == 0)
7244 {
7245 /* Special option to dump really all commands,
7246 * even the ones not understood on this platform. */
7247 printUsage(USAGE_DUMPOPTS);
7248 return 0;
7249 }
7250 else
7251 {
7252 break;
7253 }
7254 }
7255
7256 iCmdArg = iCmd + 1;
7257
7258 if (fShowLogo)
7259 showLogo();
7260
7261 HRESULT rc;
7262
7263 CHECK_RC_RET (com::Initialize());
7264
7265 /*
7266 * The input is in the host OS'es codepage (NT guarantees ACP).
7267 * For VBox we use UTF-8 and convert to UCS-2 when calling (XP)COM APIs.
7268 * For simplicity, just convert the argv[] array here.
7269 */
7270 for (int i = iCmdArg; i < argc; i++)
7271 {
7272 char *converted;
7273 RTStrCurrentCPToUtf8(&converted, argv[i]);
7274 argv[i] = converted;
7275 }
7276
7277 do
7278 {
7279 // scopes all the stuff till shutdown
7280 ////////////////////////////////////////////////////////////////////////////
7281
7282 /* update settings command (no VirtualBox instantiation!) */
7283 if (argc >= iCmdArg && (strcmp(argv[iCmd], "updatesettings") == 0))
7284 {
7285 rc = handleUpdateSettings(argc - iCmdArg, argv + iCmdArg);
7286 break;
7287 }
7288
7289 /* convertdd: does not need a VirtualBox instantiation) */
7290 if (argc >= iCmdArg && (strcmp(argv[iCmd], "convertdd") == 0))
7291 {
7292 rc = handleConvertDDImage(argc - iCmdArg, argv + iCmdArg);
7293 break;
7294 }
7295
7296 ComPtr <IVirtualBox> virtualBox;
7297 ComPtr <ISession> session;
7298
7299 rc = virtualBox.createLocalObject (CLSID_VirtualBox);
7300 if (FAILED(rc))
7301 {
7302 RTPrintf ("[!] Failed to create the VirtualBox object!\n");
7303 PRINT_RC_MESSAGE (rc);
7304
7305 com::ErrorInfo info;
7306 if (!info.isFullAvailable() && !info.isBasicAvailable())
7307 RTPrintf ("[!] Most likely, the VirtualBox COM server is not running "
7308 "or failed to start.\n");
7309 else
7310 PRINT_ERROR_INFO (info);
7311 break;
7312 }
7313
7314 CHECK_RC_BREAK (session.createInprocObject (CLSID_Session));
7315
7316 /* create the event queue
7317 * (here it is necessary only to process remaining XPCOM/IPC events
7318 * after the session is closed) */
7319
7320 EventQueue eventQ;
7321
7322 /*
7323 * All registered command handlers
7324 */
7325 struct
7326 {
7327 const char *command;
7328 PFNHANDLER handler;
7329 } commandHandlers[] =
7330 {
7331 { "internalcommands", handleInternalCommands },
7332 { "list", handleList },
7333 { "showvminfo", handleShowVMInfo },
7334 { "registervm", handleRegisterVM },
7335 { "unregistervm", handleUnregisterVM },
7336 { "createvdi", handleCreateVDI },
7337 { "modifyvdi", handleModifyVDI },
7338 { "addiscsidisk", handleAddiSCSIDisk },
7339 { "createvm", handleCreateVM },
7340 { "modifyvm", handleModifyVM },
7341 { "clonevdi", handleCloneVDI },
7342 { "startvm", handleStartVM },
7343 { "controlvm", handleControlVM },
7344 { "discardstate", handleDiscardState },
7345 { "snapshot", handleSnapshot },
7346 { "registerimage", handleRegisterImage },
7347 { "unregisterimage", handleUnregisterImage },
7348 { "showvdiinfo", handleShowVDIInfo },
7349#ifdef RT_OS_WINDOWS
7350 { "createhostif", handleCreateHostIF },
7351 { "removehostif", handleRemoveHostIF },
7352#endif
7353 { "getextradata", handleGetExtraData },
7354 { "setextradata", handleSetExtraData },
7355 { "setproperty", handleSetProperty },
7356 { "usbfilter", handleUSBFilter },
7357 { "sharedfolder", handleSharedFolder },
7358 { NULL, NULL }
7359 };
7360
7361 int commandIndex;
7362 for (commandIndex = 0; commandHandlers[commandIndex].command != NULL; commandIndex++)
7363 {
7364 if (strcmp(commandHandlers[commandIndex].command, argv[iCmd]) == 0)
7365 {
7366 rc = commandHandlers[commandIndex].handler(argc - iCmdArg, &argv[iCmdArg], virtualBox, session);
7367 break;
7368 }
7369 }
7370 if (!commandHandlers[commandIndex].command)
7371 {
7372 rc = errorSyntax(USAGE_ALL, "Invalid command '%s'", Utf8Str(argv[iCmd]).raw());
7373 }
7374
7375
7376 // end "all-stuff" scope
7377 ////////////////////////////////////////////////////////////////////////////
7378 }
7379 while (0);
7380
7381 com::Shutdown();
7382
7383 /*
7384 * Free converted argument vector
7385 */
7386 for (int i = iCmdArg; i < argc; i++)
7387 RTStrFree(argv[i]);
7388
7389 return rc;
7390}
Note: See TracBrowser for help on using the repository browser.

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