VirtualBox

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

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

Main & All Frontends: replaced the IGuestOSType IMachine::OSType property with the wstring IMachine::OSTypeId property (+ converted IGuest and IGuestOSType to VirtualBoxBaseNEXT semantics).

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