VirtualBox

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

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

VBoxManage: Added "adoptstate <vm> <state_file>" to instruct the VM to adopt the external saved state file.

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