VirtualBox

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

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

VBoxManage: fixed handling of VBoxManage snapshot machine_uuid showvminfo snapshot_uuid if the VM is not powered up

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