VirtualBox

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

Last change on this file since 15051 was 15051, checked in by vboxsync, 16 years ago

Main: Cleaned up the long standing const BSTR = const (OLECHAR *) on WIn32 vs (const PRunichar) * on XPCOM clash. Cleaned up BSTR/GUID macros (IN_BSTR replaces INPTR BSTR, IN_GUID replaces INPTR GUIDPARAM, OUT_GUID replaces GUIDPARAMOUT).

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

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