VirtualBox

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

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

Backed out 29633 & 29635 again

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

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