VirtualBox

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

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

nit picking.

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