VirtualBox

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

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

Main & FEs: 3002: GUI/Main enhancements for 64 bits guests implemented.

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