VirtualBox

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

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

Wrong printf format for time offset

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