VirtualBox

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

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

modifyvdi settype doesn't currently work

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

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