VirtualBox

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

最後變更 在這個檔案從1710是 1551,由 vboxsync 提交於 18 年 前

Mac OS X audio support (only playback).

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

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