VirtualBox

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

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

Frontends/VBoxManage: split off metrics command to reduce chance of compiler screwup.

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