VirtualBox

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

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

VBoxManage: Clear UUID structure before using it.

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

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