VirtualBox

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

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

correction

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

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