VirtualBox

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

Last change on this file since 8605 was 8452, checked in by vboxsync, 17 years ago

Disabled access to 82543GC

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

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