VirtualBox

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

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

Added setting for guest PAE (default off)

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