VirtualBox

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

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

Main, VBoxManage: Implemented IHardDisk2::cloneTo(). Resurrected 'clonehd' functionality.

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

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