VirtualBox

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

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

better fix (use IPRT functions)

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