VirtualBox

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

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

Removed obsolete createif & removeif commands.

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

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