VirtualBox

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

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

Add rudimentary VHD support

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