VirtualBox

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

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

82543GC support is ready. RX crit section removed.

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

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