VirtualBox

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

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

VBoxManage: When specifying the host DVD drive, also check the real name (e.g. /dev/cdrom > /dev/hda)

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

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