VirtualBox

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

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

Main, VBoxManage: add setting for webservice authentication library (which can be NULL to disable authentication)

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