VirtualBox

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

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

VBoxManage: added 'list runningvms'

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