VirtualBox

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

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

Main: Applied SATA changes from #2406. Increased XML settings version format from 1.2 to 1.3.pre.

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

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