VirtualBox

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

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

small fix

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

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