VirtualBox

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

Last change on this file since 11378 was 11378, checked in by vboxsync, 16 years ago

PerfAPI: VBoxManage metrics command implementation. Removed an assertion to allow creating a null array from an array parameter.

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

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