VirtualBox

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

Last change on this file since 4729 was 4685, checked in by vboxsync, 18 years ago

Sample number added for guest statistics

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