VirtualBox

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

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

gcc-4.2 warnings

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