VirtualBox

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

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

Make the vrdp address output in VBoxManage showvminfo easier to read.
Just the empty string is confusing.

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