VirtualBox

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

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

Implement configuration option in VBoxManage for the interface the RDP server binds to.

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

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