VirtualBox

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

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

EHCI: added -usbehci VBoxManage option

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