VirtualBox

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

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

FE/VBoxManage: Don't hold COM objects past XPCOM shutdown; pack all handler arguments to a single structure.

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