VirtualBox

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

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

FE/VBoxManage: add number of online CPUs to "list hostinfo"

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