VirtualBox

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

Last change on this file since 8997 was 8691, checked in by vboxsync, 17 years ago

warning

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 281.1 KB
Line 
1/** @file
2 *
3 * VBox frontends: VBoxManage (command-line interface)
4 *
5 * VBoxManage is VirtualBox's command-line interface. This is its rather
6 * long source.
7 */
8
9/*
10 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
11 *
12 * This file is part of VirtualBox Open Source Edition (OSE), as
13 * available from http://www.virtualbox.org. This file is free software;
14 * you can redistribute it and/or modify it under the terms of the GNU
15 * General Public License (GPL) as published by the Free Software
16 * Foundation, in version 2 as it comes in the "COPYING" file of the
17 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
18 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
19 *
20 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
21 * Clara, CA 95054 USA or visit http://www.sun.com if you need
22 * additional information or have any questions.
23 */
24
25
26/*******************************************************************************
27* Header Files *
28*******************************************************************************/
29
30#include <VBox/com/com.h>
31#include <VBox/com/string.h>
32#include <VBox/com/Guid.h>
33#include <VBox/com/array.h>
34#include <VBox/com/ErrorInfo.h>
35#include <VBox/com/EventQueue.h>
36
37#include <VBox/com/VirtualBox.h>
38
39#include <stdlib.h>
40#include <stdarg.h>
41
42#include <vector>
43#include <list>
44
45#include <iprt/runtime.h>
46#include <iprt/stream.h>
47#include <iprt/string.h>
48#include <iprt/asm.h>
49#include <iprt/uuid.h>
50#include <iprt/thread.h>
51#include <iprt/path.h>
52#include <iprt/param.h>
53#include <iprt/dir.h>
54#include <iprt/file.h>
55#include <iprt/env.h>
56#include <iprt/cidr.h>
57#include <VBox/err.h>
58#include <VBox/version.h>
59#include <VBox/VBoxHDD.h>
60
61#include "VBoxManage.h"
62
63using namespace com;
64
65/* missing XPCOM <-> COM wrappers */
66#ifndef STDMETHOD_
67# define STDMETHOD_(ret, meth) NS_IMETHOD_(ret) meth
68#endif
69#ifndef NS_GET_IID
70# define NS_GET_IID(I) IID_##I
71#endif
72#ifndef RT_OS_WINDOWS
73#define IUnknown nsISupports
74#endif
75
76/** command handler type */
77typedef DECLCALLBACK(int) FNHANDLER(int argc, char *argv[], ComPtr<IVirtualBox> aVirtualBox, ComPtr<ISession> aSession);
78typedef FNHANDLER *PFNHANDLER;
79
80/**
81 * Quick IUSBDevice implementation for detaching / attaching
82 * devices to the USB Controller.
83 */
84class MyUSBDevice : public IUSBDevice
85{
86public:
87 // public initializer/uninitializer for internal purposes only
88 MyUSBDevice(uint16_t a_u16VendorId, uint16_t a_u16ProductId, uint16_t a_bcdRevision, uint64_t a_u64SerialHash, const char *a_pszComment)
89 : m_usVendorId(a_u16VendorId), m_usProductId(a_u16ProductId),
90 m_bcdRevision(a_bcdRevision), m_u64SerialHash(a_u64SerialHash),
91 m_bstrComment(a_pszComment),
92 m_cRefs(0)
93 {
94 }
95
96 STDMETHOD_(ULONG, AddRef)(void)
97 {
98 return ASMAtomicIncU32(&m_cRefs);
99 }
100 STDMETHOD_(ULONG, Release)(void)
101 {
102 ULONG cRefs = ASMAtomicDecU32(&m_cRefs);
103 if (!cRefs)
104 delete this;
105 return cRefs;
106 }
107 STDMETHOD(QueryInterface)(const IID &iid, void **ppvObject)
108 {
109 Guid guid(iid);
110 if (guid == Guid(NS_GET_IID(IUnknown)))
111 *ppvObject = (IUnknown *)this;
112 else if (guid == Guid(NS_GET_IID(IUSBDevice)))
113 *ppvObject = (IUSBDevice *)this;
114 else
115 return E_NOINTERFACE;
116 AddRef();
117 return S_OK;
118 }
119
120 STDMETHOD(COMGETTER(Id))(GUIDPARAMOUT a_pId) { return E_NOTIMPL; }
121 STDMETHOD(COMGETTER(VendorId))(USHORT *a_pusVendorId) { *a_pusVendorId = m_usVendorId; return S_OK; }
122 STDMETHOD(COMGETTER(ProductId))(USHORT *a_pusProductId) { *a_pusProductId = m_usProductId; return S_OK; }
123 STDMETHOD(COMGETTER(Revision))(USHORT *a_pusRevision) { *a_pusRevision = m_bcdRevision; return S_OK; }
124 STDMETHOD(COMGETTER(SerialHash))(ULONG64 *a_pullSerialHash) { *a_pullSerialHash = m_u64SerialHash; return S_OK; }
125 STDMETHOD(COMGETTER(Manufacturer))(BSTR *a_pManufacturer) { return E_NOTIMPL; }
126 STDMETHOD(COMGETTER(Product))(BSTR *a_pProduct) { return E_NOTIMPL; }
127 STDMETHOD(COMGETTER(SerialNumber))(BSTR *a_pSerialNumber) { return E_NOTIMPL; }
128 STDMETHOD(COMGETTER(Address))(BSTR *a_pAddress) { return E_NOTIMPL; }
129
130private:
131 /** The vendor id of this USB device. */
132 USHORT m_usVendorId;
133 /** The product id of this USB device. */
134 USHORT m_usProductId;
135 /** The product revision number of this USB device.
136 * (high byte = integer; low byte = decimal) */
137 USHORT m_bcdRevision;
138 /** The USB serial hash of the device. */
139 uint64_t m_u64SerialHash;
140 /** The user comment string. */
141 Bstr m_bstrComment;
142 /** Reference counter. */
143 uint32_t volatile m_cRefs;
144};
145
146
147// types
148///////////////////////////////////////////////////////////////////////////////
149
150template <typename T>
151class Nullable
152{
153public:
154
155 Nullable() : mIsNull (true) {}
156 Nullable (const T &aValue, bool aIsNull = false)
157 : mIsNull (aIsNull), mValue (aValue) {}
158
159 bool isNull() const { return mIsNull; };
160 void setNull (bool aIsNull = true) { mIsNull = aIsNull; }
161
162 operator const T&() const { return mValue; }
163
164 Nullable &operator= (const T &aValue)
165 {
166 mValue = aValue;
167 mIsNull = false;
168 return *this;
169 }
170
171private:
172
173 bool mIsNull;
174 T mValue;
175};
176
177/** helper structure to encapsulate USB filter manipulation commands */
178struct USBFilterCmd
179{
180 struct USBFilter
181 {
182 USBFilter ()
183 : mAction (USBDeviceFilterAction_Null)
184 {}
185
186 Bstr mName;
187 Nullable <bool> mActive;
188 Bstr mVendorId;
189 Bstr mProductId;
190 Bstr mRevision;
191 Bstr mManufacturer;
192 Bstr mProduct;
193 Bstr mRemote;
194 Bstr mSerialNumber;
195 Nullable <ULONG> mMaskedInterfaces;
196 USBDeviceFilterAction_T mAction;
197 };
198
199 enum Action { Invalid, Add, Modify, Remove };
200
201 USBFilterCmd() : mAction (Invalid), mIndex (0), mGlobal (false) {}
202
203 Action mAction;
204 ULONG mIndex;
205 /** flag whether the command target is a global filter */
206 bool mGlobal;
207 /** machine this command is targeted at (null for global filters) */
208 ComPtr<IMachine> mMachine;
209 USBFilter mFilter;
210};
211
212// funcs
213///////////////////////////////////////////////////////////////////////////////
214
215static void showLogo(void)
216{
217 static bool fShown; /* show only once */
218
219 if (!fShown)
220 {
221 RTPrintf("VirtualBox Command Line Management Interface Version "
222 VBOX_VERSION_STRING "\n"
223 "(C) 2005-2008 Sun Microsystems, Inc.\n"
224 "All rights reserved.\n"
225 "\n");
226 fShown = true;
227 }
228}
229
230static void printUsage(USAGECATEGORY u64Cmd)
231{
232#ifdef RT_OS_LINUX
233 bool fLinux = true;
234#else
235 bool fLinux = false;
236#endif
237#ifdef RT_OS_WINDOWS
238 bool fWin = true;
239#else
240 bool fWin = false;
241#endif
242#ifdef RT_OS_SOLARIS
243 bool fSolaris = true;
244#else
245 bool fSolaris = false;
246#endif
247#ifdef RT_OS_DARWIN
248 bool fDarwin = true;
249#else
250 bool fDarwin = false;
251#endif
252#ifdef VBOX_VRDP
253 bool fVRDP = true;
254#else
255 bool fVRDP = false;
256#endif
257
258 if (u64Cmd == USAGE_DUMPOPTS)
259 {
260 fLinux = true;
261 fWin = true;
262 fSolaris = true;
263 fDarwin = true;
264 fVRDP = true;
265 u64Cmd = USAGE_ALL;
266 }
267
268 RTPrintf("Usage:\n"
269 "\n");
270
271 if (u64Cmd == USAGE_ALL)
272 {
273 RTPrintf("VBoxManage [-v|-version] print version number and exit\n"
274 "VBoxManage -nologo ... suppress the logo\n"
275 "\n"
276 "VBoxManage -convertSettings ... allow to auto-convert settings files\n"
277 "VBoxManage -convertSettingsBackup ... allow to auto-convert settings files\n"
278 " but create backup copies before\n"
279 "VBoxManage -convertSettingsIgnore ... allow to auto-convert settings files\n"
280 " but don't explicitly save the results\n"
281 "\n");
282 }
283
284 if (u64Cmd & USAGE_LIST)
285 {
286 RTPrintf("VBoxManage list vms|runningvms|ostypes|hostdvds|hostfloppies|\n");
287 if (fWin)
288 RTPrintf( "hostifs|");
289 RTPrintf(" hdds|dvds|floppies|usbhost|usbfilters|\n"
290 " systemproperties\n"
291 "\n");
292 }
293
294 if (u64Cmd & USAGE_SHOWVMINFO)
295 {
296 RTPrintf("VBoxManage showvminfo <uuid>|<name>\n"
297 " [-details]\n"
298 " [-statistics]\n"
299 " [-machinereadable]\n"
300 "\n");
301 }
302
303 if (u64Cmd & USAGE_REGISTERVM)
304 {
305 RTPrintf("VBoxManage registervm <filename>\n"
306 "\n");
307 }
308
309 if (u64Cmd & USAGE_UNREGISTERVM)
310 {
311 RTPrintf("VBoxManage unregistervm <uuid>|<name>\n"
312 " [-delete]\n"
313 "\n");
314 }
315
316 if (u64Cmd & USAGE_CREATEVM)
317 {
318 RTPrintf("VBoxManage createvm -name <name>\n"
319 " [-register]\n"
320 " [-basefolder <path> | -settingsfile <path>]\n"
321 " [-uuid <uuid>]\n"
322 " \n"
323 "\n");
324 }
325
326 if (u64Cmd & USAGE_MODIFYVM)
327 {
328 RTPrintf("VBoxManage modifyvm <uuid|name>\n"
329 " [-name <name>]\n"
330 " [-ostype <ostype>]\n"
331 " [-memory <memorysize>]\n"
332 " [-vram <vramsize>]\n"
333 " [-acpi on|off]\n"
334 " [-ioapic on|off]\n"
335 " [-pae on|off]\n"
336 " [-hwvirtex on|off|default]\n"
337 " [-monitorcount <number>]\n"
338 " [-bioslogofadein on|off]\n"
339 " [-bioslogofadeout on|off]\n"
340 " [-bioslogodisplaytime <msec>]\n"
341 " [-bioslogoimagepath <imagepath>]\n"
342 " [-biosbootmenu disabled|menuonly|messageandmenu]\n"
343 " [-biossystemtimeoffset <msec>]\n"
344 " [-biospxedebug on|off]\n"
345 " [-boot<1-4> none|floppy|dvd|disk|net>]\n"
346 " [-hd<a|b|d> none|<uuid>|<filename>]\n"
347#ifdef VBOX_WITH_AHCI
348 " [-sata on|off]\n"
349 " [-sataportcount <1-30>]\n"
350 " [-sataport<1-30> none|<uuid>|<filename>]\n"
351 " [-sataideemulation<1-4> <1-30>]\n"
352#endif
353 " [-dvd none|<uuid>|<filename>|host:<drive>]\n"
354 " [-dvdpassthrough on|off]\n"
355 " [-floppy disabled|empty|<uuid>|\n"
356 " <filename>|host:<drive>]\n"
357 " [-nic<1-N> none|null|nat|hostif|intnet]\n"
358 " [-nictype<1-N> Am79C970A|Am79C973"
359#ifdef VBOX_WITH_E1000
360 "|82540EM|82543GC"
361#endif
362 "]\n"
363 " [-cableconnected<1-N> on|off]\n"
364 " [-nictrace<1-N> on|off]\n"
365 " [-nictracefile<1-N> <filename>]\n"
366 " [-nicspeed<1-N> <kbps>]\n"
367 " [-hostifdev<1-N> none|<devicename>]\n"
368 " [-intnet<1-N> <network name>]\n"
369 " [-natnet<1-N> <network>|default]\n"
370 " [-macaddress<1-N> auto|<mac>]\n"
371 " [-uart<1-N> off|<I/O base> <IRQ>]\n"
372 " [-uartmode<1-N> disconnected|\n"
373 " server <pipe>|\n"
374 " client <pipe>|\n"
375 " <devicename>]\n"
376#ifdef VBOX_WITH_MEM_BALLOONING
377 " [-guestmemoryballoon <balloonsize>]\n"
378#endif
379 " [-gueststatisticsinterval <seconds>]\n"
380 );
381 if (fLinux)
382 {
383 RTPrintf(" [-tapsetup<1-N> none|<application>]\n"
384 " [-tapterminate<1-N> none|<application>]\n");
385 }
386 RTPrintf(" [-audio none|null");
387 if (fWin)
388 {
389#ifdef VBOX_WITH_WINMM
390 RTPrintf( "|winmm|dsound");
391#else
392 RTPrintf( "|dsound");
393#endif
394 }
395 if (fSolaris)
396 {
397 RTPrintf( "|solaudio");
398 }
399 if (fLinux)
400 {
401 RTPrintf( "|oss"
402#ifdef VBOX_WITH_ALSA
403 "|alsa"
404#endif
405#ifdef VBOX_WITH_PULSE
406 "|pulse"
407#endif
408 );
409 }
410 if (fDarwin)
411 {
412 RTPrintf( "|coreaudio");
413 }
414 RTPrintf( "]\n");
415 RTPrintf(" [-audiocontroller ac97|sb16]\n"
416 " [-clipboard disabled|hosttoguest|guesttohost|\n"
417 " bidirectional]\n");
418 if (fVRDP)
419 {
420 RTPrintf(" [-vrdp on|off]\n"
421 " [-vrdpport default|<port>]\n"
422 " [-vrdpaddress <host>]\n"
423 " [-vrdpauthtype null|external|guest]\n"
424 " [-vrdpmulticon on|off]\n");
425 }
426 RTPrintf(" [-usb on|off]\n"
427 " [-usbehci on|off]\n"
428 " [-snapshotfolder default|<path>]\n");
429 RTPrintf("\n");
430 }
431
432 if (u64Cmd & USAGE_STARTVM)
433 {
434 RTPrintf("VBoxManage startvm <uuid>|<name>\n");
435 if (fVRDP)
436 RTPrintf(" [-type gui|vrdp]\n");
437 RTPrintf("\n");
438 }
439
440 if (u64Cmd & USAGE_CONTROLVM)
441 {
442 RTPrintf("VBoxManage controlvm <uuid>|<name>\n"
443 " pause|resume|reset|poweroff|savestate|\n"
444 " acpipowerbutton|acpisleepbutton|\n"
445 " keyboardputscancode <hex> [<hex> ...]|\n"
446 " setlinkstate<1-4> on|off |\n"
447 " usbattach <uuid>|<address> |\n"
448 " usbdetach <uuid>|<address> |\n"
449 " dvdattach none|<uuid>|<filename>|host:<drive> |\n"
450 " floppyattach none|<uuid>|<filename>|host:<drive> |\n"
451 " setvideomodehint <xres> <yres> <bpp> [display]|\n"
452 " setcredentials <username> <password> <domain>\n"
453 " [-allowlocallogon <yes|no>]\n"
454 "\n");
455 }
456
457 if (u64Cmd & USAGE_DISCARDSTATE)
458 {
459 RTPrintf("VBoxManage discardstate <uuid>|<name>\n"
460 "\n");
461 }
462
463 if (u64Cmd & USAGE_ADOPTSTATE)
464 {
465 RTPrintf("VBoxManage adoptstate <uuid>|<name> <state_file>\n"
466 "\n");
467 }
468
469 if (u64Cmd & USAGE_SNAPSHOT)
470 {
471 RTPrintf("VBoxManage snapshot <uuid>|<name>\n"
472 " take <name> [-desc <desc>] |\n"
473 " discard <uuid>|<name> |\n"
474 " discardcurrent -state|-all |\n"
475 " edit <uuid>|<name>|-current\n"
476 " [-newname <name>]\n"
477 " [-newdesc <desc>] |\n"
478 " showvminfo <uuid>|<name>\n"
479 "\n");
480 }
481
482 if (u64Cmd & USAGE_REGISTERIMAGE)
483 {
484 RTPrintf("VBoxManage registerimage disk|dvd|floppy <filename>\n"
485 " [-type normal|immutable|writethrough] (disk only)\n"
486 "\n");
487 }
488
489 if (u64Cmd & USAGE_UNREGISTERIMAGE)
490 {
491 RTPrintf("VBoxManage unregisterimage disk|dvd|floppy <uuid>|<filename>\n"
492 "\n");
493 }
494
495 if (u64Cmd & USAGE_SHOWVDIINFO)
496 {
497 RTPrintf("VBoxManage showvdiinfo <uuid>|<filename>\n"
498 "\n");
499 }
500
501 if (u64Cmd & USAGE_CREATEVDI)
502 {
503 RTPrintf("VBoxManage createvdi -filename <filename>\n"
504 " -size <megabytes>\n"
505 " [-static]\n"
506 " [-comment <comment>]\n"
507 " [-register]\n"
508 " [-type normal|writethrough] (default: normal)\n"
509 "\n");
510 }
511
512 if (u64Cmd & USAGE_MODIFYVDI)
513 {
514 RTPrintf("VBoxManage modifyvdi <uuid>|<filename>\n"
515#if 0 /* doesn't currently work */
516 " settype normal|writethrough|immutable |\n"
517#endif
518 " compact\n"
519 "\n");
520 }
521
522 if (u64Cmd & USAGE_CLONEVDI)
523 {
524 RTPrintf("VBoxManage clonevdi <uuid>|<filename> <outputfile>\n"
525 "\n");
526 }
527
528 if (u64Cmd & USAGE_CONVERTDD)
529 {
530 RTPrintf("VBoxManage convertdd <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 (strcmp(argv[1], "keyboardputscancode") == 0)
5568 {
5569 ComPtr<IKeyboard> keyboard;
5570 CHECK_ERROR_BREAK(console, COMGETTER(Keyboard)(keyboard.asOutParam()));
5571
5572 if (argc <= 1 + 1)
5573 {
5574 errorArgument("Missing argument to '%s'. Expected IBM PC AT set 2 keyboard scancode(s) as hex byte(s).", argv[1]);
5575 rc = E_FAIL;
5576 break;
5577 }
5578
5579 /* Arbitrary restrict the length of a sequence of scancodes to 1024. */
5580 LONG alScancodes[1024];
5581 int cScancodes = 0;
5582
5583 /* Process the command line. */
5584 int i;
5585 for (i = 1 + 1; i < argc && cScancodes < (int)RT_ELEMENTS(alScancodes); i++, cScancodes++)
5586 {
5587 if ( isxdigit (argv[i][0])
5588 && isxdigit (argv[i][1])
5589 && argv[i][2] == 0)
5590 {
5591 uint8_t u8Scancode;
5592 int rc = RTStrToUInt8Ex(argv[i], NULL, 16, &u8Scancode);
5593 if (RT_FAILURE (rc))
5594 {
5595 RTPrintf("Error: converting '%s' returned %Vrc!\n", argv[i], rc);
5596 rc = E_FAIL;
5597 break;
5598 }
5599
5600 alScancodes[cScancodes] = u8Scancode;
5601 }
5602 else
5603 {
5604 RTPrintf("Error: '%s' is not a hex byte!\n", argv[i]);
5605 rc = E_FAIL;
5606 break;
5607 }
5608 }
5609
5610 if (FAILED(rc))
5611 break;
5612
5613 if ( cScancodes == RT_ELEMENTS(alScancodes)
5614 && i < argc)
5615 {
5616 RTPrintf("Error: too many scancodes, maximum %d allowed!\n", RT_ELEMENTS(alScancodes));
5617 rc = E_FAIL;
5618 break;
5619 }
5620
5621 /* Send scancodes to the VM.
5622 * Note: 'PutScancodes' did not work here. Only the first scancode was transmitted.
5623 */
5624 for (i = 0; i < cScancodes; i++)
5625 {
5626 CHECK_ERROR_BREAK(keyboard, PutScancode(alScancodes[i]));
5627 RTPrintf("Scancode[%d]: 0x%02X\n", i, alScancodes[i]);
5628 }
5629 }
5630 else if (strncmp(argv[1], "setlinkstate", 12) == 0)
5631 {
5632 /* Get the number of network adapters */
5633 ULONG NetworkAdapterCount = 0;
5634 ComPtr <ISystemProperties> info;
5635 CHECK_ERROR_BREAK (virtualBox, COMGETTER(SystemProperties) (info.asOutParam()));
5636 CHECK_ERROR_BREAK (info, COMGETTER(NetworkAdapterCount) (&NetworkAdapterCount));
5637
5638 unsigned n = parseNum(&argv[1][12], NetworkAdapterCount, "NIC");
5639 if (!n)
5640 {
5641 rc = E_FAIL;
5642 break;
5643 }
5644 if (argc <= 1 + 1)
5645 {
5646 errorArgument("Missing argument to '%s'", argv[1]);
5647 rc = E_FAIL;
5648 break;
5649 }
5650 /* get the corresponding network adapter */
5651 ComPtr<INetworkAdapter> adapter;
5652 CHECK_ERROR_BREAK (sessionMachine, GetNetworkAdapter(n - 1, adapter.asOutParam()));
5653 if (adapter)
5654 {
5655 if (strcmp(argv[2], "on") == 0)
5656 {
5657 CHECK_ERROR_BREAK (adapter, COMSETTER(CableConnected)(TRUE));
5658 }
5659 else if (strcmp(argv[2], "off") == 0)
5660 {
5661 CHECK_ERROR_BREAK (adapter, COMSETTER(CableConnected)(FALSE));
5662 }
5663 else
5664 {
5665 errorArgument("Invalid link state '%s'", Utf8Str(argv[2]).raw());
5666 rc = E_FAIL;
5667 break;
5668 }
5669 }
5670 }
5671 else if (strcmp (argv[1], "usbattach") == 0 ||
5672 strcmp (argv[1], "usbdetach") == 0)
5673 {
5674 if (argc < 3)
5675 {
5676 errorSyntax(USAGE_CONTROLVM, "Not enough parameters");
5677 rc = E_FAIL;
5678 break;
5679 }
5680
5681 bool attach = strcmp (argv[1], "usbattach") == 0;
5682
5683 Guid usbId = argv [2];
5684 if (usbId.isEmpty())
5685 {
5686 // assume address
5687 if (attach)
5688 {
5689 ComPtr <IHost> host;
5690 CHECK_ERROR_BREAK (virtualBox, COMGETTER(Host) (host.asOutParam()));
5691 ComPtr <IHostUSBDeviceCollection> coll;
5692 CHECK_ERROR_BREAK (host, COMGETTER(USBDevices) (coll.asOutParam()));
5693 ComPtr <IHostUSBDevice> dev;
5694 CHECK_ERROR_BREAK (coll, FindByAddress (Bstr (argv [2]), dev.asOutParam()));
5695 CHECK_ERROR_BREAK (dev, COMGETTER(Id) (usbId.asOutParam()));
5696 }
5697 else
5698 {
5699 ComPtr <IUSBDeviceCollection> coll;
5700 CHECK_ERROR_BREAK (console, COMGETTER(USBDevices)(coll.asOutParam()));
5701 ComPtr <IUSBDevice> dev;
5702 CHECK_ERROR_BREAK (coll, FindByAddress (Bstr (argv [2]), dev.asOutParam()));
5703 CHECK_ERROR_BREAK (dev, COMGETTER(Id) (usbId.asOutParam()));
5704 }
5705 }
5706
5707 if (attach)
5708 CHECK_ERROR_BREAK (console, AttachUSBDevice (usbId));
5709 else
5710 {
5711 ComPtr <IUSBDevice> dev;
5712 CHECK_ERROR_BREAK (console, DetachUSBDevice (usbId, dev.asOutParam()));
5713 }
5714 }
5715 else if (strcmp(argv[1], "setvideomodehint") == 0)
5716 {
5717 if (argc != 5 && argc != 6)
5718 {
5719 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
5720 rc = E_FAIL;
5721 break;
5722 }
5723 uint32_t xres = atoi(argv[2]);
5724 uint32_t yres = atoi(argv[3]);
5725 uint32_t bpp = atoi(argv[4]);
5726 uint32_t displayIdx = 0;
5727 if (argc == 6)
5728 displayIdx = atoi(argv[5]);
5729
5730 ComPtr<IDisplay> display;
5731 CHECK_ERROR_BREAK(console, COMGETTER(Display)(display.asOutParam()));
5732 CHECK_ERROR_BREAK(display, SetVideoModeHint(xres, yres, bpp, displayIdx));
5733 }
5734 else if (strcmp(argv[1], "setcredentials") == 0)
5735 {
5736 bool fAllowLocalLogon = true;
5737 if (argc == 7)
5738 {
5739 if (strcmp(argv[5], "-allowlocallogon") != 0)
5740 {
5741 errorArgument("Invalid parameter '%s'", argv[5]);
5742 rc = E_FAIL;
5743 break;
5744 }
5745 if (strcmp(argv[6], "no") == 0)
5746 fAllowLocalLogon = false;
5747 }
5748 else if (argc != 5)
5749 {
5750 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
5751 rc = E_FAIL;
5752 break;
5753 }
5754
5755 ComPtr<IGuest> guest;
5756 CHECK_ERROR_BREAK(console, COMGETTER(Guest)(guest.asOutParam()));
5757 CHECK_ERROR_BREAK(guest, SetCredentials(Bstr(argv[2]), Bstr(argv[3]), Bstr(argv[4]), fAllowLocalLogon));
5758 }
5759 else if (strcmp(argv[1], "dvdattach") == 0)
5760 {
5761 if (argc != 3)
5762 {
5763 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
5764 rc = E_FAIL;
5765 break;
5766 }
5767 ComPtr<IDVDDrive> dvdDrive;
5768 sessionMachine->COMGETTER(DVDDrive)(dvdDrive.asOutParam());
5769 ASSERT(dvdDrive);
5770
5771 /* unmount? */
5772 if (strcmp(argv[2], "none") == 0)
5773 {
5774 CHECK_ERROR(dvdDrive, Unmount());
5775 }
5776 /* host drive? */
5777 else if (strncmp(argv[2], "host:", 5) == 0)
5778 {
5779 ComPtr<IHost> host;
5780 CHECK_ERROR(virtualBox, COMGETTER(Host)(host.asOutParam()));
5781 ComPtr<IHostDVDDriveCollection> hostDVDs;
5782 CHECK_ERROR(host, COMGETTER(DVDDrives)(hostDVDs.asOutParam()));
5783 ComPtr<IHostDVDDrive> hostDVDDrive;
5784 rc = hostDVDs->FindByName(Bstr(argv[2] + 5), hostDVDDrive.asOutParam());
5785 if (!hostDVDDrive)
5786 {
5787 errorArgument("Invalid host DVD drive name");
5788 rc = E_FAIL;
5789 break;
5790 }
5791 CHECK_ERROR(dvdDrive, CaptureHostDrive(hostDVDDrive));
5792 }
5793 else
5794 {
5795 /* first assume it's a UUID */
5796 Guid uuid(argv[2]);
5797 ComPtr<IDVDImage> dvdImage;
5798 rc = virtualBox->GetDVDImage(uuid, dvdImage.asOutParam());
5799 if (FAILED(rc) || !dvdImage)
5800 {
5801 /* must be a filename, check if it's in the collection */
5802 ComPtr<IDVDImageCollection> dvdImages;
5803 virtualBox->COMGETTER(DVDImages)(dvdImages.asOutParam());
5804 rc = dvdImages->FindByPath(Bstr(argv[2]), dvdImage.asOutParam());
5805 /* not registered, do that on the fly */
5806 if (!dvdImage)
5807 {
5808 Guid emptyUUID;
5809 CHECK_ERROR(virtualBox, OpenDVDImage(Bstr(argv[2]), emptyUUID, dvdImage.asOutParam()));
5810 if (SUCCEEDED(rc) && dvdImage)
5811 {
5812 /* time to register the image */
5813 CHECK_ERROR(virtualBox, RegisterDVDImage(dvdImage));
5814 }
5815 }
5816 }
5817 if (!dvdImage)
5818 {
5819 rc = E_FAIL;
5820 break;
5821 }
5822 dvdImage->COMGETTER(Id)(uuid.asOutParam());
5823 CHECK_ERROR(dvdDrive, MountImage(uuid));
5824 }
5825 }
5826 else if (strcmp(argv[1], "floppyattach") == 0)
5827 {
5828 if (argc != 3)
5829 {
5830 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
5831 rc = E_FAIL;
5832 break;
5833 }
5834
5835 ComPtr<IFloppyDrive> floppyDrive;
5836 sessionMachine->COMGETTER(FloppyDrive)(floppyDrive.asOutParam());
5837 ASSERT(floppyDrive);
5838
5839 /* unmount? */
5840 if (strcmp(argv[2], "none") == 0)
5841 {
5842 CHECK_ERROR(floppyDrive, Unmount());
5843 }
5844 /* host drive? */
5845 else if (strncmp(argv[2], "host:", 5) == 0)
5846 {
5847 ComPtr<IHost> host;
5848 CHECK_ERROR(virtualBox, COMGETTER(Host)(host.asOutParam()));
5849 ComPtr<IHostFloppyDriveCollection> hostFloppies;
5850 CHECK_ERROR(host, COMGETTER(FloppyDrives)(hostFloppies.asOutParam()));
5851 ComPtr<IHostFloppyDrive> hostFloppyDrive;
5852 rc = hostFloppies->FindByName(Bstr(argv[2] + 5), hostFloppyDrive.asOutParam());
5853 if (!hostFloppyDrive)
5854 {
5855 errorArgument("Invalid host floppy drive name");
5856 rc = E_FAIL;
5857 break;
5858 }
5859 CHECK_ERROR(floppyDrive, CaptureHostDrive(hostFloppyDrive));
5860 }
5861 else
5862 {
5863 /* first assume it's a UUID */
5864 Guid uuid(argv[2]);
5865 ComPtr<IFloppyImage> floppyImage;
5866 rc = virtualBox->GetFloppyImage(uuid, floppyImage.asOutParam());
5867 if (FAILED(rc) || !floppyImage)
5868 {
5869 /* must be a filename, check if it's in the collection */
5870 ComPtr<IFloppyImageCollection> floppyImages;
5871 virtualBox->COMGETTER(FloppyImages)(floppyImages.asOutParam());
5872 rc = floppyImages->FindByPath(Bstr(argv[2]), floppyImage.asOutParam());
5873 /* not registered, do that on the fly */
5874 if (!floppyImage)
5875 {
5876 Guid emptyUUID;
5877 CHECK_ERROR(virtualBox, OpenFloppyImage(Bstr(argv[2]), emptyUUID, floppyImage.asOutParam()));
5878 if (SUCCEEDED(rc) && floppyImage)
5879 {
5880 /* time to register the image */
5881 CHECK_ERROR(virtualBox, RegisterFloppyImage(floppyImage));
5882 }
5883 }
5884 }
5885 if (!floppyImage)
5886 {
5887 rc = E_FAIL;
5888 break;
5889 }
5890 floppyImage->COMGETTER(Id)(uuid.asOutParam());
5891 CHECK_ERROR(floppyDrive, MountImage(uuid));
5892 }
5893 }
5894#ifdef VBOX_WITH_MEM_BALLOONING
5895 else if (strncmp(argv[1], "-guestmemoryballoon", 19) == 0)
5896 {
5897 if (argc != 3)
5898 {
5899 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
5900 rc = E_FAIL;
5901 break;
5902 }
5903 uint32_t uVal;
5904 int vrc;
5905 vrc = RTStrToUInt32Ex(argv[2], NULL, 0, &uVal);
5906 if (vrc != VINF_SUCCESS)
5907 {
5908 errorArgument("Error parsing guest memory balloon size '%s'", argv[2]);
5909 rc = E_FAIL;
5910 break;
5911 }
5912
5913 /* guest is running; update IGuest */
5914 ComPtr <IGuest> guest;
5915
5916 rc = console->COMGETTER(Guest)(guest.asOutParam());
5917 if (SUCCEEDED(rc))
5918 CHECK_ERROR(guest, COMSETTER(MemoryBalloonSize)(uVal));
5919 }
5920#endif
5921 else if (strncmp(argv[1], "-gueststatisticsinterval", 24) == 0)
5922 {
5923 if (argc != 3)
5924 {
5925 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
5926 rc = E_FAIL;
5927 break;
5928 }
5929 uint32_t uVal;
5930 int vrc;
5931 vrc = RTStrToUInt32Ex(argv[2], NULL, 0, &uVal);
5932 if (vrc != VINF_SUCCESS)
5933 {
5934 errorArgument("Error parsing guest statistics interval '%s'", argv[2]);
5935 rc = E_FAIL;
5936 break;
5937 }
5938
5939 /* guest is running; update IGuest */
5940 ComPtr <IGuest> guest;
5941
5942 rc = console->COMGETTER(Guest)(guest.asOutParam());
5943 if (SUCCEEDED(rc))
5944 CHECK_ERROR(guest, COMSETTER(StatisticsUpdateInterval)(uVal));
5945 }
5946 else
5947 {
5948 errorSyntax(USAGE_CONTROLVM, "Invalid parameter '%s'", Utf8Str(argv[1]).raw());
5949 rc = E_FAIL;
5950 }
5951 }
5952 while (0);
5953
5954 session->Close();
5955
5956 return SUCCEEDED (rc) ? 0 : 1;
5957}
5958
5959static int handleDiscardState(int argc, char *argv[],
5960 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)
5961{
5962 HRESULT rc;
5963
5964 if (argc != 1)
5965 return errorSyntax(USAGE_DISCARDSTATE, "Incorrect number of parameters");
5966
5967 ComPtr<IMachine> machine;
5968 /* assume it's a UUID */
5969 rc = virtualBox->GetMachine(Guid(argv[0]), machine.asOutParam());
5970 if (FAILED(rc) || !machine)
5971 {
5972 /* must be a name */
5973 CHECK_ERROR(virtualBox, FindMachine(Bstr(argv[0]), machine.asOutParam()));
5974 }
5975 if (machine)
5976 {
5977 do
5978 {
5979 /* we have to open a session for this task */
5980 Guid guid;
5981 machine->COMGETTER(Id)(guid.asOutParam());
5982 CHECK_ERROR_BREAK(virtualBox, OpenSession(session, guid));
5983 do
5984 {
5985 ComPtr<IConsole> console;
5986 CHECK_ERROR_BREAK(session, COMGETTER(Console)(console.asOutParam()));
5987 CHECK_ERROR_BREAK(console, DiscardSavedState());
5988 }
5989 while (0);
5990 CHECK_ERROR_BREAK(session, Close());
5991 }
5992 while (0);
5993 }
5994
5995 return SUCCEEDED(rc) ? 0 : 1;
5996}
5997
5998static int handleAdoptdState(int argc, char *argv[],
5999 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)
6000{
6001 HRESULT rc;
6002
6003 if (argc != 2)
6004 return errorSyntax(USAGE_ADOPTSTATE, "Incorrect number of parameters");
6005
6006 ComPtr<IMachine> machine;
6007 /* assume it's a UUID */
6008 rc = virtualBox->GetMachine(Guid(argv[0]), machine.asOutParam());
6009 if (FAILED(rc) || !machine)
6010 {
6011 /* must be a name */
6012 CHECK_ERROR(virtualBox, FindMachine(Bstr(argv[0]), machine.asOutParam()));
6013 }
6014 if (machine)
6015 {
6016 do
6017 {
6018 /* we have to open a session for this task */
6019 Guid guid;
6020 machine->COMGETTER(Id)(guid.asOutParam());
6021 CHECK_ERROR_BREAK(virtualBox, OpenSession(session, guid));
6022 do
6023 {
6024 ComPtr<IConsole> console;
6025 CHECK_ERROR_BREAK(session, COMGETTER(Console)(console.asOutParam()));
6026 CHECK_ERROR_BREAK(console, AdoptSavedState (Bstr (argv[1])));
6027 }
6028 while (0);
6029 CHECK_ERROR_BREAK(session, Close());
6030 }
6031 while (0);
6032 }
6033
6034 return SUCCEEDED(rc) ? 0 : 1;
6035}
6036
6037static int handleSnapshot(int argc, char *argv[],
6038 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)
6039{
6040 HRESULT rc;
6041
6042 /* we need at least a VM and a command */
6043 if (argc < 2)
6044 return errorSyntax(USAGE_SNAPSHOT, "Not enough parameters");
6045
6046 /* the first argument must be the VM */
6047 ComPtr<IMachine> machine;
6048 /* assume it's a UUID */
6049 rc = virtualBox->GetMachine(Guid(argv[0]), machine.asOutParam());
6050 if (FAILED(rc) || !machine)
6051 {
6052 /* must be a name */
6053 CHECK_ERROR(virtualBox, FindMachine(Bstr(argv[0]), machine.asOutParam()));
6054 }
6055 if (!machine)
6056 return 1;
6057 Guid guid;
6058 machine->COMGETTER(Id)(guid.asOutParam());
6059
6060 do
6061 {
6062 /* we have to open a session for this task. First try an existing session */
6063 rc = virtualBox->OpenExistingSession(session, guid);
6064 if (FAILED(rc))
6065 CHECK_ERROR_BREAK(virtualBox, OpenSession(session, guid));
6066 ComPtr<IConsole> console;
6067 CHECK_ERROR_BREAK(session, COMGETTER(Console)(console.asOutParam()));
6068
6069 /* switch based on the command */
6070 if (strcmp(argv[1], "take") == 0)
6071 {
6072 /* there must be a name */
6073 if (argc < 3)
6074 {
6075 errorSyntax(USAGE_SNAPSHOT, "Missing snapshot name");
6076 rc = E_FAIL;
6077 break;
6078 }
6079 Bstr name(argv[2]);
6080 if ((argc > 3) && ((argc != 5) || (strcmp(argv[3], "-desc") != 0)))
6081 {
6082 errorSyntax(USAGE_SNAPSHOT, "Incorrect description format");
6083 rc = E_FAIL;
6084 break;
6085 }
6086 Bstr desc;
6087 if (argc == 5)
6088 desc = argv[4];
6089 ComPtr<IProgress> progress;
6090 CHECK_ERROR_BREAK(console, TakeSnapshot(name, desc, progress.asOutParam()));
6091
6092 showProgress(progress);
6093 progress->COMGETTER(ResultCode)(&rc);
6094 if (FAILED(rc))
6095 {
6096 com::ProgressErrorInfo info(progress);
6097 if (info.isBasicAvailable())
6098 RTPrintf("Error: failed to take snapshot. Error message: %lS\n", info.getText().raw());
6099 else
6100 RTPrintf("Error: failed to take snapshot. No error message available!\n");
6101 }
6102 }
6103 else if (strcmp(argv[1], "discard") == 0)
6104 {
6105 /* exactly one parameter: snapshot name */
6106 if (argc != 3)
6107 {
6108 errorSyntax(USAGE_SNAPSHOT, "Expecting snapshot name only");
6109 rc = E_FAIL;
6110 break;
6111 }
6112
6113 ComPtr<ISnapshot> snapshot;
6114
6115 /* assume it's a UUID */
6116 Guid guid(argv[2]);
6117 if (!guid.isEmpty())
6118 {
6119 CHECK_ERROR_BREAK(machine, GetSnapshot(guid, snapshot.asOutParam()));
6120 }
6121 else
6122 {
6123 /* then it must be a name */
6124 CHECK_ERROR_BREAK(machine, FindSnapshot(Bstr(argv[2]), snapshot.asOutParam()));
6125 }
6126
6127 snapshot->COMGETTER(Id)(guid.asOutParam());
6128
6129 ComPtr<IProgress> progress;
6130 CHECK_ERROR_BREAK(console, DiscardSnapshot(guid, progress.asOutParam()));
6131
6132 showProgress(progress);
6133 progress->COMGETTER(ResultCode)(&rc);
6134 if (FAILED(rc))
6135 {
6136 com::ProgressErrorInfo info(progress);
6137 if (info.isBasicAvailable())
6138 RTPrintf("Error: failed to discard snapshot. Error message: %lS\n", info.getText().raw());
6139 else
6140 RTPrintf("Error: failed to discard snapshot. No error message available!\n");
6141 }
6142 }
6143 else if (strcmp(argv[1], "discardcurrent") == 0)
6144 {
6145 if ( (argc != 3)
6146 || ( (strcmp(argv[2], "-state") != 0)
6147 && (strcmp(argv[2], "-all") != 0)))
6148 {
6149 errorSyntax(USAGE_SNAPSHOT, "Invalid parameter '%s'", Utf8Str(argv[2]).raw());
6150 rc = E_FAIL;
6151 break;
6152 }
6153 bool fAll = false;
6154 if (strcmp(argv[2], "-all") == 0)
6155 fAll = true;
6156
6157 ComPtr<IProgress> progress;
6158
6159 if (fAll)
6160 {
6161 CHECK_ERROR_BREAK(console, DiscardCurrentSnapshotAndState(progress.asOutParam()));
6162 }
6163 else
6164 {
6165 CHECK_ERROR_BREAK(console, DiscardCurrentState(progress.asOutParam()));
6166 }
6167
6168 showProgress(progress);
6169 progress->COMGETTER(ResultCode)(&rc);
6170 if (FAILED(rc))
6171 {
6172 com::ProgressErrorInfo info(progress);
6173 if (info.isBasicAvailable())
6174 RTPrintf("Error: failed to discard. Error message: %lS\n", info.getText().raw());
6175 else
6176 RTPrintf("Error: failed to discard. No error message available!\n");
6177 }
6178
6179 }
6180 else if (strcmp(argv[1], "edit") == 0)
6181 {
6182 if (argc < 3)
6183 {
6184 errorSyntax(USAGE_SNAPSHOT, "Missing snapshot name");
6185 rc = E_FAIL;
6186 break;
6187 }
6188
6189 ComPtr<ISnapshot> snapshot;
6190
6191 if (strcmp(argv[2], "-current") == 0)
6192 {
6193 CHECK_ERROR_BREAK(machine, COMGETTER(CurrentSnapshot)(snapshot.asOutParam()));
6194 }
6195 else
6196 {
6197 /* assume it's a UUID */
6198 Guid guid(argv[2]);
6199 if (!guid.isEmpty())
6200 {
6201 CHECK_ERROR_BREAK(machine, GetSnapshot(guid, snapshot.asOutParam()));
6202 }
6203 else
6204 {
6205 /* then it must be a name */
6206 CHECK_ERROR_BREAK(machine, FindSnapshot(Bstr(argv[2]), snapshot.asOutParam()));
6207 }
6208 }
6209
6210 /* parse options */
6211 for (int i = 3; i < argc; i++)
6212 {
6213 if (strcmp(argv[i], "-newname") == 0)
6214 {
6215 if (argc <= i + 1)
6216 {
6217 errorArgument("Missing argument to '%s'", argv[i]);
6218 rc = E_FAIL;
6219 break;
6220 }
6221 i++;
6222 snapshot->COMSETTER(Name)(Bstr(argv[i]));
6223 }
6224 else if (strcmp(argv[i], "-newdesc") == 0)
6225 {
6226 if (argc <= i + 1)
6227 {
6228 errorArgument("Missing argument to '%s'", argv[i]);
6229 rc = E_FAIL;
6230 break;
6231 }
6232 i++;
6233 snapshot->COMSETTER(Description)(Bstr(argv[i]));
6234 }
6235 else
6236 {
6237 errorSyntax(USAGE_SNAPSHOT, "Invalid parameter '%s'", Utf8Str(argv[i]).raw());
6238 rc = E_FAIL;
6239 break;
6240 }
6241 }
6242
6243 }
6244 else if (strcmp(argv[1], "showvminfo") == 0)
6245 {
6246 /* exactly one parameter: snapshot name */
6247 if (argc != 3)
6248 {
6249 errorSyntax(USAGE_SNAPSHOT, "Expecting snapshot name only");
6250 rc = E_FAIL;
6251 break;
6252 }
6253
6254 ComPtr<ISnapshot> snapshot;
6255
6256 /* assume it's a UUID */
6257 Guid guid(argv[2]);
6258 if (!guid.isEmpty())
6259 {
6260 CHECK_ERROR_BREAK(machine, GetSnapshot(guid, snapshot.asOutParam()));
6261 }
6262 else
6263 {
6264 /* then it must be a name */
6265 CHECK_ERROR_BREAK(machine, FindSnapshot(Bstr(argv[2]), snapshot.asOutParam()));
6266 }
6267
6268 /* get the machine of the given snapshot */
6269 ComPtr<IMachine> machine;
6270 snapshot->COMGETTER(Machine)(machine.asOutParam());
6271 showVMInfo(virtualBox, machine, console);
6272 }
6273 else
6274 {
6275 errorSyntax(USAGE_SNAPSHOT, "Invalid parameter '%s'", Utf8Str(argv[1]).raw());
6276 rc = E_FAIL;
6277 }
6278 } while (0);
6279
6280 session->Close();
6281
6282 return SUCCEEDED(rc) ? 0 : 1;
6283}
6284
6285static int handleShowVDIInfo(int argc, char *argv[],
6286 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)
6287{
6288 HRESULT rc;
6289
6290 if (argc != 1)
6291 return errorSyntax(USAGE_SHOWVDIINFO, "Incorrect number of parameters");
6292
6293 ComPtr<IHardDisk> hardDisk;
6294 Bstr filepath;
6295
6296 bool registered = true;
6297
6298 /* first guess is that it's a UUID */
6299 Guid uuid(argv[0]);
6300 rc = virtualBox->GetHardDisk(uuid, hardDisk.asOutParam());
6301 /* no? then it must be a filename */
6302 if (FAILED (rc))
6303 {
6304 filepath = argv[0];
6305 rc = virtualBox->FindHardDisk(filepath, hardDisk.asOutParam());
6306 /* no? well, then it's an unregistered image */
6307 if (FAILED (rc))
6308 {
6309 registered = false;
6310 CHECK_ERROR(virtualBox, OpenHardDisk(filepath, hardDisk.asOutParam()));
6311 }
6312 }
6313 if (SUCCEEDED(rc) && hardDisk)
6314 {
6315 /* query a VDI object (will remain null if it's not VDI) */
6316 ComPtr<IVirtualDiskImage> vdi = hardDisk;
6317
6318 hardDisk->COMGETTER(Id)(uuid.asOutParam());
6319 RTPrintf("UUID: %s\n", uuid.toString().raw());
6320
6321 RTPrintf("Registered: %s\n", registered ? "yes" : "no");
6322
6323 /* check for accessibility */
6324 BOOL accessible = FALSE;
6325 CHECK_ERROR_RET (hardDisk, COMGETTER(Accessible)(&accessible), 1);
6326 RTPrintf("Accessible: %s\n", accessible ? "yes" : "no");
6327
6328 if (!accessible)
6329 {
6330 Bstr err;
6331 CHECK_ERROR_RET (hardDisk, COMGETTER(LastAccessError)(err.asOutParam()), 1);
6332 RTPrintf("Access Error: %lS\n", err.raw());
6333 }
6334
6335 Bstr description;
6336 hardDisk->COMGETTER(Description)(description.asOutParam());
6337 if (description)
6338 {
6339 RTPrintf("Description: %lS\n", description.raw());
6340 }
6341
6342 ULONG64 size;
6343 hardDisk->COMGETTER(Size)(&size);
6344 RTPrintf("Size: %llu MBytes\n", size);
6345 ULONG64 actualSize;
6346 hardDisk->COMGETTER(ActualSize)(&actualSize);
6347 RTPrintf("Current size on disk: %llu MBytes\n", actualSize >> 20);
6348
6349 HardDiskType_T type;
6350 hardDisk->COMGETTER(Type)(&type);
6351 const char *typeStr = "unknown";
6352 switch (type)
6353 {
6354 case HardDiskType_Normal:
6355 typeStr = "standard";
6356 break;
6357 case HardDiskType_Immutable:
6358 typeStr = "immutable";
6359 break;
6360 case HardDiskType_Writethrough:
6361 typeStr = "writethrough";
6362 break;
6363 }
6364 RTPrintf("Type: %s\n", typeStr);
6365
6366 HardDiskStorageType_T storageType;
6367 const char *storageTypeStr = "unknown";
6368 hardDisk->COMGETTER(StorageType)(&storageType);
6369 switch (storageType)
6370 {
6371 case HardDiskStorageType_VirtualDiskImage:
6372 storageTypeStr = "Virtual Disk Image (VDI)";
6373 break;
6374 case HardDiskStorageType_VMDKImage:
6375 storageTypeStr = "VMDK Image";
6376 break;
6377 case HardDiskStorageType_ISCSIHardDisk:
6378 storageTypeStr = "iSCSI target";
6379 break;
6380 case HardDiskStorageType_VHDImage:
6381 storageTypeStr = "VHD Image";
6382 break;
6383 }
6384 RTPrintf("Storage type: %s\n", storageTypeStr);
6385
6386 if (registered)
6387 {
6388 hardDisk->COMGETTER(MachineId)(uuid.asOutParam());
6389 RTPrintf("In use by VM: %s\n", uuid ? uuid.toString().raw() : "<none>");
6390 }
6391
6392 if (vdi)
6393 {
6394 /* VDI specific information */
6395 vdi->COMGETTER(FilePath)(filepath.asOutParam());
6396 RTPrintf("Path: %lS\n", filepath.raw());
6397
6398 }
6399 else
6400 {
6401 /* Generic location information */
6402 Bstr loc;
6403 hardDisk->COMGETTER(Location)(loc.asOutParam());
6404 RTPrintf("Location: %lS\n", loc.raw());
6405 }
6406 }
6407 return SUCCEEDED(rc) ? 0 : 1;
6408}
6409
6410static int handleRegisterImage(int argc, char *argv[],
6411 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)
6412{
6413 HRESULT rc;
6414
6415 if (argc < 2)
6416 return errorSyntax(USAGE_REGISTERIMAGE, "Not enough parameters");
6417
6418 Bstr filepath(argv[1]);
6419
6420 if (strcmp(argv[0], "disk") == 0)
6421 {
6422 const char *type = NULL;
6423 /* there can be a type parameter */
6424 if ((argc > 2) && (argc != 4))
6425 return errorSyntax(USAGE_REGISTERIMAGE, "Incorrect number of parameters");
6426 if (argc == 4)
6427 {
6428 if (strcmp(argv[2], "-type") != 0)
6429 return errorSyntax(USAGE_REGISTERIMAGE, "Invalid parameter '%s'", Utf8Str(argv[2]).raw());
6430 if ( (strcmp(argv[3], "normal") != 0)
6431 && (strcmp(argv[3], "immutable") != 0)
6432 && (strcmp(argv[3], "writethrough") != 0))
6433 return errorArgument("Invalid VDI type '%s' specified", Utf8Str(argv[3]).raw());
6434 type = argv[3];
6435 }
6436
6437 ComPtr<IHardDisk> hardDisk;
6438 CHECK_ERROR(virtualBox, OpenHardDisk(filepath, hardDisk.asOutParam()));
6439 if (SUCCEEDED(rc) && hardDisk)
6440 {
6441 /* change the type if requested */
6442 if (type)
6443 {
6444 if (strcmp(type, "normal") == 0)
6445 CHECK_ERROR(hardDisk, COMSETTER(Type)(HardDiskType_Normal));
6446 else if (strcmp(type, "immutable") == 0)
6447 CHECK_ERROR(hardDisk, COMSETTER(Type)(HardDiskType_Immutable));
6448 else if (strcmp(type, "writethrough") == 0)
6449 CHECK_ERROR(hardDisk, COMSETTER(Type)(HardDiskType_Writethrough));
6450 }
6451 if (SUCCEEDED(rc))
6452 CHECK_ERROR(virtualBox, RegisterHardDisk(hardDisk));
6453 }
6454 }
6455 else if (strcmp(argv[0], "dvd") == 0)
6456 {
6457 ComPtr<IDVDImage> dvdImage;
6458 CHECK_ERROR(virtualBox, OpenDVDImage(filepath, Guid(), dvdImage.asOutParam()));
6459 if (SUCCEEDED(rc) && dvdImage)
6460 {
6461 CHECK_ERROR(virtualBox, RegisterDVDImage(dvdImage));
6462 }
6463 }
6464 else if (strcmp(argv[0], "floppy") == 0)
6465 {
6466 ComPtr<IFloppyImage> floppyImage;
6467 CHECK_ERROR(virtualBox, OpenFloppyImage(filepath, Guid(), floppyImage.asOutParam()));
6468 if (SUCCEEDED(rc) && floppyImage)
6469 {
6470 CHECK_ERROR(virtualBox, RegisterFloppyImage(floppyImage));
6471 }
6472 }
6473 else
6474 return errorSyntax(USAGE_REGISTERIMAGE, "Invalid parameter '%s'", Utf8Str(argv[1]).raw());
6475
6476 return SUCCEEDED(rc) ? 0 : 1;
6477}
6478
6479static int handleUnregisterImage(int argc, char *argv[],
6480 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)
6481{
6482 HRESULT rc;
6483
6484 if (argc != 2)
6485 return errorSyntax(USAGE_UNREGISTERIMAGE, "Incorrect number of parameters");
6486
6487 /* first guess is that it's a UUID */
6488 Guid uuid(argv[1]);
6489
6490 if (strcmp(argv[0], "disk") == 0)
6491 {
6492 ComPtr<IHardDisk> hardDisk;
6493 rc = virtualBox->GetHardDisk(uuid, hardDisk.asOutParam());
6494 /* not a UUID or not registered? Then it must be a filename */
6495 if (!hardDisk)
6496 {
6497 ComPtr<IVirtualDiskImage> vdi;
6498 CHECK_ERROR(virtualBox, FindVirtualDiskImage(Bstr(argv[1]), vdi.asOutParam()));
6499 hardDisk = vdi;
6500 }
6501 if (SUCCEEDED(rc) && hardDisk)
6502 {
6503 hardDisk->COMGETTER(Id)(uuid.asOutParam());
6504 CHECK_ERROR(virtualBox, UnregisterHardDisk(uuid, hardDisk.asOutParam()));
6505 }
6506 }
6507 else
6508 if (strcmp(argv[0], "dvd") == 0)
6509 {
6510 ComPtr<IDVDImage> dvdImage;
6511 rc = virtualBox->GetDVDImage(uuid, dvdImage.asOutParam());
6512 /* not a UUID or not registered? Then it must be a filename */
6513 if (!dvdImage)
6514 {
6515 ComPtr<IDVDImageCollection> dvdColl;
6516 virtualBox->COMGETTER(DVDImages)(dvdColl.asOutParam());
6517 CHECK_ERROR(dvdColl, FindByPath(Bstr(argv[1]), dvdImage.asOutParam()));
6518 }
6519 if (SUCCEEDED(rc) && dvdImage)
6520 {
6521 dvdImage->COMGETTER(Id)(uuid.asOutParam());
6522 CHECK_ERROR(virtualBox, UnregisterDVDImage(uuid, dvdImage.asOutParam()));
6523 }
6524 }
6525 else
6526 if (strcmp(argv[0], "floppy") == 0)
6527 {
6528 ComPtr<IFloppyImage> floppyImage;
6529 rc = virtualBox->GetFloppyImage(uuid, floppyImage.asOutParam());
6530 /* not a UUID or not registered? Then it must be a filename */
6531 if (!floppyImage)
6532 {
6533 ComPtr<IFloppyImageCollection> floppyColl;
6534 virtualBox->COMGETTER(FloppyImages)(floppyColl.asOutParam());
6535 CHECK_ERROR(floppyColl, FindByPath(Bstr(argv[1]), floppyImage.asOutParam()));
6536 }
6537 if (SUCCEEDED(rc) && floppyImage)
6538 {
6539 floppyImage->COMGETTER(Id)(uuid.asOutParam());
6540 CHECK_ERROR(virtualBox, UnregisterFloppyImage(uuid, floppyImage.asOutParam()));
6541 }
6542 }
6543 else
6544 return errorSyntax(USAGE_UNREGISTERIMAGE, "Invalid parameter '%s'", Utf8Str(argv[1]).raw());
6545
6546 return SUCCEEDED(rc) ? 0 : 1;
6547}
6548
6549#ifdef RT_OS_WINDOWS
6550static int handleCreateHostIF(int argc, char *argv[],
6551 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)
6552{
6553 if (argc != 1)
6554 return errorSyntax(USAGE_CREATEHOSTIF, "Incorrect number of parameters");
6555
6556 HRESULT rc = S_OK;
6557
6558 do
6559 {
6560 ComPtr<IHost> host;
6561 CHECK_ERROR_BREAK(virtualBox, COMGETTER(Host)(host.asOutParam()));
6562
6563 ComPtr<IHostNetworkInterface> hostif;
6564 ComPtr<IProgress> progress;
6565 CHECK_ERROR_BREAK(host,
6566 CreateHostNetworkInterface(Bstr(argv[0]),
6567 hostif.asOutParam(),
6568 progress.asOutParam()));
6569
6570 showProgress(progress);
6571 HRESULT result;
6572 CHECK_ERROR_BREAK(progress, COMGETTER(ResultCode)(&result));
6573 if (FAILED(result))
6574 {
6575 com::ProgressErrorInfo info(progress);
6576 PRINT_ERROR_INFO(info);
6577 rc = result;
6578 }
6579 }
6580 while (0);
6581
6582 return SUCCEEDED(rc) ? 0 : 1;
6583}
6584
6585static int handleRemoveHostIF(int argc, char *argv[],
6586 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)
6587{
6588 if (argc != 1)
6589 return errorSyntax(USAGE_REMOVEHOSTIF, "Incorrect number of parameters");
6590
6591 HRESULT rc = S_OK;
6592
6593 do
6594 {
6595 ComPtr<IHost> host;
6596 CHECK_ERROR_BREAK(virtualBox, COMGETTER(Host)(host.asOutParam()));
6597
6598 ComPtr<IHostNetworkInterface> hostif;
6599
6600 /* first guess is that it's a UUID */
6601 Guid uuid(argv[0]);
6602 if (uuid.isEmpty())
6603 {
6604 /* not a valid UUID, search for it */
6605 ComPtr<IHostNetworkInterfaceCollection> coll;
6606 CHECK_ERROR_BREAK(host, COMGETTER(NetworkInterfaces)(coll.asOutParam()));
6607 CHECK_ERROR_BREAK(coll, FindByName(Bstr(argv[0]), hostif.asOutParam()));
6608 CHECK_ERROR_BREAK(hostif, COMGETTER(Id)(uuid.asOutParam()));
6609 }
6610
6611 ComPtr<IProgress> progress;
6612 CHECK_ERROR_BREAK(host,
6613 RemoveHostNetworkInterface(uuid,
6614 hostif.asOutParam(),
6615 progress.asOutParam()));
6616
6617 showProgress(progress);
6618 HRESULT result;
6619 CHECK_ERROR_BREAK(progress, COMGETTER(ResultCode)(&result));
6620 if (FAILED(result))
6621 {
6622 com::ProgressErrorInfo info(progress);
6623 PRINT_ERROR_INFO(info);
6624 rc = result;
6625 }
6626 }
6627 while (0);
6628
6629 return SUCCEEDED(rc) ? 0 : 1;
6630}
6631#endif /* RT_OS_WINDOWS */
6632
6633static int handleGetExtraData(int argc, char *argv[],
6634 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)
6635{
6636 HRESULT rc = S_OK;
6637
6638 if (argc != 2)
6639 return errorSyntax(USAGE_GETEXTRADATA, "Incorrect number of parameters");
6640
6641 /* global data? */
6642 if (strcmp(argv[0], "global") == 0)
6643 {
6644 /* enumeration? */
6645 if (strcmp(argv[1], "enumerate") == 0)
6646 {
6647 Bstr extraDataKey;
6648
6649 do
6650 {
6651 Bstr nextExtraDataKey;
6652 Bstr nextExtraDataValue;
6653 HRESULT rcEnum = virtualBox->GetNextExtraDataKey(extraDataKey, nextExtraDataKey.asOutParam(),
6654 nextExtraDataValue.asOutParam());
6655 extraDataKey = nextExtraDataKey;
6656
6657 if (SUCCEEDED(rcEnum) && extraDataKey)
6658 RTPrintf("Key: %lS, Value: %lS\n", nextExtraDataKey.raw(), nextExtraDataValue.raw());
6659 } while (extraDataKey);
6660 }
6661 else
6662 {
6663 Bstr value;
6664 CHECK_ERROR(virtualBox, GetExtraData(Bstr(argv[1]), value.asOutParam()));
6665 if (value)
6666 RTPrintf("Value: %lS\n", value.raw());
6667 else
6668 RTPrintf("No value set!\n");
6669 }
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 /* enumeration? */
6684 if (strcmp(argv[1], "enumerate") == 0)
6685 {
6686 Bstr extraDataKey;
6687
6688 do
6689 {
6690 Bstr nextExtraDataKey;
6691 Bstr nextExtraDataValue;
6692 HRESULT rcEnum = machine->GetNextExtraDataKey(extraDataKey, nextExtraDataKey.asOutParam(),
6693 nextExtraDataValue.asOutParam());
6694 extraDataKey = nextExtraDataKey;
6695
6696 if (SUCCEEDED(rcEnum) && extraDataKey)
6697 {
6698 RTPrintf("Key: %lS, Value: %lS\n", nextExtraDataKey.raw(), nextExtraDataValue.raw());
6699 }
6700 } while (extraDataKey);
6701 }
6702 else
6703 {
6704 Bstr value;
6705 CHECK_ERROR(machine, GetExtraData(Bstr(argv[1]), value.asOutParam()));
6706 if (value)
6707 RTPrintf("Value: %lS\n", value.raw());
6708 else
6709 RTPrintf("No value set!\n");
6710 }
6711 }
6712 }
6713 return SUCCEEDED(rc) ? 0 : 1;
6714}
6715
6716static int handleSetExtraData(int argc, char *argv[],
6717 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)
6718{
6719 HRESULT rc = S_OK;
6720
6721 if (argc < 2)
6722 return errorSyntax(USAGE_SETEXTRADATA, "Not enough parameters");
6723
6724 /* global data? */
6725 if (strcmp(argv[0], "global") == 0)
6726 {
6727 if (argc < 3)
6728 CHECK_ERROR(virtualBox, SetExtraData(Bstr(argv[1]), NULL));
6729 else if (argc == 3)
6730 CHECK_ERROR(virtualBox, SetExtraData(Bstr(argv[1]), Bstr(argv[2])));
6731 else
6732 return errorSyntax(USAGE_SETEXTRADATA, "Too many parameters");
6733 }
6734 else
6735 {
6736 ComPtr<IMachine> machine;
6737 /* assume it's a UUID */
6738 rc = virtualBox->GetMachine(Guid(argv[0]), machine.asOutParam());
6739 if (FAILED(rc) || !machine)
6740 {
6741 /* must be a name */
6742 CHECK_ERROR(virtualBox, FindMachine(Bstr(argv[0]), machine.asOutParam()));
6743 }
6744 if (machine)
6745 {
6746 if (argc < 3)
6747 CHECK_ERROR(machine, SetExtraData(Bstr(argv[1]), NULL));
6748 else if (argc == 3)
6749 CHECK_ERROR(machine, SetExtraData(Bstr(argv[1]), Bstr(argv[2])));
6750 else
6751 return errorSyntax(USAGE_SETEXTRADATA, "Too many parameters");
6752 }
6753 }
6754 return SUCCEEDED(rc) ? 0 : 1;
6755}
6756
6757static int handleSetProperty(int argc, char *argv[],
6758 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)
6759{
6760 HRESULT rc;
6761
6762 /* there must be two arguments: property name and value */
6763 if (argc != 2)
6764 return errorSyntax(USAGE_SETPROPERTY, "Incorrect number of parameters");
6765
6766 ComPtr<ISystemProperties> systemProperties;
6767 virtualBox->COMGETTER(SystemProperties)(systemProperties.asOutParam());
6768
6769 if (strcmp(argv[0], "vdifolder") == 0)
6770 {
6771 /* reset to default? */
6772 if (strcmp(argv[1], "default") == 0)
6773 CHECK_ERROR(systemProperties, COMSETTER(DefaultVDIFolder)(NULL));
6774 else
6775 CHECK_ERROR(systemProperties, COMSETTER(DefaultVDIFolder)(Bstr(argv[1])));
6776 }
6777 else if (strcmp(argv[0], "machinefolder") == 0)
6778 {
6779 /* reset to default? */
6780 if (strcmp(argv[1], "default") == 0)
6781 CHECK_ERROR(systemProperties, COMSETTER(DefaultMachineFolder)(NULL));
6782 else
6783 CHECK_ERROR(systemProperties, COMSETTER(DefaultMachineFolder)(Bstr(argv[1])));
6784 }
6785 else if (strcmp(argv[0], "vrdpauthlibrary") == 0)
6786 {
6787 /* reset to default? */
6788 if (strcmp(argv[1], "default") == 0)
6789 CHECK_ERROR(systemProperties, COMSETTER(RemoteDisplayAuthLibrary)(NULL));
6790 else
6791 CHECK_ERROR(systemProperties, COMSETTER(RemoteDisplayAuthLibrary)(Bstr(argv[1])));
6792 }
6793 else if (strcmp(argv[0], "websrvauthlibrary") == 0)
6794 {
6795 /* reset to default? */
6796 if (strcmp(argv[1], "default") == 0)
6797 CHECK_ERROR(systemProperties, COMSETTER(WebServiceAuthLibrary)(NULL));
6798 else
6799 CHECK_ERROR(systemProperties, COMSETTER(WebServiceAuthLibrary)(Bstr(argv[1])));
6800 }
6801 else if (strcmp(argv[0], "hwvirtexenabled") == 0)
6802 {
6803 if (strcmp(argv[1], "yes") == 0)
6804 CHECK_ERROR(systemProperties, COMSETTER(HWVirtExEnabled)(TRUE));
6805 else if (strcmp(argv[1], "no") == 0)
6806 CHECK_ERROR(systemProperties, COMSETTER(HWVirtExEnabled)(FALSE));
6807 else
6808 return errorArgument("Invalid value '%s' for hardware virtualization extension flag", argv[1]);
6809 }
6810 else if (strcmp(argv[0], "loghistorycount") == 0)
6811 {
6812 uint32_t uVal;
6813 int vrc;
6814 vrc = RTStrToUInt32Ex(argv[1], NULL, 0, &uVal);
6815 if (vrc != VINF_SUCCESS)
6816 return errorArgument("Error parsing Log history count '%s'", argv[1]);
6817 CHECK_ERROR(systemProperties, COMSETTER(LogHistoryCount)(uVal));
6818 }
6819 else
6820 return errorSyntax(USAGE_SETPROPERTY, "Invalid parameter '%s'", argv[0]);
6821
6822 return SUCCEEDED(rc) ? 0 : 1;
6823}
6824
6825static int handleUSBFilter (int argc, char *argv[],
6826 ComPtr <IVirtualBox> aVirtualBox, ComPtr<ISession> aSession)
6827{
6828 HRESULT rc = S_OK;
6829 USBFilterCmd cmd;
6830
6831 /* at least: 0: command, 1: index, 2: -target, 3: <target value> */
6832 if (argc < 4)
6833 return errorSyntax(USAGE_USBFILTER, "Not enough parameters");
6834
6835 /* which command? */
6836 cmd.mAction = USBFilterCmd::Invalid;
6837 if (strcmp (argv [0], "add") == 0) cmd.mAction = USBFilterCmd::Add;
6838 else if (strcmp (argv [0], "modify") == 0) cmd.mAction = USBFilterCmd::Modify;
6839 else if (strcmp (argv [0], "remove") == 0) cmd.mAction = USBFilterCmd::Remove;
6840
6841 if (cmd.mAction == USBFilterCmd::Invalid)
6842 return errorSyntax(USAGE_USBFILTER, "Invalid parameter '%s'", argv[0]);
6843
6844 /* which index? */
6845 char *endptr = NULL;
6846 cmd.mIndex = strtoul (argv[1], &endptr, 10);
6847 if (!endptr || *endptr)
6848 return errorSyntax(USAGE_USBFILTER, "Invalid index '%s'", argv[1]);
6849
6850 switch (cmd.mAction)
6851 {
6852 case USBFilterCmd::Add:
6853 case USBFilterCmd::Modify:
6854 {
6855 /* at least: 0: command, 1: index, 2: -target, 3: <target value>, 4: -name, 5: <name value> */
6856 if (argc < 6)
6857 {
6858 if (cmd.mAction == USBFilterCmd::Add)
6859 return errorSyntax(USAGE_USBFILTER_ADD, "Not enough parameters");
6860
6861 return errorSyntax(USAGE_USBFILTER_MODIFY, "Not enough parameters");
6862 }
6863
6864 // set Active to true by default
6865 // (assuming that the user sets up all necessary attributes
6866 // at once and wants the filter to be active immediately)
6867 if (cmd.mAction == USBFilterCmd::Add)
6868 cmd.mFilter.mActive = true;
6869
6870 for (int i = 2; i < argc; i++)
6871 {
6872 if (strcmp(argv [i], "-target") == 0)
6873 {
6874 if (argc <= i + 1 || !*argv[i+1])
6875 return errorArgument("Missing argument to '%s'", argv[i]);
6876 i++;
6877 if (strcmp (argv [i], "global") == 0)
6878 cmd.mGlobal = true;
6879 else
6880 {
6881 /* assume it's a UUID of a machine */
6882 rc = aVirtualBox->GetMachine(Guid(argv[i]), cmd.mMachine.asOutParam());
6883 if (FAILED(rc) || !cmd.mMachine)
6884 {
6885 /* must be a name */
6886 CHECK_ERROR_RET(aVirtualBox, FindMachine(Bstr(argv[i]), cmd.mMachine.asOutParam()), 1);
6887 }
6888 }
6889 }
6890 else if (strcmp(argv [i], "-name") == 0)
6891 {
6892 if (argc <= i + 1 || !*argv[i+1])
6893 return errorArgument("Missing argument to '%s'", argv[i]);
6894 i++;
6895 cmd.mFilter.mName = argv [i];
6896 }
6897 else if (strcmp(argv [i], "-active") == 0)
6898 {
6899 if (argc <= i + 1)
6900 return errorArgument("Missing argument to '%s'", argv[i]);
6901 i++;
6902 if (strcmp (argv [i], "yes") == 0)
6903 cmd.mFilter.mActive = true;
6904 else if (strcmp (argv [i], "no") == 0)
6905 cmd.mFilter.mActive = false;
6906 else
6907 return errorArgument("Invalid -active argument '%s'", argv[i]);
6908 }
6909 else if (strcmp(argv [i], "-vendorid") == 0)
6910 {
6911 if (argc <= i + 1)
6912 return errorArgument("Missing argument to '%s'", argv[i]);
6913 i++;
6914 cmd.mFilter.mVendorId = argv [i];
6915 }
6916 else if (strcmp(argv [i], "-productid") == 0)
6917 {
6918 if (argc <= i + 1)
6919 return errorArgument("Missing argument to '%s'", argv[i]);
6920 i++;
6921 cmd.mFilter.mProductId = argv [i];
6922 }
6923 else if (strcmp(argv [i], "-revision") == 0)
6924 {
6925 if (argc <= i + 1)
6926 return errorArgument("Missing argument to '%s'", argv[i]);
6927 i++;
6928 cmd.mFilter.mRevision = argv [i];
6929 }
6930 else if (strcmp(argv [i], "-manufacturer") == 0)
6931 {
6932 if (argc <= i + 1)
6933 return errorArgument("Missing argument to '%s'", argv[i]);
6934 i++;
6935 cmd.mFilter.mManufacturer = argv [i];
6936 }
6937 else if (strcmp(argv [i], "-product") == 0)
6938 {
6939 if (argc <= i + 1)
6940 return errorArgument("Missing argument to '%s'", argv[i]);
6941 i++;
6942 cmd.mFilter.mProduct = argv [i];
6943 }
6944 else if (strcmp(argv [i], "-remote") == 0)
6945 {
6946 if (argc <= i + 1)
6947 return errorArgument("Missing argument to '%s'", argv[i]);
6948 i++;
6949 cmd.mFilter.mRemote = argv[i];
6950 }
6951 else if (strcmp(argv [i], "-serialnumber") == 0)
6952 {
6953 if (argc <= i + 1)
6954 return errorArgument("Missing argument to '%s'", argv[i]);
6955 i++;
6956 cmd.mFilter.mSerialNumber = argv [i];
6957 }
6958 else if (strcmp(argv [i], "-maskedinterfaces") == 0)
6959 {
6960 if (argc <= i + 1)
6961 return errorArgument("Missing argument to '%s'", argv[i]);
6962 i++;
6963 uint32_t u32;
6964 rc = RTStrToUInt32Full(argv[i], 0, &u32);
6965 if (RT_FAILURE(rc))
6966 return errorArgument("Failed to convert the -maskedinterfaces value '%s' to a number, rc=%Rrc", argv[i], rc);
6967 cmd.mFilter.mMaskedInterfaces = u32;
6968 }
6969 else if (strcmp(argv [i], "-action") == 0)
6970 {
6971 if (argc <= i + 1)
6972 return errorArgument("Missing argument to '%s'", argv[i]);
6973 i++;
6974 if (strcmp (argv [i], "ignore") == 0)
6975 cmd.mFilter.mAction = USBDeviceFilterAction_Ignore;
6976 else if (strcmp (argv [i], "hold") == 0)
6977 cmd.mFilter.mAction = USBDeviceFilterAction_Hold;
6978 else
6979 return errorArgument("Invalid USB filter action '%s'", argv[i]);
6980 }
6981 else
6982 return errorSyntax(cmd.mAction == USBFilterCmd::Add ? USAGE_USBFILTER_ADD : USAGE_USBFILTER_MODIFY,
6983 "Unknown option '%s'", argv[i]);
6984 }
6985
6986 if (cmd.mAction == USBFilterCmd::Add)
6987 {
6988 // mandatory/forbidden options
6989 if ( cmd.mFilter.mName.isEmpty()
6990 ||
6991 ( cmd.mGlobal
6992 && cmd.mFilter.mAction == USBDeviceFilterAction_Null
6993 )
6994 || ( !cmd.mGlobal
6995 && !cmd.mMachine)
6996 || ( cmd.mGlobal
6997 && cmd.mFilter.mRemote)
6998 )
6999 {
7000 return errorSyntax(USAGE_USBFILTER_ADD, "Mandatory options not supplied");
7001 }
7002 }
7003 break;
7004 }
7005
7006 case USBFilterCmd::Remove:
7007 {
7008 /* at least: 0: command, 1: index, 2: -target, 3: <target value> */
7009 if (argc < 4)
7010 return errorSyntax(USAGE_USBFILTER_REMOVE, "Not enough parameters");
7011
7012 for (int i = 2; i < argc; i++)
7013 {
7014 if (strcmp(argv [i], "-target") == 0)
7015 {
7016 if (argc <= i + 1 || !*argv[i+1])
7017 return errorArgument("Missing argument to '%s'", argv[i]);
7018 i++;
7019 if (strcmp (argv [i], "global") == 0)
7020 cmd.mGlobal = true;
7021 else
7022 {
7023 /* assume it's a UUID of a machine */
7024 rc = aVirtualBox->GetMachine(Guid(argv[i]), cmd.mMachine.asOutParam());
7025 if (FAILED(rc) || !cmd.mMachine)
7026 {
7027 /* must be a name */
7028 CHECK_ERROR_RET(aVirtualBox, FindMachine(Bstr(argv[i]), cmd.mMachine.asOutParam()), 1);
7029 }
7030 }
7031 }
7032 }
7033
7034 // mandatory options
7035 if (!cmd.mGlobal && !cmd.mMachine)
7036 return errorSyntax(USAGE_USBFILTER_REMOVE, "Mandatory options not supplied");
7037
7038 break;
7039 }
7040
7041 default: break;
7042 }
7043
7044 USBFilterCmd::USBFilter &f = cmd.mFilter;
7045
7046 ComPtr <IHost> host;
7047 ComPtr <IUSBController> ctl;
7048 if (cmd.mGlobal)
7049 CHECK_ERROR_RET (aVirtualBox, COMGETTER(Host) (host.asOutParam()), 1);
7050 else
7051 {
7052 Guid uuid;
7053 cmd.mMachine->COMGETTER(Id)(uuid.asOutParam());
7054 /* open a session for the VM */
7055 CHECK_ERROR_RET (aVirtualBox, OpenSession(aSession, uuid), 1);
7056 /* get the mutable session machine */
7057 aSession->COMGETTER(Machine)(cmd.mMachine.asOutParam());
7058 /* and get the USB controller */
7059 CHECK_ERROR_RET (cmd.mMachine, COMGETTER(USBController) (ctl.asOutParam()), 1);
7060 }
7061
7062 switch (cmd.mAction)
7063 {
7064 case USBFilterCmd::Add:
7065 {
7066 if (cmd.mGlobal)
7067 {
7068 ComPtr <IHostUSBDeviceFilter> flt;
7069 CHECK_ERROR_BREAK (host, CreateUSBDeviceFilter (f.mName, flt.asOutParam()));
7070
7071 if (!f.mActive.isNull())
7072 CHECK_ERROR_BREAK (flt, COMSETTER(Active) (f.mActive));
7073 if (!f.mVendorId.isNull())
7074 CHECK_ERROR_BREAK (flt, COMSETTER(VendorId) (f.mVendorId.setNullIfEmpty()));
7075 if (!f.mProductId.isNull())
7076 CHECK_ERROR_BREAK (flt, COMSETTER(ProductId) (f.mProductId.setNullIfEmpty()));
7077 if (!f.mRevision.isNull())
7078 CHECK_ERROR_BREAK (flt, COMSETTER(Revision) (f.mRevision.setNullIfEmpty()));
7079 if (!f.mManufacturer.isNull())
7080 CHECK_ERROR_BREAK (flt, COMSETTER(Manufacturer) (f.mManufacturer.setNullIfEmpty()));
7081 if (!f.mSerialNumber.isNull())
7082 CHECK_ERROR_BREAK (flt, COMSETTER(SerialNumber) (f.mSerialNumber.setNullIfEmpty()));
7083 if (!f.mMaskedInterfaces.isNull())
7084 CHECK_ERROR_BREAK (flt, COMSETTER(MaskedInterfaces) (f.mMaskedInterfaces));
7085
7086 if (f.mAction != USBDeviceFilterAction_Null)
7087 CHECK_ERROR_BREAK (flt, COMSETTER(Action) (f.mAction));
7088
7089 CHECK_ERROR_BREAK (host, InsertUSBDeviceFilter (cmd.mIndex, flt));
7090 }
7091 else
7092 {
7093 ComPtr <IUSBDeviceFilter> flt;
7094 CHECK_ERROR_BREAK (ctl, CreateDeviceFilter (f.mName, flt.asOutParam()));
7095
7096 if (!f.mActive.isNull())
7097 CHECK_ERROR_BREAK (flt, COMSETTER(Active) (f.mActive));
7098 if (!f.mVendorId.isNull())
7099 CHECK_ERROR_BREAK (flt, COMSETTER(VendorId) (f.mVendorId.setNullIfEmpty()));
7100 if (!f.mProductId.isNull())
7101 CHECK_ERROR_BREAK (flt, COMSETTER(ProductId) (f.mProductId.setNullIfEmpty()));
7102 if (!f.mRevision.isNull())
7103 CHECK_ERROR_BREAK (flt, COMSETTER(Revision) (f.mRevision.setNullIfEmpty()));
7104 if (!f.mManufacturer.isNull())
7105 CHECK_ERROR_BREAK (flt, COMSETTER(Manufacturer) (f.mManufacturer.setNullIfEmpty()));
7106 if (!f.mRemote.isNull())
7107 CHECK_ERROR_BREAK (flt, COMSETTER(Remote) (f.mRemote.setNullIfEmpty()));
7108 if (!f.mSerialNumber.isNull())
7109 CHECK_ERROR_BREAK (flt, COMSETTER(SerialNumber) (f.mSerialNumber.setNullIfEmpty()));
7110 if (!f.mMaskedInterfaces.isNull())
7111 CHECK_ERROR_BREAK (flt, COMSETTER(MaskedInterfaces) (f.mMaskedInterfaces));
7112
7113 CHECK_ERROR_BREAK (ctl, InsertDeviceFilter (cmd.mIndex, flt));
7114 }
7115 break;
7116 }
7117 case USBFilterCmd::Modify:
7118 {
7119 if (cmd.mGlobal)
7120 {
7121 ComPtr <IHostUSBDeviceFilterCollection> coll;
7122 CHECK_ERROR_BREAK (host, COMGETTER(USBDeviceFilters) (coll.asOutParam()));
7123 ComPtr <IHostUSBDeviceFilter> flt;
7124 CHECK_ERROR_BREAK (coll, GetItemAt (cmd.mIndex, flt.asOutParam()));
7125
7126 if (!f.mName.isNull())
7127 CHECK_ERROR_BREAK (flt, COMSETTER(Name) (f.mName.setNullIfEmpty()));
7128 if (!f.mActive.isNull())
7129 CHECK_ERROR_BREAK (flt, COMSETTER(Active) (f.mActive));
7130 if (!f.mVendorId.isNull())
7131 CHECK_ERROR_BREAK (flt, COMSETTER(VendorId) (f.mVendorId.setNullIfEmpty()));
7132 if (!f.mProductId.isNull())
7133 CHECK_ERROR_BREAK (flt, COMSETTER(ProductId) (f.mProductId.setNullIfEmpty()));
7134 if (!f.mRevision.isNull())
7135 CHECK_ERROR_BREAK (flt, COMSETTER(Revision) (f.mRevision.setNullIfEmpty()));
7136 if (!f.mManufacturer.isNull())
7137 CHECK_ERROR_BREAK (flt, COMSETTER(Manufacturer) (f.mManufacturer.setNullIfEmpty()));
7138 if (!f.mSerialNumber.isNull())
7139 CHECK_ERROR_BREAK (flt, COMSETTER(SerialNumber) (f.mSerialNumber.setNullIfEmpty()));
7140 if (!f.mMaskedInterfaces.isNull())
7141 CHECK_ERROR_BREAK (flt, COMSETTER(MaskedInterfaces) (f.mMaskedInterfaces));
7142
7143 if (f.mAction != USBDeviceFilterAction_Null)
7144 CHECK_ERROR_BREAK (flt, COMSETTER(Action) (f.mAction));
7145 }
7146 else
7147 {
7148 ComPtr <IUSBDeviceFilterCollection> coll;
7149 CHECK_ERROR_BREAK (ctl, COMGETTER(DeviceFilters) (coll.asOutParam()));
7150
7151 ComPtr <IUSBDeviceFilter> flt;
7152 CHECK_ERROR_BREAK (coll, GetItemAt (cmd.mIndex, flt.asOutParam()));
7153
7154 if (!f.mName.isNull())
7155 CHECK_ERROR_BREAK (flt, COMSETTER(Name) (f.mName.setNullIfEmpty()));
7156 if (!f.mActive.isNull())
7157 CHECK_ERROR_BREAK (flt, COMSETTER(Active) (f.mActive));
7158 if (!f.mVendorId.isNull())
7159 CHECK_ERROR_BREAK (flt, COMSETTER(VendorId) (f.mVendorId.setNullIfEmpty()));
7160 if (!f.mProductId.isNull())
7161 CHECK_ERROR_BREAK (flt, COMSETTER(ProductId) (f.mProductId.setNullIfEmpty()));
7162 if (!f.mRevision.isNull())
7163 CHECK_ERROR_BREAK (flt, COMSETTER(Revision) (f.mRevision.setNullIfEmpty()));
7164 if (!f.mManufacturer.isNull())
7165 CHECK_ERROR_BREAK (flt, COMSETTER(Manufacturer) (f.mManufacturer.setNullIfEmpty()));
7166 if (!f.mRemote.isNull())
7167 CHECK_ERROR_BREAK (flt, COMSETTER(Remote) (f.mRemote.setNullIfEmpty()));
7168 if (!f.mSerialNumber.isNull())
7169 CHECK_ERROR_BREAK (flt, COMSETTER(SerialNumber) (f.mSerialNumber.setNullIfEmpty()));
7170 if (!f.mMaskedInterfaces.isNull())
7171 CHECK_ERROR_BREAK (flt, COMSETTER(MaskedInterfaces) (f.mMaskedInterfaces));
7172 }
7173 break;
7174 }
7175 case USBFilterCmd::Remove:
7176 {
7177 if (cmd.mGlobal)
7178 {
7179 ComPtr <IHostUSBDeviceFilter> flt;
7180 CHECK_ERROR_BREAK (host, RemoveUSBDeviceFilter (cmd.mIndex, flt.asOutParam()));
7181 }
7182 else
7183 {
7184 ComPtr <IUSBDeviceFilter> flt;
7185 CHECK_ERROR_BREAK (ctl, RemoveDeviceFilter (cmd.mIndex, flt.asOutParam()));
7186 }
7187 break;
7188 }
7189 default:
7190 break;
7191 }
7192
7193 if (cmd.mMachine)
7194 {
7195 /* commit and close the session */
7196 CHECK_ERROR(cmd.mMachine, SaveSettings());
7197 aSession->Close();
7198 }
7199
7200 return SUCCEEDED (rc) ? 0 : 1;
7201}
7202
7203static int handleSharedFolder (int argc, char *argv[],
7204 ComPtr <IVirtualBox> aVirtualBox, ComPtr<ISession> aSession)
7205{
7206 HRESULT rc;
7207
7208 /* we need at least a command and target */
7209 if (argc < 2)
7210 return errorSyntax(USAGE_SHAREDFOLDER, "Not enough parameters");
7211
7212 ComPtr<IMachine> machine;
7213 /* assume it's a UUID */
7214 rc = aVirtualBox->GetMachine(Guid(argv[1]), machine.asOutParam());
7215 if (FAILED(rc) || !machine)
7216 {
7217 /* must be a name */
7218 CHECK_ERROR(aVirtualBox, FindMachine(Bstr(argv[1]), machine.asOutParam()));
7219 }
7220 if (!machine)
7221 return 1;
7222 Guid uuid;
7223 machine->COMGETTER(Id)(uuid.asOutParam());
7224
7225 if (strcmp(argv[0], "add") == 0)
7226 {
7227 /* we need at least four more parameters */
7228 if (argc < 5)
7229 return errorSyntax(USAGE_SHAREDFOLDER_ADD, "Not enough parameters");
7230
7231 char *name = NULL;
7232 char *hostpath = NULL;
7233 bool fTransient = false;
7234 bool fWritable = true;
7235
7236 for (int i = 2; i < argc; i++)
7237 {
7238 if (strcmp(argv[i], "-name") == 0)
7239 {
7240 if (argc <= i + 1 || !*argv[i+1])
7241 return errorArgument("Missing argument to '%s'", argv[i]);
7242 i++;
7243 name = argv[i];
7244 }
7245 else if (strcmp(argv[i], "-hostpath") == 0)
7246 {
7247 if (argc <= i + 1 || !*argv[i+1])
7248 return errorArgument("Missing argument to '%s'", argv[i]);
7249 i++;
7250 hostpath = argv[i];
7251 }
7252 else if (strcmp(argv[i], "-readonly") == 0)
7253 {
7254 fWritable = false;
7255 }
7256 else if (strcmp(argv[i], "-transient") == 0)
7257 {
7258 fTransient = true;
7259 }
7260 else
7261 return errorSyntax(USAGE_SHAREDFOLDER_ADD, "Invalid parameter '%s'", Utf8Str(argv[i]).raw());
7262 }
7263
7264 /* required arguments */
7265 if (!name || !hostpath)
7266 {
7267 return errorSyntax(USAGE_SHAREDFOLDER_ADD, "Parameters -name and -hostpath are required");
7268 }
7269
7270 if (fTransient)
7271 {
7272 ComPtr <IConsole> console;
7273
7274 /* open an existing session for the VM */
7275 CHECK_ERROR_RET(aVirtualBox, OpenExistingSession (aSession, uuid), 1);
7276 /* get the session machine */
7277 CHECK_ERROR_RET(aSession, COMGETTER(Machine)(machine.asOutParam()), 1);
7278 /* get the session console */
7279 CHECK_ERROR_RET(aSession, COMGETTER(Console)(console.asOutParam()), 1);
7280
7281 CHECK_ERROR(console, CreateSharedFolder(Bstr(name), Bstr(hostpath), fWritable));
7282
7283 if (console)
7284 aSession->Close();
7285 }
7286 else
7287 {
7288 /* open a session for the VM */
7289 CHECK_ERROR_RET (aVirtualBox, OpenSession(aSession, uuid), 1);
7290
7291 /* get the mutable session machine */
7292 aSession->COMGETTER(Machine)(machine.asOutParam());
7293
7294 CHECK_ERROR(machine, CreateSharedFolder(Bstr(name), Bstr(hostpath), fWritable));
7295
7296 if (SUCCEEDED(rc))
7297 CHECK_ERROR(machine, SaveSettings());
7298
7299 aSession->Close();
7300 }
7301 }
7302 else if (strcmp(argv[0], "remove") == 0)
7303 {
7304 /* we need at least two more parameters */
7305 if (argc < 3)
7306 return errorSyntax(USAGE_SHAREDFOLDER_REMOVE, "Not enough parameters");
7307
7308 char *name = NULL;
7309 bool fTransient = false;
7310
7311 for (int i = 2; i < argc; i++)
7312 {
7313 if (strcmp(argv[i], "-name") == 0)
7314 {
7315 if (argc <= i + 1 || !*argv[i+1])
7316 return errorArgument("Missing argument to '%s'", argv[i]);
7317 i++;
7318 name = argv[i];
7319 }
7320 else if (strcmp(argv[i], "-transient") == 0)
7321 {
7322 fTransient = true;
7323 }
7324 else
7325 return errorSyntax(USAGE_SHAREDFOLDER_REMOVE, "Invalid parameter '%s'", Utf8Str(argv[i]).raw());
7326 }
7327
7328 /* required arguments */
7329 if (!name)
7330 return errorSyntax(USAGE_SHAREDFOLDER_REMOVE, "Parameter -name is required");
7331
7332 if (fTransient)
7333 {
7334 ComPtr <IConsole> console;
7335
7336 /* open an existing session for the VM */
7337 CHECK_ERROR_RET(aVirtualBox, OpenExistingSession (aSession, uuid), 1);
7338 /* get the session machine */
7339 CHECK_ERROR_RET(aSession, COMGETTER(Machine)(machine.asOutParam()), 1);
7340 /* get the session console */
7341 CHECK_ERROR_RET(aSession, COMGETTER(Console)(console.asOutParam()), 1);
7342
7343 CHECK_ERROR(console, RemoveSharedFolder(Bstr(name)));
7344
7345 if (console)
7346 aSession->Close();
7347 }
7348 else
7349 {
7350 /* open a session for the VM */
7351 CHECK_ERROR_RET (aVirtualBox, OpenSession(aSession, uuid), 1);
7352
7353 /* get the mutable session machine */
7354 aSession->COMGETTER(Machine)(machine.asOutParam());
7355
7356 CHECK_ERROR(machine, RemoveSharedFolder(Bstr(name)));
7357
7358 /* commit and close the session */
7359 CHECK_ERROR(machine, SaveSettings());
7360 aSession->Close();
7361 }
7362 }
7363 else
7364 return errorSyntax(USAGE_SETPROPERTY, "Invalid parameter '%s'", Utf8Str(argv[0]).raw());
7365
7366 return 0;
7367}
7368
7369static int handleVMStatistics(int argc, char *argv[],
7370 ComPtr<IVirtualBox> aVirtualBox, ComPtr<ISession> aSession)
7371{
7372 HRESULT rc;
7373
7374 /* at least one option: the UUID or name of the VM */
7375 if (argc < 1)
7376 return errorSyntax(USAGE_VM_STATISTICS, "Incorrect number of parameters");
7377
7378 /* try to find the given machine */
7379 ComPtr <IMachine> machine;
7380 Guid uuid (argv[0]);
7381 if (!uuid.isEmpty())
7382 CHECK_ERROR(aVirtualBox, GetMachine(uuid, machine.asOutParam()));
7383 else
7384 {
7385 CHECK_ERROR(aVirtualBox, FindMachine(Bstr(argv[0]), machine.asOutParam()));
7386 if (SUCCEEDED (rc))
7387 machine->COMGETTER(Id)(uuid.asOutParam());
7388 }
7389 if (FAILED(rc))
7390 return 1;
7391
7392 /* parse arguments. */
7393 bool fReset = false;
7394 bool fWithDescriptions = false;
7395 const char *pszPattern = NULL; /* all */
7396 for (int i = 1; i < argc; i++)
7397 {
7398 if (!strcmp(argv[i], "-pattern"))
7399 {
7400 if (pszPattern)
7401 return errorSyntax(USAGE_VM_STATISTICS, "Multiple -patterns options is not permitted");
7402 if (i + 1 >= argc)
7403 return errorArgument("Missing argument to '%s'", argv[i]);
7404 pszPattern = argv[++i];
7405 }
7406 else if (!strcmp(argv[i], "-descriptions"))
7407 fWithDescriptions = true;
7408 /* add: -file <filename> and -formatted */
7409 else if (!strcmp(argv[i], "-reset"))
7410 fReset = true;
7411 else
7412 return errorSyntax(USAGE_VM_STATISTICS, "Unknown option '%s'", argv[i]);
7413 }
7414 if (fReset && fWithDescriptions)
7415 return errorSyntax(USAGE_VM_STATISTICS, "The -reset and -descriptions options does not mix");
7416
7417
7418 /* open an existing session for the VM. */
7419 CHECK_ERROR(aVirtualBox, OpenExistingSession(aSession, uuid));
7420 if (SUCCEEDED(rc))
7421 {
7422 /* get the session console. */
7423 ComPtr <IConsole> console;
7424 CHECK_ERROR(aSession, COMGETTER(Console)(console.asOutParam()));
7425 if (SUCCEEDED(rc))
7426 {
7427 /* get the machine debugger. */
7428 ComPtr <IMachineDebugger> debugger;
7429 CHECK_ERROR(console, COMGETTER(Debugger)(debugger.asOutParam()));
7430 if (SUCCEEDED(rc))
7431 {
7432 if (fReset)
7433 CHECK_ERROR(debugger, ResetStats(Bstr(pszPattern).raw()));
7434 else
7435 {
7436 Bstr stats;
7437 CHECK_ERROR(debugger, GetStats(Bstr(pszPattern).raw(), fWithDescriptions, stats.asOutParam()));
7438 if (SUCCEEDED(rc))
7439 {
7440 /* if (fFormatted)
7441 { big mess }
7442 else
7443 */
7444 RTPrintf("%ls\n", stats.raw());
7445 }
7446 }
7447 }
7448 aSession->Close();
7449 }
7450 }
7451
7452 return SUCCEEDED(rc) ? 0 : 1;
7453}
7454
7455enum ConvertSettings
7456{
7457 ConvertSettings_No = 0,
7458 ConvertSettings_Yes = 1,
7459 ConvertSettings_Backup = 2,
7460 ConvertSettings_Ignore = 3,
7461};
7462
7463/**
7464 * Checks if any of the settings files were auto-converted and informs the
7465 * user if so.
7466 *
7467 * @return @false if the program should terminate and @true otherwise.
7468 */
7469static bool checkForAutoConvertedSettings (ComPtr<IVirtualBox> virtualBox,
7470 ComPtr<ISession> session,
7471 ConvertSettings fConvertSettings)
7472{
7473 /* return early if nothing to do */
7474 if (fConvertSettings == ConvertSettings_Ignore)
7475 return true;
7476
7477 HRESULT rc;
7478
7479 do
7480 {
7481 Bstr formatVersion;
7482 CHECK_RC_BREAK (virtualBox->
7483 COMGETTER(SettingsFormatVersion) (formatVersion.asOutParam()));
7484
7485 bool isGlobalConverted = false;
7486 std::list <ComPtr <IMachine> > cvtMachines;
7487 std::list <Utf8Str> fileList;
7488 Bstr version;
7489 Bstr filePath;
7490
7491 com::SafeIfaceArray <IMachine> machines;
7492 CHECK_RC_BREAK (virtualBox->
7493 COMGETTER(Machines2) (ComSafeArrayAsOutParam (machines)));
7494
7495 for (size_t i = 0; i < machines.size(); ++ i)
7496 {
7497 BOOL accessible;
7498 CHECK_RC_BREAK (machines [i]->
7499 COMGETTER(Accessible) (&accessible));
7500 if (!accessible)
7501 continue;
7502
7503 CHECK_RC_BREAK (machines [i]->
7504 COMGETTER(SettingsFileVersion) (version.asOutParam()));
7505
7506 if (version != formatVersion)
7507 {
7508 cvtMachines.push_back (machines [i]);
7509 Bstr filePath;
7510 CHECK_RC_BREAK (machines [i]->
7511 COMGETTER(SettingsFilePath) (filePath.asOutParam()));
7512 fileList.push_back (Utf8StrFmt ("%ls (%ls)", filePath.raw(),
7513 version.raw()));
7514 }
7515 }
7516
7517 CHECK_RC_BREAK (rc);
7518
7519 CHECK_RC_BREAK (virtualBox->
7520 COMGETTER(SettingsFileVersion) (version.asOutParam()));
7521 if (version != formatVersion)
7522 {
7523 isGlobalConverted = true;
7524 CHECK_RC_BREAK (virtualBox->
7525 COMGETTER(SettingsFilePath) (filePath.asOutParam()));
7526 fileList.push_back (Utf8StrFmt ("%ls (%ls)", filePath.raw(),
7527 version.raw()));
7528 }
7529
7530 if (fileList.size() > 0)
7531 {
7532 switch (fConvertSettings)
7533 {
7534 case ConvertSettings_No:
7535 {
7536 RTPrintf (
7537"WARNING! The following VirtualBox settings files have been automatically\n"
7538"converted to the new settings file format version '%ls':\n"
7539"\n",
7540 formatVersion.raw());
7541
7542 for (std::list <Utf8Str>::const_iterator f = fileList.begin();
7543 f != fileList.end(); ++ f)
7544 RTPrintf (" %S\n", (*f).raw());
7545 RTPrintf (
7546"\n"
7547"The current command was aborted to prevent overwriting the above settings\n"
7548"files with the results of the auto-conversion without your permission.\n"
7549"Please put one of the following command line switches to the beginning of\n"
7550"the VBoxManage command line and repeat the command:\n"
7551"\n"
7552" -convertSettings - to save all auto-converted files (it will not\n"
7553" be possible to use these settings files with an\n"
7554" older version of VirtualBox in the future);\n"
7555" -convertSettingsBackup - to create backup copies of the settings files in\n"
7556" the old format before saving them in the new format;\n"
7557" -convertSettingsIgnore - to not save the auto-converted settings files.\n"
7558"\n"
7559"Note that if you use -convertSettingsIgnore, the auto-converted settings files\n"
7560"will be implicitly saved in the new format anyway once you change a setting or\n"
7561"start a virtual machine, but NO backup copies will be created in this case.\n");
7562 return false;
7563 }
7564 case ConvertSettings_Yes:
7565 case ConvertSettings_Backup:
7566 {
7567 break;
7568 }
7569 default:
7570 AssertFailedReturn (false);
7571 }
7572
7573 for (std::list <ComPtr <IMachine> >::const_iterator m = cvtMachines.begin();
7574 m != cvtMachines.end(); ++ m)
7575 {
7576 Guid id;
7577 CHECK_RC_BREAK ((*m)->COMGETTER(Id) (id.asOutParam()));
7578
7579 /* open a session for the VM */
7580 CHECK_ERROR_BREAK (virtualBox, OpenSession (session, id));
7581
7582 ComPtr <IMachine> sm;
7583 CHECK_RC_BREAK (session->COMGETTER(Machine) (sm.asOutParam()));
7584
7585 Bstr bakFileName;
7586 if (fConvertSettings == ConvertSettings_Backup)
7587 CHECK_ERROR (sm, SaveSettingsWithBackup (bakFileName.asOutParam()));
7588 else
7589 CHECK_ERROR (sm, SaveSettings());
7590
7591 session->Close();
7592
7593 CHECK_RC_BREAK (rc);
7594 }
7595
7596 CHECK_RC_BREAK (rc);
7597
7598 if (isGlobalConverted)
7599 {
7600 Bstr bakFileName;
7601 if (fConvertSettings == ConvertSettings_Backup)
7602 CHECK_ERROR (virtualBox, SaveSettingsWithBackup (bakFileName.asOutParam()));
7603 else
7604 CHECK_ERROR (virtualBox, SaveSettings());
7605 }
7606
7607 CHECK_RC_BREAK (rc);
7608 }
7609 }
7610 while (0);
7611
7612 return SUCCEEDED (rc);
7613}
7614
7615// main
7616///////////////////////////////////////////////////////////////////////////////
7617
7618int main(int argc, char *argv[])
7619{
7620 /*
7621 * Before we do anything, init the runtime without loading
7622 * the support driver.
7623 */
7624 RTR3Init(false);
7625
7626 bool fShowLogo = true;
7627 int iCmd = 1;
7628 int iCmdArg;
7629
7630 ConvertSettings fConvertSettings = ConvertSettings_No;
7631
7632 /* global options */
7633 for (int i = 1; i < argc || argc <= iCmd; i++)
7634 {
7635 if ( argc <= iCmd
7636 || (strcmp(argv[i], "help") == 0)
7637 || (strcmp(argv[i], "-?") == 0)
7638 || (strcmp(argv[i], "-h") == 0)
7639 || (strcmp(argv[i], "-help") == 0)
7640 || (strcmp(argv[i], "--help") == 0))
7641 {
7642 showLogo();
7643 printUsage(USAGE_ALL);
7644 return 0;
7645 }
7646 else if ( strcmp(argv[i], "-v") == 0
7647 || strcmp(argv[i], "-version") == 0
7648 || strcmp(argv[i], "-Version") == 0
7649 || strcmp(argv[i], "--version") == 0)
7650 {
7651 /* Print version number, and do nothing else. */
7652 RTPrintf("%sr%d\n", VBOX_VERSION_STRING, VBoxSVNRev ());
7653 exit(0);
7654 }
7655 else if (strcmp(argv[i], "-dumpopts") == 0)
7656 {
7657 /* Special option to dump really all commands,
7658 * even the ones not understood on this platform. */
7659 printUsage(USAGE_DUMPOPTS);
7660 return 0;
7661 }
7662 else if (strcmp(argv[i], "-nologo") == 0)
7663 {
7664 /* suppress the logo */
7665 fShowLogo = false;
7666 iCmd++;
7667 }
7668 else if (strcmp(argv[i], "-convertSettings") == 0)
7669 {
7670 fConvertSettings = ConvertSettings_Yes;
7671 iCmd++;
7672 }
7673 else if (strcmp(argv[i], "-convertSettingsBackup") == 0)
7674 {
7675 fConvertSettings = ConvertSettings_Backup;
7676 iCmd++;
7677 }
7678 else if (strcmp(argv[i], "-convertSettingsIgnore") == 0)
7679 {
7680 fConvertSettings = ConvertSettings_Ignore;
7681 iCmd++;
7682 }
7683 else
7684 {
7685 break;
7686 }
7687 }
7688
7689 iCmdArg = iCmd + 1;
7690
7691 if (fShowLogo)
7692 showLogo();
7693
7694 HRESULT rc;
7695
7696 CHECK_RC_RET (com::Initialize());
7697
7698 /*
7699 * The input is in the host OS'es codepage (NT guarantees ACP).
7700 * For VBox we use UTF-8 and convert to UCS-2 when calling (XP)COM APIs.
7701 * For simplicity, just convert the argv[] array here.
7702 */
7703 for (int i = iCmdArg; i < argc; i++)
7704 {
7705 char *converted;
7706 RTStrCurrentCPToUtf8(&converted, argv[i]);
7707 argv[i] = converted;
7708 }
7709
7710 do
7711 {
7712 // scopes all the stuff till shutdown
7713 ////////////////////////////////////////////////////////////////////////////
7714
7715 /* convertdd: does not need a VirtualBox instantiation) */
7716 if (argc >= iCmdArg && (strcmp(argv[iCmd], "convertdd") == 0))
7717 {
7718 rc = handleConvertDDImage(argc - iCmdArg, argv + iCmdArg);
7719 break;
7720 }
7721
7722 ComPtr <IVirtualBox> virtualBox;
7723 ComPtr <ISession> session;
7724
7725 rc = virtualBox.createLocalObject (CLSID_VirtualBox);
7726 if (FAILED(rc))
7727 {
7728 RTPrintf ("[!] Failed to create the VirtualBox object!\n");
7729 PRINT_RC_MESSAGE (rc);
7730
7731 com::ErrorInfo info;
7732 if (!info.isFullAvailable() && !info.isBasicAvailable())
7733 RTPrintf ("[!] Most likely, the VirtualBox COM server is not running "
7734 "or failed to start.\n");
7735 else
7736 PRINT_ERROR_INFO (info);
7737 break;
7738 }
7739
7740 CHECK_RC_BREAK (session.createInprocObject (CLSID_Session));
7741
7742 /* create the event queue
7743 * (here it is necessary only to process remaining XPCOM/IPC events
7744 * after the session is closed) */
7745
7746 EventQueue eventQ;
7747
7748 if (!checkForAutoConvertedSettings (virtualBox, session, fConvertSettings))
7749 break;
7750
7751 /*
7752 * All registered command handlers
7753 */
7754 struct
7755 {
7756 const char *command;
7757 PFNHANDLER handler;
7758 } commandHandlers[] =
7759 {
7760 { "internalcommands", handleInternalCommands },
7761 { "list", handleList },
7762 { "showvminfo", handleShowVMInfo },
7763 { "registervm", handleRegisterVM },
7764 { "unregistervm", handleUnregisterVM },
7765 { "createvdi", handleCreateVDI },
7766 { "modifyvdi", handleModifyVDI },
7767 { "addiscsidisk", handleAddiSCSIDisk },
7768 { "createvm", handleCreateVM },
7769 { "modifyvm", handleModifyVM },
7770 { "clonevdi", handleCloneVDI },
7771 { "startvm", handleStartVM },
7772 { "controlvm", handleControlVM },
7773 { "discardstate", handleDiscardState },
7774 { "adoptstate", handleAdoptdState },
7775 { "snapshot", handleSnapshot },
7776 { "registerimage", handleRegisterImage },
7777 { "unregisterimage", handleUnregisterImage },
7778 { "showvdiinfo", handleShowVDIInfo },
7779#ifdef RT_OS_WINDOWS
7780 { "createhostif", handleCreateHostIF },
7781 { "removehostif", handleRemoveHostIF },
7782#endif
7783 { "getextradata", handleGetExtraData },
7784 { "setextradata", handleSetExtraData },
7785 { "setproperty", handleSetProperty },
7786 { "usbfilter", handleUSBFilter },
7787 { "sharedfolder", handleSharedFolder },
7788 { "vmstatistics", handleVMStatistics },
7789 { NULL, NULL }
7790 };
7791
7792 int commandIndex;
7793 for (commandIndex = 0; commandHandlers[commandIndex].command != NULL; commandIndex++)
7794 {
7795 if (strcmp(commandHandlers[commandIndex].command, argv[iCmd]) == 0)
7796 {
7797 rc = commandHandlers[commandIndex].handler(argc - iCmdArg, &argv[iCmdArg], virtualBox, session);
7798 break;
7799 }
7800 }
7801 if (!commandHandlers[commandIndex].command)
7802 {
7803 rc = errorSyntax(USAGE_ALL, "Invalid command '%s'", Utf8Str(argv[iCmd]).raw());
7804 }
7805
7806 /* Although all handlers should always close the session if they open it,
7807 * we do it here just in case if some of the handlers contains a bug --
7808 * leaving the direct session not closed will turn the machine state to
7809 * Aborted which may have unwanted side effects like killing the saved
7810 * state file (if the machine was in the Saved state before). */
7811 session->Close();
7812
7813 // end "all-stuff" scope
7814 ////////////////////////////////////////////////////////////////////////////
7815 }
7816 while (0);
7817
7818 com::Shutdown();
7819
7820 /*
7821 * Free converted argument vector
7822 */
7823 for (int i = iCmdArg; i < argc; i++)
7824 RTStrFree(argv[i]);
7825
7826 return rc;
7827}
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