VirtualBox

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

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

VBoxManage: Temporarily disabled the settings update function (that is based on the to-be-removed CFGLDR). Will be remplemented using libxslt when needed.

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