VirtualBox

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

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

Main & VBoxManage: Made HostNetworkInterface, IHost::networkInterfaces and list hostifs available everywhere. Only Windows and Darwin implements the enumeration.

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