VirtualBox

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

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

fixed 'VBoxManage convertdd stdin <size>' when size is not divisible by 1M

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 264.9 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 %RU64 bytes (%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 size_t cbBuffer = VDIDiskGetBufferSize(pVdi);
3245 void *pvBuf = RTMemAlloc(cbBuffer);
3246 if (pvBuf)
3247 {
3248 uint64_t offFile = 0;
3249 while (offFile < cbFile)
3250 {
3251 size_t cbRead = 0;
3252 size_t cbToRead = cbFile - offFile >= cbBuffer ? cbBuffer : cbFile - offFile;
3253 rc = RTFileRead(File, pvBuf, cbToRead, &cbRead);
3254 if (VBOX_FAILURE(rc) || !cbRead)
3255 break;
3256 rc = VDIDiskWrite(pVdi, offFile, pvBuf, cbRead);
3257 if (VBOX_FAILURE(rc))
3258 break;
3259 offFile += cbRead;
3260 }
3261
3262 RTMemFree(pvBuf);
3263 }
3264 else
3265 rc = VERR_NO_MEMORY;
3266
3267 VDIDiskCloseImage(pVdi);
3268 }
3269
3270 if (VBOX_FAILURE(rc))
3271 {
3272 /* delete image on error */
3273 RTPrintf("Failed (%Vrc)!\n", rc);
3274 VDIDeleteImage(argv[1]);
3275 }
3276 }
3277 else
3278 RTPrintf("Failed to create output file (%Vrc)!\n", rc);
3279 }
3280 RTFileClose(File);
3281
3282 return rc;
3283}
3284
3285static int handleAddiSCSIDisk(int argc, char *argv[],
3286 ComPtr <IVirtualBox> aVirtualBox, ComPtr<ISession> aSession)
3287{
3288 HRESULT rc;
3289 Bstr server;
3290 Bstr target;
3291 uint16_t port = UINT16_MAX;
3292 uint64_t lun = UINT64_MAX;
3293 Bstr username;
3294 Bstr password;
3295 Bstr comment;
3296
3297 /* at least server and target */
3298 if (argc < 4)
3299 {
3300 return errorSyntax(USAGE_ADDISCSIDISK, "Not enough parameters");
3301 }
3302
3303 /* let's have a closer look at the arguments */
3304 for (int i = 0; i < argc; i++)
3305 {
3306 if (strcmp(argv[i], "-server") == 0)
3307 {
3308 if (argc <= i + 1)
3309 {
3310 return errorArgument("Missing argument to '%s'", argv[i]);
3311 }
3312 i++;
3313 server = argv[i];
3314 }
3315 else if (strcmp(argv[i], "-target") == 0)
3316 {
3317 if (argc <= i + 1)
3318 {
3319 return errorArgument("Missing argument to '%s'", argv[i]);
3320 }
3321 i++;
3322 target = argv[i];
3323 }
3324 else if (strcmp(argv[i], "-port") == 0)
3325 {
3326 if (argc <= i + 1)
3327 {
3328 return errorArgument("Missing argument to '%s'", argv[i]);
3329 }
3330 i++;
3331 port = atoi(argv[i]);
3332 }
3333 else if (strcmp(argv[i], "-lun") == 0)
3334 {
3335 /** @todo move the LUN encoding algorithm into IISCSIHardDisk, add decoding */
3336 if (argc <= i + 1)
3337 {
3338 return errorArgument("Missing argument to '%s'", argv[i]);
3339 }
3340 i++;
3341 char *pszNext;
3342 int rc = RTStrToUInt64Ex(argv[i], &pszNext, 0, &lun);
3343 if (VBOX_FAILURE(rc) || *pszNext != '\0' || lun >= 16384)
3344 return errorArgument("Invalid LUN number '%s'", argv[i]);
3345 if (lun <= 255)
3346 {
3347 /* Assume bus identifier = 0. */
3348 lun = (lun << 48); /* uses peripheral device addressing method */
3349 }
3350 else
3351 {
3352 /* Check above already limited the LUN to 14 bits. */
3353 lun = (lun << 48) | RT_BIT_64(62); /* uses flat space addressing method */
3354 }
3355 }
3356 else if (strcmp(argv[i], "-encodedlun") == 0)
3357 {
3358 if (argc <= i + 1)
3359 {
3360 return errorArgument("Missing argument to '%s'", argv[i]);
3361 }
3362 i++;
3363 char *pszNext;
3364 int rc = RTStrToUInt64Ex(argv[i], &pszNext, 0, &lun);
3365 if (VBOX_FAILURE(rc) || *pszNext != '\0')
3366 return errorArgument("Invalid encoded LUN number '%s'", argv[i]);
3367 }
3368 else if (strcmp(argv[i], "-username") == 0)
3369 {
3370 if (argc <= i + 1)
3371 {
3372 return errorArgument("Missing argument to '%s'", argv[i]);
3373 }
3374 i++;
3375 username = argv[i];
3376 }
3377 else if (strcmp(argv[i], "-password") == 0)
3378 {
3379 if (argc <= i + 1)
3380 {
3381 return errorArgument("Missing argument to '%s'", argv[i]);
3382 }
3383 i++;
3384 password = argv[i];
3385 }
3386 else if (strcmp(argv[i], "-comment") == 0)
3387 {
3388 if (argc <= i + 1)
3389 {
3390 return errorArgument("Missing argument to '%s'", argv[i]);
3391 }
3392 i++;
3393 comment = argv[i];
3394 }
3395 else
3396 {
3397 return errorSyntax(USAGE_ADDISCSIDISK, "Invalid parameter '%s'", Utf8Str(argv[i]).raw());
3398 }
3399 }
3400
3401 /* check for required options */
3402 if (!server || !target)
3403 {
3404 return errorSyntax(USAGE_ADDISCSIDISK, "Parameters -server and -target are required");
3405 }
3406
3407 ComPtr<IHardDisk> hardDisk;
3408 CHECK_ERROR(aVirtualBox, CreateHardDisk(HardDiskStorageType_ISCSIHardDisk, hardDisk.asOutParam()));
3409 if (SUCCEEDED(rc) && hardDisk)
3410 {
3411 CHECK_ERROR(hardDisk, COMSETTER(Description)(comment));
3412 ComPtr<IISCSIHardDisk> iSCSIDisk = hardDisk;
3413 CHECK_ERROR(iSCSIDisk, COMSETTER(Server)(server));
3414 if (port != UINT16_MAX)
3415 CHECK_ERROR(iSCSIDisk, COMSETTER(Port)(port));
3416 CHECK_ERROR(iSCSIDisk, COMSETTER(Target)(target));
3417 if (lun != UINT64_MAX)
3418 CHECK_ERROR(iSCSIDisk, COMSETTER(Lun)(lun));
3419 CHECK_ERROR(iSCSIDisk, COMSETTER(UserName)(username));
3420 CHECK_ERROR(iSCSIDisk, COMSETTER(Password)(password));
3421
3422 if (SUCCEEDED(rc))
3423 {
3424 CHECK_ERROR(aVirtualBox, RegisterHardDisk(hardDisk));
3425 }
3426
3427 if (SUCCEEDED(rc))
3428 {
3429 Guid guid;
3430 CHECK_ERROR(hardDisk, COMGETTER(Id)(guid.asOutParam()));
3431 RTPrintf("iSCSI disk created. UUID: %s\n", guid.toString().raw());
3432 }
3433 }
3434
3435 return SUCCEEDED(rc) ? 0 : 1;
3436}
3437
3438static int handleCreateVM(int argc, char *argv[],
3439 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)
3440{
3441 HRESULT rc;
3442 Bstr baseFolder;
3443 Bstr settingsFile;
3444 Bstr name;
3445 RTUUID id;
3446 bool fRegister = false;
3447
3448 for (int i = 0; i < argc; i++)
3449 {
3450 if (strcmp(argv[i], "-basefolder") == 0)
3451 {
3452 if (argc <= i + 1)
3453 {
3454 return errorArgument("Missing argument to '%s'", argv[i]);
3455 }
3456 i++;
3457 baseFolder = argv[i];
3458 }
3459 else if (strcmp(argv[i], "-settingsfile") == 0)
3460 {
3461 if (argc <= i + 1)
3462 {
3463 return errorArgument("Missing argument to '%s'", argv[i]);
3464 }
3465 i++;
3466 settingsFile = argv[i];
3467 }
3468 else if (strcmp(argv[i], "-name") == 0)
3469 {
3470 if (argc <= i + 1)
3471 {
3472 return errorArgument("Missing argument to '%s'", argv[i]);
3473 }
3474 i++;
3475 name = argv[i];
3476 }
3477 else if (strcmp(argv[i], "-uuid") == 0)
3478 {
3479 if (argc <= i + 1)
3480 {
3481 return errorArgument("Missing argument to '%s'", argv[i]);
3482 }
3483 i++;
3484 if (VBOX_FAILURE(RTUuidFromStr(&id, argv[i])))
3485 {
3486 return errorArgument("Invalid UUID format %s\n", argv[i]);
3487 }
3488 }
3489 else if (strcmp(argv[i], "-register") == 0)
3490 {
3491 fRegister = true;
3492 }
3493 else
3494 {
3495 return errorSyntax(USAGE_CREATEVM, "Invalid parameter '%s'", Utf8Str(argv[i]).raw());
3496 }
3497 }
3498 if (!name)
3499 {
3500 return errorSyntax(USAGE_CREATEVM, "Parameter -name is required");
3501 }
3502 if (!!baseFolder && !!settingsFile)
3503 {
3504 return errorSyntax(USAGE_CREATEVM, "Either -basefolder or -settingsfile must be specified");
3505 }
3506
3507 do
3508 {
3509 ComPtr<IMachine> machine;
3510
3511 if (!settingsFile)
3512 CHECK_ERROR_BREAK(virtualBox,
3513 CreateMachine(baseFolder, name, Guid(id), machine.asOutParam()));
3514 else
3515 CHECK_ERROR_BREAK(virtualBox,
3516 CreateLegacyMachine(settingsFile, name, Guid(id), machine.asOutParam()));
3517
3518 CHECK_ERROR_BREAK(machine, SaveSettings());
3519 if (fRegister)
3520 {
3521 CHECK_ERROR_BREAK(virtualBox, RegisterMachine(machine));
3522 }
3523 Guid uuid;
3524 CHECK_ERROR_BREAK(machine, COMGETTER(Id)(uuid.asOutParam()));
3525 CHECK_ERROR_BREAK(machine, COMGETTER(SettingsFilePath)(settingsFile.asOutParam()));
3526 RTPrintf("Virtual machine '%ls' is created%s.\n"
3527 "UUID: %s\n"
3528 "Settings file: '%ls'\n",
3529 name.raw(), fRegister ? " and registered" : "",
3530 uuid.toString().raw(), settingsFile.raw());
3531 }
3532 while (0);
3533
3534 return SUCCEEDED(rc) ? 0 : 1;
3535}
3536
3537/**
3538 * Parses a number.
3539 *
3540 * @returns Valid number on success.
3541 * @returns 0 if invalid number. All necesary bitching has been done.
3542 * @param psz Pointer to the nic number.
3543 */
3544static unsigned parseNum(const char *psz, unsigned cMaxNum, const char *name)
3545{
3546 uint32_t u32;
3547 char *pszNext;
3548 int rc = RTStrToUInt32Ex(psz, &pszNext, 10, &u32);
3549 if ( VBOX_SUCCESS(rc)
3550 && *pszNext == '\0'
3551 && u32 >= 1
3552 && u32 <= cMaxNum)
3553 return (unsigned)u32;
3554 errorArgument("Invalid %s number '%s'", name, psz);
3555 return 0;
3556}
3557
3558static int handleModifyVM(int argc, char *argv[],
3559 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)
3560{
3561 HRESULT rc;
3562 Bstr name;
3563 Bstr ostype;
3564 ULONG memorySize = 0;
3565 ULONG vramSize = 0;
3566 char *acpi = NULL;
3567 char *hwvirtex = NULL;
3568 char *ioapic = NULL;
3569 int monitorcount = -1;
3570 char *bioslogofadein = NULL;
3571 char *bioslogofadeout = NULL;
3572 uint32_t bioslogodisplaytime = ~0;
3573 char *bioslogoimagepath = NULL;
3574 char *biosbootmenumode = NULL;
3575 char *biossystemtimeoffset = NULL;
3576 char *biospxedebug = NULL;
3577 DeviceType_T bootDevice[4];
3578 int bootDeviceChanged[4] = { false };
3579 char *hdds[4] = {0};
3580 char *dvd = NULL;
3581 char *dvdpassthrough = NULL;
3582 char *floppy = NULL;
3583 char *audio = NULL;
3584 char *clipboard = NULL;
3585#ifdef VBOX_VRDP
3586 char *vrdp = NULL;
3587 uint16_t vrdpport = UINT16_MAX;
3588 char *vrdpaddress = NULL;
3589 char *vrdpauthtype = NULL;
3590 char *vrdpmulticon = NULL;
3591#endif
3592 int fUsbEnabled = -1;
3593 char *snapshotFolder = NULL;
3594 ULONG guestMemBalloonSize = (ULONG)-1;
3595 ULONG guestStatInterval = (ULONG)-1;
3596
3597 /* VM ID + at least one parameter. Parameter arguments are checked
3598 * individually. */
3599 if (argc < 2)
3600 return errorSyntax(USAGE_MODIFYVM, "Not enough parameters");
3601
3602 /* Get the number of network adapters */
3603 ULONG NetworkAdapterCount = 0;
3604 {
3605 ComPtr <ISystemProperties> info;
3606 CHECK_ERROR_RET (virtualBox, COMGETTER(SystemProperties) (info.asOutParam()), 1);
3607 CHECK_ERROR_RET (info, COMGETTER(NetworkAdapterCount) (&NetworkAdapterCount), 1);
3608 }
3609 ULONG SerialPortCount = 0;
3610 {
3611 ComPtr <ISystemProperties> info;
3612 CHECK_ERROR_RET (virtualBox, COMGETTER(SystemProperties) (info.asOutParam()), 1);
3613 CHECK_ERROR_RET (info, COMGETTER(SerialPortCount) (&SerialPortCount), 1);
3614 }
3615
3616 std::vector <char *> nics (NetworkAdapterCount, 0);
3617 std::vector <char *> nictype (NetworkAdapterCount, 0);
3618 std::vector <char *> cableconnected (NetworkAdapterCount, 0);
3619 std::vector <char *> nictrace (NetworkAdapterCount, 0);
3620 std::vector <char *> nictracefile (NetworkAdapterCount, 0);
3621 std::vector <char *> nicspeed (NetworkAdapterCount, 0);
3622 std::vector <char *> hostifdev (NetworkAdapterCount, 0);
3623 std::vector <const char *> intnet (NetworkAdapterCount, 0);
3624#ifdef RT_OS_LINUX
3625 std::vector <char *> tapsetup (NetworkAdapterCount, 0);
3626 std::vector <char *> tapterm (NetworkAdapterCount, 0);
3627#endif
3628 std::vector <char *> macs (NetworkAdapterCount, 0);
3629 std::vector <char *> uarts_mode (SerialPortCount, 0);
3630 std::vector <ULONG> uarts_base (SerialPortCount, 0);
3631 std::vector <ULONG> uarts_irq (SerialPortCount, 0);
3632 std::vector <char *> uarts_path (SerialPortCount, 0);
3633
3634 for (int i = 1; i < argc; i++)
3635 {
3636 if (strcmp(argv[i], "-name") == 0)
3637 {
3638 if (argc <= i + 1)
3639 {
3640 return errorArgument("Missing argument to '%s'", argv[i]);
3641 }
3642 i++;
3643 name = argv[i];
3644 }
3645 else if (strcmp(argv[i], "-ostype") == 0)
3646 {
3647 if (argc <= i + 1)
3648 {
3649 return errorArgument("Missing argument to '%s'", argv[i]);
3650 }
3651 i++;
3652 ostype = argv[i];
3653 }
3654 else if (strcmp(argv[i], "-memory") == 0)
3655 {
3656 if (argc <= i + 1)
3657 {
3658 return errorArgument("Missing argument to '%s'", argv[i]);
3659 }
3660 i++;
3661 memorySize = atoi(argv[i]);
3662 }
3663 else if (strcmp(argv[i], "-vram") == 0)
3664 {
3665 if (argc <= i + 1)
3666 {
3667 return errorArgument("Missing argument to '%s'", argv[i]);
3668 }
3669 i++;
3670 vramSize = atoi(argv[i]);
3671 }
3672 else if (strcmp(argv[i], "-acpi") == 0)
3673 {
3674 if (argc <= i + 1)
3675 {
3676 return errorArgument("Missing argument to '%s'", argv[i]);
3677 }
3678 i++;
3679 acpi = argv[i];
3680 }
3681 else if (strcmp(argv[i], "-ioapic") == 0)
3682 {
3683 if (argc <= i + 1)
3684 {
3685 return errorArgument("Missing argument to '%s'", argv[i]);
3686 }
3687 i++;
3688 ioapic = argv[i];
3689 }
3690 else if (strcmp(argv[i], "-hwvirtex") == 0)
3691 {
3692 if (argc <= i + 1)
3693 {
3694 return errorArgument("Missing argument to '%s'", argv[i]);
3695 }
3696 i++;
3697 hwvirtex = argv[i];
3698 }
3699 else if (strcmp(argv[i], "-monitorcount") == 0)
3700 {
3701 if (argc <= i + 1)
3702 {
3703 return errorArgument("Missing argument to '%s'", argv[i]);
3704 }
3705 i++;
3706 monitorcount = atoi(argv[i]);
3707 }
3708 else if (strcmp(argv[i], "-bioslogofadein") == 0)
3709 {
3710 if (argc <= i + 1)
3711 {
3712 return errorArgument("Missing argument to '%s'", argv[i]);
3713 }
3714 i++;
3715 bioslogofadein = argv[i];
3716 }
3717 else if (strcmp(argv[i], "-bioslogofadeout") == 0)
3718 {
3719 if (argc <= i + 1)
3720 {
3721 return errorArgument("Missing argument to '%s'", argv[i]);
3722 }
3723 i++;
3724 bioslogofadeout = argv[i];
3725 }
3726 else if (strcmp(argv[i], "-bioslogodisplaytime") == 0)
3727 {
3728 if (argc <= i + 1)
3729 {
3730 return errorArgument("Missing argument to '%s'", argv[i]);
3731 }
3732 i++;
3733 bioslogodisplaytime = atoi(argv[i]);
3734 }
3735 else if (strcmp(argv[i], "-bioslogoimagepath") == 0)
3736 {
3737 if (argc <= i + 1)
3738 {
3739 return errorArgument("Missing argument to '%s'", argv[i]);
3740 }
3741 i++;
3742 bioslogoimagepath = argv[i];
3743 }
3744 else if (strcmp(argv[i], "-biosbootmenu") == 0)
3745 {
3746 if (argc <= i + 1)
3747 {
3748 return errorArgument("Missing argument to '%s'", argv[i]);
3749 }
3750 i++;
3751 biosbootmenumode = argv[i];
3752 }
3753 else if (strcmp(argv[i], "-biossystemtimeoffset") == 0)
3754 {
3755 if (argc <= i + 1)
3756 {
3757 return errorArgument("Missing argument to '%s'", argv[i]);
3758 }
3759 i++;
3760 biossystemtimeoffset = argv[i];
3761 }
3762 else if (strcmp(argv[i], "-biospxedebug") == 0)
3763 {
3764 if (argc <= i + 1)
3765 {
3766 return errorArgument("Missing argument to '%s'", argv[i]);
3767 }
3768 i++;
3769 biospxedebug = argv[i];
3770 }
3771 else if (strncmp(argv[i], "-boot", 5) == 0)
3772 {
3773 ULONG n = 0;
3774 if (!argv[i][5])
3775 {
3776 return errorSyntax(USAGE_MODIFYVM, "Missing boot slot number in '%s'", argv[i]);
3777 }
3778 if ((n = strtoul(&argv[i][5], NULL, 10)) < 1)
3779 {
3780 return errorSyntax(USAGE_MODIFYVM, "Invalid boot slot number in '%s'", argv[i]);
3781 }
3782 if (argc <= i + 1)
3783 {
3784 return errorArgument("Missing argument to '%s'", argv[i]);
3785 }
3786 i++;
3787 if (strcmp(argv[i], "none") == 0)
3788 {
3789 bootDevice[n - 1] = DeviceType_NoDevice;
3790 }
3791 else if (strcmp(argv[i], "floppy") == 0)
3792 {
3793 bootDevice[n - 1] = DeviceType_FloppyDevice;
3794 }
3795 else if (strcmp(argv[i], "dvd") == 0)
3796 {
3797 bootDevice[n - 1] = DeviceType_DVDDevice;
3798 }
3799 else if (strcmp(argv[i], "disk") == 0)
3800 {
3801 bootDevice[n - 1] = DeviceType_HardDiskDevice;
3802 }
3803 else if (strcmp(argv[i], "net") == 0)
3804 {
3805 bootDevice[n - 1] = DeviceType_NetworkDevice;
3806 }
3807 else
3808 {
3809 return errorArgument("Invalid boot device '%s'", argv[i]);
3810 }
3811 bootDeviceChanged[n - 1] = true;
3812 }
3813 else if (strcmp(argv[i], "-hda") == 0)
3814 {
3815 if (argc <= i + 1)
3816 {
3817 return errorArgument("Missing argument to '%s'", argv[i]);
3818 }
3819 i++;
3820 hdds[0] = argv[i];
3821 }
3822 else if (strcmp(argv[i], "-hdb") == 0)
3823 {
3824 if (argc <= i + 1)
3825 {
3826 return errorArgument("Missing argument to '%s'", argv[i]);
3827 }
3828 i++;
3829 hdds[1] = argv[i];
3830 }
3831 else if (strcmp(argv[i], "-hdd") == 0)
3832 {
3833 if (argc <= i + 1)
3834 {
3835 return errorArgument("Missing argument to '%s'", argv[i]);
3836 }
3837 i++;
3838 hdds[2] = argv[i];
3839 }
3840 else if (strcmp(argv[i], "-dvd") == 0)
3841 {
3842 if (argc <= i + 1)
3843 {
3844 return errorArgument("Missing argument to '%s'", argv[i]);
3845 }
3846 i++;
3847 dvd = argv[i];
3848 }
3849 else if (strcmp(argv[i], "-dvdpassthrough") == 0)
3850 {
3851 if (argc <= i + 1)
3852 {
3853 return errorArgument("Missing argument to '%s'", argv[i]);
3854 }
3855 i++;
3856 dvdpassthrough = argv[i];
3857 }
3858 else if (strcmp(argv[i], "-floppy") == 0)
3859 {
3860 if (argc <= i + 1)
3861 {
3862 return errorArgument("Missing argument to '%s'", argv[i]);
3863 }
3864 i++;
3865 floppy = argv[i];
3866 }
3867 else if (strcmp(argv[i], "-audio") == 0)
3868 {
3869 if (argc <= i + 1)
3870 {
3871 return errorArgument("Missing argument to '%s'", argv[i]);
3872 }
3873 i++;
3874 audio = argv[i];
3875 }
3876 else if (strcmp(argv[i], "-clipboard") == 0)
3877 {
3878 if (argc <= i + 1)
3879 {
3880 return errorArgument("Missing argument to '%s'", argv[i]);
3881 }
3882 i++;
3883 clipboard = argv[i];
3884 }
3885 else if (strncmp(argv[i], "-cableconnected", 15) == 0)
3886 {
3887 unsigned n = parseNum(&argv[i][15], NetworkAdapterCount, "NIC");
3888 if (!n)
3889 return 1;
3890 if (argc <= i + 1)
3891 {
3892 return errorArgument("Missing argument to '%s'", argv[i]);
3893 }
3894 cableconnected[n - 1] = argv[i + 1];
3895 i++;
3896 }
3897 /* watch for the right order of these -nic* comparisons! */
3898 else if (strncmp(argv[i], "-nictracefile", 13) == 0)
3899 {
3900 unsigned n = parseNum(&argv[i][13], NetworkAdapterCount, "NIC");
3901 if (!n)
3902 return 1;
3903 if (argc <= i + 1)
3904 {
3905 return errorArgument("Missing argument to '%s'", argv[i]);
3906 }
3907 nictracefile[n - 1] = argv[i + 1];
3908 i++;
3909 }
3910 else if (strncmp(argv[i], "-nictrace", 9) == 0)
3911 {
3912 unsigned n = parseNum(&argv[i][9], NetworkAdapterCount, "NIC");
3913 if (!n)
3914 return 1;
3915 if (argc <= i + 1)
3916 {
3917 return errorArgument("Missing argument to '%s'", argv[i]);
3918 }
3919 nictrace[n - 1] = argv[i + 1];
3920 i++;
3921 }
3922 else if (strncmp(argv[i], "-nictype", 8) == 0)
3923 {
3924 unsigned n = parseNum(&argv[i][8], NetworkAdapterCount, "NIC");
3925 if (!n)
3926 return 1;
3927 if (argc <= i + 1)
3928 {
3929 return errorArgument("Missing argument to '%s'", argv[i]);
3930 }
3931 nictype[n - 1] = argv[i + 1];
3932 i++;
3933 }
3934 else if (strncmp(argv[i], "-nicspeed", 9) == 0)
3935 {
3936 unsigned n = parseNum(&argv[i][9], NetworkAdapterCount, "NIC");
3937 if (!n)
3938 return 1;
3939 if (argc <= i + 1)
3940 {
3941 return errorArgument("Missing argument to '%s'", argv[i]);
3942 }
3943 nicspeed[n - 1] = argv[i + 1];
3944 i++;
3945 }
3946 else if (strncmp(argv[i], "-nic", 4) == 0)
3947 {
3948 unsigned n = parseNum(&argv[i][4], NetworkAdapterCount, "NIC");
3949 if (!n)
3950 return 1;
3951 if (argc <= i + 1)
3952 {
3953 return errorArgument("Missing argument to '%s'", argv[i]);
3954 }
3955 nics[n - 1] = argv[i + 1];
3956 i++;
3957 }
3958 else if (strncmp(argv[i], "-hostifdev", 10) == 0)
3959 {
3960 unsigned n = parseNum(&argv[i][10], NetworkAdapterCount, "NIC");
3961 if (!n)
3962 return 1;
3963 if (argc <= i + 1)
3964 {
3965 return errorArgument("Missing argument to '%s'", argv[i]);
3966 }
3967 hostifdev[n - 1] = argv[i + 1];
3968 i++;
3969 }
3970 else if (strncmp(argv[i], "-intnet", 7) == 0)
3971 {
3972 unsigned n = parseNum(&argv[i][7], NetworkAdapterCount, "NIC");
3973 if (!n)
3974 return 1;
3975 if (argc <= i + 1)
3976 {
3977 return errorArgument("Missing argument to '%s'", argv[i]);
3978 }
3979 intnet[n - 1] = argv[i + 1];
3980 i++;
3981 }
3982#ifdef RT_OS_LINUX
3983 else if (strncmp(argv[i], "-tapsetup", 9) == 0)
3984 {
3985 unsigned n = parseNum(&argv[i][9], NetworkAdapterCount, "NIC");
3986 if (!n)
3987 return 1;
3988 if (argc <= i + 1)
3989 {
3990 return errorArgument("Missing argument to '%s'", argv[i]);
3991 }
3992 tapsetup[n - 1] = argv[i + 1];
3993 i++;
3994 }
3995 else if (strncmp(argv[i], "-tapterminate", 13) == 0)
3996 {
3997 unsigned n = parseNum(&argv[i][13], NetworkAdapterCount, "NIC");
3998 if (!n)
3999 return 1;
4000 if (argc <= i + 1)
4001 {
4002 return errorArgument("Missing argument to '%s'", argv[i]);
4003 }
4004 tapterm[n - 1] = argv[i + 1];
4005 i++;
4006 }
4007#endif /* RT_OS_LINUX */
4008 else if (strncmp(argv[i], "-macaddress", 11) == 0)
4009 {
4010 unsigned n = parseNum(&argv[i][11], NetworkAdapterCount, "NIC");
4011 if (!n)
4012 return 1;
4013 if (argc <= i + 1)
4014 {
4015 return errorArgument("Missing argument to '%s'", argv[i]);
4016 }
4017 macs[n - 1] = argv[i + 1];
4018 i++;
4019 }
4020#ifdef VBOX_VRDP
4021 else if (strcmp(argv[i], "-vrdp") == 0)
4022 {
4023 if (argc <= i + 1)
4024 {
4025 return errorArgument("Missing argument to '%s'", argv[i]);
4026 }
4027 i++;
4028 vrdp = argv[i];
4029 }
4030 else if (strcmp(argv[i], "-vrdpport") == 0)
4031 {
4032 if (argc <= i + 1)
4033 {
4034 return errorArgument("Missing argument to '%s'", argv[i]);
4035 }
4036 i++;
4037 if (strcmp(argv[i], "default") == 0)
4038 vrdpport = 0;
4039 else
4040 vrdpport = atoi(argv[i]);
4041 }
4042 else if (strcmp(argv[i], "-vrdpaddress") == 0)
4043 {
4044 if (argc <= i + 1)
4045 {
4046 return errorArgument("Missing argument to '%s'", argv[i]);
4047 }
4048 i++;
4049 vrdpaddress = argv[i];
4050 }
4051 else if (strcmp(argv[i], "-vrdpauthtype") == 0)
4052 {
4053 if (argc <= i + 1)
4054 {
4055 return errorArgument("Missing argument to '%s'", argv[i]);
4056 }
4057 i++;
4058 vrdpauthtype = argv[i];
4059 }
4060 else if (strcmp(argv[i], "-vrdpmulticon") == 0)
4061 {
4062 if (argc <= i + 1)
4063 {
4064 return errorArgument("Missing argument to '%s'", argv[i]);
4065 }
4066 i++;
4067 vrdpmulticon = argv[i];
4068 }
4069#endif /* VBOX_VRDP */
4070 else if (strcmp(argv[i], "-usb") == 0)
4071 {
4072 if (argc <= i + 1)
4073 {
4074 return errorArgument("Missing argument to '%s'", argv[i]);
4075 }
4076 i++;
4077 if (strcmp(argv[i], "on") == 0 || strcmp(argv[i], "enable") == 0)
4078 fUsbEnabled = 1;
4079 else if (strcmp(argv[i], "off") == 0 || strcmp(argv[i], "disable") == 0)
4080 fUsbEnabled = 0;
4081 else
4082 return errorArgument("Invalid -usb argument '%s'", argv[i]);
4083 }
4084 else if (strcmp(argv[i], "-snapshotfolder") == 0)
4085 {
4086 if (argc <= i + 1)
4087 {
4088 return errorArgument("Missing argument to '%s'", argv[i]);
4089 }
4090 i++;
4091 snapshotFolder = argv[i];
4092 }
4093 else if (strncmp(argv[i], "-uartmode", 9) == 0)
4094 {
4095 unsigned n = parseNum(&argv[i][9], SerialPortCount, "UART");
4096 if (!n)
4097 return 1;
4098 i++;
4099 if (strcmp(argv[i], "disconnected") == 0)
4100 {
4101 uarts_mode[n - 1] = argv[i];
4102 }
4103 else
4104 {
4105 if (strcmp(argv[i], "server") == 0 || strcmp(argv[i], "client") == 0)
4106 {
4107 uarts_mode[n - 1] = argv[i];
4108 i++;
4109#ifdef RT_OS_WINDOWS
4110 if (strncmp(argv[i], "\\\\.\\pipe\\", 9))
4111 return errorArgument("Uart pipe must start with \\\\.\\pipe\\");
4112#endif
4113 }
4114 else
4115 {
4116 uarts_mode[n - 1] = (char*)"device";
4117 }
4118 if (argc <= i)
4119 {
4120 return errorArgument("Missing argument to -uartmode");
4121 }
4122 uarts_path[n - 1] = argv[i];
4123 }
4124 }
4125 else if (strncmp(argv[i], "-uart", 5) == 0)
4126 {
4127 unsigned n = parseNum(&argv[i][5], SerialPortCount, "UART");
4128 if (!n)
4129 return 1;
4130 if (argc <= i + 1)
4131 {
4132 return errorArgument("Missing argument to '%s'", argv[i]);
4133 }
4134 i++;
4135 if (strcmp(argv[i], "off") == 0 || strcmp(argv[i], "disable") == 0)
4136 {
4137 uarts_base[n - 1] = (ULONG)-1;
4138 }
4139 else
4140 {
4141 if (argc <= i + 1)
4142 {
4143 return errorArgument("Missing argument to '%s'", argv[i-1]);
4144 }
4145 uint32_t uVal;
4146 int vrc;
4147 vrc = RTStrToUInt32Ex(argv[i], NULL, 0, &uVal);
4148 if (vrc != VINF_SUCCESS || uVal == 0)
4149 return errorArgument("Error parsing UART I/O base '%s'", argv[i]);
4150 uarts_base[n - 1] = uVal;
4151 i++;
4152 vrc = RTStrToUInt32Ex(argv[i], NULL, 0, &uVal);
4153 if (vrc != VINF_SUCCESS)
4154 return errorArgument("Error parsing UART IRQ '%s'", argv[i]);
4155 uarts_irq[n - 1] = uVal;
4156 }
4157 }
4158 else if (strncmp(argv[i], "-guestmemoryballoon", 19) == 0)
4159 {
4160 if (argc <= i + 1)
4161 return errorArgument("Missing argument to '%s'", argv[i]);
4162 i++;
4163 uint32_t uVal;
4164 int vrc;
4165 vrc = RTStrToUInt32Ex(argv[i], NULL, 0, &uVal);
4166 if (vrc != VINF_SUCCESS)
4167 return errorArgument("Error parsing guest memory balloon size '%s'", argv[i]);
4168 guestMemBalloonSize = uVal;
4169 }
4170 else if (strncmp(argv[i], "-gueststatisticsinterval", 24) == 0)
4171 {
4172 if (argc <= i + 1)
4173 return errorArgument("Missing argument to '%s'", argv[i]);
4174 i++;
4175 uint32_t uVal;
4176 int vrc;
4177 vrc = RTStrToUInt32Ex(argv[i], NULL, 0, &uVal);
4178 if (vrc != VINF_SUCCESS)
4179 return errorArgument("Error parsing guest statistics interval '%s'", argv[i]);
4180 guestStatInterval = uVal;
4181 }
4182 else
4183 {
4184 return errorSyntax(USAGE_MODIFYVM, "Invalid parameter '%s'", Utf8Str(argv[i]).raw());
4185 }
4186 }
4187
4188 /* try to find the given machine */
4189 ComPtr <IMachine> machine;
4190 Guid uuid (argv[0]);
4191 if (!uuid.isEmpty())
4192 {
4193 CHECK_ERROR (virtualBox, GetMachine (uuid, machine.asOutParam()));
4194 }
4195 else
4196 {
4197 CHECK_ERROR (virtualBox, FindMachine(Bstr(argv[0]), machine.asOutParam()));
4198 if (SUCCEEDED (rc))
4199 machine->COMGETTER(Id)(uuid.asOutParam());
4200 }
4201 if (FAILED (rc))
4202 return 1;
4203
4204 /* open a session for the VM */
4205 CHECK_ERROR_RET (virtualBox, OpenSession(session, uuid), 1);
4206
4207 do
4208 {
4209 /* get the mutable session machine */
4210 session->COMGETTER(Machine)(machine.asOutParam());
4211
4212 ComPtr <IBIOSSettings> biosSettings;
4213 machine->COMGETTER(BIOSSettings)(biosSettings.asOutParam());
4214
4215 if (name)
4216 CHECK_ERROR(machine, COMSETTER(Name)(name));
4217 if (ostype)
4218 {
4219 ComPtr<IGuestOSType> guestOSType;
4220 CHECK_ERROR(virtualBox, GetGuestOSType(ostype, guestOSType.asOutParam()));
4221 if (SUCCEEDED(rc) && guestOSType)
4222 {
4223 CHECK_ERROR(machine, COMSETTER(OSTypeId)(ostype));
4224 }
4225 else
4226 {
4227 errorArgument("Invalid guest OS type '%s'", Utf8Str(ostype).raw());
4228 rc = E_FAIL;
4229 break;
4230 }
4231 }
4232 if (memorySize > 0)
4233 CHECK_ERROR(machine, COMSETTER(MemorySize)(memorySize));
4234 if (vramSize > 0)
4235 CHECK_ERROR(machine, COMSETTER(VRAMSize)(vramSize));
4236 if (acpi)
4237 {
4238 if (strcmp(acpi, "on") == 0)
4239 {
4240 CHECK_ERROR(biosSettings, COMSETTER(ACPIEnabled)(true));
4241 }
4242 else if (strcmp(acpi, "off") == 0)
4243 {
4244 CHECK_ERROR(biosSettings, COMSETTER(ACPIEnabled)(false));
4245 }
4246 else
4247 {
4248 errorArgument("Invalid -acpi argument '%s'", acpi);
4249 rc = E_FAIL;
4250 break;
4251 }
4252 }
4253 if (ioapic)
4254 {
4255 if (strcmp(ioapic, "on") == 0)
4256 {
4257 CHECK_ERROR(biosSettings, COMSETTER(IOAPICEnabled)(true));
4258 }
4259 else if (strcmp(ioapic, "off") == 0)
4260 {
4261 CHECK_ERROR(biosSettings, COMSETTER(IOAPICEnabled)(false));
4262 }
4263 else
4264 {
4265 errorArgument("Invalid -ioapic argument '%s'", ioapic);
4266 rc = E_FAIL;
4267 break;
4268 }
4269 }
4270 if (hwvirtex)
4271 {
4272 if (strcmp(hwvirtex, "on") == 0)
4273 {
4274 CHECK_ERROR(machine, COMSETTER(HWVirtExEnabled)(TriStateBool_True));
4275 }
4276 else if (strcmp(hwvirtex, "off") == 0)
4277 {
4278 CHECK_ERROR(machine, COMSETTER(HWVirtExEnabled)(TriStateBool_False));
4279 }
4280 else if (strcmp(hwvirtex, "default") == 0)
4281 {
4282 CHECK_ERROR(machine, COMSETTER(HWVirtExEnabled)(TriStateBool_Default));
4283 }
4284 else
4285 {
4286 errorArgument("Invalid -hwvirtex argument '%s'", hwvirtex);
4287 rc = E_FAIL;
4288 break;
4289 }
4290 }
4291 if (monitorcount != -1)
4292 {
4293 CHECK_ERROR(machine, COMSETTER(MonitorCount)(monitorcount));
4294 }
4295 if (bioslogofadein)
4296 {
4297 if (strcmp(bioslogofadein, "on") == 0)
4298 {
4299 CHECK_ERROR(biosSettings, COMSETTER(LogoFadeIn)(true));
4300 }
4301 else if (strcmp(bioslogofadein, "off") == 0)
4302 {
4303 CHECK_ERROR(biosSettings, COMSETTER(LogoFadeIn)(false));
4304 }
4305 else
4306 {
4307 errorArgument("Invalid -bioslogofadein argument '%s'", bioslogofadein);
4308 rc = E_FAIL;
4309 break;
4310 }
4311 }
4312 if (bioslogofadeout)
4313 {
4314 if (strcmp(bioslogofadeout, "on") == 0)
4315 {
4316 CHECK_ERROR(biosSettings, COMSETTER(LogoFadeOut)(true));
4317 }
4318 else if (strcmp(bioslogofadeout, "off") == 0)
4319 {
4320 CHECK_ERROR(biosSettings, COMSETTER(LogoFadeOut)(false));
4321 }
4322 else
4323 {
4324 errorArgument("Invalid -bioslogofadeout argument '%s'", bioslogofadeout);
4325 rc = E_FAIL;
4326 break;
4327 }
4328 }
4329 if (bioslogodisplaytime != ~0U)
4330 {
4331 CHECK_ERROR(biosSettings, COMSETTER(LogoDisplayTime)(bioslogodisplaytime));
4332 }
4333 if (bioslogoimagepath)
4334 {
4335 CHECK_ERROR(biosSettings, COMSETTER(LogoImagePath)(Bstr(bioslogoimagepath)));
4336 }
4337 if (biosbootmenumode)
4338 {
4339 if (strcmp(biosbootmenumode, "disabled") == 0)
4340 CHECK_ERROR(biosSettings, COMSETTER(BootMenuMode)(BIOSBootMenuMode_Disabled));
4341 else if (strcmp(biosbootmenumode, "menuonly") == 0)
4342 CHECK_ERROR(biosSettings, COMSETTER(BootMenuMode)(BIOSBootMenuMode_MenuOnly));
4343 else if (strcmp(biosbootmenumode, "messageandmenu") == 0)
4344 CHECK_ERROR(biosSettings, COMSETTER(BootMenuMode)(BIOSBootMenuMode_MessageAndMenu));
4345 else
4346 {
4347 errorArgument("Invalid -biosbootmenu argument '%s'", biosbootmenumode);
4348 rc = E_FAIL;
4349 break;
4350 }
4351
4352 }
4353 if (biossystemtimeoffset)
4354 {
4355 LONG64 timeOffset = RTStrToInt64(biossystemtimeoffset);
4356 CHECK_ERROR(biosSettings, COMSETTER(TimeOffset)(timeOffset));
4357 }
4358 if (biospxedebug)
4359 {
4360 if (strcmp(biospxedebug, "on") == 0)
4361 {
4362 CHECK_ERROR(biosSettings, COMSETTER(PXEDebugEnabled)(true));
4363 }
4364 else if (strcmp(biospxedebug, "off") == 0)
4365 {
4366 CHECK_ERROR(biosSettings, COMSETTER(PXEDebugEnabled)(false));
4367 }
4368 else
4369 {
4370 errorArgument("Invalid -biospxedebug argument '%s'", biospxedebug);
4371 rc = E_FAIL;
4372 break;
4373 }
4374 }
4375 for (int curBootDev = 0; curBootDev < 4; curBootDev++)
4376 {
4377 if (bootDeviceChanged[curBootDev])
4378 CHECK_ERROR(machine, SetBootOrder (curBootDev + 1, bootDevice[curBootDev]));
4379 }
4380 if (hdds[0])
4381 {
4382 if (strcmp(hdds[0], "none") == 0)
4383 {
4384 machine->DetachHardDisk(DiskControllerType_IDE0Controller, 0);
4385 }
4386 else
4387 {
4388 /* first guess is that it's a UUID */
4389 Guid uuid(hdds[0]);
4390 ComPtr<IHardDisk> hardDisk;
4391 rc = virtualBox->GetHardDisk(uuid, hardDisk.asOutParam());
4392 /* not successful? Then it must be a filename */
4393 if (!hardDisk)
4394 {
4395 CHECK_ERROR(virtualBox, OpenHardDisk(Bstr(hdds[0]), hardDisk.asOutParam()));
4396 if (SUCCEEDED(rc) && hardDisk)
4397 {
4398 /* first check if it's already registered */
4399 Guid hddUUID;
4400 hardDisk->COMGETTER(Id)(hddUUID.asOutParam());
4401 ComPtr<IHardDisk> registeredHDD;
4402 rc = virtualBox->GetHardDisk(hddUUID, registeredHDD.asOutParam());
4403 if (SUCCEEDED(rc) && registeredHDD)
4404 hardDisk = registeredHDD;
4405 else
4406 {
4407 /* it has to be registered */
4408 CHECK_ERROR(virtualBox, RegisterHardDisk(hardDisk));
4409 if (FAILED(rc))
4410 break;
4411 }
4412 }
4413 }
4414 if (hardDisk)
4415 {
4416 hardDisk->COMGETTER(Id)(uuid.asOutParam());
4417 CHECK_ERROR(machine, AttachHardDisk(uuid, DiskControllerType_IDE0Controller, 0));
4418 }
4419 else
4420 rc = E_FAIL;
4421 if (FAILED(rc))
4422 break;
4423 }
4424 }
4425 if (hdds[1])
4426 {
4427 if (strcmp(hdds[1], "none") == 0)
4428 {
4429 machine->DetachHardDisk(DiskControllerType_IDE0Controller, 1);
4430 }
4431 else
4432 {
4433 /* first guess is that it's a UUID */
4434 Guid uuid(hdds[1]);
4435 ComPtr<IHardDisk> hardDisk;
4436 rc = virtualBox->GetHardDisk(uuid, hardDisk.asOutParam());
4437 /* not successful? Then it must be a filename */
4438 if (!hardDisk)
4439 {
4440 CHECK_ERROR(virtualBox, OpenHardDisk(Bstr(hdds[1]), hardDisk.asOutParam()));
4441 if (SUCCEEDED(rc) && hardDisk)
4442 {
4443 /* first check if it's already registered */
4444 Guid hddUUID;
4445 hardDisk->COMGETTER(Id)(hddUUID.asOutParam());
4446 ComPtr<IHardDisk> registeredHDD;
4447 rc = virtualBox->GetHardDisk(hddUUID, registeredHDD.asOutParam());
4448 if (SUCCEEDED(rc) && registeredHDD)
4449 hardDisk = registeredHDD;
4450 else
4451 {
4452 /* it has to be registered */
4453 CHECK_ERROR(virtualBox, RegisterHardDisk(hardDisk));
4454 if (FAILED(rc))
4455 break;
4456 }
4457 }
4458 }
4459 if (hardDisk)
4460 {
4461 hardDisk->COMGETTER(Id)(uuid.asOutParam());
4462 CHECK_ERROR(machine, AttachHardDisk(uuid, DiskControllerType_IDE0Controller, 1));
4463 }
4464 else
4465 rc = E_FAIL;
4466 if (FAILED(rc))
4467 break;
4468 }
4469 }
4470 if (hdds[2])
4471 {
4472 if (strcmp(hdds[2], "none") == 0)
4473 {
4474 machine->DetachHardDisk(DiskControllerType_IDE1Controller, 1);
4475 }
4476 else
4477 {
4478 /* first guess is that it's a UUID */
4479 Guid uuid(hdds[2]);
4480 ComPtr<IHardDisk> hardDisk;
4481 rc = virtualBox->GetHardDisk(uuid, hardDisk.asOutParam());
4482 /* not successful? Then it must be a filename */
4483 if (!hardDisk)
4484 {
4485 CHECK_ERROR(virtualBox, OpenHardDisk(Bstr(hdds[2]), hardDisk.asOutParam()));
4486 if (SUCCEEDED(rc) && hardDisk)
4487 {
4488 /* first check if it's already registered */
4489 Guid hddUUID;
4490 hardDisk->COMGETTER(Id)(hddUUID.asOutParam());
4491 ComPtr<IHardDisk> registeredHDD;
4492 rc = virtualBox->GetHardDisk(hddUUID, registeredHDD.asOutParam());
4493 if (SUCCEEDED(rc) && registeredHDD)
4494 hardDisk = registeredHDD;
4495 else
4496 {
4497 /* it has to be registered */
4498 CHECK_ERROR(virtualBox, RegisterHardDisk(hardDisk));
4499 if (FAILED(rc))
4500 break;
4501 }
4502 }
4503 }
4504 if (hardDisk)
4505 {
4506 hardDisk->COMGETTER(Id)(uuid.asOutParam());
4507 CHECK_ERROR(machine, AttachHardDisk(uuid, DiskControllerType_IDE1Controller, 1));
4508 }
4509 else
4510 rc = E_FAIL;
4511 if (FAILED(rc))
4512 break;
4513 }
4514 }
4515 if (dvd)
4516 {
4517 ComPtr<IDVDDrive> dvdDrive;
4518 machine->COMGETTER(DVDDrive)(dvdDrive.asOutParam());
4519 ASSERT(dvdDrive);
4520
4521 /* unmount? */
4522 if (strcmp(dvd, "none") == 0)
4523 {
4524 CHECK_ERROR(dvdDrive, Unmount());
4525 }
4526 /* host drive? */
4527 else if (strncmp(dvd, "host:", 5) == 0)
4528 {
4529 ComPtr<IHost> host;
4530 CHECK_ERROR(virtualBox, COMGETTER(Host)(host.asOutParam()));
4531 ComPtr<IHostDVDDriveCollection> hostDVDs;
4532 CHECK_ERROR(host, COMGETTER(DVDDrives)(hostDVDs.asOutParam()));
4533 ComPtr<IHostDVDDrive> hostDVDDrive;
4534 rc = hostDVDs->FindByName(Bstr(dvd + 5), hostDVDDrive.asOutParam());
4535 if (!hostDVDDrive)
4536 {
4537 /* 2nd try: try with the real name, important on Linux+libhal */
4538 char szPathReal[RTPATH_MAX];
4539 if (VBOX_FAILURE(RTPathReal(dvd + 5, szPathReal, sizeof(szPathReal))))
4540 {
4541 errorArgument("Invalid host DVD drive name");
4542 rc = E_FAIL;
4543 break;
4544 }
4545 rc = hostDVDs->FindByName(Bstr(szPathReal), hostDVDDrive.asOutParam());
4546 if (!hostDVDDrive)
4547 {
4548 errorArgument("Invalid host DVD drive name");
4549 rc = E_FAIL;
4550 break;
4551 }
4552 }
4553 CHECK_ERROR(dvdDrive, CaptureHostDrive(hostDVDDrive));
4554 }
4555 else
4556 {
4557 /* first assume it's a UUID */
4558 Guid uuid(dvd);
4559 ComPtr<IDVDImage> dvdImage;
4560 rc = virtualBox->GetDVDImage(uuid, dvdImage.asOutParam());
4561 if (FAILED(rc) || !dvdImage)
4562 {
4563 /* must be a filename, check if it's in the collection */
4564 ComPtr<IDVDImageCollection> dvdImages;
4565 virtualBox->COMGETTER(DVDImages)(dvdImages.asOutParam());
4566 rc = dvdImages->FindByPath(Bstr(dvd), dvdImage.asOutParam());
4567 /* not registered, do that on the fly */
4568 if (!dvdImage)
4569 {
4570 Guid emptyUUID;
4571 CHECK_ERROR(virtualBox, OpenDVDImage(Bstr(dvd), emptyUUID, dvdImage.asOutParam()));
4572 if (SUCCEEDED(rc) && dvdImage)
4573 {
4574 /* time to register the image */
4575 CHECK_ERROR(virtualBox, RegisterDVDImage(dvdImage));
4576 }
4577 }
4578 }
4579 if (!dvdImage)
4580 {
4581 rc = E_FAIL;
4582 break;
4583 }
4584
4585 dvdImage->COMGETTER(Id)(uuid.asOutParam());
4586 CHECK_ERROR(dvdDrive, MountImage(uuid));
4587 }
4588 }
4589 if (dvdpassthrough)
4590 {
4591 ComPtr<IDVDDrive> dvdDrive;
4592 machine->COMGETTER(DVDDrive)(dvdDrive.asOutParam());
4593 ASSERT(dvdDrive);
4594
4595 CHECK_ERROR(dvdDrive, COMSETTER(Passthrough)(strcmp(dvdpassthrough, "on") == 0));
4596 }
4597 if (floppy)
4598 {
4599 ComPtr<IFloppyDrive> floppyDrive;
4600 machine->COMGETTER(FloppyDrive)(floppyDrive.asOutParam());
4601 ASSERT(floppyDrive);
4602
4603 /* disable? */
4604 if (strcmp(floppy, "disabled") == 0)
4605 {
4606 /* disable the controller */
4607 CHECK_ERROR(floppyDrive, COMSETTER(Enabled)(false));
4608 }
4609 else
4610 {
4611 /* enable the controller */
4612 CHECK_ERROR(floppyDrive, COMSETTER(Enabled)(true));
4613
4614 /* unmount? */
4615 if (strcmp(floppy, "empty") == 0)
4616 {
4617 CHECK_ERROR(floppyDrive, Unmount());
4618 }
4619 /* host drive? */
4620 else if (strncmp(floppy, "host:", 5) == 0)
4621 {
4622 ComPtr<IHost> host;
4623 CHECK_ERROR(virtualBox, COMGETTER(Host)(host.asOutParam()));
4624 ComPtr<IHostFloppyDriveCollection> hostFloppies;
4625 CHECK_ERROR(host, COMGETTER(FloppyDrives)(hostFloppies.asOutParam()));
4626 ComPtr<IHostFloppyDrive> hostFloppyDrive;
4627 rc = hostFloppies->FindByName(Bstr(floppy + 5), hostFloppyDrive.asOutParam());
4628 if (!hostFloppyDrive)
4629 {
4630 errorArgument("Invalid host floppy drive name");
4631 rc = E_FAIL;
4632 break;
4633 }
4634 CHECK_ERROR(floppyDrive, CaptureHostDrive(hostFloppyDrive));
4635 }
4636 else
4637 {
4638 /* first assume it's a UUID */
4639 Guid uuid(floppy);
4640 ComPtr<IFloppyImage> floppyImage;
4641 rc = virtualBox->GetFloppyImage(uuid, floppyImage.asOutParam());
4642 if (FAILED(rc) || !floppyImage)
4643 {
4644 /* must be a filename */
4645 Guid emptyUUID;
4646 CHECK_ERROR(virtualBox, OpenFloppyImage(Bstr(floppy), emptyUUID, floppyImage.asOutParam()));
4647 if (SUCCEEDED(rc) && floppyImage)
4648 {
4649 /** @todo first iterate through the collection and try to find the image */
4650 /* time to register the image */
4651 CHECK_ERROR(virtualBox, RegisterFloppyImage(floppyImage));
4652 }
4653 }
4654 if (!floppyImage)
4655 {
4656 rc = E_FAIL;
4657 break;
4658 }
4659
4660 floppyImage->COMGETTER(Id)(uuid.asOutParam());
4661 CHECK_ERROR(floppyDrive, MountImage(uuid));
4662 }
4663 }
4664 }
4665 if (audio)
4666 {
4667 ComPtr<IAudioAdapter> audioAdapter;
4668 machine->COMGETTER(AudioAdapter)(audioAdapter.asOutParam());
4669 ASSERT(audioAdapter);
4670
4671 /* disable? */
4672 if (strcmp(audio, "none") == 0)
4673 {
4674 CHECK_ERROR(audioAdapter, COMSETTER(Enabled)(false));
4675 }
4676 else if (strcmp(audio, "null") == 0)
4677 {
4678 CHECK_ERROR(audioAdapter, COMSETTER(AudioDriver)(AudioDriverType_NullAudioDriver));
4679 CHECK_ERROR(audioAdapter, COMSETTER(Enabled)(true));
4680 }
4681#ifdef RT_OS_WINDOWS
4682#ifdef VBOX_WITH_WINMM
4683 else if (strcmp(audio, "winmm") == 0)
4684 {
4685 CHECK_ERROR(audioAdapter, COMSETTER(AudioDriver)(AudioDriverType_WINMMAudioDriver));
4686 CHECK_ERROR(audioAdapter, COMSETTER(Enabled)(true));
4687 }
4688#endif
4689 else if (strcmp(audio, "dsound") == 0)
4690 {
4691 CHECK_ERROR(audioAdapter, COMSETTER(AudioDriver)(AudioDriverType_DSOUNDAudioDriver));
4692 CHECK_ERROR(audioAdapter, COMSETTER(Enabled)(true));
4693 }
4694#endif /* RT_OS_WINDOWS */
4695#ifdef RT_OS_LINUX
4696 else if (strcmp(audio, "oss") == 0)
4697 {
4698 CHECK_ERROR(audioAdapter, COMSETTER(AudioDriver)(AudioDriverType_OSSAudioDriver));
4699 CHECK_ERROR(audioAdapter, COMSETTER(Enabled)(true));
4700 }
4701# ifdef VBOX_WITH_ALSA
4702 else if (strcmp(audio, "alsa") == 0)
4703 {
4704 CHECK_ERROR(audioAdapter, COMSETTER(AudioDriver)(AudioDriverType_ALSAAudioDriver));
4705 CHECK_ERROR(audioAdapter, COMSETTER(Enabled)(true));
4706 }
4707# endif
4708#endif /* !RT_OS_LINUX */
4709#ifdef RT_OS_DARWIN
4710 else if (strcmp(audio, "coreaudio") == 0)
4711 {
4712 CHECK_ERROR(audioAdapter, COMSETTER(AudioDriver)(AudioDriverType_CoreAudioDriver));
4713 CHECK_ERROR(audioAdapter, COMSETTER(Enabled)(true));
4714 }
4715#endif /* !RT_OS_DARWIN */
4716 else
4717 {
4718 errorArgument("Invalid -audio argument '%s'", audio);
4719 rc = E_FAIL;
4720 break;
4721 }
4722 }
4723 /* Shared clipboard state */
4724 if (clipboard)
4725 {
4726/* ComPtr<IClipboardMode> clipboardMode;
4727 machine->COMGETTER(ClipboardMode)(clipboardMode.asOutParam());
4728 ASSERT(clipboardMode);
4729*/
4730 if (strcmp(clipboard, "disabled") == 0)
4731 {
4732 CHECK_ERROR(machine, COMSETTER(ClipboardMode)(ClipboardMode_ClipDisabled));
4733 }
4734 else if (strcmp(clipboard, "hosttoguest") == 0)
4735 {
4736 CHECK_ERROR(machine, COMSETTER(ClipboardMode)(ClipboardMode_ClipHostToGuest));
4737 }
4738 else if (strcmp(clipboard, "guesttohost") == 0)
4739 {
4740 CHECK_ERROR(machine, COMSETTER(ClipboardMode)(ClipboardMode_ClipGuestToHost));
4741 }
4742 else if (strcmp(clipboard, "bidirectional") == 0)
4743 {
4744 CHECK_ERROR(machine, COMSETTER(ClipboardMode)(ClipboardMode_ClipBidirectional));
4745 }
4746 else
4747 {
4748 errorArgument("Invalid -clipboard argument '%s'", clipboard);
4749 rc = E_FAIL;
4750 break;
4751 }
4752 }
4753 /* iterate through all possible NICs */
4754 for (ULONG n = 0; n < NetworkAdapterCount; n ++)
4755 {
4756 ComPtr<INetworkAdapter> nic;
4757 CHECK_ERROR_RET (machine, GetNetworkAdapter (n, nic.asOutParam()), 1);
4758
4759 ASSERT(nic);
4760
4761 /* something about the NIC? */
4762 if (nics[n])
4763 {
4764 if (strcmp(nics[n], "none") == 0)
4765 {
4766 CHECK_ERROR_RET(nic, COMSETTER(Enabled) (FALSE), 1);
4767 }
4768 else if (strcmp(nics[n], "null") == 0)
4769 {
4770 CHECK_ERROR_RET(nic, COMSETTER(Enabled) (TRUE), 1);
4771 CHECK_ERROR_RET(nic, Detach(), 1);
4772 }
4773 else if (strcmp(nics[n], "nat") == 0)
4774 {
4775 CHECK_ERROR_RET(nic, COMSETTER(Enabled) (TRUE), 1);
4776 CHECK_ERROR_RET(nic, AttachToNAT(), 1);
4777 }
4778 else if (strcmp(nics[n], "hostif") == 0)
4779 {
4780 CHECK_ERROR_RET(nic, COMSETTER(Enabled) (TRUE), 1);
4781 CHECK_ERROR_RET(nic, AttachToHostInterface(), 1);
4782 }
4783 else if (strcmp(nics[n], "intnet") == 0)
4784 {
4785 CHECK_ERROR_RET(nic, COMSETTER(Enabled) (TRUE), 1);
4786 CHECK_ERROR_RET(nic, AttachToInternalNetwork(), 1);
4787 }
4788 else
4789 {
4790 errorArgument("Invalid type '%s' specfied for NIC %lu", nics[n], n + 1);
4791 rc = E_FAIL;
4792 break;
4793 }
4794 }
4795
4796 /* something about the NIC type? */
4797 if (nictype[n])
4798 {
4799 if (strcmp(nictype[n], "Am79C970A") == 0)
4800 {
4801 CHECK_ERROR_RET(nic, COMSETTER(AdapterType)(NetworkAdapterType_NetworkAdapterAm79C970A), 1);
4802 }
4803 else if (strcmp(nictype[n], "Am79C973") == 0)
4804 {
4805 CHECK_ERROR_RET(nic, COMSETTER(AdapterType)(NetworkAdapterType_NetworkAdapterAm79C973), 1);
4806 }
4807 else
4808 {
4809 errorArgument("Invalid NIC type '%s' specified for NIC %lu", nictype[n], n + 1);
4810 rc = E_FAIL;
4811 break;
4812 }
4813 }
4814
4815 /* something about the MAC address? */
4816 if (macs[n])
4817 {
4818 /* generate one? */
4819 if (strcmp(macs[n], "auto") == 0)
4820 {
4821 CHECK_ERROR_RET(nic, COMSETTER(MACAddress)(NULL), 1);
4822 }
4823 else
4824 {
4825 CHECK_ERROR_RET(nic, COMSETTER(MACAddress)(Bstr(macs[n])), 1);
4826 }
4827 }
4828
4829 /* something about the reported link speed? */
4830 if (nicspeed[n])
4831 {
4832 uint32_t u32LineSpeed;
4833
4834 u32LineSpeed = atoi(nicspeed[n]);
4835
4836 if (u32LineSpeed < 1000 || u32LineSpeed > 4000000)
4837 {
4838 errorArgument("Invalid -nicspeed%lu argument '%s'", n + 1, nicspeed[n]);
4839 rc = E_FAIL;
4840 break;
4841 }
4842 CHECK_ERROR_RET(nic, COMSETTER(LineSpeed)(u32LineSpeed), 1);
4843 }
4844
4845 /* the link status flag? */
4846 if (cableconnected[n])
4847 {
4848 if (strcmp(cableconnected[n], "on") == 0)
4849 {
4850 CHECK_ERROR_RET(nic, COMSETTER(CableConnected)(TRUE), 1);
4851 }
4852 else if (strcmp(cableconnected[n], "off") == 0)
4853 {
4854 CHECK_ERROR_RET(nic, COMSETTER(CableConnected)(FALSE), 1);
4855 }
4856 else
4857 {
4858 errorArgument("Invalid -cableconnected%lu argument '%s'", n + 1, cableconnected[n]);
4859 rc = E_FAIL;
4860 break;
4861 }
4862 }
4863
4864 /* the trace flag? */
4865 if (nictrace[n])
4866 {
4867 if (strcmp(nictrace[n], "on") == 0)
4868 {
4869 CHECK_ERROR_RET(nic, COMSETTER(TraceEnabled)(TRUE), 1);
4870 }
4871 else if (strcmp(nictrace[n], "off") == 0)
4872 {
4873 CHECK_ERROR_RET(nic, COMSETTER(TraceEnabled)(FALSE), 1);
4874 }
4875 else
4876 {
4877 errorArgument("Invalid -nictrace%lu argument '%s'", n + 1, nictrace[n]);
4878 rc = E_FAIL;
4879 break;
4880 }
4881 }
4882
4883 /* the tracefile flag? */
4884 if (nictracefile[n])
4885 {
4886 CHECK_ERROR_RET(nic, COMSETTER(TraceFile)(Bstr(nictracefile[n])), 1);
4887 }
4888
4889 /* the host interface device? */
4890 if (hostifdev[n])
4891 {
4892 /* remove it? */
4893 if (strcmp(hostifdev[n], "none") == 0)
4894 {
4895 CHECK_ERROR_RET(nic, COMSETTER(HostInterface)(NULL), 1);
4896 }
4897 else
4898 {
4899 CHECK_ERROR_RET(nic, COMSETTER(HostInterface)(Bstr(hostifdev[n])), 1);
4900 }
4901 }
4902
4903 /* the internal network name? */
4904 if (intnet[n])
4905 {
4906 /* remove it? */
4907 if (strcmp(intnet[n], "none") == 0)
4908 {
4909 CHECK_ERROR_RET(nic, COMSETTER(InternalNetwork)(NULL), 1);
4910 }
4911 else
4912 {
4913 CHECK_ERROR_RET(nic, COMSETTER(InternalNetwork)(Bstr(intnet[n])), 1);
4914 }
4915 }
4916
4917#ifdef RT_OS_LINUX
4918 /* the TAP setup application? */
4919 if (tapsetup[n])
4920 {
4921 /* remove it? */
4922 if (strcmp(tapsetup[n], "none") == 0)
4923 {
4924 CHECK_ERROR_RET(nic, COMSETTER(TAPSetupApplication)(NULL), 1);
4925 }
4926 else
4927 {
4928 CHECK_ERROR_RET(nic, COMSETTER(TAPSetupApplication)(Bstr(tapsetup[n])), 1);
4929 }
4930 }
4931
4932 /* the TAP terminate application? */
4933 if (tapterm[n])
4934 {
4935 /* remove it? */
4936 if (strcmp(tapterm[n], "none") == 0)
4937 {
4938 CHECK_ERROR_RET(nic, COMSETTER(TAPTerminateApplication)(NULL), 1);
4939 }
4940 else
4941 {
4942 CHECK_ERROR_RET(nic, COMSETTER(TAPTerminateApplication)(Bstr(tapterm[n])), 1);
4943 }
4944 }
4945#endif /* RT_OS_LINUX */
4946
4947 }
4948 if (FAILED(rc))
4949 break;
4950
4951 /* iterate through all possible serial ports */
4952 for (ULONG n = 0; n < SerialPortCount; n ++)
4953 {
4954 ComPtr<ISerialPort> uart;
4955 CHECK_ERROR_RET (machine, GetSerialPort (n, uart.asOutParam()), 1);
4956
4957 ASSERT(uart);
4958
4959 if (uarts_base[n])
4960 {
4961 if (uarts_base[n] == (ULONG)-1)
4962 {
4963 CHECK_ERROR_RET(uart, COMSETTER(Enabled) (FALSE), 1);
4964 }
4965 else
4966 {
4967 CHECK_ERROR_RET(uart, COMSETTER(IOBase) (uarts_base[n]), 1);
4968 CHECK_ERROR_RET(uart, COMSETTER(IRQ) (uarts_irq[n]), 1);
4969 CHECK_ERROR_RET(uart, COMSETTER(Enabled) (TRUE), 1);
4970 }
4971 }
4972 if (uarts_mode[n])
4973 {
4974 if (strcmp(uarts_mode[n], "disconnected") == 0)
4975 {
4976 CHECK_ERROR_RET(uart, COMSETTER(HostMode) (PortMode_DisconnectedPort), 1);
4977 }
4978 else
4979 {
4980 if (strcmp(uarts_mode[n], "server") == 0)
4981 {
4982 CHECK_ERROR_RET(uart, COMSETTER(HostMode) (PortMode_HostPipePort), 1);
4983 CHECK_ERROR_RET(uart, COMSETTER(Server) (TRUE), 1);
4984 }
4985 else if (strcmp(uarts_mode[n], "client") == 0)
4986 {
4987 CHECK_ERROR_RET(uart, COMSETTER(HostMode) (PortMode_HostPipePort), 1);
4988 CHECK_ERROR_RET(uart, COMSETTER(Server) (FALSE), 1);
4989 }
4990 else
4991 {
4992 CHECK_ERROR_RET(uart, COMSETTER(HostMode) (PortMode_HostDevicePort), 1);
4993 }
4994 CHECK_ERROR_RET(uart, COMSETTER(Path) (Bstr(uarts_path[n])), 1);
4995 }
4996 }
4997 }
4998 if (FAILED(rc))
4999 break;
5000
5001#ifdef VBOX_VRDP
5002 if (vrdp || (vrdpport != UINT16_MAX) || vrdpaddress || vrdpauthtype || vrdpmulticon)
5003 {
5004 ComPtr<IVRDPServer> vrdpServer;
5005 machine->COMGETTER(VRDPServer)(vrdpServer.asOutParam());
5006 ASSERT(vrdpServer);
5007 if (vrdpServer)
5008 {
5009 if (vrdp)
5010 {
5011 if (strcmp(vrdp, "on") == 0)
5012 {
5013 CHECK_ERROR(vrdpServer, COMSETTER(Enabled)(true));
5014 }
5015 else if (strcmp(vrdp, "off") == 0)
5016 {
5017 CHECK_ERROR(vrdpServer, COMSETTER(Enabled)(false));
5018 }
5019 else
5020 {
5021 errorArgument("Invalid -vrdp argument '%s'", vrdp);
5022 rc = E_FAIL;
5023 break;
5024 }
5025 }
5026 if (vrdpport != UINT16_MAX)
5027 {
5028 CHECK_ERROR(vrdpServer, COMSETTER(Port)(vrdpport));
5029 }
5030 if (vrdpaddress)
5031 {
5032 CHECK_ERROR(vrdpServer, COMSETTER(NetAddress)(Bstr(vrdpaddress)));
5033 }
5034 if (vrdpauthtype)
5035 {
5036 if (strcmp(vrdpauthtype, "null") == 0)
5037 {
5038 CHECK_ERROR(vrdpServer, COMSETTER(AuthType)(VRDPAuthType_VRDPAuthNull));
5039 }
5040 else if (strcmp(vrdpauthtype, "external") == 0)
5041 {
5042 CHECK_ERROR(vrdpServer, COMSETTER(AuthType)(VRDPAuthType_VRDPAuthExternal));
5043 }
5044 else if (strcmp(vrdpauthtype, "guest") == 0)
5045 {
5046 CHECK_ERROR(vrdpServer, COMSETTER(AuthType)(VRDPAuthType_VRDPAuthGuest));
5047 }
5048 else
5049 {
5050 errorArgument("Invalid -vrdpauthtype argument '%s'", vrdpauthtype);
5051 rc = E_FAIL;
5052 break;
5053 }
5054 }
5055 if (vrdpmulticon)
5056 {
5057 if (strcmp(vrdpmulticon, "on") == 0)
5058 {
5059 CHECK_ERROR(vrdpServer, COMSETTER(AllowMultiConnection)(true));
5060 }
5061 else if (strcmp(vrdpmulticon, "off") == 0)
5062 {
5063 CHECK_ERROR(vrdpServer, COMSETTER(AllowMultiConnection)(false));
5064 }
5065 else
5066 {
5067 errorArgument("Invalid -vrdpmulticon argument '%s'", vrdpmulticon);
5068 rc = E_FAIL;
5069 break;
5070 }
5071 }
5072 }
5073 }
5074#endif /* VBOX_VRDP */
5075
5076 /*
5077 * USB enable/disable
5078 */
5079 if (fUsbEnabled != -1)
5080 {
5081 ComPtr<IUSBController> UsbCtl;
5082 CHECK_ERROR(machine, COMGETTER(USBController)(UsbCtl.asOutParam()));
5083 if (SUCCEEDED(rc))
5084 {
5085 CHECK_ERROR(UsbCtl, COMSETTER(Enabled)(!!fUsbEnabled));
5086 }
5087 }
5088
5089 if (snapshotFolder)
5090 {
5091 if (strcmp(snapshotFolder, "default") == 0)
5092 {
5093 CHECK_ERROR(machine, COMSETTER(SnapshotFolder)(NULL));
5094 }
5095 else
5096 {
5097 CHECK_ERROR(machine, COMSETTER(SnapshotFolder)(Bstr(snapshotFolder)));
5098 }
5099 }
5100
5101 if (guestMemBalloonSize != (ULONG)-1)
5102 CHECK_ERROR(machine, COMSETTER(MemoryBalloonSize)(guestMemBalloonSize));
5103
5104 if (guestStatInterval != (ULONG)-1)
5105 CHECK_ERROR(machine, COMSETTER(StatisticsUpdateInterval)(guestStatInterval));
5106
5107 /* commit changes */
5108 CHECK_ERROR(machine, SaveSettings());
5109 }
5110 while (0);
5111
5112 /* it's important to always close sessions */
5113 session->Close();
5114
5115 return SUCCEEDED(rc) ? 0 : 1;
5116}
5117
5118static int handleStartVM(int argc, char *argv[],
5119 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)
5120{
5121 HRESULT rc;
5122
5123 if (argc < 1)
5124 {
5125 return errorSyntax(USAGE_STARTVM, "Not enough parameters");
5126 }
5127
5128 ComPtr<IMachine> machine;
5129 /* assume it's a UUID */
5130 rc = virtualBox->GetMachine(Guid(argv[0]), machine.asOutParam());
5131 if (FAILED(rc) || !machine)
5132 {
5133 /* must be a name */
5134 CHECK_ERROR(virtualBox, FindMachine(Bstr(argv[0]), machine.asOutParam()));
5135 }
5136 if (machine)
5137 {
5138 Guid uuid;
5139 machine->COMGETTER(Id)(uuid.asOutParam());
5140
5141 /* default to GUI session type */
5142 Bstr sessionType = "gui";
5143 /* has a session type been specified? */
5144 if ((argc > 2) && (strcmp(argv[1], "-type") == 0))
5145 {
5146 if (strcmp(argv[2], "gui") == 0)
5147 {
5148 sessionType = "gui";
5149 }
5150 else if (strcmp(argv[2], "vrdp") == 0)
5151 {
5152 sessionType = "vrdp";
5153 }
5154 else if (strcmp(argv[2], "capture") == 0)
5155 {
5156 sessionType = "capture";
5157 }
5158 else
5159 {
5160 return errorArgument("Invalid session type argument '%s'", argv[2]);
5161 }
5162 }
5163
5164 Bstr env;
5165#ifdef RT_OS_LINUX
5166 /* make sure the VM process will start on the same display as VBoxManage */
5167 {
5168 const char *display = RTEnvGet ("DISPLAY");
5169 if (display)
5170 env = Utf8StrFmt ("DISPLAY=%s", display);
5171 }
5172#endif
5173 ComPtr<IProgress> progress;
5174 CHECK_ERROR_RET(virtualBox, OpenRemoteSession(session, uuid, sessionType,
5175 env, progress.asOutParam()), rc);
5176 RTPrintf("Waiting for the remote session to open...\n");
5177 CHECK_ERROR_RET(progress, WaitForCompletion (-1), 1);
5178
5179 BOOL completed;
5180 CHECK_ERROR_RET(progress, COMGETTER(Completed)(&completed), rc);
5181 ASSERT(completed);
5182
5183 HRESULT resultCode;
5184 CHECK_ERROR_RET(progress, COMGETTER(ResultCode)(&resultCode), rc);
5185 if (FAILED(resultCode))
5186 {
5187 ComPtr <IVirtualBoxErrorInfo> errorInfo;
5188 CHECK_ERROR_RET(progress, COMGETTER(ErrorInfo)(errorInfo.asOutParam()), 1);
5189 ErrorInfo info (errorInfo);
5190 PRINT_ERROR_INFO(info);
5191 }
5192 else
5193 {
5194 RTPrintf("Remote session has been successfully opened.\n");
5195 }
5196 }
5197
5198 /* it's important to always close sessions */
5199 session->Close();
5200
5201 return SUCCEEDED(rc) ? 0 : 1;
5202}
5203
5204static int handleControlVM(int argc, char *argv[],
5205 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)
5206{
5207 HRESULT rc;
5208
5209 if (argc < 2)
5210 {
5211 return errorSyntax(USAGE_CONTROLVM, "Not enough parameters");
5212 }
5213
5214 /* try to find the given machine */
5215 ComPtr <IMachine> machine;
5216 Guid uuid (argv[0]);
5217 if (!uuid.isEmpty())
5218 {
5219 CHECK_ERROR (virtualBox, GetMachine (uuid, machine.asOutParam()));
5220 }
5221 else
5222 {
5223 CHECK_ERROR (virtualBox, FindMachine (Bstr(argv[0]), machine.asOutParam()));
5224 if (SUCCEEDED (rc))
5225 machine->COMGETTER(Id) (uuid.asOutParam());
5226 }
5227 if (FAILED (rc))
5228 return 1;
5229
5230 /* open a session for the VM */
5231 CHECK_ERROR_RET (virtualBox, OpenExistingSession (session, uuid), 1);
5232
5233 do
5234 {
5235 /* get the associated console */
5236 ComPtr<IConsole> console;
5237 CHECK_ERROR_BREAK (session, COMGETTER(Console)(console.asOutParam()));
5238 /* ... and session machine */
5239 ComPtr<IMachine> sessionMachine;
5240 CHECK_ERROR_BREAK (session, COMGETTER(Machine)(sessionMachine.asOutParam()));
5241
5242 /* which command? */
5243 if (strcmp(argv[1], "pause") == 0)
5244 {
5245 CHECK_ERROR_BREAK (console, Pause());
5246 }
5247 else if (strcmp(argv[1], "resume") == 0)
5248 {
5249 CHECK_ERROR_BREAK (console, Resume());
5250 }
5251 else if (strcmp(argv[1], "reset") == 0)
5252 {
5253 CHECK_ERROR_BREAK (console, Reset());
5254 }
5255 else if (strcmp(argv[1], "poweroff") == 0)
5256 {
5257 CHECK_ERROR_BREAK (console, PowerDown());
5258 }
5259 else if (strcmp(argv[1], "savestate") == 0)
5260 {
5261 ComPtr<IProgress> progress;
5262 CHECK_ERROR_BREAK (console, SaveState(progress.asOutParam()));
5263
5264 showProgress(progress);
5265
5266 progress->COMGETTER(ResultCode)(&rc);
5267 if (FAILED(rc))
5268 {
5269 com::ProgressErrorInfo info(progress);
5270 if (info.isBasicAvailable())
5271 {
5272 RTPrintf("Error: failed to save machine state. Error message: %lS\n", info.getText().raw());
5273 }
5274 else
5275 {
5276 RTPrintf("Error: failed to save machine state. No error message available!\n");
5277 }
5278 }
5279 }
5280 else if (strcmp(argv[1], "acpipowerbutton") == 0)
5281 {
5282 CHECK_ERROR_BREAK (console, PowerButton());
5283 }
5284 else if (strncmp(argv[1], "setlinkstate", 12) == 0)
5285 {
5286 /* Get the number of network adapters */
5287 ULONG NetworkAdapterCount = 0;
5288 ComPtr <ISystemProperties> info;
5289 CHECK_ERROR_BREAK (virtualBox, COMGETTER(SystemProperties) (info.asOutParam()));
5290 CHECK_ERROR_BREAK (info, COMGETTER(NetworkAdapterCount) (&NetworkAdapterCount));
5291
5292 unsigned n = parseNum(&argv[1][12], NetworkAdapterCount, "NIC");
5293 if (!n)
5294 {
5295 rc = E_FAIL;
5296 break;
5297 }
5298 if (argc <= 1 + 1)
5299 {
5300 errorArgument("Missing argument to '%s'", argv[1]);
5301 rc = E_FAIL;
5302 break;
5303 }
5304 /* get the corresponding network adapter */
5305 ComPtr<INetworkAdapter> adapter;
5306 CHECK_ERROR_BREAK (sessionMachine, GetNetworkAdapter(n - 1, adapter.asOutParam()));
5307 if (adapter)
5308 {
5309 if (strcmp(argv[2], "on") == 0)
5310 {
5311 CHECK_ERROR_BREAK (adapter, COMSETTER(CableConnected)(TRUE));
5312 }
5313 else if (strcmp(argv[2], "off") == 0)
5314 {
5315 CHECK_ERROR_BREAK (adapter, COMSETTER(CableConnected)(FALSE));
5316 }
5317 else
5318 {
5319 errorArgument("Invalid link state '%s'", Utf8Str(argv[2]).raw());
5320 rc = E_FAIL;
5321 break;
5322 }
5323 }
5324 }
5325 else if (strcmp (argv[1], "usbattach") == 0 ||
5326 strcmp (argv[1], "usbdetach") == 0)
5327 {
5328 if (argc < 3)
5329 {
5330 errorSyntax(USAGE_CONTROLVM, "Not enough parameters");
5331 rc = E_FAIL;
5332 break;
5333 }
5334
5335 bool attach = strcmp (argv[1], "usbattach") == 0;
5336
5337 Guid usbId = argv [2];
5338 if (usbId.isEmpty())
5339 {
5340 // assume address
5341 if (attach)
5342 {
5343 ComPtr <IHost> host;
5344 CHECK_ERROR_BREAK (virtualBox, COMGETTER(Host) (host.asOutParam()));
5345 ComPtr <IHostUSBDeviceCollection> coll;
5346 CHECK_ERROR_BREAK (host, COMGETTER(USBDevices) (coll.asOutParam()));
5347 ComPtr <IHostUSBDevice> dev;
5348 CHECK_ERROR_BREAK (coll, FindByAddress (Bstr (argv [2]), dev.asOutParam()));
5349 CHECK_ERROR_BREAK (dev, COMGETTER(Id) (usbId.asOutParam()));
5350 }
5351 else
5352 {
5353 ComPtr <IUSBDeviceCollection> coll;
5354 CHECK_ERROR_BREAK (console, COMGETTER(USBDevices)(coll.asOutParam()));
5355 ComPtr <IUSBDevice> dev;
5356 CHECK_ERROR_BREAK (coll, FindByAddress (Bstr (argv [2]), dev.asOutParam()));
5357 CHECK_ERROR_BREAK (dev, COMGETTER(Id) (usbId.asOutParam()));
5358 }
5359 }
5360
5361 if (attach)
5362 CHECK_ERROR_BREAK (console, AttachUSBDevice (usbId));
5363 else
5364 {
5365 ComPtr <IUSBDevice> dev;
5366 CHECK_ERROR_BREAK (console, DetachUSBDevice (usbId, dev.asOutParam()));
5367 }
5368 }
5369 else if (strcmp(argv[1], "setvideomodehint") == 0)
5370 {
5371 if (argc != 5 && argc != 6)
5372 {
5373 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
5374 rc = E_FAIL;
5375 break;
5376 }
5377 uint32_t xres = atoi(argv[2]);
5378 uint32_t yres = atoi(argv[3]);
5379 uint32_t bpp = atoi(argv[4]);
5380 uint32_t displayIdx = 0;
5381 if (argc == 6)
5382 displayIdx = atoi(argv[5]);
5383
5384 ComPtr<IDisplay> display;
5385 CHECK_ERROR_BREAK(console, COMGETTER(Display)(display.asOutParam()));
5386 CHECK_ERROR_BREAK(display, SetVideoModeHint(xres, yres, bpp, displayIdx));
5387 }
5388 else if (strcmp(argv[1], "setcredentials") == 0)
5389 {
5390 bool fAllowLocalLogon = true;
5391 if (argc == 7)
5392 {
5393 if (strcmp(argv[5], "-allowlocallogon") != 0)
5394 {
5395 errorArgument("Invalid parameter '%s'", argv[5]);
5396 rc = E_FAIL;
5397 break;
5398 }
5399 if (strcmp(argv[6], "no") == 0)
5400 fAllowLocalLogon = false;
5401 }
5402 else if (argc != 5)
5403 {
5404 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
5405 rc = E_FAIL;
5406 break;
5407 }
5408
5409 ComPtr<IGuest> guest;
5410 CHECK_ERROR_BREAK(console, COMGETTER(Guest)(guest.asOutParam()));
5411 CHECK_ERROR_BREAK(guest, SetCredentials(Bstr(argv[2]), Bstr(argv[3]), Bstr(argv[4]), fAllowLocalLogon));
5412 }
5413 else if (strcmp(argv[1], "dvdattach") == 0)
5414 {
5415 if (argc != 3)
5416 {
5417 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
5418 rc = E_FAIL;
5419 break;
5420 }
5421 ComPtr<IDVDDrive> dvdDrive;
5422 sessionMachine->COMGETTER(DVDDrive)(dvdDrive.asOutParam());
5423 ASSERT(dvdDrive);
5424
5425 /* unmount? */
5426 if (strcmp(argv[2], "none") == 0)
5427 {
5428 CHECK_ERROR(dvdDrive, Unmount());
5429 }
5430 /* host drive? */
5431 else if (strncmp(argv[2], "host:", 5) == 0)
5432 {
5433 ComPtr<IHost> host;
5434 CHECK_ERROR(virtualBox, COMGETTER(Host)(host.asOutParam()));
5435 ComPtr<IHostDVDDriveCollection> hostDVDs;
5436 CHECK_ERROR(host, COMGETTER(DVDDrives)(hostDVDs.asOutParam()));
5437 ComPtr<IHostDVDDrive> hostDVDDrive;
5438 rc = hostDVDs->FindByName(Bstr(argv[2] + 5), hostDVDDrive.asOutParam());
5439 if (!hostDVDDrive)
5440 {
5441 errorArgument("Invalid host DVD drive name");
5442 rc = E_FAIL;
5443 break;
5444 }
5445 CHECK_ERROR(dvdDrive, CaptureHostDrive(hostDVDDrive));
5446 }
5447 else
5448 {
5449 /* first assume it's a UUID */
5450 Guid uuid(argv[2]);
5451 ComPtr<IDVDImage> dvdImage;
5452 rc = virtualBox->GetDVDImage(uuid, dvdImage.asOutParam());
5453 if (FAILED(rc) || !dvdImage)
5454 {
5455 /* must be a filename, check if it's in the collection */
5456 ComPtr<IDVDImageCollection> dvdImages;
5457 virtualBox->COMGETTER(DVDImages)(dvdImages.asOutParam());
5458 rc = dvdImages->FindByPath(Bstr(argv[2]), dvdImage.asOutParam());
5459 /* not registered, do that on the fly */
5460 if (!dvdImage)
5461 {
5462 Guid emptyUUID;
5463 CHECK_ERROR(virtualBox, OpenDVDImage(Bstr(argv[2]), emptyUUID, dvdImage.asOutParam()));
5464 if (SUCCEEDED(rc) && dvdImage)
5465 {
5466 /* time to register the image */
5467 CHECK_ERROR(virtualBox, RegisterDVDImage(dvdImage));
5468 }
5469 }
5470 }
5471 if (!dvdImage)
5472 {
5473 rc = E_FAIL;
5474 break;
5475 }
5476 dvdImage->COMGETTER(Id)(uuid.asOutParam());
5477 CHECK_ERROR(dvdDrive, MountImage(uuid));
5478 }
5479 }
5480 else if (strcmp(argv[1], "floppyattach") == 0)
5481 {
5482 if (argc != 3)
5483 {
5484 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
5485 rc = E_FAIL;
5486 break;
5487 }
5488
5489 ComPtr<IFloppyDrive> floppyDrive;
5490 sessionMachine->COMGETTER(FloppyDrive)(floppyDrive.asOutParam());
5491 ASSERT(floppyDrive);
5492
5493 /* unmount? */
5494 if (strcmp(argv[2], "none") == 0)
5495 {
5496 CHECK_ERROR(floppyDrive, Unmount());
5497 }
5498 /* host drive? */
5499 else if (strncmp(argv[2], "host:", 5) == 0)
5500 {
5501 ComPtr<IHost> host;
5502 CHECK_ERROR(virtualBox, COMGETTER(Host)(host.asOutParam()));
5503 ComPtr<IHostFloppyDriveCollection> hostFloppies;
5504 CHECK_ERROR(host, COMGETTER(FloppyDrives)(hostFloppies.asOutParam()));
5505 ComPtr<IHostFloppyDrive> hostFloppyDrive;
5506 rc = hostFloppies->FindByName(Bstr(argv[2] + 5), hostFloppyDrive.asOutParam());
5507 if (!hostFloppyDrive)
5508 {
5509 errorArgument("Invalid host floppy drive name");
5510 rc = E_FAIL;
5511 break;
5512 }
5513 CHECK_ERROR(floppyDrive, CaptureHostDrive(hostFloppyDrive));
5514 }
5515 else
5516 {
5517 /* first assume it's a UUID */
5518 Guid uuid(argv[2]);
5519 ComPtr<IFloppyImage> floppyImage;
5520 rc = virtualBox->GetFloppyImage(uuid, floppyImage.asOutParam());
5521 if (FAILED(rc) || !floppyImage)
5522 {
5523 /* must be a filename, check if it's in the collection */
5524 ComPtr<IFloppyImageCollection> floppyImages;
5525 virtualBox->COMGETTER(FloppyImages)(floppyImages.asOutParam());
5526 rc = floppyImages->FindByPath(Bstr(argv[2]), floppyImage.asOutParam());
5527 /* not registered, do that on the fly */
5528 if (!floppyImage)
5529 {
5530 Guid emptyUUID;
5531 CHECK_ERROR(virtualBox, OpenFloppyImage(Bstr(argv[2]), emptyUUID, floppyImage.asOutParam()));
5532 if (SUCCEEDED(rc) && floppyImage)
5533 {
5534 /* time to register the image */
5535 CHECK_ERROR(virtualBox, RegisterFloppyImage(floppyImage));
5536 }
5537 }
5538 }
5539 if (!floppyImage)
5540 {
5541 rc = E_FAIL;
5542 break;
5543 }
5544 floppyImage->COMGETTER(Id)(uuid.asOutParam());
5545 CHECK_ERROR(floppyDrive, MountImage(uuid));
5546 }
5547 }
5548 else if (strncmp(argv[1], "-guestmemoryballoon", 19) == 0)
5549 {
5550 if (argc != 3)
5551 {
5552 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
5553 rc = E_FAIL;
5554 break;
5555 }
5556 uint32_t uVal;
5557 int vrc;
5558 vrc = RTStrToUInt32Ex(argv[2], NULL, 0, &uVal);
5559 if (vrc != VINF_SUCCESS)
5560 {
5561 errorArgument("Error parsing guest memory balloon size '%s'", argv[2]);
5562 rc = E_FAIL;
5563 break;
5564 }
5565
5566 /* guest is running; update IGuest */
5567 ComPtr <IGuest> guest;
5568
5569 rc = console->COMGETTER(Guest)(guest.asOutParam());
5570 if (SUCCEEDED(rc))
5571 CHECK_ERROR(guest, COMSETTER(MemoryBalloonSize)(uVal));
5572 }
5573 else if (strncmp(argv[1], "-gueststatisticsinterval", 24) == 0)
5574 {
5575 if (argc != 3)
5576 {
5577 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
5578 rc = E_FAIL;
5579 break;
5580 }
5581 uint32_t uVal;
5582 int vrc;
5583 vrc = RTStrToUInt32Ex(argv[2], NULL, 0, &uVal);
5584 if (vrc != VINF_SUCCESS)
5585 {
5586 errorArgument("Error parsing guest memory balloon size '%s'", argv[2]);
5587 rc = E_FAIL;
5588 break;
5589 }
5590
5591 /* guest is running; update IGuest */
5592 ComPtr <IGuest> guest;
5593
5594 rc = console->COMGETTER(Guest)(guest.asOutParam());
5595 if (SUCCEEDED(rc))
5596 CHECK_ERROR(guest, COMSETTER(StatisticsUpdateInterval)(uVal));
5597 }
5598 else
5599 {
5600 errorSyntax(USAGE_CONTROLVM, "Invalid parameter '%s'", Utf8Str(argv[1]).raw());
5601 rc = E_FAIL;
5602 }
5603 }
5604 while (0);
5605
5606 session->Close();
5607
5608 return SUCCEEDED (rc) ? 0 : 1;
5609}
5610
5611static int handleDiscardState(int argc, char *argv[],
5612 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)
5613{
5614 HRESULT rc;
5615
5616 if (argc != 1)
5617 {
5618 return errorSyntax(USAGE_DISCARDSTATE, "Incorrect number of parameters");
5619 }
5620
5621 ComPtr<IMachine> machine;
5622 /* assume it's a UUID */
5623 rc = virtualBox->GetMachine(Guid(argv[0]), machine.asOutParam());
5624 if (FAILED(rc) || !machine)
5625 {
5626 /* must be a name */
5627 CHECK_ERROR(virtualBox, FindMachine(Bstr(argv[0]), machine.asOutParam()));
5628 }
5629 if (machine)
5630 {
5631 do
5632 {
5633 /* we have to open a session for this task */
5634 Guid guid;
5635 machine->COMGETTER(Id)(guid.asOutParam());
5636 CHECK_ERROR_BREAK(virtualBox, OpenSession(session, guid));
5637 do
5638 {
5639 ComPtr<IConsole> console;
5640 CHECK_ERROR_BREAK(session, COMGETTER(Console)(console.asOutParam()));
5641 CHECK_ERROR_BREAK(console, DiscardSavedState());
5642 }
5643 while (0);
5644 CHECK_ERROR_BREAK(session, Close());
5645 }
5646 while (0);
5647 }
5648
5649 return SUCCEEDED(rc) ? 0 : 1;
5650}
5651
5652static int handleAdoptdState(int argc, char *argv[],
5653 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)
5654{
5655 HRESULT rc;
5656
5657 if (argc != 2)
5658 {
5659 return errorSyntax(USAGE_ADOPTSTATE, "Incorrect number of parameters");
5660 }
5661
5662 ComPtr<IMachine> machine;
5663 /* assume it's a UUID */
5664 rc = virtualBox->GetMachine(Guid(argv[0]), machine.asOutParam());
5665 if (FAILED(rc) || !machine)
5666 {
5667 /* must be a name */
5668 CHECK_ERROR(virtualBox, FindMachine(Bstr(argv[0]), machine.asOutParam()));
5669 }
5670 if (machine)
5671 {
5672 do
5673 {
5674 /* we have to open a session for this task */
5675 Guid guid;
5676 machine->COMGETTER(Id)(guid.asOutParam());
5677 CHECK_ERROR_BREAK(virtualBox, OpenSession(session, guid));
5678 do
5679 {
5680 ComPtr<IConsole> console;
5681 CHECK_ERROR_BREAK(session, COMGETTER(Console)(console.asOutParam()));
5682 CHECK_ERROR_BREAK(console, AdoptSavedState (Bstr (argv[1])));
5683 }
5684 while (0);
5685 CHECK_ERROR_BREAK(session, Close());
5686 }
5687 while (0);
5688 }
5689
5690 return SUCCEEDED(rc) ? 0 : 1;
5691}
5692
5693static int handleSnapshot(int argc, char *argv[],
5694 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)
5695{
5696 HRESULT rc;
5697
5698 /* we need at least a VM and a command */
5699 if (argc < 2)
5700 {
5701 return errorSyntax(USAGE_SNAPSHOT, "Not enough parameters");
5702 }
5703
5704 /* the first argument must be the VM */
5705 ComPtr<IMachine> machine;
5706 /* assume it's a UUID */
5707 rc = virtualBox->GetMachine(Guid(argv[0]), machine.asOutParam());
5708 if (FAILED(rc) || !machine)
5709 {
5710 /* must be a name */
5711 CHECK_ERROR(virtualBox, FindMachine(Bstr(argv[0]), machine.asOutParam()));
5712 }
5713 if (!machine)
5714 return 1;
5715 Guid guid;
5716 machine->COMGETTER(Id)(guid.asOutParam());
5717
5718 do
5719 {
5720 /* we have to open a session for this task. First try an existing session */
5721 rc = virtualBox->OpenExistingSession(session, guid);
5722 if (FAILED(rc))
5723 CHECK_ERROR_BREAK(virtualBox, OpenSession(session, guid));
5724 ComPtr<IConsole> console;
5725 CHECK_ERROR_BREAK(session, COMGETTER(Console)(console.asOutParam()));
5726
5727 /* switch based on the command */
5728 if (strcmp(argv[1], "take") == 0)
5729 {
5730 /* there must be a name */
5731 if (argc < 3)
5732 {
5733 errorSyntax(USAGE_SNAPSHOT, "Missing snapshot name");
5734 rc = E_FAIL;
5735 break;
5736 }
5737 Bstr name(argv[2]);
5738 if ((argc > 3) && ((argc != 5) || (strcmp(argv[3], "-desc") != 0)))
5739 {
5740 errorSyntax(USAGE_SNAPSHOT, "Incorrect description format");
5741 rc = E_FAIL;
5742 break;
5743 }
5744 Bstr desc;
5745 if (argc == 5)
5746 desc = argv[4];
5747 ComPtr<IProgress> progress;
5748 CHECK_ERROR_BREAK(console, TakeSnapshot(name, desc, progress.asOutParam()));
5749
5750 showProgress(progress);
5751 progress->COMGETTER(ResultCode)(&rc);
5752 if (FAILED(rc))
5753 {
5754 com::ProgressErrorInfo info(progress);
5755 if (info.isBasicAvailable())
5756 {
5757 RTPrintf("Error: failed to take snapshot. Error message: %lS\n", info.getText().raw());
5758 }
5759 else
5760 {
5761 RTPrintf("Error: failed to take snapshot. No error message available!\n");
5762 }
5763 }
5764 }
5765 else if (strcmp(argv[1], "discard") == 0)
5766 {
5767 /* exactly one parameter: snapshot name */
5768 if (argc != 3)
5769 {
5770 errorSyntax(USAGE_SNAPSHOT, "Expecting snapshot name only");
5771 rc = E_FAIL;
5772 break;
5773 }
5774
5775 ComPtr<ISnapshot> snapshot;
5776
5777 /* assume it's a UUID */
5778 Guid guid(argv[2]);
5779 if (!guid.isEmpty())
5780 {
5781 CHECK_ERROR_BREAK(machine, GetSnapshot(guid, snapshot.asOutParam()));
5782 }
5783 else
5784 {
5785 /* then it must be a name */
5786 CHECK_ERROR_BREAK(machine, FindSnapshot(Bstr(argv[2]), snapshot.asOutParam()));
5787 }
5788
5789 snapshot->COMGETTER(Id)(guid.asOutParam());
5790
5791 ComPtr<IProgress> progress;
5792 CHECK_ERROR_BREAK(console, DiscardSnapshot(guid, progress.asOutParam()));
5793
5794 showProgress(progress);
5795 progress->COMGETTER(ResultCode)(&rc);
5796 if (FAILED(rc))
5797 {
5798 com::ProgressErrorInfo info(progress);
5799 if (info.isBasicAvailable())
5800 {
5801 RTPrintf("Error: failed to discard snapshot. Error message: %lS\n", info.getText().raw());
5802 }
5803 else
5804 {
5805 RTPrintf("Error: failed to discard snapshot. No error message available!\n");
5806 }
5807 }
5808 }
5809 else if (strcmp(argv[1], "discardcurrent") == 0)
5810 {
5811 if ( (argc != 3)
5812 || ( (strcmp(argv[2], "-state") != 0)
5813 && (strcmp(argv[2], "-all") != 0)))
5814 {
5815 errorSyntax(USAGE_SNAPSHOT, "Invalid parameter '%s'", Utf8Str(argv[2]).raw());
5816 rc = E_FAIL;
5817 break;
5818 }
5819 bool fAll = false;
5820 if (strcmp(argv[2], "-all") == 0)
5821 fAll = true;
5822
5823 ComPtr<IProgress> progress;
5824
5825 if (fAll)
5826 {
5827 CHECK_ERROR_BREAK(console, DiscardCurrentSnapshotAndState(progress.asOutParam()));
5828 }
5829 else
5830 {
5831 CHECK_ERROR_BREAK(console, DiscardCurrentState(progress.asOutParam()));
5832 }
5833
5834 showProgress(progress);
5835 progress->COMGETTER(ResultCode)(&rc);
5836 if (FAILED(rc))
5837 {
5838 com::ProgressErrorInfo info(progress);
5839 if (info.isBasicAvailable())
5840 {
5841 RTPrintf("Error: failed to discard. Error message: %lS\n", info.getText().raw());
5842 }
5843 else
5844 {
5845 RTPrintf("Error: failed to discard. No error message available!\n");
5846 }
5847 }
5848
5849 }
5850 else if (strcmp(argv[1], "edit") == 0)
5851 {
5852 if (argc < 3)
5853 {
5854 errorSyntax(USAGE_SNAPSHOT, "Missing snapshot name");
5855 rc = E_FAIL;
5856 break;
5857 }
5858
5859 ComPtr<ISnapshot> snapshot;
5860
5861 if (strcmp(argv[2], "-current") == 0)
5862 {
5863 CHECK_ERROR_BREAK(machine, COMGETTER(CurrentSnapshot)(snapshot.asOutParam()));
5864 }
5865 else
5866 {
5867 /* assume it's a UUID */
5868 Guid guid(argv[2]);
5869 if (!guid.isEmpty())
5870 {
5871 CHECK_ERROR_BREAK(machine, GetSnapshot(guid, snapshot.asOutParam()));
5872 }
5873 else
5874 {
5875 /* then it must be a name */
5876 CHECK_ERROR_BREAK(machine, FindSnapshot(Bstr(argv[2]), snapshot.asOutParam()));
5877 }
5878 }
5879
5880 /* parse options */
5881 for (int i = 3; i < argc; i++)
5882 {
5883 if (strcmp(argv[i], "-newname") == 0)
5884 {
5885 if (argc <= i + 1)
5886 {
5887 errorArgument("Missing argument to '%s'", argv[i]);
5888 rc = E_FAIL;
5889 break;
5890 }
5891 i++;
5892 snapshot->COMSETTER(Name)(Bstr(argv[i]));
5893 }
5894 else if (strcmp(argv[i], "-newdesc") == 0)
5895 {
5896 if (argc <= i + 1)
5897 {
5898 errorArgument("Missing argument to '%s'", argv[i]);
5899 rc = E_FAIL;
5900 break;
5901 }
5902 i++;
5903 snapshot->COMSETTER(Description)(Bstr(argv[i]));
5904 }
5905 else
5906 {
5907 errorSyntax(USAGE_SNAPSHOT, "Invalid parameter '%s'", Utf8Str(argv[i]).raw());
5908 rc = E_FAIL;
5909 break;
5910 }
5911 }
5912
5913 }
5914 else if (strcmp(argv[1], "showvminfo") == 0)
5915 {
5916 /* exactly one parameter: snapshot name */
5917 if (argc != 3)
5918 {
5919 errorSyntax(USAGE_SNAPSHOT, "Expecting snapshot name only");
5920 rc = E_FAIL;
5921 break;
5922 }
5923
5924 ComPtr<ISnapshot> snapshot;
5925
5926 /* assume it's a UUID */
5927 Guid guid(argv[2]);
5928 if (!guid.isEmpty())
5929 {
5930 CHECK_ERROR_BREAK(machine, GetSnapshot(guid, snapshot.asOutParam()));
5931 }
5932 else
5933 {
5934 /* then it must be a name */
5935 CHECK_ERROR_BREAK(machine, FindSnapshot(Bstr(argv[2]), snapshot.asOutParam()));
5936 }
5937
5938 /* get the machine of the given snapshot */
5939 ComPtr<IMachine> machine;
5940 snapshot->COMGETTER(Machine)(machine.asOutParam());
5941 showVMInfo(virtualBox, machine, console);
5942 }
5943 else
5944 {
5945 errorSyntax(USAGE_SNAPSHOT, "Invalid parameter '%s'", Utf8Str(argv[1]).raw());
5946 rc = E_FAIL;
5947 }
5948 } while (0);
5949
5950 session->Close();
5951
5952 return SUCCEEDED(rc) ? 0 : 1;
5953}
5954
5955static int handleShowVDIInfo(int argc, char *argv[],
5956 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)
5957{
5958 HRESULT rc;
5959
5960 if (argc != 1)
5961 {
5962 return errorSyntax(USAGE_SHOWVDIINFO, "Incorrect number of parameters");
5963 }
5964
5965 ComPtr<IHardDisk> hardDisk;
5966 Bstr filepath;
5967
5968 bool registered = true;
5969
5970 /* first guess is that it's a UUID */
5971 Guid uuid(argv[0]);
5972 rc = virtualBox->GetHardDisk(uuid, hardDisk.asOutParam());
5973 /* no? then it must be a filename */
5974 if (FAILED (rc))
5975 {
5976 filepath = argv[0];
5977 rc = virtualBox->FindHardDisk(filepath, hardDisk.asOutParam());
5978 /* no? well, then it's an unregistered image */
5979 if (FAILED (rc))
5980 {
5981 registered = false;
5982 CHECK_ERROR(virtualBox, OpenHardDisk(filepath, hardDisk.asOutParam()));
5983 }
5984 }
5985 if (SUCCEEDED(rc) && hardDisk)
5986 {
5987 /* query a VDI object (will remain null if it's not VDI) */
5988 ComPtr<IVirtualDiskImage> vdi = hardDisk;
5989
5990 hardDisk->COMGETTER(Id)(uuid.asOutParam());
5991 RTPrintf("UUID: %s\n", uuid.toString().raw());
5992
5993 RTPrintf("Registered: %s\n", registered ? "yes" : "no");
5994
5995 /* check for accessibility */
5996 BOOL accessible = FALSE;
5997 CHECK_ERROR_RET (hardDisk, COMGETTER(Accessible)(&accessible), 1);
5998 RTPrintf("Accessible: %s\n", accessible ? "yes" : "no");
5999
6000 if (!accessible)
6001 {
6002 Bstr err;
6003 CHECK_ERROR_RET (hardDisk, COMGETTER(LastAccessError)(err.asOutParam()), 1);
6004 RTPrintf("Access Error: %lS\n", err.raw());
6005 }
6006
6007 Bstr description;
6008 hardDisk->COMGETTER(Description)(description.asOutParam());
6009 if (description)
6010 {
6011 RTPrintf("Description: %lS\n", description.raw());
6012 }
6013
6014 ULONG64 size;
6015 hardDisk->COMGETTER(Size)(&size);
6016 RTPrintf("Size: %llu MBytes\n", size);
6017 ULONG64 actualSize;
6018 hardDisk->COMGETTER(ActualSize)(&actualSize);
6019 RTPrintf("Current size on disk: %llu MBytes\n", actualSize >> 20);
6020
6021 HardDiskType_T type;
6022 hardDisk->COMGETTER(Type)(&type);
6023 const char *typeStr = "unknown";
6024 switch (type)
6025 {
6026 case HardDiskType_NormalHardDisk:
6027 typeStr = "standard";
6028 break;
6029 case HardDiskType_ImmutableHardDisk:
6030 typeStr = "immutable";
6031 break;
6032 case HardDiskType_WritethroughHardDisk:
6033 typeStr = "writethrough";
6034 break;
6035 }
6036 RTPrintf("Type: %s\n", typeStr);
6037
6038 HardDiskStorageType_T storageType;
6039 const char *storageTypeStr = "unknown";
6040 hardDisk->COMGETTER(StorageType)(&storageType);
6041 switch (storageType)
6042 {
6043 case HardDiskStorageType_VirtualDiskImage:
6044 storageTypeStr = "Virtual Disk Image (VDI)";
6045 break;
6046 case HardDiskStorageType_VMDKImage:
6047 storageTypeStr = "VMDK Image";
6048 break;
6049 case HardDiskStorageType_ISCSIHardDisk:
6050 storageTypeStr = "iSCSI target";
6051 break;
6052 }
6053 RTPrintf("Storage type: %s\n", storageTypeStr);
6054
6055 if (registered)
6056 {
6057 hardDisk->COMGETTER(MachineId)(uuid.asOutParam());
6058 RTPrintf("In use by VM: %s\n", uuid ? uuid.toString().raw() : "<none>");
6059 }
6060
6061 if (vdi)
6062 {
6063 /* VDI specific information */
6064 vdi->COMGETTER(FilePath)(filepath.asOutParam());
6065 RTPrintf("Path: %lS\n", filepath.raw());
6066
6067 }
6068 else
6069 {
6070 /* Generic location information */
6071 Bstr loc;
6072 hardDisk->COMGETTER(Location)(loc.asOutParam());
6073 RTPrintf("Location: %lS\n", loc.raw());
6074 }
6075 }
6076 return SUCCEEDED(rc) ? 0 : 1;
6077}
6078
6079static int handleRegisterImage(int argc, char *argv[],
6080 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)
6081{
6082 HRESULT rc;
6083
6084 if (argc < 2)
6085 {
6086 return errorSyntax(USAGE_REGISTERIMAGE, "Not enough parameters");
6087 }
6088
6089 Bstr filepath(argv[1]);
6090
6091 if (strcmp(argv[0], "disk") == 0)
6092 {
6093 const char *type = NULL;
6094 /* there can be a type parameter */
6095 if ((argc > 2) && (argc != 4))
6096 {
6097 return errorSyntax(USAGE_REGISTERIMAGE, "Incorrect number of parameters");
6098 }
6099 if (argc == 4)
6100 {
6101 if (strcmp(argv[2], "-type") != 0)
6102 {
6103 return errorSyntax(USAGE_REGISTERIMAGE, "Invalid parameter '%s'", Utf8Str(argv[2]).raw());
6104 }
6105 if ( (strcmp(argv[3], "normal") != 0)
6106 && (strcmp(argv[3], "immutable") != 0)
6107 && (strcmp(argv[3], "writethrough") != 0))
6108 {
6109 return errorArgument("Invalid VDI type '%s' specified", Utf8Str(argv[3]).raw());
6110 }
6111 type = argv[3];
6112 }
6113
6114 ComPtr<IHardDisk> hardDisk;
6115 CHECK_ERROR(virtualBox, OpenHardDisk(filepath, hardDisk.asOutParam()));
6116 if (SUCCEEDED(rc) && hardDisk)
6117 {
6118 /* change the type if requested */
6119 if (type)
6120 {
6121 if (strcmp(type, "normal") == 0)
6122 CHECK_ERROR(hardDisk, COMSETTER(Type)(HardDiskType_NormalHardDisk));
6123 else if (strcmp(type, "immutable") == 0)
6124 CHECK_ERROR(hardDisk, COMSETTER(Type)(HardDiskType_ImmutableHardDisk));
6125 else if (strcmp(type, "writethrough") == 0)
6126 CHECK_ERROR(hardDisk, COMSETTER(Type)(HardDiskType_WritethroughHardDisk));
6127 }
6128 if (SUCCEEDED(rc))
6129 CHECK_ERROR(virtualBox, RegisterHardDisk(hardDisk));
6130 }
6131 }
6132 else if (strcmp(argv[0], "dvd") == 0)
6133 {
6134 ComPtr<IDVDImage> dvdImage;
6135 CHECK_ERROR(virtualBox, OpenDVDImage(filepath, Guid(), dvdImage.asOutParam()));
6136 if (SUCCEEDED(rc) && dvdImage)
6137 {
6138 CHECK_ERROR(virtualBox, RegisterDVDImage(dvdImage));
6139 }
6140 }
6141 else if (strcmp(argv[0], "floppy") == 0)
6142 {
6143 ComPtr<IFloppyImage> floppyImage;
6144 CHECK_ERROR(virtualBox, OpenFloppyImage(filepath, Guid(), floppyImage.asOutParam()));
6145 if (SUCCEEDED(rc) && floppyImage)
6146 {
6147 CHECK_ERROR(virtualBox, RegisterFloppyImage(floppyImage));
6148 }
6149 }
6150 else
6151 {
6152 return errorSyntax(USAGE_REGISTERIMAGE, "Invalid parameter '%s'", Utf8Str(argv[1]).raw());
6153 }
6154 return SUCCEEDED(rc) ? 0 : 1;
6155}
6156
6157static int handleUnregisterImage(int argc, char *argv[],
6158 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)
6159{
6160 HRESULT rc;
6161
6162 if (argc != 2)
6163 {
6164 return errorSyntax(USAGE_UNREGISTERIMAGE, "Incorrect number of parameters");
6165 }
6166
6167 /* first guess is that it's a UUID */
6168 Guid uuid(argv[1]);
6169
6170 if (strcmp(argv[0], "disk") == 0)
6171 {
6172 ComPtr<IHardDisk> hardDisk;
6173 rc = virtualBox->GetHardDisk(uuid, hardDisk.asOutParam());
6174 /* not a UUID or not registered? Then it must be a filename */
6175 if (!hardDisk)
6176 {
6177 ComPtr<IVirtualDiskImage> vdi;
6178 CHECK_ERROR(virtualBox, FindVirtualDiskImage(Bstr(argv[1]), vdi.asOutParam()));
6179 hardDisk = vdi;
6180 }
6181 if (SUCCEEDED(rc) && hardDisk)
6182 {
6183 hardDisk->COMGETTER(Id)(uuid.asOutParam());
6184 CHECK_ERROR(virtualBox, UnregisterHardDisk(uuid, hardDisk.asOutParam()));
6185 }
6186 }
6187 else
6188 if (strcmp(argv[0], "dvd") == 0)
6189 {
6190 ComPtr<IDVDImage> dvdImage;
6191 rc = virtualBox->GetDVDImage(uuid, dvdImage.asOutParam());
6192 /* not a UUID or not registered? Then it must be a filename */
6193 if (!dvdImage)
6194 {
6195 ComPtr<IDVDImageCollection> dvdColl;
6196 virtualBox->COMGETTER(DVDImages)(dvdColl.asOutParam());
6197 CHECK_ERROR(dvdColl, FindByPath(Bstr(argv[1]), dvdImage.asOutParam()));
6198 }
6199 if (SUCCEEDED(rc) && dvdImage)
6200 {
6201 dvdImage->COMGETTER(Id)(uuid.asOutParam());
6202 CHECK_ERROR(virtualBox, UnregisterDVDImage(uuid, dvdImage.asOutParam()));
6203 }
6204 }
6205 else
6206 if (strcmp(argv[0], "floppy") == 0)
6207 {
6208 ComPtr<IFloppyImage> floppyImage;
6209 rc = virtualBox->GetFloppyImage(uuid, floppyImage.asOutParam());
6210 /* not a UUID or not registered? Then it must be a filename */
6211 if (!floppyImage)
6212 {
6213 ComPtr<IFloppyImageCollection> floppyColl;
6214 virtualBox->COMGETTER(FloppyImages)(floppyColl.asOutParam());
6215 CHECK_ERROR(floppyColl, FindByPath(Bstr(argv[1]), floppyImage.asOutParam()));
6216 }
6217 if (SUCCEEDED(rc) && floppyImage)
6218 {
6219 floppyImage->COMGETTER(Id)(uuid.asOutParam());
6220 CHECK_ERROR(virtualBox, UnregisterFloppyImage(uuid, floppyImage.asOutParam()));
6221 }
6222 }
6223 else
6224 {
6225 return errorSyntax(USAGE_UNREGISTERIMAGE, "Invalid parameter '%s'", Utf8Str(argv[1]).raw());
6226 }
6227 return SUCCEEDED(rc) ? 0 : 1;
6228}
6229
6230#ifdef RT_OS_WINDOWS
6231static int handleCreateHostIF(int argc, char *argv[],
6232 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)
6233{
6234 if (argc != 1)
6235 {
6236 return errorSyntax(USAGE_CREATEHOSTIF, "Incorrect number of parameters");
6237 }
6238
6239 HRESULT rc = S_OK;
6240
6241 do
6242 {
6243 ComPtr<IHost> host;
6244 CHECK_ERROR_BREAK(virtualBox, COMGETTER(Host)(host.asOutParam()));
6245
6246 ComPtr<IHostNetworkInterface> hostif;
6247 ComPtr<IProgress> progress;
6248 CHECK_ERROR_BREAK(host,
6249 CreateHostNetworkInterface(Bstr(argv[0]),
6250 hostif.asOutParam(),
6251 progress.asOutParam()));
6252
6253 showProgress(progress);
6254 HRESULT result;
6255 CHECK_ERROR_BREAK(progress, COMGETTER(ResultCode)(&result));
6256 if (FAILED(result))
6257 {
6258 com::ProgressErrorInfo info(progress);
6259 PRINT_ERROR_INFO(info);
6260 rc = result;
6261 }
6262 }
6263 while (0);
6264
6265 return SUCCEEDED(rc) ? 0 : 1;
6266}
6267
6268static int handleRemoveHostIF(int argc, char *argv[],
6269 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)
6270{
6271 if (argc != 1)
6272 {
6273 return errorSyntax(USAGE_REMOVEHOSTIF, "Incorrect number of parameters");
6274 }
6275
6276 HRESULT rc = S_OK;
6277
6278 do
6279 {
6280 ComPtr<IHost> host;
6281 CHECK_ERROR_BREAK(virtualBox, COMGETTER(Host)(host.asOutParam()));
6282
6283 ComPtr<IHostNetworkInterface> hostif;
6284
6285 /* first guess is that it's a UUID */
6286 Guid uuid(argv[0]);
6287 if (uuid.isEmpty())
6288 {
6289 /* not a valid UUID, search for it */
6290 ComPtr<IHostNetworkInterfaceCollection> coll;
6291 CHECK_ERROR_BREAK(host, COMGETTER(NetworkInterfaces)(coll.asOutParam()));
6292 CHECK_ERROR_BREAK(coll, FindByName(Bstr(argv[0]), hostif.asOutParam()));
6293 CHECK_ERROR_BREAK(hostif, COMGETTER(Id)(uuid.asOutParam()));
6294 }
6295
6296 ComPtr<IProgress> progress;
6297 CHECK_ERROR_BREAK(host,
6298 RemoveHostNetworkInterface(uuid,
6299 hostif.asOutParam(),
6300 progress.asOutParam()));
6301
6302 showProgress(progress);
6303 HRESULT result;
6304 CHECK_ERROR_BREAK(progress, COMGETTER(ResultCode)(&result));
6305 if (FAILED(result))
6306 {
6307 com::ProgressErrorInfo info(progress);
6308 PRINT_ERROR_INFO(info);
6309 rc = result;
6310 }
6311 }
6312 while (0);
6313
6314 return SUCCEEDED(rc) ? 0 : 1;
6315}
6316#endif /* RT_OS_WINDOWS */
6317
6318static int handleGetExtraData(int argc, char *argv[],
6319 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)
6320{
6321 HRESULT rc = S_OK;
6322
6323 if (argc != 2)
6324 {
6325 return errorSyntax(USAGE_GETEXTRADATA, "Incorrect number of parameters");
6326 }
6327 /* global data? */
6328 if (strcmp(argv[0], "global") == 0)
6329 {
6330 /* enumeration? */
6331 if (strcmp(argv[1], "enumerate") == 0)
6332 {
6333 Bstr extraDataKey;
6334
6335 do
6336 {
6337 Bstr nextExtraDataKey;
6338 Bstr nextExtraDataValue;
6339 HRESULT rcEnum = virtualBox->GetNextExtraDataKey(extraDataKey, nextExtraDataKey.asOutParam(),
6340 nextExtraDataValue.asOutParam());
6341 extraDataKey = nextExtraDataKey;
6342
6343 if (SUCCEEDED(rcEnum) && extraDataKey)
6344 {
6345 RTPrintf("Key: %lS, Value: %lS\n", nextExtraDataKey.raw(), nextExtraDataValue.raw());
6346 }
6347 } while (extraDataKey);
6348 }
6349 else
6350 {
6351 Bstr value;
6352 CHECK_ERROR(virtualBox, GetExtraData(Bstr(argv[1]), value.asOutParam()));
6353 if (value)
6354 RTPrintf("Value: %lS\n", value.raw());
6355 else
6356 RTPrintf("No value set!\n");
6357 }
6358 }
6359 else
6360 {
6361 ComPtr<IMachine> machine;
6362 /* assume it's a UUID */
6363 rc = virtualBox->GetMachine(Guid(argv[0]), machine.asOutParam());
6364 if (FAILED(rc) || !machine)
6365 {
6366 /* must be a name */
6367 CHECK_ERROR(virtualBox, FindMachine(Bstr(argv[0]), machine.asOutParam()));
6368 }
6369 if (machine)
6370 {
6371 /* enumeration? */
6372 if (strcmp(argv[1], "enumerate") == 0)
6373 {
6374 Bstr extraDataKey;
6375
6376 do
6377 {
6378 Bstr nextExtraDataKey;
6379 Bstr nextExtraDataValue;
6380 HRESULT rcEnum = machine->GetNextExtraDataKey(extraDataKey, nextExtraDataKey.asOutParam(),
6381 nextExtraDataValue.asOutParam());
6382 extraDataKey = nextExtraDataKey;
6383
6384 if (SUCCEEDED(rcEnum) && extraDataKey)
6385 {
6386 RTPrintf("Key: %lS, Value: %lS\n", nextExtraDataKey.raw(), nextExtraDataValue.raw());
6387 }
6388 } while (extraDataKey);
6389 }
6390 else
6391 {
6392 Bstr value;
6393 CHECK_ERROR(machine, GetExtraData(Bstr(argv[1]), value.asOutParam()));
6394 if (value)
6395 RTPrintf("Value: %lS\n", value.raw());
6396 else
6397 RTPrintf("No value set!\n");
6398 }
6399 }
6400 }
6401 return SUCCEEDED(rc) ? 0 : 1;
6402}
6403
6404static int handleSetExtraData(int argc, char *argv[],
6405 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)
6406{
6407 HRESULT rc = S_OK;
6408
6409 if (argc < 2)
6410 {
6411 return errorSyntax(USAGE_SETEXTRADATA, "Not enough parameters");
6412 }
6413 /* global data? */
6414 if (strcmp(argv[0], "global") == 0)
6415 {
6416 if (argc < 3)
6417 CHECK_ERROR(virtualBox, SetExtraData(Bstr(argv[1]), NULL));
6418 else if (argc == 3)
6419 CHECK_ERROR(virtualBox, SetExtraData(Bstr(argv[1]), Bstr(argv[2])));
6420 else
6421 return errorSyntax(USAGE_SETEXTRADATA, "Too many parameters");
6422 }
6423 else
6424 {
6425 ComPtr<IMachine> machine;
6426 /* assume it's a UUID */
6427 rc = virtualBox->GetMachine(Guid(argv[0]), machine.asOutParam());
6428 if (FAILED(rc) || !machine)
6429 {
6430 /* must be a name */
6431 CHECK_ERROR(virtualBox, FindMachine(Bstr(argv[0]), machine.asOutParam()));
6432 }
6433 if (machine)
6434 {
6435 if (argc < 3)
6436 CHECK_ERROR(machine, SetExtraData(Bstr(argv[1]), NULL));
6437 else if (argc == 3)
6438 CHECK_ERROR(machine, SetExtraData(Bstr(argv[1]), Bstr(argv[2])));
6439 else
6440 return errorSyntax(USAGE_SETEXTRADATA, "Too many parameters");
6441 }
6442 }
6443 return SUCCEEDED(rc) ? 0 : 1;
6444}
6445
6446static int handleSetProperty(int argc, char *argv[],
6447 ComPtr<IVirtualBox> virtualBox, ComPtr<ISession> session)
6448{
6449 HRESULT rc;
6450
6451 /* there must be two arguments: property name and value */
6452 if (argc != 2)
6453 {
6454 return errorSyntax(USAGE_SETPROPERTY, "Incorrect number of parameters");
6455 }
6456 ComPtr<ISystemProperties> systemProperties;
6457 virtualBox->COMGETTER(SystemProperties)(systemProperties.asOutParam());
6458
6459 if (strcmp(argv[0], "vdifolder") == 0)
6460 {
6461 /* reset to default? */
6462 if (strcmp(argv[1], "default") == 0)
6463 CHECK_ERROR(systemProperties, COMSETTER(DefaultVDIFolder)(NULL));
6464 else
6465 CHECK_ERROR(systemProperties, COMSETTER(DefaultVDIFolder)(Bstr(argv[1])));
6466 }
6467 else if (strcmp(argv[0], "machinefolder") == 0)
6468 {
6469 /* reset to default? */
6470 if (strcmp(argv[1], "default") == 0)
6471 CHECK_ERROR(systemProperties, COMSETTER(DefaultMachineFolder)(NULL));
6472 else
6473 CHECK_ERROR(systemProperties, COMSETTER(DefaultMachineFolder)(Bstr(argv[1])));
6474 }
6475 else if (strcmp(argv[0], "vrdpauthlibrary") == 0)
6476 {
6477 /* reset to default? */
6478 if (strcmp(argv[1], "default") == 0)
6479 CHECK_ERROR(systemProperties, COMSETTER(RemoteDisplayAuthLibrary)(NULL));
6480 else
6481 CHECK_ERROR(systemProperties, COMSETTER(RemoteDisplayAuthLibrary)(Bstr(argv[1])));
6482 }
6483 else if (strcmp(argv[0], "hwvirtexenabled") == 0)
6484 {
6485 if (strcmp(argv[1], "yes") == 0)
6486 CHECK_ERROR(systemProperties, COMSETTER(HWVirtExEnabled)(TRUE));
6487 else if (strcmp(argv[1], "no") == 0)
6488 CHECK_ERROR(systemProperties, COMSETTER(HWVirtExEnabled)(FALSE));
6489 else
6490 return errorArgument("Invalid value '%s' for hardware virtualization extension flag", argv[1]);
6491 }
6492 else if (strcmp(argv[0], "loghistorycount") == 0)
6493 {
6494 uint32_t uVal;
6495 int vrc;
6496 vrc = RTStrToUInt32Ex(argv[1], NULL, 0, &uVal);
6497 if (vrc != VINF_SUCCESS)
6498 return errorArgument("Error parsing Log history count '%s'", argv[1]);
6499 CHECK_ERROR(systemProperties, COMSETTER(LogHistoryCount)(uVal));
6500 }
6501 else
6502 return errorSyntax(USAGE_SETPROPERTY, "Invalid parameter '%s'", Utf8Str(argv[0]).raw());
6503
6504 return SUCCEEDED(rc) ? 0 : 1;
6505}
6506
6507static int handleUSBFilter (int argc, char *argv[],
6508 ComPtr <IVirtualBox> aVirtualBox, ComPtr<ISession> aSession)
6509{
6510 HRESULT rc = S_OK;
6511 USBFilterCmd cmd;
6512
6513 /* at least: 0: command, 1: index, 2: -target, 3: <target value> */
6514 if (argc < 4)
6515 {
6516 return errorSyntax(USAGE_USBFILTER, "Not enough parameters");
6517 }
6518
6519 /* which command? */
6520 cmd.mAction = USBFilterCmd::Invalid;
6521 if (strcmp (argv [0], "add") == 0) cmd.mAction = USBFilterCmd::Add;
6522 else if (strcmp (argv [0], "modify") == 0) cmd.mAction = USBFilterCmd::Modify;
6523 else if (strcmp (argv [0], "remove") == 0) cmd.mAction = USBFilterCmd::Remove;
6524
6525 if (cmd.mAction == USBFilterCmd::Invalid)
6526 {
6527 return errorSyntax(USAGE_USBFILTER, "Invalid parameter '%s'", Utf8Str(argv[0]).raw());
6528 }
6529
6530 /* which index? */
6531 char *endptr = NULL;
6532 cmd.mIndex = strtoul (argv[1], &endptr, 10);
6533 if (!endptr || *endptr)
6534 {
6535 return errorSyntax(USAGE_USBFILTER, "Invalid index '%s'", argv[1]);
6536 }
6537
6538 switch (cmd.mAction)
6539 {
6540 case USBFilterCmd::Add:
6541 case USBFilterCmd::Modify:
6542 {
6543 /* at least: 0: command, 1: index, 2: -target, 3: <target value>, 4: -name, 5: <name value> */
6544 if (argc < 6)
6545 {
6546 if (cmd.mAction == USBFilterCmd::Add)
6547 {
6548 return errorSyntax(USAGE_USBFILTER_ADD, "Not enough parameters");
6549 }
6550 else
6551 {
6552 return errorSyntax(USAGE_USBFILTER_MODIFY, "Not enough parameters");
6553 }
6554 }
6555
6556 // set Active to true by default
6557 // (assuming that the user sets up all necessary attributes
6558 // at once and wants the filter to be active immediately)
6559 if (cmd.mAction == USBFilterCmd::Add)
6560 cmd.mFilter.mActive = true;
6561
6562 for (int i = 2; i < argc; i++)
6563 {
6564 if (strcmp(argv [i], "-target") == 0)
6565 {
6566 if (argc <= i + 1 || !*argv[i+1])
6567 {
6568 return errorArgument("Missing argument to '%s'", argv[i]);
6569 }
6570 i++;
6571 if (strcmp (argv [i], "global") == 0)
6572 cmd.mGlobal = true;
6573 else
6574 {
6575 /* assume it's a UUID of a machine */
6576 rc = aVirtualBox->GetMachine(Guid(argv[i]), cmd.mMachine.asOutParam());
6577 if (FAILED(rc) || !cmd.mMachine)
6578 {
6579 /* must be a name */
6580 CHECK_ERROR_RET(aVirtualBox, FindMachine(Bstr(argv[i]), cmd.mMachine.asOutParam()), 1);
6581 }
6582 }
6583 }
6584 else if (strcmp(argv [i], "-name") == 0)
6585 {
6586 if (argc <= i + 1 || !*argv[i+1])
6587 {
6588 return errorArgument("Missing argument to '%s'", argv[i]);
6589 }
6590 i++;
6591 cmd.mFilter.mName = argv [i];
6592 }
6593 else if (strcmp(argv [i], "-active") == 0)
6594 {
6595 if (argc <= i + 1)
6596 {
6597 return errorArgument("Missing argument to '%s'", argv[i]);
6598 }
6599 i++;
6600 if (strcmp (argv [i], "yes") == 0)
6601 cmd.mFilter.mActive = true;
6602 else if (strcmp (argv [i], "no") == 0)
6603 cmd.mFilter.mActive = false;
6604 else
6605 {
6606 return errorArgument("Invalid -active argument '%s'", Utf8Str(argv[i]).raw());
6607 }
6608 }
6609 else if (strcmp(argv [i], "-vendorid") == 0)
6610 {
6611 if (argc <= i + 1)
6612 {
6613 return errorArgument("Missing argument to '%s'", argv[i]);
6614 }
6615 i++;
6616 cmd.mFilter.mVendorId = argv [i];
6617 }
6618 else if (strcmp(argv [i], "-productid") == 0)
6619 {
6620 if (argc <= i + 1)
6621 {
6622 return errorArgument("Missing argument to '%s'", argv[i]);
6623 }
6624 i++;
6625 cmd.mFilter.mProductId = argv [i];
6626 }
6627 else if (strcmp(argv [i], "-revision") == 0)
6628 {
6629 if (argc <= i + 1)
6630 {
6631 return errorArgument("Missing argument to '%s'", argv[i]);
6632 }
6633 i++;
6634 cmd.mFilter.mRevision = argv [i];
6635 }
6636 else if (strcmp(argv [i], "-manufacturer") == 0)
6637 {
6638 if (argc <= i + 1)
6639 {
6640 return errorArgument("Missing argument to '%s'", argv[i]);
6641 }
6642 i++;
6643 cmd.mFilter.mManufacturer = argv [i];
6644 }
6645 else if (strcmp(argv [i], "-product") == 0)
6646 {
6647 if (argc <= i + 1)
6648 {
6649 return errorArgument("Missing argument to '%s'", argv[i]);
6650 }
6651 i++;
6652 cmd.mFilter.mProduct = argv [i];
6653 }
6654 else if (strcmp(argv [i], "-remote") == 0)
6655 {
6656 if (argc <= i + 1)
6657 {
6658 return errorArgument("Missing argument to '%s'", argv[i]);
6659 }
6660 i++;
6661 cmd.mFilter.mRemote = argv[i];
6662 }
6663 else if (strcmp(argv [i], "-serialnumber") == 0)
6664 {
6665 if (argc <= i + 1)
6666 {
6667 return errorArgument("Missing argument to '%s'", argv[i]);
6668 }
6669 i++;
6670 cmd.mFilter.mSerialNumber = argv [i];
6671 }
6672 else if (strcmp(argv [i], "-action") == 0)
6673 {
6674 if (argc <= i + 1)
6675 {
6676 return errorArgument("Missing argument to '%s'", argv[i]);
6677 }
6678 i++;
6679 if (strcmp (argv [i], "ignore") == 0)
6680 cmd.mFilter.mAction = USBDeviceFilterAction_USBDeviceFilterIgnore;
6681 else if (strcmp (argv [i], "hold") == 0)
6682 cmd.mFilter.mAction = USBDeviceFilterAction_USBDeviceFilterHold;
6683 else
6684 {
6685 return errorArgument("Invalid USB filter action '%s'", Utf8Str(argv[i]).raw());
6686 }
6687 }
6688
6689 }
6690
6691 if (cmd.mAction == USBFilterCmd::Add)
6692 {
6693 // mandatory/forbidden options
6694 if ( cmd.mFilter.mName.isEmpty()
6695 ||
6696 ( cmd.mGlobal
6697 && cmd.mFilter.mAction == USBDeviceFilterAction_InvalidUSBDeviceFilterAction
6698 )
6699 || ( !cmd.mGlobal
6700 && !cmd.mMachine)
6701 || ( cmd.mGlobal
6702 && cmd.mFilter.mRemote)
6703 )
6704 {
6705 return errorSyntax(USAGE_USBFILTER_ADD, "Mandatory options not supplied");
6706 }
6707 }
6708 break;
6709 }
6710
6711 case USBFilterCmd::Remove:
6712 {
6713 /* at least: 0: command, 1: index, 2: -target, 3: <target value> */
6714 if (argc < 4)
6715 {
6716 return errorSyntax(USAGE_USBFILTER_REMOVE, "Not enough parameters");
6717 }
6718
6719 for (int i = 2; i < argc; i++)
6720 {
6721 if (strcmp(argv [i], "-target") == 0)
6722 {
6723 if (argc <= i + 1 || !*argv[i+1])
6724 {
6725 return errorArgument("Missing argument to '%s'", argv[i]);
6726 }
6727 i++;
6728 if (strcmp (argv [i], "global") == 0)
6729 cmd.mGlobal = true;
6730 else
6731 {
6732 /* assume it's a UUID of a machine */
6733 rc = aVirtualBox->GetMachine(Guid(argv[i]), cmd.mMachine.asOutParam());
6734 if (FAILED(rc) || !cmd.mMachine)
6735 {
6736 /* must be a name */
6737 CHECK_ERROR_RET(aVirtualBox, FindMachine(Bstr(argv[i]), cmd.mMachine.asOutParam()), 1);
6738 }
6739 }
6740 }
6741 }
6742
6743 // mandatory options
6744 if (!cmd.mGlobal && !cmd.mMachine)
6745 {
6746 return errorSyntax(USAGE_USBFILTER_REMOVE, "Mandatory options not supplied");
6747 }
6748
6749 break;
6750 }
6751
6752 default: break;
6753 }
6754
6755 USBFilterCmd::USBFilter &f = cmd.mFilter;
6756
6757 ComPtr <IHost> host;
6758 ComPtr <IUSBController> ctl;
6759 if (cmd.mGlobal)
6760 CHECK_ERROR_RET (aVirtualBox, COMGETTER(Host) (host.asOutParam()), 1);
6761 else
6762 {
6763 Guid uuid;
6764 cmd.mMachine->COMGETTER(Id)(uuid.asOutParam());
6765 /* open a session for the VM */
6766 CHECK_ERROR_RET (aVirtualBox, OpenSession(aSession, uuid), 1);
6767 /* get the mutable session machine */
6768 aSession->COMGETTER(Machine)(cmd.mMachine.asOutParam());
6769 /* and get the USB controller */
6770 CHECK_ERROR_RET (cmd.mMachine, COMGETTER(USBController) (ctl.asOutParam()), 1);
6771 }
6772
6773 switch (cmd.mAction)
6774 {
6775 case USBFilterCmd::Add:
6776 {
6777 if (cmd.mGlobal)
6778 {
6779 ComPtr <IHostUSBDeviceFilter> flt;
6780 CHECK_ERROR_BREAK (host, CreateUSBDeviceFilter (f.mName, flt.asOutParam()));
6781
6782 if (!f.mActive.isNull())
6783 CHECK_ERROR_BREAK (flt, COMSETTER(Active) (f.mActive));
6784 if (!f.mVendorId.isNull())
6785 CHECK_ERROR_BREAK (flt, COMSETTER(VendorId) (f.mVendorId.setNullIfEmpty()));
6786 if (!f.mProductId.isNull())
6787 CHECK_ERROR_BREAK (flt, COMSETTER(ProductId) (f.mProductId.setNullIfEmpty()));
6788 if (!f.mRevision.isNull())
6789 CHECK_ERROR_BREAK (flt, COMSETTER(Revision) (f.mRevision.setNullIfEmpty()));
6790 if (!f.mManufacturer.isNull())
6791 CHECK_ERROR_BREAK (flt, COMSETTER(Manufacturer) (f.mManufacturer.setNullIfEmpty()));
6792 if (!f.mSerialNumber.isNull())
6793 CHECK_ERROR_BREAK (flt, COMSETTER(SerialNumber) (f.mSerialNumber.setNullIfEmpty()));
6794
6795 if (f.mAction != USBDeviceFilterAction_InvalidUSBDeviceFilterAction)
6796 CHECK_ERROR_BREAK (flt, COMSETTER(Action) (f.mAction));
6797
6798 CHECK_ERROR_BREAK (host, InsertUSBDeviceFilter (cmd.mIndex, flt));
6799 }
6800 else
6801 {
6802 ComPtr <IUSBDeviceFilter> flt;
6803 CHECK_ERROR_BREAK (ctl, CreateDeviceFilter (f.mName, flt.asOutParam()));
6804
6805 if (!f.mActive.isNull())
6806 CHECK_ERROR_BREAK (flt, COMSETTER(Active) (f.mActive));
6807 if (!f.mVendorId.isNull())
6808 CHECK_ERROR_BREAK (flt, COMSETTER(VendorId) (f.mVendorId.setNullIfEmpty()));
6809 if (!f.mProductId.isNull())
6810 CHECK_ERROR_BREAK (flt, COMSETTER(ProductId) (f.mProductId.setNullIfEmpty()));
6811 if (!f.mRevision.isNull())
6812 CHECK_ERROR_BREAK (flt, COMSETTER(Revision) (f.mRevision.setNullIfEmpty()));
6813 if (!f.mManufacturer.isNull())
6814 CHECK_ERROR_BREAK (flt, COMSETTER(Manufacturer) (f.mManufacturer.setNullIfEmpty()));
6815 if (!f.mRemote.isNull())
6816 CHECK_ERROR_BREAK (flt, COMSETTER(Remote) (f.mRemote.setNullIfEmpty()));
6817 if (!f.mSerialNumber.isNull())
6818 CHECK_ERROR_BREAK (flt, COMSETTER(SerialNumber) (f.mSerialNumber.setNullIfEmpty()));
6819
6820 CHECK_ERROR_BREAK (ctl, InsertDeviceFilter (cmd.mIndex, flt));
6821 }
6822 break;
6823 }
6824 case USBFilterCmd::Modify:
6825 {
6826 if (cmd.mGlobal)
6827 {
6828 ComPtr <IHostUSBDeviceFilterCollection> coll;
6829 CHECK_ERROR_BREAK (host, COMGETTER(USBDeviceFilters) (coll.asOutParam()));
6830 ComPtr <IHostUSBDeviceFilter> flt;
6831 CHECK_ERROR_BREAK (coll, GetItemAt (cmd.mIndex, flt.asOutParam()));
6832
6833 if (!f.mName.isNull())
6834 CHECK_ERROR_BREAK (flt, COMSETTER(Name) (f.mName.setNullIfEmpty()));
6835 if (!f.mActive.isNull())
6836 CHECK_ERROR_BREAK (flt, COMSETTER(Active) (f.mActive));
6837 if (!f.mVendorId.isNull())
6838 CHECK_ERROR_BREAK (flt, COMSETTER(VendorId) (f.mVendorId.setNullIfEmpty()));
6839 if (!f.mProductId.isNull())
6840 CHECK_ERROR_BREAK (flt, COMSETTER(ProductId) (f.mProductId.setNullIfEmpty()));
6841 if (!f.mRevision.isNull())
6842 CHECK_ERROR_BREAK (flt, COMSETTER(Revision) (f.mRevision.setNullIfEmpty()));
6843 if (!f.mManufacturer.isNull())
6844 CHECK_ERROR_BREAK (flt, COMSETTER(Manufacturer) (f.mManufacturer.setNullIfEmpty()));
6845 if (!f.mSerialNumber.isNull())
6846 CHECK_ERROR_BREAK (flt, COMSETTER(SerialNumber) (f.mSerialNumber.setNullIfEmpty()));
6847
6848 if (f.mAction != USBDeviceFilterAction_InvalidUSBDeviceFilterAction)
6849 CHECK_ERROR_BREAK (flt, COMSETTER(Action) (f.mAction));
6850 }
6851 else
6852 {
6853 ComPtr <IUSBDeviceFilterCollection> coll;
6854 CHECK_ERROR_BREAK (ctl, COMGETTER(DeviceFilters) (coll.asOutParam()));
6855
6856 ComPtr <IUSBDeviceFilter> flt;
6857 CHECK_ERROR_BREAK (coll, GetItemAt (cmd.mIndex, flt.asOutParam()));
6858
6859 if (!f.mName.isNull())
6860 CHECK_ERROR_BREAK (flt, COMSETTER(Name) (f.mName.setNullIfEmpty()));
6861 if (!f.mActive.isNull())
6862 CHECK_ERROR_BREAK (flt, COMSETTER(Active) (f.mActive));
6863 if (!f.mVendorId.isNull())
6864 CHECK_ERROR_BREAK (flt, COMSETTER(VendorId) (f.mVendorId.setNullIfEmpty()));
6865 if (!f.mProductId.isNull())
6866 CHECK_ERROR_BREAK (flt, COMSETTER(ProductId) (f.mProductId.setNullIfEmpty()));
6867 if (!f.mRevision.isNull())
6868 CHECK_ERROR_BREAK (flt, COMSETTER(Revision) (f.mRevision.setNullIfEmpty()));
6869 if (!f.mManufacturer.isNull())
6870 CHECK_ERROR_BREAK (flt, COMSETTER(Manufacturer) (f.mManufacturer.setNullIfEmpty()));
6871 if (!f.mRemote.isNull())
6872 CHECK_ERROR_BREAK (flt, COMSETTER(Remote) (f.mRemote.setNullIfEmpty()));
6873 if (!f.mSerialNumber.isNull())
6874 CHECK_ERROR_BREAK (flt, COMSETTER(SerialNumber) (f.mSerialNumber.setNullIfEmpty()));
6875 }
6876 break;
6877 }
6878 case USBFilterCmd::Remove:
6879 {
6880 if (cmd.mGlobal)
6881 {
6882 ComPtr <IHostUSBDeviceFilter> flt;
6883 CHECK_ERROR_BREAK (host, RemoveUSBDeviceFilter (cmd.mIndex, flt.asOutParam()));
6884 }
6885 else
6886 {
6887 ComPtr <IUSBDeviceFilter> flt;
6888 CHECK_ERROR_BREAK (ctl, RemoveDeviceFilter (cmd.mIndex, flt.asOutParam()));
6889 }
6890 break;
6891 }
6892 default:
6893 break;
6894 }
6895
6896 if (cmd.mMachine)
6897 {
6898 /* commit and close the session */
6899 CHECK_ERROR(cmd.mMachine, SaveSettings());
6900 aSession->Close();
6901 }
6902
6903 return SUCCEEDED (rc) ? 0 : 1;
6904}
6905
6906static int handleSharedFolder (int argc, char *argv[],
6907 ComPtr <IVirtualBox> aVirtualBox, ComPtr<ISession> aSession)
6908{
6909 HRESULT rc;
6910
6911 /* we need at least a command and target */
6912 if (argc < 2)
6913 {
6914 return errorSyntax(USAGE_SHAREDFOLDER, "Not enough parameters");
6915 }
6916
6917 ComPtr<IMachine> machine;
6918 /* assume it's a UUID */
6919 rc = aVirtualBox->GetMachine(Guid(argv[1]), machine.asOutParam());
6920 if (FAILED(rc) || !machine)
6921 {
6922 /* must be a name */
6923 CHECK_ERROR(aVirtualBox, FindMachine(Bstr(argv[1]), machine.asOutParam()));
6924 }
6925 if (!machine)
6926 return 1;
6927 Guid uuid;
6928 machine->COMGETTER(Id)(uuid.asOutParam());
6929
6930 if (strcmp(argv[0], "add") == 0)
6931 {
6932 /* we need at least four more parameters */
6933 if (argc < 5)
6934 {
6935 return errorSyntax(USAGE_SHAREDFOLDER_ADD, "Not enough parameters");
6936 }
6937
6938 char *name = NULL;
6939 char *hostpath = NULL;
6940 bool fTransient = false;
6941
6942 for (int i = 2; i < argc; i++)
6943 {
6944 if (strcmp(argv[i], "-name") == 0)
6945 {
6946 if (argc <= i + 1 || !*argv[i+1])
6947 {
6948 return errorArgument("Missing argument to '%s'", argv[i]);
6949 }
6950 i++;
6951 name = argv[i];
6952 }
6953 else if (strcmp(argv[i], "-hostpath") == 0)
6954 {
6955 if (argc <= i + 1 || !*argv[i+1])
6956 {
6957 return errorArgument("Missing argument to '%s'", argv[i]);
6958 }
6959 i++;
6960 hostpath = argv[i];
6961
6962 }
6963 else if (strcmp(argv[i], "-transient") == 0)
6964 {
6965 fTransient = true;
6966 }
6967 else
6968 {
6969 return errorSyntax(USAGE_SHAREDFOLDER_ADD, "Invalid parameter '%s'", Utf8Str(argv[i]).raw());
6970 }
6971 }
6972
6973 /* required arguments */
6974 if (!name || !hostpath)
6975 {
6976 return errorSyntax(USAGE_SHAREDFOLDER_ADD, "Parameters -name and -hostpath are required");
6977 }
6978
6979 if (fTransient)
6980 {
6981 ComPtr <IConsole> console;
6982
6983 /* open an existing session for the VM */
6984 CHECK_ERROR_RET(aVirtualBox, OpenExistingSession (aSession, uuid), 1);
6985 /* get the session machine */
6986 CHECK_ERROR_RET(aSession, COMGETTER(Machine)(machine.asOutParam()), 1);
6987 /* get the session console */
6988 CHECK_ERROR_RET(aSession, COMGETTER(Console)(console.asOutParam()), 1);
6989
6990 CHECK_ERROR(console, CreateSharedFolder(Bstr(name), Bstr(hostpath)));
6991
6992 if (console)
6993 aSession->Close();
6994 }
6995 else
6996 {
6997 /* open a session for the VM */
6998 CHECK_ERROR_RET (aVirtualBox, OpenSession(aSession, uuid), 1);
6999
7000 /* get the mutable session machine */
7001 aSession->COMGETTER(Machine)(machine.asOutParam());
7002
7003 CHECK_ERROR(machine, CreateSharedFolder(Bstr(name), Bstr(hostpath)));
7004
7005 if (SUCCEEDED(rc))
7006 CHECK_ERROR(machine, SaveSettings());
7007
7008 aSession->Close();
7009 }
7010 }
7011 else if (strcmp(argv[0], "remove") == 0)
7012 {
7013 /* we need at least two more parameters */
7014 if (argc < 3)
7015 {
7016 return errorSyntax(USAGE_SHAREDFOLDER_REMOVE, "Not enough parameters");
7017 }
7018
7019 char *name = NULL;
7020 bool fTransient = false;
7021
7022 for (int i = 2; i < argc; i++)
7023 {
7024 if (strcmp(argv[i], "-name") == 0)
7025 {
7026 if (argc <= i + 1 || !*argv[i+1])
7027 {
7028 return errorArgument("Missing argument to '%s'", argv[i]);
7029 }
7030 i++;
7031 name = argv[i];
7032 }
7033 else if (strcmp(argv[i], "-transient") == 0)
7034 {
7035 fTransient = true;
7036 }
7037 else
7038 {
7039 return errorSyntax(USAGE_SHAREDFOLDER_REMOVE, "Invalid parameter '%s'", Utf8Str(argv[i]).raw());
7040 }
7041 }
7042
7043 /* required arguments */
7044 if (!name)
7045 {
7046 return errorSyntax(USAGE_SHAREDFOLDER_REMOVE, "Parameter -name is required");
7047 }
7048
7049 if (fTransient)
7050 {
7051 ComPtr <IConsole> console;
7052
7053 /* open an existing session for the VM */
7054 CHECK_ERROR_RET(aVirtualBox, OpenExistingSession (aSession, uuid), 1);
7055 /* get the session machine */
7056 CHECK_ERROR_RET(aSession, COMGETTER(Machine)(machine.asOutParam()), 1);
7057 /* get the session console */
7058 CHECK_ERROR_RET(aSession, COMGETTER(Console)(console.asOutParam()), 1);
7059
7060 CHECK_ERROR(console, RemoveSharedFolder(Bstr(name)));
7061
7062 if (console)
7063 aSession->Close();
7064 }
7065 else
7066 {
7067 /* open a session for the VM */
7068 CHECK_ERROR_RET (aVirtualBox, OpenSession(aSession, uuid), 1);
7069
7070 /* get the mutable session machine */
7071 aSession->COMGETTER(Machine)(machine.asOutParam());
7072
7073 CHECK_ERROR(machine, RemoveSharedFolder(Bstr(name)));
7074
7075 /* commit and close the session */
7076 CHECK_ERROR(machine, SaveSettings());
7077 aSession->Close();
7078 }
7079 }
7080 else
7081 {
7082 return errorSyntax(USAGE_SETPROPERTY, "Invalid parameter '%s'", Utf8Str(argv[0]).raw());
7083 }
7084 return 0;
7085}
7086
7087static int handleVMStatistics(int argc, char *argv[],
7088 ComPtr<IVirtualBox> aVirtualBox, ComPtr<ISession> aSession)
7089{
7090 HRESULT rc;
7091
7092 /* at least one option: the UUID or name of the VM */
7093 if (argc < 1)
7094 return errorSyntax(USAGE_VM_STATISTICS, "Incorrect number of parameters");
7095
7096 /* try to find the given machine */
7097 ComPtr <IMachine> machine;
7098 Guid uuid (argv[0]);
7099 if (!uuid.isEmpty())
7100 CHECK_ERROR(aVirtualBox, GetMachine(uuid, machine.asOutParam()));
7101 else
7102 {
7103 CHECK_ERROR(aVirtualBox, FindMachine(Bstr(argv[0]), machine.asOutParam()));
7104 if (SUCCEEDED (rc))
7105 machine->COMGETTER(Id)(uuid.asOutParam());
7106 }
7107 if (FAILED(rc))
7108 return 1;
7109
7110 /* parse arguments. */
7111 bool fReset = false;
7112 bool fWithDescriptions = false;
7113 const char *pszPattern = NULL; /* all */
7114 for (int i = 1; i < argc; i++)
7115 {
7116 if (!strcmp(argv[i], "-pattern"))
7117 {
7118 if (pszPattern)
7119 return errorSyntax(USAGE_VM_STATISTICS, "Multiple -patterns options is not permitted");
7120 if (i + 1 >= argc)
7121 return errorArgument("Missing argument to '%s'", argv[i]);
7122 pszPattern = argv[++i];
7123 }
7124 else if (!strcmp(argv[i], "-descriptions"))
7125 fWithDescriptions = true;
7126 /* add: -file <filename> and -formatted */
7127 else if (!strcmp(argv[i], "-reset"))
7128 fReset = true;
7129 else
7130 return errorSyntax(USAGE_VM_STATISTICS, "Unknown option '%s'", argv[i]);
7131 }
7132 if (fReset && fWithDescriptions)
7133 return errorSyntax(USAGE_VM_STATISTICS, "The -reset and -descriptions options does not mix");
7134
7135
7136 /* open an existing session for the VM. */
7137 CHECK_ERROR(aVirtualBox, OpenExistingSession(aSession, uuid));
7138 if (SUCCEEDED(rc))
7139 {
7140 /* get the session console. */
7141 ComPtr <IConsole> console;
7142 CHECK_ERROR(aSession, COMGETTER(Console)(console.asOutParam()));
7143 if (SUCCEEDED(rc))
7144 {
7145 /* get the machine debugger. */
7146 ComPtr <IMachineDebugger> debugger;
7147 CHECK_ERROR(console, COMGETTER(Debugger)(debugger.asOutParam()));
7148 if (SUCCEEDED(rc))
7149 {
7150 if (fReset)
7151 CHECK_ERROR(debugger, ResetStats(Bstr(pszPattern).raw()));
7152 else
7153 {
7154 Bstr stats;
7155 CHECK_ERROR(debugger, GetStats(Bstr(pszPattern).raw(), fWithDescriptions, stats.asOutParam()));
7156 if (SUCCEEDED(rc))
7157 {
7158 /* if (fFormatted)
7159 { big mess }
7160 else
7161 */
7162 RTPrintf("%ls\n", stats.raw());
7163 }
7164 }
7165 }
7166 aSession->Close();
7167 }
7168 }
7169
7170 return SUCCEEDED(rc) ? 0 : 1;
7171}
7172
7173enum HUSPD { HUSPD_DryRun, HUSPD_Apply, HUSPD_ApplyNoBackup };
7174
7175static int handleUpdateSettings_processFile (const char *filePath, HUSPD mode)
7176{
7177 RTPrintf ("%s\n", filePath);
7178
7179 CFGHANDLE config = 0;
7180 char *errMsg = NULL;
7181
7182 int vrc = CFGLDRLoad (&config, filePath, NIL_RTFILE,
7183 NULL, false, NULL, //cfgLdrEntityResolver,
7184 &errMsg);
7185 if (VBOX_SUCCESS (vrc))
7186 {
7187 CFGNODE vbox = 0;
7188 CFGLDRGetNode (config, "VirtualBox", 0, &vbox);
7189 Bstr version;
7190 CFGLDRQueryBSTR (vbox, "version", version.asOutParam());
7191 CFGLDRReleaseNode (vbox);
7192
7193 RTPrintf (" current version : %ls\n", version.raw());
7194
7195 /// @todo (dmik) use cfgLdrEntityResolver later
7196 vrc = CFGLDRTransform (config, "SettingsConverter.xsl", NULL, &errMsg);
7197 if (VBOX_SUCCESS (vrc))
7198 {
7199 CFGLDRGetNode (config, "VirtualBox", 0, &vbox);
7200 CFGLDRQueryBSTR (vbox, "version", version.asOutParam());
7201 CFGLDRReleaseNode (vbox);
7202
7203 RTPrintf (" new version : %ls\n\n", version.raw());
7204
7205 if (mode != HUSPD_DryRun)
7206 {
7207 if (mode != HUSPD_ApplyNoBackup)
7208 {
7209 Utf8StrFmt filePathBak ("%s.bak", filePath);
7210 vrc = RTFileCopy (filePath, filePathBak);
7211 if (VBOX_FAILURE (vrc))
7212 {
7213 RTPrintf ("Error copying '%s' to '%s' (%Vrc)\n",
7214 filePath, filePathBak.raw(), vrc);
7215 }
7216 }
7217
7218 if (VBOX_SUCCESS (vrc))
7219 {
7220 vrc = CFGLDRSave (config, &errMsg);
7221 if (VBOX_FAILURE (vrc))
7222 {
7223 RTPrintf ("Error saving the settings file '%s' (%Vrc)%s%s\n",
7224 filePath, vrc,
7225 errMsg ? "\n" : "", errMsg ? errMsg : "");
7226 }
7227 }
7228 }
7229 }
7230 else
7231 {
7232 RTPrintf ("Could not convert the settings file '%s' (%Vrc)%s%s\n",
7233 filePath, vrc, errMsg ? "\n" : "", errMsg ? errMsg : "");
7234 }
7235
7236 CFGLDRFree (config);
7237 }
7238 else
7239 {
7240 RTPrintf ("Error loading the settings file '%s' (%Vrc)%s%s\n",
7241 filePath, vrc, errMsg ? "\n" : "", errMsg ? errMsg : "");
7242 }
7243
7244 if (errMsg)
7245 RTStrFree (errMsg);
7246
7247 return vrc;
7248}
7249
7250static int handleUpdateSettings_processDir (const char *dirPath, HUSPD mode,
7251 bool skipInvalid)
7252{
7253 PRTDIR dir;
7254 int vrc = RTDirOpen (&dir, dirPath);
7255 if (VBOX_FAILURE (vrc))
7256 {
7257 return vrc;
7258 }
7259
7260 RTDIRENTRYEX entry;
7261 while (VBOX_SUCCESS (vrc))
7262 {
7263 vrc = RTDirReadEx (dir, &entry, NULL, RTFSOBJATTRADD_UNIX);
7264 if (VBOX_FAILURE (vrc))
7265 {
7266 if (vrc == VERR_NO_MORE_FILES)
7267 vrc = VINF_SUCCESS;
7268 else
7269 RTPrintf ("Error reading directory '%s' (%Vrc)\n", dirPath, vrc);
7270 break;
7271 }
7272
7273 if (RTFS_IS_DIRECTORY (entry.Info.Attr.fMode))
7274 {
7275 if (entry.szName[0] == '.' &&
7276 (entry.szName[1] == 0 ||
7277 (entry.szName[1] == '.' && entry.szName[2] == 0)))
7278 continue;
7279
7280 vrc = handleUpdateSettings_processDir (
7281 Utf8StrFmt ("%s%c%s", dirPath, RTPATH_DELIMITER, entry.szName),
7282 mode, skipInvalid);
7283 if (VBOX_FAILURE (vrc))
7284 break;
7285
7286 continue;
7287 }
7288 else if (RTFS_IS_FILE (entry.Info.Attr.fMode))
7289 {
7290 const char *ext = RTPathExt (entry.szName);
7291 if (!ext || strcmp (ext, ".xml") != 0)
7292 continue;
7293 }
7294 else
7295 continue;
7296
7297 Utf8Str filePath = Utf8StrFmt ("%s%c%s", dirPath, RTPATH_DELIMITER,
7298 entry.szName);
7299
7300 vrc = handleUpdateSettings_processFile (filePath, mode);
7301
7302 if (skipInvalid)
7303 vrc = VINF_SUCCESS;
7304 }
7305
7306 RTDirClose (dir);
7307
7308 return vrc;
7309}
7310
7311static int handleUpdateSettings (int argc, char *argv[])
7312{
7313 const char *dirOrFilePath = NULL;
7314 bool apply = false;
7315 bool nobackup = false;
7316 bool skipinvalid = false;
7317
7318 for (int i = 0; i < argc; i++)
7319 {
7320 if (i == 0 && argv[i][0] != '-')
7321 {
7322 dirOrFilePath = argv[i];
7323 }
7324 else if (argv[i][0] == '-')
7325 {
7326 if (strcmp (&argv[i][1], "apply") == 0)
7327 apply = true;
7328 else if (strcmp (&argv[i][1], "nobackup") == 0)
7329 nobackup = true;
7330 else if (strcmp (&argv[i][1], "skipinvalid") == 0)
7331 skipinvalid = true;
7332 else
7333 {
7334 return errorSyntax(USAGE_SETPROPERTY, "Invalid parameter '%s'", Utf8Str(argv[i]).raw());
7335 }
7336 }
7337 else
7338 {
7339 return errorSyntax(USAGE_SETPROPERTY, "Invalid parameter '%s'", Utf8Str(argv[i]).raw());
7340 }
7341 }
7342
7343 HUSPD mode = HUSPD_DryRun;
7344 if (apply)
7345 mode = nobackup ? HUSPD_ApplyNoBackup : HUSPD_Apply;
7346
7347 int vrc = CFGLDRInitialize();
7348 if (VBOX_FAILURE (vrc))
7349 {
7350 RTPrintf ("Could not initialize XML subsystem (%Vrc)\n", vrc);
7351 return 1;
7352 }
7353
7354 if (dirOrFilePath)
7355 {
7356 if (RTDirExists (dirOrFilePath))
7357 {
7358 char fullPath [RTPATH_MAX];
7359 vrc = RTPathReal (dirOrFilePath, fullPath, RTPATH_MAX);
7360 if (VBOX_FAILURE (vrc))
7361 {
7362 RTPrintf ("Invalid directory path '%s' (%Vrc)\n", dirOrFilePath, vrc);
7363 return 1;
7364 }
7365
7366 RTPrintf ("Updating settings files in the following directory:\n"
7367 "\n %s\n\n", fullPath);
7368
7369 vrc = handleUpdateSettings_processDir (dirOrFilePath, mode, skipinvalid);
7370 }
7371 else
7372 {
7373 vrc = handleUpdateSettings_processFile (dirOrFilePath, mode);
7374 }
7375 }
7376 else
7377 {
7378 char homeDir [RTPATH_MAX];
7379 vrc = GetVBoxUserHomeDirectory (homeDir, sizeof (homeDir));
7380
7381 AssertRC (vrc);
7382 if (VBOX_SUCCESS (vrc))
7383 {
7384 RTPrintf ("Updating settings files in the following VirtualBox Home Directory:\n"
7385 "\n %s\n\n", homeDir);
7386
7387 vrc = handleUpdateSettings_processDir (homeDir, mode, skipinvalid);
7388 }
7389 }
7390
7391 if (mode == HUSPD_DryRun)
7392 {
7393 RTPrintf ("NOTE: No actual changes to the setting files were made.\n"
7394 " Repeat the command with the -apply option supplied.\n");
7395 }
7396
7397 CFGLDRShutdown();
7398
7399 return VBOX_SUCCESS (vrc) ? 0 : 1;
7400}
7401
7402// main
7403///////////////////////////////////////////////////////////////////////////////
7404
7405int main(int argc, char *argv[])
7406{
7407 /*
7408 * Before we do anything, init the runtime without loading
7409 * the support driver.
7410 */
7411 RTR3Init(false);
7412
7413 bool fShowLogo = true;
7414 int iCmd = 1;
7415 int iCmdArg;
7416
7417 for (int i = 1; i < argc || argc <= iCmd; i++)
7418 {
7419 if ( argc <= iCmd
7420 || (strcmp(argv[i], "help") == 0)
7421 || (strcmp(argv[i], "-?") == 0)
7422 || (strcmp(argv[i], "-h") == 0)
7423 || (strcmp(argv[i], "-help") == 0)
7424 || (strcmp(argv[i], "--help") == 0))
7425 {
7426 showLogo();
7427 printUsage(USAGE_ALL);
7428 return 0;
7429 }
7430 else if ( strcmp(argv[i], "-v") == 0
7431 || strcmp(argv[i], "-version") == 0
7432 || strcmp(argv[i], "-Version") == 0
7433 || strcmp(argv[i], "--version") == 0)
7434 {
7435 /* Print version number, and do nothing else. */
7436 RTPrintf("%sr%d\n", VBOX_VERSION_STRING, VBoxSVNRev ());
7437 exit(0);
7438 }
7439 else if (strcmp(argv[i], "-nologo") == 0)
7440 {
7441 /* suppress the logo */
7442 fShowLogo = false;
7443 iCmd++;
7444 }
7445 else if (strcmp(argv[i], "-dumpopts") == 0)
7446 {
7447 /* Special option to dump really all commands,
7448 * even the ones not understood on this platform. */
7449 printUsage(USAGE_DUMPOPTS);
7450 return 0;
7451 }
7452 else
7453 {
7454 break;
7455 }
7456 }
7457
7458 iCmdArg = iCmd + 1;
7459
7460 if (fShowLogo)
7461 showLogo();
7462
7463 HRESULT rc;
7464
7465 CHECK_RC_RET (com::Initialize());
7466
7467 /*
7468 * The input is in the host OS'es codepage (NT guarantees ACP).
7469 * For VBox we use UTF-8 and convert to UCS-2 when calling (XP)COM APIs.
7470 * For simplicity, just convert the argv[] array here.
7471 */
7472 for (int i = iCmdArg; i < argc; i++)
7473 {
7474 char *converted;
7475 RTStrCurrentCPToUtf8(&converted, argv[i]);
7476 argv[i] = converted;
7477 }
7478
7479 do
7480 {
7481 // scopes all the stuff till shutdown
7482 ////////////////////////////////////////////////////////////////////////////
7483
7484 /* update settings command (no VirtualBox instantiation!) */
7485 if (argc >= iCmdArg && (strcmp(argv[iCmd], "updatesettings") == 0))
7486 {
7487 rc = handleUpdateSettings(argc - iCmdArg, argv + iCmdArg);
7488 break;
7489 }
7490
7491 /* convertdd: does not need a VirtualBox instantiation) */
7492 if (argc >= iCmdArg && (strcmp(argv[iCmd], "convertdd") == 0))
7493 {
7494 rc = handleConvertDDImage(argc - iCmdArg, argv + iCmdArg);
7495 break;
7496 }
7497
7498 ComPtr <IVirtualBox> virtualBox;
7499 ComPtr <ISession> session;
7500
7501 rc = virtualBox.createLocalObject (CLSID_VirtualBox);
7502 if (FAILED(rc))
7503 {
7504 RTPrintf ("[!] Failed to create the VirtualBox object!\n");
7505 PRINT_RC_MESSAGE (rc);
7506
7507 com::ErrorInfo info;
7508 if (!info.isFullAvailable() && !info.isBasicAvailable())
7509 RTPrintf ("[!] Most likely, the VirtualBox COM server is not running "
7510 "or failed to start.\n");
7511 else
7512 PRINT_ERROR_INFO (info);
7513 break;
7514 }
7515
7516 CHECK_RC_BREAK (session.createInprocObject (CLSID_Session));
7517
7518 /* create the event queue
7519 * (here it is necessary only to process remaining XPCOM/IPC events
7520 * after the session is closed) */
7521
7522 EventQueue eventQ;
7523
7524 /*
7525 * All registered command handlers
7526 */
7527 struct
7528 {
7529 const char *command;
7530 PFNHANDLER handler;
7531 } commandHandlers[] =
7532 {
7533 { "internalcommands", handleInternalCommands },
7534 { "list", handleList },
7535 { "showvminfo", handleShowVMInfo },
7536 { "registervm", handleRegisterVM },
7537 { "unregistervm", handleUnregisterVM },
7538 { "createvdi", handleCreateVDI },
7539 { "modifyvdi", handleModifyVDI },
7540 { "addiscsidisk", handleAddiSCSIDisk },
7541 { "createvm", handleCreateVM },
7542 { "modifyvm", handleModifyVM },
7543 { "clonevdi", handleCloneVDI },
7544 { "startvm", handleStartVM },
7545 { "controlvm", handleControlVM },
7546 { "discardstate", handleDiscardState },
7547 { "adoptstate", handleAdoptdState },
7548 { "snapshot", handleSnapshot },
7549 { "registerimage", handleRegisterImage },
7550 { "unregisterimage", handleUnregisterImage },
7551 { "showvdiinfo", handleShowVDIInfo },
7552#ifdef RT_OS_WINDOWS
7553 { "createhostif", handleCreateHostIF },
7554 { "removehostif", handleRemoveHostIF },
7555#endif
7556 { "getextradata", handleGetExtraData },
7557 { "setextradata", handleSetExtraData },
7558 { "setproperty", handleSetProperty },
7559 { "usbfilter", handleUSBFilter },
7560 { "sharedfolder", handleSharedFolder },
7561 { "vmstatistics", handleVMStatistics },
7562 { NULL, NULL }
7563 };
7564
7565 int commandIndex;
7566 for (commandIndex = 0; commandHandlers[commandIndex].command != NULL; commandIndex++)
7567 {
7568 if (strcmp(commandHandlers[commandIndex].command, argv[iCmd]) == 0)
7569 {
7570 rc = commandHandlers[commandIndex].handler(argc - iCmdArg, &argv[iCmdArg], virtualBox, session);
7571 break;
7572 }
7573 }
7574 if (!commandHandlers[commandIndex].command)
7575 {
7576 rc = errorSyntax(USAGE_ALL, "Invalid command '%s'", Utf8Str(argv[iCmd]).raw());
7577 }
7578
7579 /* Although all handlers should always close the session if they open it,
7580 * we do it here just in case if some of the handlers contains a bug --
7581 * leaving the direct session not closed will turn the machine state to
7582 * Aborted which may have unwanted side effects like killing the saved
7583 * state file (if the machine was in the Saved state before). */
7584 session->Close();
7585
7586 // end "all-stuff" scope
7587 ////////////////////////////////////////////////////////////////////////////
7588 }
7589 while (0);
7590
7591 com::Shutdown();
7592
7593 /*
7594 * Free converted argument vector
7595 */
7596 for (int i = iCmdArg; i < argc; i++)
7597 RTStrFree(argv[i]);
7598
7599 return rc;
7600}
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette